is more of a concern.',
),
array(
'',
'div {background-image:\\0}',
),
);
}
/**
* Test new function wp_kses_hair_parse().
*
* @dataProvider data_hair_parse
*/
public function test_hair_parse( $input, $output ) {
return $this->assertSame( $output, wp_kses_hair_parse( $input ) );
}
public function data_hair_parse() {
return array(
array(
'title="hello" href="#" id="my_id" ',
array( 'title="hello" ', 'href="#" ', 'id="my_id" ' ),
),
array(
'[shortcode attr="value"] href="http://www.google.com/"title="moo"disabled',
array( '[shortcode attr="value"] ', 'href="http://www.google.com/"', 'title="moo"', 'disabled' ),
),
array(
'',
array(),
),
array(
'a',
array( 'a' ),
),
array(
'title="hello"disabled href=# id=\'my_id\'',
array( 'title="hello"', 'disabled ', 'href=# ', "id='my_id'" ),
),
array(
' ', // Calling function is expected to strip leading whitespace.
false,
),
array(
'abcd=abcd"abcd"',
false,
),
array(
"array[1]='z'z'z'z",
false,
),
// Using a digit in attribute name should work.
array(
'href="https://example.com/[shortcode attr=\'value\']" data-op3-timer-seconds="0"',
array( 'href="https://example.com/[shortcode attr=\'value\']" ', 'data-op3-timer-seconds="0"' ),
),
// Using an underscore in attribute name should work.
array(
'href="https://example.com/[shortcode attr=\'value\']" data-op_timer-seconds="0"',
array( 'href="https://example.com/[shortcode attr=\'value\']" ', 'data-op_timer-seconds="0"' ),
),
// Using a period in attribute name should work.
array(
'href="https://example.com/[shortcode attr=\'value\']" data-op.timer-seconds="0"',
array( 'href="https://example.com/[shortcode attr=\'value\']" ', 'data-op.timer-seconds="0"' ),
),
// Using a digit at the beginning of attribute name should return false.
array(
'href="https://example.com/[shortcode attr=\'value\']" 3data-op-timer-seconds="0"',
false,
),
);
}
/**
* Test new function wp_kses_attr_parse().
*
* @dataProvider data_attr_parse
*/
public function test_attr_parse( $input, $output ) {
return $this->assertSame( $output, wp_kses_attr_parse( $input ) );
}
public function data_attr_parse() {
return array(
array(
'
',
array( '' ),
),
array(
'',
array( '' ),
),
array(
'',
false,
),
array(
'a',
false,
),
array(
'',
array( '' ),
),
array(
'',
false,
),
array(
'',
array( '' ),
),
array(
'',
array( '' ),
),
array(
'',
false,
),
array(
"",
false,
),
array(
'
',
array( '
' ),
),
);
}
/**
* Test new function wp_kses_one_attr().
*
* @dataProvider data_one_attr
*/
public function test_one_attr( $element, $input, $output ) {
return $this->assertSame( $output, wp_kses_one_attr( $input, $element ) );
}
public function data_one_attr() {
return array(
array(
'a',
' title="hello" ',
' title="hello" ',
),
array(
'a',
'title = "hello"',
'title="hello"',
),
array(
'a',
"title='hello'",
"title='hello'",
),
array(
'a',
'title=hello',
'title="hello"',
),
array(
'a',
'href="javascript:alert(1)"',
'href="alert(1)"',
),
array(
'a',
'style ="style "',
'style="style"',
),
array(
'a',
'style="style "',
'style="style"',
),
array(
'a',
'style ="style ="',
'',
),
array(
'img',
'src="mypic.jpg"',
'src="mypic.jpg"',
),
array(
'img',
'loading="lazy"',
'loading="lazy"',
),
array(
'img',
'onerror=alert(1)',
'',
),
array(
'img',
'title=>',
'title=">"',
),
array(
'img',
'title="&garbage";"',
'title="&garbage";"',
),
);
}
/**
* @ticket 34063
*/
public function test_bdo_tag_allowed() {
global $allowedposttags;
$input = 'This is a BDO tag. Weird, right?
';
$this->assertSame( $input, wp_kses( $input, $allowedposttags ) );
}
/**
* @ticket 54698
*/
public function test_ruby_tag_allowed() {
global $allowedposttags;
$input = '✶';
$this->assertSame( $input, wp_kses( $input, $allowedposttags ) );
}
/**
* @ticket 35079
*/
public function test_ol_reversed_attribute_allowed() {
global $allowedposttags;
$input = '- Item 1
- Item 2
- Item 3
';
$this->assertSame( $input, wp_kses( $input, $allowedposttags ) );
}
/**
* @ticket 40680
*/
public function test_wp_kses_attr_no_attributes_allowed_with_empty_array() {
$element = 'foo';
$attribute = 'title="foo" class="bar"';
$this->assertSame( "<{$element}>", wp_kses_attr( $element, $attribute, array( 'foo' => array() ), array() ) );
}
/**
* @ticket 40680
*/
public function test_wp_kses_attr_no_attributes_allowed_with_true() {
$element = 'foo';
$attribute = 'title="foo" class="bar"';
$this->assertSame( "<{$element}>", wp_kses_attr( $element, $attribute, array( 'foo' => true ), array() ) );
}
/**
* @ticket 40680
*/
public function test_wp_kses_attr_single_attribute_is_allowed() {
$element = 'foo';
$attribute = 'title="foo" class="bar"';
$this->assertSame( "<{$element} title=\"foo\">", wp_kses_attr( $element, $attribute, array( 'foo' => array( 'title' => true ) ), array() ) );
}
/**
* @ticket 43312
*/
public function test_wp_kses_attr_no_attributes_allowed_with_false() {
$element = 'foo';
$attribute = 'title="foo" class="bar"';
$this->assertSame( "<{$element}>", wp_kses_attr( $element, $attribute, array( 'foo' => false ), array() ) );
}
/**
* Testing the safecss_filter_attr() function.
*
* @ticket 37248
* @ticket 42729
* @ticket 48376
* @dataProvider data_test_safecss_filter_attr
*
* @param string $css A string of CSS rules.
* @param string $expected Expected string of CSS rules.
*/
public function test_safecss_filter_attr( $css, $expected ) {
$this->assertSame( $expected, safecss_filter_attr( $css ) );
}
/**
* Data Provider for test_safecss_filter_attr().
*
* @return array {
* @type array {
* @string string $css A string of CSS rules.
* @string string $expected Expected string of CSS rules.
* }
* }
*/
public function data_test_safecss_filter_attr() {
return array(
// Empty input, empty output.
array(
'css' => '',
'expected' => '',
),
// An arbitrary attribute name isn't allowed.
array(
'css' => 'foo:bar',
'expected' => '',
),
// A single attribute name, with a single value.
array(
'css' => 'margin-top: 2px',
'expected' => 'margin-top: 2px',
),
// Backslash \ isn't supported.
array(
'css' => 'margin-top: \2px',
'expected' => '',
),
// Curly bracket } isn't supported.
array(
'css' => 'margin-bottom: 2px}',
'expected' => '',
),
// A single attribute name, with a single text value.
array(
'css' => 'text-transform: uppercase',
'expected' => 'text-transform: uppercase',
),
// Only lowercase attribute names are supported.
array(
'css' => 'Text-transform: capitalize',
'expected' => '',
),
// Uppercase attribute values goes through.
array(
'css' => 'text-transform: None',
'expected' => 'text-transform: None',
),
// A single attribute, with multiple values.
array(
'css' => 'font: bold 15px arial, sans-serif',
'expected' => 'font: bold 15px arial, sans-serif',
),
// Multiple attributes, with single values.
array(
'css' => 'font-weight: bold;font-size: 15px',
'expected' => 'font-weight: bold;font-size: 15px',
),
// Multiple attributes, separated by a space.
array(
'css' => 'font-weight: bold; font-size: 15px',
'expected' => 'font-weight: bold;font-size: 15px',
),
// Multiple attributes, with multiple values.
array(
'css' => 'margin: 10px 20px;padding: 5px 10px',
'expected' => 'margin: 10px 20px;padding: 5px 10px',
),
// Parenthesis ( is supported for some attributes.
array(
'css' => 'background: green url("foo.jpg") no-repeat fixed center',
'expected' => 'background: green url("foo.jpg") no-repeat fixed center',
),
// Additional background attributes introduced in 5.3.
array(
'css' => 'background-size: cover;background-size: 200px 100px;background-attachment: local, scroll;background-blend-mode: hard-light',
'expected' => 'background-size: cover;background-size: 200px 100px;background-attachment: local, scroll;background-blend-mode: hard-light',
),
// `border-radius` attribute introduced in 5.3.
array(
'css' => 'border-radius: 10% 30% 50% 70%;border-radius: 30px',
'expected' => 'border-radius: 10% 30% 50% 70%;border-radius: 30px',
),
// `flex` and related attributes introduced in 5.3.
array(
'css' => 'flex: 0 1 auto;flex-basis: 75%;flex-direction: row-reverse;flex-flow: row-reverse nowrap;flex-grow: 2;flex-shrink: 1',
'expected' => 'flex: 0 1 auto;flex-basis: 75%;flex-direction: row-reverse;flex-flow: row-reverse nowrap;flex-grow: 2;flex-shrink: 1',
),
// `grid` and related attributes introduced in 5.3.
array(
'css' => 'grid-template-columns: 1fr 60px;grid-auto-columns: min-content;grid-column-start: span 2;grid-column-end: -1;grid-column-gap: 10%;grid-gap: 10px 20px',
'expected' => 'grid-template-columns: 1fr 60px;grid-auto-columns: min-content;grid-column-start: span 2;grid-column-end: -1;grid-column-gap: 10%;grid-gap: 10px 20px',
),
array(
'css' => 'grid-template-rows: 40px 4em 40px;grid-auto-rows: min-content;grid-row-start: -1;grid-row-end: 3;grid-row-gap: 1em',
'expected' => 'grid-template-rows: 40px 4em 40px;grid-auto-rows: min-content;grid-row-start: -1;grid-row-end: 3;grid-row-gap: 1em',
),
// `grid` does not yet support functions or `\`.
array(
'css' => 'grid-template-columns: repeat(2, 50px 1fr);grid-template: 1em / 20% 20px 1fr',
'expected' => '',
),
// `flex` and `grid` alignments introduced in 5.3.
array(
'css' => 'align-content: space-between;align-items: start;align-self: center;justify-items: center;justify-content: space-between;justify-self: end',
'expected' => 'align-content: space-between;align-items: start;align-self: center;justify-items: center;justify-content: space-between;justify-self: end',
),
// `columns` and related attributes introduced in 5.3.
array(
'css' => 'columns: 6rem auto;column-count: 4;column-fill: balance;column-gap: 9px;column-rule: thick inset blue;column-span: none;column-width: 120px',
'expected' => 'columns: 6rem auto;column-count: 4;column-fill: balance;column-gap: 9px;column-rule: thick inset blue;column-span: none;column-width: 120px',
),
// Gradients introduced in 5.3.
array(
'css' => 'background: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)',
'expected' => 'background: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)',
),
array(
'css' => 'background: linear-gradient(135deg,rgba(6,147,227,1) ) (0%,rgb(155,81,224) 100%)',
'expected' => '',
),
array(
'css' => 'background-image: linear-gradient(red,yellow);',
'expected' => 'background-image: linear-gradient(red,yellow)',
),
array(
'css' => 'color: linear-gradient(red,yellow);',
'expected' => '',
),
array(
'css' => 'background-image: linear-gradient(red,yellow); background: prop( red,yellow); width: 100px;',
'expected' => 'background-image: linear-gradient(red,yellow);width: 100px',
),
array(
'css' => 'background: unknown-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)',
'expected' => '',
),
array(
'css' => 'background: repeating-linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)',
'expected' => 'background: repeating-linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)',
),
array(
'css' => 'width: 100px; height: 100px; background: linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%);',
'expected' => 'width: 100px;height: 100px;background: linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)',
),
array(
'css' => 'background: radial-gradient(#ff0, red, yellow, green, rgba(6,147,227,1), rgb(155,81,224) 90%);',
'expected' => 'background: radial-gradient(#ff0, red, yellow, green, rgba(6,147,227,1), rgb(155,81,224) 90%)',
),
array(
'css' => 'background: radial-gradient(#ff0, red, yellow, green, rgba(6,147,227,1), rgb(155,81,224) 90%);',
'expected' => 'background: radial-gradient(#ff0, red, yellow, green, rgba(6,147,227,1), rgb(155,81,224) 90%)',
),
array(
'css' => 'background: conic-gradient(at 0% 30%, red 10%, yellow 30%, #1e90ff 50%)',
'expected' => 'background: conic-gradient(at 0% 30%, red 10%, yellow 30%, #1e90ff 50%)',
),
// Expressions are not allowed.
array(
'css' => 'height: expression( body.scrollTop + 50 + "px" )',
'expected' => '',
),
// RGB color values are not allowed.
array(
'css' => 'color: rgb( 100, 100, 100 )',
'expected' => '',
),
// RGBA color values are not allowed.
array(
'css' => 'color: rgb( 100, 100, 100, .4 )',
'expected' => '',
),
);
}
/**
* Data attributes are globally accepted.
*
* @ticket 33121
*/
public function test_wp_kses_attr_data_attribute_is_allowed() {
$test = 'Pens and pencils
';
$expected = 'Pens and pencils
';
$this->assertSame( $expected, wp_kses_post( $test ) );
}
/**
* Ensure wildcard attributes block unprefixed wildcard uses.
*
* @ticket 33121
*/
public function test_wildcard_requires_hyphen_after_prefix() {
$allowed_html = array(
'div' => array(
'data-*' => true,
'on-*' => true,
),
);
$string = 'Malformed attributes
';
$expected = 'Malformed attributes
';
$actual = wp_kses( $string, $allowed_html );
$this->assertSame( $expected, $actual );
}
/**
* Ensure wildcard allows two hyphen.
*
* @ticket 33121
*/
public function test_wildcard_allows_two_hyphens() {
$allowed_html = array(
'div' => array(
'data-*' => true,
),
);
$string = 'Well formed attribute
';
$expected = 'Well formed attribute
';
$actual = wp_kses( $string, $allowed_html );
$this->assertSame( $expected, $actual );
}
/**
* Ensure wildcard attributes only support valid prefixes.
*
* @dataProvider data_wildcard_attribute_prefixes
*
* @ticket 33121
*/
public 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.
*/
public 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 ),
);
}
/**
* Test URL sanitization in the style tag.
*
* @dataProvider data_kses_style_attr_with_url
*
* @ticket 45067
* @ticket 46197
* @ticket 46498
*
* @param $input string The style attribute saved in the editor.
* @param $expected string The sanitized style attribute.
*/
public function test_kses_style_attr_with_url( $input, $expected ) {
$actual = safecss_filter_attr( $input );
$this->assertSame( $expected, $actual );
}
/**
* Data provider testing style attribute sanitization.
*
* @return array Nested array of input, expected pairs.
*/
public function data_kses_style_attr_with_url() {
return array(
/*
* Valid use cases.
*/
// Double quotes.
array(
'background-image: url( "http://example.com/valid.gif" );',
'background-image: url( "http://example.com/valid.gif" )',
),
// Single quotes.
array(
"background-image: url( 'http://example.com/valid.gif' );",
"background-image: url( 'http://example.com/valid.gif' )",
),
// No quotes.
array(
'background-image: url( http://example.com/valid.gif );',
'background-image: url( http://example.com/valid.gif )',
),
// Single quotes, extra spaces.
array(
"background-image: url( ' http://example.com/valid.gif ' );",
"background-image: url( ' http://example.com/valid.gif ' )",
),
// Line breaks, single quotes.
array(
"background-image: url(\n'http://example.com/valid.gif' );",
"background-image: url('http://example.com/valid.gif' )",
),
// Tabs not spaces, single quotes.
array(
"background-image: url(\t'http://example.com/valid.gif'\t\t);",
"background-image: url('http://example.com/valid.gif')",
),
// Single quotes, absolute path.
array(
"background: url('/valid.gif');",
"background: url('/valid.gif')",
),
// Single quotes, relative path.
array(
"background: url('../wp-content/uploads/2018/10/valid.gif');",
"background: url('../wp-content/uploads/2018/10/valid.gif')",
),
// Error check: valid property not containing a URL.
array(
'background: red',
'background: red',
),
// CSS calc().
array(
'width: calc(2em + 3px)',
'width: calc(2em + 3px)',
),
// CSS variable.
array(
'padding: var(--wp-var1) var(--wp-var2)',
'padding: var(--wp-var1) var(--wp-var2)',
),
// CSS calc() with var().
array(
'margin-top: calc(var(--wp-var1) * 3 + 2em)',
'margin-top: calc(var(--wp-var1) * 3 + 2em)',
),
/*
* Invalid use cases.
*/
// Attribute doesn't support URL properties.
array(
'color: url( "http://example.com/invalid.gif" );',
'',
),
// Mismatched quotes.
array(
'background-image: url( "http://example.com/valid.gif\' );',
'',
),
// Bad protocol, double quotes.
array(
'background-image: url( "bad://example.com/invalid.gif" );',
'',
),
// Bad protocol, single quotes.
array(
"background-image: url( 'bad://example.com/invalid.gif' );",
'',
),
// Bad protocol, single quotes.
array(
"background-image: url( 'bad://example.com/invalid.gif' );",
'',
),
// Bad protocol, single quotes, strange spacing.
array(
"background-image: url( ' \tbad://example.com/invalid.gif ' );",
'',
),
// Bad protocol, no quotes.
array(
'background-image: url( bad://example.com/invalid.gif );',
'',
),
// No URL inside url().
array(
'background-image: url();',
'',
),
// Malformed, no closing `)`.
array(
'background-image: url( "http://example.com" ;',
'',
),
// Malformed, no closing `"`.
array(
'background-image: url( "http://example.com );',
'',
),
// Malformed calc, no closing `)`.
array(
'width: calc(3em + 10px',
'',
),
// Malformed var, no closing `)`.
array(
'width: var(--wp-var1',
'',
),
);
}
/**
* Testing the safecss_filter_attr() function with the safecss_filter_attr_allow_css filter.
*
* @ticket 37134
*
* @dataProvider data_test_safecss_filter_attr_filtered
*
* @param string $css A string of CSS rules.
* @param string $expected Expected string of CSS rules.
*/
public function test_safecss_filter_attr_filtered( $css, $expected ) {
add_filter( 'safecss_filter_attr_allow_css', '__return_true' );
$this->assertSame( $expected, safecss_filter_attr( $css ) );
remove_filter( 'safecss_filter_attr_allow_css', '__return_true' );
}
/**
* Data Provider for test_safecss_filter_attr_filtered().
*
* @return array {
* @type array {
* @string string $css A string of CSS rules.
* @string string $expected Expected string of CSS rules.
* }
* }
*/
public function data_test_safecss_filter_attr_filtered() {
return array(
// A single attribute name, with a single value.
array(
'css' => 'margin-top: 2px',
'expected' => 'margin-top: 2px',
),
// Backslash \ can be allowed with the 'safecss_filter_attr_allow_css' filter.
array(
'css' => 'margin-top: \2px',
'expected' => 'margin-top: \2px',
),
// Curly bracket } can be allowed with the 'safecss_filter_attr_allow_css' filter.
array(
'css' => 'margin-bottom: 2px}',
'expected' => 'margin-bottom: 2px}',
),
// Parenthesis ) can be allowed with the 'safecss_filter_attr_allow_css' filter.
array(
'css' => 'margin-bottom: 2px)',
'expected' => 'margin-bottom: 2px)',
),
// Ampersand & can be allowed with the 'safecss_filter_attr_allow_css' filter.
array(
'css' => 'margin-bottom: 2px&',
'expected' => 'margin-bottom: 2px&',
),
// Expressions can be allowed with the 'safecss_filter_attr_allow_css' filter.
array(
'css' => 'height: expression( body.scrollTop + 50 + "px" )',
'expected' => 'height: expression( body.scrollTop + 50 + "px" )',
),
// RGB color values can be allowed with the 'safecss_filter_attr_allow_css' filter.
array(
'css' => 'color: rgb( 100, 100, 100 )',
'expected' => 'color: rgb( 100, 100, 100 )',
),
// RGBA color values can be allowed with the 'safecss_filter_attr_allow_css' filter.
array(
'css' => 'color: rgb( 100, 100, 100, .4 )',
'expected' => 'color: rgb( 100, 100, 100, .4 )',
),
);
}
/**
* Test filtering a standard img tag.
*
* @ticket 50731
*/
public function test_wp_kses_img_tag_standard_attributes() {
$html = array(
'
',
);
$html = implode( ' ', $html );
$this->assertSame( $html, wp_kses_post( $html ) );
}
/**
* Test filtering a standard main tag.
*
* @ticket 53156
*/
public function test_wp_kses_main_tag_standard_attributes() {
$test = array(
'',
);
$html = implode( ' ', $test );
$this->assertSame( $html, wp_kses_post( $html ) );
}
/**
* Test that object tags are allowed under limited circumstances.
*
* @ticket 54261
*
* @dataProvider data_wp_kses_object_tag_allowed
*
* @param string $html A string of HTML to test.
* @param string $expected The expected result from KSES.
*/
function test_wp_kses_object_tag_allowed( $html, $expected ) {
$this->assertSame( $expected, wp_kses_post( $html ) );
}
/**
* Data provider for test_wp_kses_object_tag_allowed().
*/
function data_wp_kses_object_tag_allowed() {
return array(
'valid value for type' => array(
'',
'',
),
'invalid value for type' => array(
'',
'',
),
'multiple type attributes, last invalid' => array(
'',
'',
),
'multiple type attributes, first uppercase, last invalid' => array(
'',
'',
),
'multiple type attributes, last upper case and invalid' => array(
'',
'',
),
'multiple type attributes, first invalid' => array(
'',
'',
),
'multiple type attributes, first upper case and invalid' => array(
'',
'',
),
'multiple type attributes, first invalid, last uppercase' => array(
'',
'',
),
'multiple object tags, last invalid' => array(
'',
'',
),
'multiple object tags, first invalid' => array(
'',
'',
),
'type attribute with partially incorrect value' => array(
'',
'',
),
'type attribute with empty value' => array(
'',
'',
),
'type attribute with no value' => array(
'',
'',
),
'no type attribute' => array(
'',
'',
),
'different protocol in url' => array(
'',
'',
),
'query string on url' => array(
'',
'',
),
'fragment on url' => array(
'',
'',
),
'wrong extension' => array(
'',
'',
),
'protocol-relative url' => array(
'',
'',
),
'unsupported protocol' => array(
'',
'',
),
'relative url' => array(
'',
'',
),
'url with port number-like path' => array(
'',
'',
),
);
}
/**
* Test that object tags are allowed when there is a port number in the URL.
*
* @ticket 54261
*
* @dataProvider data_wp_kses_object_data_url_with_port_number_allowed
*
* @param string $html A string of HTML to test.
* @param string $expected The expected result from KSES.
*/
function test_wp_kses_object_data_url_with_port_number_allowed( $html, $expected ) {
add_filter( 'upload_dir', array( $this, 'wp_kses_upload_dir_filter' ), 10, 2 );
$this->assertSame( $expected, wp_kses_post( $html ) );
}
/**
* Data provider for test_wp_kses_object_data_url_with_port_number_allowed().
*/
function data_wp_kses_object_data_url_with_port_number_allowed() {
return array(
'url with port number' => array(
'',
'',
),
'url with port number and http protocol' => array(
'',
'',
),
'url with wrong port number' => array(
'',
'',
),
'url without port number' => array(
'',
'',
),
);
}
/**
* Filter upload directory for tests using port number.
*
* @param array $param See wp_upload_dir()
* @return array $param with a modified `url`.
*/
public function wp_kses_upload_dir_filter( $param ) {
$url_with_port_number = is_string( $param['url'] ) ? str_replace( 'example.org', 'example.org:8888', $param['url'] ) : $param['url'];
$param['url'] = $url_with_port_number;
return $param;
}
/**
* Test that object tags will continue to function if they've been added using the
* 'wp_kses_allowed_html' filter.
*
* @ticket 54261
*/
function test_wp_kses_object_added_in_html_filter() {
$html = <<
HTML;
add_filter( 'wp_kses_allowed_html', array( $this, 'filter_wp_kses_object_added_in_html_filter' ), 10, 2 );
$filtered_html = wp_kses_post( $html );
remove_filter( 'wp_kses_allowed_html', array( $this, 'filter_wp_kses_object_added_in_html_filter' ) );
$this->assertSame( $html, $filtered_html );
}
function filter_wp_kses_object_added_in_html_filter( $tags, $context ) {
if ( 'post' === $context ) {
$tags['object'] = array(
'type' => true,
'data' => true,
);
$tags['param'] = array(
'name' => true,
'value' => true,
);
}
return $tags;
}
/**
* Test that attributes with a list of allowed values are filtered correctly.
*
* @ticket 54261
*
* @dataProvider data_wp_kses_allowed_values_list
*
* @param string $html A string of HTML to test.
* @param string $expected The expected result from KSES.
* @param array $allowed_html The allowed HTML to pass to KSES.
*/
function test_wp_kses_allowed_values_list( $html, $expected, $allowed_html ) {
$this->assertSame( $expected, wp_kses( $html, $allowed_html ) );
}
/**
* Data provider for test_wp_kses_allowed_values_list().
*/
function data_wp_kses_allowed_values_list() {
$data = array(
'valid dir attribute value' => array(
'
foo
',
'
foo
',
),
'valid dir attribute value, upper case' => array(
'
foo
',
'
foo
',
),
'invalid dir attribute value' => array(
'
foo
',
'
foo
',
),
'dir attribute with empty value' => array(
'
foo
',
'
foo
',
),
'dir attribute with no value' => array(
'
foo
',
'
foo
',
),
);
return array_map(
function ( $datum ) {
$datum[] = array(
'p' => array(
'dir' => array(
'values' => array( 'ltr', 'rtl' ),
),
),
);
return $datum;
},
$data
);
}
/**
* Test that attributes with the required flag are handled correctly.
*
* @ticket 54261
*
* @dataProvider data_wp_kses_required_attribute
*
* @param string $html A string of HTML to test.
* @param string $expected The expected result from KSES.
* @param array $allowed_html The allowed HTML to pass to KSES.
*/
function test_wp_kses_required_attribute( $html, $expected, $allowed_html ) {
$this->assertSame( $expected, wp_kses( $html, $allowed_html ) );
}
/**
* Data provider for test_wp_kses_required_attribute().
*/
function data_wp_kses_required_attribute() {
$data = array(
'valid dir attribute value' => array(
'
foo
', // Test HTML.
'
foo
', // Expected result when dir is not required.
'
foo
', // Expected result when dir is required.
'
foo
', // Expected result when dir is required, but has no value filter.
),
'valid dir attribute value, upper case' => array(
'
foo
',
'
foo
',
'
foo
',
'
foo
',
),
'invalid dir attribute value' => array(
'
foo
',
'
foo
',
'
foo
',
'
foo
',
),
'dir attribute with empty value' => array(
'
foo
',
'
foo
',
'
foo
',
'
foo
',
),
'dir attribute with no value' => array(
'
foo
',
'
foo
',
'
foo
',
'
foo
',
),
'dir attribute not set' => array(
'
foo
',
'
foo
',
'
foo
',
'
foo
',
),
);
$return_data = array();
foreach ( $data as $description => $datum ) {
// Test that the required flag defaults to false.
$return_data[ "$description - required flag not set" ] = array(
$datum[0],
$datum[1],
array(
'p' => array(
'dir' => array(
'values' => array( 'ltr', 'rtl' ),
),
),
),
);
// Test when the attribute is not required, but has allowed values.
$return_data[ "$description - required flag set to false" ] = array(
$datum[0],
$datum[1],
array(
'p' => array(
'dir' => array(
'required' => false,
'values' => array( 'ltr', 'rtl' ),
),
),
),
);
// Test when the attribute is required, but has allowed values.
$return_data[ "$description - required flag set to true" ] = array(
$datum[0],
$datum[2],
array(
'p' => array(
'dir' => array(
'required' => true,
'values' => array( 'ltr', 'rtl' ),
),
),
),
);
// Test when the attribute is required, but has no allowed values.
$return_data[ "$description - required flag set to true, no allowed values specified" ] = array(
$datum[0],
$datum[3],
array(
'p' => array(
'dir' => array(
'required' => true,
),
),
),
);
}
return $return_data;
}
/**
* Test that XML named entities are encoded correctly.
*
* @dataProvider data_wp_kses_xml_named_entities
*
* @ticket 54060
* @covers ::wp_kses_xml_named_entities
*
* @param array $input The input to wp_kses_xml_named_entities().
* @param string $expected The expected output.
*/
public function test_wp_kses_xml_named_entities( $input, $expected ) {
$this->assertSame( $expected, wp_kses_xml_named_entities( $input ) );
}
/**
* Data provider for test_wp_kses_xml_named_entities().
*
* @return array Nested array of input, expected pairs.
*/
public function data_wp_kses_xml_named_entities() {
return array(
// Empty string value testing.
'empty string' => array(
'input' => '',
'expected' => '',
),
// Empty string array value testing.
'empty string array' => array(
'input' => array( '', '' ),
'expected' => '',
),
// $allowedxmlentitynames values testing.
'amp' => array(
'input' => array( '', 'amp' ),
'expected' => '&',
),
'lt' => array(
'input' => array( '', 'lt' ),
'expected' => '<',
),
'gt' => array(
'input' => array( '', 'gt' ),
'expected' => '>',
),
// $allowedentitynames values testing.
'nbsp' => array(
'input' => array( '', 'nbsp' ),
'expected' => utf8_encode( chr( 160 ) ),
),
'iexcl' => array(
'input' => array( '', 'iexcl' ),
'expected' => '¡',
),
'cent' => array(
'input' => array( '', 'cent' ),
'expected' => '¢',
),
// Some other value testing.
'test' => array(
'input' => array( '', 'test' ),
'expected' => '&test;',
),
);
}
/**
* Test that KSES globals are defined.
*
* @dataProvider data_kses_globals_are_defined
*
* @ticket 54060
*
* @param string $global The name of the global variable.
*/
public function test_kses_globals_are_defined( $global ) {
$this->assertArrayHasKey( $global, $GLOBALS );
}
/**
* Data provider for test_kses_globals_are_defined().
*
* @return array
*/
public function data_kses_globals_are_defined() {
return array(
'allowedposttags' => array(
'global' => 'allowedposttags',
),
'allowedtags' => array(
'global' => 'allowedtags',
),
'allowedentitynames' => array(
'global' => 'allowedentitynames',
),
'allowedxmlentitynames' => array(
'global' => 'allowedxmlentitynames',
),
);
}
}