close
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions src/wp-includes/formatting.php
Original file line number Diff line number Diff line change
Expand Up @@ -2402,12 +2402,13 @@ function sanitize_sql_orderby( $orderby ) {
/**
* Sanitizes an HTML classname to ensure it only contains valid characters.
*
* Strips the string down to A-Z,a-z,0-9,_,-. If this results in an empty
* Strips the string down to characters that are allowed by the HTML5 specification for class attributes.
* Class names can contain any Unicode character except whitespace.
* string then it will return the alternative value supplied.
*
* @todo Expand to support the full range of CDATA that a class attribute can contain.
*
* @since 2.8.0
* @since 6.9.0 Added support for the full range of CDATA characters that a class attribute can contain,
* allowing any Unicode character except whitespace.
*
* @param string $classname The classname to be sanitized.
* @param string $fallback Optional. The value to return if the sanitization ends up as an empty string.
Expand All @@ -2418,12 +2419,16 @@ function sanitize_html_class( $classname, $fallback = '' ) {
// Strip out any percent-encoded characters.
$sanitized = preg_replace( '|%[a-fA-F0-9][a-fA-F0-9]|', '', $classname );

// Limit to A-Z, a-z, 0-9, '_', '-'.
$sanitized = preg_replace( '/[^A-Za-z0-9_-]/', '', $sanitized );
// Remove any whitespace characters (spaces, tabs, newlines, etc.).
$sanitized = preg_replace( '/\s+/', '', $sanitized );

// Allow all Unicode characters except whitespace characters.
$sanitized = preg_replace( '/[^\P{Z}]/u', '', $sanitized );

if ( '' === $sanitized && $fallback ) {
return sanitize_html_class( $fallback );
}

/**
* Filters a sanitized HTML class string.
*
Expand Down
85 changes: 85 additions & 0 deletions tests/phpunit/tests/formatting/sanitizeHtmlClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php
/**
* Test for sanitize_html_class function using dataProvider.
*
* @group formatting
*
* @covers ::sanitize_html_class
*/
class Test_Formatting_SanitizeHtmlClass extends WP_UnitTestCase {

/**
* Data provider for sanitize_html_class.
*
* @return array[]
*/
public function data_should_sanitize_class_names_when_valid() {
return array(
'valid-class' => array( 'valid-class', 'valid-class' ),
'class_123' => array( 'class_123', 'class_123' ),
'class-name' => array( 'class-name', 'class-name' ),
'class_一二三' => array( 'class一二三', 'class一二三' ),
'class_点' => array( 'class_点', 'class_点' ),
'space removed' => array( 'class 123', 'class123' ),
'tab removed' => array( "class\tname", 'classname' ),
'newline removed' => array( "class\nname", 'classname' ),
'special chars removed' => array( 'class$name', 'class$name' ),
'%20 removed (space)' => array( 'class%20name', 'classname' ),
'%24 removed ($)' => array( 'class%24name', 'classname' ),
'multiple invalid chars' => array( 'valid*class&^%$#@!', 'valid*class&^%$#@!' ),
);
}

/**
* @dataProvider data_should_sanitize_class_names_when_valid
* @ticket 63156
*/
public function test_should_sanitize_class_names_when_valid( $classname, $expected, $fallback = null ) {
if ( is_null( $fallback ) ) {
$this->assertSame( $expected, sanitize_html_class( $classname ) );
} else {
$this->assertSame( $expected, sanitize_html_class( $classname, $fallback ) );
}
}

/**
* Data provider for sanitize_html_class_with_fallback.
*
* @return array[]
*/
public function data_should_sanitize_class_with_fallback_when_empty_result() {
return array(
'empty string' => array( '', 'fallback-class', 'fallback-class' ),
'only spaces' => array( ' ', 'fallback-class', 'fallback-class' ),
'percent-encoded spaces' => array( '%20%20', 'fallback-class', 'fallback-class' ),
'spaces and percent' => array( ' %20 ', 'fallback-class', 'fallback-class' ),
);
}

/**
* @dataProvider data_should_sanitize_class_with_fallback_when_empty_result
* @ticket 63156
*/
public function test_should_sanitize_class_with_fallback_when_empty_result( $classname, $expected, $fallback ) {
$this->assertSame( $expected, sanitize_html_class( $classname, $fallback ) );
}

/**
* Data provider for sanitize_html_class_empty_result.
*
* @return array[]
*/
public function data_should_return_empty_result_when_no_fallback() {
return array(
'percent-encoded space' => array( ' %20 ', '' ),
);
}

/**
* @dataProvider data_should_return_empty_result_when_no_fallback
* @ticket 63156
*/
public function test_should_return_empty_result_when_no_fallback( $classname, $expected ) {
$this->assertSame( $expected, sanitize_html_class( $classname ) );
}
}
Loading