diff --git a/NEWS b/NEWS index 9ef2fe26..3365bc70 100644 --- a/NEWS +++ b/NEWS @@ -10,9 +10,9 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier ========================== 1.4.0, unknown release date -(major feature release) +. Implemented AttrDef_CSSURI for url(http://google.com) style declarations -1.3.3, unknown release date, may be dropped +1.3.3, unknown release date, likely to be dropped ! Moved SLOW to docs/enduser-slow.html and added code examples 1.3.2, released 2006-12-25 diff --git a/library/HTMLPurifier/AttrDef/CSS.php b/library/HTMLPurifier/AttrDef/CSS.php index 404c7000..ca1b0224 100644 --- a/library/HTMLPurifier/AttrDef/CSS.php +++ b/library/HTMLPurifier/AttrDef/CSS.php @@ -20,6 +20,9 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef // we're going to break the spec and explode by semicolons. // This is because semicolon rarely appears in escaped form + // Doing this is generally flaky but fast + // IT MIGHT APPEAR IN URIs, see HTMLPurifier_AttrDef_CSSURI + // for details $declarations = explode(';', $css); $propvalues = array(); diff --git a/library/HTMLPurifier/AttrDef/CSSURI.php b/library/HTMLPurifier/AttrDef/CSSURI.php new file mode 100644 index 00000000..a92b6263 --- /dev/null +++ b/library/HTMLPurifier/AttrDef/CSSURI.php @@ -0,0 +1,58 @@ +HTMLPurifier_AttrDef_URI(true); // always embedded + } + + function validate($uri_string, $config, &$context) { + // parse the URI out of the string and then pass it onto + // the parent object + + $uri_string = $this->parseCDATA($uri_string); + if (strpos($uri_string, 'url(') !== 0) return false; + $uri_string = substr($uri_string, 4); + $new_length = strlen($uri_string) - 1; + if ($uri_string[$new_length] != ')') return false; + $uri = trim(substr($uri_string, 0, $new_length)); + + if (isset($uri[0]) && ($uri[0] == "'" || $uri[0] == '"')) { + $quote = $uri[0]; + $new_length = strlen($uri) - 1; + if ($uri[$new_length] !== $quote) return false; + $uri = substr($uri, 1, $new_length - 1); + } + + $keys = array( '(', ')', ',', ' ', '"', "'"); + $values = array('\\(', '\\)', '\\,', '\\ ', '\\"', "\\'"); + $uri = str_replace($values, $keys, $uri); + + $result = parent::validate($uri, $config, $context); + + if ($result === false) return false; + + // escape necessary characters according to CSS spec + // except for the comma, none of these should appear in the + // URI at all + $result = str_replace($keys, $values, $result); + + return "url($result)"; + + } + +} + +?> \ No newline at end of file diff --git a/tests/HTMLPurifier/AttrDef/CSSURITest.php b/tests/HTMLPurifier/AttrDef/CSSURITest.php new file mode 100644 index 00000000..1fe1a3dc --- /dev/null +++ b/tests/HTMLPurifier/AttrDef/CSSURITest.php @@ -0,0 +1,37 @@ +def = new HTMLPurifier_AttrDef_CSSURI(); + + $this->assertDef('', false); + + // we could be nice but we won't be + $this->assertDef('http://www.example.com/', false); + + // no quotes are used, since that's the most widely supported + // syntax + $this->assertDef('url(', false); + $this->assertDef('url()', true); + $result = "url(http://www.example.com/)"; + $this->assertDef('url(http://www.example.com/)', $result); + $this->assertDef('url("http://www.example.com/")', $result); + $this->assertDef("url('http://www.example.com/')", $result); + $this->assertDef( + ' url( "http://www.example.com/" ) ', $result); + + // escaping + $this->assertDef("url(http://www.example.com/foo,bar\))", + "url(http://www.example.com/foo\,bar\))"); + + } + +} + +?> \ No newline at end of file diff --git a/tests/index.php b/tests/index.php index 92c845fe..3b8b87b1 100644 --- a/tests/index.php +++ b/tests/index.php @@ -84,6 +84,7 @@ $test_files[] = 'AttrDef/FontTest.php'; $test_files[] = 'AttrDef/BorderTest.php'; $test_files[] = 'AttrDef/ListStyleTest.php'; $test_files[] = 'AttrDef/Email/SimpleCheckTest.php'; +$test_files[] = 'AttrDef/CSSURITest.php'; $test_files[] = 'IDAccumulatorTest.php'; $test_files[] = 'TagTransformTest.php'; $test_files[] = 'AttrTransform/LangTest.php';