1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix #49278: SoapClient::__getLastResponseHeaders returns NULL if wsdl operation !has output

Instead of early exiting, process the headers if tracing is enabled, and
exit after that.

Closes GH-12609.
This commit is contained in:
Niels Dossche
2023-11-04 16:09:30 +01:00
parent ccdc21b39a
commit 92e4e8bdf4
4 changed files with 177 additions and 55 deletions

2
NEWS
View File

@@ -46,6 +46,8 @@ SOAP:
. Add support for clark notation for namespaces in class map. (lxShaDoWxl)
. Mitigate #51561 (SoapServer with a extented class and using sessions,
lost the setPersistence()). (nielsdos)
. Fixed bug #49278 (SoapClient::__getLastResponseHeaders returns NULL if
wsdl operation !has output). (nielsdos)
Sockets:
. Removed the deprecated inet_ntoa call support. (David Carlier)

View File

@@ -532,6 +532,8 @@ try_again:
}
PG(allow_url_fopen) = old_allow_url_fopen;
bool client_trace = Z_TYPE_P(Z_CLIENT_TRACE_P(this_ptr)) == IS_TRUE;
if (stream) {
zval *cookies, *login, *password;
zend_resource *ret = zend_register_resource(phpurl, le_url);
@@ -863,7 +865,7 @@ try_again:
smart_str_append_const(&soap_headers, "\r\n");
smart_str_0(&soap_headers);
if (Z_TYPE_P(Z_CLIENT_TRACE_P(this_ptr)) == IS_TRUE) {
if (client_trace) {
zval_ptr_dtor(Z_CLIENT_LAST_REQUEST_HEADERS_P(this_ptr));
/* Need to copy the string here, as we continue appending to soap_headers below. */
ZVAL_STRINGL(Z_CLIENT_LAST_REQUEST_HEADERS_P(this_ptr),
@@ -892,65 +894,78 @@ try_again:
return FALSE;
}
if (!return_value) {
php_stream_close(stream);
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
smart_str_free(&soap_headers_z);
return TRUE;
http_headers = NULL;
if (return_value || client_trace) {
do {
http_headers = get_http_headers(stream);
if (!http_headers) {
if (request != buf) {
zend_string_release_ex(request, 0);
}
php_stream_close(stream);
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL);
smart_str_free(&soap_headers_z);
return FALSE;
}
if (client_trace) {
zval_ptr_dtor(Z_CLIENT_LAST_RESPONSE_HEADERS_P(this_ptr));
ZVAL_STR_COPY(Z_CLIENT_LAST_RESPONSE_HEADERS_P(this_ptr), http_headers);
}
/* Check to see what HTTP status was sent */
http_1_1 = 0;
http_status = 0;
http_version = get_http_header_value(ZSTR_VAL(http_headers), "HTTP/");
if (http_version) {
char *tmp;
if (!strncmp(http_version,"1.1", 3)) {
http_1_1 = 1;
}
tmp = strstr(http_version," ");
if (tmp != NULL) {
tmp++;
http_status = atoi(tmp);
}
tmp = strstr(tmp," ");
if (tmp != NULL) {
tmp++;
if (http_msg) {
efree(http_msg);
}
http_msg = estrdup(tmp);
}
efree(http_version);
/* Try and get headers again */
if (http_status == 100) {
zend_string_release_ex(http_headers, 0);
}
}
} while (http_status == 100);
}
do {
http_headers = get_http_headers(stream);
if (!http_headers) {
if (request != buf) {
zend_string_release_ex(request, 0);
}
php_stream_close(stream);
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL);
smart_str_free(&soap_headers_z);
return FALSE;
if (!return_value) {
/* In this case, the headers were only fetched because client_trace was true. */
if (request != buf) {
zend_string_release_ex(request, 0);
}
if (Z_TYPE_P(Z_CLIENT_TRACE_P(this_ptr)) == IS_TRUE) {
zval_ptr_dtor(Z_CLIENT_LAST_RESPONSE_HEADERS_P(this_ptr));
ZVAL_STR_COPY(Z_CLIENT_LAST_RESPONSE_HEADERS_P(this_ptr), http_headers);
php_stream_close(stream);
if (http_headers) {
zend_string_release_ex(http_headers, 0);
}
/* Check to see what HTTP status was sent */
http_1_1 = 0;
http_status = 0;
http_version = get_http_header_value(ZSTR_VAL(http_headers), "HTTP/");
if (http_version) {
char *tmp;
if (!strncmp(http_version,"1.1", 3)) {
http_1_1 = 1;
}
tmp = strstr(http_version," ");
if (tmp != NULL) {
tmp++;
http_status = atoi(tmp);
}
tmp = strstr(tmp," ");
if (tmp != NULL) {
tmp++;
if (http_msg) {
efree(http_msg);
}
http_msg = estrdup(tmp);
}
efree(http_version);
/* Try and get headers again */
if (http_status == 100) {
zend_string_release_ex(http_headers, 0);
}
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
if (http_msg) {
efree(http_msg);
}
} while (http_status == 100);
smart_str_free(&soap_headers_z);
return true;
}
/* Grab and send back every cookie */

View File

@@ -0,0 +1,59 @@
--TEST--
Bug #49278 (SoapClient::__getLastResponseHeaders returns NULL if wsdl operation !has output)
--EXTENSIONS--
soap
--INI--
soap.wsdl_cache_enabled=0
--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 = '$server = new SoapServer("' . __DIR__ . '"/bug49278.wsdl", ["trace"=>1]);' .
<<<'PHP'
function Add() {}
$server->addFunction('Add');
$server->handle();
PHP;
php_cli_server_start($code, null, $args);
$client = new SoapClient(__DIR__ . '/bug49278.wsdl', array('location' => "http://".PHP_CLI_SERVER_ADDRESS, 'trace' => 1));
$client->Add();
var_dump($client->__getLastResponse());
var_dump($client->__getLastResponse());
var_dump($client->__getLastRequestHeaders());
var_dump($client->__getLastResponseHeaders());
?>
--EXPECTF--
string(0) ""
string(0) ""
string(177) "POST / HTTP/1.1
Host: %s
Connection: Keep-Alive
User-Agent: PHP-SOAP/8.4.0-dev
Content-Type: text/xml; charset=utf-8
SOAPAction: "Add"
Content-Length: %d
"
string(165) "HTTP/1.1 200 OK
Host: %s
Date: %s
Connection: close
X-Powered-By: PHP/8.4.0-dev
Content-type: text/html; charset=UTF-8
"

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" ?>
<definitions
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:si="http://soapinterop.org/xsd"
xmlns:tns="http://linuxsrv.home/~dmitry/soap/test.wsdl"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://linuxsrv.home/~dmitry/soap/test.wsdl">
<types>
<xsd:schema targetNamespace="http://linuxsrv.home/~dmitry/soap/test.wsdl">
<xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
<xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" />
</xsd:schema>
</types>
<message name="AddRequest"/>
<message name="AddResponse"/>
<portType name="TestServicePortType">
<operation name="Add">
<input message="tns:AddRequest" />
</operation>
</portType>
<binding name="TestServiceBinding" type="tns:TestServicePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="Add">
<soap:operation soapAction="Add" style="rpc" />
<input>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</input>
</operation>
</binding>
<service name="TestService">
<port name="TestServicePort" binding="tns:TestServiceBinding">
<soap:address location="http://linuxsrv.home/~dmitry/soap/soap_server.php" />
</port>
</service>
</definitions>