]>
Commit | Line | Data |
---|---|---|
1 | <?php\r | |
2 | \r | |
3 | /**\r | |
4 | * Injects tokens into the document while parsing for well-formedness.\r | |
5 | * This enables "formatter-like" functionality such as auto-paragraphing,\r | |
6 | * smiley-ification and linkification to take place.\r | |
7 | *\r | |
8 | * A note on how handlers create changes; this is done by assigning a new\r | |
9 | * value to the $token reference. These values can take a variety of forms and\r | |
10 | * are best described HTMLPurifier_Strategy_MakeWellFormed->processToken()\r | |
11 | * documentation.\r | |
12 | *\r | |
13 | * @todo Allow injectors to request a re-run on their output. This\r | |
14 | * would help if an operation is recursive.\r | |
15 | */\r | |
16 | abstract class HTMLPurifier_Injector\r | |
17 | {\r | |
18 | \r | |
19 | /**\r | |
20 | * Advisory name of injector, this is for friendly error messages.\r | |
21 | * @type string\r | |
22 | */\r | |
23 | public $name;\r | |
24 | \r | |
25 | /**\r | |
26 | * @type HTMLPurifier_HTMLDefinition\r | |
27 | */\r | |
28 | protected $htmlDefinition;\r | |
29 | \r | |
30 | /**\r | |
31 | * Reference to CurrentNesting variable in Context. This is an array\r | |
32 | * list of tokens that we are currently "inside"\r | |
33 | * @type array\r | |
34 | */\r | |
35 | protected $currentNesting;\r | |
36 | \r | |
37 | /**\r | |
38 | * Reference to current token.\r | |
39 | * @type HTMLPurifier_Token\r | |
40 | */\r | |
41 | protected $currentToken;\r | |
42 | \r | |
43 | /**\r | |
44 | * Reference to InputZipper variable in Context.\r | |
45 | * @type HTMLPurifier_Zipper\r | |
46 | */\r | |
47 | protected $inputZipper;\r | |
48 | \r | |
49 | /**\r | |
50 | * Array of elements and attributes this injector creates and therefore\r | |
51 | * need to be allowed by the definition. Takes form of\r | |
52 | * array('element' => array('attr', 'attr2'), 'element2')\r | |
53 | * @type array\r | |
54 | */\r | |
55 | public $needed = array();\r | |
56 | \r | |
57 | /**\r | |
58 | * Number of elements to rewind backwards (relative).\r | |
59 | * @type bool|int\r | |
60 | */\r | |
61 | protected $rewindOffset = false;\r | |
62 | \r | |
63 | /**\r | |
64 | * Rewind to a spot to re-perform processing. This is useful if you\r | |
65 | * deleted a node, and now need to see if this change affected any\r | |
66 | * earlier nodes. Rewinding does not affect other injectors, and can\r | |
67 | * result in infinite loops if not used carefully.\r | |
68 | * @param bool|int $offset\r | |
69 | * @warning HTML Purifier will prevent you from fast-forwarding with this\r | |
70 | * function.\r | |
71 | */\r | |
72 | public function rewindOffset($offset)\r | |
73 | {\r | |
74 | $this->rewindOffset = $offset;\r | |
75 | }\r | |
76 | \r | |
77 | /**\r | |
78 | * Retrieves rewind offset, and then unsets it.\r | |
79 | * @return bool|int\r | |
80 | */\r | |
81 | public function getRewindOffset()\r | |
82 | {\r | |
83 | $r = $this->rewindOffset;\r | |
84 | $this->rewindOffset = false;\r | |
85 | return $r;\r | |
86 | }\r | |
87 | \r | |
88 | /**\r | |
89 | * Prepares the injector by giving it the config and context objects:\r | |
90 | * this allows references to important variables to be made within\r | |
91 | * the injector. This function also checks if the HTML environment\r | |
92 | * will work with the Injector (see checkNeeded()).\r | |
93 | * @param HTMLPurifier_Config $config\r | |
94 | * @param HTMLPurifier_Context $context\r | |
95 | * @return bool|string Boolean false if success, string of missing needed element/attribute if failure\r | |
96 | */\r | |
97 | public function prepare($config, $context)\r | |
98 | {\r | |
99 | $this->htmlDefinition = $config->getHTMLDefinition();\r | |
100 | // Even though this might fail, some unit tests ignore this and\r | |
101 | // still test checkNeeded, so be careful. Maybe get rid of that\r | |
102 | // dependency.\r | |
103 | $result = $this->checkNeeded($config);\r | |
104 | if ($result !== false) {\r | |
105 | return $result;\r | |
106 | }\r | |
107 | $this->currentNesting =& $context->get('CurrentNesting');\r | |
108 | $this->currentToken =& $context->get('CurrentToken');\r | |
109 | $this->inputZipper =& $context->get('InputZipper');\r | |
110 | return false;\r | |
111 | }\r | |
112 | \r | |
113 | /**\r | |
114 | * This function checks if the HTML environment\r | |
115 | * will work with the Injector: if p tags are not allowed, the\r | |
116 | * Auto-Paragraphing injector should not be enabled.\r | |
117 | * @param HTMLPurifier_Config $config\r | |
118 | * @return bool|string Boolean false if success, string of missing needed element/attribute if failure\r | |
119 | */\r | |
120 | public function checkNeeded($config)\r | |
121 | {\r | |
122 | $def = $config->getHTMLDefinition();\r | |
123 | foreach ($this->needed as $element => $attributes) {\r | |
124 | if (is_int($element)) {\r | |
125 | $element = $attributes;\r | |
126 | }\r | |
127 | if (!isset($def->info[$element])) {\r | |
128 | return $element;\r | |
129 | }\r | |
130 | if (!is_array($attributes)) {\r | |
131 | continue;\r | |
132 | }\r | |
133 | foreach ($attributes as $name) {\r | |
134 | if (!isset($def->info[$element]->attr[$name])) {\r | |
135 | return "$element.$name";\r | |
136 | }\r | |
137 | }\r | |
138 | }\r | |
139 | return false;\r | |
140 | }\r | |
141 | \r | |
142 | /**\r | |
143 | * Tests if the context node allows a certain element\r | |
144 | * @param string $name Name of element to test for\r | |
145 | * @return bool True if element is allowed, false if it is not\r | |
146 | */\r | |
147 | public function allowsElement($name)\r | |
148 | {\r | |
149 | if (!empty($this->currentNesting)) {\r | |
150 | $parent_token = array_pop($this->currentNesting);\r | |
151 | $this->currentNesting[] = $parent_token;\r | |
152 | $parent = $this->htmlDefinition->info[$parent_token->name];\r | |
153 | } else {\r | |
154 | $parent = $this->htmlDefinition->info_parent_def;\r | |
155 | }\r | |
156 | if (!isset($parent->child->elements[$name]) || isset($parent->excludes[$name])) {\r | |
157 | return false;\r | |
158 | }\r | |
159 | // check for exclusion\r | |
160 | for ($i = count($this->currentNesting) - 2; $i >= 0; $i--) {\r | |
161 | $node = $this->currentNesting[$i];\r | |
162 | $def = $this->htmlDefinition->info[$node->name];\r | |
163 | if (isset($def->excludes[$name])) {\r | |
164 | return false;\r | |
165 | }\r | |
166 | }\r | |
167 | return true;\r | |
168 | }\r | |
169 | \r | |
170 | /**\r | |
171 | * Iterator function, which starts with the next token and continues until\r | |
172 | * you reach the end of the input tokens.\r | |
173 | * @warning Please prevent previous references from interfering with this\r | |
174 | * functions by setting $i = null beforehand!\r | |
175 | * @param int $i Current integer index variable for inputTokens\r | |
176 | * @param HTMLPurifier_Token $current Current token variable.\r | |
177 | * Do NOT use $token, as that variable is also a reference\r | |
178 | * @return bool\r | |
179 | */\r | |
180 | protected function forward(&$i, &$current)\r | |
181 | {\r | |
182 | if ($i === null) {\r | |
183 | $i = count($this->inputZipper->back) - 1;\r | |
184 | } else {\r | |
185 | $i--;\r | |
186 | }\r | |
187 | if ($i < 0) {\r | |
188 | return false;\r | |
189 | }\r | |
190 | $current = $this->inputZipper->back[$i];\r | |
191 | return true;\r | |
192 | }\r | |
193 | \r | |
194 | /**\r | |
195 | * Similar to _forward, but accepts a third parameter $nesting (which\r | |
196 | * should be initialized at 0) and stops when we hit the end tag\r | |
197 | * for the node $this->inputIndex starts in.\r | |
198 | * @param int $i Current integer index variable for inputTokens\r | |
199 | * @param HTMLPurifier_Token $current Current token variable.\r | |
200 | * Do NOT use $token, as that variable is also a reference\r | |
201 | * @param int $nesting\r | |
202 | * @return bool\r | |
203 | */\r | |
204 | protected function forwardUntilEndToken(&$i, &$current, &$nesting)\r | |
205 | {\r | |
206 | $result = $this->forward($i, $current);\r | |
207 | if (!$result) {\r | |
208 | return false;\r | |
209 | }\r | |
210 | if ($nesting === null) {\r | |
211 | $nesting = 0;\r | |
212 | }\r | |
213 | if ($current instanceof HTMLPurifier_Token_Start) {\r | |
214 | $nesting++;\r | |
215 | } elseif ($current instanceof HTMLPurifier_Token_End) {\r | |
216 | if ($nesting <= 0) {\r | |
217 | return false;\r | |
218 | }\r | |
219 | $nesting--;\r | |
220 | }\r | |
221 | return true;\r | |
222 | }\r | |
223 | \r | |
224 | /**\r | |
225 | * Iterator function, starts with the previous token and continues until\r | |
226 | * you reach the beginning of input tokens.\r | |
227 | * @warning Please prevent previous references from interfering with this\r | |
228 | * functions by setting $i = null beforehand!\r | |
229 | * @param int $i Current integer index variable for inputTokens\r | |
230 | * @param HTMLPurifier_Token $current Current token variable.\r | |
231 | * Do NOT use $token, as that variable is also a reference\r | |
232 | * @return bool\r | |
233 | */\r | |
234 | protected function backward(&$i, &$current)\r | |
235 | {\r | |
236 | if ($i === null) {\r | |
237 | $i = count($this->inputZipper->front) - 1;\r | |
238 | } else {\r | |
239 | $i--;\r | |
240 | }\r | |
241 | if ($i < 0) {\r | |
242 | return false;\r | |
243 | }\r | |
244 | $current = $this->inputZipper->front[$i];\r | |
245 | return true;\r | |
246 | }\r | |
247 | \r | |
248 | /**\r | |
249 | * Handler that is called when a text token is processed\r | |
250 | */\r | |
251 | public function handleText(&$token)\r | |
252 | {\r | |
253 | }\r | |
254 | \r | |
255 | /**\r | |
256 | * Handler that is called when a start or empty token is processed\r | |
257 | */\r | |
258 | public function handleElement(&$token)\r | |
259 | {\r | |
260 | }\r | |
261 | \r | |
262 | /**\r | |
263 | * Handler that is called when an end token is processed\r | |
264 | */\r | |
265 | public function handleEnd(&$token)\r | |
266 | {\r | |
267 | $this->notifyEnd($token);\r | |
268 | }\r | |
269 | \r | |
270 | /**\r | |
271 | * Notifier that is called when an end token is processed\r | |
272 | * @param HTMLPurifier_Token $token Current token variable.\r | |
273 | * @note This differs from handlers in that the token is read-only\r | |
274 | * @deprecated\r | |
275 | */\r | |
276 | public function notifyEnd($token)\r | |
277 | {\r | |
278 | }\r | |
279 | }\r | |
280 | \r | |
281 | // vim: et sw=4 sts=4\r |