summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 a15aecad11..3aa6bed270 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)) {
@@ -223,12 +244,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);