From 9f7edd04137428b015f7937b491efd80864e23e5 Mon Sep 17 00:00:00 2001 From: Aaron Jorbin Date: Thu, 12 Oct 2023 12:58:23 +0000 Subject: [PATCH] Editor: Harden the display of footnotes. Props: jorgefilipecosta, peterwilsoncc, costdev, xknown, jorbin. Built from https://develop.svn.wordpress.org/trunk@56839 git-svn-id: http://core.svn.wordpress.org/trunk@56351 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/blocks.php | 86 +++++++++++++++++++++++++++++++++++++++++ wp-includes/version.php | 2 +- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/wp-includes/blocks.php b/wp-includes/blocks.php index 00d9fdae3e..dddcfa27ce 100644 --- a/wp-includes/blocks.php +++ b/wp-includes/blocks.php @@ -1946,3 +1946,89 @@ function get_comments_pagination_arrow( $block, $pagination_type = 'next' ) { } return null; } + +/** + * Strips all HTML from the content of footnotes, and sanitizes the ID. + * This function expects slashed data on the footnotes content. + * + * @access private + * @since 6.3.2 + * + * @param string $footnotes JSON encoded string of an array containing the content and ID of each footnote. + * @return string Filtered content without any HTML on the footnote content and with the sanitized id. + */ +function _wp_filter_post_meta_footnotes( $footnotes ) { + $footnotes_decoded = json_decode( $footnotes, true ); + if ( ! is_array( $footnotes_decoded ) ) { + return ''; + } + $footnotes_sanitized = array(); + foreach ( $footnotes_decoded as $footnote ) { + if ( ! empty( $footnote['content'] ) && ! empty( $footnote['id'] ) ) { + $footnotes_sanitized[] = array( + 'id' => sanitize_key( $footnote['id'] ), + 'content' => wp_unslash( wp_filter_post_kses( wp_slash( $footnote['content'] ) ) ), + ); + } + } + return wp_json_encode( $footnotes_sanitized ); +} + +/** + * Adds the filters to filter footnotes meta field. + * + * @access private + * @since 6.3.2 + */ +function _wp_footnotes_kses_init_filters() { + add_filter( 'sanitize_post_meta_footnotes', '_wp_filter_post_meta_footnotes' ); +} + +/** + * Removes the filters that filter footnotes meta field. + * + * @access private + * @since 6.3.2 + */ +function _wp_footnotes_remove_filters() { + remove_filter( 'sanitize_post_meta_footnotes', '_wp_filter_post_meta_footnotes' ); +} + +/** + * Registers the filter of footnotes meta field if the user does not have unfiltered_html capability. + * + * @access private + * @since 6.3.2 + */ +function _wp_footnotes_kses_init() { + _wp_footnotes_remove_filters(); + if ( ! current_user_can( 'unfiltered_html' ) ) { + _wp_footnotes_kses_init_filters(); + } +} + +/** + * Initializes footnotes meta field filters when imported data should be filtered. + * + * This filter is the last being executed on force_filtered_html_on_import. + * If the input of the filter is true it means we are in an import situation and should + * enable kses, independently of the user capabilities. + * So in that case we call _wp_footnotes_kses_init_filters; + * + * @access private + * @since 6.3.2 + * + * @param string $arg Input argument of the filter. + * @return string Input argument of the filter. + */ +function _wp_footnotes_force_filtered_html_on_import_filter( $arg ) { + // force_filtered_html_on_import is true we need to init the global styles kses filters. + if ( $arg ) { + _wp_footnotes_kses_init_filters(); + } + return $arg; +} + +add_action( 'init', '_wp_footnotes_kses_init' ); +add_action( 'set_current_user', '_wp_footnotes_kses_init' ); +add_filter( 'force_filtered_html_on_import', '_wp_footnotes_force_filtered_html_on_import_filter', 999 ); diff --git a/wp-includes/version.php b/wp-includes/version.php index e17abee134..049a4d2fe4 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.4-beta3-56838'; +$wp_version = '6.4-beta3-56839'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.