WordPress.org

Make WordPress Core

Changeset 10298


Ignore:
Timestamp:
01/04/2009 11:37:47 PM (9 years ago)
Author:
azaozz
Message:

Latest version of the patch for refactor filters to avoid potential XSS attacks, props sambauers and DD32, see #8767

Location:
trunk/wp-includes
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/compat.php

    r10297 r10298  
    9999if ( !function_exists( 'htmlspecialchars_decode' ) ) {
    100100    // Added in PHP 5.1.0
    101     // from php.net (modified by Sam Bauers to deal with some quirks in HTML_SPECIALCHARS constant)
    102     function htmlspecialchars_decode( $str, $quote_style = ENT_COMPAT ) {
    103         $table = array_flip( get_html_translation_table( HTML_SPECIALCHARS, $quote_style ) );
    104         $table = array_merge( array( ''' => "'" ), $table, array( '&' => "&", '&' => "&" ) );
    105         return strtr( $str, $table );
     101    // Error checks from PEAR::PHP_Compat
     102    function htmlspecialchars_decode( $str, $quote_style = ENT_COMPAT )
     103    {
     104        if ( !is_scalar( $string ) ) {
     105            trigger_error( 'htmlspecialchars_decode() expects parameter 1 to be string, ' . gettype( $string ) . ' given', E_USER_WARNING );
     106            return;
     107        }
     108
     109        if ( !is_int( $quote_style ) && $quote_style !== null ) {
     110            trigger_error( 'htmlspecialchars_decode() expects parameter 2 to be integer, ' . gettype( $quote_style ) . ' given', E_USER_WARNING );
     111            return;
     112        }
     113
     114        return wp_specialchars_decode( $str, $quote_style );
    106115    }
    107116}
  • trunk/wp-includes/formatting.php

    r10297 r10298  
    187187 * Converts a number of special characters into their HTML entities.
    188188 *
    189  * Specifically changes: & to &#038;, < to &lt; and > to &gt;.
     189 * Specifically deals with: &, <, >, ", and '.
    190190 *
    191191 * $quote_style can be set to ENT_COMPAT to encode " to
     
    200200 * @return string The encoded text with HTML entities.
    201201 */
    202 function wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) {
     202function wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false )
     203{
     204    $string = (string) $string;
     205
    203206    if ( 0 === strlen( $string ) ) {
    204207        return '';
     
    213216    }
    214217
    215     // Backwards compatibility
    216218    switch ( $quote_style ) {
    217         // Handle expected values first for speed
    218         case ENT_NOQUOTES:
    219             $_quote_style = ENT_NOQUOTES;
     219        case ENT_QUOTES:
     220        default:
     221            $quote_style = ENT_QUOTES;
     222            $_quote_style = ENT_QUOTES;
    220223            break;
    221224        case ENT_COMPAT:
     225        case 'double':
     226            $quote_style = ENT_COMPAT;
    222227            $_quote_style = ENT_COMPAT;
    223228            break;
    224         case ENT_QUOTES:
    225             $_quote_style = ENT_QUOTES;
     229        case 'single':
     230            $quote_style = ENT_NOQUOTES;
     231            $_quote_style = 'single';
    226232            break;
    227         // Old values
     233        case ENT_NOQUOTES:
    228234        case false:
    229235        case 0:
    230236        case '':
    231237        case null:
    232         case 'single':
     238            $quote_style = ENT_NOQUOTES;
    233239            $_quote_style = ENT_NOQUOTES;
    234240            break;
    235         case 'double':
    236             $_quote_style = ENT_COMPAT;
    237             break;
    238         default:
    239             $_quote_style = ENT_QUOTES;
    240             break;
    241     }
    242 
    243     if ( version_compare( PHP_VERSION, '5.2.3', '>=' ) ) {
    244         $string = htmlspecialchars( $string, $_quote_style, $charset, $double_encode );
    245     } else {
    246         // Handle double encoding for PHP versions that don't support it in htmlspecialchars()
    247         if ( !$double_encode ) {
    248             $string = htmlspecialchars_decode( $string, $_quote_style );
    249             // Backwards compatibility
    250             if ( 'single' === $quote_style ) {
    251                 $string = str_replace( array( '&#039;', '&#39;' ), "'", $string );
    252             }
    253         }
    254         $string = htmlspecialchars( $string, $_quote_style, $charset );
     241    }
     242
     243    // Handle double encoding ourselves
     244    if ( !$double_encode ) {
     245        $string = wp_specialchars_decode( $string, $_quote_style );
     246        $string = preg_replace( '/&(#?x?[0-9]+|[a-z]+);/i', '|wp_entity|$1|/wp_entity|', $string );
     247    }
     248
     249    $string = htmlspecialchars( $string, $quote_style, $charset );
     250
     251    // Handle double encoding ourselves
     252    if ( !$double_encode ) {
     253        $string = str_replace( array( '|wp_entity|', '|/wp_entity|' ), array( '&', ';' ), $string );
    255254    }
    256255
    257256    // Backwards compatibility
    258     if ( 'single' === $quote_style ) {
     257    if ( 'single' === $_quote_style ) {
    259258        $string = str_replace( "'", '&#039;', $string );
    260259    }
     
    264263
    265264/**
    266  * Converts all special characters into their HTML entities.
    267  *
    268  * $quote_style can be set to ENT_COMPAT to encode " to
    269  * &quot;, or ENT_QUOTES to do both. Default is ENT_NOQUOTES where no quotes are encoded.
     265 * Converts a number of HTML entities into their special characters.
     266 *
     267 * Specifically deals with: &, <, >, ", and '.
     268 *
     269 * $quote_style can be set to ENT_COMPAT to decode " entities,
     270 * or ENT_QUOTES to do both " and '. Default is ENT_NOQUOTES where no quotes are decoded.
    270271 *
    271272 * @since 2.8
    272273 *
    273  * @param string $string The text which is to be encoded.
    274  * @param mixed $quote_style Optional. Converts double quotes if set to ENT_COMPAT, both single and double if set to ENT_QUOTES or none if set to ENT_NOQUOTES. Default is ENT_NOQUOTES.
    275  * @param string $charset Optional. The character encoding of the string. Default is false.
    276  * @param boolean $double_encode Optional. Whether or not to encode existing html entities. Default is false.
    277  * @return string The encoded text with HTML entities.
    278  */
    279 function wp_entities( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) {
     274 * @param string $string The text which is to be decoded.
     275 * @param mixed $quote_style Optional. Converts double quotes if set to ENT_COMPAT, both single and double if set to ENT_QUOTES or none if set to ENT_NOQUOTES. Also compatible with old wp_specialchars() values; converting single quotes if set to 'single', double if set to 'double' or both if otherwise set. Default is ENT_NOQUOTES.
     276 * @return string The decoded text without HTML entities.
     277 */
     278function wp_specialchars_decode( $string, $quote_style = ENT_NOQUOTES )
     279{
     280    $string = (string) $string;
     281
    280282    if ( 0 === strlen( $string ) ) {
    281283        return '';
    282284    }
    283285
    284     if ( !$charset ) {
    285         $charset = get_option( 'blog_charset' );
    286     }
    287     if ( in_array( $charset, array( 'utf8', 'utf-8', 'UTF8' ) ) ) {
    288         $charset = 'UTF-8';
    289     }
    290 
    291     if ( version_compare( PHP_VERSION, '5.2.3', '>=' ) ) {
    292         $string = htmlentities( $string, $quote_style, $charset, $double_encode );
    293     } else {
    294         // Handle double encoding for PHP versions that don't support it in htmlentities()
    295         if ( !$double_encode ) {
    296             // Multi-byte charsets are not supported below PHP 5.0.0
    297             // 'cp866', 'cp1251', 'KOI8-R' charsets are not supported below PHP 4.3.2
    298             $string = html_entity_decode( $string, $quote_style, $charset );
    299         }
    300         // 'cp866', 'cp1251', 'KOI8-R' charsets are not supported below PHP 4.3.2
    301         $string = htmlentities( $string, $quote_style, $charset );
    302     }
    303 
    304     return $string;
     286    // More complete than get_html_translation_table( HTML_SPECIALCHARS )
     287    $single = array( '&#039;'  => '\'', '&#x27;' => '\'' );
     288    $single_preg = array( '/&#0*39;/'  => '&#039;', '/&#x0*27;/i' => '&#x27;' );
     289    $double = array( '&quot;' => '"', '&#034;'  => '"', '&#x22;' => '"' );
     290    $double_preg = array( '/&#0*34;/'  => '&#034;', '/&#x0*22;/i' => '&#x22;' );
     291    $others = array( '&lt;'   => '<', '&#060;'  => '<', '&gt;'   => '>', '&#062;'  => '>', '&amp;'  => '&', '&#038;'  => '&', '&#x26;' => '&' );
     292    $others_preg = array( '/&#0*60;/'  => '&#060;', '/&#0*62;/'  => '&#062;', '/&#0*38;/'  => '&#038;', '/&#x0*26;/i' => '&#x26;' );
     293
     294    switch ( $quote_style ) {
     295        case ENT_QUOTES:
     296        default:
     297            $translation = array_merge( $single, $double, $others );
     298            $translation_preg = array_merge( $single_preg, $double_preg, $others_preg );
     299            break;
     300        case ENT_COMPAT:
     301        case 'double':
     302            $translation = array_merge( $double, $others );
     303            $translation_preg = array_merge( $double_preg, $others_preg );
     304            break;
     305        case 'single':
     306            $translation = array_merge( $single, $others );
     307            $translation_preg = array_merge( $single_preg, $others_preg );
     308            break;
     309        case ENT_NOQUOTES:
     310        case false:
     311        case 0:
     312        case '':
     313        case null:
     314            $translation = $others;
     315            $translation_preg = $others_preg;
     316            break;
     317    }
     318
     319    // Remove zero padding on numeric entities
     320    $string = preg_replace( array_keys( $translation_preg ), array_values( $translation_preg ), $string );
     321
     322    // Replace characters according to translation table
     323    return strtr( $string, $translation );
    305324}
    306325
     
    314333 * @return string The checked text.
    315334 */
    316 function wp_check_invalid_utf8( $string, $strip = false ) {
     335function wp_check_invalid_utf8( $string, $strip = false )
     336{
     337    $string = (string) $string;
     338
    317339    if ( 0 === strlen( $string ) ) {
    318340        return '';
     
    18611883 */
    18621884function js_escape($text) {
    1863     $safe_text = wp_specialchars($text, 'double');
    1864     $safe_text = preg_replace('/&#(x)?0*(?(1)27|39);?/i', "'", stripslashes($safe_text));
    1865     $safe_text = preg_replace("/\r?\n/", "\\n", addslashes($safe_text));
    1866     return apply_filters('js_escape', $safe_text, $text);
     1885    $safe_text = wp_check_invalid_utf8( $text );
     1886    $safe_text = wp_specialchars( $safe_text, ENT_COMPAT );
     1887    $safe_text = preg_replace( '/&#(x)?0*(?(1)27|39);?/i', "'", stripslashes( $safe_text ) );
     1888    $safe_text = preg_replace( "/\r?\n/", "\\n", addslashes( $safe_text ) );
     1889    return apply_filters( 'js_escape', $safe_text, $text );
    18671890}
    18681891
     
    18771900function attribute_escape( $text ) {
    18781901    $safe_text = wp_check_invalid_utf8( $text );
    1879     $safe_text = wp_entities( $safe_text, ENT_QUOTES );
     1902    $safe_text = wp_specialchars( $safe_text, ENT_QUOTES );
    18801903    return apply_filters( 'attribute_escape', $safe_text, $text );
    18811904}
Note: See TracChangeset for help on using the changeset viewer.