Make WordPress Core

Changeset 43727


Ignore:
Timestamp:
10/15/2018 05:21:04 AM (5 years ago)
Author:
peterwilsoncc
Message:

KSES: Allow HTML data-* attributes.

Add global support for HTML attributes prefixed data- for authors and contributors, as required by the new editor.

Props azaozz, peterwilsoncc.
Fixes #33121.

Location:
branches/5.0
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/5.0/src/wp-includes/kses.php

    r42861 r43727  
    855855 *
    856856 * @since 4.2.3
     857 * @since 5.0.0 Add support for `data-*` wildcard attributes.
    857858 *
    858859 * @param string $name The attribute name. Returns empty string when not allowed.
     
    865866 */
    866867function wp_kses_attr_check( &$name, &$value, &$whole, $vless, $element, $allowed_html ) {
    867     $allowed_attr = $allowed_html[strtolower( $element )];
     868    $allowed_attr = $allowed_html[ strtolower( $element ) ];
    868869
    869870    $name_low = strtolower( $name );
     871
    870872    if ( ! isset( $allowed_attr[$name_low] ) || '' == $allowed_attr[$name_low] ) {
    871         $name = $value = $whole = '';
    872         return false;
     873        /*
     874         * Allow `data-*` attributes.
     875         *
     876         * When specifying `$allowed_html`, the attribute name should be set as
     877         * `data-*` (not to be mixed with the HTML 4.0 `data` attribute, see
     878         * https://www.w3.org/TR/html40/struct/objects.html#adef-data).
     879         *
     880         * Note: the attribute name should only contain `A-Za-z0-9_-` chars,
     881         * double hyphens `--` are not accepted by WordPress.
     882         */
     883        if ( strpos( $name_low, 'data-' ) === 0 && ! empty( $allowed_attr['data-*'] ) && preg_match( '/^data(?:-[a-z0-9_]+)+$/', $name_low, $match ) ) {
     884            /*
     885             * Add the whole attribute name to the allowed attributes and set any restrictions
     886             * for the `data-*` attribute values for the current element.
     887             */
     888            $allowed_attr[ $match[0] ] = $allowed_attr['data-*'];
     889        } else {
     890            $name = $value = $whole = '';
     891            return false;
     892        }
    873893    }
    874894
     
    885905    }
    886906
    887     if ( is_array( $allowed_attr[$name_low] ) ) {
     907    if ( is_array( $allowed_attr[ $name_low ] ) ) {
    888908        // there are some checks
    889909        foreach ( $allowed_attr[$name_low] as $currkey => $currval ) {
     
    18091829 *
    18101830 * @since 3.5.0
     1831 * @since 5.0.0 Add support for `data-*` wildcard attributes.
    18111832 * @access private
    18121833 *
     
    18211842        'title' => true,
    18221843        'role' => true,
     1844        'data-*' => true,
    18231845    );
    18241846
  • branches/5.0/tests/phpunit/tests/kses.php

    r42861 r43727  
    719719        $this->assertEquals( "<{$element}>", wp_kses_attr( $element, $attribute, array( 'foo' => false ), array() ) );
    720720    }
     721
     722    /**
     723     * Data attributes are globally accepted.
     724     *
     725     * @ticket 33121
     726     */
     727    function test_wp_kses_attr_data_attribute_is_allowed() {
     728        $test = '<div data-foo="foo" data-bar="bar" datainvalid="gone" data--invaild="gone"  data-also-invaild-="gone" data-two-hyphens="remains">Pens and pencils</div>';
     729        $expected = '<div data-foo="foo" data-bar="bar" data-two-hyphens="remains">Pens and pencils</div>';
     730
     731        $this->assertEquals( $expected, wp_kses_post( $test ) );
     732    }
     733
     734    /**
     735     * Ensure wildcard attributes block unprefixed wildcard uses.
     736     *
     737     * @ticket 33121
     738     */
     739    function test_wildcard_requires_hyphen_after_prefix() {
     740        $allowed_html = array(
     741            'div' => array(
     742                'data-*' => true,
     743                'on-*' => true,
     744            ),
     745        );
     746
     747        $string = '<div datamelformed-prefix="gone" data="gone" data-="gone" onclick="alert(1)">Malformed attributes</div>';
     748        $expected = '<div>Malformed attributes</div>';
     749
     750        $actual = wp_kses( $string, $allowed_html );
     751
     752        $this->assertSame( $expected, $actual );
     753    }
     754
     755    /**
     756     * Ensure wildcard allows two hyphen.
     757     *
     758     * @ticket 33121
     759     */
     760    function test_wildcard_allows_two_hyphens() {
     761        $allowed_html = array(
     762            'div' => array(
     763                'data-*' => true,
     764            ),
     765        );
     766
     767        $string = '<div data-wp-id="pens-and-pencils">Well formed attribute</div>';
     768        $expected = '<div data-wp-id="pens-and-pencils">Well formed attribute</div>';
     769
     770        $actual = wp_kses( $string, $allowed_html );
     771
     772        $this->assertSame( $expected, $actual );
     773    }
     774
     775    /**
     776     * Ensure wildcard attributes only support valid prefixes.
     777     *
     778     * @dataProvider data_wildcard_attribute_prefixes
     779     *
     780     * @ticket 33121
     781     */
     782    function test_wildcard_attribute_prefixes( $wildcard_attribute, $expected ) {
     783        $allowed_html = array(
     784            'div' => array(
     785                $wildcard_attribute => true,
     786            ),
     787        );
     788
     789        $name = str_replace( '*', strtolower( __FUNCTION__ ), $wildcard_attribute );
     790        $value = __FUNCTION__;
     791        $whole = "{$name}=\"{$value}\"";
     792
     793        $actual = wp_kses_attr_check( $name, $value, $whole, 'n', 'div', $allowed_html );
     794
     795        $this->assertSame( $expected, $actual );
     796    }
     797
     798    /**
     799     * @return array Array of arguments for wildcard testing
     800     *               [0] The prefix being tested.
     801     *               [1] The outcome of `wp_kses_attr_check` for the prefix.
     802     */
     803    function data_wildcard_attribute_prefixes() {
     804        return array(
     805            // Ends correctly
     806            array( 'data-*', true ),
     807
     808            // Does not end with trialing `-`.
     809            array( 'data*', false ),
     810
     811            // Multiple wildcards.
     812            array( 'd*ta-*', false ),
     813            array( 'data**', false ),
     814        );
     815    }
    721816}
  • branches/5.0/tests/phpunit/tests/rest-api/rest-attachments-controller.php

    r43720 r43727  
    929929                // Raw values.
    930930                array(
    931                     'title'   => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
    932                     'description' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
    933                     'caption' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     931                    'title'   => '<a href="#" target="_blank" unfiltered=true>link</a>',
     932                    'description' => '<a href="#" target="_blank" unfiltered=true>link</a>',
     933                    'caption' => '<a href="#" target="_blank" unfiltered=true>link</a>',
    934934                ),
    935935                // Expected returned values.
  • branches/5.0/tests/phpunit/tests/rest-api/rest-posts-controller.php

    r43720 r43727  
    29142914                // Raw values.
    29152915                array(
    2916                     'title'   => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
    2917                     'content' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
    2918                     'excerpt' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     2916                    'title'   => '<a href="#" target="_blank" unfiltered=true>link</a>',
     2917                    'content' => '<a href="#" target="_blank" unfiltered=true>link</a>',
     2918                    'excerpt' => '<a href="#" target="_blank" unfiltered=true>link</a>',
    29192919                ),
    29202920                // Expected returned values.
Note: See TracChangeset for help on using the changeset viewer.