Commit f877611b authored by Francois Cartegnie's avatar 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
parent 674e38ba
...@@ -154,24 +154,52 @@ int RarAccessOpen(vlc_object_t *object) ...@@ -154,24 +154,52 @@ int RarAccessOpen(vlc_object_t *object)
decode_URI(base); decode_URI(base);
stream_t *s = stream_UrlNew(access, base); stream_t *s = stream_UrlNew(access, base);
if (!s) if (!s || RarProbe(s))
goto error; goto error;
int count = 0;
rar_file_t **files; struct
if ( RarProbe(s) || ( {
RarParse(s, &count, &files, false ) && int filescount;
RarParse(s, &count, &files, true ) rar_file_t **files;
) || unsigned int i_nbvols;
count <= 0 ) } newscheme = { 0, NULL, 0 }, oldscheme = { 0, NULL, 0 }, *p_scheme;
goto error;
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; rar_file_t *file = NULL;
for (int i = 0; i < count; i++) { for (int i = 0; i < p_scheme->filescount; i++) {
if (!file && !strcmp(files[i]->name, name)) if (!file && !strcmp(p_scheme->files[i]->name, name))
file = files[i]; file = p_scheme->files[i];
else else
RarFileDelete(files[i]); RarFileDelete(p_scheme->files[i]);
} }
free(files); free(p_scheme->files);
if (!file) if (!file)
goto error; goto error;
......
...@@ -287,7 +287,8 @@ typedef struct { ...@@ -287,7 +287,8 @@ typedef struct {
static const rar_pattern_t *FindVolumePattern(const char *location, bool b_extonly ) static const rar_pattern_t *FindVolumePattern(const char *location, bool b_extonly )
{ {
static const rar_pattern_t patterns[] = { 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 { ".part001.rar", "%s.part%.3d.rar", 2, 999, false }, // new
{ ".rar", "%s.%c%.2d", 0, 999, true }, // old { ".rar", "%s.%c%.2d", 0, 999, true }, // old
{ NULL, NULL, 0, 0, false }, { NULL, NULL, 0, 0, false },
...@@ -309,10 +310,12 @@ static const rar_pattern_t *FindVolumePattern(const char *location, bool b_exton ...@@ -309,10 +310,12 @@ static const rar_pattern_t *FindVolumePattern(const char *location, bool b_exton
return NULL; 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; *count = 0;
*file = NULL; *file = NULL;
*pi_nbvols = 1;
const rar_pattern_t *pattern = FindVolumePattern(s->psz_path, b_extonly); const rar_pattern_t *pattern = FindVolumePattern(s->psz_path, b_extonly);
int volume_offset = 0; int volume_offset = 0;
...@@ -406,6 +409,7 @@ int RarParse(stream_t *s, int *count, rar_file_t ***file, bool b_extonly) ...@@ -406,6 +409,7 @@ int RarParse(stream_t *s, int *count, rar_file_t ***file, bool b_extonly)
free(volume_mrl); free(volume_mrl);
return VLC_SUCCESS; return VLC_SUCCESS;
} }
(*pi_nbvols)++;
} }
} }
...@@ -40,7 +40,7 @@ typedef struct { ...@@ -40,7 +40,7 @@ typedef struct {
int RarProbe(stream_t *); int RarProbe(stream_t *);
void RarFileDelete(rar_file_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 *); int RarAccessOpen(vlc_object_t *);
void RarAccessClose(vlc_object_t *); void RarAccessClose(vlc_object_t *);
......
...@@ -69,15 +69,39 @@ int RarStreamOpen(vlc_object_t *object) ...@@ -69,15 +69,39 @@ int RarStreamOpen(vlc_object_t *object)
if (RarProbe(s->p_source)) if (RarProbe(s->p_source))
return VLC_EGENERIC; return VLC_EGENERIC;
int count; struct
rar_file_t **files; {
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); 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); stream_Seek(s->p_source, position);
msg_Info(s, "Invalid or unsupported RAR archive"); msg_Info(s, "Invalid or unsupported RAR archive");
free(files); free(oldscheme.files);
free(newscheme.files);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
...@@ -97,8 +121,8 @@ int RarStreamOpen(vlc_object_t *object) ...@@ -97,8 +121,8 @@ int RarStreamOpen(vlc_object_t *object)
free(encoded); free(encoded);
char *data = strdup("#EXTM3U\n"); char *data = strdup("#EXTM3U\n");
for (int i = 0; i < count; i++) { for (int i = 0; i < p_scheme->filescount; i++) {
rar_file_t *f = files[i]; rar_file_t *f = p_scheme->files[i];
char *next; char *next;
if (base && data && if (base && data &&
asprintf(&next, "%s" asprintf(&next, "%s"
...@@ -111,7 +135,7 @@ int RarStreamOpen(vlc_object_t *object) ...@@ -111,7 +135,7 @@ int RarStreamOpen(vlc_object_t *object)
RarFileDelete(f); RarFileDelete(f);
} }
free(base); free(base);
free(files); free(p_scheme->files);
if (!data) if (!data)
return VLC_EGENERIC; return VLC_EGENERIC;
stream_t *payload = stream_MemoryNew(s, (uint8_t*)data, strlen(data), false); stream_t *payload = stream_MemoryNew(s, (uint8_t*)data, strlen(data), false);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment