wp/wp-includes/class-wp-http-encoding.php
changeset 7 cf61fcea0001
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
       
     1 <?php
       
     2 /**
       
     3  * HTTP API: WP_Http_Encoding class
       
     4  *
       
     5  * @package WordPress
       
     6  * @subpackage HTTP
       
     7  * @since 4.4.0
       
     8  */
       
     9 
       
    10 /**
       
    11  * Core class used to implement deflate and gzip transfer encoding support for HTTP requests.
       
    12  *
       
    13  * Includes RFC 1950, RFC 1951, and RFC 1952.
       
    14  *
       
    15  * @since 2.8.0
       
    16  */
       
    17 class WP_Http_Encoding {
       
    18 
       
    19 	/**
       
    20 	 * Compress raw string using the deflate format.
       
    21 	 *
       
    22 	 * Supports the RFC 1951 standard.
       
    23 	 *
       
    24 	 * @since 2.8.0
       
    25 	 *
       
    26 	 * @static
       
    27 	 *
       
    28 	 * @param string $raw String to compress.
       
    29 	 * @param int $level Optional, default is 9. Compression level, 9 is highest.
       
    30 	 * @param string $supports Optional, not used. When implemented it will choose the right compression based on what the server supports.
       
    31 	 * @return string|false False on failure.
       
    32 	 */
       
    33 	public static function compress( $raw, $level = 9, $supports = null ) {
       
    34 		return gzdeflate( $raw, $level );
       
    35 	}
       
    36 
       
    37 	/**
       
    38 	 * Decompression of deflated string.
       
    39 	 *
       
    40 	 * Will attempt to decompress using the RFC 1950 standard, and if that fails
       
    41 	 * then the RFC 1951 standard deflate will be attempted. Finally, the RFC
       
    42 	 * 1952 standard gzip decode will be attempted. If all fail, then the
       
    43 	 * original compressed string will be returned.
       
    44 	 *
       
    45 	 * @since 2.8.0
       
    46 	 *
       
    47 	 * @static
       
    48 	 *
       
    49 	 * @param string $compressed String to decompress.
       
    50 	 * @param int $length The optional length of the compressed data.
       
    51 	 * @return string|bool False on failure.
       
    52 	 */
       
    53 	public static function decompress( $compressed, $length = null ) {
       
    54 
       
    55 		if ( empty($compressed) )
       
    56 			return $compressed;
       
    57 
       
    58 		if ( false !== ( $decompressed = @gzinflate( $compressed ) ) )
       
    59 			return $decompressed;
       
    60 
       
    61 		if ( false !== ( $decompressed = self::compatible_gzinflate( $compressed ) ) )
       
    62 			return $decompressed;
       
    63 
       
    64 		if ( false !== ( $decompressed = @gzuncompress( $compressed ) ) )
       
    65 			return $decompressed;
       
    66 
       
    67 		if ( function_exists('gzdecode') ) {
       
    68 			$decompressed = @gzdecode( $compressed );
       
    69 
       
    70 			if ( false !== $decompressed )
       
    71 				return $decompressed;
       
    72 		}
       
    73 
       
    74 		return $compressed;
       
    75 	}
       
    76 
       
    77 	/**
       
    78 	 * Decompression of deflated string while staying compatible with the majority of servers.
       
    79 	 *
       
    80 	 * Certain Servers will return deflated data with headers which PHP's gzinflate()
       
    81 	 * function cannot handle out of the box. The following function has been created from
       
    82 	 * various snippets on the gzinflate() PHP documentation.
       
    83 	 *
       
    84 	 * Warning: Magic numbers within. Due to the potential different formats that the compressed
       
    85 	 * data may be returned in, some "magic offsets" are needed to ensure proper decompression
       
    86 	 * takes place. For a simple progmatic way to determine the magic offset in use, see:
       
    87 	 * https://core.trac.wordpress.org/ticket/18273
       
    88 	 *
       
    89 	 * @since 2.8.1
       
    90 	 * @link https://core.trac.wordpress.org/ticket/18273
       
    91 	 * @link https://secure.php.net/manual/en/function.gzinflate.php#70875
       
    92 	 * @link https://secure.php.net/manual/en/function.gzinflate.php#77336
       
    93 	 *
       
    94 	 * @static
       
    95 	 *
       
    96 	 * @param string $gzData String to decompress.
       
    97 	 * @return string|bool False on failure.
       
    98 	 */
       
    99 	public static function compatible_gzinflate($gzData) {
       
   100 
       
   101 		// Compressed data might contain a full header, if so strip it for gzinflate().
       
   102 		if ( substr($gzData, 0, 3) == "\x1f\x8b\x08" ) {
       
   103 			$i = 10;
       
   104 			$flg = ord( substr($gzData, 3, 1) );
       
   105 			if ( $flg > 0 ) {
       
   106 				if ( $flg & 4 ) {
       
   107 					list($xlen) = unpack('v', substr($gzData, $i, 2) );
       
   108 					$i = $i + 2 + $xlen;
       
   109 				}
       
   110 				if ( $flg & 8 )
       
   111 					$i = strpos($gzData, "\0", $i) + 1;
       
   112 				if ( $flg & 16 )
       
   113 					$i = strpos($gzData, "\0", $i) + 1;
       
   114 				if ( $flg & 2 )
       
   115 					$i = $i + 2;
       
   116 			}
       
   117 			$decompressed = @gzinflate( substr($gzData, $i, -8) );
       
   118 			if ( false !== $decompressed )
       
   119 				return $decompressed;
       
   120 		}
       
   121 
       
   122 		// Compressed data from java.util.zip.Deflater amongst others.
       
   123 		$decompressed = @gzinflate( substr($gzData, 2) );
       
   124 		if ( false !== $decompressed )
       
   125 			return $decompressed;
       
   126 
       
   127 		return false;
       
   128 	}
       
   129 
       
   130 	/**
       
   131 	 * What encoding types to accept and their priority values.
       
   132 	 *
       
   133 	 * @since 2.8.0
       
   134 	 *
       
   135 	 * @static
       
   136 	 *
       
   137 	 * @param string $url
       
   138 	 * @param array  $args
       
   139 	 * @return string Types of encoding to accept.
       
   140 	 */
       
   141 	public static function accept_encoding( $url, $args ) {
       
   142 		$type = array();
       
   143 		$compression_enabled = self::is_available();
       
   144 
       
   145 		if ( ! $args['decompress'] ) // Decompression specifically disabled.
       
   146 			$compression_enabled = false;
       
   147 		elseif ( $args['stream'] ) // Disable when streaming to file.
       
   148 			$compression_enabled = false;
       
   149 		elseif ( isset( $args['limit_response_size'] ) ) // If only partial content is being requested, we won't be able to decompress it.
       
   150 			$compression_enabled = false;
       
   151 
       
   152 		if ( $compression_enabled ) {
       
   153 			if ( function_exists( 'gzinflate' ) )
       
   154 				$type[] = 'deflate;q=1.0';
       
   155 
       
   156 			if ( function_exists( 'gzuncompress' ) )
       
   157 				$type[] = 'compress;q=0.5';
       
   158 
       
   159 			if ( function_exists( 'gzdecode' ) )
       
   160 				$type[] = 'gzip;q=0.5';
       
   161 		}
       
   162 
       
   163 		/**
       
   164 		 * Filters the allowed encoding types.
       
   165 		 *
       
   166 		 * @since 3.6.0
       
   167 		 *
       
   168 		 * @param array  $type Encoding types allowed. Accepts 'gzinflate',
       
   169 		 *                     'gzuncompress', 'gzdecode'.
       
   170 		 * @param string $url  URL of the HTTP request.
       
   171 		 * @param array  $args HTTP request arguments.
       
   172 		 */
       
   173 		$type = apply_filters( 'wp_http_accept_encoding', $type, $url, $args );
       
   174 
       
   175 		return implode(', ', $type);
       
   176 	}
       
   177 
       
   178 	/**
       
   179 	 * What encoding the content used when it was compressed to send in the headers.
       
   180 	 *
       
   181 	 * @since 2.8.0
       
   182 	 *
       
   183 	 * @static
       
   184 	 *
       
   185 	 * @return string Content-Encoding string to send in the header.
       
   186 	 */
       
   187 	public static function content_encoding() {
       
   188 		return 'deflate';
       
   189 	}
       
   190 
       
   191 	/**
       
   192 	 * Whether the content be decoded based on the headers.
       
   193 	 *
       
   194 	 * @since 2.8.0
       
   195 	 *
       
   196 	 * @static
       
   197 	 *
       
   198 	 * @param array|string $headers All of the available headers.
       
   199 	 * @return bool
       
   200 	 */
       
   201 	public static function should_decode($headers) {
       
   202 		if ( is_array( $headers ) ) {
       
   203 			if ( array_key_exists('content-encoding', $headers) && ! empty( $headers['content-encoding'] ) )
       
   204 				return true;
       
   205 		} elseif ( is_string( $headers ) ) {
       
   206 			return ( stripos($headers, 'content-encoding:') !== false );
       
   207 		}
       
   208 
       
   209 		return false;
       
   210 	}
       
   211 
       
   212 	/**
       
   213 	 * Whether decompression and compression are supported by the PHP version.
       
   214 	 *
       
   215 	 * Each function is tested instead of checking for the zlib extension, to
       
   216 	 * ensure that the functions all exist in the PHP version and aren't
       
   217 	 * disabled.
       
   218 	 *
       
   219 	 * @since 2.8.0
       
   220 	 *
       
   221 	 * @static
       
   222 	 *
       
   223 	 * @return bool
       
   224 	 */
       
   225 	public static function is_available() {
       
   226 		return ( function_exists('gzuncompress') || function_exists('gzdeflate') || function_exists('gzinflate') );
       
   227 	}
       
   228 }