*
 * @package External
 * @subpackage KSES
 */
/**
 * Specifies the default allowable HTML tags.
 *
 * Using `CUSTOM_TAGS` is not recommended and should be considered deprecated. The
 * {@see 'wp_kses_allowed_html'} filter is more powerful and supplies context.
 *
 * When using this constant, make sure to set all of these globals to arrays:
 *
 *  - `$allowedposttags`
 *  - `$allowedtags`
 *  - `$allowedentitynames`
 *  - `$allowedxmlentitynames`
 *
 * @see wp_kses_allowed_html()
 * @since 1.2.0
 *
 * @var array[]|false Array of default allowable HTML tags, or false to use the defaults.
 */
if ( ! defined( 'CUSTOM_TAGS' ) ) {
	define( 'CUSTOM_TAGS', false );
}
// Ensure that these variables are added to the global namespace
// (e.g. if using namespaces / autoload in the current PHP environment).
global $allowedposttags, $allowedtags, $allowedentitynames, $allowedxmlentitynames;
if ( ! CUSTOM_TAGS ) {
	/**
	 * KSES global for default allowable HTML tags.
	 *
	 * Can be overridden with the `CUSTOM_TAGS` constant.
	 *
	 * @var array[] $allowedposttags Array of default allowable HTML tags.
	 * @since 2.0.0
	 */
	$allowedposttags = array(
		'address'    => array(),
		'a'          => array(
			'href'     => true,
			'rel'      => true,
			'rev'      => true,
			'name'     => true,
			'target'   => true,
			'download' => array(
				'valueless' => 'y',
			),
		),
		'abbr'       => array(),
		'acronym'    => array(),
		'area'       => array(
			'alt'    => true,
			'coords' => true,
			'href'   => true,
			'nohref' => true,
			'shape'  => true,
			'target' => true,
		),
		'article'    => array(
			'align' => true,
		),
		'aside'      => array(
			'align' => true,
		),
		'audio'      => array(
			'autoplay' => true,
			'controls' => true,
			'loop'     => true,
			'muted'    => true,
			'preload'  => true,
			'src'      => true,
		),
		'b'          => array(),
		'bdo'        => array(),
		'big'        => array(),
		'blockquote' => array(
			'cite' => true,
		),
		'br'         => array(),
		'button'     => array(
			'disabled' => true,
			'name'     => true,
			'type'     => true,
			'value'    => true,
		),
		'caption'    => array(
			'align' => true,
		),
		'cite'       => array(),
		'code'       => array(),
		'col'        => array(
			'align'   => true,
			'char'    => true,
			'charoff' => true,
			'span'    => true,
			'valign'  => true,
			'width'   => true,
		),
		'colgroup'   => array(
			'align'   => true,
			'char'    => true,
			'charoff' => true,
			'span'    => true,
			'valign'  => true,
			'width'   => true,
		),
		'del'        => array(
			'datetime' => true,
		),
		'dd'         => array(),
		'dfn'        => array(),
		'details'    => array(
			'align' => true,
			'open'  => true,
		),
		'div'        => array(
			'align' => true,
		),
		'dl'         => array(),
		'dt'         => array(),
		'em'         => array(),
		'fieldset'   => array(),
		'figure'     => array(
			'align' => true,
		),
		'figcaption' => array(
			'align' => true,
		),
		'font'       => array(
			'color' => true,
			'face'  => true,
			'size'  => true,
		),
		'footer'     => array(
			'align' => true,
		),
		'h1'         => array(
			'align' => true,
		),
		'h2'         => array(
			'align' => true,
		),
		'h3'         => array(
			'align' => true,
		),
		'h4'         => array(
			'align' => true,
		),
		'h5'         => array(
			'align' => true,
		),
		'h6'         => array(
			'align' => true,
		),
		'header'     => array(
			'align' => true,
		),
		'hgroup'     => array(
			'align' => true,
		),
		'hr'         => array(
			'align'   => true,
			'noshade' => true,
			'size'    => true,
			'width'   => true,
		),
		'i'          => array(),
		'img'        => array(
			'alt'      => true,
			'align'    => true,
			'border'   => true,
			'height'   => true,
			'hspace'   => true,
			'loading'  => true,
			'longdesc' => true,
			'vspace'   => true,
			'src'      => true,
			'usemap'   => true,
			'width'    => true,
		),
		'ins'        => array(
			'datetime' => true,
			'cite'     => true,
		),
		'kbd'        => array(),
		'label'      => array(
			'for' => true,
		),
		'legend'     => array(
			'align' => true,
		),
		'li'         => array(
			'align' => true,
			'value' => true,
		),
		'main'       => array(
			'align' => true,
		),
		'map'        => array(
			'name' => true,
		),
		'mark'       => array(),
		'menu'       => array(
			'type' => true,
		),
		'nav'        => array(
			'align' => true,
		),
		'object'     => array(
			'data' => array(
				'required'       => true,
				'value_callback' => '_wp_kses_allow_pdf_objects',
			),
			'type' => array(
				'required' => true,
				'values'   => array( 'application/pdf' ),
			),
		),
		'p'          => array(
			'align' => true,
		),
		'pre'        => array(
			'width' => true,
		),
		'q'          => array(
			'cite' => true,
		),
		'rb'         => array(),
		'rp'         => array(),
		'rt'         => array(),
		'rtc'        => array(),
		'ruby'       => array(),
		's'          => array(),
		'samp'       => array(),
		'span'       => array(
			'align' => true,
		),
		'section'    => array(
			'align' => true,
		),
		'small'      => array(),
		'strike'     => array(),
		'strong'     => array(),
		'sub'        => array(),
		'summary'    => array(
			'align' => true,
		),
		'sup'        => array(),
		'table'      => array(
			'align'       => true,
			'bgcolor'     => true,
			'border'      => true,
			'cellpadding' => true,
			'cellspacing' => true,
			'rules'       => true,
			'summary'     => true,
			'width'       => true,
		),
		'tbody'      => array(
			'align'   => true,
			'char'    => true,
			'charoff' => true,
			'valign'  => true,
		),
		'td'         => array(
			'abbr'    => true,
			'align'   => true,
			'axis'    => true,
			'bgcolor' => true,
			'char'    => true,
			'charoff' => true,
			'colspan' => true,
			'headers' => true,
			'height'  => true,
			'nowrap'  => true,
			'rowspan' => true,
			'scope'   => true,
			'valign'  => true,
			'width'   => true,
		),
		'textarea'   => array(
			'cols'     => true,
			'rows'     => true,
			'disabled' => true,
			'name'     => true,
			'readonly' => true,
		),
		'tfoot'      => array(
			'align'   => true,
			'char'    => true,
			'charoff' => true,
			'valign'  => true,
		),
		'th'         => array(
			'abbr'    => true,
			'align'   => true,
			'axis'    => true,
			'bgcolor' => true,
			'char'    => true,
			'charoff' => true,
			'colspan' => true,
			'headers' => true,
			'height'  => true,
			'nowrap'  => true,
			'rowspan' => true,
			'scope'   => true,
			'valign'  => true,
			'width'   => true,
		),
		'thead'      => array(
			'align'   => true,
			'char'    => true,
			'charoff' => true,
			'valign'  => true,
		),
		'title'      => array(),
		'tr'         => array(
			'align'   => true,
			'bgcolor' => true,
			'char'    => true,
			'charoff' => true,
			'valign'  => true,
		),
		'track'      => array(
			'default' => true,
			'kind'    => true,
			'label'   => true,
			'src'     => true,
			'srclang' => true,
		),
		'tt'         => array(),
		'u'          => array(),
		'ul'         => array(
			'type' => true,
		),
		'ol'         => array(
			'start'    => true,
			'type'     => true,
			'reversed' => true,
		),
		'var'        => array(),
		'video'      => array(
			'autoplay'    => true,
			'controls'    => true,
			'height'      => true,
			'loop'        => true,
			'muted'       => true,
			'playsinline' => true,
			'poster'      => true,
			'preload'     => true,
			'src'         => true,
			'width'       => true,
		),
	);
	/**
	 * @var array[] $allowedtags Array of KSES allowed HTML elements.
	 * @since 1.0.0
	 */
	$allowedtags = array(
		'a'          => array(
			'href'  => true,
			'title' => true,
		),
		'abbr'       => array(
			'title' => true,
		),
		'acronym'    => array(
			'title' => true,
		),
		'b'          => array(),
		'blockquote' => array(
			'cite' => true,
		),
		'cite'       => array(),
		'code'       => array(),
		'del'        => array(
			'datetime' => true,
		),
		'em'         => array(),
		'i'          => array(),
		'q'          => array(
			'cite' => true,
		),
		's'          => array(),
		'strike'     => array(),
		'strong'     => array(),
	);
	/**
	 * @var string[] $allowedentitynames Array of KSES allowed HTML entity names.
	 * @since 1.0.0
	 */
	$allowedentitynames = array(
		'nbsp',
		'iexcl',
		'cent',
		'pound',
		'curren',
		'yen',
		'brvbar',
		'sect',
		'uml',
		'copy',
		'ordf',
		'laquo',
		'not',
		'shy',
		'reg',
		'macr',
		'deg',
		'plusmn',
		'acute',
		'micro',
		'para',
		'middot',
		'cedil',
		'ordm',
		'raquo',
		'iquest',
		'Agrave',
		'Aacute',
		'Acirc',
		'Atilde',
		'Auml',
		'Aring',
		'AElig',
		'Ccedil',
		'Egrave',
		'Eacute',
		'Ecirc',
		'Euml',
		'Igrave',
		'Iacute',
		'Icirc',
		'Iuml',
		'ETH',
		'Ntilde',
		'Ograve',
		'Oacute',
		'Ocirc',
		'Otilde',
		'Ouml',
		'times',
		'Oslash',
		'Ugrave',
		'Uacute',
		'Ucirc',
		'Uuml',
		'Yacute',
		'THORN',
		'szlig',
		'agrave',
		'aacute',
		'acirc',
		'atilde',
		'auml',
		'aring',
		'aelig',
		'ccedil',
		'egrave',
		'eacute',
		'ecirc',
		'euml',
		'igrave',
		'iacute',
		'icirc',
		'iuml',
		'eth',
		'ntilde',
		'ograve',
		'oacute',
		'ocirc',
		'otilde',
		'ouml',
		'divide',
		'oslash',
		'ugrave',
		'uacute',
		'ucirc',
		'uuml',
		'yacute',
		'thorn',
		'yuml',
		'quot',
		'amp',
		'lt',
		'gt',
		'apos',
		'OElig',
		'oelig',
		'Scaron',
		'scaron',
		'Yuml',
		'circ',
		'tilde',
		'ensp',
		'emsp',
		'thinsp',
		'zwnj',
		'zwj',
		'lrm',
		'rlm',
		'ndash',
		'mdash',
		'lsquo',
		'rsquo',
		'sbquo',
		'ldquo',
		'rdquo',
		'bdquo',
		'dagger',
		'Dagger',
		'permil',
		'lsaquo',
		'rsaquo',
		'euro',
		'fnof',
		'Alpha',
		'Beta',
		'Gamma',
		'Delta',
		'Epsilon',
		'Zeta',
		'Eta',
		'Theta',
		'Iota',
		'Kappa',
		'Lambda',
		'Mu',
		'Nu',
		'Xi',
		'Omicron',
		'Pi',
		'Rho',
		'Sigma',
		'Tau',
		'Upsilon',
		'Phi',
		'Chi',
		'Psi',
		'Omega',
		'alpha',
		'beta',
		'gamma',
		'delta',
		'epsilon',
		'zeta',
		'eta',
		'theta',
		'iota',
		'kappa',
		'lambda',
		'mu',
		'nu',
		'xi',
		'omicron',
		'pi',
		'rho',
		'sigmaf',
		'sigma',
		'tau',
		'upsilon',
		'phi',
		'chi',
		'psi',
		'omega',
		'thetasym',
		'upsih',
		'piv',
		'bull',
		'hellip',
		'prime',
		'Prime',
		'oline',
		'frasl',
		'weierp',
		'image',
		'real',
		'trade',
		'alefsym',
		'larr',
		'uarr',
		'rarr',
		'darr',
		'harr',
		'crarr',
		'lArr',
		'uArr',
		'rArr',
		'dArr',
		'hArr',
		'forall',
		'part',
		'exist',
		'empty',
		'nabla',
		'isin',
		'notin',
		'ni',
		'prod',
		'sum',
		'minus',
		'lowast',
		'radic',
		'prop',
		'infin',
		'ang',
		'and',
		'or',
		'cap',
		'cup',
		'int',
		'sim',
		'cong',
		'asymp',
		'ne',
		'equiv',
		'le',
		'ge',
		'sub',
		'sup',
		'nsub',
		'sube',
		'supe',
		'oplus',
		'otimes',
		'perp',
		'sdot',
		'lceil',
		'rceil',
		'lfloor',
		'rfloor',
		'lang',
		'rang',
		'loz',
		'spades',
		'clubs',
		'hearts',
		'diams',
		'sup1',
		'sup2',
		'sup3',
		'frac14',
		'frac12',
		'frac34',
		'there4',
	);
	/**
	 * @var string[] $allowedxmlentitynames Array of KSES allowed XML entity names.
	 * @since 5.5.0
	 */
	$allowedxmlentitynames = array(
		'amp',
		'lt',
		'gt',
		'apos',
		'quot',
	);
	$allowedposttags = array_map( '_wp_add_global_attributes', $allowedposttags );
} else {
	$required_kses_globals = array(
		'allowedposttags',
		'allowedtags',
		'allowedentitynames',
		'allowedxmlentitynames',
	);
	$missing_kses_globals  = array();
	foreach ( $required_kses_globals as $global_name ) {
		if ( ! isset( $GLOBALS[ $global_name ] ) || ! is_array( $GLOBALS[ $global_name ] ) ) {
			$missing_kses_globals[] = '$' . $global_name . '';
		}
	}
	if ( $missing_kses_globals ) {
		_doing_it_wrong(
			'wp_kses_allowed_html',
			sprintf(
				/* translators: 1: CUSTOM_TAGS, 2: Global variable names. */
				__( 'When using the %1$s constant, make sure to set these globals to an array: %2$s.' ),
				'CUSTOM_TAGS',
				implode( ', ', $missing_kses_globals )
			),
			'6.2.0'
		);
	}
	$allowedtags     = wp_kses_array_lc( $allowedtags );
	$allowedposttags = wp_kses_array_lc( $allowedposttags );
}
/**
 * Filters text content and strips out disallowed HTML.
 *
 * This function makes sure that only the allowed HTML element names, attribute
 * names, attribute values, and HTML entities will occur in the given text string.
 *
 * This function expects unslashed data.
 *
 * @see wp_kses_post() for specifically filtering post content and fields.
 * @see wp_allowed_protocols() for the default allowed protocols in link URLs.
 *
 * @since 1.0.0
 *
 * @param string         $content           Text content to filter.
 * @param array[]|string $allowed_html      An array of allowed HTML elements and attributes,
 *                                          or a context name such as 'post'. See wp_kses_allowed_html()
 *                                          for the list of accepted context names.
 * @param string[]       $allowed_protocols Optional. Array of allowed URL protocols.
 *                                          Defaults to the result of wp_allowed_protocols().
 * @return string Filtered content containing only the allowed HTML.
 */
function wp_kses( $content, $allowed_html, $allowed_protocols = array() ) {
	if ( empty( $allowed_protocols ) ) {
		$allowed_protocols = wp_allowed_protocols();
	}
	$content = wp_kses_no_null( $content, array( 'slash_zero' => 'keep' ) );
	$content = wp_kses_normalize_entities( $content );
	$content = wp_kses_hook( $content, $allowed_html, $allowed_protocols );
	return wp_kses_split( $content, $allowed_html, $allowed_protocols );
}
/**
 * Filters one HTML attribute and ensures its value is allowed.
 *
 * This function can escape data in some situations where `wp_kses()` must strip the whole attribute.
 *
 * @since 4.2.3
 *
 * @param string $attr    The 'whole' attribute, including name and value.
 * @param string $element The HTML element name to which the attribute belongs.
 * @return string Filtered attribute.
 */
function wp_kses_one_attr( $attr, $element ) {
	$uris              = wp_kses_uri_attributes();
	$allowed_html      = wp_kses_allowed_html( 'post' );
	$allowed_protocols = wp_allowed_protocols();
	$attr              = wp_kses_no_null( $attr, array( 'slash_zero' => 'keep' ) );
	// Preserve leading and trailing whitespace.
	$matches = array();
	preg_match( '/^\s*/', $attr, $matches );
	$lead = $matches[0];
	preg_match( '/\s*$/', $attr, $matches );
	$trail = $matches[0];
	if ( empty( $trail ) ) {
		$attr = substr( $attr, strlen( $lead ) );
	} else {
		$attr = substr( $attr, strlen( $lead ), -strlen( $trail ) );
	}
	// Parse attribute name and value from input.
	$split = preg_split( '/\s*=\s*/', $attr, 2 );
	$name  = $split[0];
	if ( count( $split ) === 2 ) {
		$value = $split[1];
		/*
		 * Remove quotes surrounding $value.
		 * Also guarantee correct quoting in $attr for this one attribute.
		 */
		if ( '' === $value ) {
			$quote = '';
		} else {
			$quote = $value[0];
		}
		if ( '"' === $quote || "'" === $quote ) {
			if ( ! str_ends_with( $value, $quote ) ) {
				return '';
			}
			$value = substr( $value, 1, -1 );
		} else {
			$quote = '"';
		}
		// Sanitize quotes, angle braces, and entities.
		$value = esc_attr( $value );
		// Sanitize URI values.
		if ( in_array( strtolower( $name ), $uris, true ) ) {
			$value = wp_kses_bad_protocol( $value, $allowed_protocols );
		}
		$attr  = "$name=$quote$value$quote";
		$vless = 'n';
	} else {
		$value = '';
		$vless = 'y';
	}
	// Sanitize attribute by name.
	wp_kses_attr_check( $name, $value, $attr, $vless, $element, $allowed_html );
	// Restore whitespace.
	return $lead . $attr . $trail;
}
/**
 * Returns an array of allowed HTML tags and attributes for a given context.
 *
 * @since 3.5.0
 * @since 5.0.1 `form` removed as allowable HTML tag.
 *
 * @global array $allowedposttags
 * @global array $allowedtags
 * @global array $allowedentitynames
 *
 * @param string|array $context The context for which to retrieve tags. Allowed values are 'post',
 *                              'strip', 'data', 'entities', or the name of a field filter such as
 *                              'pre_user_description', or an array of allowed HTML elements and attributes.
 * @return array Array of allowed HTML tags and their allowed attributes.
 */
function wp_kses_allowed_html( $context = '' ) {
	global $allowedposttags, $allowedtags, $allowedentitynames;
	if ( is_array( $context ) ) {
		// When `$context` is an array it's actually an array of allowed HTML elements and attributes.
		$html    = $context;
		$context = 'explicit';
		/**
		 * Filters the HTML tags that are allowed for a given context.
		 *
		 * HTML tags and attribute names are case-insensitive in HTML but must be
		 * added to the KSES allow list in lowercase. An item added to the allow list
		 * in upper or mixed case will not recognized as permitted by KSES.
		 *
		 * @since 3.5.0
		 *
		 * @param array[] $html    Allowed HTML tags.
		 * @param string  $context Context name.
		 */
		return apply_filters( 'wp_kses_allowed_html', $html, $context );
	}
	switch ( $context ) {
		case 'post':
			/** This filter is documented in wp-includes/kses.php */
			$tags = apply_filters( 'wp_kses_allowed_html', $allowedposttags, $context );
			// 5.0.1 removed the `