diff --git a/common/encode_lavc.c b/common/encode_lavc.c index 2b9bdb4a66..b64232fb87 100644 --- a/common/encode_lavc.c +++ b/common/encode_lavc.c @@ -830,7 +830,9 @@ static void encoder_2pass_prepare(struct encoder_context *p) if (p->encoder->flags & AV_CODEC_FLAG_PASS2) { MP_INFO(p, "Reading 2-pass log: %s\n", filename); - struct stream *s = stream_open(filename, p->global); + struct stream *s = stream_create(filename, + STREAM_ORIGIN_DIRECT | STREAM_READ, + NULL, p->global); if (s) { struct bstr content = stream_read_complete(s, p, 1000000000); if (content.start) { diff --git a/common/playlist.c b/common/playlist.c index 7572e67780..b5d6ca15c2 100644 --- a/common/playlist.c +++ b/common/playlist.c @@ -32,6 +32,7 @@ struct playlist_entry *playlist_entry_new(const char *filename) struct playlist_entry *e = talloc_zero(NULL, struct playlist_entry); char *local_filename = mp_file_url_to_filename(e, bstr0(filename)); e->filename = local_filename ? local_filename : talloc_strdup(e, filename); + e->stream_flags = STREAM_ORIGIN_DIRECT; return e; } @@ -281,7 +282,10 @@ struct playlist *playlist_parse_file(const char *file, struct mp_cancel *cancel, struct mp_log *log = mp_log_new(NULL, global->log, "!playlist_parser"); mp_verbose(log, "Parsing playlist file %s...\n", file); - struct demuxer_params p = {.force_format = "playlist"}; + struct demuxer_params p = { + .force_format = "playlist", + .stream_flags = STREAM_ORIGIN_DIRECT, + }; struct demuxer *d = demux_open_url(file, &p, cancel, global); if (!d) { talloc_free(log); diff --git a/common/playlist.h b/common/playlist.h index a37c516519..bbf6821428 100644 --- a/common/playlist.h +++ b/common/playlist.h @@ -53,11 +53,8 @@ struct playlist_entry { // Additional refcount. Normally (reserved==0), the entry is owned by the // playlist, and this can be used to keep the entry alive. int reserved; + // Any flags from STREAM_ORIGIN_FLAGS. 0 if unknown. // Used to reject loading of unsafe entries from external playlists. - // Can have any of the following bit flags set: - // STREAM_SAFE_ONLY: only allow streams marked with is_safe - // STREAM_NETWORK_ONLY: only allow streams marked with is_network - // The value 0 allows everything. int stream_flags; }; @@ -69,8 +66,6 @@ struct playlist { // current_was_replaced is set to true. struct playlist_entry *current; bool current_was_replaced; - - bool disable_safety; }; void playlist_entry_add_param(struct playlist_entry *e, bstr name, bstr value); diff --git a/demux/demux.c b/demux/demux.c index 813cb1aa23..21ad3383c1 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -2894,6 +2894,7 @@ static void demux_copy(struct demuxer *dst, struct demuxer *src) dst->duration = src->duration; dst->is_network = src->is_network; dst->is_streaming = src->is_streaming; + dst->stream_origin = src->stream_origin; dst->priv = src->priv; dst->metadata = mp_tags_dup(dst, src->metadata); } @@ -3145,6 +3146,7 @@ struct parent_stream_info { bool seekable; bool is_network; bool is_streaming; + int stream_origin; struct mp_cancel *cancel; char *filename; }; @@ -3176,6 +3178,7 @@ static struct demuxer *open_given_type(struct mpv_global *global, .filename = talloc_strdup(demuxer, sinfo->filename), .is_network = sinfo->is_network, .is_streaming = sinfo->is_streaming, + .stream_origin = sinfo->stream_origin, .access_references = opts->access_references, .events = DEMUX_EVENT_ALL, .duration = -1, @@ -3309,6 +3312,7 @@ static struct demuxer *demux_open(struct stream *stream, .seekable = stream->seekable, .is_network = stream->is_network, .is_streaming = stream->streaming, + .stream_origin = stream->stream_origin, .cancel = cancel, .filename = talloc_strdup(NULL, stream->url), }; @@ -3364,9 +3368,8 @@ struct demuxer *demux_open_url(const char *url, struct mp_cancel *cancel, struct mpv_global *global) { - struct demuxer_params dummy = {0}; if (!params) - params = &dummy; + return NULL; struct mp_cancel *priv_cancel = mp_cancel_new(NULL); if (cancel) mp_cancel_set_parent(priv_cancel, cancel); diff --git a/demux/demux.h b/demux/demux.h index 235744c6f7..4c15e074c2 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -197,6 +197,7 @@ typedef struct demuxer { bool fully_read; bool is_network; // opened directly from a network stream bool is_streaming; // implies a "slow" input, such as network or FUSE + int stream_origin; // any STREAM_ORIGIN_* (set from source stream) bool access_references; // allow opening other files/URLs // Bitmask of DEMUX_EVENT_* diff --git a/demux/demux_cue.c b/demux/demux_cue.c index 35874972b9..edd1a97d1b 100644 --- a/demux/demux_cue.c +++ b/demux/demux_cue.c @@ -78,7 +78,11 @@ static bool try_open(struct timeline *tl, char *filename) || bstrcasecmp(bstr0(tl->demuxer->filename), bfilename) == 0) return false; - struct demuxer *d = demux_open_url(filename, NULL, tl->cancel, tl->global); + struct demuxer_params p = { + .stream_flags = tl->stream_origin, + }; + + struct demuxer *d = demux_open_url(filename, &p, tl->cancel, tl->global); // Since .bin files are raw PCM data with no headers, we have to explicitly // open them. Also, try to avoid to open files that are most likely not .bin // files, as that would only play noise. Checking the file extension is @@ -87,7 +91,7 @@ static bool try_open(struct timeline *tl, char *filename) // CD sector size (2352 bytes) if (!d && bstr_case_endswith(bfilename, bstr0(".bin"))) { MP_WARN(tl, "CUE: Opening as BIN file!\n"); - struct demuxer_params p = {.force_format = "rawaudio"}; + p.force_format = "rawaudio"; d = demux_open_url(filename, &p, tl->cancel, tl->global); } if (d) { diff --git a/demux/demux_disc.c b/demux/demux_disc.c index 919360d074..3dfff45403 100644 --- a/demux/demux_disc.c +++ b/demux/demux_disc.c @@ -296,6 +296,7 @@ static int d_open(demuxer_t *demuxer, enum demux_check check) struct demuxer_params params = { .force_format = "+lavf", .external_stream = demuxer->stream, + .stream_flags = demuxer->stream_origin, }; struct stream *cur = demuxer->stream; diff --git a/demux/demux_edl.c b/demux/demux_edl.c index 1ac912888f..b1f268ad8b 100644 --- a/demux/demux_edl.c +++ b/demux/demux_edl.c @@ -203,6 +203,7 @@ static struct demuxer *open_source(struct timeline *root, } struct demuxer_params params = { .init_fragment = tl->init_fragment, + .stream_flags = root->stream_origin, }; struct demuxer *d = demux_open_url(filename, ¶ms, root->cancel, root->global); @@ -268,7 +269,8 @@ static struct timeline_par *build_timeline(struct timeline *root, if (parts->init_fragment_url && parts->init_fragment_url[0]) { MP_VERBOSE(root, "Opening init fragment...\n"); - stream_t *s = stream_create(parts->init_fragment_url, STREAM_READ, + stream_t *s = stream_create(parts->init_fragment_url, + STREAM_READ | root->stream_origin, root->cancel, root->global); if (s) { root->is_network |= s->is_network; @@ -282,6 +284,7 @@ static struct timeline_par *build_timeline(struct timeline *root, } struct demuxer_params params = { .init_fragment = tl->init_fragment, + .stream_flags = root->stream_origin, }; tl->track_layout = demux_open_url("memory://", ¶ms, root->cancel, root->global); diff --git a/demux/demux_libarchive.c b/demux/demux_libarchive.c index 80bd3e240e..f2e669aa72 100644 --- a/demux/demux_libarchive.c +++ b/demux/demux_libarchive.c @@ -64,9 +64,6 @@ static int open_file(struct demuxer *demuxer, enum demux_check check) struct playlist *pl = talloc_zero(demuxer, struct playlist); demuxer->playlist = pl; - // make it load archive:// - pl->disable_safety = true; - char *prefix = mp_url_escape(mpa, demuxer->stream->url, "~|"); char **files = NULL; @@ -85,6 +82,9 @@ static int open_file(struct demuxer *demuxer, enum demux_check check) for (int n = 0; n < num_files; n++) playlist_add_file(pl, files[n]); + for (struct playlist_entry *e = pl->first; e; e = e->next) + e->stream_flags = demuxer->stream_origin; + demuxer->filetype = "archive"; demuxer->fully_read = true; diff --git a/demux/demux_mf.c b/demux/demux_mf.c index 6698ef8c62..2f46d356f3 100644 --- a/demux/demux_mf.c +++ b/demux/demux_mf.c @@ -188,8 +188,10 @@ static bool demux_mf_read_packet(struct demuxer *demuxer, struct stream *stream = entry_stream; if (!stream) { char *filename = mf->names[mf->curr_frame]; - if (filename) - stream = stream_open(filename, demuxer->global); + if (filename) { + stream = stream_create(filename, demuxer->stream_origin | STREAM_READ, + demuxer->cancel, demuxer->global); + } } if (stream) { diff --git a/demux/demux_mkv_timeline.c b/demux/demux_mkv_timeline.c index 5bbadc0781..22d859c75c 100644 --- a/demux/demux_mkv_timeline.c +++ b/demux/demux_mkv_timeline.c @@ -172,6 +172,7 @@ static bool check_file_seg(struct tl_ctx *ctx, char *filename, int segment) .matroska_wanted_segment = segment, .matroska_was_valid = &was_valid, .disable_timeline = true, + .stream_flags = ctx->tl->stream_origin, }; struct mp_cancel *cancel = ctx->tl->cancel; if (mp_cancel_test(cancel)) diff --git a/demux/demux_playlist.c b/demux/demux_playlist.c index 00db544b30..b40beda980 100644 --- a/demux/demux_playlist.c +++ b/demux/demux_playlist.c @@ -462,6 +462,8 @@ static int open_file(struct demuxer *demuxer, enum demux_check check) bool ok = fmt->parse(p) >= 0 && !p->error; if (p->add_base) playlist_add_base_path(p->pl, mp_dirname(demuxer->filename)); + for (struct playlist_entry *e = p->pl->first; e; e = e->next) + e->stream_flags = demuxer->stream_origin; demuxer->playlist = talloc_steal(demuxer, p->pl); demuxer->filetype = p->format ? p->format : fmt->name; demuxer->fully_read = true; diff --git a/demux/demux_timeline.c b/demux/demux_timeline.c index f8f096c464..ecce06bcb2 100644 --- a/demux/demux_timeline.c +++ b/demux/demux_timeline.c @@ -212,6 +212,7 @@ static void reopen_lazy_segments(struct demuxer *demuxer, struct demuxer_params params = { .init_fragment = src->tl->init_fragment, .skip_lavf_probing = true, + .stream_flags = demuxer->stream_origin, }; src->current->d = demux_open_url(src->current->url, ¶ms, demuxer->cancel, demuxer->global); diff --git a/demux/timeline.c b/demux/timeline.c index 967c20da01..0e5ff75192 100644 --- a/demux/timeline.c +++ b/demux/timeline.c @@ -17,6 +17,7 @@ struct timeline *timeline_load(struct mpv_global *global, struct mp_log *log, .cancel = demuxer->cancel, .demuxer = demuxer, .format = "unknown", + .stream_origin = demuxer->stream_origin, }; demuxer->desc->load_timeline(tl); diff --git a/demux/timeline.h b/demux/timeline.h index e64b2f96c9..c8151a0606 100644 --- a/demux/timeline.h +++ b/demux/timeline.h @@ -36,6 +36,7 @@ struct timeline { struct mp_cancel *cancel; bool is_network, is_streaming; + int stream_origin; const char *format; // main source, and all other sources (this usually only has special meaning diff --git a/input/input.c b/input/input.c index 1bc8e303f6..f9475648b0 100644 --- a/input/input.c +++ b/input/input.c @@ -1276,7 +1276,7 @@ static int parse_config_file(struct input_ctx *ictx, char *file, bool warn) file = mp_get_user_path(tmp, ictx->global, file); - s = stream_open(file, ictx->global); + s = stream_create(file, STREAM_ORIGIN_DIRECT | STREAM_READ, NULL, ictx->global); if (!s) { MP_ERR(ictx, "Can't open input config file %s.\n", file); goto done; diff --git a/options/options.c b/options/options.c index a874e95483..312354d988 100644 --- a/options/options.c +++ b/options/options.c @@ -649,7 +649,6 @@ static const m_option_t mp_opts[] = { OPT_STRING("chapters-file", chapter_file, M_OPT_FILE), - OPT_FLAG("load-unsafe-playlists", load_unsafe_playlists, 0), OPT_FLAG("merge-files", merge_files, 0), // a-v sync stuff: diff --git a/options/options.h b/options/options.h index 588b897e57..c87a4f2d36 100644 --- a/options/options.h +++ b/options/options.h @@ -194,7 +194,6 @@ typedef struct MPOpts { int chapter_merge_threshold; double chapter_seek_threshold; char *chapter_file; - int load_unsafe_playlists; int merge_files; int quiet; int load_config; diff --git a/player/loadfile.c b/player/loadfile.c index 2535e75617..462355f60e 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -746,6 +746,7 @@ int mp_add_external_file(struct MPContext *mpctx, char *filename, struct demuxer_params params = { .is_top_level = true, + .stream_flags = STREAM_ORIGIN_DIRECT, }; switch (filter) { @@ -949,7 +950,8 @@ static void load_chapters(struct MPContext *mpctx) if (chapter_file && chapter_file[0]) { chapter_file = talloc_strdup(NULL, chapter_file); mp_core_unlock(mpctx); - struct demuxer *demux = demux_open_url(chapter_file, NULL, + struct demuxer_params p = {.stream_flags = STREAM_ORIGIN_DIRECT}; + struct demuxer *demux = demux_open_url(chapter_file, &p, mpctx->playback_abort, mpctx->global); mp_core_lock(mpctx); @@ -1065,8 +1067,6 @@ static void start_open(struct MPContext *mpctx, char *url, int url_flags, mpctx->open_format = talloc_strdup(NULL, mpctx->opts->demuxer_name); mpctx->open_url_flags = url_flags; mpctx->open_for_prefetch = for_prefetch && mpctx->opts->demuxer_thread; - if (mpctx->opts->load_unsafe_playlists) - mpctx->open_url_flags = 0; if (pthread_create(&mpctx->open_thread, NULL, open_demux_thread, mpctx)) { cancel_open(mpctx); @@ -1473,14 +1473,6 @@ static void play_current_file(struct MPContext *mpctx) if (mpctx->demuxer->playlist) { struct playlist *pl = mpctx->demuxer->playlist; - int entry_stream_flags = 0; - if (!pl->disable_safety && !mpctx->opts->load_unsafe_playlists) { - entry_stream_flags = STREAM_SAFE_ONLY; - if (mpctx->demuxer->is_network) - entry_stream_flags |= STREAM_NETWORK_ONLY; - } - for (struct playlist_entry *e = pl->first; e; e = e->next) - e->stream_flags |= entry_stream_flags; transfer_playlist(mpctx, pl); mp_notify_property(mpctx, "playlist"); mpctx->error_playing = 2; diff --git a/player/misc.c b/player/misc.c index ae4550fec5..5a96d6cc25 100644 --- a/player/misc.c +++ b/player/misc.c @@ -238,7 +238,9 @@ void error_on_track(struct MPContext *mpctx, struct track *track) int stream_dump(struct MPContext *mpctx, const char *source_filename) { struct MPOpts *opts = mpctx->opts; - stream_t *stream = stream_open(source_filename, mpctx->global); + stream_t *stream = stream_create(source_filename, + STREAM_ORIGIN_DIRECT | STREAM_READ, + mpctx->playback_abort, mpctx->global); if (!stream) return -1; diff --git a/stream/stream.c b/stream/stream.c index 271e268a1c..157776cd87 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -101,6 +101,7 @@ static const stream_info_t *const stream_list[] = { struct stream_opts { int64_t buffer_size; + int load_unsafe_playlists; }; #define OPT_BASE_STRUCT struct stream_opts @@ -109,6 +110,7 @@ const struct m_sub_options stream_conf = { .opts = (const struct m_option[]){ OPT_BYTE_SIZE("stream-buffer-size", buffer_size, 0, STREAM_MIN_BUFFER_SIZE, 512 * 1024 * 1024), + OPT_FLAG("load-unsafe-playlists", load_unsafe_playlists, 0), {0} }, .size = sizeof(struct stream_opts), @@ -202,6 +204,30 @@ static const char *match_proto(const char *url, const char *proto) return NULL; } +// src and new are both STREAM_ORIGIN_* values. This checks whether a stream +// with flags "new" can be opened from the "src". On success, return +// new origin, on incompatibility return 0. +static int check_origin(int src, int new) +{ + switch (src) { + case STREAM_ORIGIN_DIRECT: + case STREAM_ORIGIN_UNSAFE: + // Allow anything, but constrain it to the new origin. + return new; + case STREAM_ORIGIN_FS: + // From unix FS, allow all but unsafe. + if (new == STREAM_ORIGIN_FS || new == STREAM_ORIGIN_NET) + return new; + break; + case STREAM_ORIGIN_NET: + // Allow only other network links. + if (new == STREAM_ORIGIN_NET) + return new; + break; + } + return 0; +} + // Read len bytes from the start position, and wrap around as needed. Limit the // actually read data to the size of the buffer. Return amount of copied bytes. // len: max bytes to copy to dst @@ -289,11 +315,6 @@ static int stream_create_instance(const stream_info_t *sinfo, *ret = NULL; - if (!sinfo->is_safe && (flags & STREAM_SAFE_ONLY)) - return STREAM_UNSAFE; - if (!sinfo->is_network && (flags & STREAM_NETWORK_ONLY)) - return STREAM_UNSAFE; - const char *path = url; for (int n = 0; sinfo->protocols && sinfo->protocols[n]; n++) { path = match_proto(url, sinfo->protocols[n]); @@ -304,11 +325,9 @@ static int stream_create_instance(const stream_info_t *sinfo, if (!path) return STREAM_NO_MATCH; - struct stream_opts *opts = - mp_get_config_group(NULL, args->global, &stream_conf); - stream_t *s = talloc_zero(NULL, stream_t); s->global = args->global; + struct stream_opts *opts = mp_get_config_group(s, s->global, &stream_conf); if (flags & STREAM_SILENT) { s->log = mp_null_log; } else { @@ -318,7 +337,6 @@ static int stream_create_instance(const stream_info_t *sinfo, s->cancel = args->cancel; s->url = talloc_strdup(s, url); s->path = talloc_strdup(s, path); - s->is_network = sinfo->is_network; s->mode = flags & (STREAM_READ | STREAM_WRITE); s->requested_buffer_size = opts->buffer_size; @@ -326,8 +344,6 @@ static int stream_create_instance(const stream_info_t *sinfo, mp_read_option_raw(s->global, "access-references", &m_option_type_flag, &opt); s->access_references = opt; - talloc_free(opts); - MP_VERBOSE(s, "Opening %s\n", url); if (strlen(url) > INT_MAX / 8) { @@ -342,6 +358,18 @@ static int stream_create_instance(const stream_info_t *sinfo, return STREAM_NO_MATCH; } + s->stream_origin = flags & STREAM_ORIGIN_MASK; // pass through by default + if (opts->load_unsafe_playlists) { + s->stream_origin = STREAM_ORIGIN_DIRECT; + } else if (sinfo->stream_origin) { + s->stream_origin = check_origin(s->stream_origin, sinfo->stream_origin); + } + + if (!s->stream_origin) { + talloc_free(s); + return STREAM_UNSAFE; + } + int r = STREAM_UNSUPPORTED; if (sinfo->open2) { r = sinfo->open2(s, args); @@ -429,14 +457,10 @@ struct stream *stream_create(const char *url, int flags, return s; } -struct stream *stream_open(const char *filename, struct mpv_global *global) -{ - return stream_create(filename, STREAM_READ, NULL, global); -} - stream_t *open_output_stream(const char *filename, struct mpv_global *global) { - return stream_create(filename, STREAM_WRITE, NULL, global); + return stream_create(filename, STREAM_ORIGIN_DIRECT | STREAM_WRITE, + NULL, global); } // Read function bypassing the local stream buffer. This will not write into @@ -787,7 +811,8 @@ struct bstr stream_read_file(const char *filename, void *talloc_ctx, { struct bstr res = {0}; char *fname = mp_get_user_path(NULL, global, filename); - stream_t *s = stream_open(fname, global); + stream_t *s = + stream_create(fname, STREAM_ORIGIN_DIRECT | STREAM_READ, NULL, global); if (s) { res = stream_read_complete(s, talloc_ctx, max_size); free_stream(s); diff --git a/stream/stream.h b/stream/stream.h index aa764818b7..c85aeffd73 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -32,14 +32,23 @@ // it's guaranteed that you can seek back by <= of this size again. #define STREAM_BUFFER_SIZE 2048 -// stream->mode -#define STREAM_READ 0 -#define STREAM_WRITE 1 - // flags for stream_open_ext (this includes STREAM_READ and STREAM_WRITE) -#define STREAM_SAFE_ONLY 4 -#define STREAM_NETWORK_ONLY 8 -#define STREAM_SILENT 16 + +// stream->mode +#define STREAM_READ 0 +#define STREAM_WRITE (1 << 0) + +#define STREAM_SILENT (1 << 1) + +// Origin value for "security". This is an integer within the flags bit-field. +#define STREAM_ORIGIN_DIRECT (1 << 2) // passed from cmdline or loadfile +#define STREAM_ORIGIN_FS (2 << 2) // referenced from playlist on unix FS +#define STREAM_ORIGIN_NET (3 << 2) // referenced from playlist on network +#define STREAM_ORIGIN_UNSAFE (4 << 2) // from a grotesque source + +#define STREAM_ORIGIN_MASK (7 << 2) // for extracting origin value from flags + +// end flags for stream_open_ext (the naming convention sucks) #define STREAM_UNSAFE -3 #define STREAM_NO_MATCH -2 @@ -100,8 +109,8 @@ typedef struct stream_info_st { int (*open2)(struct stream *st, struct stream_open_args *args); const char *const *protocols; bool can_write; // correctly checks for READ/WRITE modes - bool is_safe; // opening is no security issue, even with remote provided URLs - bool is_network; // used to restrict remote playlist entries to remote URLs + int stream_origin; // 0 or set of STREAM_ORIGIN_*; if 0, the same origin + // is set, or the stream's open() function handles it } stream_info_t; typedef struct stream { @@ -123,6 +132,7 @@ typedef struct stream { int64_t pos; int eof; // valid only after read calls that returned a short result int mode; //STREAM_READ or STREAM_WRITE + int stream_origin; // any STREAM_ORIGIN_* void *priv; // used for DVD, TV, RTSP etc char *url; // filename/url (possibly including protocol prefix) char *path; // filename (url without protocol prefix) @@ -132,7 +142,7 @@ typedef struct stream { bool streaming : 1; // known to be a network stream if true bool seekable : 1; // presence of general byte seeking support bool fast_skip : 1; // consider stream fast enough to fw-seek by skipping - bool is_network : 1; // original stream_info_t.is_network flag + bool is_network : 1; // I really don't know what this is for bool is_local_file : 1; // from the filesystem bool is_directory : 1; // directory on the filesystem bool access_references : 1; // open other streams @@ -223,7 +233,6 @@ struct stream_open_args { int stream_create_with_args(struct stream_open_args *args, struct stream **ret); struct stream *stream_create(const char *url, int flags, struct mp_cancel *c, struct mpv_global *global); -struct stream *stream_open(const char *filename, struct mpv_global *global); stream_t *open_output_stream(const char *filename, struct mpv_global *global); void mp_url_unescape_inplace(char *buf); diff --git a/stream/stream_avdevice.c b/stream/stream_avdevice.c index 5185b7a844..3cfdfe1a53 100644 --- a/stream/stream_avdevice.c +++ b/stream/stream_avdevice.c @@ -30,4 +30,5 @@ const stream_info_t stream_info_avdevice = { .name = "avdevice", .open = open_f, .protocols = (const char*const[]){ "avdevice", "av", NULL }, + .stream_origin = STREAM_ORIGIN_UNSAFE, }; diff --git a/stream/stream_bluray.c b/stream/stream_bluray.c index 1d57730539..19e99a458b 100644 --- a/stream/stream_bluray.c +++ b/stream/stream_bluray.c @@ -512,12 +512,14 @@ const stream_info_t stream_info_bluray = { .name = "bd", .open = bluray_stream_open, .protocols = (const char*const[]){ "bd", "br", "bluray", NULL }, + .stream_origin = STREAM_ORIGIN_UNSAFE, }; const stream_info_t stream_info_bdnav = { .name = "bdnav", .open = bluray_stream_open, .protocols = (const char*const[]){ "bdnav", "brnav", "bluraynav", NULL }, + .stream_origin = STREAM_ORIGIN_UNSAFE, }; static bool check_bdmv(const char *path) @@ -605,4 +607,5 @@ const stream_info_t stream_info_bdmv_dir = { .name = "bdmv/bluray", .open = bdmv_dir_stream_open, .protocols = (const char*const[]){ "file", "", NULL }, + .stream_origin = STREAM_ORIGIN_UNSAFE, }; diff --git a/stream/stream_cb.c b/stream/stream_cb.c index ba0b3e5da3..238dd1ac1c 100644 --- a/stream/stream_cb.c +++ b/stream/stream_cb.c @@ -106,4 +106,5 @@ static int open_cb(stream_t *stream) const stream_info_t stream_info_cb = { .name = "stream_callback", .open = open_cb, + .stream_origin = STREAM_ORIGIN_UNSAFE, }; diff --git a/stream/stream_cdda.c b/stream/stream_cdda.c index 158cfd0646..87be426992 100644 --- a/stream/stream_cdda.c +++ b/stream/stream_cdda.c @@ -401,4 +401,5 @@ const stream_info_t stream_info_cdda = { .name = "cdda", .open = open_cdda, .protocols = (const char*const[]){"cdda", NULL }, + .stream_origin = STREAM_ORIGIN_UNSAFE, }; diff --git a/stream/stream_concat.c b/stream/stream_concat.c index a10fee7912..060583a604 100644 --- a/stream/stream_concat.c +++ b/stream/stream_concat.c @@ -151,7 +151,7 @@ struct stream *stream_concat_open(struct mpv_global *global, struct mp_cancel *c .global = global, .cancel = c, .url = "concat://", - .flags = STREAM_READ | STREAM_SILENT, + .flags = STREAM_READ | STREAM_SILENT | STREAM_ORIGIN_DIRECT, .sinfo = &stream_info_concat, .special_arg = &arg, }; diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c index d6907cb792..c14cce8420 100644 --- a/stream/stream_dvb.c +++ b/stream/stream_dvb.c @@ -1267,4 +1267,5 @@ const stream_info_t stream_info_dvb = { .name = "dvbin", .open = dvb_open, .protocols = (const char *const[]){ "dvb", NULL }, + .stream_origin = STREAM_ORIGIN_UNSAFE, }; diff --git a/stream/stream_dvdnav.c b/stream/stream_dvdnav.c index 619284f393..d858c51aca 100644 --- a/stream/stream_dvdnav.c +++ b/stream/stream_dvdnav.c @@ -575,7 +575,7 @@ static int open_s_internal(stream_t *stream) if (!new_dvdnav_stream(stream, filename)) { MP_ERR(stream, "Couldn't open DVD device: %s\n", filename); - return STREAM_UNSUPPORTED; + return STREAM_ERROR; } if (p->track == TITLE_LONGEST) { // longest @@ -662,6 +662,7 @@ const stream_info_t stream_info_dvdnav = { .name = "dvdnav", .open = open_s, .protocols = (const char*const[]){ "dvd", "dvdnav", NULL }, + .stream_origin = STREAM_ORIGIN_UNSAFE, }; static bool check_ifo(const char *path) @@ -714,4 +715,5 @@ const stream_info_t stream_info_ifo_dvdnav = { .name = "ifo_dvdnav", .open = ifo_dvdnav_stream_open, .protocols = (const char*const[]){ "file", "", NULL }, + .stream_origin = STREAM_ORIGIN_UNSAFE, }; diff --git a/stream/stream_file.c b/stream/stream_file.c index 1ad9a5c7f5..a79ef0e913 100644 --- a/stream/stream_file.c +++ b/stream/stream_file.c @@ -349,5 +349,5 @@ const stream_info_t stream_info_file = { .protocols = (const char*const[]){ "file", "", "fd", "fdclose", "appending", NULL }, .can_write = true, - .is_safe = true, + .stream_origin = STREAM_ORIGIN_FS, }; diff --git a/stream/stream_lavf.c b/stream/stream_lavf.c index 604535c431..c20790a505 100644 --- a/stream/stream_lavf.c +++ b/stream/stream_lavf.c @@ -342,6 +342,8 @@ static int open_f(stream_t *stream) stream->close = close_f; // enable cache (should be avoided for files, but no way to detect this) stream->streaming = true; + if (stream->info->stream_origin == STREAM_ORIGIN_NET) + stream->is_network = true; res = STREAM_OK; out: @@ -418,8 +420,7 @@ const stream_info_t stream_info_ffmpeg = { "gopher", "data", NULL }, .can_write = true, - .is_safe = true, - .is_network = true, + .stream_origin = STREAM_ORIGIN_NET, }; // Unlike above, this is not marked as safe, and can contain protocols which @@ -433,6 +434,7 @@ const stream_info_t stream_info_ffmpeg_unsafe = { "lavf", "ffmpeg", "udp", "ftp", "tcp", "tls", "unix", "sftp", "md5", "concat", NULL }, + .stream_origin = STREAM_ORIGIN_UNSAFE, .can_write = true, }; diff --git a/stream/stream_libarchive.c b/stream/stream_libarchive.c index 2e300f3747..76b47e1633 100644 --- a/stream/stream_libarchive.c +++ b/stream/stream_libarchive.c @@ -93,7 +93,9 @@ static int open_cb(struct archive *arch, void *priv) struct mp_archive_volume *vol = priv; vol->seek_to = -1; if (!vol->src) { - vol->src = stream_create(vol->url, STREAM_READ, + vol->src = stream_create(vol->url, + STREAM_READ | + vol->mpa->primary_src->stream_origin, vol->mpa->primary_src->cancel, vol->mpa->primary_src->global); return vol->src ? ARCHIVE_OK : ARCHIVE_FATAL; @@ -207,7 +209,9 @@ static char **find_volumes(struct stream *primary_stream) struct bstr base = bstr_splice(primary_url, 0, -strlen(pattern->match)); for (int i = pattern->start; i <= pattern->stop; i++) { char* url = pattern->volume_url(res, pattern->format, base, i); - struct stream *s = stream_create(url, STREAM_READ | STREAM_SAFE_ONLY, + struct stream *s = stream_create(url, + STREAM_READ | + primary_stream->stream_origin, primary_stream->cancel, primary_stream->global); if (!s) { @@ -490,7 +494,7 @@ static int archive_entry_open(stream_t *stream) p->entry_name = name + 1; mp_url_unescape_inplace(base); - p->src = stream_create(base, STREAM_READ | STREAM_SAFE_ONLY, + p->src = stream_create(base, STREAM_READ | stream->stream_origin, stream->cancel, stream->global); if (!p->src) { archive_entry_close(stream); diff --git a/stream/stream_memory.c b/stream/stream_memory.c index 7b1092a76d..01246cf33f 100644 --- a/stream/stream_memory.c +++ b/stream/stream_memory.c @@ -86,7 +86,7 @@ struct stream *stream_memory_open(struct mpv_global *global, void *data, int len struct stream_open_args sargs = { .global = global, .url = "memory://", - .flags = STREAM_READ | STREAM_SILENT, + .flags = STREAM_READ | STREAM_SILENT | STREAM_ORIGIN_DIRECT, .sinfo = &stream_info_memory, .special_arg = &(bstr){data, len}, }; diff --git a/stream/stream_smb.c b/stream/stream_smb.c index 33928d4e61..1e52b55a37 100644 --- a/stream/stream_smb.c +++ b/stream/stream_smb.c @@ -151,4 +151,5 @@ const stream_info_t stream_info_smb = { .open = open_f, .protocols = (const char*const[]){"smb", NULL}, .can_write = true, //who's gonna do that? + .stream_origin = STREAM_ORIGIN_FS, };