245 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			PHP
		
	
	
		
		
			
		
	
	
			245 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			PHP
		
	
	
|  | <?php | ||
|  | 
 | ||
|  | /** | ||
|  |  * Error collection class that enables HTML Purifier to report HTML | ||
|  |  * problems back to the user | ||
|  |  */ | ||
|  | class HTMLPurifier_ErrorCollector | ||
|  | { | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Identifiers for the returned error array. These are purposely numeric | ||
|  |      * so list() can be used. | ||
|  |      */ | ||
|  |     const LINENO   = 0; | ||
|  |     const SEVERITY = 1; | ||
|  |     const MESSAGE  = 2; | ||
|  |     const CHILDREN = 3; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * @type array | ||
|  |      */ | ||
|  |     protected $errors; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * @type array | ||
|  |      */ | ||
|  |     protected $_current; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * @type array | ||
|  |      */ | ||
|  |     protected $_stacks = array(array()); | ||
|  | 
 | ||
|  |     /** | ||
|  |      * @type HTMLPurifier_Language | ||
|  |      */ | ||
|  |     protected $locale; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * @type HTMLPurifier_Generator | ||
|  |      */ | ||
|  |     protected $generator; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * @type HTMLPurifier_Context | ||
|  |      */ | ||
|  |     protected $context; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * @type array | ||
|  |      */ | ||
|  |     protected $lines = array(); | ||
|  | 
 | ||
|  |     /** | ||
|  |      * @param HTMLPurifier_Context $context | ||
|  |      */ | ||
|  |     public function __construct($context) | ||
|  |     { | ||
|  |         $this->locale    =& $context->get('Locale'); | ||
|  |         $this->context   = $context; | ||
|  |         $this->_current  =& $this->_stacks[0]; | ||
|  |         $this->errors    =& $this->_stacks[0]; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Sends an error message to the collector for later use | ||
|  |      * @param int $severity Error severity, PHP error style (don't use E_USER_) | ||
|  |      * @param string $msg Error message text | ||
|  |      */ | ||
|  |     public function send($severity, $msg) | ||
|  |     { | ||
|  |         $args = array(); | ||
|  |         if (func_num_args() > 2) { | ||
|  |             $args = func_get_args(); | ||
|  |             array_shift($args); | ||
|  |             unset($args[0]); | ||
|  |         } | ||
|  | 
 | ||
|  |         $token = $this->context->get('CurrentToken', true); | ||
|  |         $line  = $token ? $token->line : $this->context->get('CurrentLine', true); | ||
|  |         $col   = $token ? $token->col  : $this->context->get('CurrentCol', true); | ||
|  |         $attr  = $this->context->get('CurrentAttr', true); | ||
|  | 
 | ||
|  |         // perform special substitutions, also add custom parameters
 | ||
|  |         $subst = array(); | ||
|  |         if (!is_null($token)) { | ||
|  |             $args['CurrentToken'] = $token; | ||
|  |         } | ||
|  |         if (!is_null($attr)) { | ||
|  |             $subst['$CurrentAttr.Name'] = $attr; | ||
|  |             if (isset($token->attr[$attr])) { | ||
|  |                 $subst['$CurrentAttr.Value'] = $token->attr[$attr]; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         if (empty($args)) { | ||
|  |             $msg = $this->locale->getMessage($msg); | ||
|  |         } else { | ||
|  |             $msg = $this->locale->formatMessage($msg, $args); | ||
|  |         } | ||
|  | 
 | ||
|  |         if (!empty($subst)) { | ||
|  |             $msg = strtr($msg, $subst); | ||
|  |         } | ||
|  | 
 | ||
|  |         // (numerically indexed)
 | ||
|  |         $error = array( | ||
|  |             self::LINENO   => $line, | ||
|  |             self::SEVERITY => $severity, | ||
|  |             self::MESSAGE  => $msg, | ||
|  |             self::CHILDREN => array() | ||
|  |         ); | ||
|  |         $this->_current[] = $error; | ||
|  | 
 | ||
|  |         // NEW CODE BELOW ...
 | ||
|  |         // Top-level errors are either:
 | ||
|  |         //  TOKEN type, if $value is set appropriately, or
 | ||
|  |         //  "syntax" type, if $value is null
 | ||
|  |         $new_struct = new HTMLPurifier_ErrorStruct(); | ||
|  |         $new_struct->type = HTMLPurifier_ErrorStruct::TOKEN; | ||
|  |         if ($token) { | ||
|  |             $new_struct->value = clone $token; | ||
|  |         } | ||
|  |         if (is_int($line) && is_int($col)) { | ||
|  |             if (isset($this->lines[$line][$col])) { | ||
|  |                 $struct = $this->lines[$line][$col]; | ||
|  |             } else { | ||
|  |                 $struct = $this->lines[$line][$col] = $new_struct; | ||
|  |             } | ||
|  |             // These ksorts may present a performance problem
 | ||
|  |             ksort($this->lines[$line], SORT_NUMERIC); | ||
|  |         } else { | ||
|  |             if (isset($this->lines[-1])) { | ||
|  |                 $struct = $this->lines[-1]; | ||
|  |             } else { | ||
|  |                 $struct = $this->lines[-1] = $new_struct; | ||
|  |             } | ||
|  |         } | ||
|  |         ksort($this->lines, SORT_NUMERIC); | ||
|  | 
 | ||
|  |         // Now, check if we need to operate on a lower structure
 | ||
|  |         if (!empty($attr)) { | ||
|  |             $struct = $struct->getChild(HTMLPurifier_ErrorStruct::ATTR, $attr); | ||
|  |             if (!$struct->value) { | ||
|  |                 $struct->value = array($attr, 'PUT VALUE HERE'); | ||
|  |             } | ||
|  |         } | ||
|  |         if (!empty($cssprop)) { | ||
|  |             $struct = $struct->getChild(HTMLPurifier_ErrorStruct::CSSPROP, $cssprop); | ||
|  |             if (!$struct->value) { | ||
|  |                 // if we tokenize CSS this might be a little more difficult to do
 | ||
|  |                 $struct->value = array($cssprop, 'PUT VALUE HERE'); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         // Ok, structs are all setup, now time to register the error
 | ||
|  |         $struct->addError($severity, $msg); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Retrieves raw error data for custom formatter to use | ||
|  |      */ | ||
|  |     public function getRaw() | ||
|  |     { | ||
|  |         return $this->errors; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Default HTML formatting implementation for error messages | ||
|  |      * @param HTMLPurifier_Config $config Configuration, vital for HTML output nature | ||
|  |      * @param array $errors Errors array to display; used for recursion. | ||
|  |      * @return string | ||
|  |      */ | ||
|  |     public function getHTMLFormatted($config, $errors = null) | ||
|  |     { | ||
|  |         $ret = array(); | ||
|  | 
 | ||
|  |         $this->generator = new HTMLPurifier_Generator($config, $this->context); | ||
|  |         if ($errors === null) { | ||
|  |             $errors = $this->errors; | ||
|  |         } | ||
|  | 
 | ||
|  |         // 'At line' message needs to be removed
 | ||
|  | 
 | ||
|  |         // generation code for new structure goes here. It needs to be recursive.
 | ||
|  |         foreach ($this->lines as $line => $col_array) { | ||
|  |             if ($line == -1) { | ||
|  |                 continue; | ||
|  |             } | ||
|  |             foreach ($col_array as $col => $struct) { | ||
|  |                 $this->_renderStruct($ret, $struct, $line, $col); | ||
|  |             } | ||
|  |         } | ||
|  |         if (isset($this->lines[-1])) { | ||
|  |             $this->_renderStruct($ret, $this->lines[-1]); | ||
|  |         } | ||
|  | 
 | ||
|  |         if (empty($errors)) { | ||
|  |             return '<p>' . $this->locale->getMessage('ErrorCollector: No errors') . '</p>'; | ||
|  |         } else { | ||
|  |             return '<ul><li>' . implode('</li><li>', $ret) . '</li></ul>'; | ||
|  |         } | ||
|  | 
 | ||
|  |     } | ||
|  | 
 | ||
|  |     private function _renderStruct(&$ret, $struct, $line = null, $col = null) | ||
|  |     { | ||
|  |         $stack = array($struct); | ||
|  |         $context_stack = array(array()); | ||
|  |         while ($current = array_pop($stack)) { | ||
|  |             $context = array_pop($context_stack); | ||
|  |             foreach ($current->errors as $error) { | ||
|  |                 list($severity, $msg) = $error; | ||
|  |                 $string = ''; | ||
|  |                 $string .= '<div>'; | ||
|  |                 // W3C uses an icon to indicate the severity of the error.
 | ||
|  |                 $error = $this->locale->getErrorName($severity); | ||
|  |                 $string .= "<span class=\"error e$severity\"><strong>$error</strong></span> ";
 | ||
|  |                 if (!is_null($line) && !is_null($col)) { | ||
|  |                     $string .= "<em class=\"location\">Line $line, Column $col: </em> "; | ||
|  |                 } else { | ||
|  |                     $string .= '<em class="location">End of Document: </em> '; | ||
|  |                 } | ||
|  |                 $string .= '<strong class="description">' . $this->generator->escape($msg) . '</strong> '; | ||
|  |                 $string .= '</div>'; | ||
|  |                 // Here, have a marker for the character on the column appropriate.
 | ||
|  |                 // Be sure to clip extremely long lines.
 | ||
|  |                 //$string .= '<pre>';
 | ||
|  |                 //$string .= '';
 | ||
|  |                 //$string .= '</pre>';
 | ||
|  |                 $ret[] = $string; | ||
|  |             } | ||
|  |             foreach ($current->children as $array) { | ||
|  |                 $context[] = $current; | ||
|  |                 $stack = array_merge($stack, array_reverse($array, true)); | ||
|  |                 for ($i = count($array); $i > 0; $i--) { | ||
|  |                     $context_stack[] = $context; | ||
|  |                 } | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | // vim: et sw=4 sts=4
 |