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)
 
  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])) {
 
  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);
 
  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++) {
 
  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();
 
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.