WordPress.org

Make WordPress Core

Ticket #21182: 21182.diff

File 21182.diff, 11.7 KB (added by dd32, 5 years ago)
  • wp-includes/class-http.php

     
    158158                        $r['headers'] = array();
    159159
    160160                if ( ! is_array( $r['headers'] ) ) {
    161                         $processedHeaders = WP_Http::processHeaders( $r['headers'] );
     161                        $processedHeaders = WP_Http::processHeaders( $r['headers'], $url );
    162162                        $r['headers'] = $processedHeaders['headers'];
    163163                }
    164164
     
    195195                                $r['headers']['Content-Length'] = strlen( $r['body'] );
    196196                }
    197197
    198                 return $this->_dispatch_request($url, $r);
     198                $response = $this->_dispatch_request($url, $r);
     199                if ( ! empty( $r['cookies'] ) ) {
     200                        // Append cookies that were used in this request to the response
     201                        $cookies_set = wp_list_pluck( $response['cookies'], 'name' );
     202                        foreach ( $r['cookies'] as $cookie ) {
     203                                if ( ! in_array( $cookie->name, $cookies_set ) && $cookie->test( $url ) ) {
     204                                        $response['cookies'][] = $cookie;
     205                                }
     206                        }
     207                }
     208
     209                return $response;
    199210        }
    200211
    201212        /**
     
    349360         * @since 2.7.0
    350361         *
    351362         * @param string|array $headers
     363         * @param string $url The URL that was requested
    352364         * @return array Processed string headers. If duplicate headers are encountered,
    353365         *                                      Then a numbered array is returned as the value of that header-key.
    354366         */
    355         public static function processHeaders($headers) {
     367        public static function processHeaders( $headers, $url ) {
    356368                // split headers, one per array element
    357369                if ( is_string($headers) ) {
    358370                        // tolerate line terminator: CRLF = LF (RFC 2616 19.3)
     
    399411                        } else {
    400412                                $newheaders[ $key ] = $value;
    401413                        }
    402                         if ( 'set-cookie' == $key )
    403                                 $cookies[] = new WP_Http_Cookie( $value );
     414                        if ( 'set-cookie' == $key || 'set-cookie2' == $key )
     415                                $cookies[] = new WP_Http_Cookie( $value, $url );
    404416                }
    405417
    406418                return array('response' => $response, 'headers' => $newheaders, 'cookies' => $cookies);
     
    420432         * @param array $r Full array of args passed into ::request()
    421433         */
    422434        public static function buildCookieHeader( &$r ) {
    423                 if ( ! empty($r['cookies']) ) {
     435                if ( ! empty( $r['cookies'] ) ) {
    424436                        $cookies_header = '';
    425437                        foreach ( (array) $r['cookies'] as $cookie ) {
    426438                                $cookies_header .= $cookie->getHeaderValue() . '; ';
     
    593605
    594606                return $absolute_path . '/' . ltrim( $path, '/' );
    595607        }
     608
     609        static function handle_redirects( $url, $args, $response ) {
     610                // If no redirects are present, or, redirects were not requested, perform no action.
     611                if ( ! isset( $response['headers']['location'] ) || 0 === $args['_redirection'] )
     612                        return null;
     613
     614                // Only perform redirections on redirection http codes
     615                if ( $response['response']['code'] > 399 || $response['response']['code'] < 300 )
     616                        return null;
     617
     618                // Don't redirect if we've run out of redirects
     619                if ( $args['redirection']-- <= 0 )
     620                        return new WP_Error( 'http_request_failed', __('Too many redirects.') );
     621
     622                $redirect_location = WP_HTTP::make_absolute_url( $response['headers']['location'], $url );
     623
     624                // POST requests should not POST to a redirected location
     625                if ( 'POST' == $args['method'] ) {
     626                        if ( in_array( $response['response']['code'], array( 302, 303 ) ) )
     627                                $args['method'] = 'GET';
     628                }
     629
     630                // Include valid cookies in the redirect process
     631                if ( ! empty( $response['cookies'] ) ) {
     632                        foreach ( $response['cookies'] as $cookie ) {
     633                                if ( $cookie->test( $redirect_location ) )
     634                                        $args['cookies'][] = $cookie;
     635                        }
     636                }
     637
     638                return wp_remote_request( $redirect_location, $args ); 
     639        }
    596640}
    597641
    598642/**
     
    802846                if ( true === $secure_transport )
    803847                        error_reporting($error_reporting);
    804848
    805                 $arrHeaders = WP_Http::processHeaders( $process['headers'] );
     849                $arrHeaders = WP_Http::processHeaders( $process['headers'], $url );
    806850
    807                 // If location is found, then assume redirect and redirect to location.
    808                 if ( isset($arrHeaders['headers']['location']) && 0 !== $r['_redirection'] ) {
    809                         if ( $r['redirection']-- > 0 ) {
    810                                 return wp_remote_request( WP_HTTP::make_absolute_url( $arrHeaders['headers']['location'], $url ), $r);
    811                         } else {
    812                                 return new WP_Error('http_request_failed', __('Too many redirects.'));
    813                         }
    814                 }
     851                $response = array(
     852                        'headers' => $arrHeaders['headers'],
     853                        'body' => null, // Not yet processed
     854                        'response' => $arrHeaders['response'],
     855                        'cookies' => $arrHeaders['cookies'],
     856                        'filename' => $r['filename']
     857                );
    815858
     859                // Handle redirects
     860                if ( null !== ( $redirect_response = WP_HTTP::handle_redirects( $url, $r, $response ) ) )
     861                        return $redirect_response;
     862
    816863                // If the body was chunk encoded, then decode it.
    817864                if ( ! empty( $process['body'] ) && isset( $arrHeaders['headers']['transfer-encoding'] ) && 'chunked' == $arrHeaders['headers']['transfer-encoding'] )
    818865                        $process['body'] = WP_Http::chunkTransferDecode($process['body']);
     
    823870                if ( isset( $r['limit_response_size'] ) && strlen( $process['body'] ) > $r['limit_response_size'] )
    824871                        $process['body'] = substr( $process['body'], 0, $r['limit_response_size'] );
    825872
    826                 return array( 'headers' => $arrHeaders['headers'], 'body' => $process['body'], 'response' => $arrHeaders['response'], 'cookies' => $arrHeaders['cookies'], 'filename' => $r['filename'] );
     873                $response['body'] = $process['body'];
     874
     875                return $response;
    827876        }
    828877
    829878        /**
     
    9911040
    9921041                $processedHeaders = array();
    9931042                if ( isset( $meta['wrapper_data']['headers'] ) )
    994                         $processedHeaders = WP_Http::processHeaders($meta['wrapper_data']['headers']);
     1043                        $processedHeaders = WP_Http::processHeaders( $meta['wrapper_data']['headers'], $url);
    9951044                else
    996                         $processedHeaders = WP_Http::processHeaders($meta['wrapper_data']);
     1045                        $processedHeaders = WP_Http::processHeaders( $meta['wrapper_data'], $url );
    9971046
    998                 if ( ! empty( $processedHeaders['headers']['location'] ) && 0 !== $r['_redirection'] ) { // _redirection: The requested number of redirections
    999                         if ( $r['redirection']-- > 0 ) {
    1000                                 return wp_remote_request( WP_HTTP::make_absolute_url( $processedHeaders['headers']['location'], $url ), $r );
    1001                         } else {
    1002                                 return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) );
    1003                         }
    1004                 }
     1047                $response = array(
     1048                        'headers' => $processedHeaders['headers'],
     1049                        'body' => null,
     1050                        'response' => $processedHeaders['response'],
     1051                        'cookies' => $processedHeaders['cookies'],
     1052                        'filename' => $r['filename']
     1053                );
    10051054
     1055                // Handle redirects
     1056                if ( null !== ( $redirect_response = WP_HTTP::handle_redirects( $url, $r, $response ) ) )
     1057                        return $redirect_response;
     1058
    10061059                if ( ! empty( $strResponse ) && isset( $processedHeaders['headers']['transfer-encoding'] ) && 'chunked' == $processedHeaders['headers']['transfer-encoding'] )
    10071060                        $strResponse = WP_Http::chunkTransferDecode($strResponse);
    10081061
    10091062                if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($processedHeaders['headers']) )
    10101063                        $strResponse = WP_Http_Encoding::decompress( $strResponse );
    10111064
    1012                 return array( 'headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response'], 'cookies' => $processedHeaders['cookies'], 'filename' => $r['filename'] );
     1065                $response['body'] = $strResponse;
     1066
     1067                return $response;
    10131068        }
    10141069
    10151070        /**
     
    12351290                }
    12361291
    12371292                $theResponse = curl_exec( $handle );
    1238                 $theHeaders = WP_Http::processHeaders( $this->headers );
     1293                $theHeaders = WP_Http::processHeaders( $this->headers, $url );
    12391294                $theBody = $this->body;
    12401295
    12411296                $this->headers = '';
     
    12621317                if ( $r['stream'] )
    12631318                        fclose( $this->stream_handle );
    12641319
    1265                 // See #11305 - When running under safe mode, redirection is disabled above. Handle it manually.
    1266                 if ( ! empty( $theHeaders['headers']['location'] ) && 0 !== $r['_redirection'] ) { // _redirection: The requested number of redirections
    1267                         if ( $r['redirection']-- > 0 ) {
    1268                                 return wp_remote_request( WP_HTTP::make_absolute_url( $theHeaders['headers']['location'], $url ), $r );
    1269                         } else {
    1270                                 return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) );
    1271                         }
    1272                 }
     1320                $response = array(
     1321                        'headers' => $theHeaders['headers'],
     1322                        'body' => null,
     1323                        'response' => $response,
     1324                        'cookies' => $theHeaders['cookies'],
     1325                        'filename' => $r['filename']
     1326                );
    12731327
     1328                // Handle redirects
     1329                if ( null !== ( $redirect_response = WP_HTTP::handle_redirects( $url, $r, $response ) ) )
     1330                        return $redirect_response;
     1331
    12741332                if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($theHeaders['headers']) )
    12751333                        $theBody = WP_Http_Encoding::decompress( $theBody );
    12761334
    1277                 return array( 'headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $response, 'cookies' => $theHeaders['cookies'], 'filename' => $r['filename'] );
     1335                $response['body'] = $theBody;
     1336
     1337                return $response;
    12781338        }
    12791339
    12801340        /**
     
    15491609         * @since 2.8.0
    15501610         * @var string
    15511611         */
    1552         var $name;
     1612        var $name = '';
    15531613
    15541614        /**
    15551615         * Cookie value.
     
    15571617         * @since 2.8.0
    15581618         * @var string
    15591619         */
    1560         var $value;
     1620        var $value = '';
    15611621
    15621622        /**
    15631623         * When the cookie expires.
     
    15651625         * @since 2.8.0
    15661626         * @var string
    15671627         */
    1568         var $expires;
     1628        var $expires = null;
    15691629
    15701630        /**
    15711631         * Cookie URL path.
     
    15731633         * @since 2.8.0
    15741634         * @var string
    15751635         */
    1576         var $path;
     1636        var $path = null;
    15771637
    15781638        /**
    15791639         * Cookie Domain.
     
    15811641         * @since 2.8.0
    15821642         * @var string
    15831643         */
    1584         var $domain;
     1644        var $domain = null;
    15851645
    15861646        /**
    15871647         * Sets up this cookie object.
     
    16031663         *
    16041664         * @param string|array $data Raw cookie data.
    16051665         */
    1606         function __construct( $data ) {
     1666        function __construct( $data, $requested_url = '' ) {
     1667                $arrURL = parse_url( $requested_url );
     1668                $this->domain = $arrURL['host'];
     1669                $this->path = isset( $arrURL['path'] ) ? $arrURL['path'] : '/';
     1670                if ( '/' != substr( $this->path, -1 ) )
     1671                        $this->path = dirname( $this->path ) . '/';
     1672
    16071673                if ( is_string( $data ) ) {
    16081674                        // Assume it's a header string direct from a previous request
    16091675                        $pairs = explode( ';', $data );
     
    16321698                                return false;
    16331699
    16341700                        // Set properties based directly on parameters
    1635                         $this->name   = $data['name'];
    1636                         $this->value  = isset( $data['value'] ) ? $data['value'] : '';
    1637                         $this->path   = isset( $data['path'] ) ? $data['path'] : '';
    1638                         $this->domain = isset( $data['domain'] ) ? $data['domain'] : '';
     1701                        foreach ( array( 'name', 'value', 'path', 'domain' ) as $field ) {
     1702                                if ( isset( $data[ $field ] ) )
     1703                                        $this->$field = $data[ $field ];
     1704                        }
    16391705
    16401706                        if ( isset( $data['expires'] ) )
    16411707                                $this->expires = is_int( $data['expires'] ) ? $data['expires'] : strtotime( $data['expires'] );
     
    16561722         * @return boolean true if allowed, false otherwise.
    16571723         */
    16581724        function test( $url ) {
     1725                if ( empty( $this->name ) )
     1726                        return false;
     1727
    16591728                // Expires - if expired then nothing else matters
    16601729                if ( isset( $this->expires ) && time() > $this->expires )
    16611730                        return false;
    16621731
    16631732                // Get details on the URL we're thinking about sending to
    16641733                $url = parse_url( $url );
    1665                 $url['port'] = isset( $url['port'] ) ? $url['port'] : 80;
     1734                $url['port'] = isset( $url['port'] ) ? $url['port'] : ( 'https' == $url['scheme'] ? 443 : 80 );
    16661735                $url['path'] = isset( $url['path'] ) ? $url['path'] : '/';
    16671736
    16681737                // Values to use for comparison against the URL
    16691738                $path   = isset( $this->path )   ? $this->path   : '/';
    1670                 $port   = isset( $this->port )   ? $this->port   : 80;
     1739                $port   = isset( $this->port )   ? $this->port   : null;
    16711740                $domain = isset( $this->domain ) ? strtolower( $this->domain ) : strtolower( $url['host'] );
    16721741                if ( false === stripos( $domain, '.' ) )
    16731742                        $domain .= '.local';
     
    16781747                        return false;
    16791748
    16801749                // Port - supports "port-lists" in the format: "80,8000,8080"
    1681                 if ( !in_array( $url['port'], explode( ',', $port) ) )
     1750                if ( !empty( $port ) && !in_array( $url['port'], explode( ',', $port) ) )
    16821751                        return false;
    16831752
    16841753                // Path - request path must start with path restriction