diff options
Diffstat (limited to 'inc/3rdparty/htmlpurifier/HTMLPurifier/CSSDefinition.php')
-rw-r--r-- | inc/3rdparty/htmlpurifier/HTMLPurifier/CSSDefinition.php | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/CSSDefinition.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/CSSDefinition.php new file mode 100644 index 00000000..18b05f3e --- /dev/null +++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/CSSDefinition.php | |||
@@ -0,0 +1,474 @@ | |||
1 | <?php | ||
2 | |||
3 | /** | ||
4 | * Defines allowed CSS attributes and what their values are. | ||
5 | * @see HTMLPurifier_HTMLDefinition | ||
6 | */ | ||
7 | class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition | ||
8 | { | ||
9 | |||
10 | public $type = 'CSS'; | ||
11 | |||
12 | /** | ||
13 | * Assoc array of attribute name to definition object. | ||
14 | * @type HTMLPurifier_AttrDef[] | ||
15 | */ | ||
16 | public $info = array(); | ||
17 | |||
18 | /** | ||
19 | * Constructs the info array. The meat of this class. | ||
20 | * @param HTMLPurifier_Config $config | ||
21 | */ | ||
22 | protected function doSetup($config) | ||
23 | { | ||
24 | $this->info['text-align'] = new HTMLPurifier_AttrDef_Enum( | ||
25 | array('left', 'right', 'center', 'justify'), | ||
26 | false | ||
27 | ); | ||
28 | |||
29 | $border_style = | ||
30 | $this->info['border-bottom-style'] = | ||
31 | $this->info['border-right-style'] = | ||
32 | $this->info['border-left-style'] = | ||
33 | $this->info['border-top-style'] = new HTMLPurifier_AttrDef_Enum( | ||
34 | array( | ||
35 | 'none', | ||
36 | 'hidden', | ||
37 | 'dotted', | ||
38 | 'dashed', | ||
39 | 'solid', | ||
40 | 'double', | ||
41 | 'groove', | ||
42 | 'ridge', | ||
43 | 'inset', | ||
44 | 'outset' | ||
45 | ), | ||
46 | false | ||
47 | ); | ||
48 | |||
49 | $this->info['border-style'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_style); | ||
50 | |||
51 | $this->info['clear'] = new HTMLPurifier_AttrDef_Enum( | ||
52 | array('none', 'left', 'right', 'both'), | ||
53 | false | ||
54 | ); | ||
55 | $this->info['float'] = new HTMLPurifier_AttrDef_Enum( | ||
56 | array('none', 'left', 'right'), | ||
57 | false | ||
58 | ); | ||
59 | $this->info['font-style'] = new HTMLPurifier_AttrDef_Enum( | ||
60 | array('normal', 'italic', 'oblique'), | ||
61 | false | ||
62 | ); | ||
63 | $this->info['font-variant'] = new HTMLPurifier_AttrDef_Enum( | ||
64 | array('normal', 'small-caps'), | ||
65 | false | ||
66 | ); | ||
67 | |||
68 | $uri_or_none = new HTMLPurifier_AttrDef_CSS_Composite( | ||
69 | array( | ||
70 | new HTMLPurifier_AttrDef_Enum(array('none')), | ||
71 | new HTMLPurifier_AttrDef_CSS_URI() | ||
72 | ) | ||
73 | ); | ||
74 | |||
75 | $this->info['list-style-position'] = new HTMLPurifier_AttrDef_Enum( | ||
76 | array('inside', 'outside'), | ||
77 | false | ||
78 | ); | ||
79 | $this->info['list-style-type'] = new HTMLPurifier_AttrDef_Enum( | ||
80 | array( | ||
81 | 'disc', | ||
82 | 'circle', | ||
83 | 'square', | ||
84 | 'decimal', | ||
85 | 'lower-roman', | ||
86 | 'upper-roman', | ||
87 | 'lower-alpha', | ||
88 | 'upper-alpha', | ||
89 | 'none' | ||
90 | ), | ||
91 | false | ||
92 | ); | ||
93 | $this->info['list-style-image'] = $uri_or_none; | ||
94 | |||
95 | $this->info['list-style'] = new HTMLPurifier_AttrDef_CSS_ListStyle($config); | ||
96 | |||
97 | $this->info['text-transform'] = new HTMLPurifier_AttrDef_Enum( | ||
98 | array('capitalize', 'uppercase', 'lowercase', 'none'), | ||
99 | false | ||
100 | ); | ||
101 | $this->info['color'] = new HTMLPurifier_AttrDef_CSS_Color(); | ||
102 | |||
103 | $this->info['background-image'] = $uri_or_none; | ||
104 | $this->info['background-repeat'] = new HTMLPurifier_AttrDef_Enum( | ||
105 | array('repeat', 'repeat-x', 'repeat-y', 'no-repeat') | ||
106 | ); | ||
107 | $this->info['background-attachment'] = new HTMLPurifier_AttrDef_Enum( | ||
108 | array('scroll', 'fixed') | ||
109 | ); | ||
110 | $this->info['background-position'] = new HTMLPurifier_AttrDef_CSS_BackgroundPosition(); | ||
111 | |||
112 | $border_color = | ||
113 | $this->info['border-top-color'] = | ||
114 | $this->info['border-bottom-color'] = | ||
115 | $this->info['border-left-color'] = | ||
116 | $this->info['border-right-color'] = | ||
117 | $this->info['background-color'] = new HTMLPurifier_AttrDef_CSS_Composite( | ||
118 | array( | ||
119 | new HTMLPurifier_AttrDef_Enum(array('transparent')), | ||
120 | new HTMLPurifier_AttrDef_CSS_Color() | ||
121 | ) | ||
122 | ); | ||
123 | |||
124 | $this->info['background'] = new HTMLPurifier_AttrDef_CSS_Background($config); | ||
125 | |||
126 | $this->info['border-color'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_color); | ||
127 | |||
128 | $border_width = | ||
129 | $this->info['border-top-width'] = | ||
130 | $this->info['border-bottom-width'] = | ||
131 | $this->info['border-left-width'] = | ||
132 | $this->info['border-right-width'] = new HTMLPurifier_AttrDef_CSS_Composite( | ||
133 | array( | ||
134 | new HTMLPurifier_AttrDef_Enum(array('thin', 'medium', 'thick')), | ||
135 | new HTMLPurifier_AttrDef_CSS_Length('0') //disallow negative | ||
136 | ) | ||
137 | ); | ||
138 | |||
139 | $this->info['border-width'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_width); | ||
140 | |||
141 | $this->info['letter-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite( | ||
142 | array( | ||
143 | new HTMLPurifier_AttrDef_Enum(array('normal')), | ||
144 | new HTMLPurifier_AttrDef_CSS_Length() | ||
145 | ) | ||
146 | ); | ||
147 | |||
148 | $this->info['word-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite( | ||
149 | array( | ||
150 | new HTMLPurifier_AttrDef_Enum(array('normal')), | ||
151 | new HTMLPurifier_AttrDef_CSS_Length() | ||
152 | ) | ||
153 | ); | ||
154 | |||
155 | $this->info['font-size'] = new HTMLPurifier_AttrDef_CSS_Composite( | ||
156 | array( | ||
157 | new HTMLPurifier_AttrDef_Enum( | ||
158 | array( | ||
159 | 'xx-small', | ||
160 | 'x-small', | ||
161 | 'small', | ||
162 | 'medium', | ||
163 | 'large', | ||
164 | 'x-large', | ||
165 | 'xx-large', | ||
166 | 'larger', | ||
167 | 'smaller' | ||
168 | ) | ||
169 | ), | ||
170 | new HTMLPurifier_AttrDef_CSS_Percentage(), | ||
171 | new HTMLPurifier_AttrDef_CSS_Length() | ||
172 | ) | ||
173 | ); | ||
174 | |||
175 | $this->info['line-height'] = new HTMLPurifier_AttrDef_CSS_Composite( | ||
176 | array( | ||
177 | new HTMLPurifier_AttrDef_Enum(array('normal')), | ||
178 | new HTMLPurifier_AttrDef_CSS_Number(true), // no negatives | ||
179 | new HTMLPurifier_AttrDef_CSS_Length('0'), | ||
180 | new HTMLPurifier_AttrDef_CSS_Percentage(true) | ||
181 | ) | ||
182 | ); | ||
183 | |||
184 | $margin = | ||
185 | $this->info['margin-top'] = | ||
186 | $this->info['margin-bottom'] = | ||
187 | $this->info['margin-left'] = | ||
188 | $this->info['margin-right'] = new HTMLPurifier_AttrDef_CSS_Composite( | ||
189 | array( | ||
190 | new HTMLPurifier_AttrDef_CSS_Length(), | ||
191 | new HTMLPurifier_AttrDef_CSS_Percentage(), | ||
192 | new HTMLPurifier_AttrDef_Enum(array('auto')) | ||
193 | ) | ||
194 | ); | ||
195 | |||
196 | $this->info['margin'] = new HTMLPurifier_AttrDef_CSS_Multiple($margin); | ||
197 | |||
198 | // non-negative | ||
199 | $padding = | ||
200 | $this->info['padding-top'] = | ||
201 | $this->info['padding-bottom'] = | ||
202 | $this->info['padding-left'] = | ||
203 | $this->info['padding-right'] = new HTMLPurifier_AttrDef_CSS_Composite( | ||
204 | array( | ||
205 | new HTMLPurifier_AttrDef_CSS_Length('0'), | ||
206 | new HTMLPurifier_AttrDef_CSS_Percentage(true) | ||
207 | ) | ||
208 | ); | ||
209 | |||
210 | $this->info['padding'] = new HTMLPurifier_AttrDef_CSS_Multiple($padding); | ||
211 | |||
212 | $this->info['text-indent'] = new HTMLPurifier_AttrDef_CSS_Composite( | ||
213 | array( | ||
214 | new HTMLPurifier_AttrDef_CSS_Length(), | ||
215 | new HTMLPurifier_AttrDef_CSS_Percentage() | ||
216 | ) | ||
217 | ); | ||
218 | |||
219 | $trusted_wh = new HTMLPurifier_AttrDef_CSS_Composite( | ||
220 | array( | ||
221 | new HTMLPurifier_AttrDef_CSS_Length('0'), | ||
222 | new HTMLPurifier_AttrDef_CSS_Percentage(true), | ||
223 | new HTMLPurifier_AttrDef_Enum(array('auto')) | ||
224 | ) | ||
225 | ); | ||
226 | $max = $config->get('CSS.MaxImgLength'); | ||
227 | |||
228 | $this->info['width'] = | ||
229 | $this->info['height'] = | ||
230 | $max === null ? | ||
231 | $trusted_wh : | ||
232 | new HTMLPurifier_AttrDef_Switch( | ||
233 | 'img', | ||
234 | // For img tags: | ||
235 | new HTMLPurifier_AttrDef_CSS_Composite( | ||
236 | array( | ||
237 | new HTMLPurifier_AttrDef_CSS_Length('0', $max), | ||
238 | new HTMLPurifier_AttrDef_Enum(array('auto')) | ||
239 | ) | ||
240 | ), | ||
241 | // For everyone else: | ||
242 | $trusted_wh | ||
243 | ); | ||
244 | |||
245 | $this->info['text-decoration'] = new HTMLPurifier_AttrDef_CSS_TextDecoration(); | ||
246 | |||
247 | $this->info['font-family'] = new HTMLPurifier_AttrDef_CSS_FontFamily(); | ||
248 | |||
249 | // this could use specialized code | ||
250 | $this->info['font-weight'] = new HTMLPurifier_AttrDef_Enum( | ||
251 | array( | ||
252 | 'normal', | ||
253 | 'bold', | ||
254 | 'bolder', | ||
255 | 'lighter', | ||
256 | '100', | ||
257 | '200', | ||
258 | '300', | ||
259 | '400', | ||
260 | '500', | ||
261 | '600', | ||
262 | '700', | ||
263 | '800', | ||
264 | '900' | ||
265 | ), | ||
266 | false | ||
267 | ); | ||
268 | |||
269 | // MUST be called after other font properties, as it references | ||
270 | // a CSSDefinition object | ||
271 | $this->info['font'] = new HTMLPurifier_AttrDef_CSS_Font($config); | ||
272 | |||
273 | // same here | ||
274 | $this->info['border'] = | ||
275 | $this->info['border-bottom'] = | ||
276 | $this->info['border-top'] = | ||
277 | $this->info['border-left'] = | ||
278 | $this->info['border-right'] = new HTMLPurifier_AttrDef_CSS_Border($config); | ||
279 | |||
280 | $this->info['border-collapse'] = new HTMLPurifier_AttrDef_Enum( | ||
281 | array('collapse', 'separate') | ||
282 | ); | ||
283 | |||
284 | $this->info['caption-side'] = new HTMLPurifier_AttrDef_Enum( | ||
285 | array('top', 'bottom') | ||
286 | ); | ||
287 | |||
288 | $this->info['table-layout'] = new HTMLPurifier_AttrDef_Enum( | ||
289 | array('auto', 'fixed') | ||
290 | ); | ||
291 | |||
292 | $this->info['vertical-align'] = new HTMLPurifier_AttrDef_CSS_Composite( | ||
293 | array( | ||
294 | new HTMLPurifier_AttrDef_Enum( | ||
295 | array( | ||
296 | 'baseline', | ||
297 | 'sub', | ||
298 | 'super', | ||
299 | 'top', | ||
300 | 'text-top', | ||
301 | 'middle', | ||
302 | 'bottom', | ||
303 | 'text-bottom' | ||
304 | ) | ||
305 | ), | ||
306 | new HTMLPurifier_AttrDef_CSS_Length(), | ||
307 | new HTMLPurifier_AttrDef_CSS_Percentage() | ||
308 | ) | ||
309 | ); | ||
310 | |||
311 | $this->info['border-spacing'] = new HTMLPurifier_AttrDef_CSS_Multiple(new HTMLPurifier_AttrDef_CSS_Length(), 2); | ||
312 | |||
313 | // These CSS properties don't work on many browsers, but we live | ||
314 | // in THE FUTURE! | ||
315 | $this->info['white-space'] = new HTMLPurifier_AttrDef_Enum( | ||
316 | array('nowrap', 'normal', 'pre', 'pre-wrap', 'pre-line') | ||
317 | ); | ||
318 | |||
319 | if ($config->get('CSS.Proprietary')) { | ||
320 | $this->doSetupProprietary($config); | ||
321 | } | ||
322 | |||
323 | if ($config->get('CSS.AllowTricky')) { | ||
324 | $this->doSetupTricky($config); | ||
325 | } | ||
326 | |||
327 | if ($config->get('CSS.Trusted')) { | ||
328 | $this->doSetupTrusted($config); | ||
329 | } | ||
330 | |||
331 | $allow_important = $config->get('CSS.AllowImportant'); | ||
332 | // wrap all attr-defs with decorator that handles !important | ||
333 | foreach ($this->info as $k => $v) { | ||
334 | $this->info[$k] = new HTMLPurifier_AttrDef_CSS_ImportantDecorator($v, $allow_important); | ||
335 | } | ||
336 | |||
337 | $this->setupConfigStuff($config); | ||
338 | } | ||
339 | |||
340 | /** | ||
341 | * @param HTMLPurifier_Config $config | ||
342 | */ | ||
343 | protected function doSetupProprietary($config) | ||
344 | { | ||
345 | // Internet Explorer only scrollbar colors | ||
346 | $this->info['scrollbar-arrow-color'] = new HTMLPurifier_AttrDef_CSS_Color(); | ||
347 | $this->info['scrollbar-base-color'] = new HTMLPurifier_AttrDef_CSS_Color(); | ||
348 | $this->info['scrollbar-darkshadow-color'] = new HTMLPurifier_AttrDef_CSS_Color(); | ||
349 | $this->info['scrollbar-face-color'] = new HTMLPurifier_AttrDef_CSS_Color(); | ||
350 | $this->info['scrollbar-highlight-color'] = new HTMLPurifier_AttrDef_CSS_Color(); | ||
351 | $this->info['scrollbar-shadow-color'] = new HTMLPurifier_AttrDef_CSS_Color(); | ||
352 | |||
353 | // technically not proprietary, but CSS3, and no one supports it | ||
354 | $this->info['opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue(); | ||
355 | $this->info['-moz-opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue(); | ||
356 | $this->info['-khtml-opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue(); | ||
357 | |||
358 | // only opacity, for now | ||
359 | $this->info['filter'] = new HTMLPurifier_AttrDef_CSS_Filter(); | ||
360 | |||
361 | // more CSS3 | ||
362 | $this->info['page-break-after'] = | ||
363 | $this->info['page-break-before'] = new HTMLPurifier_AttrDef_Enum( | ||
364 | array( | ||
365 | 'auto', | ||
366 | 'always', | ||
367 | 'avoid', | ||
368 | 'left', | ||
369 | 'right' | ||
370 | ) | ||
371 | ); | ||
372 | $this->info['page-break-inside'] = new HTMLPurifier_AttrDef_Enum(array('auto', 'avoid')); | ||
373 | |||
374 | } | ||
375 | |||
376 | /** | ||
377 | * @param HTMLPurifier_Config $config | ||
378 | */ | ||
379 | protected function doSetupTricky($config) | ||
380 | { | ||
381 | $this->info['display'] = new HTMLPurifier_AttrDef_Enum( | ||
382 | array( | ||
383 | 'inline', | ||
384 | 'block', | ||
385 | 'list-item', | ||
386 | 'run-in', | ||
387 | 'compact', | ||
388 | 'marker', | ||
389 | 'table', | ||
390 | 'inline-block', | ||
391 | 'inline-table', | ||
392 | 'table-row-group', | ||
393 | 'table-header-group', | ||
394 | 'table-footer-group', | ||
395 | 'table-row', | ||
396 | 'table-column-group', | ||
397 | 'table-column', | ||
398 | 'table-cell', | ||
399 | 'table-caption', | ||
400 | 'none' | ||
401 | ) | ||
402 | ); | ||
403 | $this->info['visibility'] = new HTMLPurifier_AttrDef_Enum( | ||
404 | array('visible', 'hidden', 'collapse') | ||
405 | ); | ||
406 | $this->info['overflow'] = new HTMLPurifier_AttrDef_Enum(array('visible', 'hidden', 'auto', 'scroll')); | ||
407 | } | ||
408 | |||
409 | /** | ||
410 | * @param HTMLPurifier_Config $config | ||
411 | */ | ||
412 | protected function doSetupTrusted($config) | ||
413 | { | ||
414 | $this->info['position'] = new HTMLPurifier_AttrDef_Enum( | ||
415 | array('static', 'relative', 'absolute', 'fixed') | ||
416 | ); | ||
417 | $this->info['top'] = | ||
418 | $this->info['left'] = | ||
419 | $this->info['right'] = | ||
420 | $this->info['bottom'] = new HTMLPurifier_AttrDef_CSS_Composite( | ||
421 | array( | ||
422 | new HTMLPurifier_AttrDef_CSS_Length(), | ||
423 | new HTMLPurifier_AttrDef_CSS_Percentage(), | ||
424 | new HTMLPurifier_AttrDef_Enum(array('auto')), | ||
425 | ) | ||
426 | ); | ||
427 | $this->info['z-index'] = new HTMLPurifier_AttrDef_CSS_Composite( | ||
428 | array( | ||
429 | new HTMLPurifier_AttrDef_Integer(), | ||
430 | new HTMLPurifier_AttrDef_Enum(array('auto')), | ||
431 | ) | ||
432 | ); | ||
433 | } | ||
434 | |||
435 | /** | ||
436 | * Performs extra config-based processing. Based off of | ||
437 | * HTMLPurifier_HTMLDefinition. | ||
438 | * @param HTMLPurifier_Config $config | ||
439 | * @todo Refactor duplicate elements into common class (probably using | ||
440 | * composition, not inheritance). | ||
441 | */ | ||
442 | protected function setupConfigStuff($config) | ||
443 | { | ||
444 | // setup allowed elements | ||
445 | $support = "(for information on implementing this, see the " . | ||
446 | "support forums) "; | ||
447 | $allowed_properties = $config->get('CSS.AllowedProperties'); | ||
448 | if ($allowed_properties !== null) { | ||
449 | foreach ($this->info as $name => $d) { | ||
450 | if (!isset($allowed_properties[$name])) { | ||
451 | unset($this->info[$name]); | ||
452 | } | ||
453 | unset($allowed_properties[$name]); | ||
454 | } | ||
455 | // emit errors | ||
456 | foreach ($allowed_properties as $name => $d) { | ||
457 | // :TODO: Is this htmlspecialchars() call really necessary? | ||
458 | $name = htmlspecialchars($name); | ||
459 | trigger_error("Style attribute '$name' is not supported $support", E_USER_WARNING); | ||
460 | } | ||
461 | } | ||
462 | |||
463 | $forbidden_properties = $config->get('CSS.ForbiddenProperties'); | ||
464 | if ($forbidden_properties !== null) { | ||
465 | foreach ($this->info as $name => $d) { | ||
466 | if (isset($forbidden_properties[$name])) { | ||
467 | unset($this->info[$name]); | ||
468 | } | ||
469 | } | ||
470 | } | ||
471 | } | ||
472 | } | ||
473 | |||
474 | // vim: et sw=4 sts=4 | ||