aboutsummaryrefslogtreecommitdiffstats
path: root/library/HTMLPurifier/AttrDef/CSS
diff options
context:
space:
mode:
Diffstat (limited to 'library/HTMLPurifier/AttrDef/CSS')
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/AlphaValue.php27
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/Background.php60
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php54
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/Border.php21
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/Color.php67
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/Composite.php22
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php28
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/Filter.php49
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/Font.php89
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/FontFamily.php185
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/Ident.php32
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php28
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/Length.php60
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/ListStyle.php78
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/Multiple.php31
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/Number.php45
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/Percentage.php36
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/TextDecoration.php20
-rw-r--r--library/HTMLPurifier/AttrDef/CSS/URI.php38
19 files changed, 739 insertions, 231 deletions
diff --git a/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php b/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php
index 292c040d4..af2b83dff 100644
--- a/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php
+++ b/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php
@@ -3,19 +3,32 @@
class HTMLPurifier_AttrDef_CSS_AlphaValue extends HTMLPurifier_AttrDef_CSS_Number
{
- public function __construct() {
+ public function __construct()
+ {
parent::__construct(false); // opacity is non-negative, but we will clamp it
}
- public function validate($number, $config, $context) {
+ /**
+ * @param string $number
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return string
+ */
+ public function validate($number, $config, $context)
+ {
$result = parent::validate($number, $config, $context);
- if ($result === false) return $result;
- $float = (float) $result;
- if ($float < 0.0) $result = '0';
- if ($float > 1.0) $result = '1';
+ if ($result === false) {
+ return $result;
+ }
+ $float = (float)$result;
+ if ($float < 0.0) {
+ $result = '0';
+ }
+ if ($float > 1.0) {
+ $result = '1';
+ }
return $result;
}
-
}
// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Background.php b/library/HTMLPurifier/AttrDef/CSS/Background.php
index 3a3d20cd6..7f1ea3b0f 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Background.php
+++ b/library/HTMLPurifier/AttrDef/CSS/Background.php
@@ -9,11 +9,16 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
/**
* Local copy of component validators.
+ * @type HTMLPurifier_AttrDef[]
* @note See HTMLPurifier_AttrDef_Font::$info for a similar impl.
*/
protected $info;
- public function __construct($config) {
+ /**
+ * @param HTMLPurifier_Config $config
+ */
+ public function __construct($config)
+ {
$def = $config->getCSSDefinition();
$this->info['background-color'] = $def->info['background-color'];
$this->info['background-image'] = $def->info['background-image'];
@@ -22,40 +27,55 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
$this->info['background-position'] = $def->info['background-position'];
}
- public function validate($string, $config, $context) {
-
+ /**
+ * @param string $string
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
+ */
+ public function validate($string, $config, $context)
+ {
// regular pre-processing
$string = $this->parseCDATA($string);
- if ($string === '') return false;
+ if ($string === '') {
+ return false;
+ }
// munge rgb() decl if necessary
$string = $this->mungeRgb($string);
// assumes URI doesn't have spaces in it
- $bits = explode(' ', strtolower($string)); // bits to process
+ $bits = explode(' ', $string); // bits to process
$caught = array();
- $caught['color'] = false;
- $caught['image'] = false;
- $caught['repeat'] = false;
+ $caught['color'] = false;
+ $caught['image'] = false;
+ $caught['repeat'] = false;
$caught['attachment'] = false;
$caught['position'] = false;
$i = 0; // number of catches
- $none = false;
foreach ($bits as $bit) {
- if ($bit === '') continue;
+ if ($bit === '') {
+ continue;
+ }
foreach ($caught as $key => $status) {
if ($key != 'position') {
- if ($status !== false) continue;
+ if ($status !== false) {
+ continue;
+ }
$r = $this->info['background-' . $key]->validate($bit, $config, $context);
} else {
$r = $bit;
}
- if ($r === false) continue;
+ if ($r === false) {
+ continue;
+ }
if ($key == 'position') {
- if ($caught[$key] === false) $caught[$key] = '';
+ if ($caught[$key] === false) {
+ $caught[$key] = '';
+ }
$caught[$key] .= $r . ' ';
} else {
$caught[$key] = $r;
@@ -65,7 +85,9 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
}
}
- if (!$i) return false;
+ if (!$i) {
+ return false;
+ }
if ($caught['position'] !== false) {
$caught['position'] = $this->info['background-position']->
validate($caught['position'], $config, $context);
@@ -73,15 +95,17 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
$ret = array();
foreach ($caught as $value) {
- if ($value === false) continue;
+ if ($value === false) {
+ continue;
+ }
$ret[] = $value;
}
- if (empty($ret)) return false;
+ if (empty($ret)) {
+ return false;
+ }
return implode(' ', $ret);
-
}
-
}
// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php b/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php
index fae82eaec..4580ef5a9 100644
--- a/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php
+++ b/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php
@@ -44,15 +44,30 @@
class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
{
+ /**
+ * @type HTMLPurifier_AttrDef_CSS_Length
+ */
protected $length;
+
+ /**
+ * @type HTMLPurifier_AttrDef_CSS_Percentage
+ */
protected $percentage;
- public function __construct() {
- $this->length = new HTMLPurifier_AttrDef_CSS_Length();
+ public function __construct()
+ {
+ $this->length = new HTMLPurifier_AttrDef_CSS_Length();
$this->percentage = new HTMLPurifier_AttrDef_CSS_Percentage();
}
- public function validate($string, $config, $context) {
+ /**
+ * @param string $string
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
+ */
+ public function validate($string, $config, $context)
+ {
$string = $this->parseCDATA($string);
$bits = explode(' ', $string);
@@ -74,7 +89,9 @@ class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
);
foreach ($bits as $bit) {
- if ($bit === '') continue;
+ if ($bit === '') {
+ continue;
+ }
// test for keyword
$lbit = ctype_lower($bit) ? $bit : strtolower($bit);
@@ -104,30 +121,37 @@ class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
$measures[] = $r;
$i++;
}
-
}
- if (!$i) return false; // no valid values were caught
+ if (!$i) {
+ return false;
+ } // no valid values were caught
$ret = array();
// first keyword
- if ($keywords['h']) $ret[] = $keywords['h'];
- elseif ($keywords['ch']) {
+ if ($keywords['h']) {
+ $ret[] = $keywords['h'];
+ } elseif ($keywords['ch']) {
$ret[] = $keywords['ch'];
$keywords['cv'] = false; // prevent re-use: center = center center
+ } elseif (count($measures)) {
+ $ret[] = array_shift($measures);
}
- 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);
+ if ($keywords['v']) {
+ $ret[] = $keywords['v'];
+ } elseif ($keywords['cv']) {
+ $ret[] = $keywords['cv'];
+ } elseif (count($measures)) {
+ $ret[] = array_shift($measures);
+ }
- if (empty($ret)) return false;
+ if (empty($ret)) {
+ return false;
+ }
return implode(' ', $ret);
-
}
-
}
// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Border.php b/library/HTMLPurifier/AttrDef/CSS/Border.php
index 42a1d1b4a..16243ba1e 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Border.php
+++ b/library/HTMLPurifier/AttrDef/CSS/Border.php
@@ -8,17 +8,29 @@ class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
/**
* Local copy of properties this property is shorthand for.
+ * @type HTMLPurifier_AttrDef[]
*/
protected $info = array();
- public function __construct($config) {
+ /**
+ * @param HTMLPurifier_Config $config
+ */
+ public function __construct($config)
+ {
$def = $config->getCSSDefinition();
$this->info['border-width'] = $def->info['border-width'];
$this->info['border-style'] = $def->info['border-style'];
$this->info['border-top-color'] = $def->info['border-top-color'];
}
- public function validate($string, $config, $context) {
+ /**
+ * @param string $string
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
+ */
+ public function validate($string, $config, $context)
+ {
$string = $this->parseCDATA($string);
$string = $this->mungeRgb($string);
$bits = explode(' ', $string);
@@ -26,7 +38,9 @@ class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
$ret = ''; // return value
foreach ($bits as $bit) {
foreach ($this->info as $propname => $validator) {
- if (isset($done[$propname])) continue;
+ if (isset($done[$propname])) {
+ continue;
+ }
$r = $validator->validate($bit, $config, $context);
if ($r !== false) {
$ret .= $r . ' ';
@@ -37,7 +51,6 @@ class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
}
return rtrim($ret);
}
-
}
// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Color.php b/library/HTMLPurifier/AttrDef/CSS/Color.php
index 07f95a671..16d2a6b98 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Color.php
+++ b/library/HTMLPurifier/AttrDef/CSS/Color.php
@@ -6,29 +6,47 @@
class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
{
- public function validate($color, $config, $context) {
-
+ /**
+ * @param string $color
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
+ */
+ 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;
+ if ($color === '') {
+ return false;
+ }
$lower = strtolower($color);
- if (isset($colors[$lower])) return $colors[$lower];
+ if (isset($colors[$lower])) {
+ return $colors[$lower];
+ }
if (strpos($color, 'rgb(') !== false) {
// rgb literal handling
$length = strlen($color);
- if (strpos($color, ')') !== $length - 1) return false;
+ if (strpos($color, ')') !== $length - 1) {
+ return false;
+ }
$triad = substr($color, 4, $length - 4 - 1);
$parts = explode(',', $triad);
- if (count($parts) !== 3) return false;
+ if (count($parts) !== 3) {
+ return false;
+ }
$type = false; // to ensure that they're all the same type
$new_parts = array();
foreach ($parts as $part) {
$part = trim($part);
- if ($part === '') return false;
+ if ($part === '') {
+ return false;
+ }
$length = strlen($part);
if ($part[$length - 1] === '%') {
// handle percents
@@ -37,9 +55,13 @@ class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
} elseif ($type !== 'percentage') {
return false;
}
- $num = (float) substr($part, 0, $length - 1);
- if ($num < 0) $num = 0;
- if ($num > 100) $num = 100;
+ $num = (float)substr($part, 0, $length - 1);
+ if ($num < 0) {
+ $num = 0;
+ }
+ if ($num > 100) {
+ $num = 100;
+ }
$new_parts[] = "$num%";
} else {
// handle integers
@@ -48,10 +70,14 @@ class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
} elseif ($type !== 'integer') {
return false;
}
- $num = (int) $part;
- if ($num < 0) $num = 0;
- if ($num > 255) $num = 255;
- $new_parts[] = (string) $num;
+ $num = (int)$part;
+ if ($num < 0) {
+ $num = 0;
+ }
+ if ($num > 255) {
+ $num = 255;
+ }
+ $new_parts[] = (string)$num;
}
}
$new_triad = implode(',', $new_parts);
@@ -65,14 +91,15 @@ class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
$color = '#' . $color;
}
$length = strlen($hex);
- if ($length !== 3 && $length !== 6) return false;
- if (!ctype_xdigit($hex)) return false;
+ if ($length !== 3 && $length !== 6) {
+ return false;
+ }
+ if (!ctype_xdigit($hex)) {
+ return false;
+ }
}
-
return $color;
-
}
-
}
// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Composite.php b/library/HTMLPurifier/AttrDef/CSS/Composite.php
index de1289cba..9c1750554 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Composite.php
+++ b/library/HTMLPurifier/AttrDef/CSS/Composite.php
@@ -13,26 +13,36 @@ class HTMLPurifier_AttrDef_CSS_Composite extends HTMLPurifier_AttrDef
{
/**
- * List of HTMLPurifier_AttrDef objects that may process strings
+ * List of objects that may process strings.
+ * @type HTMLPurifier_AttrDef[]
* @todo Make protected
*/
public $defs;
/**
- * @param $defs List of HTMLPurifier_AttrDef objects
+ * @param HTMLPurifier_AttrDef[] $defs List of HTMLPurifier_AttrDef objects
*/
- public function __construct($defs) {
+ public function __construct($defs)
+ {
$this->defs = $defs;
}
- public function validate($string, $config, $context) {
+ /**
+ * @param string $string
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
+ */
+ public function validate($string, $config, $context)
+ {
foreach ($this->defs as $i => $def) {
$result = $this->defs[$i]->validate($string, $config, $context);
- if ($result !== false) return $result;
+ if ($result !== false) {
+ return $result;
+ }
}
return false;
}
-
}
// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php b/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
index 6599c5b2d..9d77cc9aa 100644
--- a/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
+++ b/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
@@ -5,22 +5,38 @@
*/
class HTMLPurifier_AttrDef_CSS_DenyElementDecorator extends HTMLPurifier_AttrDef
{
- public $def, $element;
+ /**
+ * @type HTMLPurifier_AttrDef
+ */
+ public $def;
+ /**
+ * @type string
+ */
+ public $element;
/**
- * @param $def Definition to wrap
- * @param $element Element to deny
+ * @param HTMLPurifier_AttrDef $def Definition to wrap
+ * @param string $element Element to deny
*/
- public function __construct($def, $element) {
+ public function __construct($def, $element)
+ {
$this->def = $def;
$this->element = $element;
}
+
/**
* Checks if CurrentToken is set and equal to $this->element
+ * @param string $string
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
*/
- public function validate($string, $config, $context) {
+ public function validate($string, $config, $context)
+ {
$token = $context->get('CurrentToken', true);
- if ($token && $token->name == $this->element) return false;
+ if ($token && $token->name == $this->element) {
+ return false;
+ }
return $this->def->validate($string, $config, $context);
}
}
diff --git a/library/HTMLPurifier/AttrDef/CSS/Filter.php b/library/HTMLPurifier/AttrDef/CSS/Filter.php
index 147894b86..bde4c3301 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Filter.php
+++ b/library/HTMLPurifier/AttrDef/CSS/Filter.php
@@ -7,23 +7,37 @@
*/
class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
{
-
+ /**
+ * @type HTMLPurifier_AttrDef_Integer
+ */
protected $intValidator;
- public function __construct() {
+ public function __construct()
+ {
$this->intValidator = new HTMLPurifier_AttrDef_Integer();
}
- public function validate($value, $config, $context) {
+ /**
+ * @param string $value
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
+ */
+ public function validate($value, $config, $context)
+ {
$value = $this->parseCDATA($value);
- if ($value === 'none') return $value;
+ if ($value === 'none') {
+ return $value;
+ }
// if we looped this we could support multiple filters
$function_length = strcspn($value, '(');
$function = trim(substr($value, 0, $function_length));
if ($function !== 'alpha' &&
$function !== 'Alpha' &&
$function !== 'progid:DXImageTransform.Microsoft.Alpha'
- ) return false;
+ ) {
+ return false;
+ }
$cursor = $function_length + 1;
$parameters_length = strcspn($value, ')', $cursor);
$parameters = substr($value, $cursor, $parameters_length);
@@ -32,15 +46,25 @@ class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
$lookup = array();
foreach ($params as $param) {
list($key, $value) = explode('=', $param);
- $key = trim($key);
+ $key = trim($key);
$value = trim($value);
- if (isset($lookup[$key])) continue;
- if ($key !== 'opacity') continue;
+ if (isset($lookup[$key])) {
+ continue;
+ }
+ if ($key !== 'opacity') {
+ continue;
+ }
$value = $this->intValidator->validate($value, $config, $context);
- if ($value === false) continue;
- $int = (int) $value;
- if ($int > 100) $value = '100';
- if ($int < 0) $value = '0';
+ if ($value === false) {
+ continue;
+ }
+ $int = (int)$value;
+ if ($int > 100) {
+ $value = '100';
+ }
+ if ($int < 0) {
+ $value = '0';
+ }
$ret_params[] = "$key=$value";
$lookup[$key] = true;
}
@@ -48,7 +72,6 @@ class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
$ret_function = "$function($ret_parameters)";
return $ret_function;
}
-
}
// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Font.php b/library/HTMLPurifier/AttrDef/CSS/Font.php
index 699ee0b70..579b97ef1 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Font.php
+++ b/library/HTMLPurifier/AttrDef/CSS/Font.php
@@ -7,8 +7,8 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
{
/**
- * Local copy of component validators.
- *
+ * Local copy of validators
+ * @type HTMLPurifier_AttrDef[]
* @note If we moved specific CSS property definitions to their own
* classes instead of having them be assembled at run time by
* CSSDefinition, this wouldn't be necessary. We'd instantiate
@@ -16,18 +16,28 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
*/
protected $info = array();
- public function __construct($config) {
+ /**
+ * @param HTMLPurifier_Config $config
+ */
+ public function __construct($config)
+ {
$def = $config->getCSSDefinition();
- $this->info['font-style'] = $def->info['font-style'];
+ $this->info['font-style'] = $def->info['font-style'];
$this->info['font-variant'] = $def->info['font-variant'];
- $this->info['font-weight'] = $def->info['font-weight'];
- $this->info['font-size'] = $def->info['font-size'];
- $this->info['line-height'] = $def->info['line-height'];
- $this->info['font-family'] = $def->info['font-family'];
+ $this->info['font-weight'] = $def->info['font-weight'];
+ $this->info['font-size'] = $def->info['font-size'];
+ $this->info['line-height'] = $def->info['line-height'];
+ $this->info['font-family'] = $def->info['font-family'];
}
- public function validate($string, $config, $context) {
-
+ /**
+ * @param string $string
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
+ */
+ public function validate($string, $config, $context)
+ {
static $system_fonts = array(
'caption' => true,
'icon' => true,
@@ -39,7 +49,9 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
// regular pre-processing
$string = $this->parseCDATA($string);
- if ($string === '') return false;
+ if ($string === '') {
+ return false;
+ }
// check if it's one of the keywords
$lowercase_string = strtolower($string);
@@ -54,15 +66,20 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
$final = ''; // output
for ($i = 0, $size = count($bits); $i < $size; $i++) {
- if ($bits[$i] === '') continue;
+ if ($bits[$i] === '') {
+ continue;
+ }
switch ($stage) {
-
- // attempting to catch font-style, font-variant or font-weight
- case 0:
+ case 0: // attempting to catch font-style, font-variant or font-weight
foreach ($stage_1 as $validator_name) {
- if (isset($caught[$validator_name])) continue;
+ if (isset($caught[$validator_name])) {
+ continue;
+ }
$r = $this->info[$validator_name]->validate(
- $bits[$i], $config, $context);
+ $bits[$i],
+ $config,
+ $context
+ );
if ($r !== false) {
$final .= $r . ' ';
$caught[$validator_name] = true;
@@ -70,15 +87,17 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
}
}
// all three caught, continue on
- if (count($caught) >= 3) $stage = 1;
- if ($r !== false) break;
-
- // attempting to catch font-size and perhaps line-height
- case 1:
+ if (count($caught) >= 3) {
+ $stage = 1;
+ }
+ if ($r !== false) {
+ break;
+ }
+ case 1: // attempting to catch font-size and perhaps line-height
$found_slash = false;
if (strpos($bits[$i], '/') !== false) {
list($font_size, $line_height) =
- explode('/', $bits[$i]);
+ explode('/', $bits[$i]);
if ($line_height === '') {
// ooh, there's a space after the slash!
$line_height = false;
@@ -89,14 +108,19 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
$line_height = false;
}
$r = $this->info['font-size']->validate(
- $font_size, $config, $context);
+ $font_size,
+ $config,
+ $context
+ );
if ($r !== false) {
$final .= $r;
// attempt to catch line-height
if ($line_height === false) {
// we need to scroll forward
for ($j = $i + 1; $j < $size; $j++) {
- if ($bits[$j] === '') continue;
+ if ($bits[$j] === '') {
+ continue;
+ }
if ($bits[$j] === '/') {
if ($found_slash) {
return false;
@@ -116,7 +140,10 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
if ($found_slash) {
$i = $j;
$r = $this->info['line-height']->validate(
- $line_height, $config, $context);
+ $line_height,
+ $config,
+ $context
+ );
if ($r !== false) {
$final .= '/' . $r;
}
@@ -126,13 +153,14 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
break;
}
return false;
-
- // attempting to catch font-family
- case 2:
+ case 2: // attempting to catch font-family
$font_family =
implode(' ', array_slice($bits, $i, $size - $i));
$r = $this->info['font-family']->validate(
- $font_family, $config, $context);
+ $font_family,
+ $config,
+ $context
+ );
if ($r !== false) {
$final .= $r . ' ';
// processing completed successfully
@@ -143,7 +171,6 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
}
return false;
}
-
}
// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/FontFamily.php b/library/HTMLPurifier/AttrDef/CSS/FontFamily.php
index 42c2054c2..74e24c881 100644
--- a/library/HTMLPurifier/AttrDef/CSS/FontFamily.php
+++ b/library/HTMLPurifier/AttrDef/CSS/FontFamily.php
@@ -2,12 +2,58 @@
/**
* Validates a font family list according to CSS spec
- * @todo whitelisting allowed fonts would be nice
*/
class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
{
- public function validate($string, $config, $context) {
+ 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.
+ }
+
+ /**
+ * @param string $string
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
+ */
+ public function validate($string, $config, $context)
+ {
static $generic_names = array(
'serif' => true,
'sans-serif' => true,
@@ -15,24 +61,33 @@ 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);
$final = '';
- foreach($fonts as $font) {
+ foreach ($fonts as $font) {
$font = trim($font);
- if ($font === '') continue;
+ 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
if ($font[0] === '"' || $font[0] === "'") {
$length = strlen($font);
- if ($length <= 2) continue;
+ if ($length <= 2) {
+ continue;
+ }
$quote = $font[0];
- if ($font[$length - 1] !== $quote) continue;
+ if ($font[$length - 1] !== $quote) {
+ continue;
+ }
$font = substr($font, 1, $length - 2);
}
@@ -40,6 +95,10 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
// $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 . ', ';
@@ -50,20 +109,108 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
// shouldn't show up regardless
$font = str_replace(array("\n", "\t", "\r", "\x0C"), ' ', $font);
- // These ugly transforms don't pose a security
- // risk (as \\ and \" might). 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.
- // (warning: this code relies on the selection of quotation
- // mark below)
- $font = str_replace('\\', '\\5C ', $font);
- $font = str_replace('"', '\\22 ', $font);
-
- // complicated font, requires quoting
- $final .= "\"$font\", "; // note that this will later get turned into &quot;
+ // 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, underscores 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);
+
+ // font possibly with spaces, requires quoting
+ $final .= "'$font', ";
}
$final = rtrim($final, ', ');
- if ($final === '') return false;
+ if ($final === '') {
+ return false;
+ }
return $final;
}
diff --git a/library/HTMLPurifier/AttrDef/CSS/Ident.php b/library/HTMLPurifier/AttrDef/CSS/Ident.php
new file mode 100644
index 000000000..973002c17
--- /dev/null
+++ b/library/HTMLPurifier/AttrDef/CSS/Ident.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * Validates based on {ident} CSS grammar production
+ */
+class HTMLPurifier_AttrDef_CSS_Ident extends HTMLPurifier_AttrDef
+{
+
+ /**
+ * @param string $string
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
+ */
+ public function validate($string, $config, $context)
+ {
+ $string = trim($string);
+
+ // early abort: '' and '0' (strings that convert to false) are invalid
+ if (!$string) {
+ return false;
+ }
+
+ $pattern = '/^(-?[A-Za-z_][A-Za-z_\-0-9]*)$/';
+ if (!preg_match($pattern, $string)) {
+ return false;
+ }
+ return $string;
+ }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php b/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php
index 4e6b35e5a..ffc989fe8 100644
--- a/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php
+++ b/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php
@@ -5,20 +5,34 @@
*/
class HTMLPurifier_AttrDef_CSS_ImportantDecorator extends HTMLPurifier_AttrDef
{
- public $def, $allow;
+ /**
+ * @type HTMLPurifier_AttrDef
+ */
+ public $def;
+ /**
+ * @type bool
+ */
+ public $allow;
/**
- * @param $def Definition to wrap
- * @param $allow Whether or not to allow !important
+ * @param HTMLPurifier_AttrDef $def Definition to wrap
+ * @param bool $allow Whether or not to allow !important
*/
- public function __construct($def, $allow = false) {
+ public function __construct($def, $allow = false)
+ {
$this->def = $def;
$this->allow = $allow;
}
+
/**
* Intercepts and removes !important if necessary
+ * @param string $string
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
*/
- public function validate($string, $config, $context) {
+ public function validate($string, $config, $context)
+ {
// test for ! and important tokens
$string = trim($string);
$is_important = false;
@@ -32,7 +46,9 @@ class HTMLPurifier_AttrDef_CSS_ImportantDecorator extends HTMLPurifier_AttrDef
}
}
$string = $this->def->validate($string, $config, $context);
- if ($this->allow && $is_important) $string .= ' !important';
+ if ($this->allow && $is_important) {
+ $string .= ' !important';
+ }
return $string;
}
}
diff --git a/library/HTMLPurifier/AttrDef/CSS/Length.php b/library/HTMLPurifier/AttrDef/CSS/Length.php
index a07ec5813..f12453a04 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Length.php
+++ b/library/HTMLPurifier/AttrDef/CSS/Length.php
@@ -6,42 +6,72 @@
class HTMLPurifier_AttrDef_CSS_Length extends HTMLPurifier_AttrDef
{
- protected $min, $max;
+ /**
+ * @type HTMLPurifier_Length|string
+ */
+ protected $min;
/**
- * @param HTMLPurifier_Length $max Minimum length, or null for no bound. String is also acceptable.
- * @param HTMLPurifier_Length $max Maximum length, or null for no bound. String is also acceptable.
+ * @type HTMLPurifier_Length|string
*/
- public function __construct($min = null, $max = null) {
+ protected $max;
+
+ /**
+ * @param HTMLPurifier_Length|string $min Minimum length, or null for no bound. String is also acceptable.
+ * @param HTMLPurifier_Length|string $max Maximum length, or null for no bound. String is also acceptable.
+ */
+ public function __construct($min = null, $max = null)
+ {
$this->min = $min !== null ? HTMLPurifier_Length::make($min) : null;
$this->max = $max !== null ? HTMLPurifier_Length::make($max) : null;
}
- public function validate($string, $config, $context) {
+ /**
+ * @param string $string
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
+ */
+ public function validate($string, $config, $context)
+ {
$string = $this->parseCDATA($string);
// Optimizations
- if ($string === '') return false;
- if ($string === '0') return '0';
- if (strlen($string) === 1) return false;
+ if ($string === '') {
+ return false;
+ }
+ if ($string === '0') {
+ return '0';
+ }
+ if (strlen($string) === 1) {
+ return false;
+ }
$length = HTMLPurifier_Length::make($string);
- if (!$length->isValid()) return false;
+ if (!$length->isValid()) {
+ return false;
+ }
if ($this->min) {
$c = $length->compareTo($this->min);
- if ($c === false) return false;
- if ($c < 0) return false;
+ if ($c === false) {
+ return false;
+ }
+ if ($c < 0) {
+ return false;
+ }
}
if ($this->max) {
$c = $length->compareTo($this->max);
- if ($c === false) return false;
- if ($c > 0) return false;
+ if ($c === false) {
+ return false;
+ }
+ if ($c > 0) {
+ return false;
+ }
}
-
return $length->toString();
}
-
}
// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/ListStyle.php b/library/HTMLPurifier/AttrDef/CSS/ListStyle.php
index 4406868c0..e74d42654 100644
--- a/library/HTMLPurifier/AttrDef/CSS/ListStyle.php
+++ b/library/HTMLPurifier/AttrDef/CSS/ListStyle.php
@@ -8,46 +8,72 @@ class HTMLPurifier_AttrDef_CSS_ListStyle extends HTMLPurifier_AttrDef
{
/**
- * Local copy of component validators.
+ * Local copy of validators.
+ * @type HTMLPurifier_AttrDef[]
* @note See HTMLPurifier_AttrDef_CSS_Font::$info for a similar impl.
*/
protected $info;
- public function __construct($config) {
+ /**
+ * @param HTMLPurifier_Config $config
+ */
+ public function __construct($config)
+ {
$def = $config->getCSSDefinition();
- $this->info['list-style-type'] = $def->info['list-style-type'];
+ $this->info['list-style-type'] = $def->info['list-style-type'];
$this->info['list-style-position'] = $def->info['list-style-position'];
$this->info['list-style-image'] = $def->info['list-style-image'];
}
- public function validate($string, $config, $context) {
-
+ /**
+ * @param string $string
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
+ */
+ public function validate($string, $config, $context)
+ {
// regular pre-processing
$string = $this->parseCDATA($string);
- if ($string === '') return false;
+ if ($string === '') {
+ return false;
+ }
// assumes URI doesn't have spaces in it
$bits = explode(' ', strtolower($string)); // bits to process
$caught = array();
- $caught['type'] = false;
+ $caught['type'] = false;
$caught['position'] = false;
- $caught['image'] = false;
+ $caught['image'] = false;
$i = 0; // number of catches
$none = false;
foreach ($bits as $bit) {
- if ($i >= 3) return; // optimization bit
- if ($bit === '') continue;
+ if ($i >= 3) {
+ return;
+ } // optimization bit
+ if ($bit === '') {
+ continue;
+ }
foreach ($caught as $key => $status) {
- if ($status !== false) continue;
+ if ($status !== false) {
+ continue;
+ }
$r = $this->info['list-style-' . $key]->validate($bit, $config, $context);
- if ($r === false) continue;
+ if ($r === false) {
+ continue;
+ }
if ($r === 'none') {
- if ($none) continue;
- else $none = true;
- if ($key == 'image') continue;
+ if ($none) {
+ continue;
+ } else {
+ $none = true;
+ }
+ if ($key == 'image') {
+ continue;
+ }
}
$caught[$key] = $r;
$i++;
@@ -55,24 +81,32 @@ class HTMLPurifier_AttrDef_CSS_ListStyle extends HTMLPurifier_AttrDef
}
}
- if (!$i) return false;
+ if (!$i) {
+ return false;
+ }
$ret = array();
// construct type
- if ($caught['type']) $ret[] = $caught['type'];
+ if ($caught['type']) {
+ $ret[] = $caught['type'];
+ }
// construct image
- if ($caught['image']) $ret[] = $caught['image'];
+ if ($caught['image']) {
+ $ret[] = $caught['image'];
+ }
// construct position
- if ($caught['position']) $ret[] = $caught['position'];
+ if ($caught['position']) {
+ $ret[] = $caught['position'];
+ }
- if (empty($ret)) return false;
+ if (empty($ret)) {
+ return false;
+ }
return implode(' ', $ret);
-
}
-
}
// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Multiple.php b/library/HTMLPurifier/AttrDef/CSS/Multiple.php
index 4d62a40d7..9f266cdd1 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Multiple.php
+++ b/library/HTMLPurifier/AttrDef/CSS/Multiple.php
@@ -13,9 +13,9 @@
*/
class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef
{
-
/**
* Instance of component definition to defer validation to.
+ * @type HTMLPurifier_AttrDef
* @todo Make protected
*/
public $single;
@@ -27,32 +27,45 @@ class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef
public $max;
/**
- * @param $single HTMLPurifier_AttrDef to multiply
- * @param $max Max number of values allowed (usually four)
+ * @param HTMLPurifier_AttrDef $single HTMLPurifier_AttrDef to multiply
+ * @param int $max Max number of values allowed (usually four)
*/
- public function __construct($single, $max = 4) {
+ public function __construct($single, $max = 4)
+ {
$this->single = $single;
$this->max = $max;
}
- public function validate($string, $config, $context) {
+ /**
+ * @param string $string
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
+ */
+ public function validate($string, $config, $context)
+ {
$string = $this->parseCDATA($string);
- if ($string === '') return false;
+ if ($string === '') {
+ return false;
+ }
$parts = explode(' ', $string); // parseCDATA replaced \r, \t and \n
$length = count($parts);
$final = '';
for ($i = 0, $num = 0; $i < $length && $num < $this->max; $i++) {
- if (ctype_space($parts[$i])) continue;
+ if (ctype_space($parts[$i])) {
+ continue;
+ }
$result = $this->single->validate($parts[$i], $config, $context);
if ($result !== false) {
$final .= $result . ' ';
$num++;
}
}
- if ($final === '') return false;
+ if ($final === '') {
+ return false;
+ }
return rtrim($final);
}
-
}
// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Number.php b/library/HTMLPurifier/AttrDef/CSS/Number.php
index 3f99e12ec..8edc159e7 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Number.php
+++ b/library/HTMLPurifier/AttrDef/CSS/Number.php
@@ -7,32 +7,44 @@ class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
{
/**
- * Bool indicating whether or not only positive values allowed.
+ * Indicates whether or not only positive values are allowed.
+ * @type bool
*/
protected $non_negative = false;
/**
- * @param $non_negative Bool indicating whether negatives are forbidden
+ * @param bool $non_negative indicates whether negatives are forbidden
*/
- public function __construct($non_negative = false) {
+ public function __construct($non_negative = false)
+ {
$this->non_negative = $non_negative;
}
/**
+ * @param string $number
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return string|bool
* @warning Some contexts do not pass $config, $context. These
* variables should not be used without checking HTMLPurifier_Length
*/
- public function validate($number, $config, $context) {
-
+ public function validate($number, $config, $context)
+ {
$number = $this->parseCDATA($number);
- if ($number === '') return false;
- if ($number === '0') return '0';
+ if ($number === '') {
+ return false;
+ }
+ if ($number === '0') {
+ return '0';
+ }
$sign = '';
switch ($number[0]) {
case '-':
- if ($this->non_negative) return false;
+ if ($this->non_negative) {
+ return false;
+ }
$sign = '-';
case '+':
$number = substr($number, 1);
@@ -44,14 +56,20 @@ class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
}
// Period is the only non-numeric character allowed
- if (strpos($number, '.') === false) return false;
+ if (strpos($number, '.') === false) {
+ return false;
+ }
list($left, $right) = explode('.', $number, 2);
- if ($left === '' && $right === '') return false;
- if ($left !== '' && !ctype_digit($left)) return false;
+ if ($left === '' && $right === '') {
+ return false;
+ }
+ if ($left !== '' && !ctype_digit($left)) {
+ return false;
+ }
- $left = ltrim($left, '0');
+ $left = ltrim($left, '0');
$right = rtrim($right, '0');
if ($right === '') {
@@ -59,11 +77,8 @@ class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
} elseif (!ctype_digit($right)) {
return false;
}
-
return $sign . $left . '.' . $right;
-
}
-
}
// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Percentage.php b/library/HTMLPurifier/AttrDef/CSS/Percentage.php
index c34b8fc3c..f0f25c50a 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Percentage.php
+++ b/library/HTMLPurifier/AttrDef/CSS/Percentage.php
@@ -7,34 +7,48 @@ class HTMLPurifier_AttrDef_CSS_Percentage extends HTMLPurifier_AttrDef
{
/**
- * Instance of HTMLPurifier_AttrDef_CSS_Number to defer number validation
+ * Instance to defer number validation to.
+ * @type HTMLPurifier_AttrDef_CSS_Number
*/
protected $number_def;
/**
- * @param Bool indicating whether to forbid negative values
+ * @param bool $non_negative Whether to forbid negative values
*/
- public function __construct($non_negative = false) {
+ public function __construct($non_negative = false)
+ {
$this->number_def = new HTMLPurifier_AttrDef_CSS_Number($non_negative);
}
- public function validate($string, $config, $context) {
-
+ /**
+ * @param string $string
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
+ */
+ public function validate($string, $config, $context)
+ {
$string = $this->parseCDATA($string);
- if ($string === '') return false;
+ if ($string === '') {
+ return false;
+ }
$length = strlen($string);
- if ($length === 1) return false;
- if ($string[$length - 1] !== '%') return false;
+ if ($length === 1) {
+ return false;
+ }
+ if ($string[$length - 1] !== '%') {
+ return false;
+ }
$number = substr($string, 0, $length - 1);
$number = $this->number_def->validate($number, $config, $context);
- if ($number === false) return false;
+ if ($number === false) {
+ return false;
+ }
return "$number%";
-
}
-
}
// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php b/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php
index 772c922d8..5fd4b7f7b 100644
--- a/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php
+++ b/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php
@@ -8,8 +8,14 @@
class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
{
- public function validate($string, $config, $context) {
-
+ /**
+ * @param string $string
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
+ */
+ public function validate($string, $config, $context)
+ {
static $allowed_values = array(
'line-through' => true,
'overline' => true,
@@ -18,7 +24,9 @@ class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
$string = strtolower($this->parseCDATA($string));
- if ($string === 'none') return $string;
+ if ($string === 'none') {
+ return $string;
+ }
$parts = explode(' ', $string);
$final = '';
@@ -28,11 +36,11 @@ class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
}
}
$final = rtrim($final);
- if ($final === '') return false;
+ if ($final === '') {
+ return false;
+ }
return $final;
-
}
-
}
// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/URI.php b/library/HTMLPurifier/AttrDef/CSS/URI.php
index 1df17dc25..f9434230e 100644
--- a/library/HTMLPurifier/AttrDef/CSS/URI.php
+++ b/library/HTMLPurifier/AttrDef/CSS/URI.php
@@ -12,25 +12,39 @@
class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI
{
- public function __construct() {
+ public function __construct()
+ {
parent::__construct(true); // always embedded
}
- public function validate($uri_string, $config, $context) {
+ /**
+ * @param string $uri_string
+ * @param HTMLPurifier_Config $config
+ * @param HTMLPurifier_Context $context
+ * @return bool|string
+ */
+ public 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;
+ 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;
+ if ($uri_string[$new_length] != ')') {
+ return false;
+ }
$uri = trim(substr($uri_string, 0, $new_length));
if (!empty($uri) && ($uri[0] == "'" || $uri[0] == '"')) {
$quote = $uri[0];
$new_length = strlen($uri) - 1;
- if ($uri[$new_length] !== $quote) return false;
+ if ($uri[$new_length] !== $quote) {
+ return false;
+ }
$uri = substr($uri, 1, $new_length - 1);
}
@@ -38,15 +52,23 @@ class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI
$result = parent::validate($uri, $config, $context);
- if ($result === false) return false;
+ if ($result === false) {
+ return false;
+ }
// 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\")";
}
-
}
// vim: et sw=4 sts=4