mirror of
https://github.com/ezyang/htmlpurifier.git
synced 2024-12-23 17:01:51 +00:00
fa413e96ac
Previous design of injector streaming involved editability only to start, empty and text tokens, because they could be safely modified without causing formedness errors. By modifying notifyEnd to operate before MakeWellFormed's safeguards kick into effect, it can be converted into a handle function, allowing for arbitrary modification of end tags. This change involved quite a bit of restructuring of the MakeWellFormed code, including the moving of end of document tags to inside the loop, so rewinding on those tags would be functional, increased reuse of the end tag codepath by code that inserts end tags (as they could be changed out from under you), and processToken modified to have an extra parameter to force re-processing of a token if the original token was an end token. We're not exactly sure if handleEnd works at this point, but the important talking point about this refactoring is that nothing else broke. Also, a number of convenience functions were moved from AutoParagraph to the Injector supertype (specifically: forward, forwardToEndToken, backward, and current). Signed-off-by: Edward Z. Yang <edwardzyang@thewritingpot.com>
87 lines
3.1 KiB
PHP
87 lines
3.1 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Adds important param elements to inside of object in order to make
|
|
* things safe.
|
|
*/
|
|
class HTMLPurifier_Injector_SafeObject extends HTMLPurifier_Injector
|
|
{
|
|
public $name = 'SafeObject';
|
|
public $needed = array('object', 'param');
|
|
|
|
protected $objectStack = array();
|
|
protected $paramStack = array();
|
|
|
|
// Keep this synchronized with AttrTransform/SafeParam.php
|
|
protected $addParam = array(
|
|
'allowScriptAccess' => 'never',
|
|
'allowNetworking' => 'internal',
|
|
);
|
|
protected $allowedParam = array(
|
|
'wmode' => true,
|
|
'movie' => true,
|
|
);
|
|
|
|
public function prepare($config, $context) {
|
|
parent::prepare($config, $context);
|
|
}
|
|
|
|
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') {
|
|
$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[$n])) {
|
|
// keep token, don't do anything to it
|
|
// (could possibly check for duplicates here)
|
|
} 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);
|
|
}
|
|
}
|
|
|
|
}
|
|
|