WordPress.org

Make WordPress Core

Changeset 23605


Ignore:
Timestamp:
03/04/13 04:24:26 (14 months ago)
Author:
dd32
Message:

WP_HTTP: Enable developers to request the first x bytes of a document using the 'limit-response-size' parameter.
The connection to the remote server will be disconnected after x number of bytes has been received.
See #23472

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/class-http.php

    r23603 r23605  
    9696            'sslverify' => true, 
    9797            'stream' => false, 
    98             'filename' => null 
     98            'filename' => null, 
     99            'limit-response-size' => null, 
    99100        ); 
    100101 
     
    734735        $strResponse = ''; 
    735736        $bodyStarted = false; 
     737        $keep_reading = true; 
     738        $block_size = 4096; 
     739        if ( isset( $r['limit-response-size'] ) ) 
     740            $block_size = min( $block_size, $r['limit-response-size'] ); 
    736741 
    737742        // If streaming to a file setup the file handle 
     
    744749                return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) ); 
    745750 
    746             while ( ! feof($handle) ) { 
    747                 $block = fread( $handle, 4096 ); 
    748                 if ( $bodyStarted ) { 
    749                     fwrite( $stream_handle, $block ); 
    750                 } else { 
     751            $bytes_written = 0; 
     752            while ( ! feof($handle) && $keep_reading ) { 
     753                $block = fread( $handle, $block_size ); 
     754                if ( ! $bodyStarted ) { 
    751755                    $strResponse .= $block; 
    752756                    if ( strpos( $strResponse, "\r\n\r\n" ) ) { 
    753757                        $process = WP_Http::processResponse( $strResponse ); 
    754758                        $bodyStarted = true; 
    755                         fwrite( $stream_handle, $process['body'] ); 
     759                        $block = $process['body']; 
    756760                        unset( $strResponse ); 
    757761                        $process['body'] = ''; 
    758762                    } 
    759763                } 
     764                 
     765                if ( isset( $r['limit-response-size'] ) && ( $bytes_written + strlen( $block ) ) > $r['limit-response-size'] ) 
     766                    $block = substr( $block, 0, ( $r['limit-response-size'] - $bytes_written ) ); 
     767 
     768                $bytes_written += fwrite( $stream_handle, $block );              
     769                 
     770                $keep_reading = !isset( $r['limit-response-size'] ) || $bytes_written < $r['limit-response-size']; 
    760771            } 
    761772 
     
    763774 
    764775        } else { 
    765             while ( ! feof($handle) ) 
    766                 $strResponse .= fread( $handle, 4096 ); 
     776            $header_length = 0; 
     777            while ( ! feof( $handle ) && $keep_reading ) { 
     778                $block = fread( $handle, $block_size ); 
     779                $strResponse .= $block; 
     780                if ( ! $bodyStarted && strpos( $strResponse, "\r\n\r\n" ) ) { 
     781                    $header_length = strpos( $strResponse, "\r\n\r\n" ) + 4; 
     782                    $bodyStarted = true; 
     783                } 
     784                $keep_reading = ( ! $bodyStarted || !isset( $r['limit-response-size'] ) || strlen( $strResponse ) < ( $header_length + $r['limit-response-size'] ) ); 
     785            } 
    767786 
    768787            $process = WP_Http::processResponse( $strResponse ); 
    769788            unset( $strResponse ); 
     789 
    770790        } 
    771791 
     
    792812        if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($arrHeaders['headers']) ) 
    793813            $process['body'] = WP_Http_Encoding::decompress( $process['body'] ); 
     814 
     815        if ( isset( $r['limit-response-size'] ) && strlen( $process['body'] ) > $r['limit-response-size'] ) 
     816            $process['body'] = substr( $process['body'], 0, $r['limit-response-size'] ); 
    794817 
    795818        return array( 'headers' => $arrHeaders['headers'], 'body' => $process['body'], 'response' => $arrHeaders['response'], 'cookies' => $arrHeaders['cookies'], 'filename' => $r['filename'] ); 
     
    937960        } 
    938961 
     962        $max_bytes = isset( $r['limit-response-size'] ) ? intval( $r['limit-response-size'] ) : -1; 
    939963        if ( $r['stream'] ) { 
    940964            if ( ! WP_DEBUG ) 
     
    946970                return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) ); 
    947971 
    948             stream_copy_to_stream( $handle, $stream_handle ); 
     972            stream_copy_to_stream( $handle, $stream_handle, $max_bytes ); 
    949973 
    950974            fclose( $stream_handle ); 
    951975            $strResponse = ''; 
    952976        } else { 
    953             $strResponse = stream_get_contents( $handle ); 
     977            $strResponse = stream_get_contents( $handle, $max_bytes ); 
    954978        } 
    955979 
     
    10181042 
    10191043    /** 
    1020      * Temporary header storage for use with streaming to a file. 
     1044     * Temporary header storage for during requests. 
    10211045     * 
    10221046     * @since 3.2.0 
     
    10251049     */ 
    10261050    private $headers = ''; 
     1051 
     1052    /** 
     1053     * Temporary body storage for during requests. 
     1054     * 
     1055     * @since 3.6.0 
     1056     * @access private 
     1057     * @var string 
     1058     */ 
     1059    private $body = ''; 
     1060 
     1061    /** 
     1062     * The maximum amount of data to recieve from the remote server 
     1063     * 
     1064     * @since 3.6.0 
     1065     * @access private 
     1066     * @var int 
     1067     */ 
     1068    private $max_body_length = false; 
     1069 
     1070    /** 
     1071     * The file resource used for streaming to file. 
     1072     * 
     1073     * @since 3.6.0 
     1074     * @access private 
     1075     * @var resource 
     1076     */ 
     1077    private $stream_handle = false; 
    10271078 
    10281079    /** 
     
    11151166        } 
    11161167 
    1117         if ( true === $r['blocking'] ) 
     1168        if ( true === $r['blocking'] ) { 
    11181169            curl_setopt( $handle, CURLOPT_HEADERFUNCTION, array( $this, 'stream_headers' ) ); 
     1170            curl_setopt( $handle, CURLOPT_WRITEFUNCTION, array( $this, 'stream_body' ) ); 
     1171        } 
    11191172 
    11201173        curl_setopt( $handle, CURLOPT_HEADER, false ); 
     1174 
     1175        if ( isset( $r['limit-response-size'] ) ) 
     1176            $this->max_body_length = intval( $r['limit-response-size'] ); 
    11211177 
    11221178        // If streaming to a file open a file handle, and setup our curl streaming handler 
    11231179        if ( $r['stream'] ) { 
    11241180            if ( ! WP_DEBUG ) 
    1125                 $stream_handle = @fopen( $r['filename'], 'w+' ); 
     1181                $this->stream_handle = @fopen( $r['filename'], 'w+' ); 
    11261182            else 
    1127                 $stream_handle = fopen( $r['filename'], 'w+' ); 
    1128             if ( ! $stream_handle ) 
     1183                $this->stream_handle = fopen( $r['filename'], 'w+' ); 
     1184            if ( ! $this->stream_handle ) 
    11291185                return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) ); 
    1130             curl_setopt( $handle, CURLOPT_FILE, $stream_handle ); 
    11311186        } 
    11321187 
     
    11571212 
    11581213        $theResponse = curl_exec( $handle ); 
    1159         $theBody = ''; 
    11601214        $theHeaders = WP_Http::processHeaders( $this->headers ); 
    1161  
    1162         if ( strlen($theResponse) > 0 && ! is_bool( $theResponse ) ) // is_bool: when using $args['stream'], curl_exec will return (bool)true 
    1163             $theBody = $theResponse; 
     1215        $theBody = $this->body; 
     1216 
     1217        $this->headers = ''; 
     1218        $this->body = ''; 
    11641219 
    11651220        // If no response 
    1166         if ( 0 == strlen( $theResponse ) && empty( $theHeaders['headers'] ) ) { 
     1221        if ( 0 == strlen( $theBody ) && empty( $theHeaders['headers'] ) ) { 
    11671222            if ( $curl_error = curl_error( $handle ) ) 
    11681223                return new WP_Error( 'http_request_failed', $curl_error ); 
     
    11711226        } 
    11721227 
    1173         $this->headers = ''; 
    1174  
    11751228        $response = array(); 
    11761229        $response['code'] = curl_getinfo( $handle, CURLINFO_HTTP_CODE ); 
     
    11801233 
    11811234        if ( $r['stream'] ) 
    1182             fclose( $stream_handle ); 
     1235            fclose( $this->stream_handle ); 
    11831236 
    11841237        // See #11305 - When running under safe mode, redirection is disabled above. Handle it manually. 
     
    12091262        $this->headers .= $headers; 
    12101263        return strlen( $headers ); 
     1264    } 
     1265 
     1266    /** 
     1267     * Grab the body of the cURL request 
     1268     * 
     1269     * The contents of the document are passed in chunks, so we append to the $body property for temporary storage. 
     1270     * Returning a length shorter than the length of $data passed in will cause cURL to abort the request as "completed" 
     1271     * 
     1272     * @since 3.6.0 
     1273     * @access private 
     1274     * @return int 
     1275     */ 
     1276    private function stream_body( $handle, $data ) { 
     1277        if ( $this->max_body_length && ( strlen( $this->body ) + strlen( $data ) ) > $this->max_body_length ) 
     1278            $data = substr( $data, 0, ( $this->max_body_length - strlen( $this->body ) ) ); 
     1279 
     1280        if ( $this->stream_handle ) 
     1281            fwrite( $this->stream_handle, $data ); 
     1282        else 
     1283            $this->body .= $data; 
     1284 
     1285        return strlen( $data ); 
    12111286    } 
    12121287 
     
    17451820        elseif ( $args['stream'] ) // disable when streaming to file 
    17461821            $compression_enabled = false; 
     1822        elseif ( isset( $args['limit-response-size'] ) ) // If only partial content is being requested, we won't be able to decompress it 
     1823            $compression_enabled = false; 
    17471824 
    17481825        if ( $compression_enabled ) { 
Note: See TracChangeset for help on using the changeset viewer.