WordPress.org

Make WordPress Core

Ticket #23472: 23472.diff

File 23472.diff, 8.8 KB (added by dd32, 14 months ago)
  • wp-includes/class-http.php

     
    9595                        'decompress' => true, 
    9696                        'sslverify' => true, 
    9797                        'stream' => false, 
    98                         'filename' => null 
     98                        'filename' => null, 
     99                        'first-x-bytes' => null, 
    99100                ); 
    100101 
    101102                // Pre-parse for the HEAD checks. 
     
    166167                // Construct Cookie: header if any cookies are set 
    167168                WP_Http::buildCookieHeader( $r ); 
    168169 
    169                 if ( WP_Http_Encoding::is_available() ) 
     170                if ( WP_Http_Encoding::is_available( $r ) ) 
    170171                        $r['headers']['Accept-Encoding'] = WP_Http_Encoding::accept_encoding(); 
    171172 
    172173                if ( ( ! is_null( $r['body'] ) && '' != $r['body'] ) || 'POST' == $r['method'] || 'PUT' == $r['method'] ) { 
     
    731732 
    732733                $strResponse = ''; 
    733734                $bodyStarted = false; 
     735                $keep_reading = true; 
     736                $block_size = 4096; 
     737                if ( isset( $r['first-x-bytes'] ) ) 
     738                        $block_size = min( $block_size, $r['first-x-bytes'] ); 
    734739 
    735740                // If streaming to a file setup the file handle 
    736741                if ( $r['stream'] ) { 
     
    741746                        if ( ! $stream_handle ) 
    742747                                return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) ); 
    743748 
    744                         while ( ! feof($handle) ) { 
    745                                 $block = fread( $handle, 4096 ); 
    746                                 if ( $bodyStarted ) { 
    747                                         fwrite( $stream_handle, $block ); 
    748                                 } else { 
     749                        $bytes_written = 0; 
     750                        while ( ! feof($handle) && $keep_reading ) { 
     751                                $block = fread( $handle, $block_size ); 
     752                                if ( ! $bodyStarted ) { 
    749753                                        $strResponse .= $block; 
    750754                                        if ( strpos( $strResponse, "\r\n\r\n" ) ) { 
    751755                                                $process = WP_Http::processResponse( $strResponse ); 
    752756                                                $bodyStarted = true; 
    753                                                 fwrite( $stream_handle, $process['body'] ); 
     757                                                $block = $process['body']; 
    754758                                                unset( $strResponse ); 
    755759                                                $process['body'] = ''; 
    756760                                        } 
    757761                                } 
     762                                 
     763                                if ( isset( $r['first-x-bytes'] ) && ( $bytes_written + strlen( $block ) ) > $r['first-x-bytes'] ) { 
     764                                        $block = substr( $block, 0, ( $r['first-x-bytes'] - $bytes_written ) ); 
     765                                } 
     766                                $bytes_written += fwrite( $stream_handle, $block );                              
     767                                 
     768                                $keep_reading = !isset( $r['first-x-bytes'] ) || $bytes_written < $r['first-x-bytes']; 
    758769                        } 
    759770 
    760771                        fclose( $stream_handle ); 
    761772 
    762773                } else { 
    763                         while ( ! feof($handle) ) 
    764                                 $strResponse .= fread( $handle, 4096 ); 
     774                        $header_length = 0; 
     775                        while ( ! feof( $handle ) && $keep_reading ) { 
     776                                $block = fread( $handle, $block_size ); 
     777                                $strResponse .= $block; 
     778                                if ( ! $bodyStarted && strpos( $strResponse, "\r\n\r\n" ) ) { 
     779                                        $header_length = strpos( $strResponse, "\r\n\r\n" ) + 4; 
     780                                        $bodyStarted = true; 
     781                                } 
     782                                $keep_reading = ( ! $bodyStarted || !isset( $r['first-x-bytes'] ) || strlen( $strResponse ) < ( $header_length + $r['first-x-bytes'] ) ); 
     783                        } 
    765784 
    766785                        $process = WP_Http::processResponse( $strResponse ); 
    767786                        unset( $strResponse ); 
     787 
    768788                } 
    769789 
    770790                fclose( $handle ); 
     
    790810                if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($arrHeaders['headers']) ) 
    791811                        $process['body'] = WP_Http_Encoding::decompress( $process['body'] ); 
    792812 
     813                if ( isset( $r['first-x-bytes'] ) && strlen( $process['body'] ) > $r['first-x-bytes'] ) 
     814                        $process['body'] = substr( $process['body'], 0, $r['first-x-bytes'] ); 
     815 
    793816                return array( 'headers' => $arrHeaders['headers'], 'body' => $process['body'], 'response' => $arrHeaders['response'], 'cookies' => $arrHeaders['cookies'], 'filename' => $r['filename'] ); 
    794817        } 
    795818 
     
    933956                        return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() ); 
    934957                } 
    935958 
     959                $max_bytes = isset( $r['first-x-bytes'] ) ? intval( $r['first-x-bytes'] ) : -1; 
    936960                if ( $r['stream'] ) { 
    937961                        if ( ! WP_DEBUG ) 
    938962                                $stream_handle = @fopen( $r['filename'], 'w+' ); 
     
    942966                        if ( ! $stream_handle ) 
    943967                                return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) ); 
    944968 
    945                         stream_copy_to_stream( $handle, $stream_handle ); 
     969                        stream_copy_to_stream( $handle, $stream_handle, $max_bytes ); 
    946970 
    947971                        fclose( $stream_handle ); 
    948972                        $strResponse = ''; 
    949973                } else { 
    950                         $strResponse = stream_get_contents( $handle ); 
     974                        $strResponse = stream_get_contents( $handle, $max_bytes ); 
    951975                } 
    952976 
    953977                $meta = stream_get_meta_data( $handle ); 
     
    10111035class WP_Http_Curl { 
    10121036 
    10131037        /** 
    1014          * Temporary header storage for use with streaming to a file. 
     1038         * Temporary header storage for during requests. 
    10151039         * 
    10161040         * @since 3.2.0 
    10171041         * @access private 
     
    10201044        private $headers = ''; 
    10211045 
    10221046        /** 
     1047         * Temporary body storage for during requests. 
     1048         * 
     1049         * @since 3.6.0 
     1050         * @access private 
     1051         * @var string 
     1052         */ 
     1053        private $body = ''; 
     1054 
     1055        /** 
     1056         * The maximum amount of data to recieve from the remote server 
     1057         * 
     1058         * @since 3.6.0 
     1059         * @access private 
     1060         * @var int 
     1061         */ 
     1062        private $max_body_length = false; 
     1063 
     1064        /** 
     1065         * The file resource used for streaming to file. 
     1066         * 
     1067         * @since 3.6.0 
     1068         * @access private 
     1069         * @var resource 
     1070         */ 
     1071        private $stream_handle = false; 
     1072 
     1073        /** 
    10231074         * Send a HTTP request to a URI using cURL extension. 
    10241075         * 
    10251076         * @access public 
     
    11081159                                break; 
    11091160                } 
    11101161 
    1111                 if ( true === $r['blocking'] ) 
     1162                if ( true === $r['blocking'] ) { 
    11121163                        curl_setopt( $handle, CURLOPT_HEADERFUNCTION, array( $this, 'stream_headers' ) ); 
     1164                        curl_setopt( $handle, CURLOPT_WRITEFUNCTION, array( $this, 'stream_body' ) ); 
     1165                } 
    11131166 
    11141167                curl_setopt( $handle, CURLOPT_HEADER, false ); 
    11151168 
     1169                if ( isset( $r['first-x-bytes'] ) ) 
     1170                        $this->max_body_length = intval( $r['first-x-bytes'] ); 
     1171 
    11161172                // If streaming to a file open a file handle, and setup our curl streaming handler 
    11171173                if ( $r['stream'] ) { 
    11181174                        if ( ! WP_DEBUG ) 
    1119                                 $stream_handle = @fopen( $r['filename'], 'w+' ); 
     1175                                $this->stream_handle = @fopen( $r['filename'], 'w+' ); 
    11201176                        else 
    1121                                 $stream_handle = fopen( $r['filename'], 'w+' ); 
    1122                         if ( ! $stream_handle ) 
     1177                                $this->stream_handle = fopen( $r['filename'], 'w+' ); 
     1178                        if ( ! $this->stream_handle ) 
    11231179                                return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) ); 
    1124                         curl_setopt( $handle, CURLOPT_FILE, $stream_handle ); 
    11251180                } 
    11261181 
    11271182                if ( !empty( $r['headers'] ) ) { 
     
    11501205                } 
    11511206 
    11521207                $theResponse = curl_exec( $handle ); 
    1153                 $theBody = ''; 
    11541208                $theHeaders = WP_Http::processHeaders( $this->headers ); 
     1209                $theBody = $this->body; 
    11551210 
    1156                 if ( strlen($theResponse) > 0 && ! is_bool( $theResponse ) ) // is_bool: when using $args['stream'], curl_exec will return (bool)true 
    1157                         $theBody = $theResponse; 
     1211                $this->headers = ''; 
     1212                $this->body = ''; 
    11581213 
    11591214                // If no response 
    1160                 if ( 0 == strlen( $theResponse ) && empty( $theHeaders['headers'] ) ) { 
     1215                if ( 0 == strlen( $theBody ) && empty( $theHeaders['headers'] ) ) { 
    11611216                        if ( $curl_error = curl_error( $handle ) ) 
    11621217                                return new WP_Error( 'http_request_failed', $curl_error ); 
    11631218                        if ( in_array( curl_getinfo( $handle, CURLINFO_HTTP_CODE ), array( 301, 302 ) ) ) 
    11641219                                return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) ); 
    11651220                } 
    11661221 
    1167                 $this->headers = ''; 
    1168  
    11691222                $response = array(); 
    11701223                $response['code'] = curl_getinfo( $handle, CURLINFO_HTTP_CODE ); 
    11711224                $response['message'] = get_status_header_desc($response['code']); 
     
    11731226                curl_close( $handle ); 
    11741227 
    11751228                if ( $r['stream'] ) 
    1176                         fclose( $stream_handle ); 
     1229                        fclose( $this->stream_handle ); 
    11771230 
    11781231                // See #11305 - When running under safe mode, redirection is disabled above. Handle it manually. 
    11791232                if ( ! empty( $theHeaders['headers']['location'] ) && 0 !== $r['_redirection'] ) { // _redirection: The requested number of redirections 
     
    12051258        } 
    12061259 
    12071260        /** 
     1261         * Grab the body of the cURL request 
     1262         * 
     1263         * The contents of the document are passed in chunks, so we append to the $body property for temporary storage. 
     1264         * Returning a length shorter than the length of $data passed in will cause cURL to abort the request as "completed" 
     1265         * 
     1266         * @since 3.6.0 
     1267         * @access private 
     1268         * @return int 
     1269         */ 
     1270        private function stream_body( $handle, $data ) { 
     1271                if ( $this->max_body_length && ( strlen( $this->body ) + strlen( $data ) ) > $this->max_body_length ) 
     1272                        $data = substr( $data, 0, ( $this->max_body_length - strlen( $this->body ) ) ); 
     1273 
     1274                if ( $this->stream_handle ) 
     1275                        fwrite( $this->stream_handle, $data ); 
     1276                else 
     1277                        $this->body .= $data; 
     1278 
     1279                return strlen( $data ); 
     1280        } 
     1281 
     1282        /** 
    12081283         * Whether this class can be used for retrieving an URL. 
    12091284         * 
    12101285         * @static 
     
    17851860         * 
    17861861         * @return bool 
    17871862         */ 
    1788         public static function is_available() { 
     1863        public static function is_available( $args ) { 
     1864                // If only partial content is being requested, we won't be able to decompress it 
     1865                if ( isset( $args['first-x-bytes'] ) ) 
     1866                        return false; 
     1867 
    17891868                return ( function_exists('gzuncompress') || function_exists('gzdeflate') || function_exists('gzinflate') ); 
    17901869        } 
    17911870}