]> granicus.if.org Git - php/commitdiff
Fixed bug #36721 (The SoapServer is not able to send a header that it didn't receive)
authorDmitry Stogov <dmitry@php.net>
Tue, 21 Mar 2006 12:04:55 +0000 (12:04 +0000)
committerDmitry Stogov <dmitry@php.net>
Tue, 21 Mar 2006 12:04:55 +0000 (12:04 +0000)
NEWS
ext/soap/php_soap.h
ext/soap/soap.c
ext/soap/tests/server023.phpt [new file with mode: 0755]
ext/soap/tests/server024.phpt [new file with mode: 0755]
ext/soap/tests/server025.phpt [new file with mode: 0755]
ext/soap/tests/server025.wsdl [new file with mode: 0755]

diff --git a/NEWS b/NEWS
index 2ca68d26390acbba649fb404043c5e590399b798..3130d19a67a88bdfacb1f5da1b12206222a5fc77 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -11,7 +11,9 @@ PHP                                                                        NEWS
 - Removed the E_STRICT deprecation notice from "var". (Ilia)
 - Fixed debug_zval_dump() to support private and protected members. (Dmitry)
 - Fixed bug #36809 (__FILE__ behavior changed). (Dmitry)
-- FIxed bug #36808 (syslog ident becomes garbage between requests). (Tony)
+- Fixed bug #36808 (syslog ident becomes garbage between requests). (Tony)
+- Fixed bug #36721 (The SoapServer is not able to send a header that it didn't
+  receive). (Dmitry)
 - Fixed bug #36756 (DOMDocument::removeChild corrupts node). (Rob)
 - Fixed bug #36749 (SOAP: 'Error Fetching http body' when using HTTP Proxy).
   (Dmitry)
index 21c8e078c17636386b3a78c7d2bb5fbcae32abd6..ec193c0d83817f9edd52ca30674a892aa9f00d60 100644 (file)
@@ -97,6 +97,8 @@ struct _soapMapping {
        } map_class;
 };
 
+struct _soapHeader;
+
 struct _soapService {
        sdlPtr sdl;
 
@@ -120,6 +122,7 @@ struct _soapService {
        xmlCharEncodingHandlerPtr encoding;
        HashTable *class_map;
        int        features;
+       struct _soapHeader **soap_headers_ptr;
 };
 
 #define SOAP_CLASS 1
index 6fe86c483d9aabaa8035771bd62c4f2dd4f32c0b..12a27c78f9fbd9a46e1f0d223a220fad3ebd9979 100644 (file)
@@ -244,6 +244,7 @@ PHP_METHOD(SoapServer, getFunctions);
 PHP_METHOD(SoapServer, handle);
 PHP_METHOD(SoapServer, setPersistence);
 PHP_METHOD(SoapServer, fault);
+PHP_METHOD(SoapServer, addSoapHeader);
 #ifdef HAVE_PHP_DOMXML
 PHP_METHOD(PHP_SOAP_SERVER_CLASS, map);
 #endif
@@ -309,6 +310,7 @@ static zend_function_entry soap_server_functions[] = {
        PHP_ME(SoapServer, getFunctions, NULL, 0)
        PHP_ME(SoapServer, handle, NULL, 0)
        PHP_ME(SoapServer, fault, NULL, 0)
+       PHP_ME(SoapServer, addSoapHeader, NULL, 0)
 #ifdef HAVE_PHP_DOMXML
        PHP_ME(SoapServer, map, NULL, 0)
 #endif
@@ -1518,6 +1520,8 @@ PHP_METHOD(SoapServer, handle)
        old_soap_version = SOAP_GLOBAL(soap_version);
        function = deserialize_function_call(service->sdl, doc_request, service->actor, &function_name, &num_params, &params, &soap_version, &soap_headers TSRMLS_CC);
        xmlFreeDoc(doc_request);
+       
+       service->soap_headers_ptr = &soap_headers;
 
        soap_obj = NULL;
        if (service->type == SOAP_CLASS) {
@@ -1802,15 +1806,18 @@ fail:
                int i;
 
                soap_headers = soap_headers->next;
-               i = h->num_params;
-               while (i > 0) {
-                       zval_ptr_dtor(&h->parameters[--i]);
+               if (h->parameters) {
+                       i = h->num_params;
+                       while (i > 0) {
+                               zval_ptr_dtor(&h->parameters[--i]);
+                       }
+                       efree(h->parameters);
                }
-               efree(h->parameters);
                zval_dtor(&h->function_name);
                zval_dtor(&h->retval);
                efree(h);
        }
+       service->soap_headers_ptr = NULL;
 
        /* Free Memory */
        if (num_params > 0) {
@@ -1847,6 +1854,37 @@ PHP_METHOD(SoapServer, fault)
 }
 /* }}} */
 
+PHP_METHOD(SoapServer, addSoapHeader)
+{
+       soapServicePtr service;
+       zval *fault;
+       soapHeader **p;
+
+       SOAP_SERVER_BEGIN_CODE();
+
+       FETCH_THIS_SERVICE(service);
+
+       if (!service || !service->soap_headers_ptr) {
+               php_error_docref(NULL TSRMLS_CC, E_ERROR, "The SoapServer::addSoapHeader function may be called only during SOAP request processing");
+       }
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &fault, soap_header_class_entry) == FAILURE) {
+               php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
+       }
+
+       p = service->soap_headers_ptr;
+       while (*p != NULL) {
+               p = &(*p)->next;
+       }
+       *p = emalloc(sizeof(soapHeader));
+       memset(*p, 0, sizeof(soapHeader));
+       ZVAL_NULL(&(*p)->function_name);
+       (*p)->retval = *fault;
+       zval_copy_ctor(&(*p)->retval);
+
+       SOAP_SERVER_END_CODE();
+}
+
 static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeader *hdr TSRMLS_DC)
 {
        int soap_version;
@@ -2523,7 +2561,7 @@ static void verify_soap_headers_array(HashTable *ht TSRMLS_DC)
        zend_hash_internal_pointer_reset(ht);
        while (zend_hash_get_current_data(ht, (void**)&tmp) == SUCCESS) {
                if (Z_TYPE_PP(tmp) != IS_OBJECT ||
-                   Z_OBJCE_PP(tmp) != soap_header_class_entry) {
+                   !instanceof_function(Z_OBJCE_PP(tmp), soap_header_class_entry TSRMLS_CC)) {
                        php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid SOAP header");
                }
                zend_hash_move_forward(ht);
@@ -2583,7 +2621,7 @@ PHP_METHOD(SoapClient, __call)
                verify_soap_headers_array(soap_headers TSRMLS_CC);
                free_soap_headers = 0;
        } else if (Z_TYPE_P(headers) == IS_OBJECT &&
-                  Z_OBJCE_P(headers) == soap_header_class_entry) {
+                  instanceof_function(Z_OBJCE_P(headers), soap_header_class_entry TSRMLS_CC)) {
            soap_headers = emalloc(sizeof(HashTable));
                zend_hash_init(soap_headers, 0, NULL, ZVAL_PTR_DTOR, 0);
                zend_hash_next_index_insert(soap_headers, &headers, sizeof(zval*), NULL);
@@ -2846,7 +2884,7 @@ PHP_METHOD(SoapClient, __setSoapHeaders)
                        add_property_zval(this_ptr, "__default_headers", headers);
                }
        } else if (Z_TYPE_P(headers) == IS_OBJECT &&
-                  Z_OBJCE_P(headers) == soap_header_class_entry) {
+                  instanceof_function(Z_OBJCE_P(headers), soap_header_class_entry TSRMLS_CC)) {
                zval *default_headers;
                ALLOC_INIT_ZVAL(default_headers);
                array_init(default_headers);
@@ -3518,7 +3556,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
 
                        head = xmlNewChild(envelope, ns, "Header", NULL);
                        if (Z_TYPE_P(hdr_ret) == IS_OBJECT &&
-                           Z_OBJCE_P(hdr_ret) == soap_header_class_entry) {
+                           instanceof_function(Z_OBJCE_P(hdr_ret), soap_header_class_entry)) {
                                HashTable* ht = Z_OBJPROP_P(hdr_ret);
                                zval **tmp;
                                sdlSoapBindingFunctionHeaderPtr *hdr;
@@ -3745,7 +3783,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
 
 
                                        if (Z_TYPE(h->retval) == IS_OBJECT &&
-                                           Z_OBJCE(h->retval) == soap_header_class_entry) {
+                                           instanceof_function(Z_OBJCE(h->retval), soap_header_class_entry TSRMLS_CC)) {
                                                HashTable* ht = Z_OBJPROP(h->retval);
                                                zval **tmp;
                                                sdlSoapBindingFunctionHeaderPtr *hdr;
diff --git a/ext/soap/tests/server023.phpt b/ext/soap/tests/server023.phpt
new file mode 100755 (executable)
index 0000000..c227204
--- /dev/null
@@ -0,0 +1,37 @@
+--TEST--
+SOAP Server 23: Send SOAP headers those were not received
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+function test() {
+       global $server;
+       $server->addSoapHeader(new SoapHeader("http://testuri.org", "Test1", "Hello Header!"));
+       $server->addSoapHeader(new SoapHeader("http://testuri.org", "Test2", "Hello Header!"));
+       return "Hello Body!";
+}
+
+$server = new soapserver(null,array('uri'=>"http://testuri.org"));
+$server->addfunction("test");
+
+$HTTP_RAW_POST_DATA = <<<EOF
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<SOAP-ENV:Envelope
+  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  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:si="http://soapinterop.org/xsd">
+  <SOAP-ENV:Body>
+    <ns1:test xmlns:ns1="http://testuri.org"/>
+  </SOAP-ENV:Body>
+</SOAP-ENV:Envelope>
+EOF;
+
+$server->handle();
+echo "ok\n";
+?>
+--EXPECT--
+<?xml version="1.0" encoding="UTF-8"?>
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://testuri.org" 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:Header><ns1:Test1>Hello Header!</ns1:Test1><ns1:Test2>Hello Header!</ns1:Test2></SOAP-ENV:Header><SOAP-ENV:Body><ns1:testResponse><return xsi:type="xsd:string">Hello Body!</return></ns1:testResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
+ok
diff --git a/ext/soap/tests/server024.phpt b/ext/soap/tests/server024.phpt
new file mode 100755 (executable)
index 0000000..0ddd9ce
--- /dev/null
@@ -0,0 +1,49 @@
+--TEST--
+SOAP Server 24: Send SOAP headers those were not received
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+class TestHeader1 extends SoapHeader {
+       function __construct($data) {
+               parent::__construct("http://testuri.org", "Test1", $data);
+       }
+}
+
+class TestHeader2 extends SoapHeader {
+       function __construct($data) {
+               parent::__construct("http://testuri.org", "Test2", $data);
+       }
+}
+
+function test() {
+       global $server;
+       $server->addSoapHeader(new TestHeader1("Hello Header!"));
+       $server->addSoapHeader(new TestHeader2("Hello Header!"));
+       return "Hello Body!";
+}
+
+$server = new soapserver(null,array('uri'=>"http://testuri.org"));
+$server->addfunction("test");
+
+$HTTP_RAW_POST_DATA = <<<EOF
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<SOAP-ENV:Envelope
+  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  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:si="http://soapinterop.org/xsd">
+  <SOAP-ENV:Body>
+    <ns1:test xmlns:ns1="http://testuri.org"/>
+  </SOAP-ENV:Body>
+</SOAP-ENV:Envelope>
+EOF;
+
+$server->handle();
+echo "ok\n";
+?>
+--EXPECT--
+<?xml version="1.0" encoding="UTF-8"?>
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://testuri.org" 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:Header><ns1:Test1>Hello Header!</ns1:Test1><ns1:Test2>Hello Header!</ns1:Test2></SOAP-ENV:Header><SOAP-ENV:Body><ns1:testResponse><return xsi:type="xsd:string">Hello Body!</return></ns1:testResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
+ok
diff --git a/ext/soap/tests/server025.phpt b/ext/soap/tests/server025.phpt
new file mode 100755 (executable)
index 0000000..0a98b41
--- /dev/null
@@ -0,0 +1,46 @@
+--TEST--
+SOAP Server 25: One-way SOAP headers encoding using WSDL
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+class TestHeader1 extends SoapHeader {
+       function __construct($data) {
+               parent::__construct("http://testuri.org", "Test1", $data);
+       }
+}
+
+class TestHeader2 extends SoapHeader {
+       function __construct($data) {
+               parent::__construct("http://testuri.org", "Test2", $data);
+       }
+}
+
+function test() {
+       global $server;
+       $server->addSoapHeader(new TestHeader1("Hello Header!"));
+       $server->addSoapHeader(new TestHeader2("Hello Header!"));
+       return "Hello Body!";
+}
+
+$server = new soapserver(dirname(__FILE__)."/server025.wsdl");
+$server->addfunction("test");
+
+$HTTP_RAW_POST_DATA = <<<EOF
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<SOAP-ENV:Envelope
+  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
+  <SOAP-ENV:Body>
+    <ns1:test xmlns:ns1="http://testuri.org"/>
+  </SOAP-ENV:Body>
+</SOAP-ENV:Envelope>
+EOF;
+
+$server->handle();
+echo "ok\n";
+?>
+--EXPECT--
+<?xml version="1.0" encoding="UTF-8"?>
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="http://testuri.org"><SOAP-ENV:Header><ns1:Test1 xsi:type="xsd:string">Hello Header!</ns1:Test1><ns1:Test2 xsi:type="xsd:string">Hello Header!</ns1:Test2></SOAP-ENV:Header><SOAP-ENV:Body><ns1:testResponse><result>Hello Body!</result></ns1:testResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
+ok
diff --git a/ext/soap/tests/server025.wsdl b/ext/soap/tests/server025.wsdl
new file mode 100755 (executable)
index 0000000..2870f4e
--- /dev/null
@@ -0,0 +1,55 @@
+<?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://testuri.org">
+
+  <message name="TestHeader1">
+    <part name="Test1" type="xsd:string" />
+  </message>
+  <message name="TestHeader2">
+    <part name="Test2" type="xsd:string" />
+  </message>
+
+  <message name="TestRequest">
+  </message>
+  <message name="TestResponse">
+    <part name="result" type="xsd:string" />
+  </message>
+
+  <portType name="TestServicePortType">
+    <operation name="test">
+      <input message="tns:TestRequest" />
+      <output message="tns:TestResponse" />
+    </operation>
+  </portType>
+
+  <binding name="TestServiceBinding" type="tns:TestServicePortType">
+    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
+    <operation name="test">
+      <soap:operation soapAction="Test" style="rpc" />
+      <input>
+        <soap:body namespace="http://testuri.org" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+      </input>
+      <output>
+        <soap:body namespace="http://testuri.org" use="literal" />
+        <soap:header namespace="http://testuri.org" message="tns:TestHeader1" part="Test1" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+        <soap:header namespace="http://testuri.org" message="tns:TestHeader2" part="Test2" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+      </output>
+    </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>