KSES: Allow HTML data-* attributes.

Add global support for HTML attributes prefixed `data-` for authors and contributors, as required by the new editor.

Merges [43727] to trunk.

Props azaozz, peterwilsoncc.
Fixes #33121.


git-svn-id: https://develop.svn.wordpress.org/trunk@43981 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Jeremy Felt 2018-12-12 02:38:14 +00:00
parent 894a8e02d2
commit 1c9f359857
4 changed files with 129 additions and 13 deletions

View File

@ -1076,6 +1076,7 @@ function wp_kses_attr( $element, $attr, $allowed_html, $allowed_protocols ) {
* Determines whether an attribute is allowed.
*
* @since 4.2.3
* @since 5.0.0 Add support for `data-*` wildcard attributes.
*
* @param string $name The attribute name. Passed by reference. Returns empty string when not allowed.
* @param string $value The attribute value. Passed by reference. Returns a filtered value.
@ -1090,8 +1091,26 @@ function wp_kses_attr_check( &$name, &$value, &$whole, $vless, $element, $allowe
$name_low = strtolower( $name );
if ( ! isset( $allowed_attr[ $name_low ] ) || '' == $allowed_attr[ $name_low ] ) {
$name = $value = $whole = '';
return false;
/*
* Allow `data-*` attributes.
*
* When specifying `$allowed_html`, the attribute name should be set as
* `data-*` (not to be mixed with the HTML 4.0 `data` attribute, see
* https://www.w3.org/TR/html40/struct/objects.html#adef-data).
*
* Note: the attribute name should only contain `A-Za-z0-9_-` chars,
* double hyphens `--` are not accepted by WordPress.
*/
if ( strpos( $name_low, 'data-' ) === 0 && ! empty( $allowed_attr['data-*'] ) && preg_match( '/^data(?:-[a-z0-9_]+)+$/', $name_low, $match ) ) {
/*
* Add the whole attribute name to the allowed attributes and set any restrictions
* for the `data-*` attribute values for the current element.
*/
$allowed_attr[ $match[0] ] = $allowed_attr['data-*'];
} else {
$name = $value = $whole = '';
return false;
}
}
if ( 'style' == $name_low ) {
@ -2091,6 +2110,7 @@ function safecss_filter_attr( $css, $deprecated = '' ) {
* Helper function to add global attributes to a tag in the allowed html list.
*
* @since 3.5.0
* @since 5.0.0 Add support for `data-*` wildcard attributes.
* @access private
* @ignore
*
@ -2099,11 +2119,12 @@ function safecss_filter_attr( $css, $deprecated = '' ) {
*/
function _wp_add_global_attributes( $value ) {
$global_attributes = array(
'class' => true,
'id' => true,
'style' => true,
'title' => true,
'role' => true,
'class' => true,
'id' => true,
'style' => true,
'title' => true,
'role' => true,
'data-*' => true,
);
if ( true === $value ) {

View File

@ -825,4 +825,99 @@ EOF;
),
);
}
/**
* Data attributes are globally accepted.
*
* @ticket 33121
*/
function test_wp_kses_attr_data_attribute_is_allowed() {
$test = '<div data-foo="foo" data-bar="bar" datainvalid="gone" data--invaild="gone" data-also-invaild-="gone" data-two-hyphens="remains">Pens and pencils</div>';
$expected = '<div data-foo="foo" data-bar="bar" data-two-hyphens="remains">Pens and pencils</div>';
$this->assertEquals( $expected, wp_kses_post( $test ) );
}
/**
* Ensure wildcard attributes block unprefixed wildcard uses.
*
* @ticket 33121
*/
function test_wildcard_requires_hyphen_after_prefix() {
$allowed_html = array(
'div' => array(
'data-*' => true,
'on-*' => true,
),
);
$string = '<div datamelformed-prefix="gone" data="gone" data-="gone" onclick="alert(1)">Malformed attributes</div>';
$expected = '<div>Malformed attributes</div>';
$actual = wp_kses( $string, $allowed_html );
$this->assertSame( $expected, $actual );
}
/**
* Ensure wildcard allows two hyphen.
*
* @ticket 33121
*/
function test_wildcard_allows_two_hyphens() {
$allowed_html = array(
'div' => array(
'data-*' => true,
),
);
$string = '<div data-wp-id="pens-and-pencils">Well formed attribute</div>';
$expected = '<div data-wp-id="pens-and-pencils">Well formed attribute</div>';
$actual = wp_kses( $string, $allowed_html );
$this->assertSame( $expected, $actual );
}
/**
* Ensure wildcard attributes only support valid prefixes.
*
* @dataProvider data_wildcard_attribute_prefixes
*
* @ticket 33121
*/
function test_wildcard_attribute_prefixes( $wildcard_attribute, $expected ) {
$allowed_html = array(
'div' => array(
$wildcard_attribute => true,
),
);
$name = str_replace( '*', strtolower( __FUNCTION__ ), $wildcard_attribute );
$value = __FUNCTION__;
$whole = "{$name}=\"{$value}\"";
$actual = wp_kses_attr_check( $name, $value, $whole, 'n', 'div', $allowed_html );
$this->assertSame( $expected, $actual );
}
/**
* @return array Array of arguments for wildcard testing
* [0] The prefix being tested.
* [1] The outcome of `wp_kses_attr_check` for the prefix.
*/
function data_wildcard_attribute_prefixes() {
return array(
// Ends correctly
array( 'data-*', true ),
// Does not end with trialing `-`.
array( 'data*', false ),
// Multiple wildcards.
array( 'd*ta-*', false ),
array( 'data**', false ),
);
}
}

View File

@ -1079,9 +1079,9 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
array(
// Raw values.
array(
'title' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
'description' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
'caption' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
'title' => '<a href="#" target="_blank" unfiltered=true>link</a>',
'description' => '<a href="#" target="_blank" unfiltered=true>link</a>',
'caption' => '<a href="#" target="_blank" unfiltered=true>link</a>',
),
// Expected returned values.
array(

View File

@ -3283,9 +3283,9 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
array(
// Raw values.
array(
'title' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
'content' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
'excerpt' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
'title' => '<a href="#" target="_blank" unfiltered=true>link</a>',
'content' => '<a href="#" target="_blank" unfiltered=true>link</a>',
'excerpt' => '<a href="#" target="_blank" unfiltered=true>link</a>',
),
// Expected returned values.
array(