Skip to content
Closed
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
6 changes: 4 additions & 2 deletions src/wp-includes/fonts/class-wp-font-collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,10 @@ private static function get_sanitization_schema() {
array(
'font_family_settings' => array(
'name' => 'sanitize_text_field',
'slug' => 'sanitize_title',
'fontFamily' => 'sanitize_text_field',
'slug' => static function ( $value ) {
return _wp_to_kebab_case( sanitize_title( $value ) );
},
'fontFamily' => 'WP_Font_Utils::sanitize_font_family',
'preview' => 'sanitize_url',
'fontFace' => array(
array(
Expand Down
58 changes: 38 additions & 20 deletions src/wp-includes/fonts/class-wp-font-utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,36 @@
* @access private
*/
class WP_Font_Utils {
/**
* Adds surrounding quotes to font family names that contain special characters.
*
* It follows the recommendations from the CSS Fonts Module Level 4.
* @link https://www.w3.org/TR/css-fonts-4/#font-family-prop
*
* @since 6.5.0
*
* @param string $item A font family name.
* @return string The font family name with surrounding quotes, if necessary.
*/
private static function maybe_add_quotes( $item ) {
// Matches strings that are not exclusively alphabetic characters or hyphens, and do not exactly follow the pattern generic(alphabetic characters or hyphens).
$regex = '/^(?!generic\([a-zA-Z\-]+\)$)(?!^[a-zA-Z\-]+$).+/';
$item = trim( $item );
if ( preg_match( $regex, $item ) ) {
$item = trim( $item, "\"'" );
return '"' . $item . '"';
}
return $item;
}

/**
* Sanitizes and formats font family names.
*
* - Applies `sanitize_text_field`
* - Adds surrounding quotes to names that contain spaces and are not already quoted
* - Applies `sanitize_text_field`.
* - Adds surrounding quotes to names containing any characters that are not alphabetic or dashes.
*
* It follows the recommendations from the CSS Fonts Module Level 4.
* @link https://www.w3.org/TR/css-fonts-4/#font-family-prop
*
* @since 6.5.0
* @access private
Expand All @@ -37,26 +62,19 @@ public static function sanitize_font_family( $font_family ) {
return '';
}

$font_family = sanitize_text_field( $font_family );
$font_families = explode( ',', $font_family );
$wrapped_font_families = array_map(
function ( $family ) {
$trimmed = trim( $family );
if ( ! empty( $trimmed ) && str_contains( $trimmed, ' ' ) && ! str_contains( $trimmed, "'" ) && ! str_contains( $trimmed, '"' ) ) {
return '"' . $trimmed . '"';
$output = sanitize_text_field( $font_family );
$formatted_items = array();
if ( str_contains( $output, ',' ) ) {
$items = explode( ',', $output );
foreach ( $items as $item ) {
$formatted_item = self::maybe_add_quotes( $item );
if ( ! empty( $formatted_item ) ) {
$formatted_items[] = $formatted_item;
}
return $trimmed;
},
$font_families
);

if ( count( $wrapped_font_families ) === 1 ) {
$font_family = $wrapped_font_families[0];
} else {
$font_family = implode( ', ', $wrapped_font_families );
}
return implode( ', ', $formatted_items );
}

return $font_family;
return self::maybe_add_quotes( $output );
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public function data_create_font_collection() {
'font_families' => array(
array(
'font_family_settings' => array(
'fontFamily' => 'Open Sans, sans-serif',
'fontFamily' => '"Open Sans", sans-serif',
'slug' => 'open-sans',
'name' => 'Open Sans',
'fontFace' => array(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,13 @@ public function test_should_sanitize_font_family( $font_family, $expected ) {
public function data_should_sanitize_font_family() {
return array(
'data_families_with_spaces_and_numbers' => array(
'font_family' => 'Rock 3D , Open Sans,serif',
'expected' => '"Rock 3D", "Open Sans", serif',
'font_family' => 'Arial, Rock 3D , Open Sans,serif',
'expected' => 'Arial, "Rock 3D", "Open Sans", serif',
),
'data_single_font_family' => array(
'font_family' => 'Rock 3D',
'expected' => '"Rock 3D"',
),
'data_no_spaces' => array(
'font_family' => 'Rock3D',
'expected' => 'Rock3D',
),
'data_many_spaces_and_existing_quotes' => array(
'font_family' => 'Rock 3D serif, serif,sans-serif, "Open Sans"',
'expected' => '"Rock 3D serif", serif, sans-serif, "Open Sans"',
Expand All @@ -58,6 +54,10 @@ public function data_should_sanitize_font_family() {
'font_family' => " Rock 3D</style><script>alert('XSS');</script>\n ",
'expected' => '"Rock 3D"',
),
'data_font_family_with_generic_names' => array(
'font_family' => 'generic(kai), generic(font[name]), generic(fangsong), Rock 3D',
'expected' => 'generic(kai), "generic(font[name])", generic(fangsong), "Rock 3D"',
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ public function test_update_item() {

$settings = array(
'name' => 'Open Sans',
'fontFamily' => '"Open Sans, "Noto Sans", sans-serif',
'fontFamily' => 'Open Sans, "Noto Sans", sans-serif',
'preview' => 'https://s.w.org/images/fonts/16.9/previews/open-sans/open-sans-400-normal.svg',
);

Expand All @@ -700,7 +700,7 @@ public function test_update_item() {
$expected_settings = array(
'name' => $settings['name'],
'slug' => 'open-sans-2',
'fontFamily' => $settings['fontFamily'],
'fontFamily' => '"Open Sans", "Noto Sans", sans-serif',
'preview' => $settings['preview'],
);
$this->assertSame( $expected_settings, $data['font_family_settings'], 'The response font_family_settings should match expected settings.' );
Expand Down