68 $definition =
$config->getHTMLDefinition();
72 $escape_invalid_tags =
$config->get(
'Core.EscapeInvalidTags');
74 $global_parent_allowed_elements = $definition->info_parent_def->child->getAllowedElements(
$config);
75 $e =
$context->get(
'ErrorCollector',
true);
99 $this->injectors = array();
102 $def_injectors = $definition->info_injector;
107 if (strpos($injector,
'.') !==
false) {
110 $injector =
"HTMLPurifier_Injector_$injector";
114 $this->injectors[] =
new $injector;
116 foreach ($def_injectors as $injector) {
118 $this->injectors[] = $injector;
120 foreach ($custom_injectors as $injector) {
124 if (is_string($injector)) {
125 $injector =
"HTMLPurifier_Injector_$injector";
126 $injector =
new $injector;
128 $this->injectors[] = $injector;
133 foreach ($this->injectors as $ix => $injector) {
138 array_splice($this->injectors, $ix, 1);
139 trigger_error(
"Cannot enable {$injector->name} injector because $error is not allowed", E_USER_WARNING);
162 $rewind_offset = $this->injectors[$i]->getRewindOffset();
163 if (is_int($rewind_offset)) {
164 for ($j = 0; $j < $rewind_offset; $j++) {
165 if (empty(
$zipper->front))
break;
172 array_pop($this->stack);
174 $this->stack[] =
$token->start;
184 if (empty($this->stack)) {
189 $top_nesting = array_pop($this->stack);
190 $this->stack[] = $top_nesting;
193 if ($e && !isset($top_nesting->armor[
'MakeWellFormed_TagClosedError'])) {
194 $e->send(E_NOTICE,
'Strategy_MakeWellFormed: Tag closed by document end', $top_nesting);
209 if (empty(
$token->is_tag)) {
211 foreach ($this->injectors as $i => $injector) {
212 if (isset(
$token->skip[$i])) {
220 $injector->handleText($r);
230 if (isset($definition->info[
$token->name])) {
231 $type = $definition->info[
$token->name]->child->type;
254 new HTMLPurifier_Token_Start($old_token->name, $old_token->attr, $old_token->line, $old_token->col, $old_token->armor)
259 } elseif (
$token instanceof HTMLPurifier_Token_Empty) {
262 } elseif (
$token instanceof HTMLPurifier_Token_Start) {
266 if (!empty($this->stack)) {
281 $parent = array_pop($this->stack);
282 $this->stack[] = $parent;
285 $parent_elements = null;
287 if (isset($definition->info[$parent->name])) {
288 $parent_def = $definition->info[$parent->name];
289 $parent_elements = $parent_def->child->getAllowedElements(
$config);
290 $autoclose = !isset($parent_elements[
$token->name]);
293 if ($autoclose && $definition->info[
$token->name]->wrap) {
297 $wrapname = $definition->info[
$token->name]->wrap;
298 $wrapdef = $definition->info[$wrapname];
299 $elements = $wrapdef->child->getAllowedElements(
$config);
300 if (isset($elements[
$token->name]) && isset($parent_elements[$wrapname])) {
301 $newtoken =
new HTMLPurifier_Token_Start($wrapname);
309 if ($autoclose && $parent_def->formatting) {
316 $autoclose_ok = isset($global_parent_allowed_elements[
$token->name]);
317 if (!$autoclose_ok) {
318 foreach ($this->stack as $ancestor) {
319 $elements = $definition->info[$ancestor->name]->child->getAllowedElements(
$config);
320 if (isset($elements[
$token->name])) {
321 $autoclose_ok =
true;
324 if ($definition->info[
$token->name]->wrap) {
325 $wrapname = $definition->info[
$token->name]->wrap;
326 $wrapdef = $definition->info[$wrapname];
327 $wrap_elements = $wrapdef->child->getAllowedElements(
$config);
328 if (isset($wrap_elements[
$token->name]) && isset($elements[$wrapname])) {
329 $autoclose_ok =
true;
338 $new_token->start = $parent;
340 if ($e && !isset($parent->armor[
'MakeWellFormed_TagClosedError'])) {
342 $e->send(E_NOTICE,
'Strategy_MakeWellFormed: Tag auto closed', $parent);
344 $e->send(E_NOTICE,
'Strategy_MakeWellFormed: Tag carryover', $parent);
348 $element = clone $parent;
350 $element->armor[
'MakeWellFormed_TagClosedError'] =
true;
351 $element->carryover =
true;
368 foreach ($this->injectors as $i => $injector) {
369 if (isset(
$token->skip[$i])) {
376 $injector->handleElement($r);
383 if (
$token instanceof HTMLPurifier_Token_Start) {
387 'Improper handling of end tag in start code; possible error in MakeWellFormed'
400 if (empty($this->stack)) {
401 if ($escape_invalid_tags) {
403 $e->send(E_WARNING,
'Strategy_MakeWellFormed: Unnecessary end tag to text');
408 $e->send(E_WARNING,
'Strategy_MakeWellFormed: Unnecessary end tag removed');
420 $current_parent = array_pop($this->stack);
421 if ($current_parent->name ==
$token->name) {
422 $token->start = $current_parent;
423 foreach ($this->injectors as $i => $injector) {
424 if (isset(
$token->skip[$i])) {
431 $injector->handleEnd($r);
433 $this->stack[] = $current_parent;
443 $this->stack[] = $current_parent;
447 $size = count($this->stack);
449 $skipped_tags =
false;
450 for ($j =
$size - 2; $j >= 0; $j--) {
451 if ($this->stack[$j]->name ==
$token->name) {
452 $skipped_tags = array_slice($this->stack, $j);
458 if ($skipped_tags ===
false) {
459 if ($escape_invalid_tags) {
461 $e->send(E_WARNING,
'Strategy_MakeWellFormed: Stray end tag to text');
466 $e->send(E_WARNING,
'Strategy_MakeWellFormed: Stray end tag removed');
475 $c = count($skipped_tags);
477 for ($j = $c - 1; $j > 0; $j--) {
480 if (!isset($skipped_tags[$j]->armor[
'MakeWellFormed_TagClosedError'])) {
481 $e->send(E_NOTICE,
'Strategy_MakeWellFormed: Tag closed by element end', $skipped_tags[$j]);
488 for ($j = 1; $j < $c; $j++) {
490 $new_token =
new HTMLPurifier_Token_End($skipped_tags[$j]->name);
491 $new_token->start = $skipped_tags[$j];
492 array_unshift($replace, $new_token);
493 if (isset($definition->info[$new_token->name]) && $definition->info[$new_token->name]->formatting) {
495 $element = clone $skipped_tags[$j];
496 $element->carryover =
true;
497 $element->armor[
'MakeWellFormed_TagClosedError'] =
true;
498 $replace[] = $element;
507 $context->destroy(
'CurrentNesting');
510 unset($this->injectors, $this->stack, $this->tokens);
560 $delete = array_shift(
$token);
561 list($old, $r) = $this->zipper->splice($this->token, $delete,
$token);
563 if ($injector > -1) {
565 $oldskip = isset($old[0]) ? $old[0]->skip : array();
566 foreach (
$token as $object) {
567 $object->skip = $oldskip;
568 $object->skip[$injector] =
true;
585 $splice = $this->zipper->splice($this->token, 0, array(
$token));
594 private function remove()
596 return $this->zipper->delete();