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)
decode_URI(base);
stream_t *s = stream_UrlNew(access, base);
if (!s)
if (!s || RarProbe(s))
goto error;
int count = 0;
struct
{
int filescount;
rar_file_t **files;
if ( RarProbe(s) || (
RarParse(s, &count, &files, false ) &&
RarParse(s, &count, &files, true )
) ||
count <= 0 )
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;
......
......@@ -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)++;
}
}
......@@ -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 *);
......
......@@ -69,15 +69,39 @@ int RarStreamOpen(vlc_object_t *object)
if (RarProbe(s->p_source))
return VLC_EGENERIC;
int count;
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);
......
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