File indexing completed on 2025-02-02 05:43:43
0001 <?php 0002 0003 class HTMLPurifier_Injector_RemoveEmpty extends HTMLPurifier_Injector 0004 { 0005 /** 0006 * @type HTMLPurifier_Context 0007 */ 0008 private $context; 0009 0010 /** 0011 * @type HTMLPurifier_Config 0012 */ 0013 private $config; 0014 0015 /** 0016 * @type HTMLPurifier_AttrValidator 0017 */ 0018 private $attrValidator; 0019 0020 /** 0021 * @type bool 0022 */ 0023 private $removeNbsp; 0024 0025 /** 0026 * @type bool 0027 */ 0028 private $removeNbspExceptions; 0029 0030 /** 0031 * Cached contents of %AutoFormat.RemoveEmpty.Predicate 0032 * @type array 0033 */ 0034 private $exclude; 0035 0036 /** 0037 * @param HTMLPurifier_Config $config 0038 * @param HTMLPurifier_Context $context 0039 * @return void 0040 */ 0041 public function prepare($config, $context) 0042 { 0043 parent::prepare($config, $context); 0044 $this->config = $config; 0045 $this->context = $context; 0046 $this->removeNbsp = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp'); 0047 $this->removeNbspExceptions = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions'); 0048 $this->exclude = $config->get('AutoFormat.RemoveEmpty.Predicate'); 0049 foreach ($this->exclude as $key => $attrs) { 0050 if (!is_array($attrs)) { 0051 // HACK, see HTMLPurifier/Printer/ConfigForm.php 0052 $this->exclude[$key] = explode(';', $attrs); 0053 } 0054 } 0055 $this->attrValidator = new HTMLPurifier_AttrValidator(); 0056 } 0057 0058 /** 0059 * @param HTMLPurifier_Token $token 0060 */ 0061 public function handleElement(&$token) 0062 { 0063 if (!$token instanceof HTMLPurifier_Token_Start) { 0064 return; 0065 } 0066 $next = false; 0067 $deleted = 1; // the current tag 0068 for ($i = count($this->inputZipper->back) - 1; $i >= 0; $i--, $deleted++) { 0069 $next = $this->inputZipper->back[$i]; 0070 if ($next instanceof HTMLPurifier_Token_Text) { 0071 if ($next->is_whitespace) { 0072 continue; 0073 } 0074 if ($this->removeNbsp && !isset($this->removeNbspExceptions[$token->name])) { 0075 $plain = str_replace("\xC2\xA0", "", $next->data); 0076 $isWsOrNbsp = $plain === '' || ctype_space($plain); 0077 if ($isWsOrNbsp) { 0078 continue; 0079 } 0080 } 0081 } 0082 break; 0083 } 0084 if (!$next || ($next instanceof HTMLPurifier_Token_End && $next->name == $token->name)) { 0085 $this->attrValidator->validateToken($token, $this->config, $this->context); 0086 $token->armor['ValidateAttributes'] = true; 0087 if (isset($this->exclude[$token->name])) { 0088 $r = true; 0089 foreach ($this->exclude[$token->name] as $elem) { 0090 if (!isset($token->attr[$elem])) $r = false; 0091 } 0092 if ($r) return; 0093 } 0094 if (isset($token->attr['id']) || isset($token->attr['name'])) { 0095 return; 0096 } 0097 $token = $deleted + 1; 0098 for ($b = 0, $c = count($this->inputZipper->front); $b < $c; $b++) { 0099 $prev = $this->inputZipper->front[$b]; 0100 if ($prev instanceof HTMLPurifier_Token_Text && $prev->is_whitespace) { 0101 continue; 0102 } 0103 break; 0104 } 0105 // This is safe because we removed the token that triggered this. 0106 $this->rewindOffset($b+$deleted); 0107 return; 0108 } 0109 } 0110 } 0111 0112 // vim: et sw=4 sts=4