1: | <?php
|
2: |
|
3: | |
4: | |
5: |
|
6: | class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
|
7: | {
|
8: |
|
9: | |
10: | |
11: |
|
12: | protected $alpha;
|
13: |
|
14: | public function __construct()
|
15: | {
|
16: | $this->alpha = new HTMLPurifier_AttrDef_CSS_AlphaValue();
|
17: | }
|
18: |
|
19: | |
20: | |
21: | |
22: | |
23: | |
24: |
|
25: | public function validate($color, $config, $context)
|
26: | {
|
27: | static $colors = null;
|
28: | if ($colors === null) {
|
29: | $colors = $config->get('Core.ColorKeywords');
|
30: | }
|
31: |
|
32: | $color = trim($color);
|
33: | if ($color === '') {
|
34: | return false;
|
35: | }
|
36: |
|
37: | $lower = strtolower($color);
|
38: | if (isset($colors[$lower])) {
|
39: | return $colors[$lower];
|
40: | }
|
41: |
|
42: | if (preg_match('#(rgb|rgba|hsl|hsla)\(#', $color, $matches) === 1) {
|
43: | $length = strlen($color);
|
44: | if (strpos($color, ')') !== $length - 1) {
|
45: | return false;
|
46: | }
|
47: |
|
48: |
|
49: | $function = $matches[1];
|
50: |
|
51: | $parameters_size = 3;
|
52: | $alpha_channel = false;
|
53: | if (substr($function, -1) === 'a') {
|
54: | $parameters_size = 4;
|
55: | $alpha_channel = true;
|
56: | }
|
57: |
|
58: | |
59: | |
60: | |
61: |
|
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),
|
66: | );
|
67: | $allow_different_types = false;
|
68: |
|
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),
|
74: | );
|
75: | $allow_different_types = true;
|
76: | }
|
77: |
|
78: | $values = trim(str_replace($function, '', $color), ' ()');
|
79: |
|
80: | $parts = explode(',', $values);
|
81: | if (count($parts) !== $parameters_size) {
|
82: | return false;
|
83: | }
|
84: |
|
85: | $type = false;
|
86: | $new_parts = array();
|
87: | $i = 0;
|
88: |
|
89: | foreach ($parts as $part) {
|
90: | $i++;
|
91: | $part = trim($part);
|
92: |
|
93: | if ($part === '') {
|
94: | return false;
|
95: | }
|
96: |
|
97: |
|
98: | if ($alpha_channel === true && $i === count($parts)) {
|
99: | $result = $this->alpha->validate($part, $config, $context);
|
100: |
|
101: | if ($result === false) {
|
102: | return false;
|
103: | }
|
104: |
|
105: | $new_parts[] = (string)$result;
|
106: | continue;
|
107: | }
|
108: |
|
109: | if (substr($part, -1) === '%') {
|
110: | $current_type = 'percentage';
|
111: | } else {
|
112: | $current_type = 'integer';
|
113: | }
|
114: |
|
115: | if (!array_key_exists($current_type, $allowed_types[$i])) {
|
116: | return false;
|
117: | }
|
118: |
|
119: | if (!$type) {
|
120: | $type = $current_type;
|
121: | }
|
122: |
|
123: | if ($allow_different_types === false && $type != $current_type) {
|
124: | return false;
|
125: | }
|
126: |
|
127: | $max_value = $allowed_types[$i][$current_type];
|
128: |
|
129: | if ($current_type == 'integer') {
|
130: |
|
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) . '%';
|
134: | }
|
135: | }
|
136: |
|
137: | $new_values = implode(',', $new_parts);
|
138: |
|
139: | $color = $function . '(' . $new_values . ')';
|
140: | } else {
|
141: |
|
142: | if ($color[0] === '#') {
|
143: | $hex = substr($color, 1);
|
144: | } else {
|
145: | $hex = $color;
|
146: | $color = '#' . $color;
|
147: | }
|
148: | $length = strlen($hex);
|
149: | if ($length !== 3 && $length !== 6) {
|
150: | return false;
|
151: | }
|
152: | if (!ctype_xdigit($hex)) {
|
153: | return false;
|
154: | }
|
155: | }
|
156: | return $color;
|
157: | }
|
158: |
|
159: | }
|
160: |
|
161: |
|
162: | |