summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-12-05 23:50:56 +0100
committerDiogo Franco (Kovensky) <diogomfranco@gmail.com>2015-01-25 17:00:10 +0900
commitce5f0f1a7ad00b2242277b757b3c6d9e5d595998 (patch)
tree97a2788dee848cae0d203c1438744fcaebb0a7b1
parente02146b0c0c45075d8bdbc60ce4b2e0a557aec33 (diff)
downloadmpv-ce5f0f1a7ad00b2242277b757b3c6d9e5d595998.tar.bz2
mpv-ce5f0f1a7ad00b2242277b757b3c6d9e5d595998.tar.xz
demux_playlist: detect headerless m3u files by extension
m3u files are normally just text files with a list of filenames. Nothing actually mandates that there is a header. Until now, we've rejected such files, because there's absolutely no way to detect them. If nothing else claims the file, the extension is ".m3u", and if the contents of the file look like text, then load it as m3u playlist. The text heuristic is pretty cheap, but at least it should prevent trying to load binary data as playlist. (Which would "work", but result in a catastrophic user experience.) Due to the text heuristic, UTF-16/32 files will be rejected (unless they have a header), but I don't care.
-rw-r--r--demux/demux_playlist.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/demux/demux_playlist.c b/demux/demux_playlist.c
index d229461de9..c2505d672a 100644
--- a/demux/demux_playlist.c
+++ b/demux/demux_playlist.c
@@ -47,6 +47,8 @@ struct pl_parser {
bool error;
bool probing;
bool force;
+ enum demux_check check_level;
+ struct stream *real_stream;
};
static char *pl_get_line0(struct pl_parser *p)
@@ -79,11 +81,30 @@ static bool pl_eof(struct pl_parser *p)
return p->error || p->s->eof;
}
+static bool maybe_text(bstr d)
+{
+ for (int n = 0; n < d.len; n++) {
+ unsigned char c = d.start[n];
+ if (c < 32 && c != '\n' && c != '\r' && c != '\t')
+ return false;
+ }
+ return true;
+}
+
static int parse_m3u(struct pl_parser *p)
{
bstr line = bstr_strip(pl_get_line(p));
- if (p->probing && !bstr_equals0(line, "#EXTM3U"))
+ if (p->probing && !bstr_equals0(line, "#EXTM3U")) {
+ // Last resort: if the file extension is m3u, it might be headerless.
+ if (p->check_level == DEMUX_CHECK_UNSAFE) {
+ char *ext = mp_splitext(p->real_stream->url, NULL);
+ bstr data = stream_peek(p->real_stream, PROBE_SIZE);
+ if (ext && strcmp(ext, "m3u") && data.len > 10 && maybe_text(data))
+ goto ok;
+ }
return -1;
+ }
+ok:
if (p->probing)
return 0;
while (line.len || !pl_eof(p)) {
@@ -226,12 +247,14 @@ static int open_file(struct demuxer *demuxer, enum demux_check check)
struct pl_parser *p = talloc_zero(NULL, struct pl_parser);
p->log = demuxer->log;
p->pl = talloc_zero(p, struct playlist);
+ p->real_stream = demuxer->stream;
bstr probe_buf = stream_peek(demuxer->stream, PROBE_SIZE);
p->s = open_memory_stream(probe_buf.start, probe_buf.len);
p->s->mime_type = demuxer->stream->mime_type;
p->utf16 = stream_skip_bom(p->s);
p->force = force;
+ p->check_level = check;
p->probing = true;
const struct pl_format *fmt = probe_pl(p);
free_stream(p->s);