WordPress.org

Make WordPress Core

Ticket #4779: 4779.r8519.diff

File 4779.r8519.diff, 21.5 KB (added by santosj, 7 years ago)

Adds cURL transport, but does not add it to the list, because it needs to be tested first. Fixes documentation and non-blocking mode.

  • http.php

     
    11<?php 
    22/** 
    3  * Simple HTTP request fallback system 
     3 * Simple and uniform HTTP request API. 
    44 * 
     5 * Will eventually replace and standardize the WordPress HTTP requests made. 
     6 * 
    57 * @package WordPress 
    68 * @subpackage HTTP 
    79 * @since 2.7 
     
    911 */ 
    1012 
    1113/** 
    12  * Abstract class for all of the fallback implementation 
    13  * classes. The implementation classes will extend this class 
    14  * to keep common API methods universal between different 
    15  * functionality. 
     14 * WordPress HTTP Class for managing HTTP Transports and making HTTP requests. 
    1615 * 
     16 * This class is called for the functionality of making HTTP requests and should 
     17 * replace Snoopy functionality, eventually. There is no available functionality 
     18 * to add HTTP transport implementations, since most of the HTTP transports are 
     19 * added and available for use. 
     20 * 
     21 * The exception is that cURL is not available as a transport and lacking an 
     22 * implementation. It will be added later and should be a patch on the WordPress 
     23 * Trac. 
     24 * 
     25 * There are no properties, because none are needed and for performance reasons. 
     26 * Some of the functions are static and while they do have some overhead over 
     27 * functions in PHP4, the purpose is maintainability. When PHP5 is finally the 
     28 * requirement, it will be easy to add the static keyword to the code. It is not 
     29 * as easy to convert a function to a method after enough code uses the old way. 
     30 * 
    1731 * @package WordPress 
    1832 * @subpackage HTTP 
    1933 * @since 2.7 
     
    3347        /** 
    3448         * PHP5 style Constructor - Setup available transport if not available. 
    3549         * 
     50         * PHP4 does not have the 'self' keyword and since WordPress supports PHP4, 
     51         * the class needs to be used for the static call. 
     52         * 
     53         * The transport are setup to save time. This should only be called once, so 
     54         * the overhead should be fine. 
     55         * 
    3656         * @since 2.7 
    3757         * @return WP_Http 
    3858         */ 
    3959        function __construct() { 
    4060                WP_Http::_getTransport(); 
     61                WP_Http::_postTransport(); 
    4162        } 
    4263 
    4364        /** 
     
    4667         * Tests all of the objects and returns the object that passes. Also caches 
    4768         * that object to be used later. 
    4869         * 
     70         * The order for the GET/HEAD requests are Streams, HTTP Extension, Fopen, 
     71         * and finally Fsockopen. fsockopen() is used last, because it has the most 
     72         * overhead in its implementation. There isn't any real way around it, since 
     73         * redirects have to be supported, much the same way the other transports 
     74         * also handle redirects. 
     75         * 
     76         * There are currently issues with "localhost" not resolving correctly with 
     77         * DNS. This may cause an error "failed to open stream: A connection attempt 
     78         * failed because the connected party did not properly respond after a 
     79         * period of time, or established connection failed because connected host 
     80         * has failed to respond." 
     81         * 
    4982         * @since 2.7 
    5083         * @access private 
    5184         * 
     
    75108         * that object to be used later. This is for posting content to a URL and 
    76109         * is used when there is a body. The plain Fopen Transport can not be used 
    77110         * to send content, but the streams transport can. This is a limitation that 
    78          * is addressed here. 
     111         * is addressed here, by just not including that transport. 
    79112         * 
    80113         * @since 2.7 
    81114         * @access private 
     
    98131        } 
    99132 
    100133        /** 
    101          * Retrieve the location and set the class properties after the site has been retrieved. 
     134         * Send a HTTP request to a URI. 
    102135         * 
     136         * The only URI that are supported in the HTTP Transport implementation are 
     137         * the HTTP and HTTPS protocols. HTTP and HTTPS are assumed so the server 
     138         * might not know how to handle the send headers. Other protocols are 
     139         * unsupported and most likely will fail. 
     140         * 
     141         * The defaults are 'method', 'timeout', 'redirection', 'httpversion', 
     142         * 'blocking' and 'user-agent'. 
     143         * 
     144         * Accepted 'method' values are 'GET', 'POST', and 'HEAD', some transports 
     145         * technically allow others, but should not be assumed. The 'timeout' is 
     146         * used to sent how long the connection should stay open before failing when 
     147         * no response. 'redirection' is used to track how many redirects were taken 
     148         * and used to sent the amount for other transports, but not all transports 
     149         * accept setting that value. 
     150         * 
     151         * The 'httpversion' option is used to sent the HTTP version and accepted 
     152         * values are '1.0', and '1.1' and should be a string. Version 1.1 is not 
     153         * supported, because of chunk response. The 'user-agent' option is the 
     154         * user-agent and is used to replace the default user-agent, which is 
     155         * 'WordPress/WP_Version', where WP_Version is the value from $wp_version. 
     156         * 
     157         * 'blocking' is the default, which is used to tell the transport, whether 
     158         * it should halt PHP while it performs the request or continue regardless. 
     159         * Actually, that isn't entirely correct. Blocking mode really just means 
     160         * whether the fread should just pull what it can whenever it gets bytes or 
     161         * if it should wait until it has enough in the buffer to read or finishes 
     162         * reading the entire content. It doesn't actually always mean that PHP will 
     163         * continue going after making the request. 
     164         * 
    103165         * @access public 
    104166         * @since 2.7 
    105167         * 
    106          * @param string $url 
     168         * @param string $url URI resource. 
     169         * @param str|array $args Optional. Override the defaults. 
    107170         * @param string|array $headers Optional. Either the header string or array of Header name and value pairs. Expects sanitized. 
    108171         * @param string $body Optional. The body that should be sent. Expected to be already processed. 
    109          * @param str|array $type Optional. Should be an already processed array with HTTP arguments. 
    110172         * @return boolean 
    111173         */ 
    112174        function request($url, $args = array(), $headers = null, $body = null) { 
     
    114176 
    115177                $defaults = array( 
    116178                        'method' => 'GET', 'timeout' => 3, 
    117                         'redirection' => 5, 'redirected' => false, 
    118                         'httpversion' => '1.0', 'blocking' => true 
     179                        'redirection' => 5, 'httpversion' => '1.0', 
     180                        'user-agent' => apply_filters('http_headers_useragent', 'WordPress/' . $wp_version ), 
     181                        'blocking' => true 
    119182                ); 
    120183 
    121184                $r = wp_parse_args( $args, $defaults ); 
     
    128191                } 
    129192 
    130193                if ( ! isset($headers['user-agent']) || ! isset($headers['User-Agent']) ) 
    131                         $headers['user-agent'] = apply_filters('http_headers_useragent', 'WordPress/' . $wp_version ); 
     194                        $headers['user-agent'] = $r['user-agent']; 
    132195 
    133                 if ( is_null($body) ) 
     196                if ( is_null($body) || count($headers) > 1 ) 
    134197                        $transport = WP_Http::_getTransport(); 
    135198                else 
    136199                        $transport = WP_Http::_postTransport(); 
     
    146209         * @access public 
    147210         * @since 2.7 
    148211         * 
    149          * @param string $url The location of the site and page to retrieve. 
     212         * @param string $url URI resource. 
     213         * @param str|array $args Optional. Override the defaults. 
    150214         * @param string|array $headers Optional. Either the header string or array of Header name and value pairs. 
    151215         * @param string $body Optional. The body that should be sent. Expected to be already processed. 
    152216         * @return boolean 
     
    165229         * @access public 
    166230         * @since 2.7 
    167231         * 
     232         * @param string $url URI resource. 
     233         * @param str|array $args Optional. Override the defaults. 
    168234         * @param string|array $headers Optional. Either the header string or array of Header name and value pairs. 
    169235         * @param string $body Optional. The body that should be sent. Expected to be already processed. 
    170236         * @return boolean 
     
    183249         * @access public 
    184250         * @since 2.7 
    185251         * 
     252         * @param string $url URI resource. 
     253         * @param str|array $args Optional. Override the defaults. 
    186254         * @param string|array $headers Optional. Either the header string or array of Header name and value pairs. 
    187255         * @param string $body Optional. The body that should be sent. Expected to be already processed. 
    188256         * @return boolean 
     
    227295        /** 
    228296         * Whether the headers returned a redirect location. 
    229297         * 
     298         * Actually just checks whether the location header exists. 
     299         * 
    230300         * @access public 
    231301         * @static 
    232302         * @since 2.7 
     
    243313        /** 
    244314         * Transform header string into an array. 
    245315         * 
    246          * Will overwrite the last header value, if it is not empty. 
     316         * If an array is given, then it will be immediately passed through with no 
     317         * changes. This is to prevent overhead in processing headers that don't 
     318         * need to be processed. That and it is unknown what kind of effect 
     319         * processing the array will have since there is no checking done on whether 
     320         * ':' does not exist within the array string. 
    247321         * 
     322         * Checking could be added, but it is easier and faster to just passed the 
     323         * array through and assume that it has already been processed. 
     324         * 
    248325         * @access public 
    249326         * @static 
    250327         * @since 2.7 
    251328         * 
    252329         * @param string|array $headers 
    253          * @return array 
     330         * @return array Processed string headers  
    254331         */ 
    255332        function processHeaders($headers) { 
    256333                if ( is_array($headers) ) 
    257334                        return $headers; 
    258335 
    259                 $headers = explode("\n", str_replace(array("\r"), '', $headers) ); 
     336                $headers = explode("\n", str_replace(array("\r\n", "\r"), "\n", $headers) ); 
    260337 
    261338                $response = array('code' => 0, 'message' => ''); 
    262339 
     
    285362/** 
    286363 * HTTP request method uses fsockopen function to retrieve the url. 
    287364 * 
    288  * Preferred method since it works with all WordPress supported PHP versions. 
     365 * This would be the preferred method, but the fsockopen implementation has the 
     366 * most overhead of all the HTTP transport implementations. 
    289367 * 
    290368 * @package WordPress 
    291369 * @subpackage HTTP 
     
    293371 */ 
    294372class WP_Http_Fsockopen { 
    295373        /** 
    296          * Retrieve the location and set the class properties after the site has been retrieved. 
     374         * Send a HTTP request to a URI using fsockopen(). 
    297375         * 
     376         * Does not support non-blocking mode. 
     377         * 
     378         * @see WP_Http::retrieve For default options descriptions. 
     379         * 
    298380         * @since 2.7 
    299381         * @access public 
    300          * @param string $url 
     382         * @param string $url URI resource. 
     383         * @param str|array $args Optional. Override the defaults. 
    301384         * @param string|array $headers Optional. Either the header string or array of Header name and value pairs. Expects sanitized. 
    302385         * @param string $body Optional. The body that should be sent. Expected to be already processed. 
    303          * @param str|array $type Optional. Should be an already processed array with HTTP arguments. 
    304          * @return boolean 
     386         * @return array 'headers', 'body', and 'response' keys. 
    305387         */ 
    306388        function request($url, $args = array(), $headers = null, $body = null) { 
    307389                $defaults = array( 
     
    322404                if ( ! isset($arrURL['port']) ) { 
    323405                        if ( ($arrURL['scheme'] == 'ssl' || $arrURL['scheme'] == 'https') && extension_loaded('openssl') ) { 
    324406                                $arrURL['host'] = 'ssl://' . $arrURL['host']; 
    325                                 $arrURL['port'] = apply_filters('http_request_default_port', 443); 
     407                                $arrURL['port'] = apply_filters('http_request_port', 443); 
    326408                                $secure_transport = true; 
    327409                        } else { 
    328410                                $arrURL['port'] = apply_filters('http_request_default_port', 80); 
     
    331413                        $arrURL['port'] = apply_filters('http_request_port', $arrURL['port']); 
    332414                } 
    333415 
     416                // There are issues with the HTTPS and SSL protocols that cause errors 
     417                // that can be safely ignored and should be ignored. 
    334418                if ( true === $secure_transport ) 
    335419                        $error_reporting = error_reporting(0); 
    336420 
     
    360444 
    361445                fwrite($handle, $strHeaders); 
    362446 
    363                 if ( ! $r['blocking'] ) 
    364                         return array( 'headers' => array(), 'body' => '', 'response' => array() ); 
     447                if ( ! $r['blocking'] ) { 
     448                        fclose($handle); 
     449                        return array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') ); 
     450                } 
    365451 
    366452                $strResponse = ''; 
    367453                while ( ! feof($handle) ) 
     
    410496 * for $context support, but should still be okay, to write the headers, before 
    411497 * getting the response. Also requires that 'allow_url_fopen' to be enabled. 
    412498 * 
    413  * Second preferred method for handling the retrieving the url for PHP 4.3+. 
    414  * 
    415499 * @package WordPress 
    416500 * @subpackage HTTP 
    417501 * @since 2.7 
    418502 */ 
    419503class WP_Http_Fopen { 
    420504        /** 
    421          * Retrieve the location and set the class properties after the site has been retrieved. 
     505         * Send a HTTP request to a URI using fopen(). 
    422506         * 
     507         * This transport does not support sending of headers and body, therefore 
     508         * should not be used in the instances, where there is a body and headers. 
     509         * 
     510         * Notes: Does not support non-blocking mode. Ignores 'redirection' option. 
     511         * 
     512         * @see WP_Http::retrieve For default options descriptions. 
     513         * 
    423514         * @access public 
    424515         * @since 2.7 
    425516         * 
    426          * @param string $url 
     517         * @param string $url URI resource. 
     518         * @param str|array $args Optional. Override the defaults. 
    427519         * @param string|array $headers Optional. Either the header string or array of Header name and value pairs. Expects sanitized. 
    428520         * @param string $body Optional. The body that should be sent. Expected to be already processed. 
    429          * @param str|array $type Optional. Should be an already processed array with HTTP arguments. 
    430          * @return boolean 
     521         * @return array 'headers', 'body', and 'response' keys. 
    431522         */ 
    432523        function request($url, $args = array(), $headers = null, $body = null) { 
    433524                global $http_response_header; 
     
    453544                if ( function_exists('stream_set_timeout') ) 
    454545                        stream_set_timeout($handle, apply_filters('http_request_timeout', $r['timeout']) ); 
    455546 
    456                 if ( ! $r['blocking'] ) 
    457                         return array( 'headers' => array(), 'body' => '', 'response' => array() ); 
     547                if ( ! $r['blocking'] ) { 
     548                        fclose($handle); 
     549                        return array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') ); 
     550                } 
    458551 
    459552                $strResponse = ''; 
    460553                while ( ! feof($handle) ) 
    461554                        $strResponse .= fread($handle, 4096); 
    462555 
     556                fclose($handle); 
     557 
    463558                $theHeaders = ''; 
    464559                if ( function_exists('stream_get_meta_data') ) { 
    465560                        $meta = stream_get_meta_data($handle); 
     
    467562                } else { 
    468563                        $theHeaders = $http_response_header; 
    469564                } 
    470                 fclose($handle); 
     565                $processedHeaders = WP_Http::processHeaders($theHeaders); 
    471566 
    472                 $processedHeaders = WP_Http::processHeaders($theHeaders); 
    473567                return array('headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response']); 
    474568        } 
    475569 
     
    501595 */ 
    502596class WP_Http_Streams { 
    503597        /** 
    504          * Retrieve the location and set the class properties after the site has been retrieved. 
     598         * Send a HTTP request to a URI using streams with fopen(). 
    505599         * 
    506600         * @access public 
    507601         * @since 2.7 
     
    510604         * @param str|array $args Optional. Override the defaults. 
    511605         * @param string|array $headers Optional. Either the header string or array of Header name and value pairs. Expects sanitized. 
    512606         * @param string $body Optional. The body that should be sent. Expected to be already processed. 
    513          * @return boolean 
     607         * @return array 'headers', 'body', and 'response' keys. 
    514608         */ 
    515609        function request($url, $args = array(), $headers = null, $body = null) { 
    516610                $defaults = array( 
     
    548642                if ( ! $handle) 
    549643                        return new WP_Error('http_request_failed', sprintf(__('Could not open handle for fopen() to %s'), $url)); 
    550644 
    551                 if ( ! $r['blocking'] ) 
    552                         return array( 'headers' => array(), 'body' => '', 'response' => array() ); 
     645                if ( ! $r['blocking'] ) { 
     646                        fclose($handle); 
     647                        return array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') ); 
     648                } 
    553649 
    554650                $strResponse = stream_get_contents($handle); 
    555651                $meta = stream_get_meta_data($handle); 
     652                $processedHeaders = WP_Http::processHeaders($meta['wrapper_data']); 
    556653 
    557654                fclose($handle); 
    558655 
    559                 $processedHeaders = WP_Http::processHeaders($meta['wrapper_data']); 
    560656                return array('headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response']); 
    561657        } 
    562658 
     
    583679/** 
    584680 * HTTP request method uses HTTP extension to retrieve the url. 
    585681 * 
    586  * Requires the HTTP extension to be installed. 
     682 * Requires the HTTP extension to be installed. This would be the preferred 
     683 * transport since it can handle a lot of the problems that forces the others to 
     684 * use the HTTP version 1.0. Even if PHP 5.2+ is being used, it doesn't mean 
     685 * that the HTTP extension will be enabled. 
    587686 * 
    588  * Last ditch effort to retrieve the URL before complete failure. 
    589  * Does not support non-blocking requests. 
    590  * 
    591687 * @package WordPress 
    592688 * @subpackage HTTP 
    593689 * @since 2.7 
    594690 */ 
    595691class WP_Http_ExtHTTP { 
    596692        /** 
    597          * Retrieve the location and set the class properties after the site has been retrieved. 
     693         * Send a HTTP request to a URI using HTTP extension. 
    598694         * 
     695         * Does not support non-blocking. 
     696         * 
    599697         * @access public 
    600698         * @since 2.7 
    601699         * 
     
    603701         * @param str|array $args Optional. Override the defaults. 
    604702         * @param string|array $headers Optional. Either the header string or array of Header name and value pairs. Expects sanitized. 
    605703         * @param string $body Optional. The body that should be sent. Expected to be already processed. 
    606          * @return boolean 
     704         * @return array 'headers', 'body', and 'response' keys. 
    607705         */ 
    608706        function request($url, $args = array(), $headers = null, $body = null) { 
    609707                global $wp_version; 
     
    611709                $defaults = array( 
    612710                        'method' => 'GET', 'timeout' => 3, 
    613711                        'redirection' => 5, 'httpversion' => '1.0', 
    614                         'blocking' => true, 'user_agent' => apply_filters('http_headers_useragent', 'WordPress/' . $wp_version) 
     712                        'blocking' => true 
    615713                ); 
    616714 
    617715                $r = wp_parse_args( $args, $defaults ); 
    618716 
    619                 if ( isset($headers['User-Agent']) ) 
     717                if ( isset($headers['User-Agent']) ) { 
     718                        $r['user-agent'] = $headers['User-Agent']; 
    620719                        unset($headers['User-Agent']); 
     720                } else if( isset($headers['user-agent']) ) { 
     721                        $r['user-agent'] = $headers['user-agent']; 
     722                        unset($headers['user-agent']); 
     723                } else { 
     724                        $r['user-agent'] = apply_filters('http_headers_useragent', 'WordPress/' . $wp_version ); 
     725                } 
    621726 
    622727                switch ( $r['method'] ) { 
    623728                        case 'GET': 
     
    639744                        $url = str_replace($arrURL['scheme'], 'http', $url); 
    640745 
    641746                $options = array( 
    642                         'timeout' => $this->timeout, 
    643                         'connecttimeout' => apply_filters('http_request_stream_timeout', $this->timeout), 
    644                         'redirect' => apply_filters('http_request_redirect', 3), 
     747                        'timeout' => $r['timeout'], 
     748                        'connecttimeout' => $r['timeout'], 
     749                        'redirect' => $r['redirection'], 
    645750                        'useragent' => $r['user_agent'], 
    646751                        'headers' => $headers, 
    647752                ); 
     
    651756                if ( false === $strResponse ) 
    652757                        return new WP_Error('http_request_failed', $info['response_code'] . ': ' . $info['error']); 
    653758 
     759                if ( ! $r['blocking'] ) 
     760                        return array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') ); 
     761 
    654762                list($theHeaders, $theBody) = explode("\r\n\r\n", $strResponse, 2); 
    655763                $theHeaders = WP_Http::processHeaders($theHeaders); 
    656764 
     
    678786} 
    679787 
    680788/** 
     789 * HTTP request method uses Curl extension to retrieve the url. 
     790 * 
     791 * Requires the Curl extension to be installed. 
     792 * 
     793 * @package WordPress 
     794 * @subpackage HTTP 
     795 * @since 2.7 
     796 */ 
     797class WP_Http_Curl { 
     798        /** 
     799         * Send a HTTP request to a URI using cURL extension. 
     800         * 
     801         * @access public 
     802         * @since 2.7 
     803         * 
     804         * @param string $url 
     805         * @param str|array $args Optional. Override the defaults. 
     806         * @param string|array $headers Optional. Either the header string or array of Header name and value pairs. Expects sanitized. 
     807         * @param string $body Optional. The body that should be sent. Expected to be already processed. 
     808         * @return array 'headers', 'body', and 'response' keys. 
     809         */ 
     810        function request($url, $args = array(), $headers = null, $body = null) { 
     811                global $wp_version; 
     812 
     813                $defaults = array( 
     814                        'method' => 'GET', 'timeout' => 3, 
     815                        'redirection' => 5, 'httpversion' => '1.0', 
     816                        'blocking' => true 
     817                ); 
     818 
     819                $r = wp_parse_args( $args, $defaults ); 
     820 
     821                if ( isset($headers['User-Agent']) ) { 
     822                        $r['user-agent'] = $headers['User-Agent']; 
     823                        unset($headers['User-Agent']); 
     824                } else if( isset($headers['user-agent']) ) { 
     825                        $r['user-agent'] = $headers['user-agent']; 
     826                        unset($headers['user-agent']); 
     827                } else { 
     828                        $r['user-agent'] = apply_filters('http_headers_useragent', 'WordPress/' . $wp_version ); 
     829                } 
     830 
     831                $handle = curl_init(); 
     832                curl_setopt( $handle, CURLOPT_URL, $url); 
     833 
     834                if ( true === $r['blocking'] ) { 
     835                        curl_setopt( $handle, CURLOPT_HEADER, true ); 
     836                } else { 
     837                        curl_setopt( $handle, CURLOPT_HEADER, false ); 
     838                        curl_setopt( $handle, CURLOPT_NOBODY, true ); 
     839                } 
     840 
     841                curl_setopt( $handle, CURLOPT_RETURNTRANSFER, 1 ); 
     842                curl_setopt( $handle, CURLOPT_USERAGENT, $r['user-agent'] ); 
     843                curl_setopt( $handle, CURLOPT_CONNECTTIMEOUT, 1 ); 
     844                curl_setopt( $handle, CURLOPT_TIMEOUT, $r['timeout'] ); 
     845                curl_setopt( $handle, CURLOPT_FOLLOWLOCATION, true ); 
     846                curl_setopt( $handle, CURLOPT_MAXREDIRS, $r['redirection'] ); 
     847 
     848                if( ! is_null($headers) ) 
     849                        curl_setopt( $handle, CURLOPT_HTTPHEADER, $headers ); 
     850 
     851                if ( $r['httpversion'] == '1.0' ) 
     852                        curl_setopt( $headle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0 ); 
     853                else 
     854                        curl_setopt( $headle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1 ); 
     855 
     856                if ( ! $r['blocking'] ) { 
     857                        curl_close( $handle ); 
     858                        return array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') ); 
     859                } 
     860 
     861                $theResponse = curl_exec( $handle ); 
     862 
     863                list($theHeaders, $theBody) = explode("\r\n\r\n", $strResponse, 2); 
     864                $theHeaders = WP_Http::processHeaders($theHeaders); 
     865 
     866                $response = array(); 
     867                $response['code'] = curl_getinfo( $handle, CURLINFO_HTTP_CODE ); 
     868                $response['message'] = get_status_header_desc($response['code']); 
     869 
     870                curl_close( $handle ); 
     871 
     872                return array('headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $response); 
     873        } 
     874 
     875        /** 
     876         * Whether this class can be used for retrieving an URL. 
     877         * 
     878         * @static 
     879         * @since 2.7 
     880         * 
     881         * @return boolean False means this class can not be used, true means it can. 
     882         */ 
     883        function test() { 
     884                if ( function_exists('curl_init') ) 
     885                        return true; 
     886 
     887                return false; 
     888        } 
     889} 
     890 
     891/** 
    681892 * Returns the initialized WP_Http Object 
    682893 * 
    683894 * @since 2.7