Skip to content

Commit

Permalink
fix: non standard tag match (#156)
Browse files Browse the repository at this point in the history
Prevent non-standard tags from being erroneously matched as standard tags by enforcing the colon tag delimiter

BREAKING CHANGE: Missing colon (:) tag delimiters are no longer supported
Closes #22
  • Loading branch information
Essk authored Sep 27, 2022
1 parent 6fe98ee commit 8d56f30
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 49 deletions.
41 changes: 23 additions & 18 deletions src/parse-stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,14 @@ const attributeSeparator = function() {
* @param {string} attributes the attribute line to parse
*/
const parseAttributes = function(attributes) {
const result = {};

if (!attributes) {
return result;
}

// split the string using attributes as the separator
const attrs = attributes.split(attributeSeparator());
const result = {};
let i = attrs.length;
let attr;

Expand Down Expand Up @@ -164,7 +169,7 @@ export default class ParseStream extends Stream {
});
return;
}
match = (/^#EXTINF:?([0-9\.]*)?,?(.*)?$/).exec(newLine);
match = (/^#EXTINF:([0-9\.]*)?,?(.*)?$/).exec(newLine);
if (match) {
event = {
type: 'tag',
Expand All @@ -179,7 +184,7 @@ export default class ParseStream extends Stream {
this.trigger('data', event);
return;
}
match = (/^#EXT-X-TARGETDURATION:?([0-9.]*)?/).exec(newLine);
match = (/^#EXT-X-TARGETDURATION:([0-9.]*)?/).exec(newLine);
if (match) {
event = {
type: 'tag',
Expand All @@ -191,7 +196,7 @@ export default class ParseStream extends Stream {
this.trigger('data', event);
return;
}
match = (/^#EXT-X-VERSION:?([0-9.]*)?/).exec(newLine);
match = (/^#EXT-X-VERSION:([0-9.]*)?/).exec(newLine);
if (match) {
event = {
type: 'tag',
Expand All @@ -203,7 +208,7 @@ export default class ParseStream extends Stream {
this.trigger('data', event);
return;
}
match = (/^#EXT-X-MEDIA-SEQUENCE:?(\-?[0-9.]*)?/).exec(newLine);
match = (/^#EXT-X-MEDIA-SEQUENCE:(\-?[0-9.]*)?/).exec(newLine);
if (match) {
event = {
type: 'tag',
Expand All @@ -215,7 +220,7 @@ export default class ParseStream extends Stream {
this.trigger('data', event);
return;
}
match = (/^#EXT-X-DISCONTINUITY-SEQUENCE:?(\-?[0-9.]*)?/).exec(newLine);
match = (/^#EXT-X-DISCONTINUITY-SEQUENCE:(\-?[0-9.]*)?/).exec(newLine);
if (match) {
event = {
type: 'tag',
Expand All @@ -227,7 +232,7 @@ export default class ParseStream extends Stream {
this.trigger('data', event);
return;
}
match = (/^#EXT-X-PLAYLIST-TYPE:?(.*)?$/).exec(newLine);
match = (/^#EXT-X-PLAYLIST-TYPE:(.*)?$/).exec(newLine);
if (match) {
event = {
type: 'tag',
Expand All @@ -239,7 +244,7 @@ export default class ParseStream extends Stream {
this.trigger('data', event);
return;
}
match = (/^#EXT-X-BYTERANGE:?(.*)?$/).exec(newLine);
match = (/^#EXT-X-BYTERANGE:(.*)?$/).exec(newLine);
if (match) {
event = Object.assign(parseByterange(match[1]), {
type: 'tag',
Expand All @@ -248,7 +253,7 @@ export default class ParseStream extends Stream {
this.trigger('data', event);
return;
}
match = (/^#EXT-X-ALLOW-CACHE:?(YES|NO)?/).exec(newLine);
match = (/^#EXT-X-ALLOW-CACHE:(YES|NO)?/).exec(newLine);
if (match) {
event = {
type: 'tag',
Expand All @@ -260,7 +265,7 @@ export default class ParseStream extends Stream {
this.trigger('data', event);
return;
}
match = (/^#EXT-X-MAP:?(.*)$/).exec(newLine);
match = (/^#EXT-X-MAP:(.*)$/).exec(newLine);
if (match) {
event = {
type: 'tag',
Expand All @@ -281,7 +286,7 @@ export default class ParseStream extends Stream {
this.trigger('data', event);
return;
}
match = (/^#EXT-X-STREAM-INF:?(.*)$/).exec(newLine);
match = (/^#EXT-X-STREAM-INF:(.*)$/).exec(newLine);
if (match) {
event = {
type: 'tag',
Expand Down Expand Up @@ -315,7 +320,7 @@ export default class ParseStream extends Stream {
this.trigger('data', event);
return;
}
match = (/^#EXT-X-MEDIA:?(.*)$/).exec(newLine);
match = (/^#EXT-X-MEDIA:(.*)$/).exec(newLine);
if (match) {
event = {
type: 'tag',
Expand Down Expand Up @@ -343,7 +348,7 @@ export default class ParseStream extends Stream {
});
return;
}
match = (/^#EXT-X-PROGRAM-DATE-TIME:?(.*)$/).exec(newLine);
match = (/^#EXT-X-PROGRAM-DATE-TIME:(.*)$/).exec(newLine);
if (match) {
event = {
type: 'tag',
Expand All @@ -356,7 +361,7 @@ export default class ParseStream extends Stream {
this.trigger('data', event);
return;
}
match = (/^#EXT-X-KEY:?(.*)$/).exec(newLine);
match = (/^#EXT-X-KEY:(.*)$/).exec(newLine);
if (match) {
event = {
type: 'tag',
Expand All @@ -381,7 +386,7 @@ export default class ParseStream extends Stream {
this.trigger('data', event);
return;
}
match = (/^#EXT-X-START:?(.*)$/).exec(newLine);
match = (/^#EXT-X-START:(.*)$/).exec(newLine);
if (match) {
event = {
type: 'tag',
Expand All @@ -396,7 +401,7 @@ export default class ParseStream extends Stream {
this.trigger('data', event);
return;
}
match = (/^#EXT-X-CUE-OUT-CONT:?(.*)?$/).exec(newLine);
match = (/^#EXT-X-CUE-OUT-CONT:(.*)?$/).exec(newLine);
if (match) {
event = {
type: 'tag',
Expand All @@ -410,7 +415,7 @@ export default class ParseStream extends Stream {
this.trigger('data', event);
return;
}
match = (/^#EXT-X-CUE-OUT:?(.*)?$/).exec(newLine);
match = (/^#EXT-X-CUE-OUT:(.*)?$/).exec(newLine);
if (match) {
event = {
type: 'tag',
Expand All @@ -424,7 +429,7 @@ export default class ParseStream extends Stream {
this.trigger('data', event);
return;
}
match = (/^#EXT-X-CUE-IN:?(.*)?$/).exec(newLine);
match = (/^#EXT-X-CUE-IN:(.*)?$/).exec(newLine);
if (match) {
event = {
type: 'tag',
Expand Down
22 changes: 6 additions & 16 deletions test/parse-stream.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ QUnit.test('parses #EXTM3U tags', function(assert) {

// #EXTINF
QUnit.test('parses minimal #EXTINF tags', function(assert) {
const manifest = '#EXTINF\n';
const manifest = '#EXTINF:\n';
let element;

this.parseStream.on('data', function(elem) {
Expand Down Expand Up @@ -319,7 +319,7 @@ QUnit.test('parses #EXTINF tags with carriage returns', function(assert) {

// #EXT-X-TARGETDURATION
QUnit.test('parses minimal #EXT-X-TARGETDURATION tags', function(assert) {
const manifest = '#EXT-X-TARGETDURATION\n';
const manifest = '#EXT-X-TARGETDURATION:\n';
let element;

this.parseStream.on('data', function(elem) {
Expand Down Expand Up @@ -379,7 +379,7 @@ QUnit.test('parses #EXT-X-VERSION with a version', function(assert) {

// #EXT-X-MEDIA-SEQUENCE
QUnit.test('parses minimal #EXT-X-MEDIA-SEQUENCE tags', function(assert) {
const manifest = '#EXT-X-MEDIA-SEQUENCE\n';
const manifest = '#EXT-X-MEDIA-SEQUENCE:\n';
let element;

this.parseStream.on('data', function(elem) {
Expand Down Expand Up @@ -453,7 +453,7 @@ QUnit.test('parses #EXT-X-PLAYLIST-TYPE with mutability info', function(assert)

// #EXT-X-BYTERANGE
QUnit.test('parses minimal #EXT-X-BYTERANGE tags', function(assert) {
const manifest = '#EXT-X-BYTERANGE\n';
const manifest = '#EXT-X-BYTERANGE:\n';
let element;

this.parseStream.on('data', function(elem) {
Expand Down Expand Up @@ -589,7 +589,7 @@ QUnit.test('parses #EXT-X-MAP tags with arbitrary attributes', function(assert)
});
// #EXT-X-STREAM-INF
QUnit.test('parses minimal #EXT-X-STREAM-INF tags', function(assert) {
const manifest = '#EXT-X-STREAM-INF\n';
const manifest = '#EXT-X-STREAM-INF:\n';
let element;

this.parseStream.on('data', function(elem) {
Expand All @@ -604,7 +604,7 @@ QUnit.test('parses minimal #EXT-X-STREAM-INF tags', function(assert) {
});
// #EXT-X-PROGRAM-DATE-TIME
QUnit.test('parses minimal EXT-X-PROGRAM-DATE-TIME tags', function(assert) {
const manifest = '#EXT-X-PROGRAM-DATE-TIME\n';
const manifest = '#EXT-X-PROGRAM-DATE-TIME:\n';
let element;

this.parseStream.on('data', function(elem) {
Expand Down Expand Up @@ -809,16 +809,6 @@ QUnit.test('parses lightly-broken #EXT-X-KEY tags', function(assert) {
'parsed a single-quoted uri'
);

element = null;
manifest = '#EXT-X-KEYURI="https://example.com/key",METHOD=AES-128\n';
this.lineStream.push(manifest);
assert.strictEqual(element.tagType, 'key', 'parsed the tag type');
assert.strictEqual(
element.attributes.URI,
'https://example.com/key',
'inferred a colon after the tag type'
);

element = null;
manifest = '#EXT-X-KEY: URI = "https://example.com/key",METHOD=AES-128\n';
this.lineStream.push(manifest);
Expand Down
18 changes: 3 additions & 15 deletions test/parser.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,10 @@ QUnit.module('m3u8s', function(hooks) {
'#EXT-X-CUE-OUT:10',
'#EXTINF:5,',
'ex2.ts',
'#EXT-X-CUE-OUT15',
'#EXT-UKNOWN-TAG',
'#EXTINF:5,',
'ex3.ts',
'#EXT-X-CUE-OUT',
'#EXT-X-CUE-OUT:',
'#EXTINF:5,',
'ex3.ts',
'#EXT-X-ENDLIST'
Expand All @@ -122,7 +121,6 @@ QUnit.module('m3u8s', function(hooks) {
this.parser.end();

assert.equal(this.parser.manifest.segments[1].cueOut, '10', 'parser attached cue out tag');
assert.equal(this.parser.manifest.segments[2].cueOut, '15', 'cue out without : seperator');
assert.equal(this.parser.manifest.segments[3].cueOut, '', 'cue out without data');
});

Expand All @@ -135,11 +133,10 @@ QUnit.module('m3u8s', function(hooks) {
'#EXT-X-CUE-OUT-CONT:10/60',
'#EXTINF:5,',
'ex2.ts',
'#EXT-X-CUE-OUT-CONT15/30',
'#EXT-UKNOWN-TAG',
'#EXTINF:5,',
'ex3.ts',
'#EXT-X-CUE-OUT-CONT',
'#EXT-X-CUE-OUT-CONT:',
'#EXTINF:5,',
'ex3.ts',
'#EXT-X-ENDLIST'
Expand All @@ -152,10 +149,6 @@ QUnit.module('m3u8s', function(hooks) {
this.parser.manifest.segments[1].cueOutCont, '10/60',
'parser attached cue out cont tag'
);
assert.equal(
this.parser.manifest.segments[2].cueOutCont, '15/30',
'cue out cont without : seperator'
);
assert.equal(this.parser.manifest.segments[3].cueOutCont, '', 'cue out cont without data');
});

Expand All @@ -165,14 +158,13 @@ QUnit.module('m3u8s', function(hooks) {
'#EXTINF:5,',
'#COMMENT',
'ex1.ts',
'#EXT-X-CUE-IN',
'#EXT-X-CUE-IN:',
'#EXTINF:5,',
'ex2.ts',
'#EXT-X-CUE-IN:15',
'#EXT-UKNOWN-TAG',
'#EXTINF:5,',
'ex3.ts',
'#EXT-X-CUE-IN=abc',
'#EXTINF:5,',
'ex3.ts',
'#EXT-X-ENDLIST'
Expand All @@ -183,10 +175,6 @@ QUnit.module('m3u8s', function(hooks) {

assert.equal(this.parser.manifest.segments[1].cueIn, '', 'parser attached cue in tag');
assert.equal(this.parser.manifest.segments[2].cueIn, '15', 'cue in with data');
assert.equal(
this.parser.manifest.segments[3].cueIn, '=abc',
'cue in without colon seperator'
);
});

QUnit.test('parses characteristics attribute', function(assert) {
Expand Down

0 comments on commit 8d56f30

Please sign in to comment.