WordPress.org

Make WordPress Core

Changeset 10297


Ignore:
Timestamp:
01/04/2009 10:25:50 PM (12 years ago)
Author:
azaozz
Message:

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

    r10236 r10297  
    9797}
    9898
    99 // from php.net
    100 if ( !function_exists('htmlspecialchars_decode') ) {
     99if ( !function_exists( 'htmlspecialchars_decode' ) ) {
     100    // Added in PHP 5.1.0
     101    // from php.net (modified by Sam Bauers to deal with some quirks in HTML_SPECIALCHARS constant)
    101102    function htmlspecialchars_decode( $str, $quote_style = ENT_COMPAT ) {
    102         return strtr( $str, array_flip( get_html_translation_table(HTML_SPECIALCHARS, $quote_style) ) );
    103     }
     103        $table = array_flip( get_html_translation_table( HTML_SPECIALCHARS, $quote_style ) );
     104        $table = array_merge( array( ''' => "'" ), $table, array( '&' => "&", '&' => "&" ) );
     105        return strtr( $str, $table );
     106    }
    104107}
    105108
  • trunk/wp-includes/formatting.php

    r10150 r10297  
    187187 * Converts a number of special characters into their HTML entities.
    188188 *
    189  * Differs from htmlspecialchars as existing HTML entities will not be encoded.
    190189 * Specifically changes: & to &#038;, < to &lt; and > to &gt;.
    191190 *
    192  * $quotes can be set to 'single' to encode ' to &#039;, 'double' to encode " to
    193  * &quot;, or '1' to do both. Default is 0 where no quotes are encoded.
     191 * $quote_style can be set to ENT_COMPAT to encode " to
     192 * &quot;, or ENT_QUOTES to do both. Default is ENT_NOQUOTES where no quotes are encoded.
    194193 *
    195194 * @since 1.2.2
    196195 *
    197  * @param string $text The text which is to be encoded.
    198  * @param mixed $quotes Optional. Converts single quotes if set to 'single', double if set to 'double' or both if otherwise set. Default 0.
     196 * @param string $string The text which is to be encoded.
     197 * @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 values; converting single quotes if set to 'single', double if set to 'double' or both if otherwise set. Default is ENT_NOQUOTES.
     198 * @param string $charset Optional. The character encoding of the string. Default is false.
     199 * @param boolean $double_encode Optional. Whether or not to encode existing html entities. Default is false.
    199200 * @return string The encoded text with HTML entities.
    200201 */
    201 function wp_specialchars( $text, $quotes = 0 ) {
    202     // Like htmlspecialchars except don't double-encode HTML entities
    203     $text = str_replace('&&', '&#038;&', $text);
    204     $text = str_replace('&&', '&#038;&', $text);
    205     $text = preg_replace('/&(?:$|([^#])(?![a-z1-4]{1,8};))/', '&#038;$1', $text);
    206     $text = str_replace('<', '&lt;', $text);
    207     $text = str_replace('>', '&gt;', $text);
    208     if ( 'double' === $quotes ) {
    209         $text = str_replace('"', '&quot;', $text);
    210     } elseif ( 'single' === $quotes ) {
    211         $text = str_replace("'", '&#039;', $text);
    212     } elseif ( $quotes ) {
    213         $text = str_replace('"', '&quot;', $text);
    214         $text = str_replace("'", '&#039;', $text);
    215     }
    216     return $text;
     202function wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) {
     203    if ( 0 === strlen( $string ) ) {
     204        return '';
     205    }
     206
     207    if ( !$charset ) {
     208        $alloptions = wp_load_alloptions();
     209        $charset = isset( $alloptions['blog_charset'] ) ? $alloptions['blog_charset'] : '';
     210    }
     211    if ( in_array( $charset, array( 'utf8', 'utf-8', 'UTF8' ) ) ) {
     212        $charset = 'UTF-8';
     213    }
     214
     215    // Backwards compatibility
     216    switch ( $quote_style ) {
     217        // Handle expected values first for speed
     218        case ENT_NOQUOTES:
     219            $_quote_style = ENT_NOQUOTES;
     220            break;
     221        case ENT_COMPAT:
     222            $_quote_style = ENT_COMPAT;
     223            break;
     224        case ENT_QUOTES:
     225            $_quote_style = ENT_QUOTES;
     226            break;
     227        // Old values
     228        case false:
     229        case 0:
     230        case '':
     231        case null:
     232        case 'single':
     233            $_quote_style = ENT_NOQUOTES;
     234            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 );
     255    }
     256
     257    // Backwards compatibility
     258    if ( 'single' === $quote_style ) {
     259        $string = str_replace( "'", '&#039;', $string );
     260    }
     261
     262    return $string;
     263}
     264
     265/**
     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.
     270 *
     271 * @since 2.8
     272 *
     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 */
     279function wp_entities( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) {
     280    if ( 0 === strlen( $string ) ) {
     281        return '';
     282    }
     283
     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;
     305}
     306
     307/**
     308 * Checks for invalid UTF8 in a string.
     309 *
     310 * @since 2.8
     311 *
     312 * @param string $string The text which is to be checked.
     313 * @param boolean $strip Optional. Whether to attempt to strip out invalid UTF8. Default is false.
     314 * @return string The checked text.
     315 */
     316function wp_check_invalid_utf8( $string, $strip = false ) {
     317    if ( 0 === strlen( $string ) ) {
     318        return '';
     319    }
     320
     321    if ( !in_array( get_option( 'blog_charset' ), array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ) ) {
     322        return $string;
     323    }
     324
     325    // preg_match fails when it encounters invalid UTF8 in $string
     326    if ( 1 === @preg_match( '@^.@us', $string ) ) {
     327        return $string;
     328    }
     329
     330    if ( $strip && function_exists( 'iconv' ) ) {
     331        return iconv( 'utf-8', 'utf-8', $string );
     332    } else {
     333        return '';
     334    }
    217335}
    218336
     
    17571875 * @return string
    17581876 */
    1759 function attribute_escape($text) {
    1760     $safe_text = wp_specialchars($text, true);
    1761     return apply_filters('attribute_escape', $safe_text, $text);
     1877function attribute_escape( $text ) {
     1878    $safe_text = wp_check_invalid_utf8( $text );
     1879    $safe_text = wp_entities( $safe_text, ENT_QUOTES );
     1880    return apply_filters( 'attribute_escape', $safe_text, $text );
    17621881}
    17631882
Note: See TracChangeset for help on using the changeset viewer.