S2OJ/web/app/vendor/htmlpurifier/HTMLPurifier/ErrorCollector.php
Masco Skray 96d4a3ecf7 style(judger,web): move code out from subfolder "1"
Due to historical reasons, the code is in subfolder "1".
With SVN removal, we place the code back and remove the annoying "1" folder.
2019-06-14 23:34:41 +08:00

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