3
require_once 'HTMLPurifier/Definition.php';
5
require_once 'HTMLPurifier/AttrDef/CSS/Background.php';
6
require_once 'HTMLPurifier/AttrDef/CSS/BackgroundPosition.php';
7
require_once 'HTMLPurifier/AttrDef/CSS/Border.php';
8
require_once 'HTMLPurifier/AttrDef/CSS/Color.php';
9
require_once 'HTMLPurifier/AttrDef/CSS/Composite.php';
10
require_once 'HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php';
11
require_once 'HTMLPurifier/AttrDef/CSS/Font.php';
12
require_once 'HTMLPurifier/AttrDef/CSS/FontFamily.php';
13
require_once 'HTMLPurifier/AttrDef/CSS/Length.php';
14
require_once 'HTMLPurifier/AttrDef/CSS/ListStyle.php';
15
require_once 'HTMLPurifier/AttrDef/CSS/Multiple.php';
16
require_once 'HTMLPurifier/AttrDef/CSS/Percentage.php';
17
require_once 'HTMLPurifier/AttrDef/CSS/TextDecoration.php';
18
require_once 'HTMLPurifier/AttrDef/CSS/URI.php';
19
require_once 'HTMLPurifier/AttrDef/Enum.php';
20
require_once 'HTMLPurifier/AttrDef/Switch.php';
22
HTMLPurifier_ConfigSchema::define(
23
'CSS', 'DefinitionRev', 1, 'int', '
25
Revision identifier for your custom definition. See
26
%HTML.DefinitionRev for details. This directive has been available
31
HTMLPurifier_ConfigSchema::define(
32
'CSS', 'MaxImgLength', '1200px', 'string/null', '
34
This parameter sets the maximum allowed length on <code>img</code> tags,
35
effectively the <code>width</code> and <code>height</code> properties.
36
Only absolute units of measurement (in, pt, pc, mm, cm) and pixels (px) are allowed. This is
37
in place to prevent imagecrash attacks, disable with null at your own risk.
38
This directive is similar to %HTML.MaxImgLength, and both should be
39
concurrently edited, although there are
40
subtle differences in the input format (the CSS max is a number with
46
4
* Defines allowed CSS attributes and what their values are.
47
5
* @see HTMLPurifier_HTMLDefinition
49
7
class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
55
13
* Assoc array of attribute name to definition object.
15
public $info = array();
60
18
* Constructs the info array. The meat of this class.
62
function doSetup($config) {
20
protected function doSetup($config) {
64
22
$this->info['text-align'] = new HTMLPurifier_AttrDef_Enum(
65
23
array('left', 'right', 'center', 'justify'), false);
68
$this->info['border-bottom-style'] =
69
$this->info['border-right-style'] =
70
$this->info['border-left-style'] =
26
$this->info['border-bottom-style'] =
27
$this->info['border-right-style'] =
28
$this->info['border-left-style'] =
71
29
$this->info['border-top-style'] = new HTMLPurifier_AttrDef_Enum(
72
30
array('none', 'hidden', 'dotted', 'dashed', 'solid', 'double',
73
31
'groove', 'ridge', 'inset', 'outset'), false);
75
33
$this->info['border-style'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_style);
77
35
$this->info['clear'] = new HTMLPurifier_AttrDef_Enum(
78
36
array('none', 'left', 'right', 'both'), false);
79
37
$this->info['float'] = new HTMLPurifier_AttrDef_Enum(
82
40
array('normal', 'italic', 'oblique'), false);
83
41
$this->info['font-variant'] = new HTMLPurifier_AttrDef_Enum(
84
42
array('normal', 'small-caps'), false);
86
44
$uri_or_none = new HTMLPurifier_AttrDef_CSS_Composite(
88
46
new HTMLPurifier_AttrDef_Enum(array('none')),
89
47
new HTMLPurifier_AttrDef_CSS_URI()
93
51
$this->info['list-style-position'] = new HTMLPurifier_AttrDef_Enum(
94
52
array('inside', 'outside'), false);
95
53
$this->info['list-style-type'] = new HTMLPurifier_AttrDef_Enum(
96
54
array('disc', 'circle', 'square', 'decimal', 'lower-roman',
97
55
'upper-roman', 'lower-alpha', 'upper-alpha', 'none'), false);
98
56
$this->info['list-style-image'] = $uri_or_none;
100
58
$this->info['list-style'] = new HTMLPurifier_AttrDef_CSS_ListStyle($config);
102
60
$this->info['text-transform'] = new HTMLPurifier_AttrDef_Enum(
103
61
array('capitalize', 'uppercase', 'lowercase', 'none'), false);
104
62
$this->info['color'] = new HTMLPurifier_AttrDef_CSS_Color();
106
64
$this->info['background-image'] = $uri_or_none;
107
65
$this->info['background-repeat'] = new HTMLPurifier_AttrDef_Enum(
108
66
array('repeat', 'repeat-x', 'repeat-y', 'no-repeat')
111
69
array('scroll', 'fixed')
113
71
$this->info['background-position'] = new HTMLPurifier_AttrDef_CSS_BackgroundPosition();
116
$this->info['border-top-color'] =
117
$this->info['border-bottom-color'] =
118
$this->info['border-left-color'] =
119
$this->info['border-right-color'] =
74
$this->info['border-top-color'] =
75
$this->info['border-bottom-color'] =
76
$this->info['border-left-color'] =
77
$this->info['border-right-color'] =
120
78
$this->info['background-color'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
121
79
new HTMLPurifier_AttrDef_Enum(array('transparent')),
122
80
new HTMLPurifier_AttrDef_CSS_Color()
125
83
$this->info['background'] = new HTMLPurifier_AttrDef_CSS_Background($config);
127
85
$this->info['border-color'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_color);
130
$this->info['border-top-width'] =
131
$this->info['border-bottom-width'] =
132
$this->info['border-left-width'] =
88
$this->info['border-top-width'] =
89
$this->info['border-bottom-width'] =
90
$this->info['border-left-width'] =
133
91
$this->info['border-right-width'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
134
92
new HTMLPurifier_AttrDef_Enum(array('thin', 'medium', 'thick')),
135
93
new HTMLPurifier_AttrDef_CSS_Length('0') //disallow negative
138
96
$this->info['border-width'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_width);
140
98
$this->info['letter-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
141
99
new HTMLPurifier_AttrDef_Enum(array('normal')),
142
100
new HTMLPurifier_AttrDef_CSS_Length()
145
103
$this->info['word-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
146
104
new HTMLPurifier_AttrDef_Enum(array('normal')),
147
105
new HTMLPurifier_AttrDef_CSS_Length()
150
108
$this->info['font-size'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
151
109
new HTMLPurifier_AttrDef_Enum(array('xx-small', 'x-small',
152
110
'small', 'medium', 'large', 'x-large', 'xx-large',
154
112
new HTMLPurifier_AttrDef_CSS_Percentage(),
155
113
new HTMLPurifier_AttrDef_CSS_Length()
158
116
$this->info['line-height'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
159
117
new HTMLPurifier_AttrDef_Enum(array('normal')),
160
118
new HTMLPurifier_AttrDef_CSS_Number(true), // no negatives
161
119
new HTMLPurifier_AttrDef_CSS_Length('0'),
162
120
new HTMLPurifier_AttrDef_CSS_Percentage(true)
166
$this->info['margin-top'] =
167
$this->info['margin-bottom'] =
168
$this->info['margin-left'] =
124
$this->info['margin-top'] =
125
$this->info['margin-bottom'] =
126
$this->info['margin-left'] =
169
127
$this->info['margin-right'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
170
128
new HTMLPurifier_AttrDef_CSS_Length(),
171
129
new HTMLPurifier_AttrDef_CSS_Percentage(),
172
130
new HTMLPurifier_AttrDef_Enum(array('auto'))
175
133
$this->info['margin'] = new HTMLPurifier_AttrDef_CSS_Multiple($margin);
179
$this->info['padding-top'] =
180
$this->info['padding-bottom'] =
181
$this->info['padding-left'] =
137
$this->info['padding-top'] =
138
$this->info['padding-bottom'] =
139
$this->info['padding-left'] =
182
140
$this->info['padding-right'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
183
141
new HTMLPurifier_AttrDef_CSS_Length('0'),
184
142
new HTMLPurifier_AttrDef_CSS_Percentage(true)
187
145
$this->info['padding'] = new HTMLPurifier_AttrDef_CSS_Multiple($padding);
189
147
$this->info['text-indent'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
190
148
new HTMLPurifier_AttrDef_CSS_Length(),
191
149
new HTMLPurifier_AttrDef_CSS_Percentage()
194
152
$trusted_wh = new HTMLPurifier_AttrDef_CSS_Composite(array(
195
153
new HTMLPurifier_AttrDef_CSS_Length('0'),
196
154
new HTMLPurifier_AttrDef_CSS_Percentage(true),
197
155
new HTMLPurifier_AttrDef_Enum(array('auto'))
199
$max = $config->get('CSS', 'MaxImgLength');
157
$max = $config->get('CSS.MaxImgLength');
200
159
$this->info['width'] =
201
160
$this->info['height'] =
204
163
new HTMLPurifier_AttrDef_Switch('img',
206
165
new HTMLPurifier_AttrDef_CSS_Composite(array(
210
169
// For everyone else:
214
173
$this->info['text-decoration'] = new HTMLPurifier_AttrDef_CSS_TextDecoration();
216
175
$this->info['font-family'] = new HTMLPurifier_AttrDef_CSS_FontFamily();
218
177
// this could use specialized code
219
178
$this->info['font-weight'] = new HTMLPurifier_AttrDef_Enum(
220
179
array('normal', 'bold', 'bolder', 'lighter', '100', '200', '300',
221
180
'400', '500', '600', '700', '800', '900'), false);
223
182
// MUST be called after other font properties, as it references
224
183
// a CSSDefinition object
225
184
$this->info['font'] = new HTMLPurifier_AttrDef_CSS_Font($config);
228
187
$this->info['border'] =
229
$this->info['border-bottom'] =
230
$this->info['border-top'] =
231
$this->info['border-left'] =
188
$this->info['border-bottom'] =
189
$this->info['border-top'] =
190
$this->info['border-left'] =
232
191
$this->info['border-right'] = new HTMLPurifier_AttrDef_CSS_Border($config);
234
193
$this->info['border-collapse'] = new HTMLPurifier_AttrDef_Enum(array(
235
194
'collapse', 'separate'));
237
196
$this->info['caption-side'] = new HTMLPurifier_AttrDef_Enum(array(
238
197
'top', 'bottom'));
240
199
$this->info['table-layout'] = new HTMLPurifier_AttrDef_Enum(array(
241
200
'auto', 'fixed'));
243
202
$this->info['vertical-align'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
244
203
new HTMLPurifier_AttrDef_Enum(array('baseline', 'sub', 'super',
245
204
'top', 'text-top', 'middle', 'bottom', 'text-bottom')),
246
205
new HTMLPurifier_AttrDef_CSS_Length(),
247
206
new HTMLPurifier_AttrDef_CSS_Percentage()
250
209
$this->info['border-spacing'] = new HTMLPurifier_AttrDef_CSS_Multiple(new HTMLPurifier_AttrDef_CSS_Length(), 2);
252
211
// partial support
253
212
$this->info['white-space'] = new HTMLPurifier_AttrDef_Enum(array('nowrap'));
214
if ($config->get('CSS.Proprietary')) {
215
$this->doSetupProprietary($config);
218
if ($config->get('CSS.AllowTricky')) {
219
$this->doSetupTricky($config);
222
$allow_important = $config->get('CSS.AllowImportant');
223
// wrap all attr-defs with decorator that handles !important
224
foreach ($this->info as $k => $v) {
225
$this->info[$k] = new HTMLPurifier_AttrDef_CSS_ImportantDecorator($v, $allow_important);
228
$this->setupConfigStuff($config);
231
protected function doSetupProprietary($config) {
232
// Internet Explorer only scrollbar colors
233
$this->info['scrollbar-arrow-color'] = new HTMLPurifier_AttrDef_CSS_Color();
234
$this->info['scrollbar-base-color'] = new HTMLPurifier_AttrDef_CSS_Color();
235
$this->info['scrollbar-darkshadow-color'] = new HTMLPurifier_AttrDef_CSS_Color();
236
$this->info['scrollbar-face-color'] = new HTMLPurifier_AttrDef_CSS_Color();
237
$this->info['scrollbar-highlight-color'] = new HTMLPurifier_AttrDef_CSS_Color();
238
$this->info['scrollbar-shadow-color'] = new HTMLPurifier_AttrDef_CSS_Color();
240
// technically not proprietary, but CSS3, and no one supports it
241
$this->info['opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue();
242
$this->info['-moz-opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue();
243
$this->info['-khtml-opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue();
245
// only opacity, for now
246
$this->info['filter'] = new HTMLPurifier_AttrDef_CSS_Filter();
250
protected function doSetupTricky($config) {
251
$this->info['display'] = new HTMLPurifier_AttrDef_Enum(array(
252
'inline', 'block', 'list-item', 'run-in', 'compact',
253
'marker', 'table', 'inline-table', 'table-row-group',
254
'table-header-group', 'table-footer-group', 'table-row',
255
'table-column-group', 'table-column', 'table-cell', 'table-caption', 'none'
257
$this->info['visibility'] = new HTMLPurifier_AttrDef_Enum(array(
258
'visible', 'hidden', 'collapse'
260
$this->info['overflow'] = new HTMLPurifier_AttrDef_Enum(array('visible', 'hidden', 'auto', 'scroll'));
265
* Performs extra config-based processing. Based off of
266
* HTMLPurifier_HTMLDefinition.
267
* @todo Refactor duplicate elements into common class (probably using
268
* composition, not inheritance).
270
protected function setupConfigStuff($config) {
272
// setup allowed elements
273
$support = "(for information on implementing this, see the ".
275
$allowed_properties = $config->get('CSS.AllowedProperties');
276
if ($allowed_properties !== null) {
277
foreach ($this->info as $name => $d) {
278
if(!isset($allowed_properties[$name])) unset($this->info[$name]);
279
unset($allowed_properties[$name]);
282
foreach ($allowed_properties as $name => $d) {
283
// :TODO: Is this htmlspecialchars() call really necessary?
284
$name = htmlspecialchars($name);
285
trigger_error("Style attribute '$name' is not supported $support", E_USER_WARNING);
289
$forbidden_properties = $config->get('CSS.ForbiddenProperties');
290
if ($forbidden_properties !== null) {
291
foreach ($this->info as $name => $d) {
292
if (isset($forbidden_properties[$name])) {
293
unset($this->info[$name]);
301
// vim: et sw=4 sts=4