mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Merge branch 'PHP-8.3'
* PHP-8.3: Fix bug #73182: PHP SOAPClient does not support stream context HTTP headers in array form
This commit is contained in:
commit
520fce5607
3 changed files with 136 additions and 58 deletions
|
@ -78,6 +78,68 @@ int basic_authentication(zval* this_ptr, smart_str* soap_headers)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void http_context_add_header(const char *s,
|
||||
bool has_authorization,
|
||||
bool has_proxy_authorization,
|
||||
bool has_cookies,
|
||||
smart_str *soap_headers)
|
||||
{
|
||||
const char *p;
|
||||
int name_len;
|
||||
|
||||
while (*s) {
|
||||
/* skip leading newlines and spaces */
|
||||
while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n') {
|
||||
s++;
|
||||
}
|
||||
/* extract header name */
|
||||
p = s;
|
||||
name_len = -1;
|
||||
while (*p) {
|
||||
if (*p == ':') {
|
||||
if (name_len < 0) name_len = p - s;
|
||||
break;
|
||||
} else if (*p == ' ' || *p == '\t') {
|
||||
if (name_len < 0) name_len = p - s;
|
||||
} else if (*p == '\r' || *p == '\n') {
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if (*p == ':') {
|
||||
/* extract header value */
|
||||
while (*p && *p != '\r' && *p != '\n') {
|
||||
p++;
|
||||
}
|
||||
/* skip some predefined headers */
|
||||
if ((name_len != sizeof("host")-1 ||
|
||||
strncasecmp(s, "host", sizeof("host")-1) != 0) &&
|
||||
(name_len != sizeof("connection")-1 ||
|
||||
strncasecmp(s, "connection", sizeof("connection")-1) != 0) &&
|
||||
(name_len != sizeof("user-agent")-1 ||
|
||||
strncasecmp(s, "user-agent", sizeof("user-agent")-1) != 0) &&
|
||||
(name_len != sizeof("content-length")-1 ||
|
||||
strncasecmp(s, "content-length", sizeof("content-length")-1) != 0) &&
|
||||
(name_len != sizeof("content-type")-1 ||
|
||||
strncasecmp(s, "content-type", sizeof("content-type")-1) != 0) &&
|
||||
(!has_cookies ||
|
||||
name_len != sizeof("cookie")-1 ||
|
||||
strncasecmp(s, "cookie", sizeof("cookie")-1) != 0) &&
|
||||
(!has_authorization ||
|
||||
name_len != sizeof("authorization")-1 ||
|
||||
strncasecmp(s, "authorization", sizeof("authorization")-1) != 0) &&
|
||||
(!has_proxy_authorization ||
|
||||
name_len != sizeof("proxy-authorization")-1 ||
|
||||
strncasecmp(s, "proxy-authorization", sizeof("proxy-authorization")-1) != 0)) {
|
||||
/* add header */
|
||||
smart_str_appendl(soap_headers, s, p-s);
|
||||
smart_str_append_const(soap_headers, "\r\n");
|
||||
}
|
||||
}
|
||||
s = (*p) ? (p + 1) : p;
|
||||
}
|
||||
}
|
||||
|
||||
/* Additional HTTP headers */
|
||||
void http_context_headers(php_stream_context* context,
|
||||
bool has_authorization,
|
||||
|
@ -86,64 +148,16 @@ void http_context_headers(php_stream_context* context,
|
|||
smart_str* soap_headers)
|
||||
{
|
||||
zval *tmp;
|
||||
|
||||
if (context &&
|
||||
(tmp = php_stream_context_get_option(context, "http", "header")) != NULL &&
|
||||
Z_TYPE_P(tmp) == IS_STRING && Z_STRLEN_P(tmp)) {
|
||||
char *s = Z_STRVAL_P(tmp);
|
||||
char *p;
|
||||
int name_len;
|
||||
|
||||
while (*s) {
|
||||
/* skip leading newlines and spaces */
|
||||
while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n') {
|
||||
s++;
|
||||
}
|
||||
/* extract header name */
|
||||
p = s;
|
||||
name_len = -1;
|
||||
while (*p) {
|
||||
if (*p == ':') {
|
||||
if (name_len < 0) name_len = p - s;
|
||||
break;
|
||||
} else if (*p == ' ' || *p == '\t') {
|
||||
if (name_len < 0) name_len = p - s;
|
||||
} else if (*p == '\r' || *p == '\n') {
|
||||
break;
|
||||
if (context && (tmp = php_stream_context_get_option(context, "http", "header")) != NULL) {
|
||||
if (Z_TYPE_P(tmp) == IS_STRING && Z_STRLEN_P(tmp)) {
|
||||
http_context_add_header(Z_STRVAL_P(tmp), has_authorization, has_proxy_authorization, has_cookies, soap_headers);
|
||||
} else if (Z_TYPE_P(tmp) == IS_ARRAY) {
|
||||
zval *value;
|
||||
ZEND_HASH_FOREACH_VAL(Z_ARR_P(tmp), value) {
|
||||
if (Z_TYPE_P(value) == IS_STRING && Z_STRLEN_P(value)) {
|
||||
http_context_add_header(Z_STRVAL_P(value), has_authorization, has_proxy_authorization, has_cookies, soap_headers);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if (*p == ':') {
|
||||
/* extract header value */
|
||||
while (*p && *p != '\r' && *p != '\n') {
|
||||
p++;
|
||||
}
|
||||
/* skip some predefined headers */
|
||||
if ((name_len != sizeof("host")-1 ||
|
||||
strncasecmp(s, "host", sizeof("host")-1) != 0) &&
|
||||
(name_len != sizeof("connection")-1 ||
|
||||
strncasecmp(s, "connection", sizeof("connection")-1) != 0) &&
|
||||
(name_len != sizeof("user-agent")-1 ||
|
||||
strncasecmp(s, "user-agent", sizeof("user-agent")-1) != 0) &&
|
||||
(name_len != sizeof("content-length")-1 ||
|
||||
strncasecmp(s, "content-length", sizeof("content-length")-1) != 0) &&
|
||||
(name_len != sizeof("content-type")-1 ||
|
||||
strncasecmp(s, "content-type", sizeof("content-type")-1) != 0) &&
|
||||
(!has_cookies ||
|
||||
name_len != sizeof("cookie")-1 ||
|
||||
strncasecmp(s, "cookie", sizeof("cookie")-1) != 0) &&
|
||||
(!has_authorization ||
|
||||
name_len != sizeof("authorization")-1 ||
|
||||
strncasecmp(s, "authorization", sizeof("authorization")-1) != 0) &&
|
||||
(!has_proxy_authorization ||
|
||||
name_len != sizeof("proxy-authorization")-1 ||
|
||||
strncasecmp(s, "proxy-authorization", sizeof("proxy-authorization")-1) != 0)) {
|
||||
/* add header */
|
||||
smart_str_appendl(soap_headers, s, p-s);
|
||||
smart_str_append_const(soap_headers, "\r\n");
|
||||
}
|
||||
}
|
||||
s = (*p) ? (p + 1) : p;
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -259,7 +259,9 @@ void sdl_set_uri_credentials(sdlCtx *ctx, char *uri)
|
|||
ctx->context = php_stream_context_from_zval(context_ptr, 1);
|
||||
|
||||
if (ctx->context &&
|
||||
(header = php_stream_context_get_option(ctx->context, "http", "header")) != NULL) {
|
||||
(header = php_stream_context_get_option(ctx->context, "http", "header")) != NULL &&
|
||||
Z_TYPE_P(header) == IS_STRING) {
|
||||
/* TODO: should support header as an array, but this code path is untested */
|
||||
s = strstr(Z_STRVAL_P(header), "Authorization: Basic");
|
||||
if (s && (s == Z_STRVAL_P(header) || *(s-1) == '\n' || *(s-1) == '\r')) {
|
||||
char *rest = strstr(s, "\r\n");
|
||||
|
|
62
ext/soap/tests/bugs/bug73182.phpt
Normal file
62
ext/soap/tests/bugs/bug73182.phpt
Normal file
|
@ -0,0 +1,62 @@
|
|||
--TEST--
|
||||
Bug #73182 (PHP SOAPClient does not support stream context HTTP headers in array form)
|
||||
--EXTENSIONS--
|
||||
soap
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!file_exists(__DIR__ . "/../../../../sapi/cli/tests/php_cli_server.inc")) {
|
||||
echo "skip sapi/cli/tests/php_cli_server.inc required but not found";
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
include __DIR__ . "/../../../../sapi/cli/tests/php_cli_server.inc";
|
||||
|
||||
$args = ["-d", "extension_dir=" . ini_get("extension_dir"), "-d", "extension=" . (substr(PHP_OS, 0, 3) == "WIN" ? "php_" : "") . "soap." . PHP_SHLIB_SUFFIX];
|
||||
if (php_ini_loaded_file()) {
|
||||
// Necessary such that it works from a development directory in which case extension_dir might not be the real extension dir
|
||||
$args[] = "-c";
|
||||
$args[] = php_ini_loaded_file();
|
||||
}
|
||||
$code = <<<'PHP'
|
||||
/* Receive */
|
||||
$content = trim(file_get_contents("php://input")) . PHP_EOL;
|
||||
PHP;
|
||||
|
||||
php_cli_server_start($code, null, $args);
|
||||
|
||||
$client = new soapclient(NULL, [
|
||||
'location' => 'http://' . PHP_CLI_SERVER_ADDRESS,
|
||||
'uri' => 'misc-uri',
|
||||
'trace' => true,
|
||||
'stream_context' => stream_context_create([
|
||||
'http' => [
|
||||
'header' => [
|
||||
// These 2 must be ignored because the soap http client sets them up
|
||||
'Connection: close',
|
||||
'User-Agent: bar',
|
||||
// The following 2 must be included
|
||||
'X-custom: foo',
|
||||
'Content-Description: Foo',
|
||||
' X-custom2: trim me ',
|
||||
],
|
||||
],
|
||||
]),
|
||||
]);
|
||||
|
||||
$client->__soapCall("foo", []);
|
||||
echo $client->__getLastRequestHeaders();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
POST / HTTP/1.1
|
||||
Host: localhost:%d
|
||||
Connection: Keep-Alive
|
||||
User-Agent: PHP-SOAP/%s
|
||||
Content-Type: text/xml; charset=utf-8
|
||||
SOAPAction: "misc-uri#foo"
|
||||
Content-Length: %d
|
||||
X-custom: foo
|
||||
Content-Description: Foo
|
||||
X-custom2: trim me
|
Loading…
Add table
Add a link
Reference in a new issue