File indexing completed on 2024-12-22 05:36:19

0001 <?php
0002 
0003 /**
0004  * Definition that allows a set of elements, but disallows empty children.
0005  */
0006 class HTMLPurifier_ChildDef_Required extends HTMLPurifier_ChildDef
0007 {
0008     /**
0009      * Lookup table of allowed elements.
0010      * @type array
0011      */
0012     public $elements = array();
0013 
0014     /**
0015      * Whether or not the last passed node was all whitespace.
0016      * @type bool
0017      */
0018     protected $whitespace = false;
0019 
0020     /**
0021      * @param array|string $elements List of allowed element names (lowercase).
0022      */
0023     public function __construct($elements)
0024     {
0025         if (is_string($elements)) {
0026             $elements = str_replace(' ', '', $elements);
0027             $elements = explode('|', $elements);
0028         }
0029         $keys = array_keys($elements);
0030         if ($keys == array_keys($keys)) {
0031             $elements = array_flip($elements);
0032             foreach ($elements as $i => $x) {
0033                 $elements[$i] = true;
0034                 if (empty($i)) {
0035                     unset($elements[$i]);
0036                 } // remove blank
0037             }
0038         }
0039         $this->elements = $elements;
0040     }
0041 
0042     /**
0043      * @type bool
0044      */
0045     public $allow_empty = false;
0046 
0047     /**
0048      * @type string
0049      */
0050     public $type = 'required';
0051 
0052     /**
0053      * @param array $children
0054      * @param HTMLPurifier_Config $config
0055      * @param HTMLPurifier_Context $context
0056      * @return array
0057      */
0058     public function validateChildren($children, $config, $context)
0059     {
0060         // Flag for subclasses
0061         $this->whitespace = false;
0062 
0063         // if there are no tokens, delete parent node
0064         if (empty($children)) {
0065             return false;
0066         }
0067 
0068         // the new set of children
0069         $result = array();
0070 
0071         // whether or not parsed character data is allowed
0072         // this controls whether or not we silently drop a tag
0073         // or generate escaped HTML from it
0074         $pcdata_allowed = isset($this->elements['#PCDATA']);
0075 
0076         // a little sanity check to make sure it's not ALL whitespace
0077         $all_whitespace = true;
0078 
0079         $stack = array_reverse($children);
0080         while (!empty($stack)) {
0081             $node = array_pop($stack);
0082             if (!empty($node->is_whitespace)) {
0083                 $result[] = $node;
0084                 continue;
0085             }
0086             $all_whitespace = false; // phew, we're not talking about whitespace
0087 
0088             if (!isset($this->elements[$node->name])) {
0089                 // special case text
0090                 // XXX One of these ought to be redundant or something
0091                 if ($pcdata_allowed && $node instanceof HTMLPurifier_Node_Text) {
0092                     $result[] = $node;
0093                     continue;
0094                 }
0095                 // spill the child contents in
0096                 // ToDo: Make configurable
0097                 if ($node instanceof HTMLPurifier_Node_Element) {
0098                     for ($i = count($node->children) - 1; $i >= 0; $i--) {
0099                         $stack[] = $node->children[$i];
0100                     }
0101                     continue;
0102                 }
0103                 continue;
0104             }
0105             $result[] = $node;
0106         }
0107         if (empty($result)) {
0108             return false;
0109         }
0110         if ($all_whitespace) {
0111             $this->whitespace = true;
0112             return false;
0113         }
0114         return $result;
0115     }
0116 }
0117 
0118 // vim: et sw=4 sts=4