Make WordPress Core

Changeset 55345


Ignore:
Timestamp:
02/15/2023 03:55:12 AM (4 years ago)
Author:
peterwilsoncc
Message:

Editor: Prevent KSES stripping global layout style properties.

Layout style properties are stored using indirect values, rather than direct CSS properties.

Allow users without the unfiltered_html capability to modify global styles using the indirect block spacing properties contentSize, wideSize, and blockGap, using a mapping of the eventual CSS property to the indirect property stored in theme.json. The mapped CSS property is then used for CSS validation.

Props andrewserong, costdev, hellofromtonya, mamaduka, mmtr86.
Fixes #57321.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-theme-json.php

    r55285 r55345  
    264264
    265265        /**
     266         * Indirect metadata for style properties that are not directly output.
     267         *
     268         * Each element maps from a CSS property name to an array of
     269         * paths to the value in theme.json & block attributes.
     270         *
     271         * Indirect properties are not output directly by `compute_style_properties`,
     272         * but are used elsewhere in the processing of global styles. The indirect
     273         * property is used to validate whether or not a style value is allowed.
     274         *
     275         * @since 6.1.2
     276         * @var array
     277         */
     278        const INDIRECT_PROPERTIES_METADATA = array(
     279                'gap'        => array(
     280                        array( 'spacing', 'blockGap' ),
     281                ),
     282                'column-gap' => array(
     283                        array( 'spacing', 'blockGap', 'left' ),
     284                ),
     285                'row-gap'    => array(
     286                        array( 'spacing', 'blockGap', 'top' ),
     287                ),
     288                'max-width'  => array(
     289                        array( 'layout', 'contentSize' ),
     290                        array( 'layout', 'wideSize' ),
     291                ),
     292        );
     293
     294        /**
    266295         * Protected style properties.
    267296         *
     
    29502979                        }
    29512980                }
     2981
     2982                // Ensure indirect properties not included in any `PRESETS_METADATA` value are allowed.
     2983                static::remove_indirect_properties( $input, $output );
     2984
    29522985                return $output;
    29532986        }
     
    29783011                        }
    29793012                }
     3013
     3014                // Ensure indirect properties not handled by `compute_style_properties` are allowed.
     3015                static::remove_indirect_properties( $input, $output );
     3016
    29803017                return $output;
    29813018        }
     
    29943031                $filtered          = esc_html( safecss_filter_attr( $style_to_validate ) );
    29953032                return ! empty( trim( $filtered ) );
     3033        }
     3034
     3035        /**
     3036         * Removes indirect properties from the given input node and
     3037         * sets in the given output node.
     3038         *
     3039         * @since 6.1.2
     3040         *
     3041         * @param array $input  Node to process.
     3042         * @param array $output The processed node. Passed by reference.
     3043         */
     3044        private static function remove_indirect_properties( $input, &$output ) {
     3045                foreach ( static::INDIRECT_PROPERTIES_METADATA as $property => $paths ) {
     3046                        foreach ( $paths as $path ) {
     3047                                $value = _wp_array_get( $input, $path );
     3048                                if (
     3049                                        is_string( $value ) &&
     3050                                        static::is_safe_css_declaration( $property, $value )
     3051                                ) {
     3052                                        _wp_array_set( $output, $path, $value );
     3053                                }
     3054                        }
     3055                }
    29963056        }
    29973057
  • trunk/tests/phpunit/tests/theme/wpThemeJson.php

    r55285 r55345  
    24282428
    24292429        /**
     2430         * @ticket 57321
     2431         *
     2432         * @covers WP_Theme_JSON::remove_insecure_properties
     2433         */
     2434        public function test_remove_insecure_properties_should_allow_indirect_properties() {
     2435                $actual = WP_Theme_JSON::remove_insecure_properties(
     2436                        array(
     2437                                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
     2438                                'styles'   => array(
     2439                                        'spacing' => array(
     2440                                                'blockGap' => '3em',
     2441                                        ),
     2442                                        'blocks'  => array(
     2443                                                'core/social-links' => array(
     2444                                                        'spacing' => array(
     2445                                                                'blockGap' => array(
     2446                                                                        'left' => '2em',
     2447                                                                        'top'  => '1em',
     2448                                                                ),
     2449                                                        ),
     2450                                                ),
     2451                                        ),
     2452                                ),
     2453                                'settings' => array(
     2454                                        'layout' => array(
     2455                                                'contentSize' => '800px',
     2456                                                'wideSize'    => '1000px',
     2457                                        ),
     2458                                ),
     2459                        )
     2460                );
     2461
     2462                $expected = array(
     2463                        'version'  => WP_Theme_JSON::LATEST_SCHEMA,
     2464                        'styles'   => array(
     2465                                'spacing' => array(
     2466                                        'blockGap' => '3em',
     2467                                ),
     2468                                'blocks'  => array(
     2469                                        'core/social-links' => array(
     2470                                                'spacing' => array(
     2471                                                        'blockGap' => array(
     2472                                                                'left' => '2em',
     2473                                                                'top'  => '1em',
     2474                                                        ),
     2475                                                ),
     2476                                        ),
     2477                                ),
     2478                        ),
     2479                        'settings' => array(
     2480                                'layout' => array(
     2481                                        'contentSize' => '800px',
     2482                                        'wideSize'    => '1000px',
     2483                                ),
     2484                        ),
     2485                );
     2486
     2487                $this->assertSameSetsWithIndex( $expected, $actual );
     2488        }
     2489
     2490        /**
    24302491         * @ticket 56467
    24312492         */
Note: See TracChangeset for help on using the changeset viewer.