diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/field/modules/text/text.test | 12 | ||||
-rw-r--r-- | modules/filter/filter.module | 79 | ||||
-rw-r--r-- | modules/filter/filter.test | 84 | ||||
-rw-r--r-- | modules/system/system.install | 11 |
4 files changed, 102 insertions, 84 deletions
diff --git a/modules/field/modules/text/text.test b/modules/field/modules/text/text.test index ae8a0a06a..db7c96c7c 100644 --- a/modules/field/modules/text/text.test +++ b/modules/field/modules/text/text.test @@ -286,12 +286,12 @@ class TextSummaryTestCase extends DrupalWebTestCase { // And using a text format WITH the line-break and htmlcorrector filters. $expected_lb = array( "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", - "<", - "<p", - "<p></p>", - "<p></p>", - "<p></p>", - "<p></p>", + "", + "<p />", + "<p />", + "<p />", + "<p />", + "<p />", "<p>\nHi</p>", "<p>\nHi</p>", "<p>\nHi</p>", diff --git a/modules/filter/filter.module b/modules/filter/filter.module index 00c4b5568..6b578a0a0 100644 --- a/modules/filter/filter.module +++ b/modules/filter/filter.module @@ -757,74 +757,21 @@ function _filter_url($text, $format) { * Scan input and make sure that all HTML tags are properly closed and nested. */ function _filter_htmlcorrector($text) { - // Prepare tag lists. - static $no_nesting, $single_use; - if (!isset($no_nesting)) { - // Tags which cannot be nested but are typically left unclosed. - $no_nesting = drupal_map_assoc(array('li', 'p')); - - // Single use tags in HTML4 - $single_use = drupal_map_assoc(array('base', 'meta', 'link', 'hr', 'br', 'param', 'img', 'area', 'input', 'col', 'frame')); + // Ignore warnings during HTML soup loading. + $htmlDom = @DOMDocument::loadHTML('<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>' . $text . '</body></html>'); + + // The result of DOMDocument->saveXML($bodyNode) is a partial (X)HTML document. + // We only need what is inside the body tag. + $bodyNode = $htmlDom->getElementsByTagName('body')->item(0); + if (preg_match("|^<body[^>]*>(.*)</body>$|s", $htmlDom->saveXML($bodyNode), $matches)) { + $body_content = $matches[1]; + // The XHTML guidelines recommend to include a space before the trailing / + // and > of empty elements for better rendering on HTML user agents. + return preg_replace('|<([^>]*)/>|i', '<$1 />', $body_content); } - - // Properly entify angles. - $text = preg_replace('!<([^a-zA-Z/])!', '<\1', $text); - - // Split tags from text. - $split = preg_split('/<([^>]+?)>/', $text, -1, PREG_SPLIT_DELIM_CAPTURE); - // Note: PHP ensures the array consists of alternating delimiters and literals - // and begins and ends with a literal (inserting $null as required). - - $tag = FALSE; // Odd/even counter. Tag or no tag. - $stack = array(); - $output = ''; - foreach ($split as $value) { - // Process HTML tags. - if ($tag) { - list($tagname) = explode(' ', strtolower($value), 2); - // Closing tag - if ($tagname{0} == '/') { - $tagname = substr($tagname, 1); - // Discard XHTML closing tags for single use tags. - if (!isset($single_use[$tagname])) { - // See if we possibly have a matching opening tag on the stack. - if (in_array($tagname, $stack)) { - // Close other tags lingering first. - do { - $output .= '</' . $stack[0] . '>'; - } while (array_shift($stack) != $tagname); - } - // Otherwise, discard it. - } - } - // Opening tag - else { - // See if we have an identical 'no nesting' tag already open and close it if found. - if (count($stack) && ($stack[0] == $tagname) && isset($no_nesting[$stack[0]])) { - $output .= '</' . array_shift($stack) . '>'; - } - // Push non-single-use tags onto the stack - if (!isset($single_use[$tagname])) { - array_unshift($stack, $tagname); - } - // Add trailing slash to single-use tags as per X(HT)ML. - else { - $value = rtrim($value, ' /') . ' /'; - } - $output .= '<' . $value . '>'; - } - } - else { - // Passthrough all text. - $output .= $value; - } - $tag = !$tag; - } - // Close remaining tags. - while (count($stack) > 0) { - $output .= '</' . array_shift($stack) . '>'; + else { + return ''; } - return $output; } /** diff --git a/modules/filter/filter.test b/modules/filter/filter.test index 98834d6e4..90ee5e7e1 100644 --- a/modules/filter/filter.test +++ b/modules/filter/filter.test @@ -182,24 +182,20 @@ class FilterAdminTestCase extends DrupalWebTestCase { } } -class FilterTestCase extends DrupalWebTestCase { +/** + * Unit tests for core filters. + */ +class FilterUnitTest extends DrupalWebTestCase { protected $format; public static function getInfo() { return array( 'name' => 'Core filters', - 'description' => 'Filter each filter individually: Convert URLs into links, Convert line breaks, Correct broken HTML, Escape all HTML, Limit allowed HTML tags.', + 'description' => 'Filter each filter individually: convert line breaks, correct broken HTML.', 'group' => 'Filter', ); } - function setUp() { - parent::setUp(); - - $admin_user = $this->drupalCreateUser(array('administer filters', 'create page content')); - $this->drupalLogin($admin_user); - } - /** * Test the line break filter. */ @@ -594,17 +590,17 @@ class FilterTestCase extends DrupalWebTestCase { } /** - * Test the HTML corrector. + * Test the HTML corrector filter. * * @todo This test could really use some validity checking function. */ - function testHtmlCorrector() { + function testHtmlCorrectorFilter() { // Tag closing. $f = _filter_htmlcorrector('<p>text'); $this->assertEqual($f, '<p>text</p>', t('HTML corrector -- tag closing at the end of input.')); $f = _filter_htmlcorrector('<p>text<p><p>text'); - $this->assertEqual($f, '<p>text</p><p></p><p>text</p>', t('HTML corrector -- tag closing.')); + $this->assertEqual($f, '<p>text</p><p /><p>text</p>', t('HTML corrector -- tag closing.')); $f = _filter_htmlcorrector("<ul><li>e1<li>e2"); $this->assertEqual($f, "<ul><li>e1</li><li>e2</li></ul>", t('HTML corrector -- unclosed list tags.')); @@ -615,6 +611,70 @@ class FilterTestCase extends DrupalWebTestCase { // XHTML slash for empty elements. $f = _filter_htmlcorrector('<hr><br>'); $this->assertEqual($f, '<hr /><br />', t('HTML corrector -- XHTML closing slash.')); + + $f = _filter_htmlcorrector('<P>test</P>'); + $this->assertEqual($f, '<p>test</p>', t('HTML corrector -- Convert uppercased tags to proper lowercased ones.')); + + $f = _filter_htmlcorrector('<P>test</p>'); + $this->assertEqual($f, '<p>test</p>', t('HTML corrector -- Convert uppercased tags to proper lowercased ones.')); + + $f = _filter_htmlcorrector('test<hr/>'); + $this->assertEqual($f, 'test<hr />', t('HTML corrector -- Let proper XHTML pass thru.')); + + $f = _filter_htmlcorrector('test<hr />'); + $this->assertEqual($f, 'test<hr />', t('HTML corrector -- Let proper XHTML pass thru.')); + + $f = _filter_htmlcorrector('<span class="test" />'); + $this->assertEqual($f, '<span class="test" />', t('HTML corrector -- Let proper XHTML pass thru.')); + + $f = _filter_htmlcorrector('test1<br class="test">test2'); + $this->assertEqual($f, 'test1<br class="test" />test2', t('HTML corrector -- Automatically close single tags.')); + + $f = _filter_htmlcorrector('line1<hr>line2'); + $this->assertEqual($f, 'line1<hr />line2', t('HTML corrector -- Automatically close single tags.')); + + $f = _filter_htmlcorrector('line1<HR>line2'); + $this->assertEqual($f, 'line1<hr />line2', t('HTML corrector -- Automatically close single tags.')); + + $f = _filter_htmlcorrector('<img src="http://example.com/test.jpg">test</img>'); + $this->assertEqual($f, '<img src="http://example.com/test.jpg" />test', t('HTML corrector -- Automatically close single tags.')); + + $f = _filter_htmlcorrector('<p>line1<br/><hr/>line2</p>'); + $this->assertEqual($f, '<p>line1<br /></p><hr />line2', t('HTML corrector -- Move non-inline elements outside of inline containers.')); + + $f = _filter_htmlcorrector('<p>line1<div>line2</div></p>'); + $this->assertEqual($f, '<p>line1</p><div>line2</div>', t('HTML corrector -- Move non-inline elements outside of inline containers.')); + + $f = _filter_htmlcorrector('<p>test<p>test</p>\n'); + $this->assertEqual($f, '<p>test</p><p>test</p>\n', t('HTML corrector -- Auto-close improperly nested tags.')); + + $f = _filter_htmlcorrector('<p>Line1<br><STRONG>bold stuff</b>'); + $this->assertEqual($f, '<p>Line1<br /><strong>bold stuff</strong></p>', t('HTML corrector -- Properly close unclosed tags, and remove useless closing tags.')); + + $f = _filter_htmlcorrector('test <!-- this is a comment -->'); + $this->assertEqual($f, 'test <!-- this is a comment -->', t('HTML corrector -- Do not touch HTML comments.')); + + $f = _filter_htmlcorrector('test <!--this is a comment-->'); + $this->assertEqual($f, 'test <!--this is a comment-->', t('HTML corrector -- Do not touch HTML comments.')); + + $f = _filter_htmlcorrector('test <!-- comment <p>another + <strong>multiple</strong> line + comment</p> -->'); + $this->assertEqual($f, 'test <!-- comment <p>another + <strong>multiple</strong> line + comment</p> -->', t('HTML corrector -- Do not touch HTML comments.')); + + $f = _filter_htmlcorrector('test <!-- comment <p>another comment</p> -->'); + $this->assertEqual($f, 'test <!-- comment <p>another comment</p> -->', t('HTML corrector -- Do not touch HTML comments.')); + + $f = _filter_htmlcorrector('test <!--break-->'); + $this->assertEqual($f, 'test <!--break-->', t('HTML corrector -- Do not touch HTML comments.')); + + $f = _filter_htmlcorrector('<p>test\n</p>\n'); + $this->assertEqual($f, '<p>test\n</p>\n', t('HTML corrector -- New-lines are accepted and kept as-is.')); + + $f = _filter_htmlcorrector('<p>دروبال'); + $this->assertEqual($f, '<p>دروبال</p>', t('HTML corrector -- Encoding is correctly kept.')); } function createFormat($filter) { diff --git a/modules/system/system.install b/modules/system/system.install index 38640dd7e..6e2465fca 100644 --- a/modules/system/system.install +++ b/modules/system/system.install @@ -266,6 +266,17 @@ function system_requirements($phase) { include_once DRUPAL_ROOT . '/includes/unicode.inc'; $requirements = array_merge($requirements, unicode_requirements()); + // Verify if the DOM PHP 5 extension is available. + $has_dom = class_exists('DOMDocument'); + if (!$has_dom) { + $requirements['php_dom'] = array( + 'title' => $t('PHP DOM Extension'), + 'value' => $t('Not found'), + 'severity' => REQUIREMENT_ERROR, + 'description' => $t("The DOM extension is part of PHP 5 core, but doesn't seem to be enabled on your system. You need to enable the DOM extension on your PHP installation."), + ); + } + if ($phase == 'runtime') { // Check for update status module. if (!module_exists('update')) { |