diff options
author | wm4 <wm4@nowhere> | 2013-08-02 17:03:30 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-08-02 17:05:26 +0200 |
commit | 44d6ac06aed7c13cbace543920e706023551c3c2 (patch) | |
tree | f2b352e856c7b4286f873b1cd2f5a9a6465774b2 | |
parent | f8589c98891b11eea249c998b1dc2fac50c99b46 (diff) | |
download | mpv-44d6ac06aed7c13cbace543920e706023551c3c2.tar.bz2 mpv-44d6ac06aed7c13cbace543920e706023551c3c2.tar.xz |
stream: parse URL escapes for file://
So for example "file:///file%20name.mkv" will open "file name.mkv".
I'm not sure whether we want/need this. The old code didn't do it.
Also, it's not really clear whether this is handled correctly. It
seems the corresponding freedesktop.org "standard" allows a (useless)
hostname part, which we should skip in theory. The number of slashes
is not really clear either. We can open relative filenames (by removing
one of the slashes from the example above), which is perhaps an
unneeded feature. How does this even work with Windows paths?
This issues can probably be corrected later.
The URL unescape code is based on code from m_option.c removed with
a recent commit.
-rw-r--r-- | stream/stream.c | 31 | ||||
-rw-r--r-- | stream/stream.h | 2 | ||||
-rw-r--r-- | stream/stream_dvd.c | 4 | ||||
-rw-r--r-- | stream/stream_file.c | 4 |
4 files changed, 41 insertions, 0 deletions
diff --git a/stream/stream.c b/stream/stream.c index a4d9238d46..4160e7267e 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -116,6 +116,37 @@ static const stream_info_t *const auto_open_streams[] = { static int stream_seek_unbuffered(stream_t *s, int64_t newpos); +static int from_hex(unsigned char c) +{ + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + if (c >= '0' && c <= '9') + return c - '0'; + return -1; +} + +// Replace escape sequences in an URL (or a part of an URL) +void mp_url_unescape_inplace(char *buf) +{ + int len = strlen(buf); + int o = 0; + for (int i = 0; i < len; i++) { + unsigned char c = buf[i]; + if (c == '%' && i + 2 < len) { //must have 2 more chars + int c1 = from_hex(buf[i + 1]); + int c2 = from_hex(buf[i + 2]); + if (c1 >= 0 && c2 >= 0) { + c = c1 * 16 + c2; + i = i + 2; //only skip next 2 chars if valid esc + } + } + buf[o++] = c; + } + buf[o++] = '\0'; +} + static const char *find_url_opt(struct stream *s, const char *opt) { for (int n = 0; s->info->url_options && s->info->url_options[n][0]; n++) { diff --git a/stream/stream.h b/stream/stream.h index 9800efbafd..e928a258b6 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -260,4 +260,6 @@ typedef struct { int channels; } stream_language_t; +void mp_url_unescape_inplace(char *buf); + #endif /* MPLAYER_STREAM_H */ diff --git a/stream/stream_dvd.c b/stream/stream_dvd.c index 624ea4c672..c9473c4b67 100644 --- a/stream/stream_dvd.c +++ b/stream/stream_dvd.c @@ -1050,6 +1050,10 @@ static int ifo_stream_open (stream_t *stream, int mode) stream->priv = priv; *priv = stream_priv_dflts; + // "file://" prefix -> decode URL-style escapes + if (strlen(stream->url) > strlen(stream->path)) + mp_url_unescape_inplace(stream->path); + int len = strlen(stream->path); if (len < 4 || strcasecmp (stream->path + len - 4, ".ifo")) return STREAM_UNSUPPORTED; diff --git a/stream/stream_file.c b/stream/stream_file.c index dc85314f71..1e9f372ba4 100644 --- a/stream/stream_file.c +++ b/stream/stream_file.c @@ -125,6 +125,10 @@ static int open_f(stream_t *stream, int mode) return STREAM_UNSUPPORTED; } + // "file://" prefix -> decode URL-style escapes + if (strlen(stream->url) > strlen(stream->path)) + mp_url_unescape_inplace(stream->path); + #if HAVE_DOS_PATHS // extract '/' from '/x:/path' if( filename[ 0 ] == '/' && filename[ 1 ] && filename[ 2 ] == ':' ) |