WordPress.org

Make WordPress Core

Ticket #13777: 13777.2.patch

File 13777.2.patch, 19.7 KB (added by hakre, 4 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