Make WordPress Core

Changeset 10512


Ignore:
Timestamp:
02/05/2009 09:59:37 PM (16 years ago)
Author:
ryan
Message:

Cookie support for HTTP API. Props beaulebens. fixes #9049 #9037 #8727

Location:
trunk/wp-includes
Files:
4 edited

Legend:

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

    r10508 r10512  
    623623    }
    624624    return true;
     625}
     626
     627/**
     628 * Delete a transient
     629 *
     630 * @since 2.8.0
     631 * @package WordPress
     632 * @subpackage Transient
     633 *
     634 * @param string $transient Transient name. Expected to not be SQL-escaped
     635 * @return bool true if successful, false otherwise
     636 */
     637function delete_transient($transient) {
     638    global $_wp_using_ext_object_cache, $wpdb;
     639
     640    if ( $_wp_using_ext_object_cache ) {
     641        return wp_cache_delete($transient, 'transient');
     642    } else {
     643        $transient = '_transient_' . $wpdb->escape($transient);
     644        return delete_option($transient);
     645    }
     646}
     647
     648/**
     649 * Get the value of a transient
     650 *
     651 * If the transient does not exist or does not have a value, then the return value
     652 * will be false.
     653 *
     654 * @since 2.8.0
     655 * @package WordPress
     656 * @subpackage Transient
     657 *
     658 * @param string $transient Transient name. Expected to not be SQL-escaped
     659 * @return mixed Value of transient
     660 */
     661function get_transient($transient) {
     662    global $_wp_using_ext_object_cache, $wpdb;
     663
     664    if ( $_wp_using_ext_object_cache ) {
     665        return wp_cache_get($transient, 'transient');
     666    } else {
     667        $transient = '_transient_' . $wpdb->escape($transient);
     668        return get_option($transient);
     669    }
     670}
     671
     672/**
     673 * Set/update the value of a transient
     674 *
     675 * You do not need to serialize values, if the value needs to be serialize, then
     676 * it will be serialized before it is set.
     677 *
     678 * @since 2.8.0
     679 * @package WordPress
     680 * @subpackage Transient
     681 *
     682 * @param string $transient Transient name. Expected to not be SQL-escaped
     683 * @param mixed $value Transient value.
     684 * @return bool False if value was not set and true if value was set.
     685 */
     686function set_transient($transient, $value) {
     687    global $_wp_using_ext_object_cache, $wpdb;
     688
     689    if ( $_wp_using_ext_object_cache ) {
     690        return wp_cache_set($transient, $value, 'transient');
     691    } else {
     692        $transient = '_transient_' . $transient;
     693        $safe_transient = $wpdb->escape($transient);
     694        if ( false === get_option( $safe_transient ) )
     695            return add_option($transient, $value, '', 'no');
     696        else
     697            return update_option($transient, $value);
     698    }
    625699}
    626700
  • trunk/wp-includes/http.php

    r10509 r10512  
    352352     * @param string $url URI resource.
    353353     * @param str|array $args Optional. Override the defaults.
    354      * @return boolean
     354     * @return array containing 'headers', 'body', 'response', 'cookies'
    355355     */
    356356    function request( $url, $args = array() ) {
     
    400400            unset($r['headers']['user-agent']);
    401401        }
     402       
     403        // Construct Cookie: header if any cookies are set
     404        WP_Http::buildCookieHeader( $r );
    402405
    403406        if( WP_Http_Encoding::is_available() )
     
    425428            do_action('http_api_debug', $transports, 'transports_list');
    426429
    427         $response = array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') );
     430        $response = array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() );
    428431        foreach( (array) $transports as $transport ) {
    429432            $response = $transport->request($url, $r);
    430 
     433           
    431434            if( has_action('http_api_debug') )
    432435                do_action( 'http_api_debug', $response, 'response', get_class($transport) );
     
    520523     *
    521524     * @param string|array $headers
    522      * @return array Processed string headers
     525     * @return array Processed string headers. If duplicate headers are encountered,
     526     *                  Then a numbered array is returned as the value of that header-key.
    523527     */
    524528    function processHeaders($headers) {
     
    528532        $response = array('code' => 0, 'message' => '');
    529533
     534        $cookies = array();
    530535        $newheaders = array();
    531536        foreach ( $headers as $tempheader ) {
     
    542547            list($key, $value) = explode(':', $tempheader, 2);
    543548
    544             if ( ! empty($value) )
    545                 $newheaders[strtolower($key)] = trim($value);
    546         }
    547 
    548         return array('response' => $response, 'headers' => $newheaders);
    549     }
    550 
     549            if ( !empty( $value ) ) {
     550                $key = strtolower( $key );
     551                if ( isset( $newheaders[$key] ) ) {
     552                    $newheaders[$key] = array( $newheaders[$key], trim( $value ) );
     553                } else {
     554                    $newheaders[$key] = trim( $value );
     555                }
     556                if ( 'set-cookie' == strtolower( $key ) )
     557                    $cookies[] = new WP_Http_Cookie( $value );
     558            }
     559        }
     560
     561        return array('response' => $response, 'headers' => $newheaders, 'cookies' => $cookies);
     562    }
     563   
     564    /**
     565     * Takes the arguments for a ::request() and checks for the cookie array.
     566     * If it's found, then it's assumed to contain WP_Http_Cookie objects, which
     567     * are each parsed into strings and added to the Cookie: header (within the
     568     * arguments array). Edits the array by reference.
     569     *
     570     * @access public
     571     * @static
     572     *
     573     * @param array $r Full array of args passed into ::request()
     574     */
     575    function buildCookieHeader( &$r ) {
     576        if ( count( $r['cookies'] ) ) {
     577            $cookies_header = '';
     578            foreach ( $r['cookies'] as $cookie ) {
     579                $cookies_header .= $cookie->getHeaderValue() . '; ';
     580            }
     581            $cookies_header = substr( $cookies_header, 0, -2 );
     582            $r['headers']['cookie'] = $cookies_header;
     583        }
     584    }
     585   
    551586    /**
    552587     * Decodes chunk transfer-encoding, based off the HTTP 1.1 specification.
     
    619654     * @param string $url URI resource.
    620655     * @param str|array $args Optional. Override the defaults.
    621      * @return array 'headers', 'body', and 'response' keys.
     656     * @return array 'headers', 'body', 'cookies' and 'response' keys.
    622657     */
    623658    function request($url, $args = array()) {
     
    638673            unset($r['headers']['user-agent']);
    639674        }
     675
     676        // Construct Cookie: header if any cookies are set
     677        WP_Http::buildCookieHeader( $r );
    640678
    641679        $iError = null; // Store error number
     
    711749        if ( ! $r['blocking'] ) {
    712750            fclose($handle);
    713             return array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') );
     751            return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() );
    714752        }
    715753
     
    746784            $process['body'] = WP_Http_Encoding::decompress( $process['body'] );
    747785
    748         return array('headers' => $arrHeaders['headers'], 'body' => $process['body'], 'response' => $arrHeaders['response']);
     786        return array('headers' => $arrHeaders['headers'], 'body' => $process['body'], 'response' => $arrHeaders['response'], 'cookies' => $arrHeaders['cookies']);
    749787    }
    750788
     
    794832     * @param string $url URI resource.
    795833     * @param str|array $args Optional. Override the defaults.
    796      * @return array 'headers', 'body', and 'response' keys.
     834     * @return array 'headers', 'body', 'cookies' and 'response' keys.
    797835     */
    798836    function request($url, $args = array()) {
     
    803841            'redirection' => 5, 'httpversion' => '1.0',
    804842            'blocking' => true,
    805             'headers' => array(), 'body' => null
     843            'headers' => array(), 'body' => null, 'cookies' => array()
    806844        );
    807845
     
    830868        if ( ! $r['blocking'] ) {
    831869            fclose($handle);
    832             return array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') );
     870            return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() );
    833871        }
    834872
     
    859897            $strResponse = WP_Http_Encoding::decompress( $strResponse );
    860898
    861         return array('headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response']);
     899        return array('headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response'], 'cookies' => $processedHeaders['cookies']);
    862900    }
    863901
     
    898936     * @param string $url
    899937     * @param str|array $args Optional. Override the defaults.
    900      * @return array 'headers', 'body', and 'response' keys.
     938     * @return array 'headers', 'body', 'cookies' and 'response' keys.
    901939     */
    902940    function request($url, $args = array()) {
     
    905943            'redirection' => 5, 'httpversion' => '1.0',
    906944            'blocking' => true,
    907             'headers' => array(), 'body' => null
     945            'headers' => array(), 'body' => null, 'cookies' => array()
    908946        );
    909947
     
    917955            unset($r['headers']['user-agent']);
    918956        }
     957       
     958        // Construct Cookie: header if any cookies are set
     959        WP_Http::buildCookieHeader( $r );
    919960
    920961        $arrURL = parse_url($url);
     
    9691010            stream_set_blocking($handle, 0);
    9701011            fclose($handle);
    971             return array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') );
     1012            return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() );
    9721013        }
    9731014
     
    9891030            $strResponse = WP_Http_Encoding::decompress( $strResponse );
    9901031
    991         return array('headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response']);
     1032        return array('headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response'], 'cookies' => $processedHeaders['cookies']);
    9921033    }
    9931034
     
    10351076     * @param string $url
    10361077     * @param str|array $args Optional. Override the defaults.
    1037      * @return array 'headers', 'body', and 'response' keys.
     1078     * @return array 'headers', 'body', 'cookies' and 'response' keys.
    10381079     */
    10391080    function request($url, $args = array()) {
     
    10421083            'redirection' => 5, 'httpversion' => '1.0',
    10431084            'blocking' => true,
    1044             'headers' => array(), 'body' => null
     1085            'headers' => array(), 'body' => null, 'cookies' => array()
    10451086        );
    10461087
     
    10541095            unset($r['headers']['user-agent']);
    10551096        }
     1097       
     1098        // Construct Cookie: header if any cookies are set
     1099        WP_Http::buildCookieHeader( $r );
    10561100
    10571101        switch ( $r['method'] ) {
     
    10931137
    10941138        if ( ! $r['blocking'] )
    1095             return array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') );
     1139            return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() );
    10961140
    10971141        list($theHeaders, $theBody) = explode("\r\n\r\n", $strResponse, 2);
     
    11121156        $theResponse['message'] = get_status_header_desc($info['response_code']);
    11131157
    1114         return array('headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $theResponse);
     1158        return array('headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $theResponse, 'cookies' => $theHeaders['cookies']);
    11151159    }
    11161160
     
    11491193     * @param string $url
    11501194     * @param str|array $args Optional. Override the defaults.
    1151      * @return array 'headers', 'body', and 'response' keys.
     1195     * @return array 'headers', 'body', 'cookies' and 'response' keys.
    11521196     */
    11531197    function request($url, $args = array()) {
     
    11561200            'redirection' => 5, 'httpversion' => '1.0',
    11571201            'blocking' => true,
    1158             'headers' => array(), 'body' => null
     1202            'headers' => array(), 'body' => null, 'cookies' => array()
    11591203        );
    11601204
     
    11681212            unset($r['headers']['user-agent']);
    11691213        }
     1214       
     1215        // Construct Cookie: header if any cookies are set
     1216        WP_Http::buildCookieHeader( $r );
    11701217
    11711218        // cURL extension will sometimes fail when the timeout is less than 1 as
     
    12041251            curl_setopt( $handle, CURLOPT_FOLLOWLOCATION, true );
    12051252
    1206         if( ! is_null($r['headers']) )
    1207             curl_setopt( $handle, CURLOPT_HTTPHEADER, $r['headers'] );
     1253        if ( !empty( $r['headers'] ) ) {
     1254            // cURL expects full header strings in each element
     1255            $headers = array();
     1256            foreach ( $r['headers'] as $name => $value ) {
     1257                $headers[] = "{$name}: $value";
     1258            }
     1259            curl_setopt( $handle, CURLOPT_HTTPHEADER, $headers );
     1260        }
    12081261
    12091262        if ( $r['httpversion'] == '1.0' )
     
    12171270        do_action_ref_array( 'http_api_curl', array(&$handle) );
    12181271
    1219         // We don't need to return the body, so don't. Just execution request
     1272        // We don't need to return the body, so don't. Just execute request
    12201273        // and return.
    12211274        if ( ! $r['blocking'] ) {
    12221275            curl_exec( $handle );
    12231276            curl_close( $handle );
    1224             return array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') );
     1277            return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() );
    12251278        }
    12261279
     
    12421295                return new WP_Error('http_request_failed', __('Too many redirects.'));
    12431296
    1244             $theHeaders = array( 'headers' => array() );
     1297            $theHeaders = array( 'headers' => array(), 'cookies' => array() );
    12451298            $theBody = '';
    12461299        }
     
    12551308            $theBody = WP_Http_Encoding::decompress( $theBody );
    12561309
    1257         return array('headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $response);
     1310        return array('headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $response, 'cookies' => $theHeaders['cookies']);
    12581311    }
    12591312
     
    12741327}
    12751328
     1329
     1330/**
     1331 * Internal representation of a cookie.
     1332 *
     1333 * Returned cookies are represented using this class, and when cookies are
     1334 * set, if they are not already a WP_Http_Cookie() object, then they are turned
     1335 * into one.
     1336 *
     1337 * @package WordPress
     1338 * @subpackage HTTP
     1339 */
     1340class WP_Http_Cookie {
     1341    var $name,
     1342        $value,
     1343        $expires,
     1344        $path,
     1345        $domain;
     1346   
     1347    /**
     1348     * PHP4 style Constructor - Calls PHP5 Style Constructor
     1349     */
     1350    function WP_Http_Cookie( $data ) {
     1351        return $this->__construct( $data );
     1352    }
     1353   
     1354    /**
     1355     * Sets up this cookie object.
     1356     *
     1357     * @access public
     1358     *
     1359     * @param mixed $data Either an associative array describing the cookie, or a header-string detailing it.
     1360     *      If it's an array, it should include the following elements:
     1361     *          - name
     1362     *          - value [should NOT be urlencoded already]
     1363     *          - expires (optional) String or int (UNIX timestamp)
     1364     *          - path (optional)
     1365     *          - domain (optional)
     1366     */
     1367    function __construct( $data ) {
     1368        if ( is_string( $data ) ) {
     1369            // Assume it's a header string direct from a previous request
     1370            $pairs = explode( ';', $data );
     1371           
     1372            // Special handling for first pair; name=value. Also be careful of "=" in value
     1373            $name  = trim( substr( $pairs[0], 0, strpos( $pairs[0], '=' ) ) );
     1374            $value = substr( $pairs[0], strpos( $pairs[0], '=' ) + 1 );
     1375            $this->name  = $name;
     1376            $this->value = urldecode( $value );
     1377            array_shift( $pairs );
     1378           
     1379            // Set everything else as a property
     1380            foreach ( $pairs as $pair ) {
     1381                list( $key, $val ) = explode( '=', $pair );
     1382                $key = strtolower( trim( $key ) );
     1383                if ( 'expires' == $key )
     1384                    $val = strtotime( $val );
     1385                $this->$key = $val;
     1386            }
     1387        } else {
     1388            // Set properties based directly on parameters
     1389            $this->name    = $data['name'];
     1390            $this->value   = $data['value'];
     1391            $this->expires = is_int( $data['expires'] ) ? $data['expires'] : strtotime( $data['expires'] );
     1392            $this->path    = $data['path'];
     1393            $this->domain  = $data['domain'];
     1394        }
     1395    }
     1396   
     1397    /**
     1398     * Confirms that it's OK to send this cookie to the URL checked against.
     1399     *
     1400     * Decision is based on RFC 2109/2965, so look there for details on validity.
     1401     *
     1402     * @access public
     1403     *
     1404     * @param string $url URL you intend to send this cookie to
     1405     * @return boolean TRUE if allowed, FALSE otherwise.
     1406     */
     1407    function test( $url ) {
     1408        // Expires - if expired then nothing else matters
     1409        if ( time() > $this->expires )
     1410            return false;
     1411       
     1412        // Get details on the URL we're thinking about sending to
     1413        $url = parse_url( $url );
     1414        $url['port'] = isset( $url['port'] ) ? $url['port'] : 80;
     1415        $url['path'] = isset( $url['path'] ) ? $url['path'] : '/';
     1416       
     1417         // Values to use for comparison against the URL
     1418        $path   = isset( $this->path )   ? $this->path   : '/';
     1419        $port   = isset( $this->port )   ? $this->port   : 80;
     1420        $domain = isset( $this->domain ) ? strtolower( $this->domain ) : strtolower( $url['host'] );
     1421        if ( false === stripos( $domain, '.' ) )
     1422            $domain .= '.local';
     1423       
     1424        // Host - very basic check that the request URL ends with the domain restriction (minus leading dot)
     1425        $domain = substr( $domain, 0, 1 ) == '.' ? substr( $domain, 1 ) : $domain;
     1426        if ( substr( $url['host'], -strlen( $domain ) ) != $domain )
     1427            return false;
     1428       
     1429        // Port - supports "port-lists" in the format: "80,8000,8080"
     1430        if ( !in_array( $url['port'], explode( ',', $port) ) )
     1431            return false;
     1432       
     1433        // Path - request path must start with path restriction
     1434        if ( substr( $url['path'], 0, strlen( $path ) ) != $path )
     1435            return false;
     1436       
     1437        return true;
     1438    }
     1439   
     1440    function getHeaderValue() {
     1441        if ( empty( $this->name ) || empty( $this->value ) )
     1442            return '';
     1443       
     1444        return $this->name . '=' . urlencode( $this->value );
     1445    }
     1446   
     1447    function getFullHeader() {
     1448        return 'Cookie: ' . $this->getHeaderValue();
     1449    }
     1450}
     1451
    12761452/**
    12771453 * Returns the initialized WP_Http Object
     
    12971473 *
    12981474 * <code>
    1299  * $res = array( 'headers' => array(), 'response' => array('code', 'message') );
     1475 * $res = array( 'headers' => array(), 'response' => array('code' => int, 'message' => string) );
    13001476 * </code>
    13011477 *
  • trunk/wp-includes/rewrite.php

    r10508 r10512  
    15971597     */
    15981598    function wp_rewrite_rules() {
    1599         $this->rules = get_option('rewrite_rules');
     1599        $this->rules = get_transient('rewrite_rules');
    16001600        if ( empty($this->rules) ) {
    16011601            $this->matches = 'matches';
    16021602            $this->rewrite_rules();
    1603             update_option('rewrite_rules', $this->rules);
     1603            set_transient('rewrite_rules', $this->rules);
    16041604        }
    16051605
     
    17841784     */
    17851785    function flush_rules() {
    1786         delete_option('rewrite_rules');
     1786        delete_transient('rewrite_rules');
    17871787        $this->wp_rewrite_rules();
    17881788        if ( function_exists('save_mod_rewrite_rules') )
  • trunk/wp-includes/rss.php

    r10508 r10512  
    715715        $cache_timestamp = 'rss_' . $this->file_name( $url ) . '_ts';
    716716
    717         // shouldn't these be using get_option() ?
    718         if ( !$wpdb->get_var( $wpdb->prepare( "SELECT option_name FROM $wpdb->options WHERE option_name = %s", $cache_option ) ) )
    719             add_option($cache_option, '', '', 'no');
    720         if ( !$wpdb->get_var( $wpdb->prepare( "SELECT option_name FROM $wpdb->options WHERE option_name = %s", $cache_timestamp ) ) )
    721             add_option($cache_timestamp, '', '', 'no');
    722 
    723         update_option($cache_option, $rss);
    724         update_option($cache_timestamp, time() );
     717        set_transient($cache_option, $rss);
     718        set_transient($cache_timestamp, time() );
    725719
    726720        return $cache_option;
     
    737731        $cache_option = 'rss_' . $this->file_name( $url );
    738732
    739         if ( ! get_option( $cache_option ) ) {
     733        if ( ! $rss = get_transient( $cache_option ) ) {
    740734            $this->debug(
    741735                "Cache doesn't contain: $url (cache option: $cache_option)"
     
    743737            return 0;
    744738        }
    745 
    746         $rss = get_option( $cache_option );
    747739
    748740        return $rss;
     
    761753        $cache_timestamp = 'rss_' . $this->file_name( $url ) . '_ts';
    762754
    763         if ( $mtime = get_option($cache_timestamp) ) {
     755        if ( $mtime = get_transient($cache_timestamp) ) {
    764756            // find how long ago the file was added to the cache
    765757            // and whether that is longer then MAX_AGE
Note: See TracChangeset for help on using the changeset viewer.