209 lines
		
	
	
	
		
			7.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			209 lines
		
	
	
	
		
			7.2 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;
 | |
| 
 | |
|     protected $errors;
 | |
|     protected $_current;
 | |
|     protected $_stacks = array(array());
 | |
|     protected $locale;
 | |
|     protected $generator;
 | |
|     protected $context;
 | |
| 
 | |
|     protected $lines = array();
 | |
| 
 | |
|     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 $severity int Error severity, PHP error style (don't use E_USER_)
 | |
|      * @param $msg string Error message text
 | |
|      * @param $subst1 string First substitution for $msg
 | |
|      * @param $subst2 string ...
 | |
|      */
 | |
|     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 ...
 | |
| 
 | |
|         $struct = null;
 | |
|         // 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
 | |
|      * @param List of arrays in format of array(line of error,
 | |
|      *        error severity, error message,
 | |
|      *        recursive sub-errors array)
 | |
|      */
 | |
|     public function getRaw() {
 | |
|         return $this->errors;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Default HTML formatting implementation for error messages
 | |
|      * @param $config Configuration array, vital for HTML output nature
 | |
|      * @param $errors Errors array to display; used for recursion.
 | |
|      */
 | |
|     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 $type => $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
 |