wp/wp-includes/kses.php
changeset 19 3d72ae0968f4
parent 18 be944660c56a
child 21 48c4eec2b7e6
equal deleted inserted replaced
18:be944660c56a 19:3d72ae0968f4
    79 			'nohref' => true,
    79 			'nohref' => true,
    80 			'shape'  => true,
    80 			'shape'  => true,
    81 			'target' => true,
    81 			'target' => true,
    82 		),
    82 		),
    83 		'article'    => array(
    83 		'article'    => array(
    84 			'align'    => true,
    84 			'align' => true,
    85 			'dir'      => true,
       
    86 			'lang'     => true,
       
    87 			'xml:lang' => true,
       
    88 		),
    85 		),
    89 		'aside'      => array(
    86 		'aside'      => array(
    90 			'align'    => true,
    87 			'align' => true,
    91 			'dir'      => true,
       
    92 			'lang'     => true,
       
    93 			'xml:lang' => true,
       
    94 		),
    88 		),
    95 		'audio'      => array(
    89 		'audio'      => array(
    96 			'autoplay' => true,
    90 			'autoplay' => true,
    97 			'controls' => true,
    91 			'controls' => true,
    98 			'loop'     => true,
    92 			'loop'     => true,
    99 			'muted'    => true,
    93 			'muted'    => true,
   100 			'preload'  => true,
    94 			'preload'  => true,
   101 			'src'      => true,
    95 			'src'      => true,
   102 		),
    96 		),
   103 		'b'          => array(),
    97 		'b'          => array(),
   104 		'bdo'        => array(
    98 		'bdo'        => array(),
   105 			'dir' => true,
       
   106 		),
       
   107 		'big'        => array(),
    99 		'big'        => array(),
   108 		'blockquote' => array(
   100 		'blockquote' => array(
   109 			'cite'     => true,
   101 			'cite' => true,
   110 			'lang'     => true,
       
   111 			'xml:lang' => true,
       
   112 		),
   102 		),
   113 		'br'         => array(),
   103 		'br'         => array(),
   114 		'button'     => array(
   104 		'button'     => array(
   115 			'disabled' => true,
   105 			'disabled' => true,
   116 			'name'     => true,
   106 			'name'     => true,
   118 			'value'    => true,
   108 			'value'    => true,
   119 		),
   109 		),
   120 		'caption'    => array(
   110 		'caption'    => array(
   121 			'align' => true,
   111 			'align' => true,
   122 		),
   112 		),
   123 		'cite'       => array(
   113 		'cite'       => array(),
   124 			'dir'  => true,
       
   125 			'lang' => true,
       
   126 		),
       
   127 		'code'       => array(),
   114 		'code'       => array(),
   128 		'col'        => array(
   115 		'col'        => array(
   129 			'align'   => true,
   116 			'align'   => true,
   130 			'char'    => true,
   117 			'char'    => true,
   131 			'charoff' => true,
   118 			'charoff' => true,
   132 			'span'    => true,
   119 			'span'    => true,
   133 			'dir'     => true,
       
   134 			'valign'  => true,
   120 			'valign'  => true,
   135 			'width'   => true,
   121 			'width'   => true,
   136 		),
   122 		),
   137 		'colgroup'   => array(
   123 		'colgroup'   => array(
   138 			'align'   => true,
   124 			'align'   => true,
   146 			'datetime' => true,
   132 			'datetime' => true,
   147 		),
   133 		),
   148 		'dd'         => array(),
   134 		'dd'         => array(),
   149 		'dfn'        => array(),
   135 		'dfn'        => array(),
   150 		'details'    => array(
   136 		'details'    => array(
   151 			'align'    => true,
   137 			'align' => true,
   152 			'dir'      => true,
   138 			'open'  => true,
   153 			'lang'     => true,
       
   154 			'open'     => true,
       
   155 			'xml:lang' => true,
       
   156 		),
   139 		),
   157 		'div'        => array(
   140 		'div'        => array(
   158 			'align'    => true,
   141 			'align' => true,
   159 			'dir'      => true,
       
   160 			'lang'     => true,
       
   161 			'xml:lang' => true,
       
   162 		),
   142 		),
   163 		'dl'         => array(),
   143 		'dl'         => array(),
   164 		'dt'         => array(),
   144 		'dt'         => array(),
   165 		'em'         => array(),
   145 		'em'         => array(),
   166 		'fieldset'   => array(),
   146 		'fieldset'   => array(),
   167 		'figure'     => array(
   147 		'figure'     => array(
   168 			'align'    => true,
   148 			'align' => true,
   169 			'dir'      => true,
       
   170 			'lang'     => true,
       
   171 			'xml:lang' => true,
       
   172 		),
   149 		),
   173 		'figcaption' => array(
   150 		'figcaption' => array(
   174 			'align'    => true,
   151 			'align' => true,
   175 			'dir'      => true,
       
   176 			'lang'     => true,
       
   177 			'xml:lang' => true,
       
   178 		),
   152 		),
   179 		'font'       => array(
   153 		'font'       => array(
   180 			'color' => true,
   154 			'color' => true,
   181 			'face'  => true,
   155 			'face'  => true,
   182 			'size'  => true,
   156 			'size'  => true,
   183 		),
   157 		),
   184 		'footer'     => array(
   158 		'footer'     => array(
   185 			'align'    => true,
   159 			'align' => true,
   186 			'dir'      => true,
       
   187 			'lang'     => true,
       
   188 			'xml:lang' => true,
       
   189 		),
   160 		),
   190 		'h1'         => array(
   161 		'h1'         => array(
   191 			'align' => true,
   162 			'align' => true,
   192 		),
   163 		),
   193 		'h2'         => array(
   164 		'h2'         => array(
   204 		),
   175 		),
   205 		'h6'         => array(
   176 		'h6'         => array(
   206 			'align' => true,
   177 			'align' => true,
   207 		),
   178 		),
   208 		'header'     => array(
   179 		'header'     => array(
   209 			'align'    => true,
   180 			'align' => true,
   210 			'dir'      => true,
       
   211 			'lang'     => true,
       
   212 			'xml:lang' => true,
       
   213 		),
   181 		),
   214 		'hgroup'     => array(
   182 		'hgroup'     => array(
   215 			'align'    => true,
   183 			'align' => true,
   216 			'dir'      => true,
       
   217 			'lang'     => true,
       
   218 			'xml:lang' => true,
       
   219 		),
   184 		),
   220 		'hr'         => array(
   185 		'hr'         => array(
   221 			'align'   => true,
   186 			'align'   => true,
   222 			'noshade' => true,
   187 			'noshade' => true,
   223 			'size'    => true,
   188 			'size'    => true,
   251 		'li'         => array(
   216 		'li'         => array(
   252 			'align' => true,
   217 			'align' => true,
   253 			'value' => true,
   218 			'value' => true,
   254 		),
   219 		),
   255 		'main'       => array(
   220 		'main'       => array(
   256 			'align'    => true,
   221 			'align' => true,
   257 			'dir'      => true,
       
   258 			'lang'     => true,
       
   259 			'xml:lang' => true,
       
   260 		),
   222 		),
   261 		'map'        => array(
   223 		'map'        => array(
   262 			'name' => true,
   224 			'name' => true,
   263 		),
   225 		),
   264 		'mark'       => array(),
   226 		'mark'       => array(),
   265 		'menu'       => array(
   227 		'menu'       => array(
   266 			'type' => true,
   228 			'type' => true,
   267 		),
   229 		),
   268 		'nav'        => array(
   230 		'nav'        => array(
   269 			'align'    => true,
   231 			'align' => true,
   270 			'dir'      => true,
   232 		),
   271 			'lang'     => true,
   233 		'object'     => array(
   272 			'xml:lang' => true,
   234 			'data' => array(
       
   235 				'required'       => true,
       
   236 				'value_callback' => '_wp_kses_allow_pdf_objects',
       
   237 			),
       
   238 			'type' => array(
       
   239 				'required' => true,
       
   240 				'values'   => array( 'application/pdf' ),
       
   241 			),
   273 		),
   242 		),
   274 		'p'          => array(
   243 		'p'          => array(
   275 			'align'    => true,
   244 			'align' => true,
   276 			'dir'      => true,
       
   277 			'lang'     => true,
       
   278 			'xml:lang' => true,
       
   279 		),
   245 		),
   280 		'pre'        => array(
   246 		'pre'        => array(
   281 			'width' => true,
   247 			'width' => true,
   282 		),
   248 		),
   283 		'q'          => array(
   249 		'q'          => array(
   284 			'cite' => true,
   250 			'cite' => true,
   285 		),
   251 		),
       
   252 		'rb'         => array(),
       
   253 		'rp'         => array(),
       
   254 		'rt'         => array(),
       
   255 		'rtc'        => array(),
       
   256 		'ruby'       => array(),
   286 		's'          => array(),
   257 		's'          => array(),
   287 		'samp'       => array(),
   258 		'samp'       => array(),
   288 		'span'       => array(
   259 		'span'       => array(
   289 			'dir'      => true,
   260 			'align' => true,
   290 			'align'    => true,
       
   291 			'lang'     => true,
       
   292 			'xml:lang' => true,
       
   293 		),
   261 		),
   294 		'section'    => array(
   262 		'section'    => array(
   295 			'align'    => true,
   263 			'align' => true,
   296 			'dir'      => true,
       
   297 			'lang'     => true,
       
   298 			'xml:lang' => true,
       
   299 		),
   264 		),
   300 		'small'      => array(),
   265 		'small'      => array(),
   301 		'strike'     => array(),
   266 		'strike'     => array(),
   302 		'strong'     => array(),
   267 		'strong'     => array(),
   303 		'sub'        => array(),
   268 		'sub'        => array(),
   304 		'summary'    => array(
   269 		'summary'    => array(
   305 			'align'    => true,
   270 			'align' => true,
   306 			'dir'      => true,
       
   307 			'lang'     => true,
       
   308 			'xml:lang' => true,
       
   309 		),
   271 		),
   310 		'sup'        => array(),
   272 		'sup'        => array(),
   311 		'table'      => array(
   273 		'table'      => array(
   312 			'align'       => true,
   274 			'align'       => true,
   313 			'bgcolor'     => true,
   275 			'bgcolor'     => true,
   314 			'border'      => true,
   276 			'border'      => true,
   315 			'cellpadding' => true,
   277 			'cellpadding' => true,
   316 			'cellspacing' => true,
   278 			'cellspacing' => true,
   317 			'dir'         => true,
       
   318 			'rules'       => true,
   279 			'rules'       => true,
   319 			'summary'     => true,
   280 			'summary'     => true,
   320 			'width'       => true,
   281 			'width'       => true,
   321 		),
   282 		),
   322 		'tbody'      => array(
   283 		'tbody'      => array(
   331 			'axis'    => true,
   292 			'axis'    => true,
   332 			'bgcolor' => true,
   293 			'bgcolor' => true,
   333 			'char'    => true,
   294 			'char'    => true,
   334 			'charoff' => true,
   295 			'charoff' => true,
   335 			'colspan' => true,
   296 			'colspan' => true,
   336 			'dir'     => true,
       
   337 			'headers' => true,
   297 			'headers' => true,
   338 			'height'  => true,
   298 			'height'  => true,
   339 			'nowrap'  => true,
   299 			'nowrap'  => true,
   340 			'rowspan' => true,
   300 			'rowspan' => true,
   341 			'scope'   => true,
   301 			'scope'   => true,
   450 		'strike'     => array(),
   410 		'strike'     => array(),
   451 		'strong'     => array(),
   411 		'strong'     => array(),
   452 	);
   412 	);
   453 
   413 
   454 	/**
   414 	/**
   455 	 * @var string[] $allowedentitynames Array of KSES allowed HTML entitity names.
   415 	 * @var string[] $allowedentitynames Array of KSES allowed HTML entity names.
   456 	 * @since 1.0.0
   416 	 * @since 1.0.0
   457 	 */
   417 	 */
   458 	$allowedentitynames = array(
   418 	$allowedentitynames = array(
   459 		'nbsp',
   419 		'nbsp',
   460 		'iexcl',
   420 		'iexcl',
   710 		'frac34',
   670 		'frac34',
   711 		'there4',
   671 		'there4',
   712 	);
   672 	);
   713 
   673 
   714 	/**
   674 	/**
   715 	 * @var string[] $allowedxmlentitynames Array of KSES allowed XML entitity names.
   675 	 * @var string[] $allowedxmlentitynames Array of KSES allowed XML entity names.
   716 	 * @since 5.5.0
   676 	 * @since 5.5.0
   717 	 */
   677 	 */
   718 	$allowedxmlnamedentities = array(
   678 	$allowedxmlentitynames = array(
   719 		'amp',
   679 		'amp',
   720 		'lt',
   680 		'lt',
   721 		'gt',
   681 		'gt',
   722 		'apos',
   682 		'apos',
   723 		'quot',
   683 		'quot',
   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 
  2226 			'column-rule',
  2304 			'column-rule',
  2227 			'column-span',
  2305 			'column-span',
  2228 			'column-width',
  2306 			'column-width',
  2229 
  2307 
  2230 			'color',
  2308 			'color',
       
  2309 			'filter',
  2231 			'font',
  2310 			'font',
  2232 			'font-family',
  2311 			'font-family',
  2233 			'font-size',
  2312 			'font-size',
  2234 			'font-style',
  2313 			'font-style',
  2235 			'font-variant',
  2314 			'font-variant',
  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 }