summaryrefslogtreecommitdiff
path: root/lib/htmlpurifier/library/HTMLPurifier/AttrDef
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2011-04-11 16:41:01 +0400
committerAndrew Dolgov <[email protected]>2011-04-11 16:41:01 +0400
commitf4f0f80d2118437e5047ba266f92d7acb3c38fb7 (patch)
treefb15f179dcd68b55613394ad864455f1796de555 /lib/htmlpurifier/library/HTMLPurifier/AttrDef
parentad92c6ac62903f3bb37f16048fedff44a2eb540d (diff)
update HTMLPurifier; enable embedded flash video in articles
Diffstat (limited to 'lib/htmlpurifier/library/HTMLPurifier/AttrDef')
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Background.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php21
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Border.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php2
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Composite.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Filter.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Font.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php177
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php21
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/Enum.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php0
-rw-r--r--lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Class.php34
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php2
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php2
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php10
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php2
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php36
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/Integer.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/Lang.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/Switch.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI.php2
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php6
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv4.php0
-rw-r--r--[-rwxr-xr-x]lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php0
40 files changed, 239 insertions, 76 deletions
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php
index 953e70675..953e70675 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php
index 292c040d4..292c040d4 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Background.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Background.php
index 3a3d20cd6..3a3d20cd6 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Background.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Background.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php
index 35df3985e..fae82eaec 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php
@@ -59,7 +59,8 @@ class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
$keywords = array();
$keywords['h'] = false; // left, right
$keywords['v'] = false; // top, bottom
- $keywords['c'] = false; // center
+ $keywords['ch'] = false; // center (first word)
+ $keywords['cv'] = false; // center (second word)
$measures = array();
$i = 0;
@@ -79,6 +80,13 @@ class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
$lbit = ctype_lower($bit) ? $bit : strtolower($bit);
if (isset($lookup[$lbit])) {
$status = $lookup[$lbit];
+ if ($status == 'c') {
+ if ($i == 0) {
+ $status = 'ch';
+ } else {
+ $status = 'cv';
+ }
+ }
$keywords[$status] = $lbit;
$i++;
}
@@ -101,20 +109,19 @@ class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
if (!$i) return false; // no valid values were caught
-
$ret = array();
// first keyword
if ($keywords['h']) $ret[] = $keywords['h'];
- elseif (count($measures)) $ret[] = array_shift($measures);
- elseif ($keywords['c']) {
- $ret[] = $keywords['c'];
- $keywords['c'] = false; // prevent re-use: center = center center
+ elseif ($keywords['ch']) {
+ $ret[] = $keywords['ch'];
+ $keywords['cv'] = false; // prevent re-use: center = center center
}
+ elseif (count($measures)) $ret[] = array_shift($measures);
if ($keywords['v']) $ret[] = $keywords['v'];
+ elseif ($keywords['cv']) $ret[] = $keywords['cv'];
elseif (count($measures)) $ret[] = array_shift($measures);
- elseif ($keywords['c']) $ret[] = $keywords['c'];
if (empty($ret)) return false;
return implode(' ', $ret);
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Border.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Border.php
index 42a1d1b4a..42a1d1b4a 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Border.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Border.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php
index 14c6594b6..07f95a671 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php
@@ -9,7 +9,7 @@ class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
public function validate($color, $config, $context) {
static $colors = null;
- if ($colors === null) $colors = $config->get('Core', 'ColorKeywords');
+ if ($colors === null) $colors = $config->get('Core.ColorKeywords');
$color = trim($color);
if ($color === '') return false;
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Composite.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Composite.php
index de1289cba..de1289cba 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Composite.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Composite.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
index 6599c5b2d..6599c5b2d 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Filter.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Filter.php
index 147894b86..147894b86 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Filter.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Filter.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Font.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Font.php
index 699ee0b70..699ee0b70 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Font.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Font.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php
index 705ac893d..0d9a4e12c 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php
@@ -2,11 +2,43 @@
/**
* Validates a font family list according to CSS spec
- * @todo whitelisting allowed fonts would be nice
*/
class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
{
+ protected $mask = null;
+
+ public function __construct() {
+ $this->mask = '- ';
+ for ($c = 'a'; $c <= 'z'; $c++) $this->mask .= $c;
+ for ($c = 'A'; $c <= 'Z'; $c++) $this->mask .= $c;
+ for ($c = '0'; $c <= '9'; $c++) $this->mask .= $c; // cast-y, but should be fine
+ // special bytes used by UTF-8
+ for ($i = 0x80; $i <= 0xFF; $i++) {
+ // We don't bother excluding invalid bytes in this range,
+ // because the our restriction of well-formed UTF-8 will
+ // prevent these from ever occurring.
+ $this->mask .= chr($i);
+ }
+
+ /*
+ PHP's internal strcspn implementation is
+ O(length of string * length of mask), making it inefficient
+ for large masks. However, it's still faster than
+ preg_match 8)
+ for (p = s1;;) {
+ spanp = s2;
+ do {
+ if (*spanp == c || p == s1_end) {
+ return p - s1;
+ }
+ } while (spanp++ < (s2_end - 1));
+ c = *++p;
+ }
+ */
+ // possible optimization: invert the mask.
+ }
+
public function validate($string, $config, $context) {
static $generic_names = array(
'serif' => true,
@@ -15,6 +47,7 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
'fantasy' => true,
'cursive' => true
);
+ $allowed_fonts = $config->get('CSS.AllowedFonts');
// assume that no font names contain commas in them
$fonts = explode(',', $string);
@@ -24,7 +57,9 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
if ($font === '') continue;
// match a generic name
if (isset($generic_names[$font])) {
- $final .= $font . ', ';
+ if ($allowed_fonts === null || isset($allowed_fonts[$font])) {
+ $final .= $font . ', ';
+ }
continue;
}
// match a quoted name
@@ -34,50 +69,122 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
$quote = $font[0];
if ($font[$length - 1] !== $quote) continue;
$font = substr($font, 1, $length - 2);
+ }
- $new_font = '';
- for ($i = 0, $c = strlen($font); $i < $c; $i++) {
- if ($font[$i] === '\\') {
- $i++;
- if ($i >= $c) {
- $new_font .= '\\';
- break;
- }
- if (ctype_xdigit($font[$i])) {
- $code = $font[$i];
- for ($a = 1, $i++; $i < $c && $a < 6; $i++, $a++) {
- if (!ctype_xdigit($font[$i])) break;
- $code .= $font[$i];
- }
- // We have to be extremely careful when adding
- // new characters, to make sure we're not breaking
- // the encoding.
- $char = HTMLPurifier_Encoder::unichr(hexdec($code));
- if (HTMLPurifier_Encoder::cleanUTF8($char) === '') continue;
- $new_font .= $char;
- if ($i < $c && trim($font[$i]) !== '') $i--;
- continue;
- }
- if ($font[$i] === "\n") continue;
- }
- $new_font .= $font[$i];
- }
+ $font = $this->expandCSSEscape($font);
- $font = $new_font;
- }
// $font is a pure representation of the font name
+ if ($allowed_fonts !== null && !isset($allowed_fonts[$font])) {
+ continue;
+ }
+
if (ctype_alnum($font) && $font !== '') {
// very simple font, allow it in unharmed
$final .= $font . ', ';
continue;
}
- // complicated font, requires quoting
+ // bugger out on whitespace. form feed (0C) really
+ // shouldn't show up regardless
+ $font = str_replace(array("\n", "\t", "\r", "\x0C"), ' ', $font);
+
+ // Here, there are various classes of characters which need
+ // to be treated differently:
+ // - Alphanumeric characters are essentially safe. We
+ // handled these above.
+ // - Spaces require quoting, though most parsers will do
+ // the right thing if there aren't any characters that
+ // can be misinterpreted
+ // - Dashes rarely occur, but they fairly unproblematic
+ // for parsing/rendering purposes.
+ // The above characters cover the majority of Western font
+ // names.
+ // - Arbitrary Unicode characters not in ASCII. Because
+ // most parsers give little thought to Unicode, treatment
+ // of these codepoints is basically uniform, even for
+ // punctuation-like codepoints. These characters can
+ // show up in non-Western pages and are supported by most
+ // major browsers, for example: "MS 明朝" is a
+ // legitimate font-name
+ // <http://ja.wikipedia.org/wiki/MS_明朝>. See
+ // the CSS3 spec for more examples:
+ // <http://www.w3.org/TR/2011/WD-css3-fonts-20110324/localizedfamilynames.png>
+ // You can see live samples of these on the Internet:
+ // <http://www.google.co.jp/search?q=font-family+MS+明朝|ゴシック>
+ // However, most of these fonts have ASCII equivalents:
+ // for example, 'MS Mincho', and it's considered
+ // professional to use ASCII font names instead of
+ // Unicode font names. Thanks Takeshi Terada for
+ // providing this information.
+ // The following characters, to my knowledge, have not been
+ // used to name font names.
+ // - Single quote. While theoretically you might find a
+ // font name that has a single quote in its name (serving
+ // as an apostrophe, e.g. Dave's Scribble), I haven't
+ // been able to find any actual examples of this.
+ // Internet Explorer's cssText translation (which I
+ // believe is invoked by innerHTML) normalizes any
+ // quoting to single quotes, and fails to escape single
+ // quotes. (Note that this is not IE's behavior for all
+ // CSS properties, just some sort of special casing for
+ // font-family). So a single quote *cannot* be used
+ // safely in the font-family context if there will be an
+ // innerHTML/cssText translation. Note that Firefox 3.x
+ // does this too.
+ // - Double quote. In IE, these get normalized to
+ // single-quotes, no matter what the encoding. (Fun
+ // fact, in IE8, the 'content' CSS property gained
+ // support, where they special cased to preserve encoded
+ // double quotes, but still translate unadorned double
+ // quotes into single quotes.) So, because their
+ // fixpoint behavior is identical to single quotes, they
+ // cannot be allowed either. Firefox 3.x displays
+ // single-quote style behavior.
+ // - Backslashes are reduced by one (so \\ -> \) every
+ // iteration, so they cannot be used safely. This shows
+ // up in IE7, IE8 and FF3
+ // - Semicolons, commas and backticks are handled properly.
+ // - The rest of the ASCII punctuation is handled properly.
+ // We haven't checked what browsers do to unadorned
+ // versions, but this is not important as long as the
+ // browser doesn't /remove/ surrounding quotes (as IE does
+ // for HTML).
+ //
+ // With these results in hand, we conclude that there are
+ // various levels of safety:
+ // - Paranoid: alphanumeric, spaces and dashes(?)
+ // - International: Paranoid + non-ASCII Unicode
+ // - Edgy: Everything except quotes, backslashes
+ // - NoJS: Standards compliance, e.g. sod IE. Note that
+ // with some judicious character escaping (since certain
+ // types of escaping doesn't work) this is theoretically
+ // OK as long as innerHTML/cssText is not called.
+ // We believe that international is a reasonable default
+ // (that we will implement now), and once we do more
+ // extensive research, we may feel comfortable with dropping
+ // it down to edgy.
+
+ // Edgy: alphanumeric, spaces, dashes and Unicode. Use of
+ // str(c)spn assumes that the string was already well formed
+ // Unicode (which of course it is).
+ if (strspn($font, $this->mask) !== strlen($font)) {
+ continue;
+ }
+
+ // Historical:
+ // In the absence of innerHTML/cssText, these ugly
+ // transforms don't pose a security risk (as \\ and \"
+ // might--these escapes are not supported by most browsers).
+ // We could try to be clever and use single-quote wrapping
+ // when there is a double quote present, but I have choosen
+ // not to implement that. (NOTE: you can reduce the amount
+ // of escapes by one depending on what quoting style you use)
+ // $font = str_replace('\\', '\\5C ', $font);
+ // $font = str_replace('"', '\\22 ', $font);
+ // $font = str_replace("'", '\\27 ', $font);
- // armor single quotes and new lines
- $font = str_replace("\\", "\\\\", $font);
- $font = str_replace("'", "\\'", $font);
+ // font possibly with spaces, requires quoting
$final .= "'$font', ";
}
$final = rtrim($final, ', ');
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php
index 4e6b35e5a..4e6b35e5a 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php
index a07ec5813..a07ec5813 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php
index 4406868c0..4406868c0 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php
index 4d62a40d7..4d62a40d7 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php
index 3f99e12ec..3f99e12ec 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php
index c34b8fc3c..c34b8fc3c 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php
index 772c922d8..772c922d8 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php
index 435d7930b..c2f767e57 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php
@@ -34,20 +34,25 @@ class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI
$uri = substr($uri, 1, $new_length - 1);
}
- $keys = array( '(', ')', ',', ' ', '"', "'");
- $values = array('\\(', '\\)', '\\,', '\\ ', '\\"', "\\'");
- $uri = str_replace($values, $keys, $uri);
+ $uri = $this->expandCSSEscape($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);
+ // extra sanity check; should have been done by URI
+ $result = str_replace(array('"', "\\", "\n", "\x0c", "\r"), "", $result);
- return "url($result)";
+ // suspicious characters are ()'; we're going to percent encode
+ // them for safety.
+ $result = str_replace(array('(', ')', "'"), array('%28', '%29', '%27'), $result);
+
+ // there's an extra bug where ampersands lose their escaping on
+ // an innerHTML cycle, so a very unlucky query parameter could
+ // then change the meaning of the URL. Unfortunately, there's
+ // not much we can do about that...
+
+ return "url(\"$result\")";
}
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Enum.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Enum.php
index 5d603ebcc..5d603ebcc 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Enum.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Enum.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php
index e06987eb8..e06987eb8 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Class.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Class.php
new file mode 100644
index 000000000..370068d97
--- /dev/null
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Class.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * Implements special behavior for class attribute (normally NMTOKENS)
+ */
+class HTMLPurifier_AttrDef_HTML_Class extends HTMLPurifier_AttrDef_HTML_Nmtokens
+{
+ protected function split($string, $config, $context) {
+ // really, this twiddle should be lazy loaded
+ $name = $config->getDefinition('HTML')->doctype->name;
+ if ($name == "XHTML 1.1" || $name == "XHTML 2.0") {
+ return parent::split($string, $config, $context);
+ } else {
+ return preg_split('/\s+/', $string);
+ }
+ }
+ protected function filter($tokens, $config, $context) {
+ $allowed = $config->get('Attr.AllowedClasses');
+ $forbidden = $config->get('Attr.ForbiddenClasses');
+ $ret = array();
+ foreach ($tokens as $token) {
+ if (
+ ($allowed === null || isset($allowed[$token])) &&
+ !isset($forbidden[$token]) &&
+ // We need this O(n) check because of PHP's array
+ // implementation that casts -0 to 0.
+ !in_array($token, $ret, true)
+ ) {
+ $ret[] = $token;
+ }
+ }
+ return $ret;
+ }
+}
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php
index 5311a3c61..d01e20454 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php
@@ -9,7 +9,7 @@ class HTMLPurifier_AttrDef_HTML_Color extends HTMLPurifier_AttrDef
public function validate($string, $config, $context) {
static $colors = null;
- if ($colors === null) $colors = $config->get('Core', 'ColorKeywords');
+ if ($colors === null) $colors = $config->get('Core.ColorKeywords');
$string = trim($string);
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php
index bd281a89f..ae6ea7c01 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php
@@ -12,7 +12,7 @@ class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum
public function __construct() {}
public function validate($string, $config, $context) {
- if ($this->valid_values === false) $this->valid_values = $config->get('Attr', 'AllowedFrameTargets');
+ if ($this->valid_values === false) $this->valid_values = $config->get('Attr.AllowedFrameTargets');
return parent::validate($string, $config, $context);
}
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php
index 7c5c169c2..81d03762d 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php
@@ -17,18 +17,18 @@ class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
public function validate($id, $config, $context) {
- if (!$config->get('Attr', 'EnableID')) return false;
+ if (!$config->get('Attr.EnableID')) return false;
$id = trim($id); // trim it first
if ($id === '') return false;
- $prefix = $config->get('Attr', 'IDPrefix');
+ $prefix = $config->get('Attr.IDPrefix');
if ($prefix !== '') {
- $prefix .= $config->get('Attr', 'IDPrefixLocal');
+ $prefix .= $config->get('Attr.IDPrefixLocal');
// prevent re-appending the prefix
if (strpos($id, $prefix) !== 0) $id = $prefix . $id;
- } elseif ($config->get('Attr', 'IDPrefixLocal') !== '') {
+ } elseif ($config->get('Attr.IDPrefixLocal') !== '') {
trigger_error('%Attr.IDPrefixLocal cannot be used unless '.
'%Attr.IDPrefix is set', E_USER_WARNING);
}
@@ -51,7 +51,7 @@ class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
$result = ($trim === '');
}
- $regexp = $config->get('Attr', 'IDBlacklistRegexp');
+ $regexp = $config->get('Attr.IDBlacklistRegexp');
if ($regexp && preg_match($regexp, $id)) {
return false;
}
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php
index a242f9c23..a242f9c23 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php
index 8a0da0c89..76d25ed08 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php
@@ -27,7 +27,7 @@ class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef
public function validate($string, $config, $context) {
- $allowed = $config->get('Attr', $this->name);
+ $allowed = $config->get('Attr.' . $this->name);
if (empty($allowed)) return false;
$string = $this->parseCDATA($string);
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php
index c72fc76e4..c72fc76e4 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php
index 55035c4d0..aa34120bd 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php
@@ -2,10 +2,6 @@
/**
* Validates contents based on NMTOKENS attribute type.
- * @note The only current use for this is the class attribute in HTML
- * @note Could have some functionality factored out into Nmtoken class
- * @warning We cannot assume this class will be used only for 'class'
- * attributes. Not sure how to hook in magic behavior, then.
*/
class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
{
@@ -17,6 +13,17 @@ class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
// early abort: '' and '0' (strings that convert to false) are invalid
if (!$string) return false;
+ $tokens = $this->split($string, $config, $context);
+ $tokens = $this->filter($tokens, $config, $context);
+ if (empty($tokens)) return false;
+ return implode(' ', $tokens);
+
+ }
+
+ /**
+ * Splits a space separated list of tokens into its constituent parts.
+ */
+ protected function split($string, $config, $context) {
// OPTIMIZABLE!
// do the preg_match, capture all subpatterns for reformulation
@@ -24,23 +31,20 @@ class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
// escaping because I don't know how to do that with regexps
// and plus it would complicate optimization efforts (you never
// see that anyway).
- $matches = array();
$pattern = '/(?:(?<=\s)|\A)'. // look behind for space or string start
'((?:--|-?[A-Za-z_])[A-Za-z_\-0-9]*)'.
'(?:(?=\s)|\z)/'; // look ahead for space or string end
preg_match_all($pattern, $string, $matches);
+ return $matches[1];
+ }
- if (empty($matches[1])) return false;
-
- // reconstruct string
- $new_string = '';
- foreach ($matches[1] as $token) {
- $new_string .= $token . ' ';
- }
- $new_string = rtrim($new_string);
-
- return $new_string;
-
+ /**
+ * Template method for removing certain tokens based on arbitrary criteria.
+ * @note If we wanted to be really functional, we'd do an array_filter
+ * with a callback. But... we're not.
+ */
+ protected function filter($tokens, $config, $context) {
+ return $tokens;
}
}
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php
index 4cb2c1b85..4cb2c1b85 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Integer.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Integer.php
index d59738d2a..d59738d2a 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Integer.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Integer.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Lang.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Lang.php
index 10e6da56d..10e6da56d 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Lang.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Lang.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Switch.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Switch.php
index c9e3ed193..c9e3ed193 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Switch.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Switch.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php
index c6216cc53..c6216cc53 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI.php
index 93d2f0bbf..01a6d83e9 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI.php
@@ -25,7 +25,7 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
public function validate($uri, $config, $context) {
- if ($config->get('URI', 'Disable')) return false;
+ if ($config->get('URI.Disable')) return false;
$uri = $this->parseCDATA($uri);
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email.php
index bfee9d166..bfee9d166 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php
index 94c715ab4..94c715ab4 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php
index 2156c10c6..feca469d7 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php
@@ -23,6 +23,12 @@ class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
public function validate($string, $config, $context) {
$length = strlen($string);
+ // empty hostname is OK; it's usually semantically equivalent:
+ // the default host as defined by a URI scheme is used:
+ //
+ // If the URI scheme defines a default for host, then that
+ // default applies when the host subcomponent is undefined
+ // or when the registered name is empty (zero length).
if ($string === '') return '';
if ($length > 1 && $string[0] === '[' && $string[$length-1] === ']') {
//IPv6
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv4.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv4.php
index ec4cf591b..ec4cf591b 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv4.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv4.php
diff --git a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php
index 9454e9be5..9454e9be5 100755..100644
--- a/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php
+++ b/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php