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) {
221 $injector->handleText(
$r);
231 if (isset($definition->info[
$token->name])) {
232 $type = $definition->info[
$token->name]->child->type;
255 new HTMLPurifier_Token_Start($old_token->name, $old_token->attr, $old_token->line, $old_token->col, $old_token->armor)
260 } elseif (
$token instanceof HTMLPurifier_Token_Empty) {
263 } elseif (
$token instanceof HTMLPurifier_Token_Start) {
267 if (!empty($this->stack)) {
282 $parent = array_pop($this->stack);
283 $this->stack[] = $parent;
286 $parent_elements = null;
288 if (isset($definition->info[$parent->name])) {
289 $parent_def = $definition->info[$parent->name];
290 $parent_elements = $parent_def->child->getAllowedElements(
$config);
291 $autoclose = !isset($parent_elements[
$token->name]);
294 if ($autoclose && $definition->info[
$token->name]->wrap) {
298 $wrapname = $definition->info[
$token->name]->wrap;
299 $wrapdef = $definition->info[$wrapname];
300 $elements = $wrapdef->child->getAllowedElements(
$config);
301 if (isset($elements[
$token->name]) && isset($parent_elements[$wrapname])) {
302 $newtoken =
new HTMLPurifier_Token_Start($wrapname);
310 if ($autoclose && $parent_def->formatting) {
317 $autoclose_ok = isset($global_parent_allowed_elements[
$token->name]);
318 if (!$autoclose_ok) {
319 foreach ($this->stack as $ancestor) {
320 $elements = $definition->info[$ancestor->name]->child->getAllowedElements(
$config);
321 if (isset($elements[
$token->name])) {
322 $autoclose_ok =
true;
325 if ($definition->info[
$token->name]->wrap) {
326 $wrapname = $definition->info[
$token->name]->wrap;
327 $wrapdef = $definition->info[$wrapname];
328 $wrap_elements = $wrapdef->child->getAllowedElements(
$config);
329 if (isset($wrap_elements[
$token->name]) && isset($elements[$wrapname])) {
330 $autoclose_ok =
true;
339 $new_token->start = $parent;
341 if ($e && !isset($parent->armor[
'MakeWellFormed_TagClosedError'])) {
343 $e->send(E_NOTICE,
'Strategy_MakeWellFormed: Tag auto closed', $parent);
345 $e->send(E_NOTICE,
'Strategy_MakeWellFormed: Tag carryover', $parent);
349 $element = clone $parent;
351 $element->armor[
'MakeWellFormed_TagClosedError'] =
true;
352 $element->carryover =
true;
369 foreach ($this->injectors as
$i => $injector) {
378 $injector->handleElement(
$r);
385 if (
$token instanceof HTMLPurifier_Token_Start) {
389 'Improper handling of end tag in start code; possible error in MakeWellFormed' 402 if (empty($this->stack)) {
403 if ($escape_invalid_tags) {
405 $e->send(E_WARNING,
'Strategy_MakeWellFormed: Unnecessary end tag to text');
410 $e->send(E_WARNING,
'Strategy_MakeWellFormed: Unnecessary end tag removed');
422 $current_parent = array_pop($this->stack);
423 if ($current_parent->name ==
$token->name) {
424 $token->start = $current_parent;
425 foreach ($this->injectors as
$i => $injector) {
434 $injector->handleEnd(
$r);
436 $this->stack[] = $current_parent;
446 $this->stack[] = $current_parent;
450 $size = count($this->stack);
452 $skipped_tags =
false;
453 for ($j =
$size - 2; $j >= 0; $j--) {
454 if ($this->stack[$j]->name ==
$token->name) {
455 $skipped_tags = array_slice($this->stack, $j);
461 if ($skipped_tags ===
false) {
462 if ($escape_invalid_tags) {
464 $e->send(E_WARNING,
'Strategy_MakeWellFormed: Stray end tag to text');
469 $e->send(E_WARNING,
'Strategy_MakeWellFormed: Stray end tag removed');
478 $c = count($skipped_tags);
480 for ($j = $c - 1; $j > 0; $j--) {
483 if (!isset($skipped_tags[$j]->armor[
'MakeWellFormed_TagClosedError'])) {
484 $e->send(E_NOTICE,
'Strategy_MakeWellFormed: Tag closed by element end', $skipped_tags[$j]);
491 for ($j = 1; $j < $c; $j++) {
493 $new_token =
new HTMLPurifier_Token_End($skipped_tags[$j]->name);
494 $new_token->start = $skipped_tags[$j];
495 array_unshift($replace, $new_token);
496 if (isset($definition->info[$new_token->name]) && $definition->info[$new_token->name]->formatting) {
498 $element = clone $skipped_tags[$j];
499 $element->carryover =
true;
500 $element->armor[
'MakeWellFormed_TagClosedError'] =
true;
501 $replace[] = $element;
510 $context->destroy(
'CurrentNesting');
513 unset($this->injectors, $this->stack, $this->tokens);
568 $delete = array_shift(
$token);
569 list(
$old,
$r) = $this->zipper->splice($this->token, $delete,
$token);
571 if ($injector > -1) {
579 foreach (
$token as $object) {
580 $object->skip = $oldskip;
581 $object->skip[$injector] =
true;
598 $splice = $this->zipper->splice($this->token, 0,
array(
$token));
607 private function remove()
609 return $this->zipper->delete();
Concrete end token class.
Generates HTML from tokens.
Concrete start token class.
Supertype for classes that define a strategy for modifying/purifying tokens.
Create styles array
The data for the language used.
Concrete empty token class.
Global exception class for HTML Purifier; any exceptions we throw are from here.
static fromArray($array)
Creates a zipper from an array, with a hole in the 0-index position.
Concrete text token class.