diff --git a/library/HTMLPurifier/Generator.php b/library/HTMLPurifier/Generator.php index b6a9aa24..d717332e 100644 --- a/library/HTMLPurifier/Generator.php +++ b/library/HTMLPurifier/Generator.php @@ -21,6 +21,13 @@ HTMLPurifier_ConfigSchema::define( 'This directive was available since 1.1.' ); +HTMLPurifier_ConfigSchema::define( + 'Core', 'CommentScriptContents', true, 'bool', + 'Determines whether or not HTML Purifier should attempt to fix up '. + 'the contents of script tags for legacy browsers with comments. This '. + 'directive was available since 1.7.' +); + // extension constraints could be factored into ConfigSchema HTMLPurifier_ConfigSchema::define( 'Core', 'TidyFormat', false, 'bool', @@ -54,6 +61,12 @@ class HTMLPurifier_Generator */ var $_xhtml = true; + /** + * Bool cache of %Core.CommentScriptContents + * @private + */ + var $_scriptFix = false; + /** * Generates HTML from an array of tokens. * @param $tokens Array of HTMLPurifier_Token @@ -63,11 +76,20 @@ class HTMLPurifier_Generator function generateFromTokens($tokens, $config, &$context) { $html = ''; if (!$config) $config = HTMLPurifier_Config::createDefault(); - $this->_clean_utf8 = $config->get('Core', 'CleanUTF8DuringGeneration'); - $this->_xhtml = $config->get('Core', 'XHTML'); + $this->_clean_utf8 = $config->get('Core', 'CleanUTF8DuringGeneration'); + $this->_xhtml = $config->get('Core', 'XHTML'); + $this->_scriptFix = $config->get('Core', 'CommentScriptContents'); if (!$tokens) return ''; - foreach ($tokens as $token) { - $html .= $this->generateFromToken($token); + for ($i = 0, $size = count($tokens); $i < $size; $i++) { + if ($this->_scriptFix && $tokens[$i]->name === 'script') { + // script special case + $html .= $this->generateFromToken($tokens[$i++]); + $html .= $this->generateScriptFromToken($tokens[$i++]); + while ($tokens[$i]->name != 'script') { + $html .= $this->generateScriptFromToken($tokens[$i++]); + } + } + $html .= $this->generateFromToken($tokens[$i]); } if ($config->get('Core', 'TidyFormat') && extension_loaded('tidy')) { @@ -125,6 +147,18 @@ class HTMLPurifier_Generator } } + /** + * Special case processor for the contents of script tags + * @warning This runs into problems if there's already a literal + * --> somewhere inside the script contents. + */ + function generateScriptFromToken($token) { + if (!$token->type == 'text') return $this->generateFromToken($token); + return ''; + // more advanced version: + // return ''; + } + /** * Generates attribute declarations from attribute array. * @param $assoc_array_of_attributes Attribute array diff --git a/library/HTMLPurifier/HTMLModuleManager.php b/library/HTMLPurifier/HTMLModuleManager.php index 8d3ad2d9..6adbeb59 100644 --- a/library/HTMLPurifier/HTMLModuleManager.php +++ b/library/HTMLPurifier/HTMLModuleManager.php @@ -41,6 +41,13 @@ HTMLPurifier_ConfigSchema::define( 'like %Core.XHTML or %HTML.Strict.' ); +HTMLPurifier_ConfigSchema::define( + 'HTML', 'Trusted', false, 'bool', + 'Indicates whether or not the user input is trusted or not. If the '. + 'input is trusted, a more expansive set of allowed tags and attributes '. + 'will be used. This directive has been available since 1.7.0.' +); + class HTMLPurifier_HTMLModuleManager { @@ -221,6 +228,8 @@ class HTMLPurifier_HTMLModuleManager */ function setup($config) { + $this->trusted = $config->get('HTML', 'Trusted'); + // generate $doctype = $this->doctypes->make($config); $modules = $doctype->modules; @@ -325,7 +334,7 @@ class HTMLPurifier_HTMLModuleManager // element with unknown safety is not to be trusted. // however, a merge-in definition with undefined safety // is fine - if (!$new_def->safe) continue; + if (!$trusted && !$new_def->safe) continue; $def = $new_def; } elseif ($def) { $def->mergeIn($new_def); diff --git a/tests/HTMLPurifier/GeneratorTest.php b/tests/HTMLPurifier/GeneratorTest.php index f16b95ed..7528f9fa 100644 --- a/tests/HTMLPurifier/GeneratorTest.php +++ b/tests/HTMLPurifier/GeneratorTest.php @@ -124,6 +124,31 @@ class HTMLPurifier_GeneratorTest extends HTMLPurifier_Harness $this->assertIdentical($expect, $result); } + function test_generateFromTokens_Scripting() { + $this->config = HTMLPurifier_Config::createDefault(); + + $this->assertGeneration( + array( + new HTMLPurifier_Token_Start('script'), + new HTMLPurifier_Token_Text('alert(3 < 5);'), + new HTMLPurifier_Token_End('script') + ), + "" + ); + + $this->config = HTMLPurifier_Config::createDefault(); + $this->config->set('Core', 'CommentScriptContents', false); + + $this->assertGeneration( + array( + new HTMLPurifier_Token_Start('script'), + new HTMLPurifier_Token_Text('alert(3 < 5);'), + new HTMLPurifier_Token_End('script') + ), + "" + ); + } + function test_generateFromTokens_XHTMLoff() { $this->config = HTMLPurifier_Config::createDefault(); $this->config->set('Core', 'XHTML', false); diff --git a/tests/HTMLPurifier/HTMLModule/ScriptingTest.php b/tests/HTMLPurifier/HTMLModule/ScriptingTest.php new file mode 100644 index 00000000..69b83e0a --- /dev/null +++ b/tests/HTMLPurifier/HTMLModule/ScriptingTest.php @@ -0,0 +1,52 @@ +assertResult( + '', 'foo();' + ); + + // enabled + $this->assertResult( + '', true, + array('HTML.Trusted' => true) + ); + + // max + $this->assertResult( + '', true, + array('HTML.Trusted' => true, 'Core.CommentScriptContents' => false) + ); + + // unsupported + $this->assertResult( + '', + '', + array('HTML.Trusted' => true, 'Core.CommentScriptContents' => false) + ); + + // invalid children + $this->assertResult( + '', + '', + array('HTML.Trusted' => true, 'Core.CommentScriptContents' => false) + ); + + } + +} + +?> \ No newline at end of file diff --git a/tests/test_files.php b/tests/test_files.php index 602dc47b..81df7851 100644 --- a/tests/test_files.php +++ b/tests/test_files.php @@ -68,6 +68,7 @@ $test_files[] = 'HTMLModule/EditTest.php'; $test_files[] = 'HTMLModule/HypertextTest.php'; $test_files[] = 'HTMLModule/ImageTest.php'; $test_files[] = 'HTMLModule/LegacyTest.php'; +$test_files[] = 'HTMLModule/ScriptingTest.php'; $test_files[] = 'IDAccumulatorTest.php'; $test_files[] = 'LanguageFactoryTest.php'; $test_files[] = 'LanguageTest.php';