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 ] == ':' )