diff --git a/src/wp-includes/SimplePie/src/Misc.php b/src/wp-includes/SimplePie/src/Misc.php index cc5db8aea39e0..dc88f9067c912 100644 --- a/src/wp-includes/SimplePie/src/Misc.php +++ b/src/wp-includes/SimplePie/src/Misc.php @@ -1875,7 +1875,11 @@ public static function atom_10_content_construct_type($attribs) public static function is_isegment_nz_nc($string) { - return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string); + if ( _wp_can_use_pcre_u() ) { + return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string); + } else { + return (bool) preg_match('/^([A-Za-z0-9\-._~!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/', $string); + } } public static function space_separated_tokens($string) diff --git a/src/wp-includes/class-wp-plugin-dependencies.php b/src/wp-includes/class-wp-plugin-dependencies.php index ee5e999903fb7..24f8aae54fe89 100644 --- a/src/wp-includes/class-wp-plugin-dependencies.php +++ b/src/wp-includes/class-wp-plugin-dependencies.php @@ -603,8 +603,14 @@ protected static function sanitize_dependency_slugs( $slugs ) { $slug = apply_filters( 'wp_plugin_dependencies_slug', $slug ); // Match to WordPress.org slug format. - if ( preg_match( '/^[a-z0-9]+(-[a-z0-9]+)*$/mu', $slug ) ) { - $sanitized_slugs[] = $slug; + if ( _wp_can_use_pcre_u() ) { + if ( preg_match( '/^[a-z0-9]+(-[a-z0-9]+)*$/mu', $slug ) ) { + $sanitized_slugs[] = $slug; + } + } else { + if ( preg_match( '/^[a-z0-9]+(-[a-z0-9]+)*$/m', $slug ) ) { + $sanitized_slugs[] = $slug; + } } } $sanitized_slugs = array_unique( $sanitized_slugs ); diff --git a/src/wp-includes/class-wp-text-diff-renderer-inline.php b/src/wp-includes/class-wp-text-diff-renderer-inline.php index aef1738f1f795..c957e27afe6e8 100644 --- a/src/wp-includes/class-wp-text-diff-renderer-inline.php +++ b/src/wp-includes/class-wp-text-diff-renderer-inline.php @@ -26,8 +26,35 @@ class WP_Text_Diff_Renderer_inline extends Text_Diff_Renderer_inline { */ public function _splitOnWords( $string, $newlineEscape = "\n" ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.stringFound,WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase $string = str_replace( "\0", '', $string ); - $words = preg_split( '/([^\w])/u', $string, -1, PREG_SPLIT_DELIM_CAPTURE ); - $words = str_replace( "\n", $newlineEscape, $words ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase + if ( _wp_can_use_pcre_u() ) { + $words = preg_split( '/([^\w])/u', $string, -1, PREG_SPLIT_DELIM_CAPTURE ); + } else { + if ( function_exists( 'mb_str_split' ) ) { + $chars = mb_str_split( $string, 1, 'UTF-8' ); + } else { + $chars = str_split( $string ); + } + $words = array(); + $current_word = ''; + + foreach ( $chars as $char ) { + // Simple heuristic: letters, numbers, underscore = word characters + if ( ctype_alnum( $char ) || '_' === $char || ord( $char ) > 127 ) { + $current_word .= $char; + } else { + if ( '' !== $current_word ) { + $words[] = $current_word; + $current_word = ''; + } + $words[] = $char; // Capture delimiter + } + } + if ( '' !== $current_word ) { + $words[] = $current_word; + } + } + + $words = str_replace( "\n", $newlineEscape, $words ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase return $words; } } diff --git a/src/wp-includes/comment.php b/src/wp-includes/comment.php index aabe9f60dbb4a..3a478ade54084 100644 --- a/src/wp-includes/comment.php +++ b/src/wp-includes/comment.php @@ -97,7 +97,11 @@ function check_comment( $author, $email, $url, $comment, $user_ip, $user_agent, * Check the comment fields for moderation keywords. If any are found, * fail the check for the given field by returning false. */ - $pattern = "#$word#iu"; + if ( _wp_can_use_pcre_u() ) { + $pattern = "#$word#iu"; + } else { + $pattern = "#$word#i"; + } if ( preg_match( $pattern, $author ) ) { return false; } @@ -1415,7 +1419,11 @@ function wp_check_comment_disallowed_list( $author, $email, $url, $comment, $use // Do some escaping magic so that '#' chars in the spam words don't break things: $word = preg_quote( $word, '#' ); - $pattern = "#$word#iu"; + if ( _wp_can_use_pcre_u() ) { + $pattern = "#$word#iu"; + } else { + $pattern = "#$word#i"; + } if ( preg_match( $pattern, $author ) || preg_match( $pattern, $email ) || preg_match( $pattern, $url ) diff --git a/src/wp-includes/formatting.php b/src/wp-includes/formatting.php index 61450afb9e3ea..d6bb12a5d204e 100644 --- a/src/wp-includes/formatting.php +++ b/src/wp-includes/formatting.php @@ -1048,7 +1048,7 @@ function _wp_is_valid_utf8_fallback( string $bytes ): bool { // Valid two-byte code points. if ( $b1 >= 0xC2 && $b1 <= 0xDF && $b2 >= 0x80 && $b2 <= 0xBF ) { - $i++; + ++$i; continue; } @@ -1289,19 +1289,12 @@ function wp_check_invalid_utf8( $text, $strip = false ) { return $text; } - // Check for support for utf8 in the installed PCRE library once and store the result in a static. - static $utf8_pcre = null; - if ( ! isset( $utf8_pcre ) ) { - // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged - $utf8_pcre = @preg_match( '/^./u', 'a' ); - } - // We can't demand utf8 in the PCRE installation, so just return the string in those cases. - if ( ! $utf8_pcre ) { + // Check for support for utf8 in the installed PCRE library. + if ( ! _wp_can_use_pcre_u() ) { return $text; } - // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- preg_match fails when it encounters invalid UTF8 in $text. - if ( 1 === @preg_match( '/^./us', $text ) ) { + if ( 1 === preg_match( '/^./us', $text ) ) { return $text; } @@ -4233,7 +4226,15 @@ function wp_trim_words( $text, $num_words = 55, $more = null ) { if ( str_starts_with( wp_get_word_count_type(), 'characters' ) && preg_match( '/^utf\-?8$/i', get_option( 'blog_charset' ) ) ) { $text = trim( preg_replace( "/[\n\r\t ]+/", ' ', $text ), ' ' ); - preg_match_all( '/./u', $text, $words_array ); + if ( _wp_can_use_pcre_u() ) { + preg_match_all( '/./u', $text, $words_array ); + } else { + if ( function_exists( 'mb_str_split' ) ) { + $words_array = array( mb_str_split( $text, 1, 'UTF-8' ) ); + } else { + $words_array = array( str_split( $text ) ); + } + } $words_array = array_slice( $words_array[0], 0, $num_words + 1 ); $sep = ''; } else { diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index cd7531f093cca..0f44d661e57c2 100644 --- a/src/wp-includes/functions.php +++ b/src/wp-includes/functions.php @@ -360,12 +360,20 @@ function wp_maybe_decline_date( $date, $format = '' ) { $decline = preg_match( '#[dj]\.? F#', $format ); } else { // If the format is not passed, try to guess it from the date string. - $decline = preg_match( '#\b\d{1,2}\.? [^\d ]+\b#u', $date ); + if ( _wp_can_use_pcre_u() ) { + $decline = preg_match( '#\b\d{1,2}\.? [^\d ]+\b#u', $date ); + } else { + $decline = preg_match( '#\b\d{1,2}\.? [^\d ]+\b#', $date ); + } } if ( $decline ) { foreach ( $months as $key => $month ) { - $months[ $key ] = '# ' . preg_quote( $month, '#' ) . '\b#u'; + if ( _wp_can_use_pcre_u() ) { + $months[ $key ] = '# ' . preg_quote( $month, '#' ) . '\b#u'; + } else { + $months[ $key ] = '# ' . preg_quote( $month, '#' ) . '\b#'; + } } foreach ( $months_genitive as $key => $month ) { @@ -383,12 +391,20 @@ function wp_maybe_decline_date( $date, $format = '' ) { $decline = preg_match( '#F [dj]#', $format ); } else { // If the format is not passed, try to guess it from the date string. - $decline = preg_match( '#\b[^\d ]+ \d{1,2}(st|nd|rd|th)?\b#u', trim( $date ) ); + if ( _wp_can_use_pcre_u() ) { + $decline = preg_match( '#\b[^\d ]+ \d{1,2}(st|nd|rd|th)?\b#u', trim( $date ) ); + } else { + $decline = preg_match( '#\b[^\d ]+ \d{1,2}(st|nd|rd|th)?\b#', trim( $date ) ); + } } if ( $decline ) { foreach ( $months as $key => $month ) { - $months[ $key ] = '#\b' . preg_quote( $month, '#' ) . ' (\d{1,2})(st|nd|rd|th)?([-–]\d{1,2})?(st|nd|rd|th)?\b#u'; + if ( _wp_can_use_pcre_u() ) { + $months[ $key ] = '#\b' . preg_quote( $month, '#' ) . ' (\d{1,2})(st|nd|rd|th)?([-–]\d{1,2})?(st|nd|rd|th)?\b#u'; + } else { + $months[ $key ] = '#\b' . preg_quote( $month, '#' ) . ' (\d{1,2})(st|nd|rd|th)?([-–]\d{1,2})?(st|nd|rd|th)?\b#'; + } } foreach ( $months_genitive as $key => $month ) { diff --git a/src/wp-includes/link-template.php b/src/wp-includes/link-template.php index 674e0a6fbf3f6..5980acc041c43 100644 --- a/src/wp-includes/link-template.php +++ b/src/wp-includes/link-template.php @@ -4564,7 +4564,33 @@ function get_avatar_data( $id_or_email, $args = null ) { } if ( ! empty( $name ) ) { - if ( preg_match( '/\p{Han}|\p{Hiragana}|\p{Katakana}|\p{Hangul}/u', $name ) || false === strpos( $name, ' ' ) ) { + $is_cjk = false; + + if ( _wp_can_use_pcre_u() ) { + $is_cjk = preg_match( '/\p{Han}|\p{Hiragana}|\p{Katakana}|\p{Hangul}/u', $name ); + } elseif ( class_exists( 'IntlChar' ) ) { + $first_char = mb_substr( $name, 0, 1, 'UTF-8' ); + $codepoint = IntlChar::ord( $first_char ); + + if ( null !== $codepoint ) { + $block = IntlChar::getBlockCode( $codepoint ); + $cjk_blocks = array( + IntlChar::BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS, + IntlChar::BLOCK_CODE_HANGUL_SYLLABLES, + IntlChar::BLOCK_CODE_HIRAGANA, + IntlChar::BLOCK_CODE_KATAKANA, + IntlChar::BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A, + IntlChar::BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B, + IntlChar::BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C, + IntlChar::BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D, + IntlChar::BLOCK_CODE_HANGUL_JAMO, + IntlChar::BLOCK_CODE_HANGUL_COMPATIBILITY_JAMO, + ); + $is_cjk = in_array( $block, $cjk_blocks, true ); + } + } + + if ( $is_cjk || false === strpos( $name, ' ' ) ) { $initials = mb_substr( $name, 0, min( 2, mb_strlen( $name, 'UTF-8' ) ), 'UTF-8' ); } else { $first = mb_substr( $name, 0, 1, 'UTF-8' ); diff --git a/src/wp-includes/pomo/po.php b/src/wp-includes/pomo/po.php index a4e3cab4ef17a..81a97b02b39ac 100644 --- a/src/wp-includes/pomo/po.php +++ b/src/wp-includes/pomo/po.php @@ -155,7 +155,13 @@ public static function unpoify( $input_string ) { $unpoified = ''; $previous_is_backslash = false; foreach ( $lines as $line ) { - preg_match_all( '/./u', $line, $chars ); + if ( _wp_can_use_pcre_u() ) { + preg_match_all( '/./u', $line, $chars ); + } elseif ( function_exists( 'mb_str_split' ) ) { + $chars = array( mb_str_split( $line, 1, 'UTF-8' ) ); + } else { + $chars = array( str_split( $line ) ); + } $chars = $chars[0]; foreach ( $chars as $char ) { if ( ! $previous_is_backslash ) { diff --git a/src/wp-includes/shortcodes.php b/src/wp-includes/shortcodes.php index bddf63ada28a3..58af064037a4d 100644 --- a/src/wp-includes/shortcodes.php +++ b/src/wp-includes/shortcodes.php @@ -613,7 +613,11 @@ function get_shortcode_atts_regex() { function shortcode_parse_atts( $text ) { $atts = array(); $pattern = get_shortcode_atts_regex(); - $text = preg_replace( "/[\x{00a0}\x{200b}]+/u", ' ', $text ); + if ( _wp_can_use_pcre_u() ) { + $text = preg_replace( "/[\x{00a0}\x{200b}]+/u", ' ', $text ); + } else { + $text = str_replace( array( "\xc2\xa0", "\xe2\x80\x8b" ), ' ', $text ); + } if ( preg_match_all( $pattern, $text, $match, PREG_SET_ORDER ) ) { foreach ( $match as $m ) { if ( ! empty( $m[1] ) ) {