/*
* Some code freely inspired from VobSub <URL:http://vobsub.edensrising.com>,
* with kind permission from Gabest <gabest@freemail.hu>
*/
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "config.h"
#include "version.h"
#include "vobsub.h"
#include "spudec.h"
#include "mp_msg.h"
#ifdef USE_UNRAR_EXEC
#include "unrar_exec.h"
#elif defined(USE_UNRARLIB)
#include "unrarlib.h"
#endif
#include "libavutil/common.h"
extern int vobsub_id;
// Record the original -vobsubid set by commandline, since vobsub_id will be
// overridden if slang match any of vobsub streams.
static int vobsubid = -2;
/**********************************************************************
* RAR stream handling
* The RAR file must have the same basename as the file to open
* See <URL:http://www.unrarlib.org/>
**********************************************************************/
#if defined(USE_UNRARLIB) || defined(USE_UNRAR_EXEC)
typedef struct {
FILE *file;
unsigned char *data;
unsigned long size;
unsigned long pos;
} rar_stream_t;
static rar_stream_t *
rar_open(const char *const filename, const char *const mode)
{
rar_stream_t *stream;
/* unrarlib can only read */
if (strcmp("r", mode) && strcmp("rb", mode)) {
errno = EINVAL;
return NULL;
}
stream = malloc(sizeof(rar_stream_t));
if (stream == NULL)
return NULL;
/* first try normal access */
stream->file = fopen(filename, mode);
if (stream->file == NULL) {
char *rar_filename;
const char *p;
int rc = 0;
/* Guess the RAR archive filename */
rar_filename = NULL;
p = strrchr(filename, '.');
if (p) {
ptrdiff_t l = p - filename;
rar_filename = malloc(l + 5);
if (rar_filename == NULL) {
free(stream);
return NULL;
}
strncpy(rar_filename, filename, l);
strcpy(rar_filename + l, ".rar");
}
else {
rar_filename = malloc(strlen(filename) + 5);
if (rar_filename == NULL) {
free(stream);
return NULL;
}
strcpy(rar_filename, filename);
strcat(rar_filename, ".rar");
}
/* get rid of the path if there is any */
if ((p = strrchr(filename, '/')) == NULL) {
p = filename;
} else {
p++;
}
#ifdef USE_UNRAR_EXEC
rc = unrar_exec_get(&stream->data, &stream->size, p, rar_filename);
#endif
#ifdef USE_UNRARLIB
if (!rc)
rc = urarlib_get(&stream->data, &stream->size, (char*) p, rar_filename, "");
#endif
if (!rc) {
/* There is no matching filename in the archive. However, sometimes
* the files we are looking for have been given arbitrary names in the archive.
* Let's look for a file with an exact match in the extension only. */
int i, num_files = -1, name_len;
ArchiveList_struct *list, *lp;
#ifdef USE_UNRARLIB
/* the cast in the next line is a hack to overcome a design flaw (IMHO) in unrarlib */
num_files = urarlib_list (rar_filename, (ArchiveList_struct *)&list);
#endif
#ifdef USE_UNRAR_EXEC
if (num_files <= 0)
num_files = unrar_exec_list(rar_filename, &list);
#endif
if (num_files > 0) {
char *demanded_ext;
demanded_ext = strrchr (p, '.');
if (demanded_ext) {
int demanded_ext_len = strlen (demanded_ext);
for (i=0, lp=list; i<num_files; i++, lp=lp->next) {
name_len = strlen (lp->item.Name);
if (name_len >= demanded_ext_len && !strcasecmp (lp->item.Name + name_len - demanded_ext_len, demanded_ext)) {
#ifdef USE_UNRAR_EXEC
rc = unrar_exec_get(&stream->data, &stream->size,
lp->item.Name, rar_filename);
if (rc) break;
#endif
#ifdef USE_UNRARLIB
rc = urarlib_get(&stream->data, &stream->size,
lp->item.Name, rar_filename, "");
|