mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-02 04:43:46 +01:00
0ec0d04fb3
improves on 4.1s fix for an XSS vulnerability exploitable on Internet Explorer. It also contains a number of important bugfixes, including the removal of improper logic that could result in infinite loops and fixed parsing for single-attributes with entities with DirectLex.
134 lines
3.6 KiB
PHP
Executable File
134 lines
3.6 KiB
PHP
Executable File
<?php
|
|
|
|
/* W3C says:
|
|
[ // adjective and number must be in correct order, even if
|
|
// you could switch them without introducing ambiguity.
|
|
// some browsers support that syntax
|
|
[
|
|
<percentage> | <length> | left | center | right
|
|
]
|
|
[
|
|
<percentage> | <length> | top | center | bottom
|
|
]?
|
|
] |
|
|
[ // this signifies that the vertical and horizontal adjectives
|
|
// can be arbitrarily ordered, however, there can only be two,
|
|
// one of each, or none at all
|
|
[
|
|
left | center | right
|
|
] ||
|
|
[
|
|
top | center | bottom
|
|
]
|
|
]
|
|
top, left = 0%
|
|
center, (none) = 50%
|
|
bottom, right = 100%
|
|
*/
|
|
|
|
/* QuirksMode says:
|
|
keyword + length/percentage must be ordered correctly, as per W3C
|
|
|
|
Internet Explorer and Opera, however, support arbitrary ordering. We
|
|
should fix it up.
|
|
|
|
Minor issue though, not strictly necessary.
|
|
*/
|
|
|
|
// control freaks may appreciate the ability to convert these to
|
|
// percentages or something, but it's not necessary
|
|
|
|
/**
|
|
* Validates the value of background-position.
|
|
*/
|
|
class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
|
|
{
|
|
|
|
protected $length;
|
|
protected $percentage;
|
|
|
|
public function __construct() {
|
|
$this->length = new HTMLPurifier_AttrDef_CSS_Length();
|
|
$this->percentage = new HTMLPurifier_AttrDef_CSS_Percentage();
|
|
}
|
|
|
|
public function validate($string, $config, $context) {
|
|
$string = $this->parseCDATA($string);
|
|
$bits = explode(' ', $string);
|
|
|
|
$keywords = array();
|
|
$keywords['h'] = false; // left, right
|
|
$keywords['v'] = false; // top, bottom
|
|
$keywords['ch'] = false; // center (first word)
|
|
$keywords['cv'] = false; // center (second word)
|
|
$measures = array();
|
|
|
|
$i = 0;
|
|
|
|
$lookup = array(
|
|
'top' => 'v',
|
|
'bottom' => 'v',
|
|
'left' => 'h',
|
|
'right' => 'h',
|
|
'center' => 'c'
|
|
);
|
|
|
|
foreach ($bits as $bit) {
|
|
if ($bit === '') continue;
|
|
|
|
// test for keyword
|
|
$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++;
|
|
}
|
|
|
|
// test for length
|
|
$r = $this->length->validate($bit, $config, $context);
|
|
if ($r !== false) {
|
|
$measures[] = $r;
|
|
$i++;
|
|
}
|
|
|
|
// test for percentage
|
|
$r = $this->percentage->validate($bit, $config, $context);
|
|
if ($r !== false) {
|
|
$measures[] = $r;
|
|
$i++;
|
|
}
|
|
|
|
}
|
|
|
|
if (!$i) return false; // no valid values were caught
|
|
|
|
$ret = array();
|
|
|
|
// first keyword
|
|
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);
|
|
|
|
if ($keywords['v']) $ret[] = $keywords['v'];
|
|
elseif ($keywords['cv']) $ret[] = $keywords['cv'];
|
|
elseif (count($measures)) $ret[] = array_shift($measures);
|
|
|
|
if (empty($ret)) return false;
|
|
return implode(' ', $ret);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// vim: et sw=4 sts=4
|