Example #1
0
static int Open(vlc_object_t *object)
{
    access_t *access = (access_t*)object;

    if (!strchr(access->psz_location, '|'))
        return VLC_EGENERIC;

    char *base = strdup(access->psz_location);
    if (!base)
        return VLC_EGENERIC;
    char *name = strchr(base, '|');
    *name++ = '\0';
    decode_URI(base);

    stream_t *s = stream_UrlNew(access, base);
    if (!s)
        goto error;
    int count;
    rar_file_t **files;
    if (RarProbe(s) || RarParse(s, &count, &files) || count <= 0)
        goto error;
    rar_file_t *file = NULL;
    for (int i = 0; i < count; i++) {
        if (!file && !strcmp(files[i]->name, name))
            file = files[i];
        else
            RarFileDelete(files[i]);
    }
    free(files);
    if (!file)
        goto error;

    access_sys_t *sys = access->p_sys = malloc(sizeof(*sys));
    sys->s    = s;
    sys->file = file;

    access->pf_read    = Read;
    access->pf_block   = NULL;
    access->pf_control = Control;
    access->pf_seek    = Seek;

    access_InitFields(access);
    access->info.i_size = file->size;

    rar_file_chunk_t dummy = {
        .mrl = base,
    };
    sys->chunk = &dummy;
    Seek(access, 0);

    free(base);
    return VLC_SUCCESS;

error:
    if (s)
        stream_Delete(s);
    free(base);
    return VLC_EGENERIC;
}
Example #2
0
static void Close(vlc_object_t *object)
{
    access_t *access = (access_t*)object;
    access_sys_t *sys = access->p_sys;

    if (sys->s)
        stream_Delete(sys->s);
    RarFileDelete(sys->file);
    free(sys);
}
Example #3
0
static int open_file(struct demuxer *demuxer, enum demux_check check)
{
    if (!demuxer->access_references)
        return -1;

    if (RarProbe(demuxer->stream))
        return -1;

    int count;
    rar_file_t **files;
    if (RarParse(demuxer->stream, &count, &files))
        return -1;

    void *tmp = talloc_new(NULL);
    talloc_steal(tmp, files);

    struct playlist *pl = talloc_zero(demuxer, struct playlist);
    demuxer->playlist = pl;

    // make it load rar://
    pl->disable_safety = true;

    char *prefix = mp_url_escape(tmp, demuxer->stream->url, "~|");
    for (int n = 0; n < count; n++) {
        // stream_rar.c does the real work
        playlist_add_file(pl,
                talloc_asprintf(tmp, "rar://%s|%s", prefix, files[n]->name));
        RarFileDelete(files[n]);
    }

    demuxer->filetype = "rar";
    demuxer->fully_read = true;

    talloc_free(tmp);
    return 0;
}
Example #4
0
int RarStreamOpen(vlc_object_t *object)
{
    stream_t *s = (stream_t*)object;

    if (RarProbe(s->p_source))
        return VLC_EGENERIC;

    int count;
    rar_file_t **files;
    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 )
    {
        stream_Seek(s->p_source, position);
        msg_Info(s, "Invalid or unsupported RAR archive");
        free(files);
        return VLC_EGENERIC;
    }

    /* TODO use xspf to have node for directories
     * Reusing WriteXSPF from the zip access is probably a good idea
     * (becareful about '\' and '/'.
     */
    char *mrl;
    if (asprintf(&mrl, "%s://%s", s->psz_access, s->psz_path)< 0)
        mrl = NULL;
    char *base;
    char *encoded = mrl ? encode_URI_component(mrl) : NULL;
    free(mrl);

    if (!encoded || asprintf(&base, "rar://%s", encoded) < 0)
        base = NULL;
    free(encoded);

    char *data = strdup("#EXTM3U\n");
    for (int i = 0; i < count; i++) {
        rar_file_t *f = files[i];
        char *next;
        if (base && data &&
            asprintf(&next, "%s"
                            "#EXTINF:,,%s\n"
                            "%s|%s\n",
                            data, f->name, base, f->name) >= 0) {
            free(data);
            data = next;
        }
        RarFileDelete(f);
    }
    free(base);
    free(files);
    if (!data)
        return VLC_EGENERIC;
    stream_t *payload = stream_MemoryNew(s, (uint8_t*)data, strlen(data), false);
    if (!payload) {
        free(data);
        return VLC_EGENERIC;
    }

    s->pf_read = Read;
    s->pf_peek = Peek;
    s->pf_control = Control;

    stream_sys_t *sys = s->p_sys = malloc(sizeof(*sys));
    if (!sys) {
        stream_Delete(payload);
        return VLC_ENOMEM;
    }
    sys->payload = payload;

    char *tmp;
    if (asprintf(&tmp, "%s.m3u", s->psz_path) < 0) {
        RarStreamClose(object);
        return VLC_ENOMEM;
    }
    free(s->psz_path);
    s->psz_path = tmp;

    return VLC_SUCCESS;
}
Example #5
0
int RarAccessOpen(vlc_object_t *object)
{
    access_t *access = (access_t*)object;

    const char *name = strchr(access->psz_location, '|');
    if (name == NULL)
        return VLC_EGENERIC;

    char *base = strndup(access->psz_location, name - access->psz_location);
    if (unlikely(base == NULL))
        return VLC_ENOMEM;

    name++;
    decode_URI(base);

    stream_t *s = stream_UrlNew(access, base);
    if (!s || RarProbe(s))
        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)
    {
        for (int i = 0; i < newscheme.filescount; i++)
            RarFileDelete(newscheme.files[i]);
        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)
    {
        for (int i = 0; i < oldscheme.filescount; i++)
            RarFileDelete(oldscheme.files[i]);
        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");
        for (int i = 0; i < oldscheme.filescount; i++)
            RarFileDelete(oldscheme.files[i]);
        free(oldscheme.files);
        for (int i = 0; i < newscheme.filescount; i++)
            RarFileDelete(newscheme.files[i]);
        free(newscheme.files);
        goto error;
    }

    rar_file_t *file = NULL;
    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(p_scheme->files[i]);
    }
    free(p_scheme->files);
    if (!file)
        goto error;

    access_sys_t *sys = access->p_sys = malloc(sizeof(*sys));
    sys->s    = s;
    sys->file = file;

    access->pf_read    = Read;
    access->pf_block   = NULL;
    access->pf_control = Control;
    access->pf_seek    = Seek;

    access_InitFields(access);

    rar_file_chunk_t dummy = {
        .mrl = base,
    };
    sys->chunk = &dummy;
    Seek(access, 0);

    free(base);
    return VLC_SUCCESS;

error:
    if (s)
        stream_Delete(s);
    free(base);
    return VLC_EGENERIC;
}