mirror of https://github.com/mpv-player/mpv
stream_lavf: escape disallowed characters in http URLs
In my opinion, libavformat should be doing this. But a patch handling a very safe case rejected, so I suppose we have to do it manually. (This patch was only escaping spaces, which can never work because they break the basic syntax of the HTTP protocol.) This commit attempts to do 2 things: - Try to guess whether libavformat will use the URL for http. This is not always trivial, because some protocols will recursively pass part of the user URL to http in some way. - Try to fix invalid URLs. We fix only the simplest case: only characters that are never valid are escaped. This excludes invalid escape codes, which happen with freestanding '%' characters. Fixes #1495.
This commit is contained in:
parent
724f722d7f
commit
d558accaa6
|
@ -157,7 +157,7 @@ void mp_url_unescape_inplace(char *buf)
|
|||
// ok[0] != '~': additional characters that are not escaped
|
||||
// ok[0] == '~': do not escape anything but these characters
|
||||
// (can't override the unreserved characters, which are
|
||||
// never escaped, and '%', which is always escaped)
|
||||
// never escaped)
|
||||
char *mp_url_escape(void *talloc_ctx, const char *s, const char *ok)
|
||||
{
|
||||
int len = strlen(s);
|
||||
|
@ -167,7 +167,7 @@ char *mp_url_escape(void *talloc_ctx, const char *s, const char *ok)
|
|||
unsigned char c = s[i];
|
||||
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
||||
(c >= '0' && c <= '9') || strchr("-._~", c) ||
|
||||
(ok && ((ok[0] != '~') == !!strchr(ok, c)) && c != '%'))
|
||||
(ok && ((ok[0] != '~') == !!strchr(ok, c))))
|
||||
{
|
||||
buf[o++] = c;
|
||||
} else {
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include <libavformat/avio.h>
|
||||
#include <libavutil/opt.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "options/options.h"
|
||||
#include "options/path.h"
|
||||
#include "common/msg.h"
|
||||
|
@ -34,8 +33,6 @@
|
|||
#include "misc/bstr.h"
|
||||
#include "talloc.h"
|
||||
|
||||
struct stream_lavf_params *stream_lavf_opts;
|
||||
|
||||
#define OPT_BASE_STRUCT struct stream_lavf_params
|
||||
struct stream_lavf_params {
|
||||
char **avopts;
|
||||
|
@ -49,6 +46,8 @@ const struct m_sub_options stream_lavf_conf = {
|
|||
.size = sizeof(struct stream_lavf_params),
|
||||
};
|
||||
|
||||
static const char *const http_like[];
|
||||
|
||||
static int open_f(stream_t *stream);
|
||||
static struct mp_tags *read_icy(stream_t *stream);
|
||||
|
||||
|
@ -188,6 +187,21 @@ void mp_setup_av_network_options(AVDictionary **dict, struct mpv_global *global,
|
|||
talloc_free(temp);
|
||||
}
|
||||
|
||||
// Escape http URLs with unescaped, invalid characters in them.
|
||||
// libavformat's http protocol does not do this, and a patch to add this
|
||||
// in a 100% safe case (spaces only) was rejected.
|
||||
static char *normalize_url(void *ta_parent, const char *filename)
|
||||
{
|
||||
bstr proto = mp_split_proto(bstr0(filename), NULL);
|
||||
for (int n = 0; http_like[n]; n++) {
|
||||
if (bstr_equals0(proto, http_like[n]))
|
||||
// Escape everything but reserved characters.
|
||||
// Also don't double-scape, so include '%'.
|
||||
return mp_url_escape(ta_parent, filename, ":/?#[]@!$&'()*+,;=%");
|
||||
}
|
||||
return (char *)filename;
|
||||
}
|
||||
|
||||
static int open_f(stream_t *stream)
|
||||
{
|
||||
struct MPOpts *opts = stream->opts;
|
||||
|
@ -238,6 +252,8 @@ static int open_f(stream_t *stream)
|
|||
.opaque = stream,
|
||||
};
|
||||
|
||||
filename = normalize_url(stream, filename);
|
||||
|
||||
int err = avio_open2(&avio, filename, flags, &cb, &dict);
|
||||
if (err < 0) {
|
||||
if (err == AVERROR_PROTOCOL_NOT_FOUND)
|
||||
|
@ -335,6 +351,9 @@ done:
|
|||
return res;
|
||||
}
|
||||
|
||||
static const char *const http_like[] =
|
||||
{"http", "https", "mmsh", "mmshttp", "httproxy", NULL};
|
||||
|
||||
const stream_info_t stream_info_ffmpeg = {
|
||||
.name = "ffmpeg",
|
||||
.open = open_f,
|
||||
|
|
Loading…
Reference in New Issue