WordPress.org

Make WordPress Core

Changeset 29362


Ignore:
Timestamp:
08/02/2014 08:08:52 PM (7 years ago)
Author:
azaozz
Message:

Add blog_id to the wp-settings-* cookie (used for storing user state) to prevent it being overloaded on sub-domain sites. Fixes #29095.

Location:
trunk/src/wp-includes
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/js/utils.js

    r26203 r29362  
    44
    55var wpCookies = {
    6 // The following functions are from Cookie.js class in TinyMCE, Moxiecode, used under LGPL.
    7 
    8     each : function(obj, cb, scope) {
     6// The following functions are from Cookie.js class in TinyMCE 3, Moxiecode, used under LGPL.
     7
     8    each: function( obj, cb, scope ) {
    99        var n, l;
    1010
    11         if ( !obj )
     11        if ( ! obj ) {
    1212            return 0;
     13        }
    1314
    1415        scope = scope || obj;
    1516
    16         if ( typeof(obj.length) != 'undefined' ) {
     17        if ( typeof( obj.length ) !== 'undefined' ) {
    1718            for ( n = 0, l = obj.length; n < l; n++ ) {
    18                 if ( cb.call(scope, obj[n], n, obj) === false )
     19                if ( cb.call( scope, obj[n], n, obj ) === false ) {
    1920                    return 0;
     21                }
    2022            }
    2123        } else {
    2224            for ( n in obj ) {
    2325                if ( obj.hasOwnProperty(n) ) {
    24                     if ( cb.call(scope, obj[n], n, obj) === false ) {
     26                    if ( cb.call( scope, obj[n], n, obj ) === false ) {
    2527                        return 0;
    2628                    }
     
    3537     * Returns a JS object with the name: 'value' pairs.
    3638     */
    37     getHash : function(name) {
    38         var all = this.get(name), ret;
    39 
    40         if ( all ) {
    41             this.each( all.split('&'), function(pair) {
     39    getHash: function( name ) {
     40        var cookie = this.get( name ), values;
     41
     42        if ( cookie ) {
     43            this.each( cookie.split('&'), function( pair ) {
    4244                pair = pair.split('=');
    43                 ret = ret || {};
    44                 ret[pair[0]] = pair[1];
     45                values = values || {};
     46                values[pair[0]] = pair[1];
    4547            });
    4648        }
    47         return ret;
     49
     50        return values;
    4851    },
    4952
     
    5356     * 'values_obj' is the JS object that is stored. It is encoded as URI in wpCookies.set().
    5457     */
    55     setHash : function(name, values_obj, expires, path, domain, secure) {
     58    setHash: function( name, values_obj, expires, path, domain, secure ) {
    5659        var str = '';
    5760
    58         this.each(values_obj, function(val, key) {
    59             str += (!str ? '' : '&') + key + '=' + val;
     61        this.each( values_obj, function( val, key ) {
     62            str += ( ! str ? '' : '&' ) + key + '=' + val;
    6063        });
    6164
    62         this.set(name, str, expires, path, domain, secure);
     65        this.set( name, str, expires, path, domain, secure );
    6366    },
    6467
     
    6669     * Get a cookie.
    6770     */
    68     get : function(name) {
     71    get: function( name ) {
    6972        var e, b,
    7073            cookie = document.cookie,
    7174            p = name + '=';
    7275
    73         if ( !cookie )
     76        if ( ! cookie ) {
    7477            return;
    75 
    76         b = cookie.indexOf('; ' + p);
    77 
    78         if ( b == -1 ) {
     78        }
     79
     80        b = cookie.indexOf( '; ' + p );
     81
     82        if ( b === -1 ) {
    7983            b = cookie.indexOf(p);
    8084
    81             if ( b !== 0 )
     85            if ( b !== 0 ) {
    8286                return null;
    83 
     87            }
    8488        } else {
    8589            b += 2;
     
    8892        e = cookie.indexOf( ';', b );
    8993
    90         if ( e == -1 )
     94        if ( e === -1 ) {
    9195            e = cookie.length;
    92 
    93         return decodeURIComponent( cookie.substring(b + p.length, e) );
     96        }
     97
     98        return decodeURIComponent( cookie.substring( b + p.length, e ) );
    9499    },
    95100
     
    100105     * or the number of seconds until expiration
    101106     */
    102     set : function(name, value, expires, path, domain, secure) {
     107    set: function( name, value, expires, path, domain, secure ) {
    103108        var d = new Date();
    104109
    105         if ( typeof(expires) == 'object' && expires.toGMTString ) {
     110        if ( typeof( expires ) === 'object' && expires.toGMTString ) {
    106111            expires = expires.toGMTString();
    107         } else if ( parseInt(expires, 10) ) {
    108             d.setTime( d.getTime() + ( parseInt(expires, 10) * 1000 ) ); // time must be in miliseconds
     112        } else if ( parseInt( expires, 10 ) ) {
     113            d.setTime( d.getTime() + ( parseInt( expires, 10 ) * 1000 ) ); // time must be in miliseconds
    109114            expires = d.toGMTString();
    110115        } else {
     
    124129     * This is done by setting it to an empty value and setting the expiration time in the past.
    125130     */
    126     remove : function(name, path) {
    127         this.set(name, '', -1000, path);
     131    remove: function( name, path ) {
     132        this.set( name, '', -1000, path );
    128133    }
    129134};
     
    131136// Returns the value as string. Second arg or empty string is returned when value is not set.
    132137function getUserSetting( name, def ) {
    133     var obj = getAllUserSettings();
    134 
    135     if ( obj.hasOwnProperty(name) )
    136         return obj[name];
    137 
    138     if ( typeof def != 'undefined' )
     138    var settings = getAllUserSettings();
     139
     140    if ( settings.hasOwnProperty( name ) ) {
     141        return settings[name];
     142    }
     143
     144    if ( typeof def !== 'undefined' ) {
    139145        return def;
     146    }
    140147
    141148    return '';
     
    144151// Both name and value must be only ASCII letters, numbers or underscore
    145152// and the shorter, the better (cookies can store maximum 4KB). Not suitable to store text.
     153// The value is converted and stored as string.
    146154function setUserSetting( name, value, _del ) {
    147     if ( 'object' !== typeof userSettings )
     155    if ( 'object' !== typeof userSettings ) {
    148156        return false;
    149 
    150     var cookie = 'wp-settings-' + userSettings.uid, all = wpCookies.getHash(cookie) || {}, path = userSettings.url,
    151     n = name.toString().replace(/[^A-Za-z0-9_]/, ''), v = value.toString().replace(/[^A-Za-z0-9_]/, '');
     157    }
     158
     159    var uid = userSettings.uid,
     160        oldUid = uid.lastIndexOf('-') > 0 ? uid.substring( 0, uid.lastIndexOf('-') ) : 0,
     161        settings = wpCookies.getHash( 'wp-settings-' + uid ),
     162        path = userSettings.url;
     163
     164    name = name.toString().replace( /[^A-Za-z0-9_]/, '' );
     165
     166    if ( typeof value === 'number' ) {
     167        value = parseInt( value, 10 );
     168    } else {
     169        value = value.toString().replace( /[^A-Za-z0-9_]/, '' );
     170    }
     171
     172    if ( oldUid ) {
     173        if ( ! settings ) {
     174            settings = wpCookies.getHash( 'wp-settings-' + oldUid );
     175        }
     176        // Delete old cookies
     177        if ( wpCookies.get( 'wp-settings-time-' + oldUid ) ) {
     178            wpCookies.remove( 'wp-settings-' + oldUid, path );
     179            wpCookies.remove( 'wp-settings-time-' + oldUid, path );
     180        }
     181    }
     182
     183    settings = settings || {};
    152184
    153185    if ( _del ) {
    154         delete all[n];
     186        delete settings[name];
    155187    } else {
    156         all[n] = v;
    157     }
    158 
    159     wpCookies.setHash(cookie, all, 31536000, path);
    160     wpCookies.set('wp-settings-time-'+userSettings.uid, userSettings.time, 31536000, path);
     188        settings[name] = value;
     189    }
     190
     191    wpCookies.setHash( 'wp-settings-' + uid, settings, 31536000, path );
     192    wpCookies.set( 'wp-settings-time-' + uid, userSettings.time, 31536000, path );
    161193
    162194    return name;
     
    169201// Returns all settings as js object.
    170202function getAllUserSettings() {
    171     if ( 'object' !== typeof userSettings )
     203    if ( 'object' !== typeof userSettings ) {
    172204        return {};
    173 
    174     return wpCookies.getHash('wp-settings-' + userSettings.uid) || {};
    175 }
     205    }
     206
     207    var uid = userSettings.uid,
     208        settings = wpCookies.getHash( 'wp-settings-' + uid );
     209
     210    // Try the old format cookie
     211    if ( ! settings && uid.lastIndexOf('-') > 0 ) {
     212        uid = uid.substring( 0, uid.lastIndexOf('-') );
     213        settings = wpCookies.getHash( 'wp-settings-' + uid );
     214    }
     215
     216    return settings || {};
     217}
  • trunk/src/wp-includes/option.php

    r29311 r29362  
    714714function wp_user_settings() {
    715715
    716     if ( ! is_admin() )
     716    if ( ! is_admin() || defined( 'DOING_AJAX' ) ) {
    717717        return;
    718 
    719     if ( defined('DOING_AJAX') )
     718    }
     719
     720    if ( ! $user_id = get_current_user_id() ) {
    720721        return;
    721 
    722     if ( ! $user_id = get_current_user_id() )
     722    }
     723
     724    if ( is_super_admin() && ! is_user_member_of_blog() ) {
    723725        return;
    724 
    725     if ( is_super_admin() && ! is_user_member_of_blog() )
    726         return;
     726    }
    727727
    728728    $settings = (string) get_user_option( 'user-settings', $user_id );
    729 
    730     if ( isset( $_COOKIE['wp-settings-' . $user_id] ) ) {
    731         $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $user_id] );
     729    $uid = $user_id . '-' . get_current_blog_id();
     730
     731    if ( isset( $_COOKIE['wp-settings-' . $uid] ) ) {
     732        $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $uid] );
    732733
    733734        // No change or both empty
     
    736737
    737738        $last_saved = (int) get_user_option( 'user-settings-time', $user_id );
    738         $current = isset( $_COOKIE['wp-settings-time-' . $user_id]) ? preg_replace( '/[^0-9]/', '', $_COOKIE['wp-settings-time-' . $user_id] ) : 0;
     739        $current = isset( $_COOKIE['wp-settings-time-' . $uid]) ? preg_replace( '/[^0-9]/', '', $_COOKIE['wp-settings-time-' . $uid] ) : 0;
    739740
    740741        // The cookie is newer than the saved value. Update the user_option and leave the cookie as-is
     
    748749    // The cookie is not set in the current browser or the saved value is newer.
    749750    $secure = ( 'https' === parse_url( site_url(), PHP_URL_SCHEME ) );
    750     setcookie( 'wp-settings-' . $user_id, $settings, time() + YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN, $secure );
    751     setcookie( 'wp-settings-time-' . $user_id, time(), time() + YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN, $secure );
    752     $_COOKIE['wp-settings-' . $user_id] = $settings;
     751    setcookie( 'wp-settings-' . $uid, $settings, time() + YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN, $secure );
     752    setcookie( 'wp-settings-time-' . $uid, time(), time() + YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN, $secure );
     753    $_COOKIE['wp-settings-' . $uid] = $settings;
    753754}
    754755
     
    782783function set_user_setting( $name, $value ) {
    783784
    784     if ( headers_sent() )
     785    if ( headers_sent() ) {
    785786        return false;
     787    }
    786788
    787789    $all_user_settings = get_all_user_settings();
     
    804806function delete_user_setting( $names ) {
    805807
    806     if ( headers_sent() )
     808    if ( headers_sent() ) {
    807809        return false;
     810    }
    808811
    809812    $all_user_settings = get_all_user_settings();
     
    818821    }
    819822
    820     if ( $deleted )
     823    if ( $deleted ) {
    821824        return wp_set_all_user_settings( $all_user_settings );
     825    }
    822826
    823827    return false;
     
    834838    global $_updated_user_settings;
    835839
    836     if ( ! $user_id = get_current_user_id() )
     840    if ( ! $user_id = get_current_user_id() ) {
    837841        return array();
    838 
    839     if ( isset( $_updated_user_settings ) && is_array( $_updated_user_settings ) )
     842    }
     843
     844    if ( isset( $_updated_user_settings ) && is_array( $_updated_user_settings ) ) {
    840845        return $_updated_user_settings;
     846    }
    841847
    842848    $user_settings = array();
    843     if ( isset( $_COOKIE['wp-settings-' . $user_id] ) ) {
     849    $uid = $user_id . '-' . get_current_blog_id();
     850
     851    if ( isset( $_COOKIE['wp-settings-' . $uid] ) ) {
     852        $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $uid] );
     853    } elseif ( isset( $_COOKIE['wp-settings-' . $user_id] ) ) {
    844854        $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $user_id] );
    845 
    846         if ( $cookie && strpos( $cookie, '=' ) ) // '=' cannot be 1st char
    847             parse_str( $cookie, $user_settings );
    848 
     855    }
     856
     857    if ( ! empty( $cookie ) && strpos( $cookie, '=' ) ) { // '=' cannot be 1st char
     858        parse_str( $cookie, $user_settings );
    849859    } else {
    850860        $option = get_user_option( 'user-settings', $user_id );
    851         if ( $option && is_string($option) )
     861        if ( $option && is_string( $option ) )
    852862            parse_str( $option, $user_settings );
    853863    }
     
    868878    global $_updated_user_settings;
    869879
    870     if ( ! $user_id = get_current_user_id() )
     880    if ( ! $user_id = get_current_user_id() ) {
    871881        return false;
    872 
    873     if ( is_super_admin() && ! is_user_member_of_blog() )
     882    }
     883
     884    if ( is_super_admin() && ! is_user_member_of_blog() ) {
    874885        return;
     886    }
    875887
    876888    $settings = '';
     
    879891        $_value = preg_replace( '/[^A-Za-z0-9_]+/', '', $value );
    880892
    881         if ( ! empty( $_name ) )
     893        if ( ! empty( $_name ) ) {
    882894            $settings .= $_name . '=' . $_value . '&';
    883     }
    884 
    885     $settings = rtrim($settings, '&');
     895        }
     896    }
     897
     898    $settings = rtrim( $settings, '&' );
    886899    parse_str( $settings, $_updated_user_settings );
    887900
     
    898911 */
    899912function delete_all_user_settings() {
    900     if ( ! $user_id = get_current_user_id() )
     913    if ( ! $user_id = get_current_user_id() ) {
    901914        return;
    902 
     915    }
     916
     917    $uid = $user_id . '-' . get_current_blog_id();
    903918    update_user_option( $user_id, 'user-settings', '', false );
    904     setcookie('wp-settings-' . $user_id, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH);
     919    setcookie( 'wp-settings-' . $uid, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH );
    905920}
    906921
  • trunk/src/wp-includes/script-loader.php

    r29049 r29362  
    7373    did_action( 'init' ) && $scripts->localize( 'utils', 'userSettings', array(
    7474        'url' => (string) SITECOOKIEPATH,
    75         'uid' => (string) get_current_user_id(),
     75        'uid' => get_current_user_id() . '-' . get_current_blog_id(),
    7676        'time' => (string) time(),
    7777    ) );
Note: See TracChangeset for help on using the changeset viewer.