wp/wp-includes/kses.php
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
    32  */
    32  */
    33 
    33 
    34 /**
    34 /**
    35  * You can override this in a plugin.
    35  * You can override this in a plugin.
    36  *
    36  *
    37  * The wp_kses_allowed_html filter is more powerful and supplies context.
    37  * The {@see 'wp_kses_allowed_html'} filter is more powerful and supplies context.
    38  * CUSTOM_TAGS is not recommended and should be considered deprecated.
    38  *
       
    39  * `CUSTOM_TAGS` is not recommended and should be considered deprecated.
    39  *
    40  *
    40  * @see wp_kses_allowed_html()
    41  * @see wp_kses_allowed_html()
    41  *
    42  *
    42  * @since 1.2.0
    43  * @since 1.2.0
    43  */
    44  */
    95 			'muted' => true,
    96 			'muted' => true,
    96 			'preload' => true,
    97 			'preload' => true,
    97 			'src' => true,
    98 			'src' => true,
    98 		),
    99 		),
    99 		'b' => array(),
   100 		'b' => array(),
       
   101 		'bdo' => array(
       
   102 			'dir' => true,
       
   103 		),
   100 		'big' => array(),
   104 		'big' => array(),
   101 		'blockquote' => array(
   105 		'blockquote' => array(
   102 			'cite' => true,
   106 			'cite' => true,
   103 			'lang' => true,
   107 			'lang' => true,
   104 			'xml:lang' => true,
   108 			'xml:lang' => true,
   393 			'type' => true,
   397 			'type' => true,
   394 		),
   398 		),
   395 		'ol' => array(
   399 		'ol' => array(
   396 			'start' => true,
   400 			'start' => true,
   397 			'type' => true,
   401 			'type' => true,
       
   402 			'reversed' => true,
   398 		),
   403 		),
   399 		'var' => array(),
   404 		'var' => array(),
   400 		'video' => array(
   405 		'video' => array(
   401 			'autoplay' => true,
   406 			'autoplay' => true,
   402 			'controls' => true,
   407 			'controls' => true,
   511  * covers all common link protocols, except for 'javascript' which should not
   516  * covers all common link protocols, except for 'javascript' which should not
   512  * be allowed for untrusted users.
   517  * be allowed for untrusted users.
   513  *
   518  *
   514  * @since 1.0.0
   519  * @since 1.0.0
   515  *
   520  *
   516  * @param string $string Content to filter through kses
   521  * @param string $string            Content to filter through kses
   517  * @param array $allowed_html List of allowed HTML elements
   522  * @param array  $allowed_html      List of allowed HTML elements
   518  * @param array $allowed_protocols Optional. Allowed protocol in links.
   523  * @param array  $allowed_protocols Optional. Allowed protocol in links.
   519  * @return string Filtered content with only allowed HTML elements
   524  * @return string Filtered content with only allowed HTML elements
   520  */
   525  */
   521 function wp_kses( $string, $allowed_html, $allowed_protocols = array() ) {
   526 function wp_kses( $string, $allowed_html, $allowed_protocols = array() ) {
   522 	if ( empty( $allowed_protocols ) )
   527 	if ( empty( $allowed_protocols ) )
   523 		$allowed_protocols = wp_allowed_protocols();
   528 		$allowed_protocols = wp_allowed_protocols();
   524 	$string = wp_kses_no_null($string);
   529 	$string = wp_kses_no_null( $string, array( 'slash_zero' => 'keep' ) );
   525 	$string = wp_kses_js_entities($string);
       
   526 	$string = wp_kses_normalize_entities($string);
   530 	$string = wp_kses_normalize_entities($string);
   527 	$string = wp_kses_hook($string, $allowed_html, $allowed_protocols); // WP changed the order of these funcs and added args to wp_kses_hook
   531 	$string = wp_kses_hook($string, $allowed_html, $allowed_protocols); // WP changed the order of these funcs and added args to wp_kses_hook
   528 	return wp_kses_split($string, $allowed_html, $allowed_protocols);
   532 	return wp_kses_split($string, $allowed_html, $allowed_protocols);
   529 }
   533 }
   530 
   534 
   531 /**
   535 /**
       
   536  * Filters one attribute only and ensures its value is allowed.
       
   537  *
       
   538  * This function has the advantage of being more secure than esc_attr() and can
       
   539  * escape data in some situations where wp_kses() must strip the whole attribute.
       
   540  *
       
   541  * @since 4.2.3
       
   542  *
       
   543  * @param string $string The 'whole' attribute, including name and value.
       
   544  * @param string $element The element name to which the attribute belongs.
       
   545  * @return string Filtered attribute.
       
   546  */
       
   547 function wp_kses_one_attr( $string, $element ) {
       
   548 	$uris = array('xmlns', 'profile', 'href', 'src', 'cite', 'classid', 'codebase', 'data', 'usemap', 'longdesc', 'action');
       
   549 	$allowed_html = wp_kses_allowed_html( 'post' );
       
   550 	$allowed_protocols = wp_allowed_protocols();
       
   551 	$string = wp_kses_no_null( $string, array( 'slash_zero' => 'keep' ) );
       
   552 	
       
   553 	// Preserve leading and trailing whitespace.
       
   554 	$matches = array();
       
   555 	preg_match('/^\s*/', $string, $matches);
       
   556 	$lead = $matches[0];
       
   557 	preg_match('/\s*$/', $string, $matches);
       
   558 	$trail = $matches[0];
       
   559 	if ( empty( $trail ) ) {
       
   560 		$string = substr( $string, strlen( $lead ) );
       
   561 	} else {
       
   562 		$string = substr( $string, strlen( $lead ), -strlen( $trail ) );
       
   563 	}
       
   564 	
       
   565 	// Parse attribute name and value from input.
       
   566 	$split = preg_split( '/\s*=\s*/', $string, 2 );
       
   567 	$name = $split[0];
       
   568 	if ( count( $split ) == 2 ) {
       
   569 		$value = $split[1];
       
   570 
       
   571 		// Remove quotes surrounding $value.
       
   572 		// Also guarantee correct quoting in $string for this one attribute.
       
   573 		if ( '' == $value ) {
       
   574 			$quote = '';
       
   575 		} else {
       
   576 			$quote = $value[0];
       
   577 		}
       
   578 		if ( '"' == $quote || "'" == $quote ) {
       
   579 			if ( substr( $value, -1 ) != $quote ) {
       
   580 				return '';
       
   581 			}
       
   582 			$value = substr( $value, 1, -1 );
       
   583 		} else {
       
   584 			$quote = '"';
       
   585 		}
       
   586 
       
   587 		// Sanitize quotes, angle braces, and entities.
       
   588 		$value = esc_attr( $value );
       
   589 
       
   590 		// Sanitize URI values.
       
   591 		if ( in_array( strtolower( $name ), $uris ) ) {
       
   592 			$value = wp_kses_bad_protocol( $value, $allowed_protocols );
       
   593 		}
       
   594 
       
   595 		$string = "$name=$quote$value$quote";
       
   596 		$vless = 'n';
       
   597 	} else {
       
   598 		$value = '';
       
   599 		$vless = 'y';
       
   600 	}
       
   601 	
       
   602 	// Sanitize attribute by name.
       
   603 	wp_kses_attr_check( $name, $value, $string, $vless, $element, $allowed_html );
       
   604 
       
   605 	// Restore whitespace.
       
   606 	return $lead . $string . $trail;
       
   607 }
       
   608 
       
   609 /**
   532  * Return a list of allowed tags and attributes for a given context.
   610  * Return a list of allowed tags and attributes for a given context.
   533  *
   611  *
   534  * @since 3.5.0
   612  * @since 3.5.0
   535  *
   613  *
   536  * @param string $context The context for which to retrieve tags. Allowed values are
   614  * @global array $allowedposttags
   537  *  post | strip | data | entities or the name of a field filter such as pre_user_description.
   615  * @global array $allowedtags
       
   616  * @global array $allowedentitynames
       
   617  *
       
   618  * @param string|array $context The context for which to retrieve tags.
       
   619  *                              Allowed values are post, strip, data, entities, or
       
   620  *                              the name of a field filter such as pre_user_description.
   538  * @return array List of allowed tags and their allowed attributes.
   621  * @return array List of allowed tags and their allowed attributes.
   539  */
   622  */
   540 function wp_kses_allowed_html( $context = '' ) {
   623 function wp_kses_allowed_html( $context = '' ) {
   541 	global $allowedposttags, $allowedtags, $allowedentitynames;
   624 	global $allowedposttags, $allowedtags, $allowedentitynames;
   542 
   625 
   543 	if ( is_array( $context ) ) {
   626 	if ( is_array( $context ) ) {
   544 		/**
   627 		/**
   545 		 * Filter HTML elements allowed for a given context.
   628 		 * Filters HTML elements allowed for a given context.
   546 		 *
   629 		 *
   547 		 * @since 3.5.0
   630 		 * @since 3.5.0
   548 		 *
   631 		 *
   549 		 * @param string $tags    Allowed tags, attributes, and/or entities.
   632 		 * @param array  $context      Context to judge allowed tags by.
   550 		 * @param string $context Context to judge allowed tags by. Allowed values are 'post',
   633 		 * @param string $context_type Context type (explicit).
   551 		 *                        'data', 'strip', 'entities', 'explicit', or the name of a filter.
       
   552 		 */
   634 		 */
   553 		return apply_filters( 'wp_kses_allowed_html', $context, 'explicit' );
   635 		return apply_filters( 'wp_kses_allowed_html', $context, 'explicit' );
   554 	}
   636 	}
   555 
   637 
   556 	switch ( $context ) {
   638 	switch ( $context ) {
   581 }
   663 }
   582 
   664 
   583 /**
   665 /**
   584  * You add any kses hooks here.
   666  * You add any kses hooks here.
   585  *
   667  *
   586  * There is currently only one kses WordPress hook and it is called here. All
   668  * There is currently only one kses WordPress hook, {@see 'pre_kses'}, and it is called here.
   587  * parameters are passed to the hooks and expected to receive a string.
   669  * All parameters are passed to the hooks and expected to receive a string.
   588  *
   670  *
   589  * @since 1.0.0
   671  * @since 1.0.0
   590  *
   672  *
   591  * @param string $string Content to filter through kses
   673  * @param string $string            Content to filter through kses
   592  * @param array $allowed_html List of allowed HTML elements
   674  * @param array  $allowed_html      List of allowed HTML elements
   593  * @param array $allowed_protocols Allowed protocol in links
   675  * @param array  $allowed_protocols Allowed protocol in links
   594  * @return string Filtered content through 'pre_kses' hook
   676  * @return string Filtered content through {@see 'pre_kses'} hook.
   595  */
   677  */
   596 function wp_kses_hook( $string, $allowed_html, $allowed_protocols ) {
   678 function wp_kses_hook( $string, $allowed_html, $allowed_protocols ) {
   597 	/**
   679 	/**
   598 	 * Filter content to be run through kses.
   680 	 * Filters content to be run through kses.
   599 	 *
   681 	 *
   600 	 * @since 2.3.0
   682 	 * @since 2.3.0
   601 	 *
   683 	 *
   602 	 * @param string $string            Content to run through kses.
   684 	 * @param string $string            Content to run through kses.
   603 	 * @param array  $allowed_html      Allowed HTML elements.
   685 	 * @param array  $allowed_html      Allowed HTML elements.
   604 	 * @param array  $allowed_protocols Allowed protocol in links.
   686 	 * @param array  $allowed_protocols Allowed protocol in links.
   605 	 */
   687 	 */
   606 	$string = apply_filters( 'pre_kses', $string, $allowed_html, $allowed_protocols );
   688 	return apply_filters( 'pre_kses', $string, $allowed_html, $allowed_protocols );
   607 	return $string;
       
   608 }
   689 }
   609 
   690 
   610 /**
   691 /**
   611  * This function returns kses' version number.
   692  * This function returns kses' version number.
   612  *
   693  *
   623  *
   704  *
   624  * It also matches stray ">" characters.
   705  * It also matches stray ">" characters.
   625  *
   706  *
   626  * @since 1.0.0
   707  * @since 1.0.0
   627  *
   708  *
   628  * @param string $string Content to filter
   709  * @global array $pass_allowed_html
   629  * @param array $allowed_html Allowed HTML elements
   710  * @global array $pass_allowed_protocols
   630  * @param array $allowed_protocols Allowed protocols to keep
   711  *
       
   712  * @param string $string            Content to filter
       
   713  * @param array  $allowed_html      Allowed HTML elements
       
   714  * @param array  $allowed_protocols Allowed protocols to keep
   631  * @return string Content with fixed HTML tags
   715  * @return string Content with fixed HTML tags
   632  */
   716  */
   633 function wp_kses_split( $string, $allowed_html, $allowed_protocols ) {
   717 function wp_kses_split( $string, $allowed_html, $allowed_protocols ) {
   634 	global $pass_allowed_html, $pass_allowed_protocols;
   718 	global $pass_allowed_html, $pass_allowed_protocols;
   635 	$pass_allowed_html = $allowed_html;
   719 	$pass_allowed_html = $allowed_html;
   640 /**
   724 /**
   641  * Callback for wp_kses_split.
   725  * Callback for wp_kses_split.
   642  *
   726  *
   643  * @since 3.1.0
   727  * @since 3.1.0
   644  * @access private
   728  * @access private
       
   729  *
       
   730  * @global array $pass_allowed_html
       
   731  * @global array $pass_allowed_protocols
       
   732  *
       
   733  * @return string
   645  */
   734  */
   646 function _wp_kses_split_callback( $match ) {
   735 function _wp_kses_split_callback( $match ) {
   647 	global $pass_allowed_html, $pass_allowed_protocols;
   736 	global $pass_allowed_html, $pass_allowed_protocols;
   648 	return wp_kses_split2( $match[0], $pass_allowed_html, $pass_allowed_protocols );
   737 	return wp_kses_split2( $match[0], $pass_allowed_html, $pass_allowed_protocols );
   649 }
   738 }
   661  * completed, will be returned.
   750  * completed, will be returned.
   662  *
   751  *
   663  * @access private
   752  * @access private
   664  * @since 1.0.0
   753  * @since 1.0.0
   665  *
   754  *
   666  * @param string $string Content to filter
   755  * @param string $string            Content to filter
   667  * @param array $allowed_html Allowed HTML elements
   756  * @param array  $allowed_html      Allowed HTML elements
   668  * @param array $allowed_protocols Allowed protocols to keep
   757  * @param array  $allowed_protocols Allowed protocols to keep
   669  * @return string Fixed HTML element
   758  * @return string Fixed HTML element
   670  */
   759  */
   671 function wp_kses_split2($string, $allowed_html, $allowed_protocols) {
   760 function wp_kses_split2($string, $allowed_html, $allowed_protocols) {
   672 	$string = wp_kses_stripslashes($string);
   761 	$string = wp_kses_stripslashes($string);
   673 
   762 
   687 		$string = preg_replace('/-$/', '', $string);
   776 		$string = preg_replace('/-$/', '', $string);
   688 		return "<!--{$string}-->";
   777 		return "<!--{$string}-->";
   689 	}
   778 	}
   690 	// Allow HTML comments
   779 	// Allow HTML comments
   691 
   780 
   692 	if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?$%', $string, $matches))
   781 	if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9-]+)([^>]*)>?$%', $string, $matches))
   693 		return '';
   782 		return '';
   694 	// It's seriously malformed
   783 	// It's seriously malformed
   695 
   784 
   696 	$slash = trim($matches[1]);
   785 	$slash = trim($matches[1]);
   697 	$elem = $matches[2];
   786 	$elem = $matches[2];
   720  * is to check if the tag has a closing XHTML slash, and if it does, it puts one
   809  * is to check if the tag has a closing XHTML slash, and if it does, it puts one
   721  * in the returned code as well.
   810  * in the returned code as well.
   722  *
   811  *
   723  * @since 1.0.0
   812  * @since 1.0.0
   724  *
   813  *
   725  * @param string $element HTML element/tag
   814  * @param string $element           HTML element/tag
   726  * @param string $attr HTML attributes from HTML element to closing HTML element tag
   815  * @param string $attr              HTML attributes from HTML element to closing HTML element tag
   727  * @param array $allowed_html Allowed HTML elements
   816  * @param array  $allowed_html      Allowed HTML elements
   728  * @param array $allowed_protocols Allowed protocols to keep
   817  * @param array  $allowed_protocols Allowed protocols to keep
   729  * @return string Sanitized HTML element
   818  * @return string Sanitized HTML element
   730  */
   819  */
   731 function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) {
   820 function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) {
   732 	// Is there a closing XHTML slash at the end of the attributes?
       
   733 
       
   734 	if ( ! is_array( $allowed_html ) )
   821 	if ( ! is_array( $allowed_html ) )
   735 		$allowed_html = wp_kses_allowed_html( $allowed_html );
   822 		$allowed_html = wp_kses_allowed_html( $allowed_html );
   736 
   823 
       
   824 	// Is there a closing XHTML slash at the end of the attributes?
   737 	$xhtml_slash = '';
   825 	$xhtml_slash = '';
   738 	if (preg_match('%\s*/\s*$%', $attr))
   826 	if (preg_match('%\s*/\s*$%', $attr))
   739 		$xhtml_slash = ' /';
   827 		$xhtml_slash = ' /';
   740 
   828 
   741 	// Are any attributes allowed at all for this element?
   829 	// Are any attributes allowed at all for this element?
   742 	if ( ! isset($allowed_html[strtolower($element)]) || count($allowed_html[strtolower($element)]) == 0 )
   830 	$element_low = strtolower( $element );
       
   831 	if ( empty( $allowed_html[ $element_low ] ) || true === $allowed_html[ $element_low ] ) {
   743 		return "<$element$xhtml_slash>";
   832 		return "<$element$xhtml_slash>";
       
   833 	}
   744 
   834 
   745 	// Split it
   835 	// Split it
   746 	$attrarr = wp_kses_hair($attr, $allowed_protocols);
   836 	$attrarr = wp_kses_hair($attr, $allowed_protocols);
   747 
   837 
   748 	// Go through $attrarr, and save the allowed attributes for this element
   838 	// Go through $attrarr, and save the allowed attributes for this element
   749 	// in $attr2
   839 	// in $attr2
   750 	$attr2 = '';
   840 	$attr2 = '';
   751 
   841 	foreach ( $attrarr as $arreach ) {
   752 	$allowed_attr = $allowed_html[strtolower($element)];
   842 		if ( wp_kses_attr_check( $arreach['name'], $arreach['value'], $arreach['whole'], $arreach['vless'], $element, $allowed_html ) ) {
   753 	foreach ($attrarr as $arreach) {
   843 			$attr2 .= ' '.$arreach['whole'];
   754 		if ( ! isset( $allowed_attr[strtolower($arreach['name'])] ) )
       
   755 			continue; // the attribute is not allowed
       
   756 
       
   757 		$current = $allowed_attr[strtolower($arreach['name'])];
       
   758 		if ( $current == '' )
       
   759 			continue; // the attribute is not allowed
       
   760 
       
   761 		if ( strtolower( $arreach['name'] ) == 'style' ) {
       
   762 			$orig_value = $arreach['value'];
       
   763 			$value = safecss_filter_attr( $orig_value );
       
   764 
       
   765 			if ( empty( $value ) )
       
   766 				continue;
       
   767 
       
   768 			$arreach['value'] = $value;
       
   769 			$arreach['whole'] = str_replace( $orig_value, $value, $arreach['whole'] );
       
   770 		}
   844 		}
   771 
   845 	}
   772 		if ( ! is_array($current) ) {
       
   773 			$attr2 .= ' '.$arreach['whole'];
       
   774 		// there are no checks
       
   775 
       
   776 		} else {
       
   777 			// there are some checks
       
   778 			$ok = true;
       
   779 			foreach ($current as $currkey => $currval) {
       
   780 				if ( ! wp_kses_check_attr_val($arreach['value'], $arreach['vless'], $currkey, $currval) ) {
       
   781 					$ok = false;
       
   782 					break;
       
   783 				}
       
   784 			}
       
   785 
       
   786 			if ( $ok )
       
   787 				$attr2 .= ' '.$arreach['whole']; // it passed them
       
   788 		} // if !is_array($current)
       
   789 	} // foreach
       
   790 
   846 
   791 	// Remove any "<" or ">" characters
   847 	// Remove any "<" or ">" characters
   792 	$attr2 = preg_replace('/[<>]/', '', $attr2);
   848 	$attr2 = preg_replace('/[<>]/', '', $attr2);
   793 
   849 
   794 	return "<$element$attr2$xhtml_slash>";
   850 	return "<$element$attr2$xhtml_slash>";
       
   851 }
       
   852 
       
   853 /**
       
   854  * Determine whether an attribute is allowed.
       
   855  *
       
   856  * @since 4.2.3
       
   857  *
       
   858  * @param string $name The attribute name. Returns empty string when not allowed.
       
   859  * @param string $value The attribute value. Returns a filtered value.
       
   860  * @param string $whole The name=value input. Returns filtered input.
       
   861  * @param string $vless 'y' when attribute like "enabled", otherwise 'n'.
       
   862  * @param string $element The name of the element to which this attribute belongs.
       
   863  * @param array $allowed_html The full list of allowed elements and attributes.
       
   864  * @return bool Is the attribute allowed?
       
   865  */
       
   866 function wp_kses_attr_check( &$name, &$value, &$whole, $vless, $element, $allowed_html ) {
       
   867 	$allowed_attr = $allowed_html[strtolower( $element )];
       
   868 
       
   869 	$name_low = strtolower( $name );
       
   870 	if ( ! isset( $allowed_attr[$name_low] ) || '' == $allowed_attr[$name_low] ) {
       
   871 		$name = $value = $whole = '';
       
   872 		return false;
       
   873 	}
       
   874 
       
   875 	if ( 'style' == $name_low ) {
       
   876 		$new_value = safecss_filter_attr( $value );
       
   877 
       
   878 		if ( empty( $new_value ) ) {
       
   879 			$name = $value = $whole = '';
       
   880 			return false;
       
   881 		}
       
   882 
       
   883 		$whole = str_replace( $value, $new_value, $whole );
       
   884 		$value = $new_value;
       
   885 	}
       
   886 
       
   887 	if ( is_array( $allowed_attr[$name_low] ) ) {
       
   888 		// there are some checks
       
   889 		foreach ( $allowed_attr[$name_low] as $currkey => $currval ) {
       
   890 			if ( ! wp_kses_check_attr_val( $value, $vless, $currkey, $currval ) ) {
       
   891 				$name = $value = $whole = '';
       
   892 				return false;
       
   893 			}
       
   894 		}
       
   895 	}
       
   896 
       
   897 	return true;
   795 }
   898 }
   796 
   899 
   797 /**
   900 /**
   798  * Builds an attribute list from string containing attributes.
   901  * Builds an attribute list from string containing attributes.
   799  *
   902  *
   805  * from attribute values. It also reduces duplicate attributes by using the
   908  * from attribute values. It also reduces duplicate attributes by using the
   806  * attribute defined first (foo='bar' foo='baz' will result in foo='bar').
   909  * attribute defined first (foo='bar' foo='baz' will result in foo='bar').
   807  *
   910  *
   808  * @since 1.0.0
   911  * @since 1.0.0
   809  *
   912  *
   810  * @param string $attr Attribute list from HTML element to closing HTML element tag
   913  * @param string $attr              Attribute list from HTML element to closing HTML element tag
   811  * @param array $allowed_protocols Allowed protocols to keep
   914  * @param array  $allowed_protocols Allowed protocols to keep
   812  * @return array List of attributes after parsing
   915  * @return array List of attributes after parsing
   813  */
   916  */
   814 function wp_kses_hair($attr, $allowed_protocols) {
   917 function wp_kses_hair($attr, $allowed_protocols) {
   815 	$attrarr = array();
   918 	$attrarr = array();
   816 	$mode = 0;
   919 	$mode = 0;
   922 
  1025 
   923 	return $attrarr;
  1026 	return $attrarr;
   924 }
  1027 }
   925 
  1028 
   926 /**
  1029 /**
       
  1030  * Finds all attributes of an HTML element.
       
  1031  *
       
  1032  * Does not modify input.  May return "evil" output.
       
  1033  *
       
  1034  * Based on wp_kses_split2() and wp_kses_attr()
       
  1035  *
       
  1036  * @since 4.2.3
       
  1037  *
       
  1038  * @param string $element HTML element/tag
       
  1039  * @return array|bool List of attributes found in $element. Returns false on failure.
       
  1040  */
       
  1041 function wp_kses_attr_parse( $element ) {
       
  1042 	$valid = preg_match('%^(<\s*)(/\s*)?([a-zA-Z0-9]+\s*)([^>]*)(>?)$%', $element, $matches);
       
  1043 	if ( 1 !== $valid ) {
       
  1044 		return false;
       
  1045 	}
       
  1046 
       
  1047 	$begin =  $matches[1];
       
  1048 	$slash =  $matches[2];
       
  1049 	$elname = $matches[3];
       
  1050 	$attr =   $matches[4];
       
  1051 	$end =    $matches[5];
       
  1052 
       
  1053 	if ( '' !== $slash ) {
       
  1054 		// Closing elements do not get parsed.
       
  1055 		return false;
       
  1056 	}
       
  1057 
       
  1058 	// Is there a closing XHTML slash at the end of the attributes?
       
  1059 	if ( 1 === preg_match( '%\s*/\s*$%', $attr, $matches ) ) {
       
  1060 		$xhtml_slash = $matches[0];
       
  1061 		$attr = substr( $attr, 0, -strlen( $xhtml_slash ) );
       
  1062 	} else {
       
  1063 		$xhtml_slash = '';
       
  1064 	}
       
  1065 	
       
  1066 	// Split it
       
  1067 	$attrarr = wp_kses_hair_parse( $attr );
       
  1068 	if ( false === $attrarr ) {
       
  1069 		return false;
       
  1070 	}
       
  1071 
       
  1072 	// Make sure all input is returned by adding front and back matter.
       
  1073 	array_unshift( $attrarr, $begin . $slash . $elname );
       
  1074 	array_push( $attrarr, $xhtml_slash . $end );
       
  1075 	
       
  1076 	return $attrarr;
       
  1077 }
       
  1078 
       
  1079 /**
       
  1080  * Builds an attribute list from string containing attributes.
       
  1081  *
       
  1082  * Does not modify input.  May return "evil" output.
       
  1083  * In case of unexpected input, returns false instead of stripping things.
       
  1084  *
       
  1085  * Based on wp_kses_hair() but does not return a multi-dimensional array.
       
  1086  *
       
  1087  * @since 4.2.3
       
  1088  *
       
  1089  * @param string $attr Attribute list from HTML element to closing HTML element tag
       
  1090  * @return array|bool List of attributes found in $attr. Returns false on failure.
       
  1091  */
       
  1092 function wp_kses_hair_parse( $attr ) {
       
  1093 	if ( '' === $attr ) {
       
  1094 		return array();
       
  1095 	}
       
  1096 
       
  1097 	$regex =
       
  1098 	  '(?:'
       
  1099 	.     '[-a-zA-Z:]+'   // Attribute name.
       
  1100 	. '|'
       
  1101 	.     '\[\[?[^\[\]]+\]\]?' // Shortcode in the name position implies unfiltered_html.
       
  1102 	. ')'
       
  1103 	. '(?:'               // Attribute value.
       
  1104 	.     '\s*=\s*'       // All values begin with '='
       
  1105 	.     '(?:'
       
  1106 	.         '"[^"]*"'   // Double-quoted
       
  1107 	.     '|'
       
  1108 	.         "'[^']*'"   // Single-quoted
       
  1109 	.     '|'
       
  1110 	.         '[^\s"\']+' // Non-quoted
       
  1111 	.         '(?:\s|$)'  // Must have a space
       
  1112 	.     ')'
       
  1113 	. '|'
       
  1114 	.     '(?:\s|$)'      // If attribute has no value, space is required.
       
  1115 	. ')'
       
  1116 	. '\s*';              // Trailing space is optional except as mentioned above.
       
  1117 
       
  1118 	// Although it is possible to reduce this procedure to a single regexp,
       
  1119 	// we must run that regexp twice to get exactly the expected result.
       
  1120 
       
  1121 	$validation = "%^($regex)+$%";
       
  1122 	$extraction = "%$regex%";
       
  1123 
       
  1124 	if ( 1 === preg_match( $validation, $attr ) ) {
       
  1125 		preg_match_all( $extraction, $attr, $attrarr );
       
  1126 		return $attrarr[0];
       
  1127 	} else {
       
  1128 		return false;
       
  1129 	}
       
  1130 }
       
  1131 
       
  1132 /**
   927  * Performs different checks for attribute values.
  1133  * Performs different checks for attribute values.
   928  *
  1134  *
   929  * The currently implemented checks are "maxlen", "minlen", "maxval", "minval"
  1135  * The currently implemented checks are "maxlen", "minlen", "maxval", "minval"
   930  * and "valueless".
  1136  * and "valueless".
   931  *
  1137  *
   932  * @since 1.0.0
  1138  * @since 1.0.0
   933  *
  1139  *
   934  * @param string $value Attribute value
  1140  * @param string $value      Attribute value
   935  * @param string $vless Whether the value is valueless. Use 'y' or 'n'
  1141  * @param string $vless      Whether the value is valueless. Use 'y' or 'n'
   936  * @param string $checkname What $checkvalue is checking for.
  1142  * @param string $checkname  What $checkvalue is checking for.
   937  * @param mixed $checkvalue What constraint the value should pass
  1143  * @param mixed  $checkvalue What constraint the value should pass
   938  * @return bool Whether check passes
  1144  * @return bool Whether check passes
   939  */
  1145  */
   940 function wp_kses_check_attr_val($value, $vless, $checkname, $checkvalue) {
  1146 function wp_kses_check_attr_val($value, $vless, $checkname, $checkvalue) {
   941 	$ok = true;
  1147 	$ok = true;
   942 
  1148 
  1003  * understand HTML entities. It does its work in a while loop, so it won't be
  1209  * understand HTML entities. It does its work in a while loop, so it won't be
  1004  * fooled by a string like "javascript:javascript:alert(57)".
  1210  * fooled by a string like "javascript:javascript:alert(57)".
  1005  *
  1211  *
  1006  * @since 1.0.0
  1212  * @since 1.0.0
  1007  *
  1213  *
  1008  * @param string $string Content to filter bad protocols from
  1214  * @param string $string            Content to filter bad protocols from
  1009  * @param array $allowed_protocols Allowed protocols to keep
  1215  * @param array  $allowed_protocols Allowed protocols to keep
  1010  * @return string Filtered content
  1216  * @return string Filtered content
  1011  */
  1217  */
  1012 function wp_kses_bad_protocol($string, $allowed_protocols) {
  1218 function wp_kses_bad_protocol($string, $allowed_protocols) {
  1013 	$string = wp_kses_no_null($string);
  1219 	$string = wp_kses_no_null($string);
  1014 	$iterations = 0;
  1220 	$iterations = 0;
  1030  * Also removes any instance of the '\0' string.
  1236  * Also removes any instance of the '\0' string.
  1031  *
  1237  *
  1032  * @since 1.0.0
  1238  * @since 1.0.0
  1033  *
  1239  *
  1034  * @param string $string
  1240  * @param string $string
       
  1241  * @param array $options Set 'slash_zero' => 'keep' when '\0' is allowed. Default is 'remove'.
  1035  * @return string
  1242  * @return string
  1036  */
  1243  */
  1037 function wp_kses_no_null($string) {
  1244 function wp_kses_no_null( $string, $options = null ) {
  1038 	$string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', '', $string);
  1245 	if ( ! isset( $options['slash_zero'] ) ) {
  1039 	$string = preg_replace('/(\\\\0)+/', '', $string);
  1246 		$options = array( 'slash_zero' => 'remove' );
       
  1247 	}
       
  1248 
       
  1249 	$string = preg_replace( '/[\x00-\x08\x0B\x0C\x0E-\x1F]/', '', $string );
       
  1250 	if ( 'remove' == $options['slash_zero'] ) {
       
  1251 		$string = preg_replace( '/\\\\+0+/', '', $string );
       
  1252 	}
  1040 
  1253 
  1041 	return $string;
  1254 	return $string;
  1042 }
  1255 }
  1043 
  1256 
  1044 /**
  1257 /**
  1080 
  1293 
  1081 	return $outarray;
  1294 	return $outarray;
  1082 }
  1295 }
  1083 
  1296 
  1084 /**
  1297 /**
  1085  * Removes the HTML JavaScript entities found in early versions of Netscape 4.
  1298  * Handles parsing errors in wp_kses_hair().
       
  1299  *
       
  1300  * The general plan is to remove everything to and including some whitespace,
       
  1301  * but it deals with quotes and apostrophes as well.
  1086  *
  1302  *
  1087  * @since 1.0.0
  1303  * @since 1.0.0
  1088  *
  1304  *
  1089  * @param string $string
  1305  * @param string $string
  1090  * @return string
  1306  * @return string
  1091  */
  1307  */
  1092 function wp_kses_js_entities($string) {
       
  1093 	return preg_replace('%&\s*\{[^}]*(\}\s*;?|$)%', '', $string);
       
  1094 }
       
  1095 
       
  1096 /**
       
  1097  * Handles parsing errors in wp_kses_hair().
       
  1098  *
       
  1099  * The general plan is to remove everything to and including some whitespace,
       
  1100  * but it deals with quotes and apostrophes as well.
       
  1101  *
       
  1102  * @since 1.0.0
       
  1103  *
       
  1104  * @param string $string
       
  1105  * @return string
       
  1106  */
       
  1107 function wp_kses_html_error($string) {
  1308 function wp_kses_html_error($string) {
  1108 	return preg_replace('/^("[^"]*("|$)|\'[^\']*(\'|$)|\S)*\s*/', '', $string);
  1309 	return preg_replace('/^("[^"]*("|$)|\'[^\']*(\'|$)|\S)*\s*/', '', $string);
  1109 }
  1310 }
  1110 
  1311 
  1111 /**
  1312 /**
  1114  * This function searches for URL protocols at the beginning of $string, while
  1315  * This function searches for URL protocols at the beginning of $string, while
  1115  * handling whitespace and HTML entities.
  1316  * handling whitespace and HTML entities.
  1116  *
  1317  *
  1117  * @since 1.0.0
  1318  * @since 1.0.0
  1118  *
  1319  *
  1119  * @param string $string Content to check for bad protocols
  1320  * @param string $string            Content to check for bad protocols
  1120  * @param string $allowed_protocols Allowed protocols
  1321  * @param string $allowed_protocols Allowed protocols
  1121  * @return string Sanitized content
  1322  * @return string Sanitized content
  1122  */
  1323  */
  1123 function wp_kses_bad_protocol_once($string, $allowed_protocols, $count = 1 ) {
  1324 function wp_kses_bad_protocol_once($string, $allowed_protocols, $count = 1 ) {
  1124 	$string2 = preg_split( '/:|&#0*58;|&#x0*3a;/i', $string, 2 );
  1325 	$string2 = preg_split( '/:|&#0*58;|&#x0*3a;/i', $string, 2 );
  1145  * whitelist or not, and returns different data depending on the answer.
  1346  * whitelist or not, and returns different data depending on the answer.
  1146  *
  1347  *
  1147  * @access private
  1348  * @access private
  1148  * @since 1.0.0
  1349  * @since 1.0.0
  1149  *
  1350  *
  1150  * @param string $string URI scheme to check against the whitelist
  1351  * @param string $string            URI scheme to check against the whitelist
  1151  * @param string $allowed_protocols Allowed protocols
  1352  * @param string $allowed_protocols Allowed protocols
  1152  * @return string Sanitized content
  1353  * @return string Sanitized content
  1153  */
  1354  */
  1154 function wp_kses_bad_protocol_once2( $string, $allowed_protocols ) {
  1355 function wp_kses_bad_protocol_once2( $string, $allowed_protocols ) {
  1155 	$string2 = wp_kses_decode_entities($string);
  1356 	$string2 = wp_kses_decode_entities($string);
  1181  * @param string $string Content to normalize entities
  1382  * @param string $string Content to normalize entities
  1182  * @return string Content with normalized entities
  1383  * @return string Content with normalized entities
  1183  */
  1384  */
  1184 function wp_kses_normalize_entities($string) {
  1385 function wp_kses_normalize_entities($string) {
  1185 	// Disarm all entities by converting & to &amp;
  1386 	// Disarm all entities by converting & to &amp;
  1186 
       
  1187 	$string = str_replace('&', '&amp;', $string);
  1387 	$string = str_replace('&', '&amp;', $string);
  1188 
  1388 
  1189 	// Change back the allowed entities in our entity whitelist
  1389 	// Change back the allowed entities in our entity whitelist
  1190 
       
  1191 	$string = preg_replace_callback('/&amp;([A-Za-z]{2,8}[0-9]{0,2});/', 'wp_kses_named_entities', $string);
  1390 	$string = preg_replace_callback('/&amp;([A-Za-z]{2,8}[0-9]{0,2});/', 'wp_kses_named_entities', $string);
  1192 	$string = preg_replace_callback('/&amp;#(0*[0-9]{1,7});/', 'wp_kses_normalize_entities2', $string);
  1391 	$string = preg_replace_callback('/&amp;#(0*[0-9]{1,7});/', 'wp_kses_normalize_entities2', $string);
  1193 	$string = preg_replace_callback('/&amp;#[Xx](0*[0-9A-Fa-f]{1,6});/', 'wp_kses_normalize_entities3', $string);
  1392 	$string = preg_replace_callback('/&amp;#[Xx](0*[0-9A-Fa-f]{1,6});/', 'wp_kses_normalize_entities3', $string);
  1194 
  1393 
  1195 	return $string;
  1394 	return $string;
  1201  * This function only accepts valid named entity references, which are finite,
  1400  * This function only accepts valid named entity references, which are finite,
  1202  * case-sensitive, and highly scrutinized by HTML and XML validators.
  1401  * case-sensitive, and highly scrutinized by HTML and XML validators.
  1203  *
  1402  *
  1204  * @since 3.0.0
  1403  * @since 3.0.0
  1205  *
  1404  *
       
  1405  * @global array $allowedentitynames
       
  1406  *
  1206  * @param array $matches preg_replace_callback() matches array
  1407  * @param array $matches preg_replace_callback() matches array
  1207  * @return string Correctly encoded entity
  1408  * @return string Correctly encoded entity
  1208  */
  1409  */
  1209 function wp_kses_named_entities($matches) {
  1410 function wp_kses_named_entities($matches) {
  1210 	global $allowedentitynames;
  1411 	global $allowedentitynames;
  1211 
  1412 
  1212 	if ( empty($matches[1]) )
  1413 	if ( empty($matches[1]) )
  1213 		return '';
  1414 		return '';
  1214 
  1415 
  1215 	$i = $matches[1];
  1416 	$i = $matches[1];
  1216 	return ( ( ! in_array($i, $allowedentitynames) ) ? "&amp;$i;" : "&$i;" );
  1417 	return ( ! in_array( $i, $allowedentitynames ) ) ? "&amp;$i;" : "&$i;";
  1217 }
  1418 }
  1218 
  1419 
  1219 /**
  1420 /**
  1220  * Callback for wp_kses_normalize_entities() regular expression.
  1421  * Callback for wp_kses_normalize_entities() regular expression.
  1221  *
  1422  *
  1222  * This function helps {@see wp_kses_normalize_entities()} to only accept 16-bit
  1423  * This function helps wp_kses_normalize_entities() to only accept 16-bit
  1223  * values and nothing more for `&#number;` entities.
  1424  * values and nothing more for `&#number;` entities.
  1224  *
  1425  *
  1225  * @access private
  1426  * @access private
  1226  * @since 1.0.0
  1427  * @since 1.0.0
  1227  *
  1428  *
  1247  * Callback for wp_kses_normalize_entities() for regular expression.
  1448  * Callback for wp_kses_normalize_entities() for regular expression.
  1248  *
  1449  *
  1249  * This function helps wp_kses_normalize_entities() to only accept valid Unicode
  1450  * This function helps wp_kses_normalize_entities() to only accept valid Unicode
  1250  * numeric entities in hex form.
  1451  * numeric entities in hex form.
  1251  *
  1452  *
       
  1453  * @since 2.7.0
  1252  * @access private
  1454  * @access private
  1253  *
  1455  *
  1254  * @param array $matches preg_replace_callback() matches array
  1456  * @param array $matches preg_replace_callback() matches array
  1255  * @return string Correctly encoded entity
  1457  * @return string Correctly encoded entity
  1256  */
  1458  */
  1257 function wp_kses_normalize_entities3($matches) {
  1459 function wp_kses_normalize_entities3($matches) {
  1258 	if ( empty($matches[1]) )
  1460 	if ( empty($matches[1]) )
  1259 		return '';
  1461 		return '';
  1260 
  1462 
  1261 	$hexchars = $matches[1];
  1463 	$hexchars = $matches[1];
  1262 	return ( ( ! valid_unicode(hexdec($hexchars)) ) ? "&amp;#x$hexchars;" : '&#x'.ltrim($hexchars,'0').';' );
  1464 	return ( ! valid_unicode( hexdec( $hexchars ) ) ) ? "&amp;#x$hexchars;" : '&#x'.ltrim($hexchars,'0').';';
  1263 }
  1465 }
  1264 
  1466 
  1265 /**
  1467 /**
  1266  * Helper function to determine if a Unicode value is valid.
  1468  * Helper function to determine if a Unicode value is valid.
       
  1469  *
       
  1470  * @since 2.7.0
  1267  *
  1471  *
  1268  * @param int $i Unicode value
  1472  * @param int $i Unicode value
  1269  * @return bool True if the value was a valid Unicode number
  1473  * @return bool True if the value was a valid Unicode number
  1270  */
  1474  */
  1271 function valid_unicode($i) {
  1475 function valid_unicode($i) {
  1295 }
  1499 }
  1296 
  1500 
  1297 /**
  1501 /**
  1298  * Regex callback for wp_kses_decode_entities()
  1502  * Regex callback for wp_kses_decode_entities()
  1299  *
  1503  *
       
  1504  * @since 2.9.0
       
  1505  *
  1300  * @param array $match preg match
  1506  * @param array $match preg match
  1301  * @return string
  1507  * @return string
  1302  */
  1508  */
  1303 function _wp_kses_decode_entities_chr( $match ) {
  1509 function _wp_kses_decode_entities_chr( $match ) {
  1304 	return chr( $match[1] );
  1510 	return chr( $match[1] );
  1305 }
  1511 }
  1306 
  1512 
  1307 /**
  1513 /**
  1308  * Regex callback for wp_kses_decode_entities()
  1514  * Regex callback for wp_kses_decode_entities()
  1309  *
  1515  *
       
  1516  * @since 2.9.0
       
  1517  *
  1310  * @param array $match preg match
  1518  * @param array $match preg match
  1311  * @return string
  1519  * @return string
  1312  */
  1520  */
  1313 function _wp_kses_decode_entities_chr_hexdec( $match ) {
  1521 function _wp_kses_decode_entities_chr_hexdec( $match ) {
  1314 	return chr( hexdec( $match[1] ) );
  1522 	return chr( hexdec( $match[1] ) );
  1333  *
  1541  *
  1334  * @param string $data Content to filter, expected to not be escaped
  1542  * @param string $data Content to filter, expected to not be escaped
  1335  * @return string Filtered content
  1543  * @return string Filtered content
  1336  */
  1544  */
  1337 function wp_kses_data( $data ) {
  1545 function wp_kses_data( $data ) {
  1338 	return wp_kses( $data , current_filter() );
  1546 	return wp_kses( $data, current_filter() );
  1339 }
  1547 }
  1340 
  1548 
  1341 /**
  1549 /**
  1342  * Sanitize content for allowed HTML tags for post content.
  1550  * Sanitize content for allowed HTML tags for post content.
  1343  *
  1551  *
  1347  * @since 2.0.0
  1555  * @since 2.0.0
  1348  *
  1556  *
  1349  * @param string $data Post content to filter, expected to be escaped with slashes
  1557  * @param string $data Post content to filter, expected to be escaped with slashes
  1350  * @return string Filtered post content with allowed HTML tags and attributes intact.
  1558  * @return string Filtered post content with allowed HTML tags and attributes intact.
  1351  */
  1559  */
  1352 function wp_filter_post_kses($data) {
  1560 function wp_filter_post_kses( $data ) {
  1353 	return addslashes ( wp_kses( stripslashes( $data ), 'post' ) );
  1561 	return addslashes( wp_kses( stripslashes( $data ), 'post' ) );
  1354 }
  1562 }
  1355 
  1563 
  1356 /**
  1564 /**
  1357  * Sanitize content for allowed HTML tags for post content.
  1565  * Sanitize content for allowed HTML tags for post content.
  1358  *
  1566  *
  1362  * @since 2.9.0
  1570  * @since 2.9.0
  1363  *
  1571  *
  1364  * @param string $data Post content to filter
  1572  * @param string $data Post content to filter
  1365  * @return string Filtered post content with allowed HTML tags and attributes intact.
  1573  * @return string Filtered post content with allowed HTML tags and attributes intact.
  1366  */
  1574  */
  1367 function wp_kses_post($data) {
  1575 function wp_kses_post( $data ) {
  1368 	return wp_kses( $data , 'post' );
  1576 	return wp_kses( $data, 'post' );
       
  1577 }
       
  1578 
       
  1579 /**
       
  1580  * Navigates through an array, object, or scalar, and sanitizes content for
       
  1581  * allowed HTML tags for post content.
       
  1582  *
       
  1583  * @since 4.4.2
       
  1584  *
       
  1585  * @see map_deep()
       
  1586  *
       
  1587  * @param mixed $data The array, object, or scalar value to inspect.
       
  1588  * @return mixed The filtered content.
       
  1589  */
       
  1590 function wp_kses_post_deep( $data ) {
       
  1591 	return map_deep( $data, 'wp_kses_post' );
  1369 }
  1592 }
  1370 
  1593 
  1371 /**
  1594 /**
  1372  * Strips all of the HTML in the content.
  1595  * Strips all of the HTML in the content.
  1373  *
  1596  *
  1375  *
  1598  *
  1376  * @param string $data Content to strip all HTML from
  1599  * @param string $data Content to strip all HTML from
  1377  * @return string Filtered content without any HTML
  1600  * @return string Filtered content without any HTML
  1378  */
  1601  */
  1379 function wp_filter_nohtml_kses( $data ) {
  1602 function wp_filter_nohtml_kses( $data ) {
  1380 	return addslashes ( wp_kses( stripslashes( $data ), 'strip' ) );
  1603 	return addslashes( wp_kses( stripslashes( $data ), 'strip' ) );
  1381 }
  1604 }
  1382 
  1605 
  1383 /**
  1606 /**
  1384  * Adds all Kses input form content filters.
  1607  * Adds all Kses input form content filters.
  1385  *
  1608  *
  1411  * Removes all Kses input form content filters.
  1634  * Removes all Kses input form content filters.
  1412  *
  1635  *
  1413  * A quick procedural method to removing all of the filters that kses uses for
  1636  * A quick procedural method to removing all of the filters that kses uses for
  1414  * content in WordPress Loop.
  1637  * content in WordPress Loop.
  1415  *
  1638  *
  1416  * Does not remove the kses_init() function from 'init' hook (priority is
  1639  * Does not remove the kses_init() function from {@see 'init'} hook (priority is
  1417  * default). Also does not remove kses_init() function from 'set_current_user'
  1640  * default). Also does not remove kses_init() function from {@see 'set_current_user'}
  1418  * hook (priority is also default).
  1641  * hook (priority is also default).
  1419  *
  1642  *
  1420  * @since 2.0.6
  1643  * @since 2.0.6
  1421  */
  1644  */
  1422 function kses_remove_filters() {
  1645 function kses_remove_filters() {
  1434 }
  1657 }
  1435 
  1658 
  1436 /**
  1659 /**
  1437  * Sets up most of the Kses filters for input form content.
  1660  * Sets up most of the Kses filters for input form content.
  1438  *
  1661  *
  1439  * If you remove the kses_init() function from 'init' hook and
  1662  * If you remove the kses_init() function from {@see 'init'} hook and
  1440  * 'set_current_user' (priority is default), then none of the Kses filter hooks
  1663  * {@see 'set_current_user'} (priority is default), then none of the Kses filter hooks
  1441  * will be added.
  1664  * will be added.
  1442  *
  1665  *
  1443  * First removes all of the Kses filters in case the current user does not need
  1666  * First removes all of the Kses filters in case the current user does not need
  1444  * to have Kses filter the content. If the user does not have unfiltered_html
  1667  * to have Kses filter the content. If the user does not have unfiltered_html
  1445  * capability, then Kses filters are added.
  1668  * capability, then Kses filters are added.
  1447  * @since 2.0.0
  1670  * @since 2.0.0
  1448  */
  1671  */
  1449 function kses_init() {
  1672 function kses_init() {
  1450 	kses_remove_filters();
  1673 	kses_remove_filters();
  1451 
  1674 
  1452 	if (current_user_can('unfiltered_html') == false)
  1675 	if ( ! current_user_can( 'unfiltered_html' ) ) {
  1453 		kses_init_filters();
  1676 		kses_init_filters();
       
  1677 	}
  1454 }
  1678 }
  1455 
  1679 
  1456 /**
  1680 /**
  1457  * Inline CSS filter
  1681  * Inline CSS filter
  1458  *
  1682  *
  1459  * @since 2.8.1
  1683  * @since 2.8.1
       
  1684  *
       
  1685  * @param string $css        A string of CSS rules.
       
  1686  * @param string $deprecated Not used.
       
  1687  * @return string            Filtered string of CSS rules.
  1460  */
  1688  */
  1461 function safecss_filter_attr( $css, $deprecated = '' ) {
  1689 function safecss_filter_attr( $css, $deprecated = '' ) {
  1462 	if ( !empty( $deprecated ) )
  1690 	if ( !empty( $deprecated ) )
  1463 		_deprecated_argument( __FUNCTION__, '2.8.1' ); // Never implemented
  1691 		_deprecated_argument( __FUNCTION__, '2.8.1' ); // Never implemented
  1464 
  1692 
  1469 		return '';
  1697 		return '';
  1470 
  1698 
  1471 	$css_array = explode( ';', trim( $css ) );
  1699 	$css_array = explode( ';', trim( $css ) );
  1472 
  1700 
  1473 	/**
  1701 	/**
  1474 	 * Filter list of allowed CSS attributes.
  1702 	 * Filters list of allowed CSS attributes.
  1475 	 *
  1703 	 *
  1476 	 * @since 2.8.1
  1704 	 * @since 2.8.1
       
  1705 	 * @since 4.4.0 Added support for `min-height`, `max-height`, `min-width`, and `max-width`.
       
  1706 	 * @since 4.6.0 Added support for `list-style-type`.
  1477 	 *
  1707 	 *
  1478 	 * @param array $attr List of allowed CSS attributes.
  1708 	 * @param array $attr List of allowed CSS attributes.
  1479 	 */
  1709 	 */
  1480 	$allowed_attr = apply_filters( 'safe_style_css', array( 'text-align', 'margin', 'color', 'float',
  1710 	$allowed_attr = apply_filters( 'safe_style_css', array(
  1481 	'border', 'background', 'background-color', 'border-bottom', 'border-bottom-color',
  1711 		'background',
  1482 	'border-bottom-style', 'border-bottom-width', 'border-collapse', 'border-color', 'border-left',
  1712 		'background-color',
  1483 	'border-left-color', 'border-left-style', 'border-left-width', 'border-right', 'border-right-color',
  1713 
  1484 	'border-right-style', 'border-right-width', 'border-spacing', 'border-style', 'border-top',
  1714 		'border',
  1485 	'border-top-color', 'border-top-style', 'border-top-width', 'border-width', 'caption-side',
  1715 		'border-width',
  1486 	'clear', 'cursor', 'direction', 'font', 'font-family', 'font-size', 'font-style',
  1716 		'border-color',
  1487 	'font-variant', 'font-weight', 'height', 'letter-spacing', 'line-height', 'margin-bottom',
  1717 		'border-style',
  1488 	'margin-left', 'margin-right', 'margin-top', 'overflow', 'padding', 'padding-bottom',
  1718 		'border-right',
  1489 	'padding-left', 'padding-right', 'padding-top', 'text-decoration', 'text-indent', 'vertical-align',
  1719 		'border-right-color',
  1490 	'width' ) );
  1720 		'border-right-style',
       
  1721 		'border-right-width',
       
  1722 		'border-bottom',
       
  1723 		'border-bottom-color',
       
  1724 		'border-bottom-style',
       
  1725 		'border-bottom-width',
       
  1726 		'border-left',
       
  1727 		'border-left-color',
       
  1728 		'border-left-style',
       
  1729 		'border-left-width',
       
  1730 		'border-top',
       
  1731 		'border-top-color',
       
  1732 		'border-top-style',
       
  1733 		'border-top-width',
       
  1734 
       
  1735 		'border-spacing',
       
  1736 		'border-collapse',
       
  1737 		'caption-side',
       
  1738 
       
  1739 		'color',
       
  1740 		'font',
       
  1741 		'font-family',
       
  1742 		'font-size',
       
  1743 		'font-style',
       
  1744 		'font-variant',
       
  1745 		'font-weight',
       
  1746 		'letter-spacing',
       
  1747 		'line-height',
       
  1748 		'text-decoration',
       
  1749 		'text-indent',
       
  1750 		'text-align',
       
  1751 
       
  1752 		'height',
       
  1753 		'min-height',
       
  1754 		'max-height',
       
  1755 
       
  1756 		'width',
       
  1757 		'min-width',
       
  1758 		'max-width',
       
  1759 
       
  1760 		'margin',
       
  1761 		'margin-right',
       
  1762 		'margin-bottom',
       
  1763 		'margin-left',
       
  1764 		'margin-top',
       
  1765 
       
  1766 		'padding',
       
  1767 		'padding-right',
       
  1768 		'padding-bottom',
       
  1769 		'padding-left',
       
  1770 		'padding-top',
       
  1771 
       
  1772 		'clear',
       
  1773 		'cursor',
       
  1774 		'direction',
       
  1775 		'float',
       
  1776 		'overflow',
       
  1777 		'vertical-align',
       
  1778 		'list-style-type',
       
  1779 	) );
  1491 
  1780 
  1492 	if ( empty($allowed_attr) )
  1781 	if ( empty($allowed_attr) )
  1493 		return $css;
  1782 		return $css;
  1494 
  1783 
  1495 	$css = '';
  1784 	$css = '';