diff --git a/lib/text/vtt_text_parser.js b/lib/text/vtt_text_parser.js index 1c2604a4c3..04dc734c0e 100644 --- a/lib/text/vtt_text_parser.js +++ b/lib/text/vtt_text_parser.js @@ -366,7 +366,8 @@ shaka.text.VttTextParser = class { end += timeOffset; // Get the payload. - const payload = text.slice(1).join('\n').trim(); + const payload = VttTextParser.htmlUnescape_( + text.slice(1).join('\n').trim()); let cue = null; if (styles.has('global')) { @@ -843,6 +844,39 @@ shaka.text.VttTextParser = class { return (milliseconds / 1000) + seconds + (minutes * 60) + (hours * 3600); } + + /** + * This method converts the HTML entities &, <, >, ", and + * ' in string to their corresponding characters. + * + * @param {!string} input + * @return {string} + * @private + */ + static htmlUnescape_(input) { + // Used to map HTML entities to characters. + const htmlUnescapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + ''': '\'', + }; + + // Used to match HTML entities and HTML characters. + const reEscapedHtml = /&(?:amp|lt|gt|quot|#(0+)?39);/g; + const reHasEscapedHtml = RegExp(reEscapedHtml.source); + // This check is an optimization, since replace always makes a copy + if (input && reHasEscapedHtml.test(input)) { + return input.replace(reEscapedHtml, (entity) => { + // The only thing that might not match the dictionary above is the + // single quote, which can be matched by many strings in the regex, but + // only has a single entry in the dictionary. + return htmlUnescapes[entity] || '\''; + }); + } + return input || ''; + } }; /** diff --git a/test/text/vtt_text_parser_unit.js b/test/text/vtt_text_parser_unit.js index 7f7d052bbc..56c5cc389a 100644 --- a/test/text/vtt_text_parser_unit.js +++ b/test/text/vtt_text_parser_unit.js @@ -849,6 +849,17 @@ describe('VttTextParser', () => { {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}); }); + it('support escaped html payload', () => { + verifyHelper( + [ + {startTime: 20.1, endTime: 40.505, payload: '"Test & 1"'}, + ], + 'WEBVTT\n\n' + + '00:00:20.100 --> 00:00:40.505\n' + + '"Test & 1"', + {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}); + }); + it('supports specific style blocks', () => { verifyHelper( [