Whoops, forgot to edit WHATSNEW
[htmlpurifier.git] / library / HTMLPurifier / AttrDef / CSS / Color.php
blobd7287a00c2e85ef3aef9f52af970788c748f1c6e
1 <?php
3 /**
4 * Validates Color as defined by CSS.
5 */
6 class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
9 /**
10 * @type HTMLPurifier_AttrDef_CSS_AlphaValue
12 protected $alpha;
14 public function __construct()
16 $this->alpha = new HTMLPurifier_AttrDef_CSS_AlphaValue();
19 /**
20 * @param string $color
21 * @param HTMLPurifier_Config $config
22 * @param HTMLPurifier_Context $context
23 * @return bool|string
25 public function validate($color, $config, $context)
27 static $colors = null;
28 if ($colors === null) {
29 $colors = $config->get('Core.ColorKeywords');
32 $color = trim($color);
33 if ($color === '') {
34 return false;
37 $lower = strtolower($color);
38 if (isset($colors[$lower])) {
39 return $colors[$lower];
42 if (preg_match('#(rgb|rgba|hsl|hsla)\(#', $color, $matches) === 1) {
43 $length = strlen($color);
44 if (strpos($color, ')') !== $length - 1) {
45 return false;
48 // get used function : rgb, rgba, hsl or hsla
49 $function = $matches[1];
51 $parameters_size = 3;
52 $alpha_channel = false;
53 if (substr($function, -1) === 'a') {
54 $parameters_size = 4;
55 $alpha_channel = true;
59 * Allowed types for values :
60 * parameter_position => [type => max_value]
62 $allowed_types = array(
63 1 => array('percentage' => 100, 'integer' => 255),
64 2 => array('percentage' => 100, 'integer' => 255),
65 3 => array('percentage' => 100, 'integer' => 255),
67 $allow_different_types = false;
69 if (strpos($function, 'hsl') !== false) {
70 $allowed_types = array(
71 1 => array('integer' => 360),
72 2 => array('percentage' => 100),
73 3 => array('percentage' => 100),
75 $allow_different_types = true;
78 $values = trim(str_replace($function, '', $color), ' ()');
80 $parts = explode(',', $values);
81 if (count($parts) !== $parameters_size) {
82 return false;
85 $type = false;
86 $new_parts = array();
87 $i = 0;
89 foreach ($parts as $part) {
90 $i++;
91 $part = trim($part);
93 if ($part === '') {
94 return false;
97 // different check for alpha channel
98 if ($alpha_channel === true && $i === count($parts)) {
99 $result = $this->alpha->validate($part, $config, $context);
101 if ($result === false) {
102 return false;
105 $new_parts[] = (string)$result;
106 continue;
109 if (substr($part, -1) === '%') {
110 $current_type = 'percentage';
111 } else {
112 $current_type = 'integer';
115 if (!array_key_exists($current_type, $allowed_types[$i])) {
116 return false;
119 if (!$type) {
120 $type = $current_type;
123 if ($allow_different_types === false && $type != $current_type) {
124 return false;
127 $max_value = $allowed_types[$i][$current_type];
129 if ($current_type == 'integer') {
130 // Return value between range 0 -> $max_value
131 $new_parts[] = (int)max(min($part, $max_value), 0);
132 } elseif ($current_type == 'percentage') {
133 $new_parts[] = (float)max(min(rtrim($part, '%'), $max_value), 0) . '%';
137 $new_values = implode(',', $new_parts);
139 $color = $function . '(' . $new_values . ')';
140 } else {
141 // hexadecimal handling
142 if ($color[0] === '#') {
143 $hex = substr($color, 1);
144 } else {
145 $hex = $color;
146 $color = '#' . $color;
148 $length = strlen($hex);
149 if ($length !== 3 && $length !== 6) {
150 return false;
152 if (!ctype_xdigit($hex)) {
153 return false;
156 return $color;
161 // vim: et sw=4 sts=4