Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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 = [];
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
            ['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
                [
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
            ['none', 'left', 'right', 'both'],
53
            false
54
        );
55
        $this->info['float'] = new HTMLPurifier_AttrDef_Enum(
56
            ['none', 'left', 'right'],
57
            false
58
        );
59
        $this->info['font-style'] = new HTMLPurifier_AttrDef_Enum(
60
            ['normal', 'italic', 'oblique'],
61
            false
62
        );
63
        $this->info['font-variant'] = new HTMLPurifier_AttrDef_Enum(
64
            ['normal', 'small-caps'],
65
            false
66
        );
67
 
68
        $uri_or_none = new HTMLPurifier_AttrDef_CSS_Composite(
69
            [
70
                new HTMLPurifier_AttrDef_Enum(['none']),
71
                new HTMLPurifier_AttrDef_CSS_URI()
72
            ]
73
        );
74
 
75
        $this->info['list-style-position'] = new HTMLPurifier_AttrDef_Enum(
76
            ['inside', 'outside'],
77
            false
78
        );
79
        $this->info['list-style-type'] = new HTMLPurifier_AttrDef_Enum(
80
            [
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
            ['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
            ['repeat', 'repeat-x', 'repeat-y', 'no-repeat']
106
        );
107
        $this->info['background-attachment'] = new HTMLPurifier_AttrDef_Enum(
108
            ['scroll', 'fixed']
109
        );
110
        $this->info['background-position'] = new HTMLPurifier_AttrDef_CSS_BackgroundPosition();
111
 
112
        $this->info['background-size'] = new HTMLPurifier_AttrDef_CSS_Composite(
113
            [
114
                new HTMLPurifier_AttrDef_Enum(
115
                    [
116
                        'auto',
117
                        'cover',
118
                        'contain',
119
                        'initial',
120
                        'inherit',
121
                    ]
122
                ),
123
                new HTMLPurifier_AttrDef_CSS_Percentage(),
124
                new HTMLPurifier_AttrDef_CSS_Length()
125
            ]
126
        );
127
 
128
        $border_color =
129
            $this->info['border-top-color'] =
130
            $this->info['border-bottom-color'] =
131
            $this->info['border-left-color'] =
132
            $this->info['border-right-color'] =
133
            $this->info['background-color'] = new HTMLPurifier_AttrDef_CSS_Composite(
134
                [
135
                    new HTMLPurifier_AttrDef_Enum(['transparent']),
136
                    new HTMLPurifier_AttrDef_CSS_Color()
137
                ]
138
            );
139
 
140
        $this->info['background'] = new HTMLPurifier_AttrDef_CSS_Background($config);
141
 
142
        $this->info['border-color'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_color);
143
 
144
        $border_width =
145
            $this->info['border-top-width'] =
146
            $this->info['border-bottom-width'] =
147
            $this->info['border-left-width'] =
148
            $this->info['border-right-width'] = new HTMLPurifier_AttrDef_CSS_Composite(
149
                [
150
                    new HTMLPurifier_AttrDef_Enum(['thin', 'medium', 'thick']),
151
                    new HTMLPurifier_AttrDef_CSS_Length('0') //disallow negative
152
                ]
153
            );
154
 
155
        $this->info['border-width'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_width);
156
 
157
        $this->info['letter-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite(
158
            [
159
                new HTMLPurifier_AttrDef_Enum(['normal']),
160
                new HTMLPurifier_AttrDef_CSS_Length()
161
            ]
162
        );
163
 
164
        $this->info['word-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite(
165
            [
166
                new HTMLPurifier_AttrDef_Enum(['normal']),
167
                new HTMLPurifier_AttrDef_CSS_Length()
168
            ]
169
        );
170
 
171
        $this->info['font-size'] = new HTMLPurifier_AttrDef_CSS_Composite(
172
            [
173
                new HTMLPurifier_AttrDef_Enum(
174
                    [
175
                        'xx-small',
176
                        'x-small',
177
                        'small',
178
                        'medium',
179
                        'large',
180
                        'x-large',
181
                        'xx-large',
182
                        'larger',
183
                        'smaller'
184
                    ]
185
                ),
186
                new HTMLPurifier_AttrDef_CSS_Percentage(),
187
                new HTMLPurifier_AttrDef_CSS_Length()
188
            ]
189
        );
190
 
191
        $this->info['line-height'] = new HTMLPurifier_AttrDef_CSS_Composite(
192
            [
193
                new HTMLPurifier_AttrDef_Enum(['normal']),
194
                new HTMLPurifier_AttrDef_CSS_Number(true), // no negatives
195
                new HTMLPurifier_AttrDef_CSS_Length('0'),
196
                new HTMLPurifier_AttrDef_CSS_Percentage(true)
197
            ]
198
        );
199
 
200
        $margin =
201
            $this->info['margin-top'] =
202
            $this->info['margin-bottom'] =
203
            $this->info['margin-left'] =
204
            $this->info['margin-right'] = new HTMLPurifier_AttrDef_CSS_Composite(
205
                [
206
                    new HTMLPurifier_AttrDef_CSS_Length(),
207
                    new HTMLPurifier_AttrDef_CSS_Percentage(),
208
                    new HTMLPurifier_AttrDef_Enum(['auto'])
209
                ]
210
            );
211
 
212
        $this->info['margin'] = new HTMLPurifier_AttrDef_CSS_Multiple($margin);
213
 
214
        // non-negative
215
        $padding =
216
            $this->info['padding-top'] =
217
            $this->info['padding-bottom'] =
218
            $this->info['padding-left'] =
219
            $this->info['padding-right'] = new HTMLPurifier_AttrDef_CSS_Composite(
220
                [
221
                    new HTMLPurifier_AttrDef_CSS_Length('0'),
222
                    new HTMLPurifier_AttrDef_CSS_Percentage(true)
223
                ]
224
            );
225
 
226
        $this->info['padding'] = new HTMLPurifier_AttrDef_CSS_Multiple($padding);
227
 
228
        $this->info['text-indent'] = new HTMLPurifier_AttrDef_CSS_Composite(
229
            [
230
                new HTMLPurifier_AttrDef_CSS_Length(),
231
                new HTMLPurifier_AttrDef_CSS_Percentage()
232
            ]
233
        );
234
 
235
        $trusted_wh = new HTMLPurifier_AttrDef_CSS_Composite(
236
            [
237
                new HTMLPurifier_AttrDef_CSS_Length('0'),
238
                new HTMLPurifier_AttrDef_CSS_Percentage(true),
239
                new HTMLPurifier_AttrDef_Enum(['auto', 'initial', 'inherit'])
240
            ]
241
        );
242
        $trusted_min_wh = new HTMLPurifier_AttrDef_CSS_Composite(
243
            [
244
                new HTMLPurifier_AttrDef_CSS_Length('0'),
245
                new HTMLPurifier_AttrDef_CSS_Percentage(true),
246
                new HTMLPurifier_AttrDef_Enum(['initial', 'inherit'])
247
            ]
248
        );
249
        $trusted_max_wh = new HTMLPurifier_AttrDef_CSS_Composite(
250
            [
251
                new HTMLPurifier_AttrDef_CSS_Length('0'),
252
                new HTMLPurifier_AttrDef_CSS_Percentage(true),
253
                new HTMLPurifier_AttrDef_Enum(['none', 'initial', 'inherit'])
254
            ]
255
        );
256
        $max = $config->get('CSS.MaxImgLength');
257
 
258
        $this->info['width'] =
259
        $this->info['height'] =
260
            $max === null ?
261
                $trusted_wh :
262
                new HTMLPurifier_AttrDef_Switch(
263
                    'img',
264
                    // For img tags:
265
                    new HTMLPurifier_AttrDef_CSS_Composite(
266
                        [
267
                            new HTMLPurifier_AttrDef_CSS_Length('0', $max),
268
                            new HTMLPurifier_AttrDef_Enum(['auto'])
269
                        ]
270
                    ),
271
                    // For everyone else:
272
                    $trusted_wh
273
                );
274
        $this->info['min-width'] =
275
        $this->info['min-height'] =
276
            $max === null ?
277
                $trusted_min_wh :
278
                new HTMLPurifier_AttrDef_Switch(
279
                    'img',
280
                    // For img tags:
281
                    new HTMLPurifier_AttrDef_CSS_Composite(
282
                        [
283
                            new HTMLPurifier_AttrDef_CSS_Length('0', $max),
284
                            new HTMLPurifier_AttrDef_Enum(['initial', 'inherit'])
285
                        ]
286
                    ),
287
                    // For everyone else:
288
                    $trusted_min_wh
289
                );
290
        $this->info['max-width'] =
291
        $this->info['max-height'] =
292
            $max === null ?
293
                $trusted_max_wh :
294
                new HTMLPurifier_AttrDef_Switch(
295
                    'img',
296
                    // For img tags:
297
                    new HTMLPurifier_AttrDef_CSS_Composite(
298
                        [
299
                            new HTMLPurifier_AttrDef_CSS_Length('0', $max),
300
                            new HTMLPurifier_AttrDef_Enum(['none', 'initial', 'inherit'])
301
                        ]
302
                    ),
303
                    // For everyone else:
304
                    $trusted_max_wh
305
                );
306
 
307
        // text-decoration and related shorthands
308
        $this->info['text-decoration'] = new HTMLPurifier_AttrDef_CSS_TextDecoration();
309
 
310
        $this->info['text-decoration-line'] = new HTMLPurifier_AttrDef_Enum(
311
            ['none', 'underline', 'overline', 'line-through', 'initial', 'inherit']
312
        );
313
 
314
        $this->info['text-decoration-style'] = new HTMLPurifier_AttrDef_Enum(
315
            ['solid', 'double', 'dotted', 'dashed', 'wavy', 'initial', 'inherit']
316
        );
317
 
318
        $this->info['text-decoration-color'] = new HTMLPurifier_AttrDef_CSS_Color();
319
 
320
        $this->info['text-decoration-thickness'] = new HTMLPurifier_AttrDef_CSS_Composite([
321
            new HTMLPurifier_AttrDef_CSS_Length(),
322
            new HTMLPurifier_AttrDef_CSS_Percentage(),
323
            new HTMLPurifier_AttrDef_Enum(['auto', 'from-font', 'initial', 'inherit'])
324
        ]);
325
 
326
        $this->info['font-family'] = new HTMLPurifier_AttrDef_CSS_FontFamily();
327
 
328
        // this could use specialized code
329
        $this->info['font-weight'] = new HTMLPurifier_AttrDef_Enum(
330
            [
331
                'normal',
332
                'bold',
333
                'bolder',
334
                'lighter',
335
                '100',
336
                '200',
337
                '300',
338
                '400',
339
                '500',
340
                '600',
341
                '700',
342
                '800',
343
                '900'
344
            ],
345
            false
346
        );
347
 
348
        // MUST be called after other font properties, as it references
349
        // a CSSDefinition object
350
        $this->info['font'] = new HTMLPurifier_AttrDef_CSS_Font($config);
351
 
352
        // same here
353
        $this->info['border'] =
354
        $this->info['border-bottom'] =
355
        $this->info['border-top'] =
356
        $this->info['border-left'] =
357
        $this->info['border-right'] = new HTMLPurifier_AttrDef_CSS_Border($config);
358
 
359
        $this->info['border-collapse'] = new HTMLPurifier_AttrDef_Enum(
360
            ['collapse', 'separate']
361
        );
362
 
363
        $this->info['caption-side'] = new HTMLPurifier_AttrDef_Enum(
364
            ['top', 'bottom']
365
        );
366
 
367
        $this->info['table-layout'] = new HTMLPurifier_AttrDef_Enum(
368
            ['auto', 'fixed']
369
        );
370
 
371
        $this->info['vertical-align'] = new HTMLPurifier_AttrDef_CSS_Composite(
372
            [
373
                new HTMLPurifier_AttrDef_Enum(
374
                    [
375
                        'baseline',
376
                        'sub',
377
                        'super',
378
                        'top',
379
                        'text-top',
380
                        'middle',
381
                        'bottom',
382
                        'text-bottom'
383
                    ]
384
                ),
385
                new HTMLPurifier_AttrDef_CSS_Length(),
386
                new HTMLPurifier_AttrDef_CSS_Percentage()
387
            ]
388
        );
389
 
390
        $this->info['border-spacing'] = new HTMLPurifier_AttrDef_CSS_Multiple(new HTMLPurifier_AttrDef_CSS_Length(), 2);
391
 
392
        // These CSS properties don't work on many browsers, but we live
393
        // in THE FUTURE!
394
        $this->info['white-space'] = new HTMLPurifier_AttrDef_Enum(
395
            ['nowrap', 'normal', 'pre', 'pre-wrap', 'pre-line']
396
        );
397
 
398
        if ($config->get('CSS.Proprietary')) {
399
            $this->doSetupProprietary($config);
400
        }
401
 
402
        if ($config->get('CSS.AllowTricky')) {
403
            $this->doSetupTricky($config);
404
        }
405
 
406
        if ($config->get('CSS.Trusted')) {
407
            $this->doSetupTrusted($config);
408
        }
409
 
410
        $allow_important = $config->get('CSS.AllowImportant');
411
        // wrap all attr-defs with decorator that handles !important
412
        foreach ($this->info as $k => $v) {
413
            $this->info[$k] = new HTMLPurifier_AttrDef_CSS_ImportantDecorator($v, $allow_important);
414
        }
415
 
416
        $this->setupConfigStuff($config);
417
    }
418
 
419
    /**
420
     * @param HTMLPurifier_Config $config
421
     */
422
    protected function doSetupProprietary($config)
423
    {
424
        // Internet Explorer only scrollbar colors
425
        $this->info['scrollbar-arrow-color'] = new HTMLPurifier_AttrDef_CSS_Color();
426
        $this->info['scrollbar-base-color'] = new HTMLPurifier_AttrDef_CSS_Color();
427
        $this->info['scrollbar-darkshadow-color'] = new HTMLPurifier_AttrDef_CSS_Color();
428
        $this->info['scrollbar-face-color'] = new HTMLPurifier_AttrDef_CSS_Color();
429
        $this->info['scrollbar-highlight-color'] = new HTMLPurifier_AttrDef_CSS_Color();
430
        $this->info['scrollbar-shadow-color'] = new HTMLPurifier_AttrDef_CSS_Color();
431
 
432
        // vendor specific prefixes of opacity
433
        $this->info['-moz-opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue();
434
        $this->info['-khtml-opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue();
435
 
436
        // only opacity, for now
437
        $this->info['filter'] = new HTMLPurifier_AttrDef_CSS_Filter();
438
 
439
        // more CSS3
440
        $this->info['page-break-after'] =
441
        $this->info['page-break-before'] = new HTMLPurifier_AttrDef_Enum(
442
            [
443
                'auto',
444
                'always',
445
                'avoid',
446
                'left',
447
                'right'
448
            ]
449
        );
450
        $this->info['page-break-inside'] = new HTMLPurifier_AttrDef_Enum(['auto', 'avoid']);
451
 
452
        $border_radius = new HTMLPurifier_AttrDef_CSS_Composite(
453
            [
454
                new HTMLPurifier_AttrDef_CSS_Percentage(true), // disallow negative
455
                new HTMLPurifier_AttrDef_CSS_Length('0') // disallow negative
456
            ]);
457
 
458
        $this->info['border-top-left-radius'] =
459
        $this->info['border-top-right-radius'] =
460
        $this->info['border-bottom-right-radius'] =
461
        $this->info['border-bottom-left-radius'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_radius, 2);
462
        // TODO: support SLASH syntax
463
        $this->info['border-radius'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_radius, 4);
464
 
465
    }
466
 
467
    /**
468
     * @param HTMLPurifier_Config $config
469
     */
470
    protected function doSetupTricky($config)
471
    {
472
        $this->info['display'] = new HTMLPurifier_AttrDef_Enum(
473
            [
474
                'inline',
475
                'block',
476
                'list-item',
477
                'run-in',
478
                'compact',
479
                'marker',
480
                'table',
481
                'inline-block',
482
                'inline-table',
483
                'table-row-group',
484
                'table-header-group',
485
                'table-footer-group',
486
                'table-row',
487
                'table-column-group',
488
                'table-column',
489
                'table-cell',
490
                'table-caption',
491
                'none'
492
            ]
493
        );
494
        $this->info['visibility'] = new HTMLPurifier_AttrDef_Enum(
495
            ['visible', 'hidden', 'collapse']
496
        );
497
        $this->info['overflow'] = new HTMLPurifier_AttrDef_Enum(['visible', 'hidden', 'auto', 'scroll']);
498
        $this->info['opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue();
499
    }
500
 
501
    /**
502
     * @param HTMLPurifier_Config $config
503
     */
504
    protected function doSetupTrusted($config)
505
    {
506
        $this->info['position'] = new HTMLPurifier_AttrDef_Enum(
507
            ['static', 'relative', 'absolute', 'fixed']
508
        );
509
        $this->info['top'] =
510
        $this->info['left'] =
511
        $this->info['right'] =
512
        $this->info['bottom'] = new HTMLPurifier_AttrDef_CSS_Composite(
513
            [
514
                new HTMLPurifier_AttrDef_CSS_Length(),
515
                new HTMLPurifier_AttrDef_CSS_Percentage(),
516
                new HTMLPurifier_AttrDef_Enum(['auto']),
517
            ]
518
        );
519
        $this->info['z-index'] = new HTMLPurifier_AttrDef_CSS_Composite(
520
            [
521
                new HTMLPurifier_AttrDef_Integer(),
522
                new HTMLPurifier_AttrDef_Enum(['auto']),
523
            ]
524
        );
525
    }
526
 
527
    /**
528
     * Performs extra config-based processing. Based off of
529
     * HTMLPurifier_HTMLDefinition.
530
     * @param HTMLPurifier_Config $config
531
     * @todo Refactor duplicate elements into common class (probably using
532
     *       composition, not inheritance).
533
     */
534
    protected function setupConfigStuff($config)
535
    {
536
        // setup allowed elements
537
        $support = "(for information on implementing this, see the " .
538
            "support forums) ";
539
        $allowed_properties = $config->get('CSS.AllowedProperties');
540
        if ($allowed_properties !== null) {
541
            foreach ($this->info as $name => $d) {
542
                if (!isset($allowed_properties[$name])) {
543
                    unset($this->info[$name]);
544
                }
545
                unset($allowed_properties[$name]);
546
            }
547
            // emit errors
548
            foreach ($allowed_properties as $name => $d) {
549
                // :TODO: Is this htmlspecialchars() call really necessary?
550
                $name = htmlspecialchars($name);
551
                trigger_error("Style attribute '$name' is not supported $support", E_USER_WARNING);
552
            }
553
        }
554
 
555
        $forbidden_properties = $config->get('CSS.ForbiddenProperties');
556
        if ($forbidden_properties !== null) {
557
            foreach ($this->info as $name => $d) {
558
                if (isset($forbidden_properties[$name])) {
559
                    unset($this->info[$name]);
560
                }
561
            }
562
        }
563
    }
564
}
565
 
566
// vim: et sw=4 sts=4