function httprl_decode_data in HTTP Parallel Request & Threading Library 6
Same name and namespace in other branches
- 7 httprl.module \httprl_decode_data()
Will decode chunked transfer-encoding and gzip/deflate content-encoding.
Parameters
object $result: An object from httprl_send_request.
1 call to httprl_decode_data()
- httprl_post_processing in ./
httprl.module - Run post processing on the request if we are done reading.
File
- ./
httprl.module, line 2413 - HTTP Parallel Request Library module.
Code
function httprl_decode_data(&$result) {
if (isset($result->headers['transfer-encoding']) && $result->headers['transfer-encoding'] == 'chunked') {
$stream_position = 0;
$output = '';
$data = $result->data;
while ($stream_position < httprl_strlen($data)) {
// Get the number of bytes to read for this chunk.
$rawnum = substr($data, $stream_position, strpos(substr($data, $stream_position), "\r\n") + 2);
$num = hexdec(trim($rawnum));
// Get the position to read from.
$stream_position += httprl_strlen($rawnum);
// Extract the chunk.
$chunk = substr($data, $stream_position, $num);
// Decompress if compressed.
if (isset($result->headers['content-encoding'])) {
if ($result->headers['content-encoding'] === 'gzip') {
$chunk = @gzinflate(substr($chunk, 10));
}
elseif ($result->headers['content-encoding'] === 'deflate') {
$chunk = @gzinflate($chunk);
}
elseif ($result->headers['content-encoding'] === 'br' && is_callable('brotli_uncompress')) {
$chunk = @brotli_uncompress($chunk);
}
if ($chunk === FALSE) {
break;
}
}
// Glue the chunks together.
$output .= $chunk;
$stream_position += httprl_strlen($chunk);
}
if ($chunk !== FALSE) {
$result->data = $output;
}
}
elseif (isset($result->headers['content-encoding'])) {
if ($result->headers['content-encoding'] === 'gzip') {
$chunk = @gzinflate(substr($result->data, 10));
}
elseif ($result->headers['content-encoding'] === 'deflate') {
$chunk = @gzinflate($result->data);
}
elseif ($result->headers['content-encoding'] === 'br' && is_callable('brotli_uncompress')) {
$chunk = @brotli_uncompress($result->data);
}
if (isset($chunk) && $chunk !== FALSE) {
$result->data = $chunk;
}
}
// Cut up response for one sided Range requests.
if (array_key_exists('max_data_size', $result->options)) {
$result->code = 206;
// Make the data conform to the range request.
$new_data = array();
foreach ($result->ranges as $range) {
// Get only the last X number of bytes.
if (!is_numeric($range['start'])) {
$new_data[] = substr($result->data, -$range['end']);
}
elseif (!is_numeric($range['end'])) {
$new_data[] = substr($result->data, $range['start']);
}
else {
$new_data[] = substr($result->data, $range['start'], $range['end'] + 1 - $range['start']);
}
}
$result->data = implode('', $new_data);
// Fix content-length for fake 206s.
if (isset($result->headers['content-length'])) {
$result->headers['content-length'] = httprl_strlen($result->data);
}
}
// Reassemble multipart/byteranges response.
if (isset($result->headers['content-type']) && strpos($result->headers['content-type'], 'multipart/byteranges; boundary=') !== FALSE) {
// Get boundary string.
$boundary = "\r\n--" . substr($result->headers['content-type'], 31);
$datas = explode($boundary, $result->data);
$result->data = '';
foreach ($datas as $data) {
$split = preg_split("/\r\n\r\n|\n\n|\r\r/", $data, 2);
if (count($split) < 2) {
continue;
}
// Separate the data from the headers.
list($response, $data) = $split;
$response = array_filter(preg_split("/\r\n|\n|\r/", $response));
// Parse the response headers.
while ($line = trim(array_shift($response))) {
list($name, $value) = explode(':', $line, 2);
$name = strtolower($name);
// Add key value pairs to the header.
if ($name != 'content-range') {
$result->headers[$name] = trim($value);
}
}
$result->data .= $data;
}
// Fix content-length for multipart/byteranges.
if (isset($result->headers['content-length'])) {
$result->headers['content-length'] = httprl_strlen($result->data);
}
}
}