WordPress.org

Make WordPress Core

Ticket #8674: 8674.2.diff

File 8674.2.diff, 7.1 KB (added by jacobsantos, 9 years ago)

Better and complete implementation of gzip.

  • http.php

     
    1313 */
    1414
    1515/**
     16 * Implementation for deflate and gzip transfer encodings.
     17 *
     18 * Includes RFC 1950, RFC 1951, and RFC 1952.
     19 *
     20 * @since unknown
     21 * @package WordPress
     22 * @subpackage HTTP
     23 */
     24class WP_Http_Encoding {
     25
     26        /**
     27         * Compress raw string using the deflate format.
     28         *
     29         * Supports the RFC 1951 standard.
     30         *
     31         * @since unknown
     32         *
     33         * @param string $raw String to compress.
     34         * @param int $level Optional, default is 9. Compression level, 9 is highest.
     35         * @param string $supports Optional, not used. When implemented it will choose the right compression based on what the server supports.
     36         * @return string|bool False on failure.
     37         */
     38        function compress( $raw, $level = 9, $supports = null ) {
     39                return gzdeflate( $raw, $level );
     40        }
     41
     42        /**
     43         * Decompression of deflated string.
     44         *
     45         * Will attempt to decompress using the RFC 1950 standard, and if that fails
     46         * then the RFC 1951 standard deflate will be attempted. Finally, the RFC
     47         * 1952 standard gzip decode will be attempted. If all fail, then the
     48         * original compressed string will be returned.
     49         *
     50         * @since unknown
     51         *
     52         * @param string $compressed String to decompress.
     53         * @param int $length The optional length of the compressed data.
     54         * @return string|bool False on failure.
     55         */
     56        function decompress( $compressed, $length = null ) {
     57                $decompressed = gzinflate( $compressed );
     58
     59                if( false !== $decompressed )
     60                        return $decompressed;
     61
     62                $decompressed = gzuncompress( $compressed );
     63
     64                if( false !== $decompressed )
     65                        return $decompressed;
     66
     67                $decompressed = gzdecode( $compressed );
     68
     69                if( false !== $decompressed )
     70                        return $decompressed;
     71
     72                return $compressed;
     73        }
     74
     75        /**
     76         * What encoding types to accept and their priority values.
     77         *
     78         * @since unknown
     79         *
     80         * @return string Types of encoding to accept.
     81         */
     82        function accept_encoding() {
     83                $type = array;
     84                if( function_exists( 'gzinflate' ) )
     85                        $type[] = 'deflate;q=1.0';
     86
     87                if( function_exists( 'gzuncompress' ) )
     88                        $type[] = 'compress;q=0.5';
     89
     90                if( function_exists( 'gzdecode' ) )
     91                        $type[] = 'gzip;q=0.5';
     92
     93                return implode(', ', $type);
     94        }
     95
     96        /**
     97         * What enconding the content used when it was compressed to send in the headers.
     98         *
     99         * @since unknown
     100         *
     101         * @return string Content-Encoding string to send in the header.
     102         */
     103        function content_encoding() {
     104                return 'deflate';
     105        }
     106
     107        /**
     108         * Whether the content be decoded based on the headers.
     109         *
     110         * @since unknown
     111         *
     112         * @param array|string $headers All of the available headers.
     113         * @return bool
     114         */
     115        function should_decode($headers) {
     116                if( is_array( $headers ) ) {
     117                        if( array_key_exists('content-encoding', $headers) && ! empty( $headers['content-encoding'] ) )
     118                                return true;
     119                } else if( is_string( $headers ) ) {
     120                        return ( stripos($headers, 'content-encoding:') !== false );
     121                }
     122
     123                return false;
     124        }
     125
     126        /**
     127         * Whether decompression and compression are supported by the PHP version.
     128         *
     129         * Each function is tested instead of checking for the zlib extension, to
     130         * ensure that the functions all exist in the PHP version and aren't
     131         * disabled.
     132         *
     133         * @since unknown
     134         *
     135         * @return bool
     136         */
     137        function is_available() {
     138                return ( function_exists('gzuncompress') || function_exists('gzdeflate') ||
     139                                 function_exists('gzinflate') );
     140        }
     141}
     142
     143/**
    16144 * WordPress HTTP Class for managing HTTP Transports and making HTTP requests.
    17145 *
    18146 * This class is called for the functionality of making HTTP requests and should
     
    217345                        'httpversion' => apply_filters( 'http_request_version', '1.0'),
    218346                        'user-agent' => apply_filters( 'http_headers_useragent', 'WordPress/' . $wp_version ),
    219347                        'blocking' => true,
    220                         'headers' => array(), 'body' => null
     348                        'headers' => array(),
     349                        'body' => null,
     350                        'compress' => false,
     351                        'decompress' = true
    221352                );
    222353
    223354                $r = wp_parse_args( $args, $defaults );
     
    241372                        unset($r['headers']['user-agent']);
    242373                }
    243374
     375                if( WP_Http_Encoding::is_available() )
     376                        $r['headers']['Accept-Encoding'] = WP_Http_Encoding::accept_encoding();
     377
    244378                if ( is_null($r['body']) ) {
    245379                        $r['headers']['Content-Length'] = 0;
    246380                        $transports = WP_Http::_getTransport($r);
     
    578712                if ( ! empty( $process['body'] ) && isset( $arrHeaders['headers']['transfer-encoding'] ) && 'chunked' == $arrHeaders['headers']['transfer-encoding'] )
    579713                        $process['body'] = WP_Http::chunkTransferDecode($process['body']);
    580714
     715                if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($arrHeaders) )
     716                        $process['body'] = WP_Http_Encoding::decompress( $process['body'] );
     717
    581718                return array('headers' => $arrHeaders['headers'], 'body' => $process['body'], 'response' => $arrHeaders['response']);
    582719        }
    583720
     
    688825                if ( ! empty( $strResponse ) && isset( $processedHeaders['headers']['transfer-encoding'] ) && 'chunked' == $processedHeaders['headers']['transfer-encoding'] )
    689826                        $strResponse = WP_Http::chunkTransferDecode($strResponse);
    690827
     828                if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($processedHeaders) )
     829                        $strResponse = WP_Http_Encoding::decompress( $strResponse );
     830
    691831                return array('headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response']);
    692832        }
    693833
     
    799939                $strResponse = stream_get_contents($handle);
    800940                $meta = stream_get_meta_data($handle);
    801941
     942                fclose($handle);
     943
    802944                $processedHeaders = array();
    803945                if( isset( $meta['wrapper_data']['headers'] ) )
    804946                        $processedHeaders = WP_Http::processHeaders($meta['wrapper_data']['headers']);
     
    808950                if ( ! empty( $strResponse ) && isset( $processedHeaders['headers']['transfer-encoding'] ) && 'chunked' == $processedHeaders['headers']['transfer-encoding'] )
    809951                        $strResponse = WP_Http::chunkTransferDecode($strResponse);
    810952
    811                 fclose($handle);
     953                if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($processedHeaders) )
     954                        $strResponse = WP_Http_Encoding::decompress( $strResponse );
    812955
    813956                return array('headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response']);
    814957        }
     
    9221065                                $theBody = http_chunked_decode($theBody);
    9231066                }
    9241067
     1068                if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($theHeaders) )
     1069                        $theBody = http_inflate( $theBody );
     1070
    9251071                $theResponse = array();
    9261072                $theResponse['code'] = $info['response_code'];
    9271073                $theResponse['message'] = get_status_header_desc($info['response_code']);
     
    10451191                        $theHeaders = array( 'headers' => array() );
    10461192                        $theBody = '';
    10471193                }
     1194
    10481195                $response = array();
    10491196                $response['code'] = curl_getinfo( $handle, CURLINFO_HTTP_CODE );
    10501197                $response['message'] = get_status_header_desc($response['code']);
    10511198
    10521199                curl_close( $handle );
    10531200
     1201                if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($theHeaders) )
     1202                        $theBody = WP_Http_Encoding::decompress( $theBody );
     1203
    10541204                return array('headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $response);
    10551205        }
    10561206