WordPress.org

Make WordPress Core

Ticket #29807: wp_kses_hair.patch

File wp_kses_hair.patch, 5.7 KB (added by drrobotnik, 3 years ago)

wp_kses_hair add srcset and sizes

  • wp-includes/kses.php

     
    913913 * @param array  $allowed_protocols Allowed protocols to keep
    914914 * @return array List of attributes after parsing
    915915 */
    916 function wp_kses_hair($attr, $allowed_protocols) {
     916function wp_kses_hair( $attr, $allowed_protocols ) {
    917917        $attrarr = array();
    918918        $mode = 0;
    919919        $attrname = '';
    920         $uris = array('xmlns', 'profile', 'href', 'src', 'cite', 'classid', 'codebase', 'data', 'usemap', 'longdesc', 'action');
     920        $uris = array( 'xmlns', 'profile', 'href', 'src', 'srcset', 'sizes', 'cite', 'classid', 'codebase', 'data', 'usemap', 'longdesc', 'action' );
    921921
    922922        // Loop through the whole attribute list
    923923
    924         while (strlen($attr) != 0) {
     924        while ( strlen( $attr ) !== 0 ) {
    925925                $working = 0; // Was the last operation successful?
    926926
    927                 switch ($mode) {
     927                switch ( $mode ) {
    928928                        case 0 : // attribute name, href for instance
    929929
    930                                 if ( preg_match('/^([-a-zA-Z:]+)/', $attr, $match ) ) {
     930                                if ( preg_match( '/^([-a-zA-Z:]+)/', $attr, $match ) ) {
    931931                                        $attrname = $match[1];
    932932                                        $working = $mode = 1;
    933933                                        $attr = preg_replace( '/^[-a-zA-Z:]+/', '', $attr );
     
    937937
    938938                        case 1 : // equals sign or valueless ("selected")
    939939
    940                                 if (preg_match('/^\s*=\s*/', $attr)) // equals sign
    941                                         {
     940                                if ( preg_match( '/^\s*=\s*/', $attr ) ) { // equals sign
    942941                                        $working = 1;
    943942                                        $mode = 2;
    944                                         $attr = preg_replace('/^\s*=\s*/', '', $attr);
     943                                        $attr = preg_replace( '/^\s*=\s*/', '', $attr );
    945944                                        break;
    946945                                }
    947946
    948                                 if (preg_match('/^\s+/', $attr)) // valueless
    949                                         {
     947                                if ( preg_match( '/^\s+/', $attr ) ) { // valueless
    950948                                        $working = 1;
    951949                                        $mode = 0;
    952                                         if(false === array_key_exists($attrname, $attrarr)) {
    953                                                 $attrarr[$attrname] = array ('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y');
     950                                        if ( false === array_key_exists( $attrname, $attrarr ) ) {
     951                                                $attrarr[ $attrname ] = array( 'name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y' );
    954952                                        }
    955                                         $attr = preg_replace('/^\s+/', '', $attr);
     953                                        $attr = preg_replace( '/^\s+/', '', $attr );
    956954                                }
    957955
    958956                                break;
     
    959957
    960958                        case 2 : // attribute value, a URL after href= for instance
    961959
    962                                 if (preg_match('%^"([^"]*)"(\s+|/?$)%', $attr, $match))
    963                                         // "value"
    964                                         {
    965                                         $thisval = $match[1];
    966                                         if ( in_array(strtolower($attrname), $uris) )
    967                                                 $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols);
     960                                $scenarios = array(
     961                                        array( '%^"([^"]*)"(\s+|/?$)%', "$attrname=\"$thisval\"", '/^"[^"]*"(\s+|$)/' ), // "value"
     962                                        array( "%^'([^']*)'(\s+|/?$)%", "$attrname='$thisval'", "/^'[^']*'(\s+|$)/" ), // 'value'
     963                                        array( "%^([^\s\"']+)(\s+|/?$)%", "$attrname=\"$thisval\"", "%^[^\s\"']+(\s+|$)%" ), // value
     964                                );
    968965
    969                                         if(false === array_key_exists($attrname, $attrarr)) {
    970                                                 $attrarr[$attrname] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname=\"$thisval\"", 'vless' => 'n');
    971                                         }
    972                                         $working = 1;
    973                                         $mode = 0;
    974                                         $attr = preg_replace('/^"[^"]*"(\s+|$)/', '', $attr);
    975                                         break;
    976                                 }
     966                                foreach ( $scenarios as $key => $scenario ) {
     967                                        if ( preg_match( $scenario[0], $attr, $match ) ) {
     968                                                $thisval = $match[1];
     969                                                if ( in_array( strtolower( $attrname ), $uris, true ) ) {
     970                                                        $thisval = wp_kses_bad_protocol( $thisval, $allowed_protocols );
     971                                                }
    977972
    978                                 if (preg_match("%^'([^']*)'(\s+|/?$)%", $attr, $match))
    979                                         // 'value'
    980                                         {
    981                                         $thisval = $match[1];
    982                                         if ( in_array(strtolower($attrname), $uris) )
    983                                                 $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols);
    984 
    985                                         if(false === array_key_exists($attrname, $attrarr)) {
    986                                                 $attrarr[$attrname] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname='$thisval'", 'vless' => 'n');
     973                                                if ( false === array_key_exists( $attrname, $attrarr ) ) {
     974                                                        $attrarr[ $attrname ] = array( 'name' => $attrname, 'value' => $thisval, 'whole' => $scenario[1], 'vless' => 'n' );
     975                                                }
     976                                                $working = 1;
     977                                                $mode = 0;
     978                                                $attr = preg_replace( $scenario[2], '', $attr );
     979                                                break;
    987980                                        }
    988                                         $working = 1;
    989                                         $mode = 0;
    990                                         $attr = preg_replace("/^'[^']*'(\s+|$)/", '', $attr);
    991                                         break;
    992981                                }
    993982
    994                                 if (preg_match("%^([^\s\"']+)(\s+|/?$)%", $attr, $match))
    995                                         // value
    996                                         {
    997                                         $thisval = $match[1];
    998                                         if ( in_array(strtolower($attrname), $uris) )
    999                                                 $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols);
    1000 
    1001                                         if(false === array_key_exists($attrname, $attrarr)) {
    1002                                                 $attrarr[$attrname] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname=\"$thisval\"", 'vless' => 'n');
    1003                                         }
    1004                                         // We add quotes to conform to W3C's HTML spec.
    1005                                         $working = 1;
    1006                                         $mode = 0;
    1007                                         $attr = preg_replace("%^[^\s\"']+(\s+|$)%", '', $attr);
    1008                                 }
    1009 
    1010983                                break;
    1011984                } // switch
    1012985
    1013                 if ($working == 0) // not well formed, remove and try again
    1014                 {
    1015                         $attr = wp_kses_html_error($attr);
     986                if ( 0 === $working ) { // not well formed, remove and try again
     987                        $attr = wp_kses_html_error( $attr );
    1016988                        $mode = 0;
    1017989                }
    1018990        } // while
    1019991
    1020         if ($mode == 1 && false === array_key_exists($attrname, $attrarr))
    1021                 // special case, for when the attribute list ends with a valueless
    1022                 // attribute like "selected"
    1023                 $attrarr[$attrname] = array ('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y');
     992        // special case, for when the attribute list ends with a valueless
     993        // attribute like "selected"
     994        if ( 1 === $mode && false === array_key_exists( $attrname, $attrarr ) ) {
     995                $attrarr[ $attrname ] = array( 'name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y' );
     996        }
    1024997
    1025998        return $attrarr;
    1026999}