From: Matt Fitzpatrick Date: Mon, 18 Jan 2016 01:19:26 +0000 (-0800) Subject: Whitelist additional WAI-ARIA attributes, and all role values X-Git-Tag: 1.31.0-rc.0~8180 X-Git-Url: http://git.cyclocoop.org/%22%20.%20generer_url_ecrire%28%22auteur_infos%22%2C%20%22id_auteur=%24id%22%29%20.%20%22?a=commitdiff_plain;h=13978635694119e0a75b61ae7020a247fb4c12d8;p=lhc%2Fweb%2Fwiklou.git Whitelist additional WAI-ARIA attributes, and all role values Adds the attributes aria-describedby, aria-flowto, aria-label, aria-labelledby, and aria-owns to the attribute whitelist for all elements. Adds Sanitizer::escapeIdReferenceList() to escape attributes containing space delimited HTML id lists, in the same manner as Sanitizer::escapeId(). Removes the role="presentation" restriction. Allows all values for the role attribute. Bug: T26659 Change-Id: I3a29d727c61f46ac115ca2e50fcb14deeea34418 --- diff --git a/RELEASE-NOTES-1.27 b/RELEASE-NOTES-1.27 index 50d40a6145..b48d0b6f1e 100644 --- a/RELEASE-NOTES-1.27 +++ b/RELEASE-NOTES-1.27 @@ -146,6 +146,10 @@ production. * Added MWRestrictions as a class to check restrictions on a WebRequest, e.g. to assert that the request comes from a particular IP range. * Added bot passwords, a rights-restricted login mechanism for API-using bots. +* Whitelisted the following HTML attributes for all elements in wikitext: + aria-describedby, aria-flowto, aria-label, aria-labelledby, aria-owns. +* Removed "presentation" restriction on the HTML role attribute in wikitext. + All values are now allowed for the role attribute. === External library changes in 1.27 === diff --git a/includes/Sanitizer.php b/includes/Sanitizer.php index d41e559511..e2564cdfcc 100644 --- a/includes/Sanitizer.php +++ b/includes/Sanitizer.php @@ -721,7 +721,7 @@ class Sanitizer { * Take an array of attribute names and values and normalize or discard * illegal values for the given whitelist. * - * - Discards attributes not the given whitelist + * - Discards attributes not on the given whitelist * - Unsafe style attributes are discarded * - Invalid id attributes are re-encoded * @@ -770,18 +770,18 @@ class Sanitizer { $value = Sanitizer::checkCss( $value ); } + # Escape HTML id attributes if ( $attribute === 'id' ) { $value = Sanitizer::escapeId( $value, 'noninitial' ); } - # WAI-ARIA - # http://www.w3.org/TR/wai-aria/ - # http://www.whatwg.org/html/elements.html#wai-aria - # For now we only support role="presentation" until we work out what roles should be - # usable by content and we ensure that our code explicitly rejects patterns that - # violate HTML5's ARIA restrictions. - if ( $attribute === 'role' && $value !== 'presentation' ) { - continue; + # Escape HTML id reference lists + if ( $attribute === 'aria-describedby' + || $attribute === 'aria-flowto' + || $attribute === 'aria-labelledby' + || $attribute === 'aria-owns' + ) { + $value = Sanitizer::escapeIdReferenceList( $value, 'noninitial' ); } // RDFa and microdata properties allow URLs, URIs and/or CURIs. @@ -1163,6 +1163,39 @@ class Sanitizer { return $id; } + /** + * Given a string containing a space delimited list of ids, escape each id + * to match ids escaped by the escapeId() function. + * + * @since 1.27 + * + * @param string $referenceString Space delimited list of ids + * @param string|array $options String or array of strings (default is array()): + * 'noninitial': This is a non-initial fragment of an id, not a full id, + * so don't pay attention if the first character isn't valid at the + * beginning of an id. Only matters if $wgExperimentalHtmlIds is + * false. + * 'legacy': Behave the way the old HTML 4-based ID escaping worked even + * if $wgExperimentalHtmlIds is used, so we can generate extra + * anchors and links won't break. + * @return string + */ + static function escapeIdReferenceList( $referenceString, $options = array() ) { + # Explode the space delimited list string into an array of tokens + $references = preg_split( '/\s+/', "{$referenceString}", -1, PREG_SPLIT_NO_EMPTY ); + + # Escape each token as an id + foreach ( $references as &$ref ) { + $ref = Sanitizer::escapeId( $ref, $options ); + } + + # Merge the array back to a space delimited list string + # If the array is empty, the result will be an empty string ('') + $referenceString = implode( ' ', $references ); + + return $referenceString; + } + /** * Given a value, escape it so that it can be used as a CSS class and * return it. @@ -1546,6 +1579,11 @@ class Sanitizer { 'title', # WAI-ARIA + 'aria-describedby', + 'aria-flowto', + 'aria-label', + 'aria-labelledby', + 'aria-owns', 'role', ); diff --git a/tests/phpunit/includes/SanitizerTest.php b/tests/phpunit/includes/SanitizerTest.php index d3dc512bea..ca1ec5060b 100644 --- a/tests/phpunit/includes/SanitizerTest.php +++ b/tests/phpunit/includes/SanitizerTest.php @@ -317,33 +317,6 @@ class SanitizerTest extends MediaWikiTestCase { ); } - /** - * Test for support or lack of support for specific attributes in the attribute whitelist. - */ - public static function provideAttributeSupport() { - /** array( , , ) */ - return array( - array( - 'div', - ' role="presentation"', - ' role="presentation"', - 'Support for WAI-ARIA\'s role="presentation".' - ), - array( 'div', ' role="main"', '', "Other WAI-ARIA roles are currently not supported." ), - ); - } - - /** - * @dataProvider provideAttributeSupport - * @covers Sanitizer::fixTagAttributes - */ - public function testAttributeSupport( $tag, $attributes, $expected, $message ) { - $this->assertEquals( $expected, - Sanitizer::fixTagAttributes( $attributes, $tag ), - $message - ); - } - /** * @dataProvider provideEscapeHtmlAllowEntities * @covers Sanitizer::escapeHtmlAllowEntities @@ -363,4 +336,28 @@ class SanitizerTest extends MediaWikiTestCase { array( '<script>foo</script>', '' ), ); } + + /** + * Test escapeIdReferenceList for consistency with escapeId + * + * @dataProvider provideEscapeIdReferenceList + * @covers Sanitizer::escapeIdReferenceList + */ + public function testEscapeIdReferenceList( $referenceList, $id1, $id2 ) { + $this->assertEquals( + Sanitizer::escapeIdReferenceList( $referenceList, 'noninitial' ), + Sanitizer::escapeId( $id1, 'noninitial' ) + . ' ' + . Sanitizer::escapeId( $id2, 'noninitial' ) + ); + } + + public static function provideEscapeIdReferenceList() { + /** array( , , ) */ + return array( + array( 'foo bar', 'foo', 'bar' ), + array( '#1 #2', '#1', '#2' ), + array( '+1 +2', '+1', '+2' ), + ); + } }