WordPress.org

Make WordPress Core


Ignore:
Timestamp:
10/22/2018 04:03:07 AM (2 years ago)
Author:
pento
Message:

KSES: Allow url() to be used in inline CSS.

The cover image block uses the url() function in its inline CSS, to show the cover image. KSES didn't allow this, causing the block to not save correctly for Author and Contributor users. As KSES does already check each attribute name against an allowed list, we're able to add an extra check for certain attributes to be able to use the url() function, too.

Props peterwilsoncc, azaozz, pento, dd32.
See #45067.

File:
1 edited

Legend:

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

    r43731 r43781  
    17081708 */
    17091709function safecss_filter_attr( $css, $deprecated = '' ) {
    1710     if ( !empty( $deprecated ) )
     1710    if ( ! empty( $deprecated ) ) {
    17111711        _deprecated_argument( __FUNCTION__, '2.8.1' ); // Never implemented
    1712 
    1713     $css = wp_kses_no_null($css);
    1714     $css = str_replace(array("\n","\r","\t"), '', $css);
    1715 
    1716     if ( preg_match( '%[\\\\(&=}]|/\*%', $css ) ) // remove any inline css containing \ ( & } = or comments
    1717         return '';
     1712    }
     1713
     1714    $css = wp_kses_no_null( $css );
     1715    $css = str_replace( array( "\n", "\r", "\t" ), '', $css );
     1716
     1717    $allowed_protocols = wp_allowed_protocols();
    17181718
    17191719    $css_array = explode( ';', trim( $css ) );
     
    17251725     * @since 4.4.0 Added support for `min-height`, `max-height`, `min-width`, and `max-width`.
    17261726     * @since 4.6.0 Added support for `list-style-type`.
     1727     * @since 5.0.0 Added support for `background-image`.
    17271728     *
    17281729     * @param array $attr List of allowed CSS attributes.
     
    17311732        'background',
    17321733        'background-color',
     1734        'background-image',
    17331735
    17341736        'border',
     
    17991801    ) );
    18001802
    1801     if ( empty($allowed_attr) )
     1803
     1804    /*
     1805     * CSS attributes that accept URL data types.
     1806     *
     1807     * This is in accordance to the CSS spec and unrelated to
     1808     * the sub-set of supported attributes above.
     1809     *
     1810     * See: https://developer.mozilla.org/en-US/docs/Web/CSS/url
     1811     */
     1812    $css_url_data_types = array(
     1813        'background',
     1814        'background-image',
     1815
     1816        'cursor',
     1817
     1818        'list-style',
     1819        'list-style-image',
     1820    );
     1821
     1822    if ( empty( $allowed_attr ) ) {
    18021823        return $css;
     1824    }
    18031825
    18041826    $css = '';
    18051827    foreach ( $css_array as $css_item ) {
    1806         if ( $css_item == '' )
     1828        if ( $css_item == '' ) {
    18071829            continue;
    1808         $css_item = trim( $css_item );
    1809         $found = false;
     1830        }
     1831
     1832        $css_item        = trim( $css_item );
     1833        $css_test_string = $css_item;
     1834        $found           = false;
     1835        $url_attr        = false;
     1836
    18101837        if ( strpos( $css_item, ':' ) === false ) {
    18111838            $found = true;
    18121839        } else {
    1813             $parts = explode( ':', $css_item );
    1814             if ( in_array( trim( $parts[0] ), $allowed_attr ) )
     1840            $parts = explode( ':', $css_item, 2 );
     1841            $css_selector = trim( $parts[0] );
     1842
     1843            if ( in_array( $css_selector, $allowed_attr, true ) ) {
    18151844                $found = true;
     1845                $url_attr = in_array( $css_selector, $css_url_data_types, true );
     1846            }
    18161847        }
    1817         if ( $found ) {
    1818             if( $css != '' )
     1848
     1849        if ( $found && $url_attr ) {
     1850            // Simplified: matches the sequence `url(*)`.
     1851            preg_match_all( '/url\([^)]+\)/', $parts[1], $url_matches );
     1852
     1853            foreach ( $url_matches[0] as $url_match ) {
     1854                // Clean up the URL from each of the matches above.
     1855                preg_match( '/^url\(\s*([\'\"]?)(.*)(\g1)\s*\)$/', $url_match, $url_pieces );
     1856
     1857                if ( empty( $url_pieces[2] ) ) {
     1858                    $found = false;
     1859                    break;
     1860                }
     1861
     1862                $url = trim( $url_pieces[2] );
     1863
     1864                if ( empty( $url ) || $url !== wp_kses_bad_protocol( $url, $allowed_protocols ) ) {
     1865                    $found = false;
     1866                    break;
     1867                } else {
     1868                    // Remove the whole `url(*)` bit that was matched above from the CSS.
     1869                    $css_test_string = str_replace( $url_match, '', $css_test_string );
     1870                }
     1871            }
     1872        }
     1873
     1874        // Remove any CSS containing containing \ ( & } = or comments, except for url() useage checked above.
     1875        if ( $found && ! preg_match( '%[\\\(&=}]|/\*%', $css_test_string ) ) {
     1876            if ( $css != '' ) {
    18191877                $css .= ';';
     1878            }
     1879
    18201880            $css .= $css_item;
    18211881        }
Note: See TracChangeset for help on using the changeset viewer.