mirror of
https://github.com/ezyang/htmlpurifier.git
synced 2024-11-09 23:28:42 +00:00
[2.1.3]
- HTMLDefinition->addElement now returns a reference to the created element object, as implied by the documentation . Extend Injector hooks to allow for more powerful injector routines . HTMLDefinition->addBlankElement created, as according to the HTMLModule method git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@1425 48356398-32a2-884e-a903-53898d9a118a
This commit is contained in:
parent
f5371bbad4
commit
552102f7f2
5
NEWS
5
NEWS
@ -25,11 +25,16 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
|
|||||||
- Buggy treatment of end tags of elements that have required attributes
|
- Buggy treatment of end tags of elements that have required attributes
|
||||||
fixed (does not manifest on default tag-set)
|
fixed (does not manifest on default tag-set)
|
||||||
- Spurious internal content reorganization error suppressed
|
- Spurious internal content reorganization error suppressed
|
||||||
|
- HTMLDefinition->addElement now returns a reference to the created
|
||||||
|
element object, as implied by the documentation
|
||||||
. %Core.AcceptFullDocuments renamed to %Core.ConvertDocumentToFragment
|
. %Core.AcceptFullDocuments renamed to %Core.ConvertDocumentToFragment
|
||||||
to better communicate its purpose
|
to better communicate its purpose
|
||||||
. Error unit tests can now specify the expectation of no errors. Future
|
. Error unit tests can now specify the expectation of no errors. Future
|
||||||
iterations of the harness will be extremely strict about what errors
|
iterations of the harness will be extremely strict about what errors
|
||||||
are allowed
|
are allowed
|
||||||
|
. Extend Injector hooks to allow for more powerful injector routines
|
||||||
|
. HTMLDefinition->addBlankElement created, as according to the HTMLModule
|
||||||
|
method
|
||||||
|
|
||||||
2.1.2, released 2007-09-03
|
2.1.2, released 2007-09-03
|
||||||
! Implemented Object module for trusted users
|
! Implemented Object module for trusted users
|
||||||
|
@ -236,13 +236,26 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
|
|||||||
/**
|
/**
|
||||||
* Adds a custom element to your HTML definition
|
* Adds a custom element to your HTML definition
|
||||||
* @note See HTMLPurifier_HTMLModule::addElement for detailed
|
* @note See HTMLPurifier_HTMLModule::addElement for detailed
|
||||||
* parameter descriptions.
|
* parameter and return value descriptions.
|
||||||
*/
|
*/
|
||||||
function addElement($element_name, $type, $contents, $attr_collections, $attributes) {
|
function &addElement($element_name, $type, $contents, $attr_collections, $attributes) {
|
||||||
$module =& $this->getAnonymousModule();
|
$module =& $this->getAnonymousModule();
|
||||||
// assume that if the user is calling this, the element
|
// assume that if the user is calling this, the element
|
||||||
// is safe. This may not be a good idea
|
// is safe. This may not be a good idea
|
||||||
$module->addElement($element_name, true, $type, $contents, $attr_collections, $attributes);
|
$element =& $module->addElement($element_name, true, $type, $contents, $attr_collections, $attributes);
|
||||||
|
return $element;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a blank element to your HTML definition, for overriding
|
||||||
|
* existing behavior
|
||||||
|
* @note See HTMLPurifier_HTMLModule::addBlankElement for detailed
|
||||||
|
* parameter and return value descriptions.
|
||||||
|
*/
|
||||||
|
function &addBlankElement($element_name) {
|
||||||
|
$module =& $this->getAnonymousModule();
|
||||||
|
$element =& $module->addBlankElement($element_name);
|
||||||
|
return $element;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -110,5 +110,12 @@ class HTMLPurifier_Injector
|
|||||||
*/
|
*/
|
||||||
function handleElement(&$token) {}
|
function handleElement(&$token) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifier that is called when an end token is processed
|
||||||
|
* @note This differs from handlers in that the token is read-only
|
||||||
|
*/
|
||||||
|
function notifyEnd($token) {}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,27 +36,22 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
|
|||||||
|
|
||||||
$definition = $config->getHTMLDefinition();
|
$definition = $config->getHTMLDefinition();
|
||||||
|
|
||||||
// CurrentNesting
|
// local variables
|
||||||
$this->currentNesting = array();
|
|
||||||
$context->register('CurrentNesting', $this->currentNesting);
|
|
||||||
|
|
||||||
// InputIndex
|
|
||||||
$this->inputIndex = false;
|
|
||||||
$context->register('InputIndex', $this->inputIndex);
|
|
||||||
|
|
||||||
// InputTokens
|
|
||||||
$context->register('InputTokens', $tokens);
|
|
||||||
$this->inputTokens =& $tokens;
|
|
||||||
|
|
||||||
// OutputTokens
|
|
||||||
$result = array();
|
$result = array();
|
||||||
|
$generator = new HTMLPurifier_Generator();
|
||||||
|
$escape_invalid_tags = $config->get('Core', 'EscapeInvalidTags');
|
||||||
|
$e =& $context->get('ErrorCollector', true);
|
||||||
|
|
||||||
|
// member variables
|
||||||
|
$this->currentNesting = array();
|
||||||
|
$this->inputIndex = false;
|
||||||
|
$this->inputTokens =& $tokens;
|
||||||
$this->outputTokens =& $result;
|
$this->outputTokens =& $result;
|
||||||
|
|
||||||
// %Core.EscapeInvalidTags
|
// context variables
|
||||||
$escape_invalid_tags = $config->get('Core', 'EscapeInvalidTags');
|
$context->register('CurrentNesting', $this->currentNesting);
|
||||||
$generator = new HTMLPurifier_Generator();
|
$context->register('InputIndex', $this->inputIndex);
|
||||||
|
$context->register('InputTokens', $tokens);
|
||||||
$e =& $context->get('ErrorCollector', true);
|
|
||||||
|
|
||||||
// -- begin INJECTOR --
|
// -- begin INJECTOR --
|
||||||
|
|
||||||
@ -95,6 +90,10 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
|
|||||||
trigger_error("Cannot enable $name injector because $error is not allowed", E_USER_WARNING);
|
trigger_error("Cannot enable $name injector because $error is not allowed", E_USER_WARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// warning: most foreach loops follow the convention $i => $x.
|
||||||
|
// be sure, for PHP4 compatibility, to only perform write operations
|
||||||
|
// directly referencing the object using $i: $x is only safe for reads
|
||||||
|
|
||||||
// -- end INJECTOR --
|
// -- end INJECTOR --
|
||||||
|
|
||||||
$token = false;
|
$token = false;
|
||||||
@ -116,7 +115,7 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
|
|||||||
if ($token->type === 'text') {
|
if ($token->type === 'text') {
|
||||||
// injector handler code; duplicated for performance reasons
|
// injector handler code; duplicated for performance reasons
|
||||||
foreach ($this->injectors as $i => $x) {
|
foreach ($this->injectors as $i => $x) {
|
||||||
if (!$x->skip) $x->handleText($token);
|
if (!$x->skip) $this->injectors[$i]->handleText($token);
|
||||||
if (is_array($token)) {
|
if (is_array($token)) {
|
||||||
$this->currentInjector = $i;
|
$this->currentInjector = $i;
|
||||||
break;
|
break;
|
||||||
@ -174,7 +173,7 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
|
|||||||
// injector handler code; duplicated for performance reasons
|
// injector handler code; duplicated for performance reasons
|
||||||
if ($ok) {
|
if ($ok) {
|
||||||
foreach ($this->injectors as $i => $x) {
|
foreach ($this->injectors as $i => $x) {
|
||||||
if (!$x->skip) $x->handleElement($token);
|
if (!$x->skip) $this->injectors[$i]->handleElement($token);
|
||||||
if (is_array($token)) {
|
if (is_array($token)) {
|
||||||
$this->currentInjector = $i;
|
$this->currentInjector = $i;
|
||||||
break;
|
break;
|
||||||
@ -204,6 +203,9 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
|
|||||||
$current_parent = array_pop($this->currentNesting);
|
$current_parent = array_pop($this->currentNesting);
|
||||||
if ($current_parent->name == $token->name) {
|
if ($current_parent->name == $token->name) {
|
||||||
$result[] = $token;
|
$result[] = $token;
|
||||||
|
foreach ($this->injectors as $i => $x) {
|
||||||
|
$this->injectors[$i]->notifyEnd($token);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,15 +242,15 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
|
|||||||
|
|
||||||
// okay, we found it, close all the skipped tags
|
// okay, we found it, close all the skipped tags
|
||||||
// note that skipped tags contains the element we need closed
|
// note that skipped tags contains the element we need closed
|
||||||
$size = count($skipped_tags);
|
for ($i = count($skipped_tags) - 1; $i >= 0; $i--) {
|
||||||
for ($i = $size - 1; $i > 0; $i--) {
|
if ($i && $e && !isset($skipped_tags[$i]->armor['MakeWellFormed_TagClosedError'])) {
|
||||||
if ($e && !isset($skipped_tags[$i]->armor['MakeWellFormed_TagClosedError'])) {
|
|
||||||
$e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag closed by element end', $skipped_tags[$i]);
|
$e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag closed by element end', $skipped_tags[$i]);
|
||||||
}
|
}
|
||||||
$result[] = new HTMLPurifier_Token_End($skipped_tags[$i]->name);
|
$result[] = $new_token = new HTMLPurifier_Token_End($skipped_tags[$i]->name);
|
||||||
|
foreach ($this->injectors as $j => $x) { // $j, not $i!!!
|
||||||
|
$this->injectors[$j]->notifyEnd($new_token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$result[] = new HTMLPurifier_Token_End($skipped_tags[$i]->name);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,17 +259,18 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
|
|||||||
$context->destroy('InputIndex');
|
$context->destroy('InputIndex');
|
||||||
$context->destroy('CurrentToken');
|
$context->destroy('CurrentToken');
|
||||||
|
|
||||||
// we're at the end now, fix all still unclosed tags
|
// we're at the end now, fix all still unclosed tags (this is
|
||||||
// not using processToken() because at this point we don't
|
// duplicated from the end of the loop with some slight modifications)
|
||||||
// care about current nesting
|
// not using $skipped_tags since it would invariably be all of them
|
||||||
if (!empty($this->currentNesting)) {
|
if (!empty($this->currentNesting)) {
|
||||||
$size = count($this->currentNesting);
|
for ($i = count($this->currentNesting) - 1; $i >= 0; $i--) {
|
||||||
for ($i = $size - 1; $i >= 0; $i--) {
|
|
||||||
if ($e && !isset($this->currentNesting[$i]->armor['MakeWellFormed_TagClosedError'])) {
|
if ($e && !isset($this->currentNesting[$i]->armor['MakeWellFormed_TagClosedError'])) {
|
||||||
$e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag closed by document end', $this->currentNesting[$i]);
|
$e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag closed by document end', $this->currentNesting[$i]);
|
||||||
}
|
}
|
||||||
$result[] =
|
$result[] = $new_token = new HTMLPurifier_Token_End($this->currentNesting[$i]->name);
|
||||||
new HTMLPurifier_Token_End($this->currentNesting[$i]->name);
|
foreach ($this->injectors as $j => $x) { // $j, not $i!!!
|
||||||
|
$this->injectors[$j]->notifyEnd($new_token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,19 @@ class HTMLPurifier_Strategy_MakeWellFormed_InjectorTest extends HTMLPurifier_Str
|
|||||||
$this->obj = new HTMLPurifier_Strategy_MakeWellFormed();
|
$this->obj = new HTMLPurifier_Strategy_MakeWellFormed();
|
||||||
$this->config->set('AutoFormat', 'AutoParagraph', true);
|
$this->config->set('AutoFormat', 'AutoParagraph', true);
|
||||||
$this->config->set('AutoFormat', 'Linkify', true);
|
$this->config->set('AutoFormat', 'Linkify', true);
|
||||||
|
generate_mock_once('HTMLPurifier_Injector');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testEndNotification() {
|
||||||
|
$mock = new HTMLPurifier_InjectorMock();
|
||||||
|
$mock->skip = false;
|
||||||
|
$mock->expectAt(0, 'notifyEnd', array(new HTMLPurifier_Token_End('b')));
|
||||||
|
$mock->expectAt(1, 'notifyEnd', array(new HTMLPurifier_Token_End('i')));
|
||||||
|
$mock->expectCallCount('notifyEnd', 2);
|
||||||
|
$this->config->set('AutoFormat', 'AutoParagraph', false);
|
||||||
|
$this->config->set('AutoFormat', 'Linkify', false);
|
||||||
|
$this->config->set('AutoFormat', 'Custom', array($mock));
|
||||||
|
$this->assertResult('<i><b>asdf</b>', '<i><b>asdf</b></i>');
|
||||||
}
|
}
|
||||||
|
|
||||||
function testOnlyAutoParagraph() {
|
function testOnlyAutoParagraph() {
|
||||||
|
Loading…
Reference in New Issue
Block a user