` on, so it goes before wp_kses runs as well. * * @var array */ const STRIP_ELEMENTS = array( 'script', 'style', 'noscript', 'template', 'button', 'nav', 'dialog', 'form', 'textarea', 'select', 'option', 'optgroup', 'datalist', 'input', 'fieldset', 'iframe', 'embed', 'object', 'canvas', 'applet', 'noembed', 'noframes', 'annotation-xml', ); /** * MathML global attributes allowed per the W3C MathML safe list. * * @see https://w3c.github.io/mathml-docs/mathml-safe-list * * @var array */ const MATHML_GLOBAL_ATTRS = array( 'dir' => true, 'displaystyle' => true, 'mathbackground' => true, 'mathcolor' => true, 'mathsize' => true, 'scriptlevel' => true, 'intent' => true, 'arg' => true, ); /** * Sanitize a list of URLs. * * @param string|array $value The value to sanitize. * @return array The sanitized list of URLs. */ public static function url_list( $value ) { if ( ! \is_array( $value ) ) { $value = \explode( PHP_EOL, (string) $value ); } $value = \array_filter( $value ); $value = \array_map( 'trim', $value ); $value = \array_map( 'sanitize_url', $value ); $value = \array_unique( $value ); return \array_values( $value ); } /** * Sanitize and normalize a list of account identifiers to ActivityPub IDs. * * This function processes various identifier formats, such as URLs and * webfinger identifiers, and normalizes them into a consistent format. * * @param string|array $value The value to sanitize. * * @return array The sanitized and normalized list of account identifiers. */ public static function identifier_list( $value ) { if ( ! \is_array( $value ) ) { $value = \explode( PHP_EOL, (string) $value ); } $value = \array_filter( $value ); $uris = array(); foreach ( $value as $uri ) { $uri = \trim( $uri ); $uri = \ltrim( $uri, '@' ); if ( \is_email( $uri ) ) { $_uri = Webfinger::resolve( $uri ); if ( \is_wp_error( $_uri ) ) { $uris[] = $uri; continue; } $uri = $_uri; } $uri = \sanitize_url( $uri ); $actor = Remote_Actors::fetch_by_uri( $uri ); if ( \is_wp_error( $actor ) ) { $uris[] = $uri; } else { $uris[] = \sanitize_url( $actor->guid ); } } return \array_values( \array_unique( $uris ) ); } /** * Sanitize a list of hosts. * * @param string $value The value to sanitize. * @return string The sanitized list of hosts. */ public static function host_list( $value ) { $value = \explode( PHP_EOL, (string) $value ); $value = \array_map( static function ( $host ) { $host = \trim( $host ); $host = \strtolower( $host ); $host = \set_url_scheme( $host ); $host = \sanitize_url( $host, array( 'http', 'https' ) ); // Remove protocol. if ( \str_contains( $host, 'http' ) ) { $host = \wp_parse_url( $host, PHP_URL_HOST ); } return \filter_var( $host, FILTER_VALIDATE_DOMAIN ); }, $value ); return \implode( PHP_EOL, \array_filter( $value ) ); } /** * Sanitize a blog identifier. * * @param string $value The value to sanitize. * @return string The sanitized blog identifier. */ public static function blog_identifier( $value ) { /* * `sanitize_title()` hands multibyte characters to `utf8_uri_encode()`, which percent-encodes * them rather than dropping them, so an emoji survives into the handle as `%e2%9d%a4%ef%b8%8f`. * Strict `sanitize_user()` reduces to ASCII and kills any octets that are already there. */ $value = \sanitize_user( (string) $value, true ); // Hack to allow dots in the username. $parts = \explode( '.', $value ); $parts = \array_map( 'sanitize_title', $parts ); // A segment can sanitize away to nothing, and a leading, trailing or doubled dot is not a usable handle. $parts = \array_filter( $parts, static function ( $part ) { return '' !== $part; } ); $sanitized = \implode( '.', $parts ); if ( empty( $sanitized ) ) { return Blog::get_default_username(); } // The 'application' identifier is reserved for the Application actor. if ( Application::USERNAME === $sanitized ) { \add_settings_error( 'activitypub_blog_identifier', 'activitypub_blog_identifier', \esc_html__( 'This name is reserved and cannot be used for the blog profile ID.', 'activitypub' ) ); return Blog::get_default_username(); } // Check for login or nicename. $user = new \WP_User_Query( array( 'search' => $sanitized, 'search_columns' => array( 'user_login', 'user_nicename' ), 'number' => 1, 'hide_empty' => true, 'fields' => 'ID', ) ); if ( $user->get_results() ) { \add_settings_error( 'activitypub_blog_identifier', 'activitypub_blog_identifier', \esc_html__( 'You cannot use an existing author’s name for the blog profile ID.', 'activitypub' ) ); return Blog::get_default_username(); } return $sanitized; } /** * Get the sanitized value of a constant. * * @param mixed $value The constant value. * * @return string The sanitized value. */ public static function constant_value( $value ) { if ( \is_bool( $value ) ) { return $value ? 'true' : 'false'; } if ( \is_string( $value ) ) { return \esc_attr( $value ); } if ( \is_array( $value ) ) { // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r return \print_r( $value, true ); } return $value; } /** * Sanitize a webfinger identifier. * * @param string $value The value to sanitize. * * @return string The sanitized webfinger identifier. */ public static function webfinger( $value ) { $value = \str_replace( 'acct:', '', $value ); $value = \trim( $value, '@' ); return $value; } /** * Sanitize an attachment ID that must point to an image. Returns 0 for anything else. * * @since 9.4.0 * * @param int|string $value The value to sanitize. * * @return int The sanitized attachment ID. */ public static function attachment_id( $value ) { $id = \absint( $value ); return $id && \wp_attachment_is_image( $id ) ? $id : 0; } /** * Remove elements whose inner text is noise on its own. * * Used by {@see Sanitize::clean_html()}: * kses removes a tag but keeps what is inside it, so a `