From 73605400e842e3c0210c46e4980b9ea748db3886 Mon Sep 17 00:00:00 2001
From: Dmitry Stogov <dmitry@php.net>
Date: Tue, 7 Feb 2006 12:49:10 +0000
Subject: [PATCH] Fixed bug #36083 (SoapClient waits for responses on one-way
 operations)

---
 NEWS                                 |  2 ++
 ext/soap/php_http.c                  |  7 +++++
 ext/soap/php_soap.h                  |  1 +
 ext/soap/soap.c                      | 41 ++++++++++++++++++++--------
 ext/soap/tests/schema/schema075.phpt |  2 +-
 ext/soap/tests/schema/schema076.phpt |  2 +-
 ext/soap/tests/schema/schema077.phpt |  2 +-
 ext/soap/tests/schema/schema078.phpt |  2 +-
 ext/soap/tests/schema/schema079.phpt |  2 +-
 ext/soap/tests/schema/schema080.phpt |  2 +-
 10 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/NEWS b/NEWS
index 3de47c7873..469428d58f 100644
--- a/NEWS
+++ b/NEWS
@@ -51,6 +51,8 @@ PHP                                                                        NEWS
   (Tony)
 - Fixed bug #36096 (oci_result() returns garbage after oci_fetch() failed). 
   (Tony)
+- Fixed bug #36083 (SoapClient waits for responses on one-way operations).
+  (Dmitry)
 - Fixed bug #36071 (Engine Crash related with 'clone'). (Dmitry)
 - Fixed bug #36055 (possible OCI8 crash in multithreaded environment). (Tony)
 - Fixed bug #36046 (parse_ini_file() miscounts lines in multi-line values).
diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c
index 2e5ea04fa6..9a21371d44 100644
--- a/ext/soap/php_http.c
+++ b/ext/soap/php_http.c
@@ -679,6 +679,13 @@ try_again:
 		return FALSE;
 	}
 
+	if (!buffer) {
+		php_stream_close(stream);
+		zend_hash_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"));
+		zend_hash_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy"));
+		return TRUE;
+	}
+
 	do {
 		if (!get_http_headers(stream, &http_headers, &http_header_size TSRMLS_CC)) {
 			if (http_headers) {efree(http_headers);}
diff --git a/ext/soap/php_soap.h b/ext/soap/php_soap.h
index 7d2faac1c0..21c8e078c1 100644
--- a/ext/soap/php_soap.h
+++ b/ext/soap/php_soap.h
@@ -153,6 +153,7 @@ struct _soapService {
 #define SOAP_AUTHENTICATION_DIGEST  1
 
 #define SOAP_SINGLE_ELEMENT_ARRAYS  (1<<0)
+#define SOAP_WAIT_ONE_WAY_CALLS     (2<<0)
 
 ZEND_BEGIN_MODULE_GLOBALS(soap)
 	HashTable  defEncNs;     /* mapping of default namespaces to prefixes */
diff --git a/ext/soap/soap.c b/ext/soap/soap.c
index e3d049a5f3..71fd1f9056 100644
--- a/ext/soap/soap.c
+++ b/ext/soap/soap.c
@@ -635,6 +635,7 @@ PHP_MINIT_FUNCTION(soap)
 	REGISTER_STRING_CONSTANT("XSD_1999_NAMESPACE", XSD_1999_NAMESPACE,  CONST_CS | CONST_PERSISTENT);
 
 	REGISTER_LONG_CONSTANT("SOAP_SINGLE_ELEMENT_ARRAYS", SOAP_SINGLE_ELEMENT_ARRAYS, CONST_CS | CONST_PERSISTENT);
+	REGISTER_LONG_CONSTANT("SOAP_WAIT_ONE_WAY_CALLS", SOAP_WAIT_ONE_WAY_CALLS, CONST_CS | CONST_PERSISTENT);
 
 	old_error_handler = zend_error_cb;
 	zend_error_cb = soap_error_handler;
@@ -2202,7 +2203,7 @@ PHP_METHOD(SoapClient, SoapClient)
 		}
 
 		if (zend_hash_find(ht, "features", sizeof("features"), (void**)&tmp) == SUCCESS &&
-			Z_TYPE_PP(tmp) == IS_ARRAY) {
+			Z_TYPE_PP(tmp) == IS_LONG) {
 			add_property_long(this_ptr, "_features", Z_LVAL_PP(tmp));
 	    }
 
@@ -2241,13 +2242,13 @@ PHP_METHOD(SoapClient, SoapClient)
 }
 /* }}} */
 
-static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *action, int version, zval *response TSRMLS_DC)
+static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *action, int version, int one_way, zval *response TSRMLS_DC)
 {
 	int    ret = TRUE;
 	char  *buf;
 	int    buf_size;
-	zval   func, param0, param1, param2, param3;
-	zval  *params[4];
+	zval   func, param0, param1, param2, param3, param4;
+	zval  *params[5];
 	zval **trace;
 	zval **fault;
 
@@ -2287,7 +2288,11 @@ static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *act
 	params[3] = &param3;
 	ZVAL_LONG(params[3], version);
 
-	if (call_user_function(NULL, &this_ptr, &func, response, 4, params TSRMLS_CC) != SUCCESS) {
+	INIT_ZVAL(param4);
+	params[4] = &param4;
+	ZVAL_LONG(params[4], one_way);
+
+	if (call_user_function(NULL, &this_ptr, &func, response, 5, params TSRMLS_CC) != SUCCESS) {
 		add_soap_fault(this_ptr, "Client", "SoapSlient::__doRequest() failed", NULL, NULL TSRMLS_CC);
 		ret = FALSE;
 	} else if (Z_TYPE_P(response) != IS_STRING) {
@@ -2388,16 +2393,24 @@ static void do_soap_call(zval* this_ptr,
  		fn = get_function(sdl, function);
  		if (fn != NULL) {
 			sdlBindingPtr binding = fn->binding;
+			int one_way = 0;
+
+			if (fn->responseName == NULL &&
+			    fn->responseParameters == NULL &&
+			    soap_headers == NULL) {
+				one_way = 1;
+			}
+
 			if (location == NULL) {
 				location = binding->location;
 			}
 			if (binding->bindingType == BINDING_SOAP) {
 				sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes;
  				request = serialize_function_call(this_ptr, fn, NULL, fnb->input.ns, real_args, arg_count, soap_version, soap_headers TSRMLS_CC);
- 				ret = do_request(this_ptr, request, location, fnb->soapAction, soap_version, &response TSRMLS_CC);
+ 				ret = do_request(this_ptr, request, location, fnb->soapAction, soap_version, one_way, &response TSRMLS_CC);
  			}	else {
  				request = serialize_function_call(this_ptr, fn, NULL, sdl->target_ns, real_args, arg_count, soap_version, soap_headers TSRMLS_CC);
- 				ret = do_request(this_ptr, request, location, NULL, soap_version, &response TSRMLS_CC);
+ 				ret = do_request(this_ptr, request, location, NULL, soap_version, one_way, &response TSRMLS_CC);
  			}
 
 			xmlFreeDoc(request);
@@ -2440,7 +2453,7 @@ static void do_soap_call(zval* this_ptr,
 			}
 			smart_str_0(&action);
 
-			ret = do_request(this_ptr, request, location, action.c, soap_version, &response TSRMLS_CC);
+			ret = do_request(this_ptr, request, location, action.c, soap_version, 0, &response TSRMLS_CC);
 
 	 		smart_str_free(&action);
 			xmlFreeDoc(request);
@@ -2737,15 +2750,21 @@ PHP_METHOD(SoapClient, __doRequest)
   char *buf, *location, *action;
   int   buf_size, location_size, action_size;
   long  version;
+  long  one_way = 0;
 
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssl",
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssl|l",
 	    &buf, &buf_size,
 	    &location, &location_size,
 	    &action, &action_size,
-	    &version) == FAILURE) {
+	    &version, &one_way) == FAILURE) {
 		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
 	}
-	if (make_http_soap_request(this_ptr, buf, buf_size, location, action, version,
+	if (SOAP_GLOBAL(features) & SOAP_WAIT_ONE_WAY_CALLS) {
+		one_way = 0;
+	}
+	if (one_way && make_http_soap_request(this_ptr, buf, buf_size, location, action, version, NULL, NULL TSRMLS_CC)) {
+		RETURN_EMPTY_STRING();
+	} else if (make_http_soap_request(this_ptr, buf, buf_size, location, action, version,
 	    &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value) TSRMLS_CC)) {
 		return_value->type = IS_STRING;
 		return;
diff --git a/ext/soap/tests/schema/schema075.phpt b/ext/soap/tests/schema/schema075.phpt
index 2a84be9ce9..0f430f59d7 100644
--- a/ext/soap/tests/schema/schema075.phpt
+++ b/ext/soap/tests/schema/schema075.phpt
@@ -19,7 +19,7 @@ echo "ok";
 --EXPECTF--
 <?xml version="1.0" encoding="UTF-8"?>
 <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:test><testParam ns1:int1="1" ns1:int2="2" int3="3" xsi:type="ns1:testType"/></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope>
-object(stdClass)#5 (3) {
+object(stdClass)#%d (3) {
   ["int1"]=>
   int(1)
   ["int2"]=>
diff --git a/ext/soap/tests/schema/schema076.phpt b/ext/soap/tests/schema/schema076.phpt
index dfa7791fed..6e6444a5df 100644
--- a/ext/soap/tests/schema/schema076.phpt
+++ b/ext/soap/tests/schema/schema076.phpt
@@ -19,7 +19,7 @@ echo "ok";
 --EXPECTF--
 <?xml version="1.0" encoding="UTF-8"?>
 <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:test><testParam int1="1" ns1:int2="2" int3="3" xsi:type="ns1:testType"/></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope>
-object(stdClass)#5 (3) {
+object(stdClass)#%d (3) {
   ["int1"]=>
   int(1)
   ["int2"]=>
diff --git a/ext/soap/tests/schema/schema077.phpt b/ext/soap/tests/schema/schema077.phpt
index baf10449d6..779503cb4a 100644
--- a/ext/soap/tests/schema/schema077.phpt
+++ b/ext/soap/tests/schema/schema077.phpt
@@ -19,7 +19,7 @@ echo "ok";
 --EXPECTF--
 <?xml version="1.0" encoding="UTF-8"?>
 <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:test><testParam int1="1" ns1:int2="2" int3="3" xsi:type="ns1:testType"/></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope>
-object(stdClass)#5 (3) {
+object(stdClass)#%d (3) {
   ["int1"]=>
   int(1)
   ["int2"]=>
diff --git a/ext/soap/tests/schema/schema078.phpt b/ext/soap/tests/schema/schema078.phpt
index a674270dff..7636a78f93 100644
--- a/ext/soap/tests/schema/schema078.phpt
+++ b/ext/soap/tests/schema/schema078.phpt
@@ -21,7 +21,7 @@ echo "ok";
 --EXPECTF--
 <?xml version="1.0" encoding="UTF-8"?>
 <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/"><SOAP-ENV:Body><ns1:test><testParam><ns1:int1>1</ns1:int1><ns1:int2>2</ns1:int2><int3>3</int3></testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope>
-object(stdClass)#5 (3) {
+object(stdClass)#%d (3) {
   ["int1"]=>
   int(1)
   ["int2"]=>
diff --git a/ext/soap/tests/schema/schema079.phpt b/ext/soap/tests/schema/schema079.phpt
index d7f2ab97c6..34dcd9bee7 100644
--- a/ext/soap/tests/schema/schema079.phpt
+++ b/ext/soap/tests/schema/schema079.phpt
@@ -21,7 +21,7 @@ echo "ok";
 --EXPECTF--
 <?xml version="1.0" encoding="UTF-8"?>
 <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/"><SOAP-ENV:Body><ns1:test><testParam><int1>1</int1><ns1:int2>2</ns1:int2><int3>3</int3></testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope>
-object(stdClass)#5 (3) {
+object(stdClass)#%d (3) {
   ["int1"]=>
   int(1)
   ["int2"]=>
diff --git a/ext/soap/tests/schema/schema080.phpt b/ext/soap/tests/schema/schema080.phpt
index 4accf551f1..7519d6a30d 100644
--- a/ext/soap/tests/schema/schema080.phpt
+++ b/ext/soap/tests/schema/schema080.phpt
@@ -21,7 +21,7 @@ echo "ok";
 --EXPECTF--
 <?xml version="1.0" encoding="UTF-8"?>
 <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/"><SOAP-ENV:Body><ns1:test><testParam><int1>1</int1><ns1:int2>2</ns1:int2><int3>3</int3></testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope>
-object(stdClass)#5 (3) {
+object(stdClass)#%d (3) {
   ["int1"]=>
   int(1)
   ["int2"]=>
-- 
2.40.0