File indexing completed on 2025-01-26 05:29:09
0001 <?php 0002 0003 /** 0004 * Injects tokens into the document while parsing for well-formedness. 0005 * This enables "formatter-like" functionality such as auto-paragraphing, 0006 * smiley-ification and linkification to take place. 0007 * 0008 * A note on how handlers create changes; this is done by assigning a new 0009 * value to the $token reference. These values can take a variety of forms and 0010 * are best described HTMLPurifier_Strategy_MakeWellFormed->processToken() 0011 * documentation. 0012 * 0013 * @todo Allow injectors to request a re-run on their output. This 0014 * would help if an operation is recursive. 0015 */ 0016 abstract class HTMLPurifier_Injector 0017 { 0018 0019 /** 0020 * Advisory name of injector, this is for friendly error messages. 0021 * @type string 0022 */ 0023 public $name; 0024 0025 /** 0026 * @type HTMLPurifier_HTMLDefinition 0027 */ 0028 protected $htmlDefinition; 0029 0030 /** 0031 * Reference to CurrentNesting variable in Context. This is an array 0032 * list of tokens that we are currently "inside" 0033 * @type array 0034 */ 0035 protected $currentNesting; 0036 0037 /** 0038 * Reference to current token. 0039 * @type HTMLPurifier_Token 0040 */ 0041 protected $currentToken; 0042 0043 /** 0044 * Reference to InputZipper variable in Context. 0045 * @type HTMLPurifier_Zipper 0046 */ 0047 protected $inputZipper; 0048 0049 /** 0050 * Array of elements and attributes this injector creates and therefore 0051 * need to be allowed by the definition. Takes form of 0052 * array('element' => array('attr', 'attr2'), 'element2') 0053 * @type array 0054 */ 0055 public $needed = array(); 0056 0057 /** 0058 * Number of elements to rewind backwards (relative). 0059 * @type bool|int 0060 */ 0061 protected $rewindOffset = false; 0062 0063 /** 0064 * Rewind to a spot to re-perform processing. This is useful if you 0065 * deleted a node, and now need to see if this change affected any 0066 * earlier nodes. Rewinding does not affect other injectors, and can 0067 * result in infinite loops if not used carefully. 0068 * @param bool|int $offset 0069 * @warning HTML Purifier will prevent you from fast-forwarding with this 0070 * function. 0071 */ 0072 public function rewindOffset($offset) 0073 { 0074 $this->rewindOffset = $offset; 0075 } 0076 0077 /** 0078 * Retrieves rewind offset, and then unsets it. 0079 * @return bool|int 0080 */ 0081 public function getRewindOffset() 0082 { 0083 $r = $this->rewindOffset; 0084 $this->rewindOffset = false; 0085 return $r; 0086 } 0087 0088 /** 0089 * Prepares the injector by giving it the config and context objects: 0090 * this allows references to important variables to be made within 0091 * the injector. This function also checks if the HTML environment 0092 * will work with the Injector (see checkNeeded()). 0093 * @param HTMLPurifier_Config $config 0094 * @param HTMLPurifier_Context $context 0095 * @return bool|string Boolean false if success, string of missing needed element/attribute if failure 0096 */ 0097 public function prepare($config, $context) 0098 { 0099 $this->htmlDefinition = $config->getHTMLDefinition(); 0100 // Even though this might fail, some unit tests ignore this and 0101 // still test checkNeeded, so be careful. Maybe get rid of that 0102 // dependency. 0103 $result = $this->checkNeeded($config); 0104 if ($result !== false) { 0105 return $result; 0106 } 0107 $this->currentNesting =& $context->get('CurrentNesting'); 0108 $this->currentToken =& $context->get('CurrentToken'); 0109 $this->inputZipper =& $context->get('InputZipper'); 0110 return false; 0111 } 0112 0113 /** 0114 * This function checks if the HTML environment 0115 * will work with the Injector: if p tags are not allowed, the 0116 * Auto-Paragraphing injector should not be enabled. 0117 * @param HTMLPurifier_Config $config 0118 * @return bool|string Boolean false if success, string of missing needed element/attribute if failure 0119 */ 0120 public function checkNeeded($config) 0121 { 0122 $def = $config->getHTMLDefinition(); 0123 foreach ($this->needed as $element => $attributes) { 0124 if (is_int($element)) { 0125 $element = $attributes; 0126 } 0127 if (!isset($def->info[$element])) { 0128 return $element; 0129 } 0130 if (!is_array($attributes)) { 0131 continue; 0132 } 0133 foreach ($attributes as $name) { 0134 if (!isset($def->info[$element]->attr[$name])) { 0135 return "$element.$name"; 0136 } 0137 } 0138 } 0139 return false; 0140 } 0141 0142 /** 0143 * Tests if the context node allows a certain element 0144 * @param string $name Name of element to test for 0145 * @return bool True if element is allowed, false if it is not 0146 */ 0147 public function allowsElement($name) 0148 { 0149 if (!empty($this->currentNesting)) { 0150 $parent_token = array_pop($this->currentNesting); 0151 $this->currentNesting[] = $parent_token; 0152 $parent = $this->htmlDefinition->info[$parent_token->name]; 0153 } else { 0154 $parent = $this->htmlDefinition->info_parent_def; 0155 } 0156 if (!isset($parent->child->elements[$name]) || isset($parent->excludes[$name])) { 0157 return false; 0158 } 0159 // check for exclusion 0160 for ($i = count($this->currentNesting) - 2; $i >= 0; $i--) { 0161 $node = $this->currentNesting[$i]; 0162 $def = $this->htmlDefinition->info[$node->name]; 0163 if (isset($def->excludes[$name])) { 0164 return false; 0165 } 0166 } 0167 return true; 0168 } 0169 0170 /** 0171 * Iterator function, which starts with the next token and continues until 0172 * you reach the end of the input tokens. 0173 * @warning Please prevent previous references from interfering with this 0174 * functions by setting $i = null beforehand! 0175 * @param int $i Current integer index variable for inputTokens 0176 * @param HTMLPurifier_Token $current Current token variable. 0177 * Do NOT use $token, as that variable is also a reference 0178 * @return bool 0179 */ 0180 protected function forward(&$i, &$current) 0181 { 0182 if ($i === null) { 0183 $i = count($this->inputZipper->back) - 1; 0184 } else { 0185 $i--; 0186 } 0187 if ($i < 0) { 0188 return false; 0189 } 0190 $current = $this->inputZipper->back[$i]; 0191 return true; 0192 } 0193 0194 /** 0195 * Similar to _forward, but accepts a third parameter $nesting (which 0196 * should be initialized at 0) and stops when we hit the end tag 0197 * for the node $this->inputIndex starts in. 0198 * @param int $i Current integer index variable for inputTokens 0199 * @param HTMLPurifier_Token $current Current token variable. 0200 * Do NOT use $token, as that variable is also a reference 0201 * @param int $nesting 0202 * @return bool 0203 */ 0204 protected function forwardUntilEndToken(&$i, &$current, &$nesting) 0205 { 0206 $result = $this->forward($i, $current); 0207 if (!$result) { 0208 return false; 0209 } 0210 if ($nesting === null) { 0211 $nesting = 0; 0212 } 0213 if ($current instanceof HTMLPurifier_Token_Start) { 0214 $nesting++; 0215 } elseif ($current instanceof HTMLPurifier_Token_End) { 0216 if ($nesting <= 0) { 0217 return false; 0218 } 0219 $nesting--; 0220 } 0221 return true; 0222 } 0223 0224 /** 0225 * Iterator function, starts with the previous token and continues until 0226 * you reach the beginning of input tokens. 0227 * @warning Please prevent previous references from interfering with this 0228 * functions by setting $i = null beforehand! 0229 * @param int $i Current integer index variable for inputTokens 0230 * @param HTMLPurifier_Token $current Current token variable. 0231 * Do NOT use $token, as that variable is also a reference 0232 * @return bool 0233 */ 0234 protected function backward(&$i, &$current) 0235 { 0236 if ($i === null) { 0237 $i = count($this->inputZipper->front) - 1; 0238 } else { 0239 $i--; 0240 } 0241 if ($i < 0) { 0242 return false; 0243 } 0244 $current = $this->inputZipper->front[$i]; 0245 return true; 0246 } 0247 0248 /** 0249 * Handler that is called when a text token is processed 0250 */ 0251 public function handleText(&$token) 0252 { 0253 } 0254 0255 /** 0256 * Handler that is called when a start or empty token is processed 0257 */ 0258 public function handleElement(&$token) 0259 { 0260 } 0261 0262 /** 0263 * Handler that is called when an end token is processed 0264 */ 0265 public function handleEnd(&$token) 0266 { 0267 $this->notifyEnd($token); 0268 } 0269 0270 /** 0271 * Notifier that is called when an end token is processed 0272 * @param HTMLPurifier_Token $token Current token variable. 0273 * @note This differs from handlers in that the token is read-only 0274 * @deprecated 0275 */ 0276 public function notifyEnd($token) 0277 { 0278 } 0279 } 0280 0281 // vim: et sw=4 sts=4