]> git.sesse.net Git - vlc/commitdiff
access: rar: guess scheme from volume count
authorFrancois Cartegnie <fcvlcdev@free.fr>
Wed, 30 Jul 2014 04:52:27 +0000 (13:52 +0900)
committerFrancois Cartegnie <fcvlcdev@free.fr>
Wed, 30 Jul 2014 05:06:07 +0000 (14:06 +0900)
Rar multiple volume parsing still gets tricked by filenames matching
new naming prefixes, and using the old naming.

We need to decide according to the number of volumes found if our
new naming scheme has found only 1 volume.

part01.rar,part02.rar
part1.rar,part2.rar
part1.rar,part1.r00 (tricked here)
foobar.rar,foobar.r00

refs #9835

modules/access/rar/access.c
modules/access/rar/rar.c
modules/access/rar/rar.h
modules/access/rar/stream.c

index ddba8f203635391a69e312909aa052d865e564f8..97a69da84feb2719411fe3612093fb9ffd16fbe5 100644 (file)
@@ -154,24 +154,52 @@ int RarAccessOpen(vlc_object_t *object)
     decode_URI(base);
 
     stream_t *s = stream_UrlNew(access, base);
-    if (!s)
+    if (!s || RarProbe(s))
         goto error;
-    int count = 0;
-    rar_file_t **files;
-     if ( RarProbe(s) || (
-            RarParse(s, &count, &files, false ) &&
-            RarParse(s, &count, &files, true )
-          ) ||
-          count <= 0 )
-         goto error;
+
+    struct
+    {
+        int filescount;
+        rar_file_t **files;
+        unsigned int i_nbvols;
+    } newscheme = { 0, NULL, 0 }, oldscheme = { 0, NULL, 0 }, *p_scheme;
+
+    if (RarParse(s, &newscheme.filescount, &newscheme.files, &newscheme.i_nbvols, false)
+            || newscheme.filescount < 1 || newscheme.i_nbvols < 2 )
+    {
+        /* We might want to lookup old naming scheme, could be a part1.rar,part1.r00 */
+        stream_Seek(s, 0);
+        RarParse(s, &oldscheme.filescount, &oldscheme.files, &oldscheme.i_nbvols, true);
+    }
+
+    if (oldscheme.filescount >= newscheme.filescount && oldscheme.i_nbvols > newscheme.i_nbvols)
+    {
+        free(newscheme.files);
+        p_scheme = &oldscheme;
+        msg_Dbg(s, "using rar old naming for %d files nbvols %u", p_scheme->filescount, oldscheme.i_nbvols);
+    }
+    else if (newscheme.filescount)
+    {
+        free(oldscheme.files);
+        p_scheme = &newscheme;
+        msg_Dbg(s, "using rar new naming for %d files nbvols %u", p_scheme->filescount, oldscheme.i_nbvols);
+    }
+    else
+    {
+        msg_Info(s, "Invalid or unsupported RAR archive");
+        free(oldscheme.files);
+        free(newscheme.files);
+        goto error;
+    }
+
     rar_file_t *file = NULL;
-    for (int i = 0; i < count; i++) {
-        if (!file && !strcmp(files[i]->name, name))
-            file = files[i];
+    for (int i = 0; i < p_scheme->filescount; i++) {
+        if (!file && !strcmp(p_scheme->files[i]->name, name))
+            file = p_scheme->files[i];
         else
-            RarFileDelete(files[i]);
+            RarFileDelete(p_scheme->files[i]);
     }
-    free(files);
+    free(p_scheme->files);
     if (!file)
         goto error;
 
index c644c4a849fdc84f6d8137ca445e82b75505b457..2611c6f31e000cbf35853dd7446df8d326d5c64d 100644 (file)
@@ -287,7 +287,8 @@ typedef struct {
 static const rar_pattern_t *FindVolumePattern(const char *location, bool b_extonly )
 {
     static const rar_pattern_t patterns[] = {
-        { ".part01.rar",  "%s.part%.2d.rar", 2,  99, false }, // new naming
+        { ".part1.rar",   "%s.part%.1d.rar", 2,   9, false }, // new naming
+        { ".part01.rar",  "%s.part%.2d.rar", 2,  99, false }, // new
         { ".part001.rar", "%s.part%.3d.rar", 2, 999, false }, // new
         { ".rar",         "%s.%c%.2d",       0, 999, true },  // old
         { NULL, NULL, 0, 0, false },
@@ -309,10 +310,12 @@ static const rar_pattern_t *FindVolumePattern(const char *location, bool b_exton
     return NULL;
 }
 
-int RarParse(stream_t *s, int *count, rar_file_t ***file, bool b_extonly)
+int RarParse(stream_t *s, int *count, rar_file_t ***file, unsigned int *pi_nbvols,
+             bool b_extonly)
 {
     *count = 0;
     *file = NULL;
+    *pi_nbvols = 1;
 
     const rar_pattern_t *pattern = FindVolumePattern(s->psz_path, b_extonly);
     int volume_offset = 0;
@@ -406,6 +409,7 @@ int RarParse(stream_t *s, int *count, rar_file_t ***file, bool b_extonly)
             free(volume_mrl);
             return VLC_SUCCESS;
         }
+        (*pi_nbvols)++;
     }
 }
 
index 889309fa20b787f16fe5ead302fac275f8093a0e..6542d4c03bba8d74ce6af35ebac293886a77c89e 100644 (file)
@@ -40,7 +40,7 @@ typedef struct {
 
 int  RarProbe(stream_t *);
 void RarFileDelete(rar_file_t *);
-int  RarParse(stream_t *, int *, rar_file_t ***, bool);
+int  RarParse(stream_t *, int *, rar_file_t ***, unsigned int *, bool);
 
 int RarAccessOpen(vlc_object_t *);
 void RarAccessClose(vlc_object_t *);
index 7929d97b943537ba77b7917c6fbb1d557a5fab30..4a4c76181c9aa0b5b3aa4b9c0915e3e5ced0e0d6 100644 (file)
@@ -69,15 +69,39 @@ int RarStreamOpen(vlc_object_t *object)
     if (RarProbe(s->p_source))
         return VLC_EGENERIC;
 
-    int count;
-    rar_file_t **files;
+    struct
+    {
+        int filescount;
+        rar_file_t **files;
+        unsigned int i_nbvols;
+    } newscheme = { 0, NULL, 0 }, oldscheme = { 0, NULL, 0 }, *p_scheme;
+
     const int64_t position = stream_Tell(s->p_source);
-    if ((RarParse(s->p_source, &count, &files, false) &&
-         RarParse(s->p_source, &count, &files, true )) || count == 0 )
+
+    if (RarParse(s->p_source, &newscheme.filescount, &newscheme.files, &newscheme.i_nbvols, false)
+            || (newscheme.filescount < 2 && newscheme.i_nbvols < 2) )
+    {
+        /* We might want to lookup old naming scheme, could be a part1.rar,part1.r00 */
+        stream_Seek(s->p_source, 0);
+        RarParse(s->p_source, &oldscheme.filescount, &oldscheme.files, &oldscheme.i_nbvols, true );
+    }
+
+    if (oldscheme.filescount >= newscheme.filescount && oldscheme.i_nbvols > newscheme.i_nbvols)
+    {
+        free(newscheme.files);
+        p_scheme = &oldscheme;
+    }
+    else if (newscheme.filescount)
+    {
+        free(oldscheme.files);
+        p_scheme = &newscheme;
+    }
+    else
     {
         stream_Seek(s->p_source, position);
         msg_Info(s, "Invalid or unsupported RAR archive");
-        free(files);
+        free(oldscheme.files);
+        free(newscheme.files);
         return VLC_EGENERIC;
     }
 
@@ -97,8 +121,8 @@ int RarStreamOpen(vlc_object_t *object)
     free(encoded);
 
     char *data = strdup("#EXTM3U\n");
-    for (int i = 0; i < count; i++) {
-        rar_file_t *f = files[i];
+    for (int i = 0; i < p_scheme->filescount; i++) {
+        rar_file_t *f = p_scheme->files[i];
         char *next;
         if (base && data &&
             asprintf(&next, "%s"
@@ -111,7 +135,7 @@ int RarStreamOpen(vlc_object_t *object)
         RarFileDelete(f);
     }
     free(base);
-    free(files);
+    free(p_scheme->files);
     if (!data)
         return VLC_EGENERIC;
     stream_t *payload = stream_MemoryNew(s, (uint8_t*)data, strlen(data), false);