Nessuna descrizione

class-wp-http-encoding.php 6.5KB

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