diff --git a/includes/common.inc b/includes/common.inc index 74e437e8f8c5b16837acd132ff34909121ee9c28..3f26c4949ff246f1ac827891d1293078d9f0aa04 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -3094,10 +3094,10 @@ function drupal_clear_css_cache() { } /** - * Prepare a string for use as a valid identifier (element, class or ID name). + * Prepare a string for use as a valid CSS identifier (element, class or ID name). * * http://www.w3.org/TR/CSS21/syndata.html#characters shows the syntax for valid - * identifiers (including element names, classes, and IDs in selectors.) + * CSS identifiers (including element names, classes, and IDs in selectors.) * * @param $identifier * The identifier to clean. @@ -3106,11 +3106,11 @@ function drupal_clear_css_cache() { * @return * The cleaned identifier. */ -function drupal_clean_html_identifier($identifier, $filter = array(' ' => '-', '_' => '-', '[' => '-', ']' => '')) { +function drupal_clean_css_identifier($identifier, $filter = array(' ' => '-', '_' => '-', '[' => '-', ']' => '')) { // By default, we filter using Drupal's coding standards. $identifier = strtr($identifier, $filter); - // Valid characters in a identifier are: + // Valid characters in a CSS identifier are: // - the hyphen (U+002D) // - a-z (U+0030 - U+0039) // - A-Z (U+0041 - U+005A) @@ -3135,7 +3135,7 @@ function drupal_clean_html_identifier($identifier, $filter = array(' ' => '-', ' * The cleaned class name. */ function drupal_html_class($class) { - return drupal_clean_html_identifier(drupal_strtolower($class)); + return drupal_clean_css_identifier(drupal_strtolower($class)); } /** @@ -3148,7 +3148,15 @@ function drupal_html_class($class) { */ function drupal_html_id($id) { $seen_ids = &drupal_static(__FUNCTION__, array()); - $id = drupal_clean_html_identifier(drupal_strtolower($id)); + $id = strtr(drupal_strtolower($id), array(' ' => '-', '_' => '-', '[' => '-', ']' => '')); + + // As defined in http://www.w3.org/TR/html4/types.html#type-name, HTML IDs can + // only contain letters, digits ([0-9]), hyphens ("-"), underscores ("_"), + // colons (":"), and periods ("."). We strip out any character not in that + // list. Note that the CSS spec doesn't allow colons or periods in identifiers + // (http://www.w3.org/TR/CSS21/syndata.html#characters), so we strip those two + // characters as well. + $id = preg_replace('/[^A-Za-z0-9\-_]/', '', $id); // Ensure IDs are unique. The first occurrence is held but left alone. // Subsequent occurrences get a number appended to them. This incrementing diff --git a/modules/simpletest/tests/common.test b/modules/simpletest/tests/common.test index 35c8bf52fb9427ea2f4244efee8d8869c792cb95..fe37b416ac4fb63d6f4cdc6f7d38153bd26984e0 100644 --- a/modules/simpletest/tests/common.test +++ b/modules/simpletest/tests/common.test @@ -573,47 +573,54 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase { } /** - * Test for drupal_add_css(). + * Test for cleaning HTML identifiers. */ -class DrupalCSSIdentifierTestCase extends DrupalUnitTestCase { +class DrupalHTMLIdentifierTestCase extends DrupalUnitTestCase { public static function getInfo() { return array( - 'name' => 'CSS identifiers', - 'description' => 'Test the functions drupal_html_class() and drupal_html_id() for expected behavior', + 'name' => 'HTML identifiers', + 'description' => 'Test the functions drupal_html_class(), drupal_html_id() and drupal_clean_css_identifier() for expected behavior', 'group' => 'System', ); } /** - * Tests that drupal_html_class() cleans the class name properly. + * Tests that drupal_clean_css_identifier() cleans the identifier properly. */ function testDrupalCleanCSSIdentifier() { - // Verify that no valid ASCII characters are stripped from the class name. - $class = 'abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789'; - $this->assertIdentical(drupal_clean_html_identifier($class, array()), $class, t('Verify valid ASCII characters pass through.')); + // Verify that no valid ASCII characters are stripped from the identifier. + $identifier = 'abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789'; + $this->assertIdentical(drupal_clean_css_identifier($identifier, array()), $identifier, t('Verify valid ASCII characters pass through.')); - // Verify that no valid UTF-8 characters are stripped from the class name. - $class = '¡¢£¤¥'; - $this->assertIdentical(drupal_clean_html_identifier($class, array()), $class, t('Verify valid UTF-8 characters pass through.')); + // Verify that valid UTF-8 characters are not stripped from the identifier. + $identifier = '¡¢£¤¥'; + $this->assertIdentical(drupal_clean_css_identifier($identifier, array()), $identifier, t('Verify valid UTF-8 characters pass through.')); - // Verify that invalid characters (including non-breaking space) are stripped from the class name. - $this->assertIdentical(drupal_clean_html_identifier('invalid !"#$%&\'()*+,./:;<=>?@[\\]^`{|}~ class', array()), 'invalidclass', t('Strip invalid characters.')); + // Verify that invalid characters (including non-breaking space) are stripped from the identifier. + $this->assertIdentical(drupal_clean_css_identifier('invalid !"#$%&\'()*+,./:;<=>?@[\\]^`{|}~ identifier', array()), 'invalididentifier', t('Strip invalid characters.')); } /** * Tests that drupal_html_class() cleans the class name properly. */ - function testDrupalCSSClass() { + function testDrupalHTMLClass() { // Verify Drupal coding standards are enforced. $this->assertIdentical(drupal_html_class('CLASS NAME_[Ü]'), 'class-name--ü', t('Enforce Drupal coding standards.')); } /** - * Tests that drupal_html_id() cleans the id name properly. + * Tests that drupal_html_id() cleans the ID properly. */ - function testDrupalCSSId() { + function testDrupalHTMLId() { + // Verify that letters, digits, and hyphens are not stripped from the ID. + $id = 'abcdefghijklmnopqrstuvwxyz-0123456789'; + $this->assertIdentical(drupal_html_id($id), $id, t('Verify valid characters pass through.')); + + // Verify that invalid characters are stripped from the ID. + $this->assertIdentical(drupal_html_id('invalid,./:@\\^`{Üidentifier'), 'invalididentifier', t('Strip invalid characters.')); + // Verify Drupal coding standards are enforced. - $this->assertIdentical(drupal_html_id('ID NAME_[Ü]'), 'id-name--ü', t('Enforce Drupal coding standards.')); + $this->assertIdentical(drupal_html_id('ID NAME_[1]'), 'id-name--1', t('Enforce Drupal coding standards.')); // Reset the static cache so we can ensure the unique id count is at zero. drupal_static_reset('drupal_html_id');