function HTTP_Response::_decodeGzip in Flickr API 5
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
Parameters
string gzip-encoded data:
Return value
string decoded data
1 call to HTTP_Response::_decodeGzip()
- HTTP_Response::process in phpFlickr/
PEAR/ HTTP/ Request.php - Processes a HTTP response
File
- phpFlickr/
PEAR/ HTTP/ Request.php, line 1396
Class
- HTTP_Response
- Response class to complement the Request class
Code
function _decodeGzip($data) {
if (HTTP_REQUEST_MBSTRING) {
$oldEncoding = mb_internal_encoding();
mb_internal_encoding('iso-8859-1');
}
$length = strlen($data);
// If it doesn't look like gzip-encoded data, don't bother
if (18 > $length || strcmp(substr($data, 0, 2), "")) {
return $data;
}
$method = ord(substr($data, 2, 1));
if (8 != $method) {
return PEAR::raiseError('_decodeGzip(): unknown compression method', HTTP_REQUEST_ERROR_GZIP_METHOD);
}
$flags = ord(substr($data, 3, 1));
if ($flags & 224) {
return PEAR::raiseError('_decodeGzip(): reserved bits are set', HTTP_REQUEST_ERROR_GZIP_DATA);
}
// 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 PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
}
$extraLength = unpack('v', substr($data, 10, 2));
if ($length - $headerLength - 2 - $extraLength[1] < 8) {
return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
}
$headerLength += $extraLength[1] + 2;
}
// file name, need to skip that
if ($flags & 8) {
if ($length - $headerLength - 1 < 8) {
return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
}
$filenameLength = strpos(substr($data, $headerLength), chr(0));
if (false === $filenameLength || $length - $headerLength - $filenameLength - 1 < 8) {
return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
}
$headerLength += $filenameLength + 1;
}
// comment, need to skip that also
if ($flags & 16) {
if ($length - $headerLength - 1 < 8) {
return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
}
$commentLength = strpos(substr($data, $headerLength), chr(0));
if (false === $commentLength || $length - $headerLength - $commentLength - 1 < 8) {
return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
}
$headerLength += $commentLength + 1;
}
// have a CRC for header. let's check
if ($flags & 1) {
if ($length - $headerLength - 2 < 8) {
return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
}
$crcReal = 0xffff & crc32(substr($data, 0, $headerLength));
$crcStored = unpack('v', substr($data, $headerLength, 2));
if ($crcReal != $crcStored[1]) {
return PEAR::raiseError('_decodeGzip(): header CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC);
}
$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 PEAR::raiseError('_decodeGzip(): gzinflate() call failed', HTTP_REQUEST_ERROR_GZIP_READ);
}
elseif ($dataSize != strlen($unpacked)) {
return PEAR::raiseError('_decodeGzip(): data size check failed', HTTP_REQUEST_ERROR_GZIP_READ);
}
elseif ((0xffffffff & $dataCrc) != (0xffffffff & crc32($unpacked))) {
return PEAR::raiseError('_decodeGzip(): data CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC);
}
if (HTTP_REQUEST_MBSTRING) {
mb_internal_encoding($oldEncoding);
}
return $unpacked;
}