3 require_once('HTMLPurifier/Config.php');
4 require_once('HTMLPurifier/StrategyHarness.php');
5 require_once('HTMLPurifier/Strategy/ValidateAttributes.php');
7 class HTMLPurifier_Strategy_ValidateAttributesTest
extends
8 HTMLPurifier_StrategyHarness
13 $this->obj
= new HTMLPurifier_Strategy_ValidateAttributes();
14 $this->config
= array('HTML.Doctype' => 'XHTML 1.0 Strict');
17 function testEmpty() {
18 $this->assertResult('');
23 '<div id="valid">Kill the ID.</div>',
24 '<div>Kill the ID.</div>'
27 $this->assertResult('<div id="valid">Preserve the ID.</div>', true,
28 array('HTML.EnableAttrID' => true));
31 '<div id="0invalid">Kill the ID.</div>',
32 '<div>Kill the ID.</div>',
33 array('HTML.EnableAttrID' => true)
36 // test id accumulator
38 '<div id="valid">Valid</div><div id="valid">Invalid</div>',
39 '<div id="valid">Valid</div><div>Invalid</div>',
40 array('HTML.EnableAttrID' => true)
44 '<span dir="up-to-down">Bad dir.</span>',
45 '<span>Bad dir.</span>'
48 // test attribute key case sensitivity
50 '<div ID="valid">Convert ID to lowercase.</div>',
51 '<div id="valid">Convert ID to lowercase.</div>',
52 array('HTML.EnableAttrID' => true)
55 // test simple attribute substitution
57 '<div id=" valid ">Trim whitespace.</div>',
58 '<div id="valid">Trim whitespace.</div>',
59 array('HTML.EnableAttrID' => true)
62 // test configuration id blacklist
64 '<div id="invalid">Invalid</div>',
67 'Attr.IDBlacklist' => array('invalid'),
68 'HTML.EnableAttrID' => true
72 // name rewritten as id
74 '<a name="foobar" />',
76 array('HTML.EnableAttrID' => true)
80 function testClasses() {
81 $this->assertResult('<div class="valid">Valid</div>');
84 '<div class="valid 0invalid">Keep valid.</div>',
85 '<div class="valid">Keep valid.</div>'
89 function testTitle() {
91 '<acronym title="PHP: Hypertext Preprocessor">PHP</acronym>'
97 '<span lang="fr">La soupe.</span>',
98 '<span lang="fr" xml:lang="fr">La soupe.</span>'
101 // test only xml:lang for XHTML 1.1
103 '<b lang="en">asdf</b>',
104 '<b xml:lang="en">asdf</b>', array('HTML.Doctype' => 'XHTML 1.1')
108 function testAlign() {
111 '<h1 align="center">Centered Headline</h1>',
112 '<h1 style="text-align:center;">Centered Headline</h1>'
115 '<h1 align="right">Right-aligned Headline</h1>',
116 '<h1 style="text-align:right;">Right-aligned Headline</h1>'
119 '<h1 align="left">Left-aligned Headline</h1>',
120 '<h1 style="text-align:left;">Left-aligned Headline</h1>'
123 '<p align="justify">Justified Paragraph</p>',
124 '<p style="text-align:justify;">Justified Paragraph</p>'
127 '<h1 align="invalid">Invalid Headline</h1>',
128 '<h1>Invalid Headline</h1>'
133 function testTable() {
135 '<table frame="above" rules="rows" summary="A test table" border="2" cellpadding="5%" cellspacing="3" width="100%">
136 <col align="right" width="4*" />
137 <col charoff="5" align="char" width="*" />
139 <th abbr="name">Fiddly name</th>
140 <th abbr="price">Super-duper-price</th>
143 <td abbr="carrot">Carrot Humungous</td>
147 <td colspan="2">Taken off the market</td>
152 // test col.span is non-zero
159 '<td width="5%" height="10" /><th width="10" height="5%" /><hr width="10" height="10" />',
160 '<td style="width:5%;height:10px;" /><th style="width:10px;height:5%;" /><hr style="width:10px;" />'
162 // td boolean transformation
165 '<td style="white-space:nowrap;" />'
168 // caption align transformation
170 '<caption align="left" />',
171 '<caption style="text-align:left;" />'
174 '<caption align="right" />',
175 '<caption style="text-align:right;" />'
178 '<caption align="top" />',
179 '<caption style="caption-side:top;" />'
182 '<caption align="bottom" />',
183 '<caption style="caption-side:bottom;" />'
186 '<caption align="nonsense" />',
190 // align transformation
192 '<table align="left" />',
193 '<table style="float:left;" />'
196 '<table align="center" />',
197 '<table style="margin-left:auto;margin-right:auto;" />'
200 '<table align="right" />',
201 '<table style="float:right;" />'
204 '<table align="top" />',
210 $this->assertResult('<a href="http://www.google.com/">Google</a>');
214 '<a href="javascript:badstuff();">Google</a>',
222 '<img src="" alt="Invalid image" />',
223 array('Core.RemoveInvalidImg' => false)
227 '<img src="foobar.jpg" />',
228 '<img src="foobar.jpg" alt="foobar.jpg" />'
232 '<img alt="pretty picture" />',
233 '<img alt="pretty picture" src="" />',
234 array('Core.RemoveInvalidImg' => false)
236 // mailto in image is not allowed
238 '<img src="mailto:foo@example.com" />',
239 '<img alt="mailto:foo@example.com" src="" />',
240 array('Core.RemoveInvalidImg' => false)
242 // align transformation
244 '<img src="foobar.jpg" alt="foobar" align="left" />',
245 '<img src="foobar.jpg" alt="foobar" style="float:left;" />'
248 '<img src="foobar.jpg" alt="foobar" align="right" />',
249 '<img src="foobar.jpg" alt="foobar" style="float:right;" />'
252 '<img src="foobar.jpg" alt="foobar" align="bottom" />',
253 '<img src="foobar.jpg" alt="foobar" style="vertical-align:baseline;" />'
256 '<img src="foobar.jpg" alt="foobar" align="middle" />',
257 '<img src="foobar.jpg" alt="foobar" style="vertical-align:middle;" />'
260 '<img src="foobar.jpg" alt="foobar" align="top" />',
261 '<img src="foobar.jpg" alt="foobar" style="vertical-align:top;" />'
264 '<img src="foobar.jpg" alt="foobar" align="outerspace" />',
265 '<img src="foobar.jpg" alt="foobar" />'
271 // test required attributes for bdo
273 '<bdo>Go left.</bdo>',
274 '<bdo dir="ltr">Go left.</bdo>'
278 '<bdo dir="blahblah">Invalid value!</bdo>',
279 '<bdo dir="ltr">Invalid value!</bdo>'
284 // see testBdo, behavior is subtly different
286 '<span dir="blahblah">Invalid value!</span>',
287 '<span>Invalid value!</span>'
291 function testLinks() {
294 '<a href="foo" rel="nofollow" />',
296 array('Attr.AllowedRel' => 'nofollow')
300 '<a href="foo" target="_top" />',
302 array('Attr.AllowedFrameTargets' => '_top',
303 'HTML.Doctype' => 'XHTML 1.0 Transitional')
306 '<a href="foo" target="_top" />',
310 '<a href="foo" target="_top" />',
312 array('Attr.AllowedFrameTargets' => '_top', 'HTML.Strict' => true)
316 function testBorder() {
319 '<img src="foo" alt="foo" hspace="1" vspace="3" />',
320 '<img src="foo" alt="foo" style="margin-top:3px;margin-bottom:3px;margin-left:1px;margin-right:1px;" />',
321 array('Attr.AllowedRel' => 'nofollow')
328 '<hr style="height:3px;" />'
332 '<hr style="color:#808080;background-color:#808080;border:0;" />'
334 // align transformation
336 '<hr align="left" />',
337 '<hr style="margin-left:0;margin-right:auto;text-align:left;" />'
340 '<hr align="center" />',
341 '<hr style="margin-left:auto;margin-right:auto;text-align:center;" />'
344 '<hr align="right" />',
345 '<hr style="margin-left:auto;margin-right:0;text-align:right;" />'
348 '<hr align="bottom" />',
354 // br clear transformation
356 '<br clear="left" />',
357 '<br style="clear:left;" />'
360 '<br clear="right" />',
361 '<br style="clear:right;" />'
363 $this->assertResult( // test both?
364 '<br clear="all" />',
365 '<br style="clear:both;" />'
368 '<br clear="none" />',
369 '<br style="clear:none;" />'
372 '<br clear="foo" />',
377 function testListTypeTransform() {
380 '<ul type="disc" />',
381 '<ul style="list-style-type:disc;" />'
384 '<ul type="square" />',
385 '<ul style="list-style-type:square;" />'
388 '<ul type="circle" />',
389 '<ul style="list-style-type:circle;" />'
391 $this->assertResult( // case insensitive
392 '<ul type="CIRCLE" />',
393 '<ul style="list-style-type:circle;" />'
402 '<ol style="list-style-type:decimal;" />'
406 '<ol style="list-style-type:lower-roman;" />'
410 '<ol style="list-style-type:upper-roman;" />'
414 '<ol style="list-style-type:lower-alpha;" />'
418 '<ol style="list-style-type:upper-alpha;" />'
421 '<ol type="disc" />',
426 '<li type="circle" />',
427 '<li style="list-style-type:circle;" />'
431 '<li style="list-style-type:upper-alpha;" />'
433 $this->assertResult( // case sensitive
434 '<li type="CIRCLE" />',