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)
 
  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])) {
 
  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);
 
  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++) {
 
  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) {
 
  578            $oldskip = isset($old[0]) ? $old[0]->skip : array();
 
  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();
 
An exception for terminatinating execution or to throw for unit testing.
Global exception class for HTML Purifier; any exceptions we throw are from here.
Generates HTML from tokens.
Supertype for classes that define a strategy for modifying/purifying tokens.
Concrete empty token class.
Concrete end token class.
Concrete start token class.
Concrete text token class.
static fromArray($array)
Creates a zipper from an array, with a hole in the 0-index position.