Make WordPress Core

Changeset 25153


Ignore:
Timestamp:
08/28/2013 06:52:09 AM (11 years ago)
Author:
dd32
Message:

WP_HTTP: Improve WP_HTTP::chunkTransferDecode() to properly handle binary data and chunked responses which include data in the page that looks like a chunked response.
This also fixes a case where the gzip'd data would become corrupt after chunked decoding as \r\n was replaced with \n in the data stream. Fixes #23463

File:
1 edited

Legend:

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

    r25150 r25153  
    460460     * Decodes chunk transfer-encoding, based off the HTTP 1.1 specification.
    461461     *
    462      * Based off the HTTP http_encoding_dechunk function. Does not support UTF-8. Does not support
    463      * returning footer headers. Shouldn't be too difficult to support it though.
     462     * Based off the HTTP http_encoding_dechunk function.
    464463     *
    465464     * @link http://tools.ietf.org/html/rfc2616#section-19.4.6 Process for chunked decoding.
    466465     *
    467      * @todo Add support for footer chunked headers.
    468466     * @access public
    469467     * @since 2.7.0
     
    473471     * @return string Chunked decoded body on success or raw body on failure.
    474472     */
    475     function chunkTransferDecode($body) {
    476         $body = str_replace(array("\r\n", "\r"), "\n", $body);
    477         // The body is not chunked encoding or is malformed.
    478         if ( ! preg_match( '/^[0-9a-f]+(\s|\n)+/mi', trim($body) ) )
     473    public static function chunkTransferDecode( $body ) {
     474        // The body is not chunked encoded or is malformed.
     475        if ( ! preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', trim( $body ) ) )
    479476            return $body;
    480477
    481         $parsedBody = '';
    482         //$parsedHeaders = array(); Unsupported
     478        $parsed_body = '';
     479        $body_original = $body; // We'll be altering $body, so need a backup in case of error
    483480
    484481        while ( true ) {
    485             $hasChunk = (bool) preg_match( '/^([0-9a-f]+)(\s|\n)+/mi', $body, $match );
    486 
    487             if ( $hasChunk ) {
    488                 if ( empty( $match[1] ) )
    489                     return $body;
    490 
    491                 $length = hexdec( $match[1] );
    492                 $chunkLength = strlen( $match[0] );
    493 
    494                 $strBody = substr($body, $chunkLength, $length);
    495                 $parsedBody .= $strBody;
    496 
    497                 $body = ltrim(str_replace(array($match[0], $strBody), '', $body), "\n");
    498 
    499                 if ( "0" == trim($body) )
    500                     return $parsedBody; // Ignore footer headers.
    501             } else {
    502                 return $body;
    503             }
     482            $has_chunk = (bool) preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', $body_copy, $match );
     483            if ( ! $has_chunk || empty( $match[1] ) )
     484                return $body_original;
     485
     486            $length = hexdec( $match[1] );
     487            $chunk_length = strlen( $match[0] );
     488
     489            // Parse out the chunk of data
     490            $parsed_body .= substr( $body, $chunk_length, $length );
     491
     492            // Remove the chunk from the raw data
     493            $body = substr( $body, $length + $chunk_length );
     494
     495            // End of document
     496            if ( '0' === trim( $body ) )
     497                return $parsed_body;
    504498        }
    505499    }
Note: See TracChangeset for help on using the changeset viewer.