| 2092 | 2092 | * then the RFC 1951 standard deflate will be attempted. Finally, the RFC |
| 2093 | 2093 | * 1952 standard gzip decode will be attempted. If all fail, then the |
| 2094 | 2094 | * original compressed string will be returned. |
| 2095 | 2095 | * |
| 2096 | 2096 | * @since 2.8.0 |
| 2097 | 2097 | * |
| 2098 | 2098 | * @param string $compressed String to decompress. |
| 2099 | 2099 | * @param int $length The optional length of the compressed data. |
| 2100 | 2100 | * @return string|bool False on failure. |
| 2101 | 2101 | */ |
| 2102 | 2102 | public static function decompress( $compressed, $length = null ) { |
| 2103 | 2103 | |
| 2104 | 2104 | if ( empty($compressed) ) |
| 2105 | 2105 | return $compressed; |
| 2106 | 2106 | |
| 2149 | 2146 | if ( substr($gzData, 0, 3) == "\x1f\x8b\x08" ) { |
| 2150 | 2147 | $i = 10; |
| 2151 | 2148 | $flg = ord( substr($gzData, 3, 1) ); |
| 2152 | 2149 | if ( $flg > 0 ) { |
| 2153 | 2150 | if ( $flg & 4 ) { |
| 2154 | 2151 | list($xlen) = unpack('v', substr($gzData, $i, 2) ); |
| 2155 | 2152 | $i = $i + 2 + $xlen; |
| 2156 | 2153 | } |
| 2157 | 2154 | if ( $flg & 8 ) |
| 2158 | 2155 | $i = strpos($gzData, "\0", $i) + 1; |
| 2159 | 2156 | if ( $flg & 16 ) |
| 2160 | 2157 | $i = strpos($gzData, "\0", $i) + 1; |
| 2161 | 2158 | if ( $flg & 2 ) |
| 2162 | 2159 | $i = $i + 2; |
| 2163 | 2160 | } |
| 2169 | | // Compressed data from java.util.zip.Deflater amongst others. |
| 2170 | | $decompressed = @gzinflate( substr($gzData, 2) ); |
| 2171 | | if ( false !== $decompressed ) |
| | 2168 | // If the data is Huffman Encoded, we must first strip the leading 2 byte Huffman marker for gzinflate() |
| | 2169 | // The Response is Huffman coded by many compressors such as java.util.zip.Deflater, |
| | 2170 | // Ruby’s Zlib::Deflate, and .NET's System.IO.Compression.DeflateStream. |
| | 2171 | // See http://decompres.blogspot.com/ for a quick explanation of this data type |
| | 2172 | $huffman_encoded = false; |
| | 2173 | list( , $first_nibble ) = unpack( 'h', $gzData ); // low nibble of first byte should be 0x08 |
| | 2174 | list( , $first_two_bytes ) = unpack( 'n', $gzData ); // First 2 bytes should be divisible by 0x1F |
| | 2175 | if ( 0x08 == $first_nibble && 0 == ( $first_two_bytes % 0x1F ) ) |
| | 2176 | $huffman_encoded = true; |
| | 2177 | |
| | 2178 | if ( $huffman_encoded ) { |
| | 2179 | if ( false !== ( $decompressed = @gzinflate( substr( $gzData, 2 ) ) ) ) |
| | 2180 | return $decompressed; |
| | 2181 | } |
| | 2182 | |
| | 2183 | if ( "\x50\x4b\x03\x04" == substr( $gzData, 0, 4 ) ) { |
| | 2184 | // ZIP file format header |
| | 2185 | // Offset 6: 2 bytes, General-purpose field |
| | 2186 | // Offset 26: 2 bytes, filename length |
| | 2187 | // Offset 28: 2 bytes, optional field length |
| | 2188 | // Offset 30: Filename field, followed by optional field, followed immediately by data |
| | 2189 | list( , $general_purpose_flag ) = unpack( 'v', substr( $gzData, 6, 2 ) ); |
| | 2190 | |
| | 2191 | // If the file has been compressed on the fly, 0x08 bit is set of the general purpose field |
| | 2192 | // We can use this to differentiate between a compressed document, and a ZIP file |
| | 2193 | $zip_compressed_on_the_fly = ( 0x08 == (0x08 & $general_purpose_flag ) ); |
| | 2194 | |
| | 2195 | if ( ! $zip_compressed_on_the_fly ) { |
| | 2196 | return $gzData; // Don't attempt to decode a compressed zip file from the server |
| | 2197 | } |
| | 2198 | |
| | 2199 | // Determine the first byte of data, based on the above ZIP header offsets: |
| | 2200 | $first_file_start = array_sum( unpack( 'v2', substr( $gzData, 26, 4 ) ) ); |
| | 2201 | if ( false !== ( $decompressed = @gzinflate( substr( $gzData, 30 + $first_file_start ) ) ) ) { |
| | 2202 | return $decompressed; |
| | 2203 | } |
| | 2204 | |
| | 2205 | return false; |
| | 2206 | } |
| | 2207 | |
| | 2208 | // Finally fall back to straight gzinflate |
| | 2209 | if ( false !== ( $decompressed = @gzinflate( $gzData ) ) ) { |