diff --git a/docs/progress.html b/docs/progress.html index 83722e62..d3faab2d 100644 --- a/docs/progress.html +++ b/docs/progress.html @@ -80,7 +80,7 @@ thead th {text-align:left;padding:0.1em;background-color:#EEE;} DEL, INSLink to explanation why it changed hrefA- longdescIMG- -srcIMGRequired +srcIMGRequired @@ -90,14 +90,14 @@ thead th {text-align:left;padding:0.1em;background-color:#EEE;} TABLE HREquivalent style 'text-align' (IE tested) H1, H2, H3, H4, H5, H6, PEquivalent style 'text-align' -altIMGRequired, insert image filename if non-existant +altIMGRequired, insert image filename if src is present or default invalid image text bgcolorTABLEEquivalent style 'background-color' (IE tested) TREquivalent style 'background-color' (IE tested) TD, THEquivalent style 'background-color' borderIMGEquivalent style 'border-width', only applies when link present clearBRNear-equiv style 'clear', transform 'all' into 'both' compactDL, OL, ULBoolean, needs custom CSS class -dirBDORequired, insert ltr (or configuration value) if none +dirBDORequired, insert ltr (or configuration value) if none heightTD, THNear-equiv style 'height', needs px suffix if original was in pixels hspaceIMGNear-equiv styles 'margin-top' and 'margin-bottom', needs px suffix lang*Copy value to xml:lang @@ -106,7 +106,7 @@ thead th {text-align:left;padding:0.1em;background-color:#EEE;} noshadeHRBoolean, style 'border-style:solid;' nowrapTD, THBoolean, style 'white-space:nowrap;' (not compat with IE5) sizeHRNear-equiv 'width', needs px suffix if original was pixels -srcIMGRequired, insert blank or default img if not set +srcIMGRequired, insert blank or default img if not set startOLPoorly supported 'counter-reset', transform may not be desirable typeLIEquivalent style 'list-style-type', different allowed values though. (needs testing) OL @@ -168,7 +168,7 @@ thead th {text-align:left;padding:0.1em;background-color:#EEE;} decimal, lower-roman, upper-roman, lower-alpha and upper-alpha. See also CSS 3. Mostly IE lack of support. list-styleSHORTHAND -marginMULIPLE +marginMULTIPLE margin-*COMPOSITE(<length>, <percentage>, auto) paddingMULTIPLE diff --git a/library/HTMLPurifier/AttrTransform/BdoDir.php b/library/HTMLPurifier/AttrTransform/BdoDir.php new file mode 100644 index 00000000..513566e1 --- /dev/null +++ b/library/HTMLPurifier/AttrTransform/BdoDir.php @@ -0,0 +1,25 @@ +get('Attr', 'DefaultTextDir'); + return $attributes; + } + +} + +?> \ No newline at end of file diff --git a/library/HTMLPurifier/AttrTransform/ImgRequired.php b/library/HTMLPurifier/AttrTransform/ImgRequired.php new file mode 100644 index 00000000..7fff1c78 --- /dev/null +++ b/library/HTMLPurifier/AttrTransform/ImgRequired.php @@ -0,0 +1,47 @@ +get('Attr', 'DefaultInvalidImage'); + $src = false; + } + + if (!isset($attributes['alt'])) { + if ($src) { + $attributes['alt'] = basename($attributes['src']); + } else { + $attributes['alt'] = $config->get('Attr', 'DefaultInvalidImageAlt'); + } + } + + return $attributes; + + } + +} + +?> \ No newline at end of file diff --git a/library/HTMLPurifier/AttrTransform/Lang.php b/library/HTMLPurifier/AttrTransform/Lang.php index dbc5c3c6..62297ab3 100644 --- a/library/HTMLPurifier/AttrTransform/Lang.php +++ b/library/HTMLPurifier/AttrTransform/Lang.php @@ -2,10 +2,13 @@ require_once 'HTMLPurifier/AttrTransform.php'; +// this transformation may be done pre or post validation, but post is +// preferred, since invalid languages then will have been dropped. + class HTMLPurifier_AttrTransform_Lang extends HTMLPurifier_AttrTransform { - function transform($attr) { + function transform($attr, $config) { $lang = isset($attr['lang']) ? $attr['lang'] : false; $xml_lang = isset($attr['xml:lang']) ? $attr['xml:lang'] : false; diff --git a/library/HTMLPurifier/AttrTransform/TextAlign.php b/library/HTMLPurifier/AttrTransform/TextAlign.php index e97983d7..331132de 100644 --- a/library/HTMLPurifier/AttrTransform/TextAlign.php +++ b/library/HTMLPurifier/AttrTransform/TextAlign.php @@ -5,7 +5,7 @@ require_once 'HTMLPurifier/AttrTransform.php'; class HTMLPurifier_AttrTransform_TextAlign extends HTMLPurifier_AttrTransform { - function transform($attr) { + function transform($attr, $config) { if (!isset($attr['align'])) return $attr; diff --git a/library/HTMLPurifier/HTMLDefinition.php b/library/HTMLPurifier/HTMLDefinition.php index fe795246..cd6cab1c 100644 --- a/library/HTMLPurifier/HTMLDefinition.php +++ b/library/HTMLPurifier/HTMLDefinition.php @@ -15,6 +15,8 @@ require_once 'HTMLPurifier/AttrDef.php'; require_once 'HTMLPurifier/AttrTransform.php'; require_once 'HTMLPurifier/AttrTransform/Lang.php'; require_once 'HTMLPurifier/AttrTransform/TextAlign.php'; + require_once 'HTMLPurifier/AttrTransform/BdoDir.php'; + require_once 'HTMLPurifier/AttrTransform/ImgRequired.php'; require_once 'HTMLPurifier/ChildDef.php'; require_once 'HTMLPurifier/Generator.php'; require_once 'HTMLPurifier/Token.php'; @@ -56,7 +58,8 @@ class HTMLPurifier_HTMLDefinition var $info_tag_transform = array(); // used solely by HTMLPurifier_Strategy_ValidateAttributes - var $info_attr_transform = array(); + var $info_attr_transform_pre = array(); + var $info_attr_transform_post = array(); // WARNING! Prototype is not passed by reference, so in order to get // a copy of the real one, you'll have to destroy your copy and @@ -350,23 +353,31 @@ class HTMLPurifier_HTMLDefinition // or we can just create another info ////////////////////////////////////////////////////////////////////// - // info[]->attr_transform : attribute transformations in elements + // info[]->attr_transform_* : attribute transformations in elements + // pre is applied before any validation is done, post is done after - $transform = new HTMLPurifier_AttrTransform_TextAlign(); - $this->info['h1']->attr_transform[] = - $this->info['h2']->attr_transform[] = - $this->info['h3']->attr_transform[] = - $this->info['h4']->attr_transform[] = - $this->info['h5']->attr_transform[] = - $this->info['h6']->attr_transform[] = - $this->info['p'] ->attr_transform[] = $transform; + $this->info['h1']->attr_transform_pre[] = + $this->info['h2']->attr_transform_pre[] = + $this->info['h3']->attr_transform_pre[] = + $this->info['h4']->attr_transform_pre[] = + $this->info['h5']->attr_transform_pre[] = + $this->info['h6']->attr_transform_pre[] = + $this->info['p'] ->attr_transform_pre[] = + new HTMLPurifier_AttrTransform_TextAlign(); + + $this->info['bdo']->attr_transform_post[] = + new HTMLPurifier_AttrTransform_BdoDir(); + + $this->info['img']->attr_transform_post[] = + new HTMLPurifier_AttrTransform_ImgRequired(); ////////////////////////////////////////////////////////////////////// - // info_attr_transform : global attribute transformation that is + // info_attr_transform_* : global attribute transformation that is // unconditionally called. Good for transformations that have complex // start conditions + // pre is applied before any validation is done, post is done after - $this->info_attr_transform[] = new HTMLPurifier_AttrTransform_Lang(); + $this->info_attr_transform_post[] = new HTMLPurifier_AttrTransform_Lang(); } @@ -387,7 +398,8 @@ class HTMLPurifier_ElementDef { var $attr = array(); - var $attr_transform = array(); + var $attr_transform_pre = array(); + var $attr_transform_post = array(); var $auto_close = array(); var $child; var $type = 'unknown'; diff --git a/library/HTMLPurifier/Strategy/ValidateAttributes.php b/library/HTMLPurifier/Strategy/ValidateAttributes.php index 12cc892b..59b3a1ba 100644 --- a/library/HTMLPurifier/Strategy/ValidateAttributes.php +++ b/library/HTMLPurifier/Strategy/ValidateAttributes.php @@ -47,20 +47,20 @@ class HTMLPurifier_Strategy_ValidateAttributes extends HTMLPurifier_Strategy // copy out attributes for easy manipulation $attr = $token->attributes; - // do global transformations + // do global transformations (pre) // ex. to // DEFINITION CALL - foreach ($this->definition->info_attr_transform as $transform) { - $attr = $transform->transform($attr); + foreach ($this->definition->info_attr_transform_pre as $transform) { + $attr = $transform->transform($attr, $config); } - // do local transformations only applicable to this element + // do local transformations only applicable to this element (pre) // ex.

to

// DEFINITION CALL - foreach ($this->definition->info[$token->name]->attr_transform + foreach ($this->definition->info[$token->name]->attr_transform_pre as $transform ) { - $attr = $transform->transform($attr); + $attr = $transform->transform($attr, $config); } // create alias to this element's attribute definition array, see @@ -115,6 +115,14 @@ class HTMLPurifier_Strategy_ValidateAttributes extends HTMLPurifier_Strategy // others would prepend themselves). } + // post transforms + foreach ($this->definition->info_attr_transform_post as $transform) { + $attr = $transform->transform($attr, $config); + } + foreach ($this->definition->info[$token->name]->attr_transform_post as $transform) { + $attr = $transform->transform($attr, $config); + } + // commit changes // could interfere with flyweight implementation $tokens[$key]->attributes = $attr; diff --git a/tests/HTMLPurifier/AttrTransform/BdoDirTest.php b/tests/HTMLPurifier/AttrTransform/BdoDirTest.php new file mode 100644 index 00000000..0762359d --- /dev/null +++ b/tests/HTMLPurifier/AttrTransform/BdoDirTest.php @@ -0,0 +1,36 @@ +transform = new HTMLPurifier_AttrTransform_BdoDir(); + + $inputs = array(); + $expect = array(); + $config = array(); + + // add dir + $inputs[0] = array(); + $expect[0] = array('dir' => 'ltr'); + + // leave existing dir alone + $inputs[1] = array('dir' => 'rtl'); + $expect[1] = array('dir' => 'rtl'); + + $config_rtl = HTMLPurifier_Config::createDefault(); + $config_rtl->set('Attr', 'DefaultTextDir', 'rtl'); + $inputs[2] = array(); + $expect[2] = array('dir' => 'rtl'); + $config[2] = $config_rtl; + + $this->assertTransform($inputs, $expect, $config); + + } + +} + +?> \ No newline at end of file diff --git a/tests/HTMLPurifier/AttrTransform/ImgRequiredTest.php b/tests/HTMLPurifier/AttrTransform/ImgRequiredTest.php new file mode 100644 index 00000000..c410b29f --- /dev/null +++ b/tests/HTMLPurifier/AttrTransform/ImgRequiredTest.php @@ -0,0 +1,35 @@ +transform = new HTMLPurifier_AttrTransform_ImgRequired(); + + $inputs = $expect = $config = array(); + + $inputs[0] = array(); + $expect[0] = array('src' => '', 'alt' => 'Invalid image'); + + $inputs[1] = array(); + $expect[1] = array('src' => 'blank.png', 'alt' => 'Pawned!'); + $config[1] = HTMLPurifier_Config::createDefault(); + $config[1]->set('Attr', 'DefaultInvalidImage', 'blank.png'); + $config[1]->set('Attr', 'DefaultInvalidImageAlt', 'Pawned!'); + + $inputs[2] = array('src' => '/path/to/foobar.png'); + $expect[2] = array('src' => '/path/to/foobar.png', 'alt' => 'foobar.png'); + + $inputs[3] = array('alt' => 'intrigue'); + $expect[3] = array('src' => '', 'alt' => 'intrigue'); + + $this->assertTransform($inputs, $expect, $config); + + } + +} + +?> \ No newline at end of file diff --git a/tests/HTMLPurifier/AttrTransformHarness.php b/tests/HTMLPurifier/AttrTransformHarness.php index 138d9280..ceff33b7 100644 --- a/tests/HTMLPurifier/AttrTransformHarness.php +++ b/tests/HTMLPurifier/AttrTransformHarness.php @@ -5,14 +5,13 @@ class HTMLPurifier_AttrTransformHarness extends UnitTestCase var $transform; - function assertTransform($inputs, $expect) { + function assertTransform($inputs, $expect, $config = array()) { + $default_config = HTMLPurifier_Config::createDefault(); foreach ($inputs as $i => $input) { - $result = $this->transform->transform($input); - if ($expect[$i] === true) { - $this->assertEqual($input, $result, "Test $i: %s"); - } else { - $this->assertEqual($expect[$i], $result, "Test $i: %s"); - } + if (!isset($config[$i])) $config[$i] = $default_config; + $result = $this->transform->transform($input, $config[$i]); + if ($expect[$i] === true) $expect[$i] = $input; + $this->assertEqual($expect[$i], $result, "Test $i: %s"); } } diff --git a/tests/HTMLPurifier/Strategy/ValidateAttributesTest.php b/tests/HTMLPurifier/Strategy/ValidateAttributesTest.php index beb847dc..6e610fb7 100644 --- a/tests/HTMLPurifier/Strategy/ValidateAttributesTest.php +++ b/tests/HTMLPurifier/Strategy/ValidateAttributesTest.php @@ -12,6 +12,9 @@ class HTMLPurifier_Strategy_ValidateAttributesTest extends $strategy = new HTMLPurifier_Strategy_ValidateAttributes(); + // attribute order is VERY fragile, perhaps we should define + // an ordering scheme! + $inputs = array(); $expect = array(); $config = array(); @@ -68,8 +71,9 @@ class HTMLPurifier_Strategy_ValidateAttributesTest extends $expect[12] = '

Centered Headline

'; // test table - $inputs[13] = << + $inputs[13] = + +' @@ -83,8 +87,8 @@ class HTMLPurifier_Strategy_ValidateAttributesTest extends -
Taken off the market
-HTML; +'; + $expect[13] = $inputs[13]; // test URI @@ -95,6 +99,27 @@ HTML; $inputs[15] = 'Google'; $expect[15] = 'Google'; + // test required attributes for img + $inputs[16] = ''; + $expect[16] = 'Invalid image'; + + $inputs[17] = ''; + $expect[17] = 'foobar.jpg'; + + $inputs[18] = 'pretty picture'; + $expect[18] = 'pretty picture'; + + // test required attributes for bdo + $inputs[19] = 'Go left.'; + $expect[19] = 'Go left.'; + + $inputs[20] = 'Invalid value!'; + $expect[20] = 'Invalid value!'; + + // comparison check for test 20 + $inputs[21] = 'Invalid value!'; + $expect[21] = 'Invalid value!'; + $this->assertStrategyWorks($strategy, $inputs, $expect, $config); } diff --git a/tests/index.php b/tests/index.php index a7a66b2b..ae6566ef 100644 --- a/tests/index.php +++ b/tests/index.php @@ -74,6 +74,8 @@ $test_files[] = 'IDAccumulatorTest.php'; $test_files[] = 'TagTransformTest.php'; $test_files[] = 'AttrTransform/LangTest.php'; $test_files[] = 'AttrTransform/TextAlignTest.php'; +$test_files[] = 'AttrTransform/BdoDirTest.php'; +$test_files[] = 'AttrTransform/ImgRequiredTest.php'; $test_files[] = 'URISchemeRegistryTest.php'; $test_files[] = 'URISchemeTest.php';