mirror of
https://github.com/php/php-src.git
synced 2026-04-16 12:31:06 +02:00
Merge branch 'PHP-7.1'
This commit is contained in:
@@ -755,8 +755,10 @@ finish:
|
||||
|
||||
while (!body && !php_stream_eof(stream)) {
|
||||
size_t http_header_line_length;
|
||||
|
||||
if (php_stream_get_line(stream, http_header_line, HTTP_HEADER_BLOCK_SIZE, &http_header_line_length) && *http_header_line != '\n' && *http_header_line != '\r') {
|
||||
char *e = http_header_line + http_header_line_length - 1;
|
||||
char *http_header_value;
|
||||
if (*e != '\n') {
|
||||
do { /* partial header */
|
||||
if (php_stream_get_line(stream, http_header_line, HTTP_HEADER_BLOCK_SIZE, &http_header_line_length) == NULL) {
|
||||
@@ -770,26 +772,54 @@ finish:
|
||||
while (*e == '\n' || *e == '\r') {
|
||||
e--;
|
||||
}
|
||||
http_header_line_length = e - http_header_line + 1;
|
||||
http_header_line[http_header_line_length] = '\0';
|
||||
|
||||
if (!strncasecmp(http_header_line, "Location: ", 10)) {
|
||||
/* The primary definition of an HTTP header in RFC 7230 states:
|
||||
* > Each header field consists of a case-insensitive field name followed
|
||||
* > by a colon (":"), optional leading whitespace, the field value, and
|
||||
* > optional trailing whitespace. */
|
||||
|
||||
/* Strip trailing whitespace */
|
||||
while (*e == ' ' || *e == '\t') {
|
||||
e--;
|
||||
}
|
||||
|
||||
/* Terminate header line */
|
||||
e++;
|
||||
*e = '\0';
|
||||
http_header_line_length = e - http_header_line;
|
||||
|
||||
http_header_value = memchr(http_header_line, ':', http_header_line_length);
|
||||
if (http_header_value) {
|
||||
http_header_value++; /* Skip ':' */
|
||||
|
||||
/* Strip leading whitespace */
|
||||
while (http_header_value < e
|
||||
&& (*http_header_value == ' ' || *http_header_value == '\t')) {
|
||||
http_header_value++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strncasecmp(http_header_line, "Location:", sizeof("Location:")-1)) {
|
||||
if (context && (tmpzval = php_stream_context_get_option(context, "http", "follow_location")) != NULL) {
|
||||
follow_location = zval_is_true(tmpzval);
|
||||
} else if (!((response_code >= 300 && response_code < 304) || 307 == response_code || 308 == response_code)) {
|
||||
} else if (!((response_code >= 300 && response_code < 304)
|
||||
|| 307 == response_code || 308 == response_code)) {
|
||||
/* we shouldn't redirect automatically
|
||||
if follow_location isn't set and response_code not in (300, 301, 302, 303 and 307)
|
||||
see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.1
|
||||
RFC 7238 defines 308: http://tools.ietf.org/html/rfc7238 */
|
||||
follow_location = 0;
|
||||
}
|
||||
strlcpy(location, http_header_line + 10, sizeof(location));
|
||||
} else if (!strncasecmp(http_header_line, "Content-Type: ", 14)) {
|
||||
php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, http_header_line + 14, 0);
|
||||
} else if (!strncasecmp(http_header_line, "Content-Length: ", 16)) {
|
||||
file_size = atoi(http_header_line + 16);
|
||||
strlcpy(location, http_header_value, sizeof(location));
|
||||
} else if (!strncasecmp(http_header_line, "Content-Type:", sizeof("Content-Type:")-1)) {
|
||||
php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, http_header_value, 0);
|
||||
} else if (!strncasecmp(http_header_line, "Content-Length:", sizeof("Content-Length")-1)) {
|
||||
file_size = atoi(http_header_value);
|
||||
php_stream_notify_file_size(context, file_size, http_header_line, 0);
|
||||
} else if (!strncasecmp(http_header_line, "Transfer-Encoding: chunked", sizeof("Transfer-Encoding: chunked"))) {
|
||||
} else if (
|
||||
!strncasecmp(http_header_line, "Transfer-Encoding:", sizeof("Transfer-Encoding")-1)
|
||||
&& !strncasecmp(http_header_value, "Chunked", sizeof("Chunked")-1)
|
||||
) {
|
||||
|
||||
/* create filter to decode response body */
|
||||
if (!(options & STREAM_ONLY_GET_HEADERS)) {
|
||||
@@ -808,13 +838,9 @@ finish:
|
||||
}
|
||||
}
|
||||
|
||||
if (http_header_line[0] == '\0') {
|
||||
body = 1;
|
||||
} else {
|
||||
{
|
||||
zval http_header;
|
||||
|
||||
ZVAL_STRINGL(&http_header, http_header_line, http_header_line_length);
|
||||
|
||||
zend_hash_next_index_insert(Z_ARRVAL(response_header), &http_header);
|
||||
}
|
||||
} else {
|
||||
|
||||
93
ext/standard/tests/http/bug47021.phpt
Normal file
93
ext/standard/tests/http/bug47021.phpt
Normal file
@@ -0,0 +1,93 @@
|
||||
--TEST--
|
||||
Bug #47021 (SoapClient stumbles over WSDL delivered with "Transfer-Encoding: chunked")
|
||||
--INI--
|
||||
allow_url_fopen=1
|
||||
--SKIPIF--
|
||||
<?php require 'server.inc'; http_server_skipif('tcp://127.0.0.1:12342'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require 'server.inc';
|
||||
|
||||
function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
|
||||
|
||||
switch($notification_code) {
|
||||
case STREAM_NOTIFY_MIME_TYPE_IS:
|
||||
echo "Type='$message'\n";
|
||||
break;
|
||||
case STREAM_NOTIFY_FILE_SIZE_IS:
|
||||
echo "Size=$bytes_max\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function do_test($num_spaces, $leave_trailing_space=false) {
|
||||
// SOAPClient exhibits the bug because it forces HTTP/1.1,
|
||||
// whereas file_get_contents() uses HTTP/1.0 by default.
|
||||
$options = [
|
||||
'http' => [
|
||||
'protocol_version' => '1.1',
|
||||
'header' => 'Connection: Close'
|
||||
],
|
||||
];
|
||||
|
||||
$ctx = stream_context_create($options);
|
||||
stream_context_set_params($ctx, array("notification" => "stream_notification_callback"));
|
||||
|
||||
$spaces = str_repeat(' ', $num_spaces);
|
||||
$trailing = ($leave_trailing_space ? ' ' : '');
|
||||
$responses = [
|
||||
"data://text/plain,HTTP/1.1 200 OK\r\n"
|
||||
. "Content-Type:{$spaces}text/plain{$trailing}\r\n"
|
||||
. "Transfer-Encoding:{$spaces}Chunked{$trailing}\r\n\r\n"
|
||||
. "5\nHello\n0\n",
|
||||
"data://text/plain,HTTP/1.1 200 OK\r\n"
|
||||
. "Content-Type\r\n" // Deliberately invalid header
|
||||
. "Content-Length:{$spaces}5{$trailing}\r\n\r\n"
|
||||
. "World"
|
||||
];
|
||||
$pid = http_server('tcp://127.0.0.1:12342', $responses);
|
||||
|
||||
echo file_get_contents('http://127.0.0.1:12342/', false, $ctx);
|
||||
echo "\n";
|
||||
echo file_get_contents('http://127.0.0.1:12342/', false, $ctx);
|
||||
echo "\n";
|
||||
|
||||
http_server_kill($pid);
|
||||
}
|
||||
|
||||
// Chunked decoding should be recognised by the HTTP stream wrapper regardless of whitespace
|
||||
// Transfer-Encoding:Chunked
|
||||
do_test(0);
|
||||
echo "\n";
|
||||
// Transfer-Encoding: Chunked
|
||||
do_test(1);
|
||||
echo "\n";
|
||||
// Transfer-Encoding: Chunked
|
||||
do_test(2);
|
||||
echo "\n";
|
||||
// Trailing space at end of header
|
||||
do_test(1, true);
|
||||
echo "\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Type='text/plain'
|
||||
Hello
|
||||
Size=5
|
||||
World
|
||||
|
||||
Type='text/plain'
|
||||
Hello
|
||||
Size=5
|
||||
World
|
||||
|
||||
Type='text/plain'
|
||||
Hello
|
||||
Size=5
|
||||
World
|
||||
|
||||
Type='text/plain'
|
||||
Hello
|
||||
Size=5
|
||||
World
|
||||
|
||||
37
ext/standard/tests/http/http_response_header_04.phpt
Normal file
37
ext/standard/tests/http/http_response_header_04.phpt
Normal file
@@ -0,0 +1,37 @@
|
||||
--TEST--
|
||||
$http_reponse_header (header with trailing whitespace)
|
||||
--SKIPIF--
|
||||
<?php require 'server.inc'; http_server_skipif('tcp://127.0.0.1:22349'); ?>
|
||||
--INI--
|
||||
allow_url_fopen=1
|
||||
allow_url_include=1
|
||||
--FILE--
|
||||
<?php
|
||||
require 'server.inc';
|
||||
|
||||
$responses = array(
|
||||
"data://text/plain,HTTP/1.0 200 Ok\r\nSome: Header \r\n\r\nBody",
|
||||
);
|
||||
|
||||
$pid = http_server("tcp://127.0.0.1:22349", $responses, $output);
|
||||
|
||||
function test() {
|
||||
$f = file_get_contents('http://127.0.0.1:22349/');
|
||||
var_dump($f);
|
||||
var_dump($http_response_header);
|
||||
}
|
||||
test();
|
||||
|
||||
http_server_kill($pid);
|
||||
?>
|
||||
==DONE==
|
||||
--EXPECT--
|
||||
string(4) "Body"
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(15) "HTTP/1.0 200 Ok"
|
||||
[1]=>
|
||||
string(14) "Some: Header"
|
||||
}
|
||||
==DONE==
|
||||
|
||||
37
ext/standard/tests/http/http_response_header_05.phpt
Normal file
37
ext/standard/tests/http/http_response_header_05.phpt
Normal file
@@ -0,0 +1,37 @@
|
||||
--TEST--
|
||||
$http_reponse_header (whitespace-only "header")
|
||||
--SKIPIF--
|
||||
<?php require 'server.inc'; http_server_skipif('tcp://127.0.0.1:22350'); ?>
|
||||
--INI--
|
||||
allow_url_fopen=1
|
||||
allow_url_include=1
|
||||
--FILE--
|
||||
<?php
|
||||
require 'server.inc';
|
||||
|
||||
$responses = array(
|
||||
"data://text/plain,HTTP/1.0 200 Ok\r\n \r\n\r\nBody",
|
||||
);
|
||||
|
||||
$pid = http_server("tcp://127.0.0.1:22350", $responses, $output);
|
||||
|
||||
function test() {
|
||||
$f = file_get_contents('http://127.0.0.1:22350/');
|
||||
var_dump($f);
|
||||
var_dump($http_response_header);
|
||||
}
|
||||
test();
|
||||
|
||||
http_server_kill($pid);
|
||||
?>
|
||||
==DONE==
|
||||
--EXPECT--
|
||||
string(4) "Body"
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(15) "HTTP/1.0 200 Ok"
|
||||
[1]=>
|
||||
string(0) ""
|
||||
}
|
||||
==DONE==
|
||||
|
||||
Reference in New Issue
Block a user