41 $definition =
$config->getHTMLDefinition();
45 $escape_invalid_tags =
$config->get(
'Core.EscapeInvalidTags');
46 $e =
$context->get(
'ErrorCollector',
true);
64 $context->register(
'CurrentToken', $token);
68 $this->injectors = array();
71 $def_injectors = $definition->info_injector;
76 if (strpos($injector,
'.') !==
false)
continue;
77 $injector =
"HTMLPurifier_Injector_$injector";
79 $this->injectors[] =
new $injector;
81 foreach ($def_injectors as $injector) {
83 $this->injectors[] = $injector;
85 foreach ($custom_injectors as $injector) {
86 if (is_string($injector)) {
87 $injector =
"HTMLPurifier_Injector_$injector";
88 $injector =
new $injector;
90 $this->injectors[] = $injector;
95 foreach ($this->injectors as $ix => $injector) {
98 array_splice($this->injectors, $ix, 1);
99 trigger_error(
"Cannot enable {$injector->name} injector because $error is not allowed", E_USER_WARNING);
117 $reprocess ? $reprocess =
false :
$t++
121 if (is_int($i) && $i >= 0) {
125 $rewind_to = $this->injectors[$i]->getRewind();
126 if (is_int($rewind_to) && $rewind_to <
$t) {
127 if ($rewind_to < 0) $rewind_to = 0;
128 while (
$t > $rewind_to) {
133 unset($prev->skip[$i]);
145 if (empty($this->stack))
break;
148 $top_nesting = array_pop($this->stack);
149 $this->stack[] = $top_nesting;
152 if ($e && !isset($top_nesting->armor[
'MakeWellFormed_TagClosedError'])) {
153 $e->send(E_NOTICE,
'Strategy_MakeWellFormed: Tag closed by document end', $top_nesting);
169 if (empty($token->is_tag)) {
171 foreach ($this->injectors as $i => $injector) {
172 if (isset($token->skip[$i]))
continue;
173 if ($token->rewind !== null && $token->rewind !== $i)
continue;
174 $injector->handleText($token);
184 if (isset($definition->info[$token->name])) {
185 $type = $definition->info[$token->name]->child->type;
199 $this->
insertBefore(
new HTMLPurifier_Token_Start($token->name, $token->attr));
203 } elseif ($token instanceof HTMLPurifier_Token_Empty) {
206 } elseif ($token instanceof HTMLPurifier_Token_Start) {
210 if (!empty($this->stack)) {
212 $parent = array_pop($this->stack);
213 $this->stack[] = $parent;
215 if (isset($definition->info[$parent->name])) {
216 $elements = $definition->info[$parent->name]->child->getAllowedElements(
$config);
217 $autoclose = !isset($elements[$token->name]);
223 if ($autoclose && $definition->info[$parent->name]->formatting) {
230 $new_token->start = $parent;
232 $element = clone $parent;
233 $element->armor[
'MakeWellFormed_TagClosedError'] =
true;
234 $element->carryover =
true;
235 $this->
processToken(array($new_token, $token, $element));
239 if ($e && !isset($parent->armor[
'MakeWellFormed_TagClosedError'])) {
241 $e->send(E_NOTICE,
'Strategy_MakeWellFormed: Tag auto closed', $parent);
243 $e->send(E_NOTICE,
'Strategy_MakeWellFormed: Tag carryover', $parent);
255 foreach ($this->injectors as $i => $injector) {
256 if (isset($token->skip[$i]))
continue;
257 if ($token->rewind !== null && $token->rewind !== $i)
continue;
258 $injector->handleElement($token);
266 if ($token instanceof HTMLPurifier_Token_Start) {
267 $this->stack[] = $token;
269 throw new HTMLPurifier_Exception(
'Improper handling of end tag in start code; possible error in MakeWellFormed');
281 if (empty($this->stack)) {
282 if ($escape_invalid_tags) {
283 if ($e) $e->send(E_WARNING,
'Strategy_MakeWellFormed: Unnecessary end tag to text');
285 $generator->generateFromToken($token)
289 if ($e) $e->send(E_WARNING,
'Strategy_MakeWellFormed: Unnecessary end tag removed');
299 $current_parent = array_pop($this->stack);
300 if ($current_parent->name == $token->name) {
301 $token->start = $current_parent;
302 foreach ($this->injectors as $i => $injector) {
303 if (isset($token->skip[$i]))
continue;
304 if ($token->rewind !== null && $token->rewind !== $i)
continue;
305 $injector->handleEnd($token);
307 $this->stack[] = $current_parent;
317 $this->stack[] = $current_parent;
321 $size = count($this->stack);
323 $skipped_tags =
false;
324 for ($j = $size - 2; $j >= 0; $j--) {
325 if ($this->stack[$j]->name == $token->name) {
326 $skipped_tags = array_slice($this->stack, $j);
332 if ($skipped_tags ===
false) {
333 if ($escape_invalid_tags) {
335 $generator->generateFromToken($token)
337 if ($e) $e->send(E_WARNING,
'Strategy_MakeWellFormed: Stray end tag to text');
340 if ($e) $e->send(E_WARNING,
'Strategy_MakeWellFormed: Stray end tag removed');
347 $c = count($skipped_tags);
349 for ($j = $c - 1; $j > 0; $j--) {
352 if (!isset($skipped_tags[$j]->armor[
'MakeWellFormed_TagClosedError'])) {
353 $e->send(E_NOTICE,
'Strategy_MakeWellFormed: Tag closed by element end', $skipped_tags[$j]);
359 $replace = array($token);
360 for ($j = 1; $j < $c; $j++) {
362 $new_token =
new HTMLPurifier_Token_End($skipped_tags[$j]->name);
363 $new_token->start = $skipped_tags[$j];
364 array_unshift($replace, $new_token);
365 if (isset($definition->info[$new_token->name]) && $definition->info[$new_token->name]->formatting) {
366 $element = clone $skipped_tags[$j];
367 $element->carryover =
true;
368 $element->armor[
'MakeWellFormed_TagClosedError'] =
true;
369 $replace[] = $element;
377 $context->destroy(
'CurrentNesting');
382 unset($this->injectors, $this->stack, $this->tokens, $this->t);
409 if (is_object($token)) $token = array(1, $token);
410 if (is_int($token)) $token = array($token);
411 if ($token ===
false) $token = array(1);
413 if (!is_int($token[0])) array_unshift($token, 1);
419 $delete = array_shift($token);
420 $old = array_splice($this->tokens, $this->t, $delete, $token);
422 if ($injector > -1) {
424 $oldskip = isset($old[0]) ? $old[0]->skip : array();
425 foreach ($token as $object) {
426 $object->skip = $oldskip;
427 $object->skip[$injector] =
true;
437 array_splice($this->tokens, $this->t, 0, array($token));
444 private function remove() {
445 array_splice($this->tokens, $this->t, 1);
451 private function swap($token) {