Changeset 46901 for branches/5.2/src/wp-includes/formatting.php
- Timestamp:
- 12/12/2019 06:17:35 PM (6 years ago)
- Location:
- branches/5.2
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/5.2
- Property svn:mergeinfo changed
/trunk merged: 46893-46896
- Property svn:mergeinfo changed
-
branches/5.2/src/wp-includes/formatting.php
r45991 r46901 3044 3044 function wp_targeted_link_rel( $text ) { 3045 3045 // Don't run (more expensive) regex if no links with targets. 3046 if ( stripos( $text, 'target' ) !== false && stripos( $text, '<a ' ) !== false ) { 3047 $text = preg_replace_callback( '|<a\s([^>]*target\s*=[^>]*)>|i', 'wp_targeted_link_rel_callback', $text ); 3046 if ( stripos( $text, 'target' ) === false || stripos( $text, '<a ' ) === false || is_serialized( $text ) ) { 3047 return $text; 3048 } 3049 3050 $script_and_style_regex = '/<(script|style).*?<\/\\1>/si'; 3051 3052 preg_match_all( $script_and_style_regex, $text, $matches ); 3053 $extra_parts = $matches[0]; 3054 $html_parts = preg_split( $script_and_style_regex, $text ); 3055 3056 foreach ( $html_parts as &$part ) { 3057 $part = preg_replace_callback( '|<a\s([^>]*target\s*=[^>]*)>|i', 'wp_targeted_link_rel_callback', $part ); 3058 } 3059 3060 $text = ''; 3061 for ( $i = 0; $i < count( $html_parts ); $i++ ) { 3062 $text .= $html_parts[ $i ]; 3063 if ( isset( $extra_parts[ $i ] ) ) { 3064 $text .= $extra_parts[ $i ]; 3065 } 3048 3066 } 3049 3067 … … 3063 3081 */ 3064 3082 function wp_targeted_link_rel_callback( $matches ) { 3065 $link_html = $matches[1]; 3066 $rel_match = array(); 3083 $link_html = $matches[1]; 3084 $original_link_html = $link_html; 3085 3086 // Consider the html escaped if there are no unescaped quotes 3087 $is_escaped = ! preg_match( '/(^|[^\\\\])[\'"]/', $link_html ); 3088 if ( $is_escaped ) { 3089 // Replace only the quotes so that they are parsable by wp_kses_hair, leave the rest as is 3090 $link_html = preg_replace( '/\\\\([\'"])/', '$1', $link_html ); 3091 } 3092 3093 $atts = wp_kses_hair( $link_html, wp_allowed_protocols() ); 3067 3094 3068 3095 /** … … 3076 3103 $rel = apply_filters( 'wp_targeted_link_rel', 'noopener noreferrer', $link_html ); 3077 3104 3078 // Avoid additional regex if the filter removes rel values. 3079 if ( ! $rel ) { 3080 return "<a $link_html>"; 3081 } 3082 3083 // Value with delimiters, spaces around are optional. 3084 $attr_regex = '|rel\s*=\s*?(\\\\{0,1}["\'])(.*?)\\1|i'; 3085 preg_match( $attr_regex, $link_html, $rel_match ); 3086 3087 if ( empty( $rel_match[0] ) ) { 3088 // No delimiters, try with a single value and spaces, because `rel = va"lue` is totally fine... 3089 $attr_regex = '|rel\s*=(\s*)([^\s]*)|i'; 3090 preg_match( $attr_regex, $link_html, $rel_match ); 3091 } 3092 3093 if ( ! empty( $rel_match[0] ) ) { 3094 $parts = preg_split( '|\s+|', strtolower( $rel_match[2] ) ); 3095 $parts = array_map( 'esc_attr', $parts ); 3096 $needed = explode( ' ', $rel ); 3097 $parts = array_unique( array_merge( $parts, $needed ) ); 3098 $delimiter = trim( $rel_match[1] ) ? $rel_match[1] : '"'; 3099 $rel = 'rel=' . $delimiter . trim( implode( ' ', $parts ) ) . $delimiter; 3100 $link_html = str_replace( $rel_match[0], $rel, $link_html ); 3101 } elseif ( preg_match( '|target\s*=\s*?\\\\"|', $link_html ) ) { 3102 $link_html .= " rel=\\\"$rel\\\""; 3103 } elseif ( preg_match( '#(target|href)\s*=\s*?\'#', $link_html ) ) { 3104 $link_html .= " rel='$rel'"; 3105 } else { 3106 $link_html .= " rel=\"$rel\""; 3105 // Return early if no rel values to be added or if no actual target attribute 3106 if ( ! $rel || ! isset( $atts['target'] ) ) { 3107 return "<a $original_link_html>"; 3108 } 3109 3110 if ( isset( $atts['rel'] ) ) { 3111 $all_parts = preg_split( '/\s/', "{$atts['rel']['value']} $rel", -1, PREG_SPLIT_NO_EMPTY ); 3112 $rel = implode( ' ', array_unique( $all_parts ) ); 3113 } 3114 3115 $atts['rel']['whole'] = 'rel="' . esc_attr( $rel ) . '"'; 3116 $link_html = join( ' ', array_column( $atts, 'whole' ) ); 3117 3118 if ( $is_escaped ) { 3119 $link_html = preg_replace( '/[\'"]/', '\\\\$0', $link_html ); 3107 3120 } 3108 3121 … … 4809 4822 4810 4823 /** 4824 * Remove non-allowable HTML from parsed block attribute values when filtering 4825 * in the post context. 4826 * 4827 * @since 5.3.1 4828 * 4829 * @param string $string Content to be run through KSES. 4830 * @param array[]|string $allowed_html An array of allowed HTML elements 4831 * and attributes, or a context name 4832 * such as 'post'. 4833 * @param string[] $allowed_protocols Array of allowed URL protocols. 4834 * @return string Filtered text to run through KSES. 4835 */ 4836 function wp_pre_kses_block_attributes( $string, $allowed_html, $allowed_protocols ) { 4837 /* 4838 * `filter_block_content` is expected to call `wp_kses`. Temporarily remove 4839 * the filter to avoid recursion. 4840 */ 4841 remove_filter( 'pre_kses', 'wp_pre_kses_block_attributes', 10 ); 4842 $string = filter_block_content( $string, $allowed_html, $allowed_protocols ); 4843 add_filter( 'pre_kses', 'wp_pre_kses_block_attributes', 10, 3 ); 4844 4845 return $string; 4846 } 4847 4848 /** 4811 4849 * WordPress implementation of PHP sprintf() with filters. 4812 4850 *
Note: See TracChangeset
for help on using the changeset viewer.