1
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2025-07-31 19:30:21 +02:00

Include hsl and hsla support

This commit is contained in:
f.godfrin
2017-02-09 23:34:19 +01:00
parent d41a59e422
commit 0d5ab2fe13
2 changed files with 80 additions and 45 deletions

View File

@@ -29,39 +29,63 @@ class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
return $colors[$lower];
}
if (preg_match('#(rgb|rgba)\(#', $color, $matches) === 1) {
// get used function : rgb or rgba
$function = $matches[1];
if ($function == 'rgba') {
$parameters_size = 4;
} else {
$parameters_size = 3;
}
// rgb literal handling
if (preg_match('#(rgb|rgba|hsl|hsla)\(#', $color, $matches) === 1) {
$length = strlen($color);
if (strpos($color, ')') !== $length - 1) {
return false;
}
$values = substr($color, strlen($function) + 1, $length - strlen($function) - 2);
// get used function : rgb, rgba, hsl or hsla
$function = $matches[1];
$parameters_size = 3;
$alpha_channel = false;
if (substr($function, -1) === 'a') {
$parameters_size = 4;
$alpha_channel = true;
}
/*
* Allowed types for values :
* parameter_position => [type => max_value]
*/
$allowed_types = [
1 => ['percentage' => 100, 'integer' => 255],
2 => ['percentage' => 100, 'integer' => 255],
3 => ['percentage' => 100, 'integer' => 255],
];
$allow_different_types = false;
if (strpos($function, 'hsl') !== false) {
$allowed_types = [
1 => ['integer' => 360],
2 => ['percentage' => 100],
3 => ['percentage' => 100],
];
$allow_different_types = true;
}
$values = trim(str_replace($function, '', $color), ' ()');
$parts = explode(',', $values);
if (count($parts) !== $parameters_size) {
return false;
}
$type = false; // to ensure that they're all the same type
$type = false;
$new_parts = array();
$i = 0;
foreach ($parts as $part) {
$i++;
$part = trim($part);
if ($part === '') {
return false;
}
// different check for alpha channel
if ($function === 'rgba' && $i === count($parts)) {
if ($alpha_channel === true && $i === count($parts)) {
$result = (new HTMLPurifier_AttrDef_CSS_AlphaValue())->validate($part, $config, $context);
if ($result === false) {
@@ -72,41 +96,37 @@ class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
continue;
}
$length = strlen($part);
if ($part[$length - 1] === '%') {
// handle percents
if (!$type) {
$type = 'percentage';
} elseif ($type !== 'percentage') {
return false;
}
$num = (float)substr($part, 0, $length - 1);
if ($num < 0) {
$num = 0;
}
if ($num > 100) {
$num = 100;
}
$new_parts[] = "$num%";
if (substr($part, -1) === '%') {
$current_type = 'percentage';
} else {
// handle integers
if (!$type) {
$type = 'integer';
} elseif ($type !== 'integer') {
return false;
}
$num = (int)$part;
if ($num < 0) {
$num = 0;
}
if ($num > 255) {
$num = 255;
}
$new_parts[] = (string)$num;
$current_type = 'integer';
}
if (!array_key_exists($current_type, $allowed_types[$i])) {
return false;
}
if (!$type) {
$type = $current_type;
}
if ($allow_different_types === false && $type != $current_type) {
return false;
}
$max_value = $allowed_types[$i][$current_type];
if ($current_type == 'integer') {
// Return value between range 0 -> $max_value
$new_parts[] = (int)max(min($part, $max_value), 0);
} elseif ($current_type == 'percentage') {
$new_parts[] = (float)max(min(rtrim($part, '%'), $max_value), 0) . '%';
}
}
$new_values = implode(',', $new_parts);
$color = "$function($new_values)";
$color = $function . '(' . $new_values . ')';
} else {
// hexadecimal handling
if ($color[0] === '#') {