Allow controlling allowed classes in HTMLPurifier

This commit is contained in:
Kijin Sung 2017-01-31 11:45:46 +09:00
parent 5b017affa1
commit 0f9b8cc3d6
2 changed files with 41 additions and 12 deletions

View file

@ -70,21 +70,37 @@ class HTMLFilter
* Filter HTML content to block XSS attacks.
*
* @param string $input
* @param array|bool $allow_classes (optional)
* @param bool $allow_editor_components (optional)
* @param bool $allow_widgets (optional)
* @return string
*/
public static function clean($input, $allow_editor_components = true, $allow_widgets = false)
public static function clean($input, $allow_classes = false, $allow_editor_components = true, $allow_widgets = false)
{
foreach (self::$_preproc as $callback)
{
$input = $callback($input);
}
$allowed_classes = Config::get('mediafilter.classes') ?: array();
if ($allow_widgets)
if ($allow_classes === true)
{
$allowed_classes[] = 'zbxe_widget_output';
$allowed_classes = null;
}
else
{
if (is_array($allow_classes))
{
$allowed_classes = array_values($allow_classes);
}
else
{
$allowed_classes = Config::get('mediafilter.classes') ?: array();
}
if ($allow_widgets)
{
$allowed_classes[] = 'zbxe_widget_output';
}
}
$input = self::_preprocess($input, $allow_editor_components, $allow_widgets);
@ -102,14 +118,17 @@ class HTMLFilter
/**
* Get an instance of HTMLPurifier.
*
* @param array $allowed_classes (optional)
* @param array|null $allowed_classes (optional)
* @return object
*/
public static function getHTMLPurifier($allowed_classes = array())
public static function getHTMLPurifier($allowed_classes = null)
{
// Keep separate instances for different sets of allowed classes.
$allowed_classes = array_unique($allowed_classes);
sort($allowed_classes);
if ($allowed_classes !== null)
{
$allowed_classes = array_unique($allowed_classes);
sort($allowed_classes);
}
$key = sha1(serialize($allowed_classes));
// Create an instance with reasonable defaults.
@ -242,6 +261,7 @@ class HTMLFilter
));
// Support additional properties.
$def->addAttribute('i', 'aria-hidden', 'Text');
$def->addAttribute('img', 'srcset', 'Text');
$def->addAttribute('iframe', 'allowfullscreen', 'Bool');
}

View file

@ -154,6 +154,15 @@ class HTMLFilterTest extends \Codeception\TestCase\Test
$source = '<p class="mytest">Hello World</p>';
$target = '<p class="mytest">Hello World</p>';
$this->assertEquals($target, Rhymix\Framework\Filters\HTMLFilter::clean($source));
config('mediafilter.classes', array());
$source = '<p class="whatever">Hello World</p>';
$target = '<p class="whatever">Hello World</p>';
$this->assertEquals($target, Rhymix\Framework\Filters\HTMLFilter::clean($source, true));
$source = '<p class="foobar whatever">Hello World</p>';
$target = '<p class="foobar">Hello World</p>';
$this->assertEquals($target, Rhymix\Framework\Filters\HTMLFilter::clean($source, array('foobar')));
}
public function testHTMLFilterEditorComponent()
@ -176,11 +185,11 @@ class HTMLFilterTest extends \Codeception\TestCase\Test
$source = '<img somekey="somevalue" otherkey="othervalue" onmouseover="alert(\'xss\');" editor_component="component_name" src="./foo/bar.jpg" alt="My Picture" style="width:320px;height:240px;" width="320" height="240" />';
$target = '<img src="./foo/bar.jpg" alt="My Picture" style="width:320px;height:240px;" width="320" height="240" />';
$this->assertEquals($target, Rhymix\Framework\Filters\HTMLFilter::clean($source, false));
$this->assertEquals($target, Rhymix\Framework\Filters\HTMLFilter::clean($source, false, false));
$source = '<img somekey="somevalue" otherkey="othervalue" onkeypress="alert(\'xss\');" editor_component="component_name" />';
$target = '';
$this->assertEquals($target, Rhymix\Framework\Filters\HTMLFilter::clean($source, false));
$this->assertEquals($target, Rhymix\Framework\Filters\HTMLFilter::clean($source, false, false));
}
public function testHTMLFilterWidgetCode()
@ -191,11 +200,11 @@ class HTMLFilterTest extends \Codeception\TestCase\Test
$source = '<p>Hello World</p><img class="zbxe_widget_output" widget="content" skin="default" colorset="white" widget_sequence="1234" widget_cache="1m" content_type="document" module_srls="56" list_type="normal" tab_type="none" markup_type="table" page_count="1" option_view="title,regdate,nickname" show_browser_title="Y" show_comment_count="Y" show_trackback_count="Y" show_category="Y" show_icon="Y" show_secret="N" order_target="regdate" order_type="desc" thumbnail_type="crop" />';
$target = '<p>Hello World</p><img widget="content" skin="default" colorset="white" widget_sequence="1234" widget_cache="1m" content_type="document" module_srls="56" list_type="normal" tab_type="none" markup_type="table" page_count="1" option_view="title,regdate,nickname" show_browser_title="Y" show_comment_count="Y" show_trackback_count="Y" show_category="Y" show_icon="Y" show_secret="N" order_target="regdate" order_type="desc" thumbnail_type="crop" src="" class="zbxe_widget_output" alt="" />';
$this->assertEquals($target, Rhymix\Framework\Filters\HTMLFilter::clean($source, true, true));
$this->assertEquals($target, Rhymix\Framework\Filters\HTMLFilter::clean($source, true, true, true));
$source = '<p>Hello World</p><img class="zbxe_widget_output" widget="content" onmouseover="alert(\'xss\');" skin="default" colorset="white" widget_sequence="1234" widget_cache="1m" content_type="document" module_srls="56" list_type="normal" tab_type="none" markup_type="table" page_count="1" option_view="title,regdate,nickname" show_browser_title="Y" show_comment_count="Y" show_trackback_count="Y" show_category="Y" show_icon="Y" show_secret="N" order_target="regdate" order_type="desc" thumbnail_type="crop" />';
$target = '<p>Hello World</p><img widget="content" skin="default" colorset="white" widget_sequence="1234" widget_cache="1m" content_type="document" module_srls="56" list_type="normal" tab_type="none" markup_type="table" page_count="1" option_view="title,regdate,nickname" show_browser_title="Y" show_comment_count="Y" show_trackback_count="Y" show_category="Y" show_icon="Y" show_secret="N" order_target="regdate" order_type="desc" thumbnail_type="crop" src="" class="zbxe_widget_output" alt="" />';
$this->assertEquals($target, Rhymix\Framework\Filters\HTMLFilter::clean($source, true, true));
$this->assertEquals($target, Rhymix\Framework\Filters\HTMLFilter::clean($source, true, true, true));
}
public function testHTMLFilterUserContentID()