static int SkipEnd(stream_t *s, const rar_block_t *hdr) { if (!(hdr->flags & RAR_BLOCK_END_HAS_NEXT)) return VLC_EGENERIC; if (SkipBlock(s, hdr)) return VLC_EGENERIC; /* Now, we need to look for a marker block, * It seems that there is garbage at EOF */ for (;;) { const uint8_t *peek; if (stream_Peek(s, &peek, rar_marker_size) < rar_marker_size) return VLC_EGENERIC; if (!memcmp(peek, rar_marker, rar_marker_size)) break; if (stream_Read(s, NULL, 1) != 1) return VLC_EGENERIC; } /* Skip marker and archive blocks */ if (IgnoreBlock(s, RAR_BLOCK_MARKER)) return VLC_EGENERIC; if (IgnoreBlock(s, RAR_BLOCK_ARCHIVE)) return VLC_EGENERIC; return VLC_SUCCESS; }
static int SkipEnd(struct stream *s, const rar_block_t *hdr) { if (!(hdr->flags & RAR_BLOCK_END_HAS_NEXT)) return -1; if (SkipBlock(s, hdr)) return -1; /* Now, we need to look for a marker block, * It seems that there is garbage at EOF */ for (;;) { bstr peek = stream_peek(s, rar_marker_size); if (peek.len < rar_marker_size) return -1; if (!memcmp(peek.start, rar_marker, rar_marker_size)) break; if (!stream_skip(s, 1)) return -1; } /* Skip marker and archive blocks */ if (IgnoreBlock(s, RAR_BLOCK_MARKER)) return -1; if (IgnoreBlock(s, RAR_BLOCK_ARCHIVE)) return -1; return 0; }
int RarParse(stream_t *s, int *count, rar_file_t ***file) { *count = 0; *file = NULL; /* Skip marker */ if (IgnoreBlock(s, RAR_BLOCK_MARKER)) return VLC_EGENERIC; /* Skip archive */ if (IgnoreBlock(s, RAR_BLOCK_ARCHIVE)) return VLC_EGENERIC; /* */ for (;;) { rar_block_t bk; int ret; if (PeekBlock(s, &bk)) break; switch(bk.type) { case RAR_BLOCK_END: ret = SkipEnd(s, &bk); break; case RAR_BLOCK_FILE: ret = SkipFile(s, count, file, &bk); break; default: ret = SkipBlock(s, &bk); break; } if (ret) break; } return VLC_SUCCESS; }
int RarParse(stream_t *s, int *count, rar_file_t ***file) { *count = 0; *file = NULL; const rar_pattern_t *pattern = FindVolumePattern(s->psz_path); int volume_offset = 0; char *volume_mrl; if (asprintf(&volume_mrl, "%s://%s", s->psz_access, s->psz_path) < 0) return VLC_EGENERIC; stream_t *vol = s; for (;;) { /* Skip marker & archive */ if (IgnoreBlock(vol, RAR_BLOCK_MARKER) || IgnoreBlock(vol, RAR_BLOCK_ARCHIVE)) { if (vol != s) stream_Delete(vol); free(volume_mrl); return VLC_EGENERIC; } /* */ bool has_next = false; for (;;) { rar_block_t bk; int ret; if (PeekBlock(vol, &bk)) break; switch(bk.type) { case RAR_BLOCK_END: ret = SkipEnd(vol, &bk); has_next = ret && (bk.flags & RAR_BLOCK_END_HAS_NEXT); break; case RAR_BLOCK_FILE: ret = SkipFile(vol, count, file, &bk, volume_mrl); break; default: ret = SkipBlock(vol, &bk); break; } if (ret) break; } if (vol != s) stream_Delete(vol); if (!has_next || !pattern || (*count > 0 && !(*file)[*count -1]->is_complete)) { free(volume_mrl); return VLC_SUCCESS; } /* Open next volume */ const int volume_index = pattern->start + volume_offset++; if (volume_index > pattern->stop) { free(volume_mrl); return VLC_SUCCESS; } char *volume_base; if (asprintf(&volume_base, "%s://%.*s", s->psz_access, (int)(strlen(s->psz_path) - strlen(pattern->match)), s->psz_path) < 0) { free(volume_mrl); return VLC_SUCCESS; } free(volume_mrl); if (asprintf(&volume_mrl, pattern->format, volume_base, volume_index) < 0) volume_mrl = NULL; free(volume_base); if (!volume_mrl) return VLC_SUCCESS; vol = stream_UrlNew(s, volume_mrl); if (!vol) { free(volume_mrl); return VLC_SUCCESS; } } }
int RarParse(struct stream *s, int *count, rar_file_t ***file) { *count = 0; *file = NULL; const rar_pattern_t *pattern = FindVolumePattern(s->url); int volume_offset = 0; char *volume_mrl; if (asprintf(&volume_mrl, "%s", s->url) < 0) return -1; struct stream *vol = s; for (;;) { /* Skip marker & archive */ if (IgnoreBlock(vol, RAR_BLOCK_MARKER) || IgnoreBlock(vol, RAR_BLOCK_ARCHIVE)) { if (vol != s) free_stream(vol); free(volume_mrl); return -1; } /* */ int has_next = -1; for (;;) { rar_block_t bk; int ret; if (PeekBlock(vol, &bk)) break; switch(bk.type) { case RAR_BLOCK_END: ret = SkipEnd(vol, &bk); has_next = ret && (bk.flags & RAR_BLOCK_END_HAS_NEXT); break; case RAR_BLOCK_FILE: ret = SkipFile(vol, count, file, &bk, volume_mrl); break; default: ret = SkipBlock(vol, &bk); break; } if (ret) break; } if (has_next < 0 && *count > 0 && !(*file)[*count -1]->is_complete) has_next = 1; if (vol != s) free_stream(vol); if (!has_next || !pattern) goto done; /* Open next volume */ const int volume_index = pattern->start + volume_offset++; if (volume_index > pattern->stop) goto done; char *volume_base; if (asprintf(&volume_base, "%.*s", (int)(strlen(s->url) - strlen(pattern->match)), s->url) < 0) { goto done; } free(volume_mrl); if (pattern->start) { if (asprintf(&volume_mrl, pattern->format, volume_base, volume_index) < 0) volume_mrl = NULL; } else { if (asprintf(&volume_mrl, pattern->format, volume_base, 'r' + volume_index / 100, volume_index % 100) < 0) volume_mrl = NULL; } free(volume_base); if (!volume_mrl) goto done; vol = stream_create(volume_mrl, STREAM_READ | STREAM_NO_FILTERS, s->cancel, s->global); if (!vol) goto done; } done: free(volume_mrl); if (*count == 0) { talloc_free(*file); return -1; } return 0; }
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; if( s->psz_url == NULL ) return VLC_EGENERIC; const rar_pattern_t *pattern = FindVolumePattern(s->psz_url, b_extonly); int volume_offset = 0; char *volume_mrl = strdup(s->psz_url); if (volume_mrl == NULL) return VLC_ENOMEM; stream_t *vol = s; for (;;) { /* Skip marker & archive */ if (IgnoreBlock(vol, RAR_BLOCK_MARKER) || IgnoreBlock(vol, RAR_BLOCK_ARCHIVE)) { if (vol != s) stream_Delete(vol); free(volume_mrl); return VLC_EGENERIC; } /* */ int has_next = -1; for (;;) { rar_block_t bk; int ret; if (PeekBlock(vol, &bk)) break; switch(bk.type) { case RAR_BLOCK_END: ret = SkipEnd(vol, &bk); has_next = ret && (bk.flags & RAR_BLOCK_END_HAS_NEXT); break; case RAR_BLOCK_FILE: ret = SkipFile(vol, count, file, &bk, volume_mrl); break; default: ret = SkipBlock(vol, &bk); break; } if (ret) break; } if (has_next < 0 && *count > 0 && !(*file)[*count -1]->is_complete) has_next = 1; if (vol != s) stream_Delete(vol); free(volume_mrl); if (!has_next || !pattern) return VLC_SUCCESS; /* Open next volume */ const int volume_index = pattern->start + volume_offset++; if (volume_index > pattern->stop) return VLC_SUCCESS; char *volume_base = strndup(s->psz_url, strlen(s->psz_url) - strlen(pattern->match)); if (volume_base == NULL) return VLC_SUCCESS; if (pattern->start) { if (asprintf(&volume_mrl, pattern->format, volume_base, volume_index) < 0) volume_mrl = NULL; } else { if (asprintf(&volume_mrl, pattern->format, volume_base, 'r' + volume_index / 100, volume_index % 100) < 0) volume_mrl = NULL; } free(volume_base); if (!volume_mrl) return VLC_SUCCESS; const int s_flags = s->i_flags; s->i_flags |= OBJECT_FLAGS_NOINTERACT; vol = stream_UrlNew(s, volume_mrl); s->i_flags = s_flags; if (!vol) { free(volume_mrl); return VLC_SUCCESS; } (*pi_nbvols)++; } }