From ad9f3bfe961b3f3bf3e047316419a60de8be49e7 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 10 May 2020 16:44:35 +0200 Subject: stream: make stream_read_file() more robust Change it to strictly accept local paths only. No more http://, no more $HOME expansion with "~/" or mpv config path expansion with "~~/". This should behave as if passing a path directly to open(). Reduce annoying log noise to further facilitate it using as open() replacement. --- stream/stream.c | 30 +++++++++++++++++++----------- stream/stream.h | 5 +++++ stream/stream_file.c | 29 +++++++++++++++++------------ 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/stream/stream.c b/stream/stream.c index 0d72aa082f..8361cd8748 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -319,14 +319,20 @@ static int stream_create_instance(const stream_info_t *sinfo, *ret = NULL; const char *path = url; - for (int n = 0; sinfo->protocols && sinfo->protocols[n]; n++) { - path = match_proto(url, sinfo->protocols[n]); - if (path) - break; - } - if (!path) - return STREAM_NO_MATCH; + if (flags & STREAM_LOCAL_FS_ONLY) { + if (!sinfo->local_fs) + return STREAM_NO_MATCH; + } else { + for (int n = 0; sinfo->protocols && sinfo->protocols[n]; n++) { + path = match_proto(url, sinfo->protocols[n]); + if (path) + break; + } + + if (!path) + return STREAM_NO_MATCH; + } stream_t *s = talloc_zero(NULL, stream_t); s->global = args->global; @@ -343,6 +349,9 @@ static int stream_create_instance(const stream_info_t *sinfo, s->mode = flags & (STREAM_READ | STREAM_WRITE); s->requested_buffer_size = opts->buffer_size; + if (flags & STREAM_LESS_NOISE) + mp_msg_set_max_level(s->log, MSGL_WARN); + int opt; mp_read_option_raw(s->global, "access-references", &m_option_type_flag, &opt); s->access_references = opt; @@ -820,14 +829,13 @@ struct bstr stream_read_file(const char *filename, void *talloc_ctx, struct mpv_global *global, int max_size) { struct bstr res = {0}; - char *fname = mp_get_user_path(NULL, global, filename); - stream_t *s = - stream_create(fname, STREAM_ORIGIN_DIRECT | STREAM_READ, NULL, global); + int flags = STREAM_ORIGIN_DIRECT | STREAM_READ | STREAM_LOCAL_FS_ONLY | + STREAM_LESS_NOISE; + stream_t *s = stream_create(filename, flags, NULL, global); if (s) { res = stream_read_complete(s, talloc_ctx, max_size); free_stream(s); } - talloc_free(fname); return res; } diff --git a/stream/stream.h b/stream/stream.h index 2c78a35959..c127860ceb 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -48,6 +48,9 @@ #define STREAM_ORIGIN_MASK (7 << 2) // for extracting origin value from flags +#define STREAM_LOCAL_FS_ONLY (1 << 5) // stream_file only, no URLs +#define STREAM_LESS_NOISE (1 << 6) // try to log errors only + // end flags for stream_open_ext (the naming convention sucks) #define STREAM_UNSAFE -3 @@ -109,6 +112,7 @@ 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 local_fs; // supports STREAM_LOCAL_FS_ONLY 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; @@ -218,6 +222,7 @@ struct bstr stream_read_complete(struct stream *s, void *talloc_ctx, int max_size); struct bstr stream_read_file(const char *filename, void *talloc_ctx, struct mpv_global *global, int max_size); + int stream_control(stream_t *s, int cmd, void *arg); void free_stream(stream_t *s); diff --git a/stream/stream_file.c b/stream/stream_file.c index 1c5223073b..d649ff4bdf 100644 --- a/stream/stream_file.c +++ b/stream/stream_file.c @@ -246,7 +246,7 @@ static bool check_stream_network(int fd) } #endif -static int open_f(stream_t *stream) +static int open_f(stream_t *stream, struct stream_open_args *args) { struct priv *p = talloc_ptrtype(stream, p); *p = (struct priv) { @@ -255,18 +255,21 @@ static int open_f(stream_t *stream) stream->priv = p; stream->is_local_file = true; + bool strict_fs = args->flags & STREAM_LOCAL_FS_ONLY; bool write = stream->mode == STREAM_WRITE; int m = O_CLOEXEC | (write ? O_RDWR | O_CREAT | O_TRUNC : O_RDONLY); - char *filename = mp_file_url_to_filename(stream, bstr0(stream->url)); - if (filename) { - stream->path = filename; - } else { - filename = stream->path; + char *filename = stream->path; + char *url = ""; + if (!strict_fs) { + char *fn = mp_file_url_to_filename(stream, bstr0(stream->url)); + if (fn) + filename = stream->path = fn; + url = stream->url; } - bool is_fdclose = strncmp(stream->url, "fdclose://", 10) == 0; - if (strncmp(stream->url, "fd://", 5) == 0 || is_fdclose) { + bool is_fdclose = strncmp(url, "fdclose://", 10) == 0; + if (strncmp(url, "fd://", 5) == 0 || is_fdclose) { char *begin = strstr(stream->url, "://") + 3, *end = NULL; p->fd = strtol(begin, &end, 0); if (!end || end == begin || end[0]) { @@ -275,7 +278,7 @@ static int open_f(stream_t *stream) } if (is_fdclose) p->close = true; - } else if (!strcmp(filename, "-")) { + } else if (!strict_fs && !strcmp(filename, "-")) { if (!write) { MP_INFO(stream, "Reading from stdin...\n"); p->fd = 0; @@ -306,7 +309,8 @@ static int open_f(stream_t *stream) if (fstat(p->fd, &st) == 0) { if (S_ISDIR(st.st_mode)) { stream->is_directory = true; - MP_INFO(stream, "This is a directory - adding to playlist.\n"); + if (!(args->flags & STREAM_LESS_NOISE)) + MP_INFO(stream, "This is a directory - adding to playlist.\n"); } else if (S_ISREG(st.st_mode)) { p->regular_file = true; #ifndef __MINGW32__ @@ -350,15 +354,16 @@ static int open_f(stream_t *stream) const stream_info_t stream_info_file = { .name = "file", - .open = open_f, + .open2 = open_f, .protocols = (const char*const[]){ "file", "", "appending", NULL }, .can_write = true, + .local_fs = true, .stream_origin = STREAM_ORIGIN_FS, }; const stream_info_t stream_info_fd = { .name = "fd", - .open = open_f, + .open2 = open_f, .protocols = (const char*const[]){ "fd", "fdclose", NULL }, .can_write = true, .stream_origin = STREAM_ORIGIN_UNSAFE, -- cgit v1.2.3