Merge pull request #808 from zachborboa/master

Add additional check for decoding gzip-encoded responses
This commit is contained in:
Zach Borboa
2023-08-29 09:28:04 -07:00
committed by GitHub
2 changed files with 198 additions and 2 deletions
+16 -2
View File
@@ -1933,8 +1933,22 @@ class Curl extends BaseCurl
}
if (
isset($response_headers['Content-Encoding']) && $response_headers['Content-Encoding'] === 'gzip' &&
is_string($response)
(
// Ensure that the server says the response is compressed with
// gzip and the response has not already been decoded. Use
// is_string() to ensure that $response is a string being passed
// to mb_strpos() and gzdecode().
isset($response_headers['Content-Encoding']) &&
$response_headers['Content-Encoding'] === 'gzip' &&
is_string($response) &&
mb_strpos($response, "\x1f" . "\x8b" . "\x08", 0, 'US-ASCII') === 0
) || (
// Or ensure that the response looks like it is compressed with
// gzip. Use is_string() to ensure that $response is a string
// being passed to mb_strpos() and gzdecode().
is_string($response) &&
mb_strpos($response, "\x1f" . "\x8b" . "\x08", 0, 'US-ASCII') === 0
)
) {
// Use @ to suppress message "Warning gzdecode(): data error".
$decoded_response = @gzdecode($response);
+182
View File
@@ -4885,6 +4885,36 @@ class PHPCurlClassTest extends \PHPUnit\Framework\TestCase
$this->assertEquals('hello', $test->curl->response);
}
public function testGzipAlreadyDecodedWithHeader()
{
$test = new Test();
// Send header containing all supported encoding types by setting
// CURLOPT_ENCODING to an empty string.
$test->curl->setOpt(CURLOPT_ENCODING, '');
$test->server('json_response', 'POST', [
'key' => 'content-encoding',
'value' => 'gzip',
'body' => gzencode('hello'),
]);
$this->assertEquals('hello', $test->curl->response);
}
public function testGzipAlreadyDecodedWithoutHeader()
{
$test = new Test();
// Send header containing all supported encoding types by setting
// CURLOPT_ENCODING to an empty string.
$test->curl->setOpt(CURLOPT_ENCODING, '');
$test->server('json_response', 'POST', [
'body' => gzencode('hello'),
]);
$this->assertEquals('hello', $test->curl->response);
}
public function testGzipDecodingFailureWithoutWarning()
{
$test = new Test();
@@ -4921,6 +4951,158 @@ class PHPCurlClassTest extends \PHPUnit\Framework\TestCase
$this->assertEquals('bar', $test->curl->response->{'123'});
}
public function testGzipContentEncoding()
{
// [
// [
// 'Response header content-encoding: "gzip"',
// 'Response header content-encoding: "notgzip"',
// 'Response header content-encoding: "" (empty)',
// 'Response header without content-encoding',
// ],
// [
// 'Content is valid gzip-encoded',
// 'Content is not valid gzip-encoded',
// 'Content is not gzip-encoded',
// ],
// ]
$tests = [
// Response header content-encoding: "gzip"
// Content is valid gzip-encoded
[
'data' => [
'key' => 'content-encoding',
'value' => 'gzip',
'body' => gzencode('hello'),
],
'expect_response' => 'hello',
],
// Response header content-encoding: "gzip"
// Content is not valid gzip-encoded
[
'data' => [
'key' => 'content-encoding',
'value' => 'gzip',
'body' => 'not-gzip-encoded',
],
'expect_response' => 'not-gzip-encoded',
],
// Response header content-encoding: "gzip"
// Content is not gzip-encoded
[
'data' => [
'headers' => [
'content-type: text/html; charset=utf-8',
'content-encoding: gzip',
],
'body' => '<html><body>not gzip-encoded</body></html>',
],
'expect_response' => '<html><body>not gzip-encoded</body></html>',
],
// Response header content-encoding: "notgzip"
// Content is valid gzip-encoded
[
'data' => [
'key' => 'content-encoding',
'value' => 'notgzip',
'body' => gzencode('hello'),
],
'expect_response' => 'hello',
],
// Response header content-encoding: "notgzip"
// Content is not valid gzip-encoded
[
'data' => [
'key' => 'content-encoding',
'value' => 'notgzip',
'body' => base64_encode('not-valid-gzip-encoded'),
],
'expect_response' => base64_encode('not-valid-gzip-encoded'),
],
// Response header content-encoding: "notgzip"
// Content is not gzip-encoded
[
'data' => [
'key' => 'content-encoding',
'value' => 'notgzip',
'body' => 'not-gzip-encoded',
],
'expect_response' => 'not-gzip-encoded',
],
// Response header content-encoding: "" (empty)
// Content is valid gzip-encoded
[
'data' => [
'key' => 'content-encoding',
'value' => '',
'body' => gzencode('hello'),
],
'expect_response' => 'hello',
],
// Response header content-encoding: "" (empty)
// Content is not valid gzip-encoded
[
'data' => [
'key' => 'content-encoding',
'value' => '',
'body' => base64_encode('not-valid-gzip-encoded'),
],
'expect_response' => base64_encode('not-valid-gzip-encoded'),
],
// Response header content-encoding: "" (empty)
// Content is not gzip-encoded
[
'data' => [
'key' => 'content-encoding',
'value' => '',
'body' => 'not-gzip-encoded',
],
'expect_response' => 'not-gzip-encoded',
],
// Response header without content-encoding
// Content is valid gzip-encoded
[
'data' => [
'body' => gzencode('hello'),
],
'expect_response' => 'hello',
],
// Response header without content-encoding
// Content is not valid gzip-encoded
[
'data' => [
'body' => base64_encode('not-valid-gzip-encoded'),
],
'expect_response' => base64_encode('not-valid-gzip-encoded'),
],
// Response header without content-encoding
// Content is not gzip-encoded
[
'data' => [
'body' => 'not-gzip-encoded',
],
'expect_response' => 'not-gzip-encoded',
],
];
foreach ($tests as $test_data) {
$test = new Test();
$test->server('json_response', 'POST', $test_data['data']);
$this->assertEquals($test_data['expect_response'], $test->curl->response);
}
}
public function testAfterSendAttemptCount()
{
$test = new Test();