mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #3021 from tractorcow/pulls/3.1-htmltext-whitelist
BUG HTMLText whitelist considers text nodes
This commit is contained in:
commit
f2b2ee8a68
@ -55,8 +55,9 @@ class HTMLText extends Text {
|
||||
* - whitelist: If provided, a comma-separated list of elements that will be allowed to be stored
|
||||
* (be careful on relying on this for XSS protection - some seemingly-safe elements allow
|
||||
* attributes that can be exploited, for instance <img onload="exploiting_code();" src="..." />)
|
||||
*
|
||||
* @return void
|
||||
* Text nodes outside of HTML tags are filtered out by default, but may be included by adding
|
||||
* the text() directive. E.g. 'link,meta,text()' will allow only <link /> <meta /> and text at
|
||||
* the root level.
|
||||
*/
|
||||
public function setOptions(array $options = array()) {
|
||||
parent::setOptions($options);
|
||||
@ -184,20 +185,36 @@ class HTMLText extends Text {
|
||||
}
|
||||
|
||||
public function prepValueForDB($value) {
|
||||
return parent::prepValueForDB($this->whitelistContent($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the given $value string through the whitelist filter
|
||||
*
|
||||
* @param string $value Input html content
|
||||
* @return string Value with all non-whitelisted content stripped (if applicable)
|
||||
*/
|
||||
public function whitelistContent($value) {
|
||||
if($this->whitelist) {
|
||||
$dom = Injector::inst()->create('HTMLValue', $value);
|
||||
|
||||
$query = array();
|
||||
foreach ($this->whitelist as $tag) $query[] = 'not(self::'.$tag.')';
|
||||
$textFilter = ' | //body/text()';
|
||||
foreach ($this->whitelist as $tag) {
|
||||
if($tag === 'text()') {
|
||||
$textFilter = ''; // Disable text filter if allowed
|
||||
} else {
|
||||
$query[] = 'not(self::'.$tag.')';
|
||||
}
|
||||
}
|
||||
|
||||
foreach($dom->query('//body//*['.implode(' and ', $query).']') as $el) {
|
||||
foreach($dom->query('//body//*['.implode(' and ', $query).']'.$textFilter) as $el) {
|
||||
if ($el->parentNode) $el->parentNode->removeChild($el);
|
||||
}
|
||||
|
||||
$value = $dom->getContent();
|
||||
}
|
||||
|
||||
return parent::prepValueForDB($value);
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -179,11 +179,17 @@ class HTMLTextTest extends SapphireTest {
|
||||
|
||||
function testWhitelist() {
|
||||
$textObj = new HTMLText('Test', 'meta,link');
|
||||
|
||||
$this->assertEquals(
|
||||
$textObj->prepValueForDB('<meta content="Keep"><link href="Also Keep">'),
|
||||
$textObj->prepValueForDB('<meta content="Keep"><p>Remove</p><link href="Also Keep" />'),
|
||||
'Removes any elements not in whitelist'
|
||||
'<meta content="Keep"><link href="Also Keep">',
|
||||
$textObj->whitelistContent('<meta content="Keep"><p>Remove</p><link href="Also Keep" />Remove Text'),
|
||||
'Removes any elements not in whitelist excluding text elements'
|
||||
);
|
||||
|
||||
$textObj = new HTMLText('Test', 'meta,link,text()');
|
||||
$this->assertEquals(
|
||||
'<meta content="Keep"><link href="Also Keep">Keep Text',
|
||||
$textObj->whitelistContent('<meta content="Keep"><p>Remove</p><link href="Also Keep" />Keep Text'),
|
||||
'Removes any elements not in whitelist including text elements'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user