Skip to content

Commit bea71e1

Browse files
authored
Fix validation of audio and video content, add track element
1 parent 22a7435 commit bea71e1

File tree

3 files changed

+122
-6
lines changed

3 files changed

+122
-6
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
class HTMLPurifier_ChildDef_Media extends HTMLPurifier_ChildDef
4+
{
5+
public $type = 'media';
6+
7+
public $elements = array(
8+
'source' => true,
9+
'track' => true,
10+
);
11+
12+
protected $allowedElements;
13+
14+
/**
15+
* @param HTMLPurifier_Config $config
16+
* @return array
17+
*/
18+
public function getAllowedElements($config)
19+
{
20+
if (null === $this->allowedElements) {
21+
// Add Flow content to allowed elements to prevent MakeWellFormed
22+
// strategy moving them outside details element
23+
$def = $config->getHTMLDefinition();
24+
25+
$this->allowedElements = array_merge(
26+
$def->info_content_sets['Flow'],
27+
$this->elements
28+
);
29+
unset(
30+
$this->allowedElements['audio'],
31+
$this->allowedElements['video']
32+
);
33+
}
34+
return $this->allowedElements;
35+
}
36+
37+
/**
38+
* @param array $children
39+
* @param HTMLPurifier_Config $config
40+
* @param HTMLPurifier_Context $context
41+
* @return array
42+
*/
43+
public function validateChildren($children, $config, $context)
44+
{
45+
// Content model:
46+
// If the element has a src attribute: zero or more track elements,
47+
// then transparent, but with no media element descendants.
48+
// If the element does not have a src attribute: zero or more source
49+
// elements, then zero or more track elements, then transparent, but
50+
// with no media element descendants.
51+
52+
$allowSource = isset($config->getHTMLDefinition()->info['source']);
53+
$allowTrack = isset($config->getHTMLDefinition()->info['track']);
54+
55+
$sources = array();
56+
$tracks = array();
57+
$content = array();
58+
59+
foreach ($children as $node) {
60+
switch ($node->name) {
61+
case 'source':
62+
if ($allowSource) {
63+
$sources[] = $node;
64+
}
65+
break;
66+
67+
case 'track':
68+
if ($allowTrack) {
69+
$tracks[] = $node;
70+
}
71+
break;
72+
73+
default:
74+
$content[] = $node;
75+
break;
76+
}
77+
}
78+
79+
$currentNode = $context->get('CurrentNode');
80+
$hasSrcAttr = $currentNode instanceof HTMLPurifier_Node_Element && isset($currentNode->attr['src']);
81+
82+
if ($hasSrcAttr) {
83+
$result = array_merge($tracks, $content);
84+
} else {
85+
$result = array_merge($sources, $tracks, $content);
86+
}
87+
88+
if (empty($result) && !$hasSrcAttr) {
89+
return false;
90+
}
91+
92+
return $result;
93+
}
94+
}

library/HTMLPurifier/HTML5Definition.php

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ public static function setup(HTMLPurifier_HTMLDefinition $def)
3131
$def->addElement('figure', 'Block', 'Flow', 'Common');
3232
$def->addElement('figcaption', 'Inline', 'Flow', 'Common');
3333

34-
// http://developers.whatwg.org/the-video-element.html#the-video-element
35-
$def->addElement('video', 'Block', 'Flow', 'Common', array(
34+
$mediaContent = new HTMLPurifier_ChildDef_Media();
35+
36+
// https://html.spec.whatwg.org/dev/media.html#the-video-element
37+
$def->addElement('video', 'Block', $mediaContent, 'Common', array(
3638
'controls' => 'Bool',
3739
'height' => 'Length',
3840
'poster' => 'URI',
@@ -41,22 +43,31 @@ public static function setup(HTMLPurifier_HTMLDefinition $def)
4143
'width' => 'Length',
4244
));
4345

44-
// http://developers.whatwg.org/the-video-element.html#the-audio-element
45-
$def->addElement('audio', 'Block', 'Flow', 'Common', array(
46+
// https://html.spec.whatwg.org/dev/media.html#the-audio-element
47+
$def->addElement('audio', 'Block', $mediaContent, 'Common', array(
4648
'controls' => 'Bool',
4749
'preload' => 'Enum#auto,metadata,none',
4850
'src' => 'URI',
4951
));
5052

5153
// https://html.spec.whatwg.org/dev/embedded-content.html#the-source-element
52-
$def->addElement('source', 'Block', 'Empty', 'Common', array(
54+
$def->addElement('source', false, 'Empty', 'Common', array(
5355
'media' => 'Text',
5456
'sizes' => 'Text',
5557
'src' => 'URI',
5658
'srcset' => 'Text',
5759
'type' => 'Text',
5860
));
5961

62+
// https://html.spec.whatwg.org/dev/media.html#the-track-element
63+
$def->addElement('track', false, 'Empty', 'Common', array(
64+
'kind' => 'Enum#captions,chapters,descriptions,metadata,subtitles',
65+
'src' => 'URI',
66+
'srclang' => 'Text',
67+
'label' => 'Text',
68+
'default' => 'Bool',
69+
));
70+
6071
// https://html.spec.whatwg.org/dev/embedded-content.html#the-picture-element
6172
$def->addElement('picture', 'Block', new HTMLPurifier_ChildDef_Picture(), 'Common');
6273

tests/HTMLPurifier/HTML5DefinitionTest.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,11 @@ public function audioInput()
6262
array('<audio controls><source src="audio.ogg" type="audio/ogg"></audio>'),
6363
array('<audio controls src="audio.ogg"></audio>'),
6464
array('<audio controls><source src="audio.ogg" type="audio/ogg">Your browser does not support audio</audio>'),
65-
array('<audio controls src="audio.ogg">Your browser does not support audio</audio>'),
65+
array('<audio controls><source src="audio.ogg" type="audio/ogg"><track kind="subtitles" src="subtitles.vtt">Your browser does not support audio</audio>'),
66+
array('<audio controls><track kind="subtitles" src="subtitles.vtt">Your browser does not support audio</audio>'),
67+
array('<audio src="audio.ogg">Your browser does not support audio</audio>'),
68+
array('<audio src="audio.ogg"><p>Your browser does not support audio</p></audio>'),
69+
array('<audio src="audio.ogg"><track kind="subtitles" src="subtitles.vtt"></audio>'),
6670
);
6771
}
6872

@@ -83,6 +87,13 @@ public function videoInput()
8387
array('<video width="400" height="400" poster="poster.png" src="video.mp4"></video>'),
8488
array('<video width="400" height="400" poster="poster.png"><source src="video.mp4" type="video/mp4">Your browser does not support video</video>'),
8589
array('<video width="400" height="400" poster="poster.png" src="video.mp4">Your browser does not support video</video>'),
90+
array('<video src="video.mp4"></video>'),
91+
array('<video src="video.mp4">Your browser does not support video</video>'),
92+
array('<video src="video.mp4"><p>Your browser does not support video</p></video>'),
93+
array('<video src="video.mp4"><track kind="subtitles" src="subtitles.vtt"></video>'),
94+
array('<video><source src="video.mp4" type="video/mp4"></video>'),
95+
array('<video><track kind="subtitles" src="subtitles.vtt"></video>'),
96+
array('<video><source src="video.mp4" type="video/mp4"><track kind="subtitles" src="subtitles.vtt"></video>'),
8697
);
8798
}
8899

0 commit comments

Comments
 (0)