844 * @global array $allowedtags |
804 * @global array $allowedtags |
845 * @global array $allowedentitynames |
805 * @global array $allowedentitynames |
846 * |
806 * |
847 * @param string|array $context The context for which to retrieve tags. Allowed values are 'post', |
807 * @param string|array $context The context for which to retrieve tags. Allowed values are 'post', |
848 * 'strip', 'data', 'entities', or the name of a field filter such as |
808 * 'strip', 'data', 'entities', or the name of a field filter such as |
849 * 'pre_user_description'. |
809 * 'pre_user_description', or an array of allowed HTML elements and attributes. |
850 * @return array Array of allowed HTML tags and their allowed attributes. |
810 * @return array Array of allowed HTML tags and their allowed attributes. |
851 */ |
811 */ |
852 function wp_kses_allowed_html( $context = '' ) { |
812 function wp_kses_allowed_html( $context = '' ) { |
853 global $allowedposttags, $allowedtags, $allowedentitynames; |
813 global $allowedposttags, $allowedtags, $allowedentitynames; |
854 |
814 |
855 if ( is_array( $context ) ) { |
815 if ( is_array( $context ) ) { |
|
816 // When `$context` is an array it's actually an array of allowed HTML elements and attributes. |
|
817 $html = $context; |
|
818 $context = 'explicit'; |
|
819 |
856 /** |
820 /** |
857 * Filters the HTML that is allowed for a given context. |
821 * Filters the HTML tags that are allowed for a given context. |
|
822 * |
|
823 * HTML tags and attribute names are case-insensitive in HTML but must be |
|
824 * added to the KSES allow list in lowercase. An item added to the allow list |
|
825 * in upper or mixed case will not recognized as permitted by KSES. |
858 * |
826 * |
859 * @since 3.5.0 |
827 * @since 3.5.0 |
860 * |
828 * |
861 * @param array[]|string $context Context to judge allowed tags by. |
829 * @param array[] $html Allowed HTML tags. |
862 * @param string $context_type Context name. |
830 * @param string $context Context name. |
863 */ |
831 */ |
864 return apply_filters( 'wp_kses_allowed_html', $context, 'explicit' ); |
832 return apply_filters( 'wp_kses_allowed_html', $html, $context ); |
865 } |
833 } |
866 |
834 |
867 switch ( $context ) { |
835 switch ( $context ) { |
868 case 'post': |
836 case 'post': |
869 /** This filter is documented in wp-includes/kses.php */ |
837 /** This filter is documented in wp-includes/kses.php */ |
1038 * |
1006 * |
1039 * @global array[]|string $pass_allowed_html An array of allowed HTML elements and attributes, |
1007 * @global array[]|string $pass_allowed_html An array of allowed HTML elements and attributes, |
1040 * or a context name such as 'post'. |
1008 * or a context name such as 'post'. |
1041 * @global string[] $pass_allowed_protocols Array of allowed URL protocols. |
1009 * @global string[] $pass_allowed_protocols Array of allowed URL protocols. |
1042 * |
1010 * |
1043 * @param array $matches preg_replace regexp matches |
1011 * @param array $match preg_replace regexp matches |
1044 * @return string |
1012 * @return string |
1045 */ |
1013 */ |
1046 function _wp_kses_split_callback( $match ) { |
1014 function _wp_kses_split_callback( $match ) { |
1047 global $pass_allowed_html, $pass_allowed_protocols; |
1015 global $pass_allowed_html, $pass_allowed_protocols; |
1048 |
1016 |
1124 |
1092 |
1125 /** |
1093 /** |
1126 * Removes all attributes, if none are allowed for this element. |
1094 * Removes all attributes, if none are allowed for this element. |
1127 * |
1095 * |
1128 * If some are allowed it calls `wp_kses_hair()` to split them further, and then |
1096 * If some are allowed it calls `wp_kses_hair()` to split them further, and then |
1129 * it builds up new HTML code from the data that `kses_hair()` returns. It also |
1097 * it builds up new HTML code from the data that `wp_kses_hair()` returns. It also |
1130 * removes `<` and `>` characters, if there are any left. One more thing it does |
1098 * removes `<` and `>` characters, if there are any left. One more thing it does |
1131 * is to check if the tag has a closing XHTML slash, and if it does, it puts one |
1099 * is to check if the tag has a closing XHTML slash, and if it does, it puts one |
1132 * in the returned code as well. |
1100 * in the returned code as well. |
1133 * |
1101 * |
|
1102 * An array of allowed values can be defined for attributes. If the attribute value |
|
1103 * doesn't fall into the list, the attribute will be removed from the tag. |
|
1104 * |
|
1105 * Attributes can be marked as required. If a required attribute is not present, |
|
1106 * KSES will remove all attributes from the tag. As KSES doesn't match opening and |
|
1107 * closing tags, it's not possible to safely remove the tag itself, the safest |
|
1108 * fallback is to strip all attributes from the tag, instead. |
|
1109 * |
1134 * @since 1.0.0 |
1110 * @since 1.0.0 |
|
1111 * @since 5.9.0 Added support for an array of allowed values for attributes. |
|
1112 * Added support for required attributes. |
1135 * |
1113 * |
1136 * @param string $element HTML element/tag. |
1114 * @param string $element HTML element/tag. |
1137 * @param string $attr HTML attributes from HTML element to closing HTML element tag. |
1115 * @param string $attr HTML attributes from HTML element to closing HTML element tag. |
1138 * @param array[]|string $allowed_html An array of allowed HTML elements and attributes, |
1116 * @param array[]|string $allowed_html An array of allowed HTML elements and attributes, |
1139 * or a context name such as 'post'. See wp_kses_allowed_html() |
1117 * or a context name such as 'post'. See wp_kses_allowed_html() |
1159 } |
1137 } |
1160 |
1138 |
1161 // Split it. |
1139 // Split it. |
1162 $attrarr = wp_kses_hair( $attr, $allowed_protocols ); |
1140 $attrarr = wp_kses_hair( $attr, $allowed_protocols ); |
1163 |
1141 |
1164 // Go through $attrarr, and save the allowed attributes for this element |
1142 // Check if there are attributes that are required. |
1165 // in $attr2. |
1143 $required_attrs = array_filter( |
|
1144 $allowed_html[ $element_low ], |
|
1145 function( $required_attr_limits ) { |
|
1146 return isset( $required_attr_limits['required'] ) && true === $required_attr_limits['required']; |
|
1147 } |
|
1148 ); |
|
1149 |
|
1150 /* |
|
1151 * If a required attribute check fails, we can return nothing for a self-closing tag, |
|
1152 * but for a non-self-closing tag the best option is to return the element with attributes, |
|
1153 * as KSES doesn't handle matching the relevant closing tag. |
|
1154 */ |
|
1155 $stripped_tag = ''; |
|
1156 if ( empty( $xhtml_slash ) ) { |
|
1157 $stripped_tag = "<$element>"; |
|
1158 } |
|
1159 |
|
1160 // Go through $attrarr, and save the allowed attributes for this element in $attr2. |
1166 $attr2 = ''; |
1161 $attr2 = ''; |
1167 foreach ( $attrarr as $arreach ) { |
1162 foreach ( $attrarr as $arreach ) { |
|
1163 // Check if this attribute is required. |
|
1164 $required = isset( $required_attrs[ strtolower( $arreach['name'] ) ] ); |
|
1165 |
1168 if ( wp_kses_attr_check( $arreach['name'], $arreach['value'], $arreach['whole'], $arreach['vless'], $element, $allowed_html ) ) { |
1166 if ( wp_kses_attr_check( $arreach['name'], $arreach['value'], $arreach['whole'], $arreach['vless'], $element, $allowed_html ) ) { |
1169 $attr2 .= ' ' . $arreach['whole']; |
1167 $attr2 .= ' ' . $arreach['whole']; |
|
1168 |
|
1169 // If this was a required attribute, we can mark it as found. |
|
1170 if ( $required ) { |
|
1171 unset( $required_attrs[ strtolower( $arreach['name'] ) ] ); |
|
1172 } |
|
1173 } elseif ( $required ) { |
|
1174 // This attribute was required, but didn't pass the check. The entire tag is not allowed. |
|
1175 return $stripped_tag; |
1170 } |
1176 } |
|
1177 } |
|
1178 |
|
1179 // If some required attributes weren't set, the entire tag is not allowed. |
|
1180 if ( ! empty( $required_attrs ) ) { |
|
1181 return $stripped_tag; |
1171 } |
1182 } |
1172 |
1183 |
1173 // Remove any "<" or ">" characters. |
1184 // Remove any "<" or ">" characters. |
1174 $attr2 = preg_replace( '/[<>]/', '', $attr2 ); |
1185 $attr2 = preg_replace( '/[<>]/', '', $attr2 ); |
1175 |
1186 |
1178 |
1189 |
1179 /** |
1190 /** |
1180 * Determines whether an attribute is allowed. |
1191 * Determines whether an attribute is allowed. |
1181 * |
1192 * |
1182 * @since 4.2.3 |
1193 * @since 4.2.3 |
1183 * @since 5.0.0 Add support for `data-*` wildcard attributes. |
1194 * @since 5.0.0 Added support for `data-*` wildcard attributes. |
1184 * |
1195 * |
1185 * @param string $name The attribute name. Passed by reference. Returns empty string when not allowed. |
1196 * @param string $name The attribute name. Passed by reference. Returns empty string when not allowed. |
1186 * @param string $value The attribute value. Passed by reference. Returns a filtered value. |
1197 * @param string $value The attribute value. Passed by reference. Returns a filtered value. |
1187 * @param string $whole The `name=value` input. Passed by reference. Returns filtered input. |
1198 * @param string $whole The `name=value` input. Passed by reference. Returns filtered input. |
1188 * @param string $vless Whether the attribute is valueless. Use 'y' or 'n'. |
1199 * @param string $vless Whether the attribute is valueless. Use 'y' or 'n'. |
1212 * https://www.w3.org/TR/html40/struct/objects.html#adef-data). |
1223 * https://www.w3.org/TR/html40/struct/objects.html#adef-data). |
1213 * |
1224 * |
1214 * Note: the attribute name should only contain `A-Za-z0-9_-` chars, |
1225 * Note: the attribute name should only contain `A-Za-z0-9_-` chars, |
1215 * double hyphens `--` are not accepted by WordPress. |
1226 * double hyphens `--` are not accepted by WordPress. |
1216 */ |
1227 */ |
1217 if ( strpos( $name_low, 'data-' ) === 0 && ! empty( $allowed_attr['data-*'] ) && preg_match( '/^data(?:-[a-z0-9_]+)+$/', $name_low, $match ) ) { |
1228 if ( strpos( $name_low, 'data-' ) === 0 && ! empty( $allowed_attr['data-*'] ) |
|
1229 && preg_match( '/^data(?:-[a-z0-9_]+)+$/', $name_low, $match ) |
|
1230 ) { |
1218 /* |
1231 /* |
1219 * Add the whole attribute name to the allowed attributes and set any restrictions |
1232 * Add the whole attribute name to the allowed attributes and set any restrictions |
1220 * for the `data-*` attribute values for the current element. |
1233 * for the `data-*` attribute values for the current element. |
1221 */ |
1234 */ |
1222 $allowed_attr[ $match[0] ] = $allowed_attr['data-*']; |
1235 $allowed_attr[ $match[0] ] = $allowed_attr['data-*']; |
1594 |
1607 |
1595 if ( strtolower( $checkvalue ) != $vless ) { |
1608 if ( strtolower( $checkvalue ) != $vless ) { |
1596 $ok = false; |
1609 $ok = false; |
1597 } |
1610 } |
1598 break; |
1611 break; |
|
1612 |
|
1613 case 'values': |
|
1614 /* |
|
1615 * The values check is used when you want to make sure that the attribute |
|
1616 * has one of the given values. |
|
1617 */ |
|
1618 |
|
1619 if ( false === array_search( strtolower( $value ), $checkvalue, true ) ) { |
|
1620 $ok = false; |
|
1621 } |
|
1622 break; |
|
1623 |
|
1624 case 'value_callback': |
|
1625 /* |
|
1626 * The value_callback check is used when you want to make sure that the attribute |
|
1627 * value is accepted by the callback function. |
|
1628 */ |
|
1629 |
|
1630 if ( ! call_user_func( $checkvalue, $value ) ) { |
|
1631 $ok = false; |
|
1632 } |
|
1633 break; |
1599 } // End switch. |
1634 } // End switch. |
1600 |
1635 |
1601 return $ok; |
1636 return $ok; |
1602 } |
1637 } |
1603 |
1638 |
1844 * references are converted to their code points. |
1879 * references are converted to their code points. |
1845 * |
1880 * |
1846 * @since 5.5.0 |
1881 * @since 5.5.0 |
1847 * |
1882 * |
1848 * @global array $allowedentitynames |
1883 * @global array $allowedentitynames |
1849 * @global array $allowedxmlnamedentities |
1884 * @global array $allowedxmlentitynames |
1850 * |
1885 * |
1851 * @param array $matches preg_replace_callback() matches array. |
1886 * @param array $matches preg_replace_callback() matches array. |
1852 * @return string Correctly encoded entity. |
1887 * @return string Correctly encoded entity. |
1853 */ |
1888 */ |
1854 function wp_kses_xml_named_entities( $matches ) { |
1889 function wp_kses_xml_named_entities( $matches ) { |
1855 global $allowedentitynames, $allowedxmlnamedentities; |
1890 global $allowedentitynames, $allowedxmlentitynames; |
1856 |
1891 |
1857 if ( empty( $matches[1] ) ) { |
1892 if ( empty( $matches[1] ) ) { |
1858 return ''; |
1893 return ''; |
1859 } |
1894 } |
1860 |
1895 |
1861 $i = $matches[1]; |
1896 $i = $matches[1]; |
1862 |
1897 |
1863 if ( in_array( $i, $allowedxmlnamedentities, true ) ) { |
1898 if ( in_array( $i, $allowedxmlentitynames, true ) ) { |
1864 return "&$i;"; |
1899 return "&$i;"; |
1865 } elseif ( in_array( $i, $allowedentitynames, true ) ) { |
1900 } elseif ( in_array( $i, $allowedentitynames, true ) ) { |
1866 return html_entity_decode( "&$i;", ENT_HTML5 ); |
1901 return html_entity_decode( "&$i;", ENT_HTML5 ); |
1867 } |
1902 } |
1868 |
1903 |
2026 function wp_filter_post_kses( $data ) { |
2061 function wp_filter_post_kses( $data ) { |
2027 return addslashes( wp_kses( stripslashes( $data ), 'post' ) ); |
2062 return addslashes( wp_kses( stripslashes( $data ), 'post' ) ); |
2028 } |
2063 } |
2029 |
2064 |
2030 /** |
2065 /** |
|
2066 * Sanitizes global styles user content removing unsafe rules. |
|
2067 * |
|
2068 * @since 5.9.0 |
|
2069 * |
|
2070 * @param string $data Post content to filter. |
|
2071 * @return string Filtered post content with unsafe rules removed. |
|
2072 */ |
|
2073 function wp_filter_global_styles_post( $data ) { |
|
2074 $decoded_data = json_decode( wp_unslash( $data ), true ); |
|
2075 $json_decoding_error = json_last_error(); |
|
2076 if ( |
|
2077 JSON_ERROR_NONE === $json_decoding_error && |
|
2078 is_array( $decoded_data ) && |
|
2079 isset( $decoded_data['isGlobalStylesUserThemeJSON'] ) && |
|
2080 $decoded_data['isGlobalStylesUserThemeJSON'] |
|
2081 ) { |
|
2082 unset( $decoded_data['isGlobalStylesUserThemeJSON'] ); |
|
2083 |
|
2084 $data_to_encode = WP_Theme_JSON::remove_insecure_properties( $decoded_data ); |
|
2085 |
|
2086 $data_to_encode['isGlobalStylesUserThemeJSON'] = true; |
|
2087 return wp_slash( wp_json_encode( $data_to_encode ) ); |
|
2088 } |
|
2089 return $data; |
|
2090 } |
|
2091 |
|
2092 /** |
2031 * Sanitizes content for allowed HTML tags for post content. |
2093 * Sanitizes content for allowed HTML tags for post content. |
2032 * |
2094 * |
2033 * Post content refers to the page contents of the 'post' type and not `$_POST` |
2095 * Post content refers to the page contents of the 'post' type and not `$_POST` |
2034 * data from forms. |
2096 * data from forms. |
2035 * |
2097 * |
2093 add_filter( 'pre_comment_content', 'wp_filter_post_kses' ); |
2155 add_filter( 'pre_comment_content', 'wp_filter_post_kses' ); |
2094 } else { |
2156 } else { |
2095 add_filter( 'pre_comment_content', 'wp_filter_kses' ); |
2157 add_filter( 'pre_comment_content', 'wp_filter_kses' ); |
2096 } |
2158 } |
2097 |
2159 |
|
2160 // Global Styles filtering: Global Styles filters should be executed before normal post_kses HTML filters. |
|
2161 add_filter( 'content_save_pre', 'wp_filter_global_styles_post', 9 ); |
|
2162 add_filter( 'content_filtered_save_pre', 'wp_filter_global_styles_post', 9 ); |
|
2163 |
2098 // Post filtering. |
2164 // Post filtering. |
2099 add_filter( 'content_save_pre', 'wp_filter_post_kses' ); |
2165 add_filter( 'content_save_pre', 'wp_filter_post_kses' ); |
2100 add_filter( 'excerpt_save_pre', 'wp_filter_post_kses' ); |
2166 add_filter( 'excerpt_save_pre', 'wp_filter_post_kses' ); |
2101 add_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' ); |
2167 add_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' ); |
2102 } |
2168 } |
2119 |
2185 |
2120 // Comment filtering. |
2186 // Comment filtering. |
2121 remove_filter( 'pre_comment_content', 'wp_filter_post_kses' ); |
2187 remove_filter( 'pre_comment_content', 'wp_filter_post_kses' ); |
2122 remove_filter( 'pre_comment_content', 'wp_filter_kses' ); |
2188 remove_filter( 'pre_comment_content', 'wp_filter_kses' ); |
2123 |
2189 |
|
2190 // Global Styles filtering. |
|
2191 remove_filter( 'content_save_pre', 'wp_filter_global_styles_post', 9 ); |
|
2192 remove_filter( 'content_filtered_save_pre', 'wp_filter_global_styles_post', 9 ); |
|
2193 |
2124 // Post filtering. |
2194 // Post filtering. |
2125 remove_filter( 'content_save_pre', 'wp_filter_post_kses' ); |
2195 remove_filter( 'content_save_pre', 'wp_filter_post_kses' ); |
2126 remove_filter( 'excerpt_save_pre', 'wp_filter_post_kses' ); |
2196 remove_filter( 'excerpt_save_pre', 'wp_filter_post_kses' ); |
2127 remove_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' ); |
2197 remove_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' ); |
2128 } |
2198 } |
2146 |
2216 |
2147 /** |
2217 /** |
2148 * Filters an inline style attribute and removes disallowed rules. |
2218 * Filters an inline style attribute and removes disallowed rules. |
2149 * |
2219 * |
2150 * @since 2.8.1 |
2220 * @since 2.8.1 |
|
2221 * @since 4.4.0 Added support for `min-height`, `max-height`, `min-width`, and `max-width`. |
|
2222 * @since 4.6.0 Added support for `list-style-type`. |
|
2223 * @since 5.0.0 Added support for `background-image`. |
|
2224 * @since 5.1.0 Added support for `text-transform`. |
|
2225 * @since 5.2.0 Added support for `background-position` and `grid-template-columns`. |
|
2226 * @since 5.3.0 Added support for `grid`, `flex` and `column` layout properties. |
|
2227 * Extend `background-*` support of individual properties. |
|
2228 * @since 5.3.1 Added support for gradient backgrounds. |
|
2229 * @since 5.7.1 Added support for `object-position`. |
|
2230 * @since 5.8.0 Added support for `calc()` and `var()` values. |
2151 * |
2231 * |
2152 * @param string $css A string of CSS rules. |
2232 * @param string $css A string of CSS rules. |
2153 * @param string $deprecated Not used. |
2233 * @param string $deprecated Not used. |
2154 * @return string Filtered string of CSS rules. |
2234 * @return string Filtered string of CSS rules. |
2155 */ |
2235 */ |
2164 $allowed_protocols = wp_allowed_protocols(); |
2244 $allowed_protocols = wp_allowed_protocols(); |
2165 |
2245 |
2166 $css_array = explode( ';', trim( $css ) ); |
2246 $css_array = explode( ';', trim( $css ) ); |
2167 |
2247 |
2168 /** |
2248 /** |
2169 * Filters list of allowed CSS attributes. |
2249 * Filters the list of allowed CSS attributes. |
2170 * |
2250 * |
2171 * @since 2.8.1 |
2251 * @since 2.8.1 |
2172 * @since 4.4.0 Added support for `min-height`, `max-height`, `min-width`, and `max-width`. |
|
2173 * @since 4.6.0 Added support for `list-style-type`. |
|
2174 * @since 5.0.0 Added support for `background-image`. |
|
2175 * @since 5.1.0 Added support for `text-transform`. |
|
2176 * @since 5.2.0 Added support for `background-position` and `grid-template-columns`. |
|
2177 * @since 5.3.0 Added support for `grid`, `flex` and `column` layout properties. |
|
2178 * Extend `background-*` support of individual properties. |
|
2179 * @since 5.3.1 Added support for gradient backgrounds. |
|
2180 * @since 5.7.1 Added support for `object-position`. |
|
2181 * @since 5.8.0 Added support for `calc()` and `var()` values. |
|
2182 * |
2252 * |
2183 * @param string[] $attr Array of allowed CSS attributes. |
2253 * @param string[] $attr Array of allowed CSS attributes. |
2184 */ |
2254 */ |
2185 $allowed_attr = apply_filters( |
2255 $allowed_attr = apply_filters( |
2186 'safe_style_css', |
2256 'safe_style_css', |
2202 'border-right-color', |
2272 'border-right-color', |
2203 'border-right-style', |
2273 'border-right-style', |
2204 'border-right-width', |
2274 'border-right-width', |
2205 'border-bottom', |
2275 'border-bottom', |
2206 'border-bottom-color', |
2276 'border-bottom-color', |
|
2277 'border-bottom-left-radius', |
|
2278 'border-bottom-right-radius', |
2207 'border-bottom-style', |
2279 'border-bottom-style', |
2208 'border-bottom-width', |
2280 'border-bottom-width', |
|
2281 'border-bottom-right-radius', |
|
2282 'border-bottom-left-radius', |
2209 'border-left', |
2283 'border-left', |
2210 'border-left-color', |
2284 'border-left-color', |
2211 'border-left-style', |
2285 'border-left-style', |
2212 'border-left-width', |
2286 'border-left-width', |
2213 'border-top', |
2287 'border-top', |
2214 'border-top-color', |
2288 'border-top-color', |
|
2289 'border-top-left-radius', |
|
2290 'border-top-right-radius', |
2215 'border-top-style', |
2291 'border-top-style', |
2216 'border-top-width', |
2292 'border-top-width', |
|
2293 'border-top-left-radius', |
|
2294 'border-top-right-radius', |
2217 |
2295 |
2218 'border-spacing', |
2296 'border-spacing', |
2219 'border-collapse', |
2297 'border-collapse', |
2220 'caption-side', |
2298 'caption-side', |
2221 |
2299 |
2409 * @param bool $allow_css Whether the CSS in the test string is considered safe. |
2488 * @param bool $allow_css Whether the CSS in the test string is considered safe. |
2410 * @param string $css_test_string The CSS string to test. |
2489 * @param string $css_test_string The CSS string to test. |
2411 */ |
2490 */ |
2412 $allow_css = apply_filters( 'safecss_filter_attr_allow_css', $allow_css, $css_test_string ); |
2491 $allow_css = apply_filters( 'safecss_filter_attr_allow_css', $allow_css, $css_test_string ); |
2413 |
2492 |
2414 // Only add the CSS part if it passes the regex check. |
2493 // Only add the CSS part if it passes the regex check. |
2415 if ( $allow_css ) { |
2494 if ( $allow_css ) { |
2416 if ( '' !== $css ) { |
2495 if ( '' !== $css ) { |
2417 $css .= ';'; |
2496 $css .= ';'; |
2418 } |
2497 } |
2419 |
2498 |
2427 |
2506 |
2428 /** |
2507 /** |
2429 * Helper function to add global attributes to a tag in the allowed HTML list. |
2508 * Helper function to add global attributes to a tag in the allowed HTML list. |
2430 * |
2509 * |
2431 * @since 3.5.0 |
2510 * @since 3.5.0 |
2432 * @since 5.0.0 Add support for `data-*` wildcard attributes. |
2511 * @since 5.0.0 Added support for `data-*` wildcard attributes. |
|
2512 * @since 6.0.0 Added `dir`, `lang`, and `xml:lang` to global attributes. |
|
2513 * |
2433 * @access private |
2514 * @access private |
2434 * @ignore |
2515 * @ignore |
2435 * |
2516 * |
2436 * @param array $value An array of attributes. |
2517 * @param array $value An array of attributes. |
2437 * @return array The array of attributes with global attributes added. |
2518 * @return array The array of attributes with global attributes added. |
2442 'aria-details' => true, |
2523 'aria-details' => true, |
2443 'aria-label' => true, |
2524 'aria-label' => true, |
2444 'aria-labelledby' => true, |
2525 'aria-labelledby' => true, |
2445 'aria-hidden' => true, |
2526 'aria-hidden' => true, |
2446 'class' => true, |
2527 'class' => true, |
|
2528 'data-*' => true, |
|
2529 'dir' => true, |
2447 'id' => true, |
2530 'id' => true, |
|
2531 'lang' => true, |
2448 'style' => true, |
2532 'style' => true, |
2449 'title' => true, |
2533 'title' => true, |
2450 'role' => true, |
2534 'role' => true, |
2451 'data-*' => true, |
2535 'xml:lang' => true, |
2452 ); |
2536 ); |
2453 |
2537 |
2454 if ( true === $value ) { |
2538 if ( true === $value ) { |
2455 $value = array(); |
2539 $value = array(); |
2456 } |
2540 } |
2459 return array_merge( $value, $global_attributes ); |
2543 return array_merge( $value, $global_attributes ); |
2460 } |
2544 } |
2461 |
2545 |
2462 return $value; |
2546 return $value; |
2463 } |
2547 } |
|
2548 |
|
2549 /** |
|
2550 * Helper function to check if this is a safe PDF URL. |
|
2551 * |
|
2552 * @since 5.9.0 |
|
2553 * @access private |
|
2554 * @ignore |
|
2555 * |
|
2556 * @param string $url The URL to check. |
|
2557 * @return bool True if the URL is safe, false otherwise. |
|
2558 */ |
|
2559 function _wp_kses_allow_pdf_objects( $url ) { |
|
2560 // We're not interested in URLs that contain query strings or fragments. |
|
2561 if ( str_contains( $url, '?' ) || str_contains( $url, '#' ) ) { |
|
2562 return false; |
|
2563 } |
|
2564 |
|
2565 // If it doesn't have a PDF extension, it's not safe. |
|
2566 if ( ! str_ends_with( $url, '.pdf' ) ) { |
|
2567 return false; |
|
2568 } |
|
2569 |
|
2570 // If the URL host matches the current site's media URL, it's safe. |
|
2571 $upload_info = wp_upload_dir( null, false ); |
|
2572 $parsed_url = wp_parse_url( $upload_info['url'] ); |
|
2573 $upload_host = isset( $parsed_url['host'] ) ? $parsed_url['host'] : ''; |
|
2574 $upload_port = isset( $parsed_url['port'] ) ? ':' . $parsed_url['port'] : ''; |
|
2575 |
|
2576 if ( str_starts_with( $url, "http://$upload_host$upload_port/" ) |
|
2577 || str_starts_with( $url, "https://$upload_host$upload_port/" ) |
|
2578 ) { |
|
2579 return true; |
|
2580 } |
|
2581 |
|
2582 return false; |
|
2583 } |