lib/experimental
connectors
3 months ago
content-types
3 months ago
dashboard-widgets
3 months ago
experiments
3 months ago
font-face
1 year ago
guidelines
3 months ago
interactivity-api
1 year ago
media-editor
3 months ago
pages
6 months ago
block-editor-settings-mobile.php
888 B
2 years ago
blocks.php
4.4 KB
7 months ago
class-gutenberg-hierarchical-sort.php
4.7 KB
6 months ago
class-wp-rest-block-editor-settings-controller.php
24.2 KB
7 months ago
editor-settings.php
3.3 KB
3 months ago
extensible-site-editor.php
975 B
7 months ago
kses-allowed-html.php
965 B
1 year ago
kses.php
6.2 KB
5 months ago
navigation-theme-opt-in.php
13.3 KB
6 months ago
rest-api-overrides.php
1.6 KB
9 months ago
rest-api.php
3.2 KB
7 months ago
script-modules.php
7.9 KB
6 months ago
workflow-palette.php
355 B
9 months ago
| 1 | <?php |
| 2 | /** |
| 3 | * Temporary compatibility shims for kses rules present in Gutenberg. |
| 4 | * |
| 5 | * The functions in this file should not be backported to core. |
| 6 | * |
| 7 | * @package gutenberg |
| 8 | */ |
| 9 | |
| 10 | /** |
| 11 | * Sanitizes global styles user content removing unsafe rules. |
| 12 | * |
| 13 | * This function is identical to the core version, but called the |
| 14 | * Gutenberg version of the theme JSON class (`WP_Theme_JSON_Gutenberg`). |
| 15 | * |
| 16 | * This function should not be backported to core. |
| 17 | * |
| 18 | * @since 5.9.0 |
| 19 | * |
| 20 | * @param string $data Post content to filter. |
| 21 | * @return string Filtered post content with unsafe rules removed. |
| 22 | */ |
| 23 | function gutenberg_filter_global_styles_post( $data ) { |
| 24 | $decoded_data = json_decode( wp_unslash( $data ), true ); |
| 25 | $json_decoding_error = json_last_error(); |
| 26 | if ( |
| 27 | JSON_ERROR_NONE === $json_decoding_error && |
| 28 | is_array( $decoded_data ) && |
| 29 | isset( $decoded_data['isGlobalStylesUserThemeJSON'] ) && |
| 30 | $decoded_data['isGlobalStylesUserThemeJSON'] |
| 31 | ) { |
| 32 | unset( $decoded_data['isGlobalStylesUserThemeJSON'] ); |
| 33 | |
| 34 | $data_to_encode = WP_Theme_JSON_Gutenberg::remove_insecure_properties( $decoded_data, 'custom' ); |
| 35 | |
| 36 | $data_to_encode['isGlobalStylesUserThemeJSON'] = true; |
| 37 | /** |
| 38 | * JSON encode the data stored in post content. |
| 39 | * Escape characters that are likely to be mangled by HTML filters: "<>&". |
| 40 | * |
| 41 | * This matches the escaping in {@see WP_REST_Global_Styles_Controller_Gutenberg::prepare_item_for_database()}. |
| 42 | */ |
| 43 | return wp_slash( wp_json_encode( $data_to_encode, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ) ); |
| 44 | } |
| 45 | return $data; |
| 46 | } |
| 47 | |
| 48 | /** |
| 49 | * Override core's kses_init_filters hooks for global styles, |
| 50 | * and use Gutenberg's version instead. This ensures that |
| 51 | * Gutenberg's `remove_insecure_properties` function can be called. |
| 52 | * |
| 53 | * The hooks are only set if they are already added, which ensures |
| 54 | * that global styles is only filtered for users without the `unfiltered_html` |
| 55 | * capability. |
| 56 | * |
| 57 | * This function should not be backported to core. |
| 58 | */ |
| 59 | function gutenberg_override_core_kses_init_filters() { |
| 60 | if ( has_filter( 'content_save_pre', 'wp_filter_global_styles_post' ) ) { |
| 61 | remove_filter( 'content_save_pre', 'wp_filter_global_styles_post', 9 ); |
| 62 | add_filter( 'content_save_pre', 'gutenberg_filter_global_styles_post', 9 ); |
| 63 | } |
| 64 | |
| 65 | if ( has_filter( 'content_filtered_save_pre', 'wp_filter_global_styles_post' ) ) { |
| 66 | remove_filter( 'content_filtered_save_pre', 'wp_filter_global_styles_post', 9 ); |
| 67 | add_filter( 'content_filtered_save_pre', 'gutenberg_filter_global_styles_post', 9 ); |
| 68 | } |
| 69 | } |
| 70 | // The 'kses_init_filters' is usually initialized with default priority. Use higher priority to override. |
| 71 | add_action( 'init', 'gutenberg_override_core_kses_init_filters', 20 ); |
| 72 | add_action( 'set_current_user', 'gutenberg_override_core_kses_init_filters' ); |
| 73 | |
| 74 | if ( ! function_exists( 'allow_filter_in_styles' ) ) { |
| 75 | /** |
| 76 | * See https://github.com/WordPress/wordpress-develop/pull/4108 |
| 77 | * |
| 78 | * Mark CSS safe if it contains a "filter: url('#wp-duotone-...')" rule. |
| 79 | * |
| 80 | * This function should not be backported to core. |
| 81 | * |
| 82 | * @param bool $allow_css Whether the CSS is allowed. |
| 83 | * @param string $css_test_string The CSS to test. |
| 84 | * @return bool Whether the CSS is allowed. |
| 85 | */ |
| 86 | function allow_filter_in_styles( $allow_css, $css_test_string ) { |
| 87 | if ( preg_match( |
| 88 | "/^filter:\s*url\((['\"]?)#wp-duotone-[-a-zA-Z0-9]+\\1\)(\s+!important)?$/", |
| 89 | $css_test_string |
| 90 | ) ) { |
| 91 | return true; |
| 92 | } |
| 93 | return $allow_css; |
| 94 | } |
| 95 | } |
| 96 | add_filter( 'safecss_filter_attr_allow_css', 'allow_filter_in_styles', 10, 2 ); |
| 97 | |
| 98 | /** |
| 99 | * Allow combined gradient and url() background-image values in inline styles. |
| 100 | * |
| 101 | * WordPress's safecss_filter_attr() handles gradient and url() values |
| 102 | * separately for background-image, but fails when both appear in a single |
| 103 | * comma-separated declaration. The url() portion is stripped from the test |
| 104 | * string before the filter runs, but the gradient regex in core expects the |
| 105 | * gradient to be the only value and doesn't match when a trailing comma and |
| 106 | * whitespace remain. This leaves parentheses in the test string, which |
| 107 | * triggers the unsafe-character check. |
| 108 | * |
| 109 | * This filter catches that case: the test string still contains a valid |
| 110 | * gradient function with only commas and whitespace remaining after the |
| 111 | * url() was removed. |
| 112 | * |
| 113 | * @param bool $allow_css Whether the CSS is allowed. |
| 114 | * @param string $css_test_string The CSS declaration to test. |
| 115 | * @return bool Whether the CSS is allowed. |
| 116 | */ |
| 117 | function gutenberg_allow_background_image_combined( $allow_css, $css_test_string ) { |
| 118 | if ( $allow_css ) { |
| 119 | return $allow_css; |
| 120 | } |
| 121 | /* |
| 122 | * The test string at this point has url() values already removed by |
| 123 | * safecss_filter_attr. What remains is a gradient with comma/whitespace |
| 124 | * residue where the url() was stripped. Two possible forms: |
| 125 | * |
| 126 | * Gradient first: "background-image:<gradient>(...), " |
| 127 | * URL first: "background-image:, <gradient>(...)" |
| 128 | * |
| 129 | * A trailing or leading comma (with optional whitespace) must be present |
| 130 | * to confirm a url() was actually removed. Without that residue, the |
| 131 | * gradient alone would already pass core's own check. |
| 132 | */ |
| 133 | $gradient_pattern = '(?:linear|radial|conic|repeating-linear|repeating-radial|repeating-conic)-gradient\((?:[^()]|\([^()]*\))*\)'; |
| 134 | $var_pattern = 'var\(--[a-zA-Z0-9_-]+(?:--[a-zA-Z0-9_-]+)*\)'; |
| 135 | $value_pattern = "(?:$gradient_pattern|$var_pattern)"; |
| 136 | |
| 137 | // Gradient/var first, then comma+whitespace residue from stripped url(). |
| 138 | $pattern_gradient_first = '/^background-image\s*:\s*' . $value_pattern . '\s*,[\s,]*$/'; |
| 139 | // Stripped url() first (comma+whitespace residue), then gradient/var. |
| 140 | $pattern_url_first = '/^background-image\s*:[\s,]*,\s*' . $value_pattern . '\s*$/'; |
| 141 | |
| 142 | if ( preg_match( $pattern_gradient_first, $css_test_string ) || preg_match( $pattern_url_first, $css_test_string ) ) { |
| 143 | return true; |
| 144 | } |
| 145 | |
| 146 | return $allow_css; |
| 147 | } |
| 148 | add_filter( 'safecss_filter_attr_allow_css', 'gutenberg_allow_background_image_combined', 10, 2 ); |
| 149 | |
| 150 | /** |
| 151 | * Update allowed inline style attributes list. |
| 152 | * |
| 153 | * @param string[] $attrs Array of allowed CSS attributes. |
| 154 | * @return string[] CSS attributes. |
| 155 | */ |
| 156 | function gutenberg_safe_grid_attrs( $attrs ) { |
| 157 | $attrs[] = 'grid-column'; |
| 158 | $attrs[] = 'grid-row'; |
| 159 | $attrs[] = 'container-type'; |
| 160 | return $attrs; |
| 161 | } |
| 162 | add_filter( 'safe_style_css', 'gutenberg_safe_grid_attrs' ); |
| 163 |