]>
Commit | Line | Data |
---|---|---|
d4949327 NL |
1 | <?php\r |
2 | \r | |
3 | /**\r | |
4 | * Validates the attributes of a token. Doesn't manage required attributes\r | |
5 | * very well. The only reason we factored this out was because RemoveForeignElements\r | |
6 | * also needed it besides ValidateAttributes.\r | |
7 | */\r | |
8 | class HTMLPurifier_AttrValidator\r | |
9 | {\r | |
10 | \r | |
11 | /**\r | |
12 | * Validates the attributes of a token, mutating it as necessary.\r | |
13 | * that has valid tokens\r | |
14 | * @param HTMLPurifier_Token $token Token to validate.\r | |
15 | * @param HTMLPurifier_Config $config Instance of HTMLPurifier_Config\r | |
16 | * @param HTMLPurifier_Context $context Instance of HTMLPurifier_Context\r | |
17 | */\r | |
18 | public function validateToken($token, $config, $context)\r | |
19 | {\r | |
20 | $definition = $config->getHTMLDefinition();\r | |
21 | $e =& $context->get('ErrorCollector', true);\r | |
22 | \r | |
23 | // initialize IDAccumulator if necessary\r | |
24 | $ok =& $context->get('IDAccumulator', true);\r | |
25 | if (!$ok) {\r | |
26 | $id_accumulator = HTMLPurifier_IDAccumulator::build($config, $context);\r | |
27 | $context->register('IDAccumulator', $id_accumulator);\r | |
28 | }\r | |
29 | \r | |
30 | // initialize CurrentToken if necessary\r | |
31 | $current_token =& $context->get('CurrentToken', true);\r | |
32 | if (!$current_token) {\r | |
33 | $context->register('CurrentToken', $token);\r | |
34 | }\r | |
35 | \r | |
36 | if (!$token instanceof HTMLPurifier_Token_Start &&\r | |
37 | !$token instanceof HTMLPurifier_Token_Empty\r | |
38 | ) {\r | |
39 | return;\r | |
40 | }\r | |
41 | \r | |
42 | // create alias to global definition array, see also $defs\r | |
43 | // DEFINITION CALL\r | |
44 | $d_defs = $definition->info_global_attr;\r | |
45 | \r | |
46 | // don't update token until the very end, to ensure an atomic update\r | |
47 | $attr = $token->attr;\r | |
48 | \r | |
49 | // do global transformations (pre)\r | |
50 | // nothing currently utilizes this\r | |
51 | foreach ($definition->info_attr_transform_pre as $transform) {\r | |
52 | $attr = $transform->transform($o = $attr, $config, $context);\r | |
53 | if ($e) {\r | |
54 | if ($attr != $o) {\r | |
55 | $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);\r | |
56 | }\r | |
57 | }\r | |
58 | }\r | |
59 | \r | |
60 | // do local transformations only applicable to this element (pre)\r | |
61 | // ex. <p align="right"> to <p style="text-align:right;">\r | |
62 | foreach ($definition->info[$token->name]->attr_transform_pre as $transform) {\r | |
63 | $attr = $transform->transform($o = $attr, $config, $context);\r | |
64 | if ($e) {\r | |
65 | if ($attr != $o) {\r | |
66 | $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);\r | |
67 | }\r | |
68 | }\r | |
69 | }\r | |
70 | \r | |
71 | // create alias to this element's attribute definition array, see\r | |
72 | // also $d_defs (global attribute definition array)\r | |
73 | // DEFINITION CALL\r | |
74 | $defs = $definition->info[$token->name]->attr;\r | |
75 | \r | |
76 | $attr_key = false;\r | |
77 | $context->register('CurrentAttr', $attr_key);\r | |
78 | \r | |
79 | // iterate through all the attribute keypairs\r | |
80 | // Watch out for name collisions: $key has previously been used\r | |
81 | foreach ($attr as $attr_key => $value) {\r | |
82 | \r | |
83 | // call the definition\r | |
84 | if (isset($defs[$attr_key])) {\r | |
85 | // there is a local definition defined\r | |
86 | if ($defs[$attr_key] === false) {\r | |
87 | // We've explicitly been told not to allow this element.\r | |
88 | // This is usually when there's a global definition\r | |
89 | // that must be overridden.\r | |
90 | // Theoretically speaking, we could have a\r | |
91 | // AttrDef_DenyAll, but this is faster!\r | |
92 | $result = false;\r | |
93 | } else {\r | |
94 | // validate according to the element's definition\r | |
95 | $result = $defs[$attr_key]->validate(\r | |
96 | $value,\r | |
97 | $config,\r | |
98 | $context\r | |
99 | );\r | |
100 | }\r | |
101 | } elseif (isset($d_defs[$attr_key])) {\r | |
102 | // there is a global definition defined, validate according\r | |
103 | // to the global definition\r | |
104 | $result = $d_defs[$attr_key]->validate(\r | |
105 | $value,\r | |
106 | $config,\r | |
107 | $context\r | |
108 | );\r | |
109 | } else {\r | |
110 | // system never heard of the attribute? DELETE!\r | |
111 | $result = false;\r | |
112 | }\r | |
113 | \r | |
114 | // put the results into effect\r | |
115 | if ($result === false || $result === null) {\r | |
116 | // this is a generic error message that should replaced\r | |
117 | // with more specific ones when possible\r | |
118 | if ($e) {\r | |
119 | $e->send(E_ERROR, 'AttrValidator: Attribute removed');\r | |
120 | }\r | |
121 | \r | |
122 | // remove the attribute\r | |
123 | unset($attr[$attr_key]);\r | |
124 | } elseif (is_string($result)) {\r | |
125 | // generally, if a substitution is happening, there\r | |
126 | // was some sort of implicit correction going on. We'll\r | |
127 | // delegate it to the attribute classes to say exactly what.\r | |
128 | \r | |
129 | // simple substitution\r | |
130 | $attr[$attr_key] = $result;\r | |
131 | } else {\r | |
132 | // nothing happens\r | |
133 | }\r | |
134 | \r | |
135 | // we'd also want slightly more complicated substitution\r | |
136 | // involving an array as the return value,\r | |
137 | // although we're not sure how colliding attributes would\r | |
138 | // resolve (certain ones would be completely overriden,\r | |
139 | // others would prepend themselves).\r | |
140 | }\r | |
141 | \r | |
142 | $context->destroy('CurrentAttr');\r | |
143 | \r | |
144 | // post transforms\r | |
145 | \r | |
146 | // global (error reporting untested)\r | |
147 | foreach ($definition->info_attr_transform_post as $transform) {\r | |
148 | $attr = $transform->transform($o = $attr, $config, $context);\r | |
149 | if ($e) {\r | |
150 | if ($attr != $o) {\r | |
151 | $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);\r | |
152 | }\r | |
153 | }\r | |
154 | }\r | |
155 | \r | |
156 | // local (error reporting untested)\r | |
157 | foreach ($definition->info[$token->name]->attr_transform_post as $transform) {\r | |
158 | $attr = $transform->transform($o = $attr, $config, $context);\r | |
159 | if ($e) {\r | |
160 | if ($attr != $o) {\r | |
161 | $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);\r | |
162 | }\r | |
163 | }\r | |
164 | }\r | |
165 | \r | |
166 | $token->attr = $attr;\r | |
167 | \r | |
168 | // destroy CurrentToken if we made it ourselves\r | |
169 | if (!$current_token) {\r | |
170 | $context->destroy('CurrentToken');\r | |
171 | }\r | |
172 | \r | |
173 | }\r | |
174 | \r | |
175 | \r | |
176 | }\r | |
177 | \r | |
178 | // vim: et sw=4 sts=4\r |