: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* @global array $allowedentitynames
* @global array $allowedxmlentitynames
* @param array $matches preg_replace_callback() matches array.
* @return string Correctly encoded entity.
function wp_kses_xml_named_entities( $matches ) {
global $allowedentitynames, $allowedxmlentitynames;
if ( empty( $matches[1] ) ) {
if ( in_array( $i, $allowedxmlentitynames, true ) ) {
} elseif ( in_array( $i, $allowedentitynames, true ) ) {
return html_entity_decode( "&$i;", ENT_HTML5 );
* Callback for `wp_kses_normalize_entities()` regular expression.
* This function helps `wp_kses_normalize_entities()` to only accept 16-bit
* values and nothing more for `&#number;` entities.
* @param array $matches `preg_replace_callback()` matches array.
* @return string Correctly encoded entity.
function wp_kses_normalize_entities2( $matches ) {
if ( empty( $matches[1] ) ) {
if ( valid_unicode( $i ) ) {
$i = str_pad( ltrim( $i, '0' ), 3, '0', STR_PAD_LEFT );
* Callback for `wp_kses_normalize_entities()` for regular expression.
* This function helps `wp_kses_normalize_entities()` to only accept valid Unicode
* numeric entities in hex form.
* @param array $matches `preg_replace_callback()` matches array.
* @return string Correctly encoded entity.
function wp_kses_normalize_entities3( $matches ) {
if ( empty( $matches[1] ) ) {
return ( ! valid_unicode( hexdec( $hexchars ) ) ) ? "&#x$hexchars;" : '&#x' . ltrim( $hexchars, '0' ) . ';';
* Determines if a Unicode codepoint is valid.
* @param int $i Unicode codepoint.
* @return bool Whether or not the codepoint is a valid Unicode codepoint.
function valid_unicode( $i ) {
return ( 0x9 === $i || 0xa === $i || 0xd === $i ||
( 0x20 <= $i && $i <= 0xd7ff ) ||
( 0xe000 <= $i && $i <= 0xfffd ) ||
( 0x10000 <= $i && $i <= 0x10ffff )
* Converts all numeric HTML entities to their named counterparts.
* This function decodes numeric HTML entities (`A` and `A`).
* It doesn't do anything with named entities like `ä`, but we don't
* need them in the allowed URL protocols system anyway.
* @param string $content Content to change entities.
* @return string Content after decoded entities.
function wp_kses_decode_entities( $content ) {
$content = preg_replace_callback( '/&#([0-9]+);/', '_wp_kses_decode_entities_chr', $content );
$content = preg_replace_callback( '/&#[Xx]([0-9A-Fa-f]+);/', '_wp_kses_decode_entities_chr_hexdec', $content );
* Regex callback for `wp_kses_decode_entities()`.
* @param array $matches preg match
function _wp_kses_decode_entities_chr( $matches ) {
return chr( $matches[1] );
* Regex callback for `wp_kses_decode_entities()`.
* @param array $matches preg match
function _wp_kses_decode_entities_chr_hexdec( $matches ) {
return chr( hexdec( $matches[1] ) );
* Sanitize content with allowed HTML KSES rules.
* This function expects slashed data.
* @param string $data Content to filter, expected to be escaped with slashes.
* @return string Filtered content.
function wp_filter_kses( $data ) {
return addslashes( wp_kses( stripslashes( $data ), current_filter() ) );
* Sanitize content with allowed HTML KSES rules.
* This function expects unslashed data.
* @param string $data Content to filter, expected to not be escaped.
* @return string Filtered content.
function wp_kses_data( $data ) {
return wp_kses( $data, current_filter() );
* Sanitizes content for allowed HTML tags for post content.
* Post content refers to the page contents of the 'post' type and not `$_POST`
* This function expects slashed data.
* @param string $data Post content to filter, expected to be escaped with slashes.
* @return string Filtered post content with allowed HTML tags and attributes intact.
function wp_filter_post_kses( $data ) {
return addslashes( wp_kses( stripslashes( $data ), 'post' ) );
* Sanitizes global styles user content removing unsafe rules.
* @param string $data Post content to filter.
* @return string Filtered post content with unsafe rules removed.
function wp_filter_global_styles_post( $data ) {
$decoded_data = json_decode( wp_unslash( $data ), true );
$json_decoding_error = json_last_error();
JSON_ERROR_NONE === $json_decoding_error &&
is_array( $decoded_data ) &&
isset( $decoded_data['isGlobalStylesUserThemeJSON'] ) &&
$decoded_data['isGlobalStylesUserThemeJSON']
unset( $decoded_data['isGlobalStylesUserThemeJSON'] );
$data_to_encode = WP_Theme_JSON::remove_insecure_properties( $decoded_data, 'custom' );
$data_to_encode['isGlobalStylesUserThemeJSON'] = true;
return wp_slash( wp_json_encode( $data_to_encode ) );
* Sanitizes content for allowed HTML tags for post content.
* Post content refers to the page contents of the 'post' type and not `$_POST`
* This function expects unslashed data.
* @param string $data Post content to filter.
* @return string Filtered post content with allowed HTML tags and attributes intact.
function wp_kses_post( $data ) {
return wp_kses( $data, 'post' );
* Navigates through an array, object, or scalar, and sanitizes content for
* allowed HTML tags for post content.
* @param mixed $data The array, object, or scalar value to inspect.
* @return mixed The filtered content.
function wp_kses_post_deep( $data ) {
return map_deep( $data, 'wp_kses_post' );
* Strips all HTML from a text string.
* This function expects slashed data.
* @param string $data Content to strip all HTML from.
* @return string Filtered content without any HTML.
function wp_filter_nohtml_kses( $data ) {
return addslashes( wp_kses( stripslashes( $data ), 'strip' ) );
* Adds all KSES input form content filters.
* All hooks have default priority. The `wp_filter_kses()` function is added to
* the 'pre_comment_content' and 'title_save_pre' hooks.
* The `wp_filter_post_kses()` function is added to the 'content_save_pre',
* 'excerpt_save_pre', and 'content_filtered_save_pre' hooks.
function kses_init_filters() {
add_filter( 'title_save_pre', 'wp_filter_kses' );
if ( current_user_can( 'unfiltered_html' ) ) {
add_filter( 'pre_comment_content', 'wp_filter_post_kses' );
add_filter( 'pre_comment_content', 'wp_filter_kses' );
// Global Styles filtering: Global Styles filters should be executed before normal post_kses HTML filters.
add_filter( 'content_save_pre', 'wp_filter_global_styles_post', 9 );
add_filter( 'content_filtered_save_pre', 'wp_filter_global_styles_post', 9 );
add_filter( 'content_save_pre', 'wp_filter_post_kses' );
add_filter( 'excerpt_save_pre', 'wp_filter_post_kses' );
add_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );
* Removes all KSES input form content filters.
* A quick procedural method to removing all of the filters that KSES uses for
* content in WordPress Loop.
* Does not remove the `kses_init()` function from {@see 'init'} hook (priority is
* default). Also does not remove `kses_init()` function from {@see 'set_current_user'}
* hook (priority is also default).
function kses_remove_filters() {
remove_filter( 'title_save_pre', 'wp_filter_kses' );
remove_filter( 'pre_comment_content', 'wp_filter_post_kses' );
remove_filter( 'pre_comment_content', 'wp_filter_kses' );
// Global Styles filtering.
remove_filter( 'content_save_pre', 'wp_filter_global_styles_post', 9 );
remove_filter( 'content_filtered_save_pre', 'wp_filter_global_styles_post', 9 );
remove_filter( 'content_save_pre', 'wp_filter_post_kses' );
remove_filter( 'excerpt_save_pre', 'wp_filter_post_kses' );
remove_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );
* Sets up most of the KSES filters for input form content.
* First removes all of the KSES filters in case the current user does not need
* to have KSES filter the content. If the user does not have `unfiltered_html`
* capability, then KSES filters are added.
if ( ! current_user_can( 'unfiltered_html' ) ) {
* Filters an inline style attribute and removes disallowed rules.
* @since 4.4.0 Added support for `min-height`, `max-height`, `min-width`, and `max-width`.
* @since 4.6.0 Added support for `list-style-type`.
* @since 5.0.0 Added support for `background-image`.
* @since 5.1.0 Added support for `text-transform`.
* @since 5.2.0 Added support for `background-position` and `grid-template-columns`.
* @since 5.3.0 Added support for `grid`, `flex` and `column` layout properties.
* Extended `background-*` support for individual properties.
* @since 5.3.1 Added support for gradient backgrounds.
* @since 5.7.1 Added support for `object-position`.
* @since 5.8.0 Added support for `calc()` and `var()` values.
* @since 6.1.0 Added support for `min()`, `max()`, `minmax()`, `clamp()`,
* nested `var()` values, and assigning values to CSS variables.
* Added support for `object-fit`, `gap`, `column-gap`, `row-gap`, and `flex-wrap`.
* Extended `margin-*` and `padding-*` support for logical properties.
* @since 6.2.0 Added support for `aspect-ratio`, `position`, `top`, `right`, `bottom`, `left`,
* and `z-index` CSS properties.
* @since 6.3.0 Extended support for `filter` to accept a URL and added support for repeat().
* Added support for `box-shadow`.
* @since 6.4.0 Added support for `writing-mode`.
* @since 6.5.0 Added support for `background-repeat`.
* @since 6.6.0 Added support for `grid-column`, `grid-row`, and `container-type`.
* @param string $css A string of CSS rules.
* @param string $deprecated Not used.
* @return string Filtered string of CSS rules.
function safecss_filter_attr( $css, $deprecated = '' ) {
if ( ! empty( $deprecated ) ) {
_deprecated_argument( __FUNCTION__, '2.8.1' ); // Never implemented.
$css = wp_kses_no_null( $css );
$css = str_replace( array( "\n", "\r", "\t" ), '', $css );
$allowed_protocols = wp_allowed_protocols();
$css_array = explode( ';', trim( $css ) );
* Filters the list of allowed CSS attributes.
* @param string[] $attr Array of allowed CSS attributes.
$allowed_attr = apply_filters(
'border-bottom-left-radius',
'border-bottom-right-radius',
'border-bottom-right-radius',
'border-bottom-left-radius',
'border-top-left-radius',
'border-top-right-radius',
'border-top-left-radius',
'border-top-right-radius',