Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 65 additions & 50 deletions ext/soap/php_http.c
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,8 @@ int make_http_soap_request(zval *this_ptr,
}
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);
Expand Down Expand Up @@ -863,7 +865,7 @@ int make_http_soap_request(zval *this_ptr,

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),
Expand Down Expand Up @@ -892,65 +894,78 @@ int make_http_soap_request(zval *this_ptr,
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;
}

do {
http_headers = get_http_headers(stream);
if (!http_headers) {
if (request != buf) {
zend_string_release_ex(request, 0);
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);
}
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 (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);
}
/* 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;

/* 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;
}

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);

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);
/* Try and get headers again */
if (http_status == 100) {
zend_string_release_ex(http_headers, 0);
}
http_msg = estrdup(tmp);
}
efree(http_version);
} while (http_status == 100);
}

/* Try and get headers again */
if (http_status == 100) {
zend_string_release_ex(http_headers, 0);
}
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);
}
php_stream_close(stream);
if (http_headers) {
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 */

Expand Down
59 changes: 59 additions & 0 deletions ext/soap/tests/bugs/bug49278.phpt
Original file line number Diff line number Diff line change
@@ -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
"
46 changes: 46 additions & 0 deletions ext/soap/tests/bugs/bug49278.wsdl
Original file line number Diff line number Diff line change
@@ -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>