X-Git-Url: https://scripts.mit.edu/gitweb/autoinstalls/wordpress.git/blobdiff_plain/7f1521bf193b382565eb753043c161f4cb3fcda7..16e7b37c7914d753890c1a05a9335f3b43751eb8:/wp-includes/kses.php diff --git a/wp-includes/kses.php b/wp-includes/kses.php index ba96b089..4745d8d7 100644 --- a/wp-includes/kses.php +++ b/wp-includes/kses.php @@ -34,8 +34,9 @@ /** * You can override this in a plugin. * - * The wp_kses_allowed_html filter is more powerful and supplies context. - * CUSTOM_TAGS is not recommended and should be considered deprecated. + * The {@see 'wp_kses_allowed_html'} filter is more powerful and supplies context. + * + * `CUSTOM_TAGS` is not recommended and should be considered deprecated. * * @see wp_kses_allowed_html() * @@ -97,6 +98,9 @@ if ( ! CUSTOM_TAGS ) { 'src' => true, ), 'b' => array(), + 'bdo' => array( + 'dir' => true, + ), 'big' => array(), 'blockquote' => array( 'cite' => true, @@ -395,6 +399,7 @@ if ( ! CUSTOM_TAGS ) { 'ol' => array( 'start' => true, 'type' => true, + 'reversed' => true, ), 'var' => array(), 'video' => array( @@ -513,28 +518,106 @@ if ( ! CUSTOM_TAGS ) { * * @since 1.0.0 * - * @param string $string Content to filter through kses - * @param array $allowed_html List of allowed HTML elements - * @param array $allowed_protocols Optional. Allowed protocol in links. + * @param string $string Content to filter through kses + * @param array $allowed_html List of allowed HTML elements + * @param array $allowed_protocols Optional. Allowed protocol in links. * @return string Filtered content with only allowed HTML elements */ function wp_kses( $string, $allowed_html, $allowed_protocols = array() ) { if ( empty( $allowed_protocols ) ) $allowed_protocols = wp_allowed_protocols(); - $string = wp_kses_no_null($string); - $string = wp_kses_js_entities($string); + $string = wp_kses_no_null( $string, array( 'slash_zero' => 'keep' ) ); $string = wp_kses_normalize_entities($string); $string = wp_kses_hook($string, $allowed_html, $allowed_protocols); // WP changed the order of these funcs and added args to wp_kses_hook return wp_kses_split($string, $allowed_html, $allowed_protocols); } +/** + * Filters one attribute only and ensures its value is allowed. + * + * This function has the advantage of being more secure than esc_attr() and can + * escape data in some situations where wp_kses() must strip the whole attribute. + * + * @since 4.2.3 + * + * @param string $string The 'whole' attribute, including name and value. + * @param string $element The element name to which the attribute belongs. + * @return string Filtered attribute. + */ +function wp_kses_one_attr( $string, $element ) { + $uris = array('xmlns', 'profile', 'href', 'src', 'cite', 'classid', 'codebase', 'data', 'usemap', 'longdesc', 'action'); + $allowed_html = wp_kses_allowed_html( 'post' ); + $allowed_protocols = wp_allowed_protocols(); + $string = wp_kses_no_null( $string, array( 'slash_zero' => 'keep' ) ); + + // Preserve leading and trailing whitespace. + $matches = array(); + preg_match('/^\s*/', $string, $matches); + $lead = $matches[0]; + preg_match('/\s*$/', $string, $matches); + $trail = $matches[0]; + if ( empty( $trail ) ) { + $string = substr( $string, strlen( $lead ) ); + } else { + $string = substr( $string, strlen( $lead ), -strlen( $trail ) ); + } + + // Parse attribute name and value from input. + $split = preg_split( '/\s*=\s*/', $string, 2 ); + $name = $split[0]; + if ( count( $split ) == 2 ) { + $value = $split[1]; + + // Remove quotes surrounding $value. + // Also guarantee correct quoting in $string for this one attribute. + if ( '' == $value ) { + $quote = ''; + } else { + $quote = $value[0]; + } + if ( '"' == $quote || "'" == $quote ) { + if ( substr( $value, -1 ) != $quote ) { + return ''; + } + $value = substr( $value, 1, -1 ); + } else { + $quote = '"'; + } + + // Sanitize quotes, angle braces, and entities. + $value = esc_attr( $value ); + + // Sanitize URI values. + if ( in_array( strtolower( $name ), $uris ) ) { + $value = wp_kses_bad_protocol( $value, $allowed_protocols ); + } + + $string = "$name=$quote$value$quote"; + $vless = 'n'; + } else { + $value = ''; + $vless = 'y'; + } + + // Sanitize attribute by name. + wp_kses_attr_check( $name, $value, $string, $vless, $element, $allowed_html ); + + // Restore whitespace. + return $lead . $string . $trail; +} + /** * Return a list of allowed tags and attributes for a given context. * * @since 3.5.0 * - * @param string $context The context for which to retrieve tags. Allowed values are - * post | strip | data | entities or the name of a field filter such as pre_user_description. + * @global array $allowedposttags + * @global array $allowedtags + * @global array $allowedentitynames + * + * @param string $context The context for which to retrieve tags. + * Allowed values are post, strip, data,entities, or + * the name of a field filter such as pre_user_description. * @return array List of allowed tags and their allowed attributes. */ function wp_kses_allowed_html( $context = '' ) { @@ -542,7 +625,7 @@ function wp_kses_allowed_html( $context = '' ) { if ( is_array( $context ) ) { /** - * Filter HTML elements allowed for a given context. + * Filters HTML elements allowed for a given context. * * @since 3.5.0 * @@ -583,19 +666,19 @@ function wp_kses_allowed_html( $context = '' ) { /** * You add any kses hooks here. * - * There is currently only one kses WordPress hook and it is called here. All - * parameters are passed to the hooks and expected to receive a string. + * There is currently only one kses WordPress hook, {@see 'pre_kses'}, and it is called here. + * All parameters are passed to the hooks and expected to receive a string. * * @since 1.0.0 * - * @param string $string Content to filter through kses - * @param array $allowed_html List of allowed HTML elements - * @param array $allowed_protocols Allowed protocol in links - * @return string Filtered content through 'pre_kses' hook + * @param string $string Content to filter through kses + * @param array $allowed_html List of allowed HTML elements + * @param array $allowed_protocols Allowed protocol in links + * @return string Filtered content through {@see 'pre_kses'} hook. */ function wp_kses_hook( $string, $allowed_html, $allowed_protocols ) { /** - * Filter content to be run through kses. + * Filters content to be run through kses. * * @since 2.3.0 * @@ -603,8 +686,7 @@ function wp_kses_hook( $string, $allowed_html, $allowed_protocols ) { * @param array $allowed_html Allowed HTML elements. * @param array $allowed_protocols Allowed protocol in links. */ - $string = apply_filters( 'pre_kses', $string, $allowed_html, $allowed_protocols ); - return $string; + return apply_filters( 'pre_kses', $string, $allowed_html, $allowed_protocols ); } /** @@ -625,9 +707,12 @@ function wp_kses_version() { * * @since 1.0.0 * - * @param string $string Content to filter - * @param array $allowed_html Allowed HTML elements - * @param array $allowed_protocols Allowed protocols to keep + * @global array $pass_allowed_html + * @global array $pass_allowed_protocols + * + * @param string $string Content to filter + * @param array $allowed_html Allowed HTML elements + * @param array $allowed_protocols Allowed protocols to keep * @return string Content with fixed HTML tags */ function wp_kses_split( $string, $allowed_html, $allowed_protocols ) { @@ -642,6 +727,11 @@ function wp_kses_split( $string, $allowed_html, $allowed_protocols ) { * * @since 3.1.0 * @access private + * + * @global array $pass_allowed_html + * @global array $pass_allowed_protocols + * + * @return string */ function _wp_kses_split_callback( $match ) { global $pass_allowed_html, $pass_allowed_protocols; @@ -663,9 +753,9 @@ function _wp_kses_split_callback( $match ) { * @access private * @since 1.0.0 * - * @param string $string Content to filter - * @param array $allowed_html Allowed HTML elements - * @param array $allowed_protocols Allowed protocols to keep + * @param string $string Content to filter + * @param array $allowed_html Allowed HTML elements + * @param array $allowed_protocols Allowed protocols to keep * @return string Fixed HTML element */ function wp_kses_split2($string, $allowed_html, $allowed_protocols) { @@ -689,7 +779,7 @@ function wp_kses_split2($string, $allowed_html, $allowed_protocols) { } // Allow HTML comments - if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?$%', $string, $matches)) + if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9-]+)([^>]*)>?$%', $string, $matches)) return ''; // It's seriously malformed @@ -722,18 +812,17 @@ function wp_kses_split2($string, $allowed_html, $allowed_protocols) { * * @since 1.0.0 * - * @param string $element HTML element/tag - * @param string $attr HTML attributes from HTML element to closing HTML element tag - * @param array $allowed_html Allowed HTML elements - * @param array $allowed_protocols Allowed protocols to keep + * @param string $element HTML element/tag + * @param string $attr HTML attributes from HTML element to closing HTML element tag + * @param array $allowed_html Allowed HTML elements + * @param array $allowed_protocols Allowed protocols to keep * @return string Sanitized HTML element */ function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) { - // Is there a closing XHTML slash at the end of the attributes? - if ( ! is_array( $allowed_html ) ) $allowed_html = wp_kses_allowed_html( $allowed_html ); + // Is there a closing XHTML slash at the end of the attributes? $xhtml_slash = ''; if (preg_match('%\s*/\s*$%', $attr)) $xhtml_slash = ' /'; @@ -748,50 +837,63 @@ function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) { // Go through $attrarr, and save the allowed attributes for this element // in $attr2 $attr2 = ''; + foreach ( $attrarr as $arreach ) { + if ( wp_kses_attr_check( $arreach['name'], $arreach['value'], $arreach['whole'], $arreach['vless'], $element, $allowed_html ) ) { + $attr2 .= ' '.$arreach['whole']; + } + } - $allowed_attr = $allowed_html[strtolower($element)]; - foreach ($attrarr as $arreach) { - if ( ! isset( $allowed_attr[strtolower($arreach['name'])] ) ) - continue; // the attribute is not allowed + // Remove any "<" or ">" characters + $attr2 = preg_replace('/[<>]/', '', $attr2); - $current = $allowed_attr[strtolower($arreach['name'])]; - if ( $current == '' ) - continue; // the attribute is not allowed + return "<$element$attr2$xhtml_slash>"; +} + +/** + * Determine whether an attribute is allowed. + * + * @since 4.2.3 + * + * @param string $name The attribute name. Returns empty string when not allowed. + * @param string $value The attribute value. Returns a filtered value. + * @param string $whole The name=value input. Returns filtered input. + * @param string $vless 'y' when attribute like "enabled", otherwise 'n'. + * @param string $element The name of the element to which this attribute belongs. + * @param array $allowed_html The full list of allowed elements and attributes. + * @return bool Is the attribute allowed? + */ +function wp_kses_attr_check( &$name, &$value, &$whole, $vless, $element, $allowed_html ) { + $allowed_attr = $allowed_html[strtolower( $element )]; - if ( strtolower( $arreach['name'] ) == 'style' ) { - $orig_value = $arreach['value']; - $value = safecss_filter_attr( $orig_value ); + $name_low = strtolower( $name ); + if ( ! isset( $allowed_attr[$name_low] ) || '' == $allowed_attr[$name_low] ) { + $name = $value = $whole = ''; + return false; + } - if ( empty( $value ) ) - continue; + if ( 'style' == $name_low ) { + $new_value = safecss_filter_attr( $value ); - $arreach['value'] = $value; - $arreach['whole'] = str_replace( $orig_value, $value, $arreach['whole'] ); + if ( empty( $new_value ) ) { + $name = $value = $whole = ''; + return false; } - if ( ! is_array($current) ) { - $attr2 .= ' '.$arreach['whole']; - // there are no checks + $whole = str_replace( $value, $new_value, $whole ); + $value = $new_value; + } - } else { - // there are some checks - $ok = true; - foreach ($current as $currkey => $currval) { - if ( ! wp_kses_check_attr_val($arreach['value'], $arreach['vless'], $currkey, $currval) ) { - $ok = false; - break; - } + if ( is_array( $allowed_attr[$name_low] ) ) { + // there are some checks + foreach ( $allowed_attr[$name_low] as $currkey => $currval ) { + if ( ! wp_kses_check_attr_val( $value, $vless, $currkey, $currval ) ) { + $name = $value = $whole = ''; + return false; } + } + } - if ( $ok ) - $attr2 .= ' '.$arreach['whole']; // it passed them - } // if !is_array($current) - } // foreach - - // Remove any "<" or ">" characters - $attr2 = preg_replace('/[<>]/', '', $attr2); - - return "<$element$attr2$xhtml_slash>"; + return true; } /** @@ -807,8 +909,8 @@ function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) { * * @since 1.0.0 * - * @param string $attr Attribute list from HTML element to closing HTML element tag - * @param array $allowed_protocols Allowed protocols to keep + * @param string $attr Attribute list from HTML element to closing HTML element tag + * @param array $allowed_protocols Allowed protocols to keep * @return array List of attributes after parsing */ function wp_kses_hair($attr, $allowed_protocols) { @@ -923,6 +1025,109 @@ function wp_kses_hair($attr, $allowed_protocols) { return $attrarr; } +/** + * Finds all attributes of an HTML element. + * + * Does not modify input. May return "evil" output. + * + * Based on wp_kses_split2() and wp_kses_attr() + * + * @since 4.2.3 + * + * @param string $element HTML element/tag + * @return array|bool List of attributes found in $element. Returns false on failure. + */ +function wp_kses_attr_parse( $element ) { + $valid = preg_match('%^(<\s*)(/\s*)?([a-zA-Z0-9]+\s*)([^>]*)(>?)$%', $element, $matches); + if ( 1 !== $valid ) { + return false; + } + + $begin = $matches[1]; + $slash = $matches[2]; + $elname = $matches[3]; + $attr = $matches[4]; + $end = $matches[5]; + + if ( '' !== $slash ) { + // Closing elements do not get parsed. + return false; + } + + // Is there a closing XHTML slash at the end of the attributes? + if ( 1 === preg_match( '%\s*/\s*$%', $attr, $matches ) ) { + $xhtml_slash = $matches[0]; + $attr = substr( $attr, 0, -strlen( $xhtml_slash ) ); + } else { + $xhtml_slash = ''; + } + + // Split it + $attrarr = wp_kses_hair_parse( $attr ); + if ( false === $attrarr ) { + return false; + } + + // Make sure all input is returned by adding front and back matter. + array_unshift( $attrarr, $begin . $slash . $elname ); + array_push( $attrarr, $xhtml_slash . $end ); + + return $attrarr; +} + +/** + * Builds an attribute list from string containing attributes. + * + * Does not modify input. May return "evil" output. + * In case of unexpected input, returns false instead of stripping things. + * + * Based on wp_kses_hair() but does not return a multi-dimensional array. + * + * @since 4.2.3 + * + * @param string $attr Attribute list from HTML element to closing HTML element tag + * @return array|bool List of attributes found in $attr. Returns false on failure. + */ +function wp_kses_hair_parse( $attr ) { + if ( '' === $attr ) { + return array(); + } + + $regex = + '(?:' + . '[-a-zA-Z:]+' // Attribute name. + . '|' + . '\[\[?[^\[\]]+\]\]?' // Shortcode in the name position implies unfiltered_html. + . ')' + . '(?:' // Attribute value. + . '\s*=\s*' // All values begin with '=' + . '(?:' + . '"[^"]*"' // Double-quoted + . '|' + . "'[^']*'" // Single-quoted + . '|' + . '[^\s"\']+' // Non-quoted + . '(?:\s|$)' // Must have a space + . ')' + . '|' + . '(?:\s|$)' // If attribute has no value, space is required. + . ')' + . '\s*'; // Trailing space is optional except as mentioned above. + + // Although it is possible to reduce this procedure to a single regexp, + // we must run that regexp twice to get exactly the expected result. + + $validation = "%^($regex)+$%"; + $extraction = "%$regex%"; + + if ( 1 === preg_match( $validation, $attr ) ) { + preg_match_all( $extraction, $attr, $attrarr ); + return $attrarr[0]; + } else { + return false; + } +} + /** * Performs different checks for attribute values. * @@ -931,10 +1136,10 @@ function wp_kses_hair($attr, $allowed_protocols) { * * @since 1.0.0 * - * @param string $value Attribute value - * @param string $vless Whether the value is valueless. Use 'y' or 'n' - * @param string $checkname What $checkvalue is checking for. - * @param mixed $checkvalue What constraint the value should pass + * @param string $value Attribute value + * @param string $vless Whether the value is valueless. Use 'y' or 'n' + * @param string $checkname What $checkvalue is checking for. + * @param mixed $checkvalue What constraint the value should pass * @return bool Whether check passes */ function wp_kses_check_attr_val($value, $vless, $checkname, $checkvalue) { @@ -1005,8 +1210,8 @@ function wp_kses_check_attr_val($value, $vless, $checkname, $checkvalue) { * * @since 1.0.0 * - * @param string $string Content to filter bad protocols from - * @param array $allowed_protocols Allowed protocols to keep + * @param string $string Content to filter bad protocols from + * @param array $allowed_protocols Allowed protocols to keep * @return string Filtered content */ function wp_kses_bad_protocol($string, $allowed_protocols) { @@ -1032,11 +1237,18 @@ function wp_kses_bad_protocol($string, $allowed_protocols) { * @since 1.0.0 * * @param string $string + * @param array $options Set 'slash_zero' => 'keep' when '\0' is allowed. Default is 'remove'. * @return string */ -function wp_kses_no_null($string) { - $string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', '', $string); - $string = preg_replace('/(\\\\0)+/', '', $string); +function wp_kses_no_null( $string, $options = null ) { + if ( ! isset( $options['slash_zero'] ) ) { + $options = array( 'slash_zero' => 'remove' ); + } + + $string = preg_replace( '/[\x00-\x08\x0B\x0C\x0E-\x1F]/', '', $string ); + if ( 'remove' == $options['slash_zero'] ) { + $string = preg_replace( '/\\\\+0+/', '', $string ); + } return $string; } @@ -1081,18 +1293,6 @@ function wp_kses_array_lc($inarray) { return $outarray; } -/** - * Removes the HTML JavaScript entities found in early versions of Netscape 4. - * - * @since 1.0.0 - * - * @param string $string - * @return string - */ -function wp_kses_js_entities($string) { - return preg_replace('%&\s*\{[^}]*(\}\s*;?|$)%', '', $string); -} - /** * Handles parsing errors in wp_kses_hair(). * @@ -1116,7 +1316,7 @@ function wp_kses_html_error($string) { * * @since 1.0.0 * - * @param string $string Content to check for bad protocols + * @param string $string Content to check for bad protocols * @param string $allowed_protocols Allowed protocols * @return string Sanitized content */ @@ -1147,7 +1347,7 @@ function wp_kses_bad_protocol_once($string, $allowed_protocols, $count = 1 ) { * @access private * @since 1.0.0 * - * @param string $string URI scheme to check against the whitelist + * @param string $string URI scheme to check against the whitelist * @param string $allowed_protocols Allowed protocols * @return string Sanitized content */ @@ -1183,11 +1383,9 @@ function wp_kses_bad_protocol_once2( $string, $allowed_protocols ) { */ function wp_kses_normalize_entities($string) { // Disarm all entities by converting & to & - $string = str_replace('&', '&', $string); // Change back the allowed entities in our entity whitelist - $string = preg_replace_callback('/&([A-Za-z]{2,8}[0-9]{0,2});/', 'wp_kses_named_entities', $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); @@ -1203,6 +1401,8 @@ function wp_kses_normalize_entities($string) { * * @since 3.0.0 * + * @global array $allowedentitynames + * * @param array $matches preg_replace_callback() matches array * @return string Correctly encoded entity */ @@ -1213,13 +1413,13 @@ function wp_kses_named_entities($matches) { return ''; $i = $matches[1]; - return ( ( ! in_array($i, $allowedentitynames) ) ? "&$i;" : "&$i;" ); + return ( ! in_array( $i, $allowedentitynames ) ) ? "&$i;" : "&$i;"; } /** * Callback for wp_kses_normalize_entities() regular expression. * - * This function helps {@see wp_kses_normalize_entities()} to only accept 16-bit + * This function helps wp_kses_normalize_entities() to only accept 16-bit * values and nothing more for `&#number;` entities. * * @access private @@ -1259,7 +1459,7 @@ function wp_kses_normalize_entities3($matches) { return ''; $hexchars = $matches[1]; - return ( ( ! valid_unicode(hexdec($hexchars)) ) ? "&#x$hexchars;" : '&#x'.ltrim($hexchars,'0').';' ); + return ( ! valid_unicode( hexdec( $hexchars ) ) ) ? "&#x$hexchars;" : '&#x'.ltrim($hexchars,'0').';'; } /** @@ -1335,7 +1535,7 @@ function wp_filter_kses( $data ) { * @return string Filtered content */ function wp_kses_data( $data ) { - return wp_kses( $data , current_filter() ); + return wp_kses( $data, current_filter() ); } /** @@ -1349,8 +1549,8 @@ function wp_kses_data( $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' ) ); +function wp_filter_post_kses( $data ) { + return addslashes( wp_kses( stripslashes( $data ), 'post' ) ); } /** @@ -1364,8 +1564,23 @@ function wp_filter_post_kses($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' ); +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. + * + * @since 4.4.2 + * + * @see map_deep() + * + * @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' ); } /** @@ -1377,7 +1592,7 @@ function wp_kses_post($data) { * @return string Filtered content without any HTML */ function wp_filter_nohtml_kses( $data ) { - return addslashes ( wp_kses( stripslashes( $data ), 'strip' ) ); + return addslashes( wp_kses( stripslashes( $data ), 'strip' ) ); } /** @@ -1413,8 +1628,8 @@ function kses_init_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 'init' hook (priority is - * default). Also does not remove kses_init() function from 'set_current_user' + * 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). * * @since 2.0.6 @@ -1436,8 +1651,8 @@ function kses_remove_filters() { /** * Sets up most of the Kses filters for input form content. * - * If you remove the kses_init() function from 'init' hook and - * 'set_current_user' (priority is default), then none of the Kses filter hooks + * If you remove the kses_init() function from {@see 'init'} hook and + * {@see 'set_current_user'} (priority is default), then none of the Kses filter hooks * will be added. * * First removes all of the Kses filters in case the current user does not need @@ -1449,14 +1664,19 @@ function kses_remove_filters() { function kses_init() { kses_remove_filters(); - if (current_user_can('unfiltered_html') == false) + if ( ! current_user_can( 'unfiltered_html' ) ) { kses_init_filters(); + } } /** * Inline CSS filter * * @since 2.8.1 + * + * @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 ) ) @@ -1471,23 +1691,84 @@ function safecss_filter_attr( $css, $deprecated = '' ) { $css_array = explode( ';', trim( $css ) ); /** - * Filter list of allowed CSS attributes. + * Filters list of allowed CSS attributes. * * @since 2.8.1 + * @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`. * * @param array $attr List of allowed CSS attributes. */ - $allowed_attr = apply_filters( 'safe_style_css', array( 'text-align', 'margin', 'color', 'float', - 'border', 'background', 'background-color', 'border-bottom', 'border-bottom-color', - 'border-bottom-style', 'border-bottom-width', 'border-collapse', 'border-color', 'border-left', - 'border-left-color', 'border-left-style', 'border-left-width', 'border-right', 'border-right-color', - 'border-right-style', 'border-right-width', 'border-spacing', 'border-style', 'border-top', - 'border-top-color', 'border-top-style', 'border-top-width', 'border-width', 'caption-side', - 'clear', 'cursor', 'direction', 'font', 'font-family', 'font-size', 'font-style', - 'font-variant', 'font-weight', 'height', 'letter-spacing', 'line-height', 'margin-bottom', - 'margin-left', 'margin-right', 'margin-top', 'overflow', 'padding', 'padding-bottom', - 'padding-left', 'padding-right', 'padding-top', 'text-decoration', 'text-indent', 'vertical-align', - 'width' ) ); + $allowed_attr = apply_filters( 'safe_style_css', array( + 'background', + 'background-color', + + 'border', + 'border-width', + 'border-color', + 'border-style', + 'border-right', + 'border-right-color', + 'border-right-style', + 'border-right-width', + 'border-bottom', + 'border-bottom-color', + 'border-bottom-style', + 'border-bottom-width', + 'border-left', + 'border-left-color', + 'border-left-style', + 'border-left-width', + 'border-top', + 'border-top-color', + 'border-top-style', + 'border-top-width', + + 'border-spacing', + 'border-collapse', + 'caption-side', + + 'color', + 'font', + 'font-family', + 'font-size', + 'font-style', + 'font-variant', + 'font-weight', + 'letter-spacing', + 'line-height', + 'text-decoration', + 'text-indent', + 'text-align', + + 'height', + 'min-height', + 'max-height', + + 'width', + 'min-width', + 'max-width', + + 'margin', + 'margin-right', + 'margin-bottom', + 'margin-left', + 'margin-top', + + 'padding', + 'padding-right', + 'padding-bottom', + 'padding-left', + 'padding-top', + + 'clear', + 'cursor', + 'direction', + 'float', + 'overflow', + 'vertical-align', + 'list-style-type', + ) ); if ( empty($allowed_attr) ) return $css;