From: Dmitry Stogov Date: Wed, 4 Feb 2004 14:46:12 +0000 (+0000) Subject: SOAP Headers was implemented (near complete) X-Git-Tag: php-5.0.0b4RC1~143 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9fa7d1c24aa8dd6130179da2eb2e0b37b6e4fd8d;p=php SOAP Headers was implemented (near complete) --- diff --git a/ext/soap/TODO b/ext/soap/TODO index 6db1d4a241..e05dd232d2 100644 --- a/ext/soap/TODO +++ b/ext/soap/TODO @@ -9,9 +9,10 @@ General SOAP ---- -? support for SOAP headers ++ support for SOAP headers ? actor attribute - ? mustUnderstend attribute + + mustUnderstend attribute +- SOAP routing - root attribute - make sure soap 1.1 and 1.2 are supported fully @@ -62,7 +63,7 @@ WSDL ? SOAP binding - parts attribute - - - and + - - HTTP GET/POST binding - MIME binding - SOAP 1.2 bindings??? diff --git a/ext/soap/interop/client_round2_interop.php b/ext/soap/interop/client_round2_interop.php index dfdced7b85..7d9f90455e 100644 --- a/ext/soap/interop/client_round2_interop.php +++ b/ext/soap/interop/client_round2_interop.php @@ -409,7 +409,7 @@ class Interop_Client // XXX no way to set encoding // this lets us set UTF-8, US-ASCII or other //$soap->setEncoding($soap_test->encoding); - if ($this->useWSDL) { + if ($this->useWSDL && !$soap_test->headers && !$soap_test->headers_expect) { $args = ''; foreach ($soap_test->method_params as $pname => $param) { $arg = '$soap_test->method_params["'.$pname.'"]'; diff --git a/ext/soap/interop/client_round2_params.php b/ext/soap/interop/client_round2_params.php index 0b8017418b..ee5aeade3a 100644 --- a/ext/soap/interop/client_round2_params.php +++ b/ext/soap/interop/client_round2_params.php @@ -422,48 +422,48 @@ $soap_tests['GroupB'][] = new SOAP_Test('echoNestedArray', // echoMeStringRequest // echoMeStringRequest with endpoint as header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid (echoMeStringRequest mustUnderstand=0 actor=next)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStringRequest mustUnderstand=0 actor=next)', NULL); $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeStringRequest', 'hello world', 0, SOAP_ACTOR_NEXT); $test->headers_expect = array('echoMeStringResponse'=>'hello world'); $soap_tests['GroupC'][] = $test; -$test = new SOAP_Test('echoVoid (echoMeStringRequest mustUnderstand=0 actor=next)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStringRequest mustUnderstand=0 actor=next)', NULL); $test->type = 'soapval'; $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeStringRequest', new SoapVar('hello world',XSD_STRING), 0, SOAP_ACTOR_NEXT); $test->headers_expect = array('echoMeStringResponse'=>'hello world'); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint as header destination, must understand -$test = new SOAP_Test('echoVoid (echoMeStringRequest mustUnderstand=1 actor=next)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStringRequest mustUnderstand=1 actor=next)', NULL); $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeStringRequest', 'hello world', 1, SOAP_ACTOR_NEXT); $test->headers_expect = array('echoMeStringResponse'=>'hello world'); $soap_tests['GroupC'][] = $test; -$test = new SOAP_Test('echoVoid (echoMeStringRequest mustUnderstand=1 actor=next)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStringRequest mustUnderstand=1 actor=next)', NULL); $test->type = 'soapval'; $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeStringRequest', new SoapVar('hello world',XSD_STRING), 1, SOAP_ACTOR_NEXT); $test->headers_expect = array('echoMeStringResponse'=>'hello world'); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint NOT header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid (echoMeStringRequest mustUnderstand=0 actor=other)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStringRequest mustUnderstand=0 actor=other)', NULL); $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeStringRequest', 'hello world', 0, SOAP_TEST_ACTOR_OTHER); $test->headers_expect = array(); $soap_tests['GroupC'][] = $test; -$test = new SOAP_Test('echoVoid (echoMeStringRequest mustUnderstand=0 actor=other)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStringRequest mustUnderstand=0 actor=other)', NULL); $test->type = 'soapval'; $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeStringRequest', new SoapVar('hello world',XSD_STRING), 0, SOAP_TEST_ACTOR_OTHER); $test->headers_expect = array(); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint NOT header destination, must understand -$test = new SOAP_Test('echoVoid (echoMeStringRequest mustUnderstand=1 actor=other)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStringRequest mustUnderstand=1 actor=other)', NULL); $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeStringRequest', 'hello world', 1, SOAP_TEST_ACTOR_OTHER); $test->headers_expect = array(); $soap_tests['GroupC'][] = $test; -$test = new SOAP_Test('echoVoid (echoMeStringRequest mustUnderstand=1 actor=other)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStringRequest mustUnderstand=1 actor=other)', NULL); $test->type = 'soapval'; $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeStringRequest', new SoapVar('hello world', XSD_STRING), 1, SOAP_TEST_ACTOR_OTHER); $test->headers_expect = array(); @@ -471,13 +471,13 @@ $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint header destination, must understand, // invalid namespace, should recieve a fault -$test = new SOAP_Test('echoVoid (echoMeStringRequest invalid namespace)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStringRequest invalid namespace)', NULL); $test->headers[] = new SoapHeader('http://unknown.org/echoheader/','echoMeStringRequest', 'hello world', 1, SOAP_ACTOR_NEXT); $test->headers_expect = array(); $test->expect_fault = TRUE; $soap_tests['GroupC'][] = $test; -$test = new SOAP_Test('echoVoid (echoMeStringRequest invalid namespace)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStringRequest invalid namespace)', NULL); $test->type = 'soapval'; $test->headers[] = new SoapHeader('http://unknown.org/echoheader/','echoMeStringRequest', new SoapVar('hello world', XSD_STRING), 1, SOAP_ACTOR_NEXT); $test->headers_expect = array(); @@ -488,14 +488,14 @@ $soap_tests['GroupC'][] = $test; // echoMeStructRequest // echoMeStructRequest with endpoint as header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid (echoMeStructRequest mustUnderstand=0 actor=next)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStructRequest mustUnderstand=0 actor=next)', NULL); $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeStructRequest', new SOAPStruct('arg',34,325.325), 0, SOAP_ACTOR_NEXT); $test->headers_expect = array('echoMeStructResponse'=> (object)array('varString'=>'arg','varInt'=>34,'varFloat'=>325.325)); $soap_tests['GroupC'][] = $test; -$test = new SOAP_Test('echoVoid (echoMeStructRequest mustUnderstand=0 actor=next)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStructRequest mustUnderstand=0 actor=next)', NULL); $test->type = 'soapval'; $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeStructRequest', new SoapVar(new SOAPStruct('arg',34,325.325),SOAP_ENC_OBJECT,"SOAPStruct","http://soapinterop.org/xsd"), @@ -505,14 +505,14 @@ $test->headers_expect = $soap_tests['GroupC'][] = $test; // echoMeStructRequest with endpoint as header destination, must understand -$test = new SOAP_Test('echoVoid (echoMeStructRequest mustUnderstand=1 actor=next)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStructRequest mustUnderstand=1 actor=next)', NULL); $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeStructRequest', new SOAPStruct('arg',34,325.325), 1, SOAP_ACTOR_NEXT); $test->headers_expect = array('echoMeStructResponse'=> (object)array('varString'=>'arg','varInt'=>34,'varFloat'=>325.325)); $soap_tests['GroupC'][] = $test; -$test = new SOAP_Test('echoVoid (echoMeStructRequest mustUnderstand=1 actor=next)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStructRequest mustUnderstand=1 actor=next)', NULL); $test->type = 'soapval'; $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeStructRequest', new SoapVar(new SOAPStruct('arg',34,325.325),SOAP_ENC_OBJECT,"SOAPStruct","http://soapinterop.org/xsd"), @@ -522,13 +522,13 @@ $test->headers_expect = $soap_tests['GroupC'][] = $test; // echoMeStructRequest with endpoint NOT header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid (echoMeStructRequest mustUnderstand=0 actor=other)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStructRequest mustUnderstand=0 actor=other)', NULL); $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeStructRequest', new SOAPStruct('arg',34,325.325), 0, SOAP_TEST_ACTOR_OTHER); $test->headers_expect = array(); $soap_tests['GroupC'][] = $test; -$test = new SOAP_Test('echoVoid (echoMeStructRequest mustUnderstand=0 actor=other)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStructRequest mustUnderstand=0 actor=other)', NULL); $test->type = 'soapval'; $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeStructRequest', new SoapVar(new SOAPStruct('arg',34,325.325),SOAP_ENC_OBJECT,"SOAPStruct","http://soapinterop.org/xsd"), @@ -537,13 +537,13 @@ $test->headers_expect = array(); $soap_tests['GroupC'][] = $test; // echoMeStructRequest with endpoint NOT header destination, must understand -$test = new SOAP_Test('echoVoid (echoMeStructRequest mustUnderstand=1 actor=other)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStructRequest mustUnderstand=1 actor=other)', NULL); $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeStructRequest', new SOAPStruct('arg',34,325.325), 1, SOAP_TEST_ACTOR_OTHER); $test->headers_expect = array(); $soap_tests['GroupC'][] = $test; -$test = new SOAP_Test('echoVoid (echoMeStructRequest mustUnderstand=1 actor=other)', NULL); +$test = new SOAP_Test('echoVoid(echoMeStructRequest mustUnderstand=1 actor=other)', NULL); $test->type = 'soapval'; $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeStructRequest', new SoapVar(new SOAPStruct('arg',34,325.325),SOAP_ENC_OBJECT,"SOAPStruct","http://soapinterop.org/xsd"), @@ -555,25 +555,25 @@ $soap_tests['GroupC'][] = $test; // echoMeUnknown // echoMeUnknown with endpoint as header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid (echoMeUnknown mustUnderstand=0 actor=next)', NULL); +$test = new SOAP_Test('echoVoid(echoMeUnknown mustUnderstand=0 actor=next)', NULL); $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeUnknown', 'nobody understands me!',0,SOAP_ACTOR_NEXT); $test->headers_expect = array(); $soap_tests['GroupC'][] = $test; -$test = new SOAP_Test('echoVoid (echoMeUnknown mustUnderstand=0 actor=next)', NULL); +$test = new SOAP_Test('echoVoid(echoMeUnknown mustUnderstand=0 actor=next)', NULL); $test->type = 'soapval'; $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeUnknown', new SoapVar('nobody understands me!',XSD_STRING),0,SOAP_ACTOR_NEXT); $test->headers_expect = array(); $soap_tests['GroupC'][] = $test; // echoMeUnknown with endpoint as header destination, must understand -$test = new SOAP_Test('echoVoid (echoMeUnknown mustUnderstand=1 actor=next)', NULL); +$test = new SOAP_Test('echoVoid(echoMeUnknown mustUnderstand=1 actor=next)', NULL); $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeUnknown', 'nobody understands me!',1,SOAP_ACTOR_NEXT); $test->headers_expect = array(); $test->expect_fault = TRUE; $soap_tests['GroupC'][] = $test; -$test = new SOAP_Test('echoVoid (echoMeUnknown mustUnderstand=1 actor=next)', NULL); +$test = new SOAP_Test('echoVoid(echoMeUnknown mustUnderstand=1 actor=next)', NULL); $test->type = 'soapval'; $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeUnknown', new SoapVar('nobody understands me!',XSD_STRING),1,SOAP_ACTOR_NEXT); $test->headers_expect = array(); @@ -581,24 +581,24 @@ $test->expect_fault = TRUE; $soap_tests['GroupC'][] = $test; // echoMeUnknown with endpoint NOT header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid (echoMeUnknown mustUnderstand=0 actor=other)', NULL); +$test = new SOAP_Test('echoVoid(echoMeUnknown mustUnderstand=0 actor=other)', NULL); $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeUnknown', 'nobody understands me!',0,SOAP_TEST_ACTOR_OTHER); $test->headers_expect = array(); $soap_tests['GroupC'][] = $test; -$test = new SOAP_Test('echoVoid (echoMeUnknown mustUnderstand=0 actor=other)', NULL); +$test = new SOAP_Test('echoVoid(echoMeUnknown mustUnderstand=0 actor=other)', NULL); $test->type = 'soapval'; $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeUnknown', new SoapVar('nobody understands me!',XSD_STRING),0,SOAP_TEST_ACTOR_OTHER); $test->headers_expect = array(); $soap_tests['GroupC'][] = $test; // echoMeUnknown with endpoint NOT header destination, must understand -$test = new SOAP_Test('echoVoid (echoMeUnknown mustUnderstand=1 actor=other)', NULL); +$test = new SOAP_Test('echoVoid(echoMeUnknown mustUnderstand=1 actor=other)', NULL); $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeUnknown', 'nobody understands me!',1,SOAP_TEST_ACTOR_OTHER); $test->headers_expect = array(); $soap_tests['GroupC'][] = $test; -$test = new SOAP_Test('echoVoid (echoMeUnknown mustUnderstand=1 actor=other)', NULL); +$test = new SOAP_Test('echoVoid(echoMeUnknown mustUnderstand=1 actor=other)', NULL); $test->type = 'soapval'; $test->headers[] = new SoapHeader('http://soapinterop.org/echoheader/','echoMeUnknown', new SoapVar('nobody understands me!',XSD_STRING),1,SOAP_TEST_ACTOR_OTHER); $test->headers_expect = array(); diff --git a/ext/soap/interop/server_round2_groupC.php b/ext/soap/interop/server_round2_groupC.php index 7372cae437..5d5544b1db 100644 --- a/ext/soap/interop/server_round2_groupC.php +++ b/ext/soap/interop/server_round2_groupC.php @@ -25,14 +25,15 @@ class SOAP_Interop_GroupC { function echoMeStringRequest($string) { // return $string; - return new SoapVar($string, XSD_STRING, "string", XSD_NAMESPACE, "echoMeStringResponse", $this->method_namespace); +// return new SoapVar($string, XSD_STRING, "string", XSD_NAMESPACE, "echoMeStringResponse", $this->method_namespace); + return new SoapHeader($this->method_namespace, "echoMeStringResponse", $string); } function echoMeStructRequest($struct) { // return $struct; - return new SoapVar($struct, SOAP_ENC_OBJECT, "SOAPStruct", "http://soapinterop.org/", "echoMeStructResponse",$this->method_namespace); -// new SOAP_Value('{'.$this->method_namespace.'}echoMeStructResponse','SOAPStruct',$struct); +// return new SoapVar($struct, SOAP_ENC_OBJECT, "SOAPStruct", "http://soapinterop.org/", "echoMeStructResponse",$this->method_namespace); + return new SoapHeader($this->method_namespace, "echoMeStructResponse", $struct); } function echoVoid() diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index dc8141ccfb..a0c9da9e45 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -249,22 +249,23 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr par Z_OBJCE_P(data) == soap_var_class_entry) { zval **ztype, **zdata, **zns, **zstype, **zname, **znamens; encodePtr enc; + HashTable *ht = Z_OBJPROP_P(data); - if (zend_hash_find(Z_OBJPROP_P(data), "enc_type", sizeof("enc_type"), (void **)&ztype) == FAILURE) { + if (zend_hash_find(ht, "enc_type", sizeof("enc_type"), (void **)&ztype) == FAILURE) { php_error(E_ERROR, "SOAP-ERROR: Encoding: SoapVar hasn't 'enc_type' propery"); } enc = get_conversion(Z_LVAL_P(*ztype)); - if (zend_hash_find(Z_OBJPROP_P(data), "enc_value", sizeof("enc_value"), (void **)&zdata) == FAILURE) { + if (zend_hash_find(ht, "enc_value", sizeof("enc_value"), (void **)&zdata) == FAILURE) { node = master_to_xml(enc, NULL, style, parent); } else { node = master_to_xml(enc, *zdata, style, parent); } if (style == SOAP_ENCODED) { - if (zend_hash_find(Z_OBJPROP_P(data), "enc_stype", sizeof("enc_stype"), (void **)&zstype) == SUCCESS) { - if (zend_hash_find(Z_OBJPROP_P(data), "enc_ns", sizeof("enc_ns"), (void **)&zns) == SUCCESS) { + if (zend_hash_find(ht, "enc_stype", sizeof("enc_stype"), (void **)&zstype) == SUCCESS) { + if (zend_hash_find(ht, "enc_ns", sizeof("enc_ns"), (void **)&zns) == SUCCESS) { set_ns_and_type_ex(node, Z_STRVAL_PP(zns), Z_STRVAL_PP(zstype)); } else { set_ns_and_type_ex(node, NULL, Z_STRVAL_PP(zstype)); @@ -272,10 +273,10 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr par } } - if (zend_hash_find(Z_OBJPROP_P(data), "enc_name", sizeof("enc_name"), (void **)&zname) == SUCCESS) { + if (zend_hash_find(ht, "enc_name", sizeof("enc_name"), (void **)&zname) == SUCCESS) { xmlNodeSetName(node, Z_STRVAL_PP(zname)); } - if (zend_hash_find(Z_OBJPROP_P(data), "enc_namens", sizeof("enc_namens"), (void **)&znamens) == SUCCESS) { + if (zend_hash_find(ht, "enc_namens", sizeof("enc_namens"), (void **)&znamens) == SUCCESS) { xmlNsPtr nsp = encode_add_ns(node, Z_STRVAL_PP(znamens)); xmlSetNs(node, nsp); } @@ -2307,7 +2308,7 @@ static xmlNodePtr check_and_resolve_href(xmlNodePtr data) { if (data && data->properties) { xmlAttrPtr href; - + href = data->properties; while (1) { href = get_attribute(href, "href"); diff --git a/ext/soap/php_packet_soap.c b/ext/soap/php_packet_soap.c index 84a0c5d75e..1df72f66ce 100644 --- a/ext/soap/php_packet_soap.c +++ b/ext/soap/php_packet_soap.c @@ -31,6 +31,7 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction int param_count = 0; int old_error_reporting; int soap_version; + HashTable *hdrs = NULL; ZVAL_NULL(return_value); @@ -177,17 +178,6 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction } } - if (soap_headers && head) { - trav = head->children; - while (trav != NULL) { - if (trav->type == XML_ELEMENT_NODE) { - zval *val = master_to_zval(NULL, trav); - add_assoc_zval(soap_headers, (char*)trav->name, val); - } - trav = trav->next; - } - } - /* Check if contains element */ fault = get_node_ex(body->children,"Fault",envelope_ns); if (fault != NULL) { @@ -259,6 +249,8 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes; int res_count = zend_hash_num_elements(fn->responseParameters); + hdrs = fnb->output.headers; + zend_hash_internal_pointer_reset(fn->responseParameters); while (zend_hash_get_current_data(fn->responseParameters, (void **)&h_param) == SUCCESS) { param = (*h_param); @@ -352,6 +344,35 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction } } + if (soap_headers && head) { + trav = head->children; + while (trav != NULL) { + if (trav->type == XML_ELEMENT_NODE) { + encodePtr enc = NULL; + zval* val; + + if (hdrs) { + smart_str key = {0}; + sdlSoapBindingFunctionHeaderPtr *hdr; + + if (trav->ns) { + smart_str_appends(&key,trav->ns->href); + smart_str_appendc(&key,':'); + } + smart_str_appends(&key,trav->name); + smart_str_0(&key); + if (zend_hash_find(hdrs, key.c, key.len+1, (void**)&hdr) == SUCCESS) { + enc = (*hdr)->encode; + } + smart_str_free(&key); + } + val = master_to_zval(enc, trav); + add_assoc_zval(soap_headers, (char*)trav->name, val); + } + trav = trav->next; + } + } + xmlFreeDoc(response); return TRUE; } diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c index 54b82fcd14..9dd4455823 100644 --- a/ext/soap/php_sdl.c +++ b/ext/soap/php_sdl.c @@ -33,6 +33,7 @@ typedef struct sdlCtx { static void delete_binding(void *binding); static void delete_function(void *function); static void delete_paramater(void *paramater); +static void delete_header(void *header); static void delete_document(void *doc_ptr); encodePtr get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr data, const char *type) @@ -279,6 +280,187 @@ static void load_wsdl_ex(char *struri, sdlCtx *ctx, int include) } } +static void wsdl_soap_binding_body(sdlCtx* ctx, xmlNodePtr node, char* wsdl_soap_namespace, sdlSoapBindingFunctionBody *binding) +{ + xmlNodePtr body, trav, header; + xmlAttrPtr tmp; + + body = get_node_ex(node->children, "body", wsdl_soap_namespace); + if (body) { + tmp = get_attribute(body->properties, "use"); + if (tmp && !strcmp(tmp->children->content, "literal")) { + binding->use = SOAP_LITERAL; + } else { + binding->use = SOAP_ENCODED; + } + + tmp = get_attribute(body->properties, "namespace"); + if (tmp) { + binding->ns = strdup(tmp->children->content); + } + + tmp = get_attribute(body->properties, "parts"); + if (tmp) { + binding->parts = strdup(tmp->children->content); + } + + if (binding->use == SOAP_ENCODED) { + tmp = get_attribute(body->properties, "encodingStyle"); + if (tmp && + strcmp(tmp->children->content,SOAP_1_1_ENC_NAMESPACE) != 0 && + strcmp(tmp->children->content,SOAP_1_2_ENC_NAMESPACE) != 0) { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Unknown encodingStyle '%s'",tmp->children->content); + } else if (tmp == NULL) { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Unspecified encodingStyle"); + } else { + binding->encodingStyle = strdup(tmp->children->content); + } + } + } + + /* Process elements */ + trav = node->children; + FOREACHNODEEX(trav, "header", wsdl_soap_namespace, header) { + xmlAttrPtr tmp; + xmlNodePtr *message, part; + char *ctype, *ns; + sdlSoapBindingFunctionHeaderPtr h; + smart_str key = {0}; + + tmp = get_attribute(header->properties, "message"); + if (!tmp) { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Missing message attribute for
"); + } + parse_namespace(tmp->children->content, &ctype, &ns); + if (zend_hash_find(&ctx->messages, ctype, strlen(ctype)+1, (void**)&message) != SUCCESS) { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Missing with name '%s'", tmp->children->content); + } + if (ctype) {efree(ctype);} + if (ns) {efree(ns);} + + tmp = get_attribute(header->properties, "part"); + if (!tmp) { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Missing part attribute for
"); + } + part = get_node_with_attribute((*message)->children, "part", "name", tmp->children->content); + if (!part) { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Missing part '%s' in ",tmp->children->content); + } + + h = malloc(sizeof(sdlSoapBindingFunctionHeader)); + memset(h, 0, sizeof(sdlSoapBindingFunctionHeader)); + h->name = strdup(tmp->children->content); + + tmp = get_attribute(part->properties, "type"); + if (tmp != NULL) { + h->encode = get_encoder_from_prefix(ctx->root, part, tmp->children->content); + } else { + tmp = get_attribute(part->properties, "element"); + if (tmp != NULL) { + h->element = get_element(ctx->root, part, tmp->children->content); + if (h->element) { + h->encode = h->element->encode; + } + } + } + + tmp = get_attribute(header->properties, "use"); + if (tmp && !strcmp(tmp->children->content, "encoded")) { + h->use = SOAP_ENCODED; + } else { + h->use = SOAP_LITERAL; + } + + tmp = get_attribute(header->properties, "namespace"); + if (tmp) { + h->ns = strdup(tmp->children->content); + } + + if (h->use == SOAP_ENCODED) { + tmp = get_attribute(header->properties, "encodingStyle"); + if (tmp && + strcmp(tmp->children->content,SOAP_1_1_ENC_NAMESPACE) != 0 && + strcmp(tmp->children->content,SOAP_1_2_ENC_NAMESPACE) != 0) { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Unknown encodingStyle '%s'",tmp->children->content); + } else if (tmp == NULL) { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Unspecified encodingStyle"); + } else { + h->encodingStyle = strdup(tmp->children->content); + } + } + + if (binding->headers == NULL) { + binding->headers = malloc(sizeof(HashTable)); + zend_hash_init(binding->headers, 0, NULL, delete_header, 1); + } + + if (h->ns) { + smart_str_appends(&key,h->ns); + smart_str_appendc(&key,':'); + } + smart_str_appends(&key,h->name); + smart_str_0(&key); + if (zend_hash_add(binding->headers, key.c, key.len+1, (void**)&h, sizeof(sdlSoapBindingFunctionHeaderPtr), NULL) != SUCCESS) { + delete_header((void**)&h); + } + smart_str_free(&key); + + } + ENDFOREACH(trav); +} + +static HashTable* wsdl_message(sdlCtx *ctx, char* message_name) +{ + xmlNodePtr trav, part, message, *tmp; + HashTable* parameters = NULL; + char *ns, *ctype; + + parse_namespace(message_name, &ctype, &ns); + if (zend_hash_find(&ctx->messages, ctype, strlen(ctype)+1, (void**)&tmp) != SUCCESS) { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Missing with name '%s'", message->children->content); + } + message = *tmp; + if (ctype) {efree(ctype);} + if (ns) {efree(ns);} + + parameters = malloc(sizeof(HashTable)); + zend_hash_init(parameters, 0, NULL, delete_paramater, 1); + + trav = message->children; + FOREACHNODE(trav, "part", part) { + xmlAttrPtr element, type, name; + sdlParamPtr param; + + param = malloc(sizeof(sdlParam)); + memset(param,0,sizeof(sdlParam)); + param->order = 0; + + name = get_attribute(part->properties, "name"); + if (name == NULL) { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: No name associated with '%s'", message->name); + } + + param->paramName = strdup(name->children->content); + + type = get_attribute(part->properties, "type"); + if (type != NULL) { + param->encode = get_encoder_from_prefix(ctx->root, part, type->children->content); + } else { + element = get_attribute(part->properties, "element"); + if (element != NULL) { + param->element = get_element(ctx->root, part, element->children->content); + if (param->element) { + param->encode = param->element->encode; + } + } + } + + zend_hash_next_index_insert(parameters, ¶m, sizeof(sdlParamPtr), NULL); + } + ENDFOREACH(trav); + return parameters; +} + static sdlPtr load_wsdl(char *struri) { sdlCtx ctx; @@ -419,7 +601,7 @@ static sdlPtr load_wsdl(char *struri) trav2 = binding->children; FOREACHNODE(trav2, "operation", operation) { sdlFunctionPtr function; - xmlNodePtr input, output, fault, portTypeOperation, portTypeInput, portTypeOutput, msgInput, msgOutput; + xmlNodePtr input, output, fault, portTypeOperation; xmlAttrPtr op_name, paramOrder; op_name = get_attribute(operation->properties, "name"); @@ -473,205 +655,58 @@ static sdlPtr load_wsdl(char *struri) function->bindingAttributes = (void *)soapFunctionBinding; } - input = get_node(operation->children, "input"); - portTypeInput = get_node(portTypeOperation->children, "input"); - - output = get_node(operation->children, "output"); - portTypeOutput = get_node(portTypeOperation->children, "output"); - + input = get_node(portTypeOperation->children, "input"); if (input != NULL) { xmlAttrPtr message, name; - xmlNodePtr part, trav3; - char *ns, *ctype; - - if (portTypeInput) { - message = get_attribute(portTypeInput->properties, "message"); - if (message == NULL) { - php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Missing name for of '%s'", op_name->children->content); - } - - name = get_attribute(portTypeInput->properties, "name"); - if (name != NULL) { - function->requestName = strdup(name->children->content); - } else { - function->requestName = strdup(function->functionName); - } - function->requestParameters = malloc(sizeof(HashTable)); - zend_hash_init(function->requestParameters, 0, NULL, delete_paramater, 1); - - parse_namespace(message->children->content, &ctype, &ns); - if (zend_hash_find(&ctx.messages, ctype, strlen(ctype)+1, (void**)&tmp) != SUCCESS) { - php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Missing with name '%s'", message->children->content); - } - msgInput = *tmp; + message = get_attribute(input->properties, "message"); + if (message == NULL) { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Missing name for of '%s'", op_name->children->content); + } + function->requestParameters = wsdl_message(&ctx, message->children->content); - if (ctype) {efree(ctype);} - if (ns) {efree(ns);} + name = get_attribute(input->properties, "name"); + if (name != NULL) { + function->requestName = strdup(name->children->content); + } else { + function->requestName = strdup(function->functionName); + } - if (tmpbinding->bindingType == BINDING_SOAP) { + if (tmpbinding->bindingType == BINDING_SOAP) { + input = get_node(operation->children, "input"); + if (input != NULL) { sdlSoapBindingFunctionPtr soapFunctionBinding = function->bindingAttributes; - xmlNodePtr body; - xmlAttrPtr tmp; - - body = get_node_ex(input->children, "body", wsdl_soap_namespace); - if (body) { - tmp = get_attribute(body->properties, "use"); - if (tmp && !strcmp(tmp->children->content, "literal")) { - soapFunctionBinding->input.use = SOAP_LITERAL; - } else { - soapFunctionBinding->input.use = SOAP_ENCODED; - } - - tmp = get_attribute(body->properties, "namespace"); - if (tmp) { - soapFunctionBinding->input.ns = strdup(tmp->children->content); - } - - tmp = get_attribute(body->properties, "parts"); - if (tmp) { - soapFunctionBinding->input.parts = strdup(tmp->children->content); - } - - tmp = get_attribute(body->properties, "encodingStyle"); - if (tmp) { - soapFunctionBinding->input.encodingStyle = strdup(tmp->children->content); - } - } - } - - trav3 = msgInput->children; - FOREACHNODE(trav3, "part", part) { - xmlAttrPtr element, type, name; - sdlParamPtr param; - - param = malloc(sizeof(sdlParam)); - memset(param,0,sizeof(sdlParam)); - param->order = 0; - - name = get_attribute(part->properties, "name"); - if (name == NULL) { - php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: No name associated with '%s'", msgInput->name); - } - - param->paramName = strdup(name->children->content); - - type = get_attribute(part->properties, "type"); - if (type != NULL) { - param->encode = get_encoder_from_prefix(ctx.root, part, type->children->content); - } else { - element = get_attribute(part->properties, "element"); - if (element != NULL) { - param->element = get_element(ctx.root, part, element->children->content); - if (param->element) { - param->encode = param->element->encode; - } - } - } - - zend_hash_next_index_insert(function->requestParameters, ¶m, sizeof(sdlParamPtr), NULL); + wsdl_soap_binding_body(&ctx, input, wsdl_soap_namespace,&soapFunctionBinding->input); } - ENDFOREACH(trav3); } - } + output = get_node(portTypeOperation->children, "output"); if (output != NULL) { xmlAttrPtr message, name; - xmlNodePtr part, trav3; - char *ns, *ctype; - - if (portTypeOutput) { - name = get_attribute(portTypeOutput->properties, "name"); - if (name != NULL) { - function->responseName = strdup(name->children->content); - } else if (input == NULL) { - function->responseName = strdup(function->functionName); - } else { - function->responseName = malloc(strlen(function->functionName) + strlen("Response") + 1); - sprintf(function->responseName, "%sResponse", function->functionName); - } - function->responseParameters = malloc(sizeof(HashTable)); - zend_hash_init(function->responseParameters, 0, NULL, delete_paramater, 1); - - message = get_attribute(portTypeOutput->properties, "message"); - if (message == NULL) { - php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Missing name for of '%s'", op_name->children->content); - } - - parse_namespace(message->children->content, &ctype, &ns); - if (zend_hash_find(&ctx.messages, ctype, strlen(ctype)+1, (void**)&tmp) != SUCCESS) { - php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Missing with name '%s'", message->children->content); - } - msgOutput = *tmp; - if (ctype) {efree(ctype);} - if (ns) {efree(ns);} + message = get_attribute(output->properties, "message"); + if (message == NULL) { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Missing name for of '%s'", op_name->children->content); + } + function->responseParameters = wsdl_message(&ctx, message->children->content); + + name = get_attribute(output->properties, "name"); + if (name != NULL) { + function->responseName = strdup(name->children->content); + } else if (input == NULL) { + function->responseName = strdup(function->functionName); + } else { + function->responseName = malloc(strlen(function->functionName) + strlen("Response") + 1); + sprintf(function->responseName, "%sResponse", function->functionName); + } - if (tmpbinding->bindingType == BINDING_SOAP) { + if (tmpbinding->bindingType == BINDING_SOAP) { + output = get_node(operation->children, "output"); + if (output != NULL) { sdlSoapBindingFunctionPtr soapFunctionBinding = function->bindingAttributes; - xmlNodePtr body; - xmlAttrPtr tmp; - - body = get_node_ex(output->children, "body", wsdl_soap_namespace); - if (body) { - tmp = get_attribute(body->properties, "use"); - if (tmp && !strcmp(tmp->children->content, "literal")) { - soapFunctionBinding->output.use = SOAP_LITERAL; - } else { - soapFunctionBinding->output.use = SOAP_ENCODED; - } - - tmp = get_attribute(body->properties, "namespace"); - if (tmp) { - soapFunctionBinding->output.ns = strdup(tmp->children->content); - } - - tmp = get_attribute(body->properties, "parts"); - if (tmp) { - soapFunctionBinding->output.parts = strdup(tmp->children->content); - } - - tmp = get_attribute(body->properties, "encodingStyle"); - if (tmp) { - soapFunctionBinding->output.encodingStyle = strdup(tmp->children->content); - } - } - } - - trav3 = msgOutput->children; - FOREACHNODE(trav3, "part", part) { - sdlParamPtr param; - xmlAttrPtr element, type, name; - - param = malloc(sizeof(sdlParam)); - memset(param, 0, sizeof(sdlParam)); - param->order = 0; - - name = get_attribute(part->properties, "name"); - if (name == NULL) { - php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: No name associated with '%s'", msgOutput->name); - } - - param->paramName = strdup(name->children->content); - - - type = get_attribute(part->properties, "type"); - if (type) { - param->encode = get_encoder_from_prefix(ctx.root, part, type->children->content); - } else { - element = get_attribute(part->properties, "element"); - if (element) { - param->element = get_element(ctx.root, part, element->children->content); - if (param->element) { - param->encode = param->element->encode; - } - } - } - - zend_hash_next_index_insert(function->responseParameters, ¶m, sizeof(sdlParamPtr), NULL); + wsdl_soap_binding_body(&ctx, output, wsdl_soap_namespace, &soapFunctionBinding->output); } - ENDFOREACH(trav3); } } @@ -682,6 +717,7 @@ static sdlPtr load_wsdl(char *struri) fault = get_node(operation->children, "fault"); if (!fault) { + /* FIXME: */ } function->binding = tmpbinding; @@ -870,6 +906,21 @@ static void delete_paramater(void *data) free(param); } +static void delete_header(void *data) +{ + sdlSoapBindingFunctionHeaderPtr hdr = *((sdlSoapBindingFunctionHeaderPtr*)data); + if (hdr->name) { + free(hdr->name); + } + if (hdr->ns) { + free(hdr->ns); + } + if (hdr->encodingStyle) { + free(hdr->encodingStyle); + } + free(hdr); +} + static void delete_document(void *doc_ptr) { xmlDocPtr doc = *((xmlDocPtr*)doc_ptr); diff --git a/ext/soap/php_sdl.h b/ext/soap/php_sdl.h index f765d5fbfd..221c7e03ef 100644 --- a/ext/soap/php_sdl.h +++ b/ext/soap/php_sdl.h @@ -63,11 +63,21 @@ struct _sdlSoapBinding { int style; }; +typedef struct _sdlSoapBindingFunctionHeader { + char *name; + char *ns; + int use; + sdlTypePtr element; + encodePtr encode; + char *encodingStyle; /* not implemented yet */ +} sdlSoapBindingFunctionHeader, *sdlSoapBindingFunctionHeaderPtr; + struct _sdlSoapBindingFunctionBody { - char *ns; - int use; - char *parts; /* not implemented yet */ - char *encodingStyle; /* not implemented yet */ + char *ns; + int use; + char *parts; /* not implemented yet */ + char *encodingStyle; /* not implemented yet */ + HashTable *headers; /* array of sdlSoapBindingFunctionHeaderPtr */ }; struct _sdlSoapBindingFunction { diff --git a/ext/soap/php_xml.h b/ext/soap/php_xml.h index eb34d2db11..9616e163ae 100644 --- a/ext/soap/php_xml.h +++ b/ext/soap/php_xml.h @@ -48,26 +48,28 @@ void *php_stream_xmlIO_open_wrapper(const char *filename); int php_stream_xmlIO_read(void *context, char *buffer, int len); int php_stream_xmlIO_close(void *context); -#define FOREACHATTRNODE(n,c,i) \ +#define FOREACHATTRNODE(n,c,i) FOREACHATTRNODEEX(n,c,NULL,i) +#define FOREACHATTRNODEEX(n,c,ns,i) \ do { \ if (n == NULL) { \ break; \ } \ if (c) { \ - i = get_attribute(n,c); \ + i = get_attribute_ex(n,c,ns); \ } else { \ i = n; \ } \ if (i != NULL) { \ n = i; -#define FOREACHNODE(n,c,i) \ +#define FOREACHNODE(n,c,i) FOREACHNODEEX(n,c,NULL,i) +#define FOREACHNODEEX(n,c,ns,i) \ do { \ if (n == NULL) { \ break; \ } \ if (c) { \ - i = get_node(n,c); \ + i = get_node_ex(n,c,NULL); \ } else { \ i = n; \ } \ diff --git a/ext/soap/soap.c b/ext/soap/soap.c index 7337e7e848..3e66a50954 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -30,13 +30,14 @@ static int le_url = 0; static int le_service = 0; typedef struct _soapHeader { - sdlFunctionPtr function; - zval function_name; - int mustUnderstand; - int num_params; - zval **parameters; - zval retval; - struct _soapHeader *next; + sdlFunctionPtr function; + zval function_name; + int mustUnderstand; + int num_params; + zval **parameters; + zval retval; + sdlSoapBindingFunctionHeaderPtr hdr; + struct _soapHeader *next; } soapHeader; /* Local functions */ @@ -443,7 +444,7 @@ PHP_MINIT_FUNCTION(soap) REGISTER_LONG_CONSTANT("SOAP_ENC_ARRAY", SOAP_ENC_ARRAY, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("XSD_NAMESPACE", XSD_NAMESPACE, CONST_CS | CONST_PERSISTENT); - + REGISTER_LONG_CONSTANT("XSD_ANYTYPE", XSD_ANYTYPE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("XSD_STRING", XSD_STRING, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("XSD_BOOLEAN", XSD_BOOLEAN, CONST_CS | CONST_PERSISTENT); @@ -1136,7 +1137,7 @@ PHP_METHOD(soapserver, handle) SOAP_GLOBAL(soap_version) = SOAP_1_1; } else if (strcmp(env->ns->href,SOAP_1_2_ENV_NAMESPACE) == 0) { SOAP_GLOBAL(soap_version) = SOAP_1_2; - } + } } php_error(E_ERROR,"DTD are not supported by SOAP"); } @@ -1226,7 +1227,7 @@ PHP_METHOD(soapserver, handle) soapHeader *h = header; header = header->next; - if (service->sdl && !h->function && h->mustUnderstand) { + if (h->mustUnderstand && service->sdl && !h->function && !h->hdr) { soap_server_fault("MustUnderstand","Header not understood", NULL, NULL TSRMLS_CC); } @@ -1302,7 +1303,6 @@ PHP_METHOD(soapserver, handle) php_end_ob_buffer(0, 0 TSRMLS_CC); /* xmlDocDumpMemoryEnc(doc_return, &buf, &size, XML_CHAR_ENCODING_UTF8); */ - xmlSetDocCompressMode(doc_return, 1); xmlDocDumpMemory(doc_return, &buf, &size); if (size == 0) { @@ -2201,16 +2201,16 @@ static sdlFunctionPtr deseralize_function_call(sdlPtr sdl, xmlDocPtr request, ch trav = head->children; while (trav != NULL) { if (trav->type == XML_ELEMENT_NODE) { - xmlNodePtr func = trav; + xmlNodePtr hdr_func = trav; xmlAttrPtr attr; int mustUnderstand = 0; if (*version == SOAP_1_1) { - attr = get_attribute_ex(func->properties,"encodingStyle",SOAP_1_1_ENV_NAMESPACE); + attr = get_attribute_ex(hdr_func->properties,"encodingStyle",SOAP_1_1_ENV_NAMESPACE); if (attr && strcmp(attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) { soap_server_fault("Client","Unknown Data Encoding Style", NULL, NULL TSRMLS_CC); } - attr = get_attribute_ex(func->properties,"actor",envelope_ns); + attr = get_attribute_ex(hdr_func->properties,"actor",envelope_ns); if (attr != NULL) { if (strcmp(attr->children->content,"http://schemas.xmlsoap.org/soap/actor/next") != 0 && (actor == NULL || strcmp(attr->children->content,actor) != 0)) { @@ -2218,11 +2218,11 @@ static sdlFunctionPtr deseralize_function_call(sdlPtr sdl, xmlDocPtr request, ch } } } else if (*version == SOAP_1_2) { - attr = get_attribute_ex(func->properties,"encodingStyle",SOAP_1_2_ENV_NAMESPACE); + attr = get_attribute_ex(hdr_func->properties,"encodingStyle",SOAP_1_2_ENV_NAMESPACE); if (attr && strcmp(attr->children->content,SOAP_1_2_ENC_NAMESPACE) != 0) { soap_server_fault("DataEncodingUnknown","Unknown Data Encoding Style", NULL, NULL TSRMLS_CC); } - attr = get_attribute_ex(func->properties,"role",envelope_ns); + attr = get_attribute_ex(hdr_func->properties,"role",envelope_ns); if (attr != NULL) { if (strcmp(attr->children->content,"http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver") != 0 && strcmp(attr->children->content,"http://www.w3.org/2003/05/soap-envelope/role/next") != 0 && @@ -2231,7 +2231,7 @@ static sdlFunctionPtr deseralize_function_call(sdlPtr sdl, xmlDocPtr request, ch } } } - attr = get_attribute_ex(func->properties,"mustUnderstand",envelope_ns); + attr = get_attribute_ex(hdr_func->properties,"mustUnderstand",envelope_ns); if (attr) { if (strcmp(attr->children->content,"1") == 0 || strcmp(attr->children->content,"true") == 0) { @@ -2245,15 +2245,39 @@ static sdlFunctionPtr deseralize_function_call(sdlPtr sdl, xmlDocPtr request, ch } h = emalloc(sizeof(soapHeader)); memset(h, 0, sizeof(soapHeader)); - h->function = find_function(sdl, func, &h->function_name); h->mustUnderstand = mustUnderstand; - if (h->function && h->function->binding && h->function->binding->bindingType == BINDING_SOAP) { - sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)h->function->bindingAttributes; - if (fnb->style == SOAP_RPC) { - func = func->children; + h->function = find_function(sdl, hdr_func, &h->function_name); + if (!h->function && sdl && function && function->binding && function->binding->bindingType == BINDING_SOAP) { + sdlSoapBindingFunctionHeaderPtr *hdr; + sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes; + if (fnb->input.headers) { + smart_str key = {0}; + + if (hdr_func->ns) { + smart_str_appends(&key, hdr_func->ns->href); + smart_str_appendc(&key, ':'); + } + smart_str_appendl(&key, Z_STRVAL(h->function_name), Z_STRLEN(h->function_name)); + smart_str_0(&key); + if (zend_hash_find(fnb->input.headers, key.c, key.len+1, (void**)&hdr) == SUCCESS) { + h->hdr = *hdr; + } + smart_str_free(&key); + } + } + if (h->hdr) { + h->num_params = 1; + h->parameters = emalloc(sizeof(zval*)); + h->parameters[0] = master_to_zval(h->hdr->encode, hdr_func); + } else { + if (h->function && h->function->binding && h->function->binding->bindingType == BINDING_SOAP) { + sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)h->function->bindingAttributes; + if (fnb->style == SOAP_RPC) { + hdr_func = hdr_func->children; + } } + deseralize_parameters(hdr_func, h->function, &h->num_params, &h->parameters); } - deseralize_parameters(func, h->function, &h->num_params, &h->parameters); INIT_ZVAL(h->retval); if (last == NULL) { *headers = h; @@ -2413,7 +2437,6 @@ static xmlDocPtr seralize_response_call(sdlFunctionPtr function, char *function_ } xmlDocSetRootElement(doc, envelope); - if (Z_TYPE_P(ret) == IS_OBJECT && Z_OBJCE_P(ret) == soap_fault_class_entry) { body = xmlNewChild(envelope, ns, "Body", NULL); @@ -2489,8 +2512,64 @@ static xmlDocPtr seralize_response_call(sdlFunctionPtr function, char *function_ h = headers; while (h != NULL) { if (Z_TYPE(h->retval) != IS_NULL) { - if (seralize_response_call2(head, h->function, Z_STRVAL(h->function_name), uri, &h->retval, version, 0 TSRMLS_CC) == SOAP_ENCODED) { - use = SOAP_ENCODED; + encodePtr hdr_enc = NULL; + int hdr_use = SOAP_LITERAL; + zval *hdr_ret = &h->retval; + char *hdr_ns = h->hdr?h->hdr->ns:NULL; + char *hdr_name = Z_STRVAL(h->function_name); + + + if (Z_TYPE(h->retval) == IS_OBJECT && + Z_OBJCE(h->retval) == soap_header_class_entry) { + HashTable* ht = Z_OBJPROP(h->retval); + zval **tmp; + + if (function && function->binding && function->binding->bindingType == BINDING_SOAP) { + sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes; + + if (fnb->output.headers) { + sdlSoapBindingFunctionHeaderPtr *hdr; + smart_str key = {0}; + + if (zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&tmp) == SUCCESS && + Z_TYPE_PP(tmp) == IS_STRING) { + smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); + smart_str_appendc(&key, ':'); + hdr_ns = Z_STRVAL_PP(tmp); + } + if (zend_hash_find(ht, "name", sizeof("name"), (void**)&tmp) == SUCCESS && + Z_TYPE_PP(tmp) == IS_STRING) { + smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); + hdr_name = Z_STRVAL_PP(tmp); + } + smart_str_0(&key); + if (zend_hash_find(fnb->output.headers, key.c, key.len+1, (void**)&hdr) == SUCCESS) { + hdr_enc = (*hdr)->encode; + hdr_use = (*hdr)->use; + } + smart_str_free(&key); + } + } + if (zend_hash_find(ht, "data", sizeof("data"), (void**)&tmp) == SUCCESS) { + hdr_ret = *tmp; + } else { + hdr_ret = NULL; + } + } + + if (h->function) { + if (seralize_response_call2(head, h->function, Z_STRVAL(h->function_name), uri, hdr_ret, version, 0 TSRMLS_CC) == SOAP_ENCODED) { + use = SOAP_ENCODED; + } + } else { + xmlNodePtr xmlHdr = master_to_xml(hdr_enc, hdr_ret, hdr_use, head); + if (hdr_name) { + xmlNodeSetName(xmlHdr,hdr_name); + } + if (hdr_ns) { + xmlNsPtr nsptr = encode_add_ns(xmlHdr,hdr_ns); + xmlSetNs(xmlHdr, nsptr); + } } } h = h->next; @@ -2500,7 +2579,6 @@ static xmlDocPtr seralize_response_call(sdlFunctionPtr function, char *function_ xmlUnlinkNode(head); xmlFreeNode(head); } - } body = xmlNewChild(envelope, ns, "Body", NULL); @@ -2528,10 +2606,11 @@ static xmlDocPtr seralize_response_call(sdlFunctionPtr function, char *function_ static xmlDocPtr seralize_function_call(zval *this_ptr, sdlFunctionPtr function, char *function_name, char *uri, zval **arguments, int arg_count, int version, HashTable *soap_headers TSRMLS_DC) { xmlDoc *doc; - xmlNode *envelope = NULL, *body, *method = NULL; - xmlNs *ns = NULL; + xmlNodePtr envelope = NULL, body, method = NULL, head = NULL; + xmlNsPtr ns = NULL; zval **zstyle, **zuse; int i, style, use; + HashTable *hdrs = NULL; encode_reset_ns(); @@ -2552,7 +2631,69 @@ static xmlDocPtr seralize_function_call(zval *this_ptr, sdlFunctionPtr function, xmlDocSetRootElement(doc, envelope); if (soap_headers) { - xmlNodePtr head = xmlNewChild(envelope, ns, "Header", NULL); + head = xmlNewChild(envelope, ns, "Header", NULL); + } + + body = xmlNewChild(envelope, ns, "Body", NULL); + + if (function && function->binding->bindingType == BINDING_SOAP) { + sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes; + + hdrs = fnb->input.headers; + style = fnb->style; + /*FIXME: how to pass method name if style is SOAP_DOCUMENT */ + /*style = SOAP_RPC;*/ + use = fnb->input.use; + if (style == SOAP_RPC) { + ns = encode_add_ns(body, fnb->input.ns); + if (function->requestName) { + method = xmlNewChild(body, ns, function->requestName, NULL); + } else { + method = xmlNewChild(body, ns, function->functionName, NULL); + } + } + } else { + if (zend_hash_find(Z_OBJPROP_P(this_ptr), "style", sizeof("style"), (void **)&zstyle) == SUCCESS) { + style = Z_LVAL_PP(zstyle); + } else { + style = SOAP_RPC; + } + /*FIXME: how to pass method name if style is SOAP_DOCUMENT */ + /*style = SOAP_RPC;*/ + if (style == SOAP_RPC) { + ns = encode_add_ns(body, uri); + method = xmlNewChild(body, ns, function_name, NULL); + } + + if (zend_hash_find(Z_OBJPROP_P(this_ptr), "use", sizeof("use"), (void **)&zuse) == SUCCESS && + Z_LVAL_PP(zuse) == SOAP_LITERAL) { + use = SOAP_LITERAL; + } else { + use = SOAP_ENCODED; + } + } + + for (i = 0;i < arg_count;i++) { + xmlNodePtr param; + sdlParamPtr parameter = get_param(function, NULL, i, FALSE); + + if (style == SOAP_RPC) { + param = seralize_parameter(parameter, arguments[i], i, NULL, use, method TSRMLS_CC); + } else if (style == SOAP_DOCUMENT) { + param = seralize_parameter(parameter, arguments[i], i, NULL, use, body TSRMLS_CC); + if (function && function->binding->bindingType == BINDING_SOAP) { + sdlParamPtr *sparam; + + if (zend_hash_index_find(function->requestParameters, i, (void **)&sparam) == SUCCESS && (*sparam)->element) { + ns = encode_add_ns(param, (*sparam)->element->namens); + xmlNodeSetName(param, (*sparam)->element->name); + xmlSetNs(param, ns); + } + } + } + } + + if (head) { zval** header; zend_hash_internal_pointer_reset(soap_headers); @@ -2566,9 +2707,29 @@ static xmlDocPtr seralize_function_call(zval *this_ptr, sdlFunctionPtr function, Z_TYPE_PP(ns) == IS_STRING) { xmlNodePtr h; xmlNsPtr nsptr; - + int hdr_use = SOAP_LITERAL; + encodePtr enc = NULL; + + if (hdrs) { + smart_str key = {0}; + sdlSoapBindingFunctionHeaderPtr *hdr; + + smart_str_appendl(&key, Z_STRVAL_PP(ns), Z_STRLEN_PP(ns)); + smart_str_appendc(&key, ':'); + smart_str_appendl(&key, Z_STRVAL_PP(name), Z_STRLEN_PP(name)); + smart_str_0(&key); + if (zend_hash_find(hdrs, key.c, key.len+1,(void**)&hdr) == SUCCESS) { + hdr_use = (*hdr)->use; + enc = (*hdr)->encode; + if (hdr_use == SOAP_ENCODED) { + use = SOAP_ENCODED; + } + } + smart_str_free(&key); + } + if (zend_hash_find(ht, "data", sizeof("data"), (void**)&tmp) == SUCCESS) { - h = master_to_xml(NULL,*tmp,SOAP_DOCUMENT,head); + h = master_to_xml(enc, *tmp, hdr_use, head); xmlNodeSetName(h, Z_STRVAL_PP(name)); } else { h = xmlNewNode(NULL, Z_STRVAL_PP(name)); @@ -2606,51 +2767,13 @@ static xmlDocPtr seralize_function_call(zval *this_ptr, sdlFunctionPtr function, xmlSetProp(h, SOAP_1_2_ENV_NS_PREFIX":role",SOAP_1_2_ACTOR_UNLIMATERECEIVER); } } - } + } } } zend_hash_move_forward(soap_headers); } } - body = xmlNewChild(envelope, ns, "Body", NULL); - - if (function && function->binding->bindingType == BINDING_SOAP) { - sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes; - - style = fnb->style; - /*FIXME: how to pass method name if style is SOAP_DOCUMENT */ - /*style = SOAP_RPC;*/ - use = fnb->input.use; - if (style == SOAP_RPC) { - ns = encode_add_ns(body, fnb->input.ns); - if (function->requestName) { - method = xmlNewChild(body, ns, function->requestName, NULL); - } else { - method = xmlNewChild(body, ns, function->functionName, NULL); - } - } - } else { - if (zend_hash_find(Z_OBJPROP_P(this_ptr), "style", sizeof("style"), (void **)&zstyle) == SUCCESS) { - style = Z_LVAL_PP(zstyle); - } else { - style = SOAP_RPC; - } - /*FIXME: how to pass method name if style is SOAP_DOCUMENT */ - /*style = SOAP_RPC;*/ - if (style == SOAP_RPC) { - ns = encode_add_ns(body, uri); - method = xmlNewChild(body, ns, function_name, NULL); - } - - if (zend_hash_find(Z_OBJPROP_P(this_ptr), "use", sizeof("use"), (void **)&zuse) == SUCCESS && - Z_LVAL_PP(zuse) == SOAP_LITERAL) { - use = SOAP_LITERAL; - } else { - use = SOAP_ENCODED; - } - } - if (use == SOAP_ENCODED) { xmlNewNs(envelope, XSD_NAMESPACE, XSD_NS_PREFIX); xmlNewNs(envelope, XSI_NAMESPACE, XSI_NS_PREFIX); @@ -2665,26 +2788,6 @@ static xmlDocPtr seralize_function_call(zval *this_ptr, sdlFunctionPtr function, } } - for (i = 0;i < arg_count;i++) { - xmlNodePtr param; - sdlParamPtr parameter = get_param(function, NULL, i, FALSE); - - if (style == SOAP_RPC) { - param = seralize_parameter(parameter, arguments[i], i, NULL, use, method TSRMLS_CC); - } else if (style == SOAP_DOCUMENT) { - param = seralize_parameter(parameter, arguments[i], i, NULL, use, body TSRMLS_CC); - if (function && function->binding->bindingType == BINDING_SOAP) { - sdlParamPtr *sparam; - - if (zend_hash_index_find(function->requestParameters, i, (void **)&sparam) == SUCCESS && (*sparam)->element) { - ns = encode_add_ns(param, (*sparam)->element->namens); - xmlNodeSetName(param, (*sparam)->element->name); - xmlSetNs(param, ns); - } - } - } - } - return doc; } @@ -2731,7 +2834,7 @@ static xmlNodePtr seralize_zval(zval *val, sdlParamPtr param, char *paramName, i if (param != NULL) { enc = param->encode; } else { - enc = get_conversion(val->type); + enc = NULL; } xmlParam = master_to_xml(enc, val, style, parent); if (!strcmp(xmlParam->name, "BOGUS")) { diff --git a/ext/soap/tests/schema/schema054.phpt b/ext/soap/tests/schema/schema054.phpt index 0570da0bb2..fc5cb05761 100644 --- a/ext/soap/tests/schema/schema054.phpt +++ b/ext/soap/tests/schema/schema054.phpt @@ -11,7 +11,7 @@ echo "ok"; ?> --EXPECT-- -a123b123.5 +a123b123.5 array(2) { ["a"]=> int(123) diff --git a/ext/soap/tests/schema/schema055.phpt b/ext/soap/tests/schema/schema055.phpt index c4d9577425..013cd92fd8 100644 --- a/ext/soap/tests/schema/schema055.phpt +++ b/ext/soap/tests/schema/schema055.phpt @@ -18,7 +18,7 @@ echo "ok"; ?> --EXPECT-- -a123b123.5 +a123b123.5 array(2) { ["a"]=> int(123) diff --git a/ext/soap/tests/schema/test_schema.inc b/ext/soap/tests/schema/test_schema.inc index 186eda33a6..4e1e2df9eb 100644 --- a/ext/soap/tests/schema/test_schema.inc +++ b/ext/soap/tests/schema/test_schema.inc @@ -37,7 +37,7 @@ $wsdl = << - +