Escape story fields and clean story HTML with HTML Purifier.

Add HTML Purifier 4.19.1. Stories are purified when they are saved and
when they are shown.
This commit is contained in:
tim
2026-09-25 21:34:10 +02:00
parent e881ddb458
commit 00e1829f8b
385 changed files with 33174 additions and 12 deletions
@@ -0,0 +1,124 @@
<?php
/**
* Adds important param elements to inside of object in order to make
* things safe.
*/
class HTMLPurifier_Injector_SafeObject extends HTMLPurifier_Injector
{
/**
* @type string
*/
public $name = 'SafeObject';
/**
* @type array
*/
public $needed = array('object', 'param');
/**
* @type array
*/
protected $objectStack = array();
/**
* @type array
*/
protected $paramStack = array();
/**
* Keep this synchronized with AttrTransform/SafeParam.php.
* @type array
*/
protected $addParam = array(
'allowScriptAccess' => 'never',
'allowNetworking' => 'internal',
);
/**
* These are all lower-case keys.
* @type array
*/
protected $allowedParam = array(
'wmode' => true,
'movie' => true,
'flashvars' => true,
'src' => true,
'allowfullscreen' => true, // if omitted, assume to be 'false'
);
/**
* @param HTMLPurifier_Config $config
* @param HTMLPurifier_Context $context
* @return void
*/
public function prepare($config, $context)
{
parent::prepare($config, $context);
}
/**
* @param HTMLPurifier_Token $token
*/
public function handleElement(&$token)
{
if ($token->name == 'object') {
$this->objectStack[] = $token;
$this->paramStack[] = array();
$new = array($token);
foreach ($this->addParam as $name => $value) {
$new[] = new HTMLPurifier_Token_Empty('param', array('name' => $name, 'value' => $value));
}
$token = $new;
} elseif ($token->name == 'param') {
$nest = count($this->currentNesting) - 1;
if ($nest >= 0 && $this->currentNesting[$nest]->name === 'object') {
$i = count($this->objectStack) - 1;
if (!isset($token->attr['name'])) {
$token = false;
return;
}
$n = $token->attr['name'];
// We need this fix because YouTube doesn't supply a data
// attribute, which we need if a type is specified. This is
// *very* Flash specific.
if (!isset($this->objectStack[$i]->attr['data']) &&
($token->attr['name'] == 'movie' || $token->attr['name'] == 'src')
) {
$this->objectStack[$i]->attr['data'] = $token->attr['value'];
}
// Check if the parameter is the correct value but has not
// already been added
if (!isset($this->paramStack[$i][$n]) &&
isset($this->addParam[$n]) &&
$token->attr['name'] === $this->addParam[$n]) {
// keep token, and add to param stack
$this->paramStack[$i][$n] = true;
} elseif (isset($this->allowedParam[strtolower($n)])) {
// keep token, don't do anything to it
// (could possibly check for duplicates here)
// Note: In principle, parameters should be case sensitive.
// But it seems they are not really; so accept any case.
} else {
$token = false;
}
} else {
// not directly inside an object, DENY!
$token = false;
}
}
}
public function handleEnd(&$token)
{
// This is the WRONG way of handling the object and param stacks;
// we should be inserting them directly on the relevant object tokens
// so that the global stack handling handles it.
if ($token->name == 'object') {
array_pop($this->objectStack);
array_pop($this->paramStack);
}
}
}
// vim: et sw=4 sts=4