Make WordPress Core

Ticket #13777: 13777.2.patch

File 13777.2.patch, 19.7 KB (added by hakre, 14 years ago)

Example only

  • wp-includes/class-http.php

    ### Eclipse Workspace Patch 1.0
    #P wordpress-trunk
     
    1313 */
    1414
    1515/**
     16 * HTTP Transport base class
     17 *
     18 * @since 3.2
     19 */
     20abstract class WP_Http_TransportConcrete extends WP_Http {
     21        abstract protected static function test( array $args = array(), $url = null );
     22        abstract protected function _request( $url, array $args );
     23        /**
     24         * Send a HTTP request to a URI.
     25         *
     26         * @see WP_Http::request For default options descriptions.
     27         *
     28         * @since 2.7
     29         * @access public
     30         * @param string $url URI resource.
     31         * @param str|array $args Optional. Override the defaults.
     32         * @return array 'headers', 'body', 'cookies' and 'response' keys.
     33         */
     34        public function request( $url, $args = array() ) {
     35                $defaults = array(
     36                        'method' => 'GET', 'timeout' => 5,
     37                        'redirection' => 5, 'httpversion' => '1.0',
     38                        'blocking' => true,
     39                        'headers' => array(), 'cookies' => array(), 'body' => null
     40                );
     41
     42                $args = wp_parse_args( $args, $defaults );
     43
     44                if ( isset($args['headers']['User-Agent']) ) {
     45                        $args['user-agent'] = $args['headers']['User-Agent'];
     46                        unset($args['headers']['User-Agent']);
     47                } else if ( isset($r['headers']['user-agent']) ) {
     48                        $args['user-agent'] = $args['headers']['user-agent'];
     49                        unset($args['headers']['user-agent']);
     50                }
     51
     52                // Construct Cookie: header if any cookies are set
     53                WP_Http::buildCookieHeader( $args );
     54               
     55                return $this->_request( $url, $args );
     56        }
     57}
     58
     59/**
    1660 * WordPress HTTP Class for managing HTTP Transports and making HTTP requests.
    1761 *
    1862 * This class is called for the functionality of making HTTP requests and replaces Snoopy
     
    3680 * @since 2.7.0
    3781 */
    3882class WP_Http {
     83        /**
     84         * local store of WP_Http_* Transport Objects, keyed with their Transport name.
     85         *
     86         * @var array
     87         */
     88        private static $_transports = array();
    3989
    4090        /**
    4191         * Send a HTTP request to a URI.
     
    102152                        'filename' => null
    103153                );
    104154
    105                
    106155                // Pre-parse for the HEAD checks.
    107156                $args = wp_parse_args( $args );
    108157
     
    110159                if ( isset($args['method']) && 'HEAD' == $args['method'] )
    111160                        $defaults['redirection'] = 0;
    112161
    113                 $r = wp_parse_args( $args, $defaults );
     162                $r = array_merge( $defaults, $args );
    114163                $r = apply_filters( 'http_request_args', $r, $url );
    115164
    116165                // Certain classes decrement this, store a copy of the original value for loop purposes.
     
    124173                $arrURL = parse_url( $url );
    125174
    126175                if ( empty( $url ) || empty( $arrURL['scheme'] ) )
    127                         return new WP_Error('http_request_failed', __('A valid URL was not provided.'));
     176                        return new WP_Error('http_request_failed', __( 'Invalid URL.' ));
    128177
    129178                if ( $this->block_request( $url ) )
    130179                        return new WP_Error( 'http_request_failed', __( 'User has blocked requests through HTTP.' ) );
     
    158207                        $r['headers'] = $processedHeaders['headers'];
    159208                }
    160209
    161                 if ( isset( $r['headers']['User-Agent'] ) ) {
     210                if ( isset($r['headers']['User-Agent']) ) {
    162211                        $r['user-agent'] = $r['headers']['User-Agent'];
    163                         unset( $r['headers']['User-Agent'] );
    164                 }
    165 
    166                 if ( isset( $r['headers']['user-agent'] ) ) {
     212                        unset($r['headers']['User-Agent']);
     213                } else if ( isset($r['headers']['user-agent']) ) {
    167214                        $r['user-agent'] = $r['headers']['user-agent'];
    168                         unset( $r['headers']['user-agent'] );
     215                        unset($r['headers']['user-agent']);
    169216                }
    170217
    171218                // Construct Cookie: header if any cookies are set
     
    196243        }
    197244
    198245        /**
     246         * get transport object specified by name
     247         *
     248         * Works as a multi-singleton registry on self::$transports
     249         *
     250         * @param string $transport name
     251         * @return Object
     252         */
     253        private function _transport_object( $transport ) {
     254                $class = "WP_HTTP_{$transport}";
     255
     256                if ( empty( self::$_transports[ $transport ] ) )
     257                        self::$_transports[ $transport ] = new $class;
     258
     259                return self::$_transports[ $transport ];
     260        }
     261
     262        /**
    199263         * Dispatches a HTTP request to a supporting transport.
    200264         *
    201265         * Tests each transport in order to find a transport which matches the request arguements.
     
    218282         * @return array|object Array containing 'headers', 'body', 'response', 'cookies'. A WP_Error instance upon error
    219283         */
    220284        private function _dispatch_request($url, $args) {
    221                 static $transports = null;
    222                 if ( is_null($transports) )
    223                         $transports = array();
     285                // default transports order
     286                $request_order = $args['blocking'] ?
     287                                                        array( 'exthttp', 'curl', 'streams', 'fsockopen' ): // blocking order
     288                                                        array( 'curl', 'streams', 'fsockopen', 'exthttp' ); // non-blocking order
    224289
    225                 $request_order = isset($r['blocking']) && !$r['blocking'] ?
    226                                                         array('curl', 'streams', 'fsockopen', 'exthttp') : // non-blocking order
    227                                                         array('exthttp', 'curl', 'streams', 'fsockopen'); // blocking order
     290                $request_order = apply_filters( 'http_get_transports', $request_order, $url, $args );
    228291
    229                 // Loop over each transport on each HTTP request looking for one which will serve this requests needs
    230                 foreach ( $request_order as $transport ) {
    231                         $class = 'WP_HTTP_' . $transport;
     292                // retrieve the transport from all transports and request
     293                if ( $transport = $this->_test_transports( $request_order, $url, $args ) ) {
     294                        // Transport claims to support request, give it a whirl.
     295                        $response = $this->_transport_object( $transport )->request( $url, $args );
    232296
    233                         // Check to see if this transport is a possibility, calls the transport statically
    234                         if ( ! call_user_func( array($class, 'test'), $args, $url) )
    235                                 continue;
     297                        do_action( 'http_api_debug', $response, 'response', "WP_Http_{$transport}" );
    236298
    237                         // Transport claims to support request, Instantate it and give it a whirl.
    238                         if ( empty( $transports[ $transport ] ) )
    239                                 $transports[ $transport ] = new $class;
    240 
    241                         $response = $transports[ $transport ]->request( $url, $args );
    242 
    243                         do_action( 'http_api_debug', $response, 'response', $class );
    244 
    245299                        if ( is_wp_error( $response ) )
    246300                                return $response;
    247301
     
    250304
    251305                return new WP_Error('http_failure', __('There are no HTTP transports available which can complete the requested request.') );
    252306        }
     307       
     308        /**
     309         * Test if one of the transports is available
     310         *
     311         * Returns on first match.
     312         *
     313         * @param array $transports list of transports to test against
     314         * @param string $url
     315         * @param array $args
     316         * @return string name of the transport, empty string if non could be found
     317         */
     318        private function _test_transports( array $transports, $url, array $args ) {
     319                foreach( $transports as $transport ) {
     320                        if ( $this->test_transport( $transport, $args, $url ) )
     321                                return $transport;
     322                }
     323                return '';
     324        }
    253325
    254326        /**
     327         * test if a named transport is available
     328         *
     329         * @param string $transport name of the transport
     330         * @param array $args Optional. Arguments for the transport to be tested against.
     331         * @param string $url Optional. Url for the transport to be tested against.
     332         * @return boolean Whether or not the transport can be used.
     333         */
     334        public function test_transport( $transport, array $args = array() , $url = null ) {
     335                $result = call_user_func( "WP_HTTP_{$transport}::test", $args, $url );
     336                return apply_filters( "use_{$transport}_transport", $result, $args, $url );
     337        }
     338       
     339        private function _request_by_method( $method, $url, $args ) {
     340                $defaults = array( 'method' => $method );
     341                $r = wp_parse_args( $args, $defaults );
     342                return $this->request( $url, $r );
     343        }
     344
     345        /**
    255346         * Uses the POST HTTP method.
    256347         *
    257348         * Used for sending data that is expected to be in the body.
     
    264355         * @return array|object Array containing 'headers', 'body', 'response', 'cookies'. A WP_Error instance upon error
    265356         */
    266357        function post($url, $args = array()) {
    267                 $defaults = array('method' => 'POST');
    268                 $r = wp_parse_args( $args, $defaults );
    269                 return $this->request($url, $r);
     358                return $this->_request_by_method( 'POST', $url, $args );
    270359        }
    271360
    272361        /**
     
    282371         * @return array|object Array containing 'headers', 'body', 'response', 'cookies'. A WP_Error instance upon error
    283372         */
    284373        function get($url, $args = array()) {
    285                 $defaults = array('method' => 'GET');
    286                 $r = wp_parse_args( $args, $defaults );
    287                 return $this->request($url, $r);
     374                return $this->_request_by_method( 'GET', $url, $args );
    288375        }
    289376
    290377        /**
     
    300387         * @return array|object Array containing 'headers', 'body', 'response', 'cookies'. A WP_Error instance upon error
    301388         */
    302389        function head($url, $args = array()) {
    303                 $defaults = array('method' => 'HEAD');
    304                 $r = wp_parse_args( $args, $defaults );
    305                 return $this->request($url, $r);
     390                return $this->_request_by_method( 'POST', $url, $args );
    306391        }
    307392
    308393        /**
     
    317402         */
    318403        function processResponse($strResponse) {
    319404                $res = explode("\r\n\r\n", $strResponse, 2);
     405                $res[] = '';
    320406
    321                 return array('headers' => isset($res[0]) ? $res[0] : array(), 'body' => isset($res[1]) ? $res[1] : '');
     407                return array( 'headers' => $res[0], 'body' => $res[1] );
    322408        }
    323409
    324410        /**
     
    537623 * @subpackage HTTP
    538624 * @since 2.7.0
    539625 */
    540 class WP_Http_Fsockopen {
     626class WP_Http_Fsockopen extends WP_Http_TransportConcrete {
    541627        /**
    542628         * Send a HTTP request to a URI using fsockopen().
    543629         *
    544          * Does not support non-blocking mode.
    545          *
    546          * @see WP_Http::request For default options descriptions.
    547          *
    548          * @since 2.7
    549          * @access public
     630         * @since 2.7 through request()
     631         * @access public through request()
    550632         * @param string $url URI resource.
    551          * @param str|array $args Optional. Override the defaults.
     633         * @param array $args Optional.
    552634         * @return array 'headers', 'body', 'cookies' and 'response' keys.
    553635         */
    554         function request($url, $args = array()) {
    555                 $defaults = array(
    556                         'method' => 'GET', 'timeout' => 5,
    557                         'redirection' => 5, 'httpversion' => '1.0',
    558                         'blocking' => true,
    559                         'headers' => array(), 'body' => null, 'cookies' => array()
    560                 );
     636        protected function _request($url, array $args = array()) {
     637                $r = $args; # alias parameter @todo rename
    561638
    562                 $r = wp_parse_args( $args, $defaults );
    563 
    564                 if ( isset($r['headers']['User-Agent']) ) {
    565                         $r['user-agent'] = $r['headers']['User-Agent'];
    566                         unset($r['headers']['User-Agent']);
    567                 } else if ( isset($r['headers']['user-agent']) ) {
    568                         $r['user-agent'] = $r['headers']['user-agent'];
    569                         unset($r['headers']['user-agent']);
    570                 }
    571 
    572                 // Construct Cookie: header if any cookies are set
    573                 WP_Http::buildCookieHeader( $r );
    574 
    575639                $iError = null; // Store error number
    576640                $strError = null; // Store error string
    577641
     
    718782                $arrHeaders = WP_Http::processHeaders( $process['headers'] );
    719783
    720784                // Is the response code within the 400 range?
    721                 if ( (int) $arrHeaders['response']['code'] >= 400 && (int) $arrHeaders['response']['code'] < 500 )
     785                if ( 4 === (int) ($arrHeaders['response']['code'] / 100) )
    722786                        return new WP_Error('http_request_failed', $arrHeaders['response']['code'] . ': ' . $arrHeaders['response']['message']);
    723787
    724788                // If location is found, then assume redirect and redirect to location.
     
    747811         * @static
    748812         * @return boolean False means this class can not be used, true means it can.
    749813         */
    750         function test( $args = array() ) {
     814        protected static function test( array $args = array(), $url = null ) {
    751815                if ( false !== ($option = get_option( 'disable_fsockopen' )) && time()-$option < 43200 ) // 12 hours
    752816                        return false;
    753817
     
    760824                else
    761825                        $use = false;
    762826
    763                 return apply_filters('use_fsockopen_transport', $use, $args);
     827                return $use;
    764828        }
    765829}
    766830
     
    776840 * @subpackage HTTP
    777841 * @since 2.7.0
    778842 */
    779 class WP_Http_Streams {
     843class WP_Http_Streams extends WP_Http_TransportConcrete {
    780844        /**
    781845         * Send a HTTP request to a URI using streams with fopen().
    782846         *
     
    787851         * @param str|array $args Optional. Override the defaults.
    788852         * @return array 'headers', 'body', 'cookies' and 'response' keys.
    789853         */
    790         function request($url, $args = array()) {
    791                 $defaults = array(
    792                         'method' => 'GET', 'timeout' => 5,
    793                         'redirection' => 5, 'httpversion' => '1.0',
    794                         'blocking' => true,
    795                         'headers' => array(), 'body' => null, 'cookies' => array()
    796                 );
     854        protected function _request($url, array $args = array()) {
     855                $r = $args; # alias parameter @todo rename
    797856
    798                 $r = wp_parse_args( $args, $defaults );
    799 
    800                 if ( isset($r['headers']['User-Agent']) ) {
    801                         $r['user-agent'] = $r['headers']['User-Agent'];
    802                         unset($r['headers']['User-Agent']);
    803                 } else if ( isset($r['headers']['user-agent']) ) {
    804                         $r['user-agent'] = $r['headers']['user-agent'];
    805                         unset($r['headers']['user-agent']);
    806                 }
    807 
    808                 // Construct Cookie: header if any cookies are set
    809                 WP_Http::buildCookieHeader( $r );
    810 
    811857                $arrURL = parse_url($url);
    812858
    813859                if ( false === $arrURL )
     
    931977         *
    932978         * @return boolean False means this class can not be used, true means it can.
    933979         */
    934         function test($args = array()) {
    935                 if ( ! function_exists('fopen') || (function_exists('ini_get') && true != ini_get('allow_url_fopen')) )
    936                         return false;
    937 
    938                 return apply_filters('use_streams_transport', true, $args);
     980        static protected function test( array $args = array(), $url = null ) {
     981                return !( ! function_exists('fopen') || (function_exists('ini_get') && true != ini_get('allow_url_fopen')) );
    939982        }
    940983}
    941984
     
    950993 * @subpackage HTTP
    951994 * @since 2.7.0
    952995 */
    953 class WP_Http_ExtHttp {
     996class WP_Http_ExtHttp extends WP_Http_TransportConcrete {
    954997        /**
    955998         * Send a HTTP request to a URI using HTTP extension.
    956999         *
     
    9631006         * @param str|array $args Optional. Override the defaults.
    9641007         * @return array 'headers', 'body', 'cookies' and 'response' keys.
    9651008         */
    966         function request($url, $args = array()) {
    967                 $defaults = array(
    968                         'method' => 'GET', 'timeout' => 5,
    969                         'redirection' => 5, 'httpversion' => '1.0',
    970                         'blocking' => true,
    971                         'headers' => array(), 'body' => null, 'cookies' => array()
    972                 );
     1009        function _request($url, array $args = array()) {
     1010                $r = $args; # alias parameter @todo rename
    9731011
    974                 $r = wp_parse_args( $args, $defaults );
    975 
    976                 if ( isset($r['headers']['User-Agent']) ) {
    977                         $r['user-agent'] = $r['headers']['User-Agent'];
    978                         unset($r['headers']['User-Agent']);
    979                 } else if ( isset($r['headers']['user-agent']) ) {
    980                         $r['user-agent'] = $r['headers']['user-agent'];
    981                         unset($r['headers']['user-agent']);
    982                 }
    983 
    984                 // Construct Cookie: header if any cookies are set
    985                 WP_Http::buildCookieHeader( $r );
    986 
    9871012                switch ( $r['method'] ) {
    9881013                        case 'POST':
    9891014                                $r['method'] = HTTP_METH_POST;
     
    10981123         *
    10991124         * @return boolean False means this class can not be used, true means it can.
    11001125         */
    1101         function test($args = array()) {
    1102                 return apply_filters('use_http_extension_transport', function_exists('http_request'), $args );
     1126        protected static function test(array $args = array(), $url = null) {
     1127                return function_exists('http_request');
    11031128        }
    11041129}
    11051130
     
    11121137 * @subpackage HTTP
    11131138 * @since 2.7
    11141139 */
    1115 class WP_Http_Curl {
     1140class WP_Http_Curl extends WP_Http_TransportConcrete {
    11161141
    11171142        /**
    11181143         * Temporary header storage for use with streaming to a file.
     
    11331158         * @param str|array $args Optional. Override the defaults.
    11341159         * @return array 'headers', 'body', 'cookies' and 'response' keys.
    11351160         */
    1136         function request($url, $args = array()) {
    1137                 $defaults = array(
    1138                         'method' => 'GET', 'timeout' => 5,
    1139                         'redirection' => 5, 'httpversion' => '1.0',
    1140                         'blocking' => true,
    1141                         'headers' => array(), 'body' => null, 'cookies' => array()
    1142                 );
     1161        function _request($url, array $args = array()) {
     1162                $r = $args; # alias parameter @todo rename
    11431163
    1144                 $r = wp_parse_args( $args, $defaults );
    1145 
    1146                 if ( isset($r['headers']['User-Agent']) ) {
    1147                         $r['user-agent'] = $r['headers']['User-Agent'];
    1148                         unset($r['headers']['User-Agent']);
    1149                 } else if ( isset($r['headers']['user-agent']) ) {
    1150                         $r['user-agent'] = $r['headers']['user-agent'];
    1151                         unset($r['headers']['user-agent']);
    1152                 }
    1153 
    1154                 // Construct Cookie: header if any cookies are set.
    1155                 WP_Http::buildCookieHeader( $r );
    1156 
    11571164                $handle = curl_init();
    11581165
    11591166                // cURL offers really easy proxy support.
     
    13141321         *
    13151322         * @return boolean False means this class can not be used, true means it can.
    13161323         */
    1317         function test($args = array()) {
    1318                 if ( function_exists('curl_init') && function_exists('curl_exec') )
    1319                         return apply_filters('use_curl_transport', true, $args);
    1320 
    1321                 return false;
     1324        protected static function test(array $args = array(), $url = null) {
     1325                return function_exists('curl_init') && function_exists('curl_exec');
    13221326        }
    13231327}
    13241328
  • wp-includes/http.php

     
    1919 *
    2020 * @return WP_Http HTTP Transport object.
    2121 */
    22 function &_wp_http_get_object() {
     22function _wp_http_get_object() {
    2323        static $http;
    24 
    25         if ( is_null($http) )
    26                 $http = new WP_Http();
    27 
    28         return $http;
     24        return $http ? $http : $http = new WP_Http();
    2925}
    3026
    3127/**
     
    5652 * @return WP_Error|array The response or WP_Error on failure.
    5753 */
    5854function wp_remote_request($url, $args = array()) {
    59         $objFetchSite = _wp_http_get_object();
    60         return $objFetchSite->request($url, $args);
     55        return _wp_http_get_object()->request($url, $args);
    6156}
    6257
    6358/**
     
    7267 * @return WP_Error|array The response or WP_Error on failure.
    7368 */
    7469function wp_remote_get($url, $args = array()) {
    75         $objFetchSite = _wp_http_get_object();
    76         return $objFetchSite->get($url, $args);
     70        return _wp_http_get_object()->get($url, $args);
    7771}
    7872
    7973/**
     
    8882 * @return WP_Error|array The response or WP_Error on failure.
    8983 */
    9084function wp_remote_post($url, $args = array()) {
    91         $objFetchSite = _wp_http_get_object();
    92         return $objFetchSite->post($url, $args);
     85        return _wp_http_get_object()->post($url, $args);
    9386}
    9487
    9588/**
     
    10497 * @return WP_Error|array The response or WP_Error on failure.
    10598 */
    10699function wp_remote_head($url, $args = array()) {
    107         $objFetchSite = _wp_http_get_object();
    108         return $objFetchSite->head($url, $args);
     100        return _wp_http_get_object()->head($url, $args);
    109101}
    110102
    111103/**
     
    116108 * @param array $response HTTP response.
    117109 * @return array The headers of the response. Empty array if incorrect parameter given.
    118110 */
    119 function wp_remote_retrieve_headers(&$response) {
     111function wp_remote_retrieve_headers($response) {
    120112        if ( is_wp_error($response) || ! isset($response['headers']) || ! is_array($response['headers']))
    121113                return array();
    122114
     
    132124 * @param string $header Header name to retrieve value from.
    133125 * @return string The header value. Empty string on if incorrect parameter given, or if the header doesnt exist.
    134126 */
    135 function wp_remote_retrieve_header(&$response, $header) {
     127function wp_remote_retrieve_header($response, $header) {
    136128        if ( is_wp_error($response) || ! isset($response['headers']) || ! is_array($response['headers']))
    137129                return '';
    138130
     
    152144 * @param array $response HTTP response.
    153145 * @return string the response code. Empty string on incorrect parameter given.
    154146 */
    155 function wp_remote_retrieve_response_code(&$response) {
     147function wp_remote_retrieve_response_code($response) {
    156148        if ( is_wp_error($response) || ! isset($response['response']) || ! is_array($response['response']))
    157149                return '';
    158150
     
    169161 * @param array $response HTTP response.
    170162 * @return string The response message. Empty string on incorrect parameter given.
    171163 */
    172 function wp_remote_retrieve_response_message(&$response) {
     164function wp_remote_retrieve_response_message($response) {
    173165        if ( is_wp_error($response) || ! isset($response['response']) || ! is_array($response['response']))
    174166                return '';
    175167
     
    184176 * @param array $response HTTP response.
    185177 * @return string The body of the response. Empty string if no body or incorrect parameter given.
    186178 */
    187 function wp_remote_retrieve_body(&$response) {
     179function wp_remote_retrieve_body($response) {
    188180        if ( is_wp_error($response) || ! isset($response['body']) )
    189181                return '';
    190182