Index: bootstrap.inc =================================================================== --- bootstrap.inc (revision 2) +++ bootstrap.inc (working copy) @@ -529,7 +529,7 @@ // Determine if the browser accepts gzipped data. if (@strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === FALSE && function_exists('gzencode')) { // Strip the gzip header and run uncompress. - $cache->data = gzinflate(substr(substr($cache->data, 10), 0, -8)); + $cache->data = _decodeGzip($cache->data); } elseif (function_exists('gzencode')) { header('Content-Encoding: gzip'); @@ -897,3 +897,101 @@ } return $t; } + +// +-----------------------------------------------------------------------+ +// | function _decodeGzip | +// | Author: Richard Heyes | +// | Source: PEAR Package: HTTP_Request v.1.4.0 | +// | http://pear.php.net/package/HTTP_Request/ | +// +-----------------------------------------------------------------------+ + +/** +* Decodes the message-body encoded by gzip +* +* The real decoding work is done by gzinflate() built-in function, this +* method only parses the header and checks data for compliance with +* RFC 1952 +* +* @access private +* @param string gzip-encoded data +* @return string decoded data +*/ +function _decodeGzip($data) +{ + $length = strlen($data); + // If it doesn't look like gzip-encoded data, don't bother + if (18 > $length || strcmp(substr($data, 0, 2), "\x1f\x8b")) { + return $data; + } + $method = ord(substr($data, 2, 1)); + if (8 != $method) { + return '_decodeGzip(): unknown compression method'; + } + $flags = ord(substr($data, 3, 1)); + if ($flags & 224) { + return '_decodeGzip(): reserved bits are set'; + } + + // header is 10 bytes minimum. may be longer, though. + $headerLength = 10; + // extra fields, need to skip 'em + if ($flags & 4) { + if ($length - $headerLength - 2 < 8) { + return '_decodeGzip(): data too short'; + } + $extraLength = unpack('v', substr($data, 10, 2)); + if ($length - $headerLength - 2 - $extraLength[1] < 8) { + return '_decodeGzip(): data too short'; + } + $headerLength += $extraLength[1] + 2; + } + // file name, need to skip that + if ($flags & 8) { + if ($length - $headerLength - 1 < 8) { + return '_decodeGzip(): data too short'; + } + $filenameLength = strpos(substr($data, $headerLength), chr(0)); + if (false === $filenameLength || $length - $headerLength - $filenameLength - 1 < 8) { + return '_decodeGzip(): data too short'; + } + $headerLength += $filenameLength + 1; + } + // comment, need to skip that also + if ($flags & 16) { + if ($length - $headerLength - 1 < 8) { + return '_decodeGzip(): data too short'; + } + $commentLength = strpos(substr($data, $headerLength), chr(0)); + if (false === $commentLength || $length - $headerLength - $commentLength - 1 < 8) { + return '_decodeGzip(): data too short'; + } + $headerLength += $commentLength + 1; + } + // have a CRC for header. let's check + if ($flags & 1) { + if ($length - $headerLength - 2 < 8) { + return '_decodeGzip(): data too short'; + } + $crcReal = 0xffff & crc32(substr($data, 0, $headerLength)); + $crcStored = unpack('v', substr($data, $headerLength, 2)); + if ($crcReal != $crcStored[1]) { + return '_decodeGzip(): header CRC check failed'; + } + $headerLength += 2; + } + // unpacked data CRC and size at the end of encoded data + $tmp = unpack('V2', substr($data, -8)); + $dataCrc = $tmp[1]; + $dataSize = $tmp[2]; + + // finally, call the gzinflate() function + $unpacked = @gzinflate(substr($data, $headerLength, -8), $dataSize); + if (false === $unpacked) { + return '_decodeGzip(): gzinflate() call failed'; + } elseif ($dataSize != strlen($unpacked)) { + return '_decodeGzip(): data size check failed'; + } elseif ($dataCrc != crc32($unpacked)) { + return '_decodeGzip(): data CRC check failed'; + } + return $unpacked; +} \ No newline at end of file