[vlc-commits] access: rar: guess scheme from volume count

Francois Cartegnie git at videolan.org
Wed Jul 30 07:06:22 CEST 2014


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Wed Jul 30 13:52:27 2014 +0900| [f877611b68e8b623134fd0509541e377b58d7dc7] | committer: Francois Cartegnie

access: rar: guess scheme from volume count

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

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=f877611b68e8b623134fd0509541e377b58d7dc7
---

 modules/access/rar/access.c |   56 ++++++++++++++++++++++++++++++++-----------
 modules/access/rar/rar.c    |    8 +++++--
 modules/access/rar/rar.h    |    2 +-
 modules/access/rar/stream.c |   40 ++++++++++++++++++++++++-------
 4 files changed, 81 insertions(+), 25 deletions(-)

diff --git a/modules/access/rar/access.c b/modules/access/rar/access.c
index ddba8f2..97a69da 100644
--- a/modules/access/rar/access.c
+++ b/modules/access/rar/access.c
@@ -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;
 
diff --git a/modules/access/rar/rar.c b/modules/access/rar/rar.c
index c644c4a..2611c6f 100644
--- a/modules/access/rar/rar.c
+++ b/modules/access/rar/rar.c
@@ -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)++;
     }
 }
 
diff --git a/modules/access/rar/rar.h b/modules/access/rar/rar.h
index 889309f..6542d4c 100644
--- a/modules/access/rar/rar.h
+++ b/modules/access/rar/rar.h
@@ -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 *);
diff --git a/modules/access/rar/stream.c b/modules/access/rar/stream.c
index 7929d97..4a4c761 100644
--- a/modules/access/rar/stream.c
+++ b/modules/access/rar/stream.c
@@ -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);



More information about the vlc-commits mailing list