diff --git a/wp-includes/formatting.php b/wp-includes/formatting.php index c0e4f14063..7493bcf3b5 100644 --- a/wp-includes/formatting.php +++ b/wp-includes/formatting.php @@ -2268,7 +2268,8 @@ function esc_url( $url, $protocols = null, $_context = 'display' ) { // Replace ampersands and single quotes only when displaying. if ( 'display' == $_context ) { - $url = preg_replace('/&([^#])(?![a-z]{2,8};)/', '&$1', $url); + $url = wp_kses_normalize_entities( $url ); + $url = str_replace( '&', '&', $url ); $url = str_replace( "'", ''', $url ); } diff --git a/wp-includes/kses.php b/wp-includes/kses.php index 05bdbd52ff..d36deb33e0 100644 --- a/wp-includes/kses.php +++ b/wp-includes/kses.php @@ -1027,14 +1027,9 @@ function wp_kses_html_error($string) { * @return string Sanitized content */ function wp_kses_bad_protocol_once($string, $allowed_protocols) { - global $_kses_allowed_protocols; - $_kses_allowed_protocols = $allowed_protocols; - - $string2 = preg_split('/:|:|:/i', $string, 2); - if ( isset($string2[1]) && !preg_match('%/\?%', $string2[0]) ) - $string = wp_kses_bad_protocol_once2($string2[0]) . trim($string2[1]); - else - $string = preg_replace_callback('/^((&[^;]*;|[\sA-Za-z0-9])*)'.'(:|:|&#[Xx]3[Aa];)\s*/', 'wp_kses_bad_protocol_once2', $string); + $string2 = preg_split( '/:|�*58;|�*3a;/i', $string, 2 ); + if ( isset($string2[1]) && ! preg_match('%/\?%', $string2[0]) ) + $string = wp_kses_bad_protocol_once2( $string2[0], $allowed_protocols ) . trim( $string2[1] ); return $string; } @@ -1048,29 +1043,19 @@ function wp_kses_bad_protocol_once($string, $allowed_protocols) { * @access private * @since 1.0.0 * - * @param mixed $matches string or preg_replace_callback() matches array to check for bad protocols + * @param string $string URI scheme to check against the whitelist + * @param string $allowed_protocols Allowed protocols * @return string Sanitized content */ -function wp_kses_bad_protocol_once2($matches) { - global $_kses_allowed_protocols; - - if ( is_array($matches) ) { - if ( empty($matches[1]) ) - return ''; - - $string = $matches[1]; - } else { - $string = $matches; - } - +function wp_kses_bad_protocol_once2( $string, $allowed_protocols ) { $string2 = wp_kses_decode_entities($string); $string2 = preg_replace('/\s/', '', $string2); $string2 = wp_kses_no_null($string2); $string2 = strtolower($string2); $allowed = false; - foreach ( (array) $_kses_allowed_protocols as $one_protocol) - if (strtolower($one_protocol) == $string2) { + foreach ( (array) $allowed_protocols as $one_protocol ) + if ( strtolower($one_protocol) == $string2 ) { $allowed = true; break; } @@ -1098,9 +1083,10 @@ function wp_kses_normalize_entities($string) { $string = str_replace('&', '&', $string); # Change back the allowed entities in our entity whitelist + $string = preg_replace_callback('/&([A-Za-z]{2,8});/', 'wp_kses_named_entities', $string); - $string = preg_replace_callback('/&#0*([0-9]{1,5});/', 'wp_kses_normalize_entities2', $string); - $string = preg_replace_callback('/&#[Xx]0*(([0-9A-Fa-f]{2}){1,2});/', 'wp_kses_normalize_entities3', $string); + $string = preg_replace_callback('/&#(0*[0-9]{1,7});/', 'wp_kses_normalize_entities2', $string); + $string = preg_replace_callback('/&#[Xx](0*[0-9A-Fa-f]{1,6});/', 'wp_kses_normalize_entities3', $string); return $string; } @@ -1143,7 +1129,14 @@ function wp_kses_normalize_entities2($matches) { return ''; $i = $matches[1]; - return ( ($i > 65535 || ! valid_unicode($i)) ? "&#$i;" : "&#$i;" ); + if (valid_unicode($i)) { + $i = str_pad(ltrim($i,'0'), 3, '0', STR_PAD_LEFT); + $i = "&#$i;"; + } else { + $i = "&#$i;"; + } + + return $i; } /** @@ -1162,7 +1155,7 @@ function wp_kses_normalize_entities3($matches) { return ''; $hexchars = $matches[1]; - return ( ( ! valid_unicode(hexdec($hexchars)) ) ? "&#x$hexchars;" : "&#x$hexchars;" ); + return ( ( ! valid_unicode(hexdec($hexchars)) ) ? "&#x$hexchars;" : '&#x'.ltrim($hexchars,'0').';' ); } /**