mirror of
https://github.com/moodle/moodle.git
synced 2025-05-07 00:36:01 +02:00
Prior to this change, all the line endings in the imported HTMLPurifier library were using CRLF (\r\n aka Windows style), but the HTMLPurifier source and also the downloadable artefacts use LF (\n aka Linux style) as line endings. This has been the case since 510d190382003985eafd6f4407190d43509016a5 when with the commit "MDL-38672 import HTML Purifier 4.5.0" all line endings were changed from LF to CRLF. There was no comment in the commit on why this change was done. As the original source uses LF, this commit partly reverts 510d190382003985eafd6f4407190d43509016a5 and goes back to LF as line endings. Signed-off-by: Daniel Ziegenberg <daniel@ziegenberg.at>
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
|