diff options
author | Dmitry Stogov <dmitry@php.net> | 2004-02-19 08:21:13 +0000 |
---|---|---|
committer | Dmitry Stogov <dmitry@php.net> | 2004-02-19 08:21:13 +0000 |
commit | 15ccb3be8d6f4497502050565bbf84b87f109fd8 (patch) | |
tree | addef32fe38bb096e3a5a5bbe3625a6b971a7b51 | |
parent | 0e692f950664ece1665700a565f4fceec1ecc2a5 (diff) | |
download | php-git-15ccb3be8d6f4497502050565bbf84b87f109fd8.tar.gz |
Support for SOAP Fault encoding according to WSDL <fault> and <soap:fault>
-rw-r--r-- | ext/soap/TODO | 3 | ||||
-rw-r--r-- | ext/soap/php_sdl.c | 249 | ||||
-rw-r--r-- | ext/soap/php_sdl.h | 49 | ||||
-rw-r--r-- | ext/soap/soap.c | 170 |
4 files changed, 364 insertions, 107 deletions
diff --git a/ext/soap/TODO b/ext/soap/TODO index e0f9156c87..a39ea359e5 100644 --- a/ext/soap/TODO +++ b/ext/soap/TODO @@ -49,11 +49,12 @@ Encoding WSDL ---- ? server part support for "document" style encoding +? support for <fault>, <soap:fault> +- <soap:headerfault> - <soap:body> parts attribute (with MIME/DIME binding) - MIME binding - DIME binding - support for portType/operation parameterOrder attribute -- support for <fault>, <soap:fault>, <soap:headerfault> - support for binding operation input/output name attribute (part of overloading) - function/method overloading/redeclaration (test(int); test(string)) - wsdl auto generation diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c index 3993758f15..9156ce7c56 100644 --- a/ext/soap/php_sdl.c +++ b/ext/soap/php_sdl.c @@ -33,6 +33,7 @@ # define O_BINARY 0 #endif +static void delete_fault(void *fault); static void delete_binding(void *binding); static void delete_function(void *function); static void delete_parameter(void *paramater); @@ -344,14 +345,16 @@ static void wsdl_soap_binding_body(sdlCtx* ctx, xmlNodePtr node, char* wsdl_soap if (binding->use == SOAP_ENCODED) { tmp = get_attribute(body->properties, "encodingStyle"); - if (tmp && - strncmp(tmp->children->content,SOAP_1_1_ENC_NAMESPACE,sizeof(SOAP_1_1_ENC_NAMESPACE)) != 0 && - strncmp(tmp->children->content,SOAP_1_2_ENC_NAMESPACE,sizeof(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"); + if (tmp) { + if (strncmp(tmp->children->content,SOAP_1_1_ENC_NAMESPACE,sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) { + binding->encodingStyle = SOAP_ENCODING_1_1; + } else if (strncmp(tmp->children->content,SOAP_1_2_ENC_NAMESPACE,sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) { + binding->encodingStyle = SOAP_ENCODING_1_2; + } else { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Unknown encodingStyle '%s'",tmp->children->content); + } } else { - binding->encodingStyle = estrdup(tmp->children->content); + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Unspecified encodingStyle"); } } } else if (node_is_equal_ex(trav, "header", wsdl_soap_namespace)) { @@ -404,14 +407,16 @@ static void wsdl_soap_binding_body(sdlCtx* ctx, xmlNodePtr node, char* wsdl_soap if (h->use == SOAP_ENCODED) { tmp = get_attribute(header->properties, "encodingStyle"); - if (tmp && - strncmp(tmp->children->content,SOAP_1_1_ENC_NAMESPACE,sizeof(SOAP_1_1_ENC_NAMESPACE)) != 0 && - strncmp(tmp->children->content,SOAP_1_2_ENC_NAMESPACE,sizeof(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"); + if (tmp) { + if (strncmp(tmp->children->content,SOAP_1_1_ENC_NAMESPACE,sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) { + h->encodingStyle = SOAP_ENCODING_1_1; + } else if (strncmp(tmp->children->content,SOAP_1_2_ENC_NAMESPACE,sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) { + h->encodingStyle = SOAP_ENCODING_1_2; + } else { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Unknown encodingStyle '%s'",tmp->children->content); + } } else { - h->encodingStyle = estrdup(tmp->children->content); + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Unspecified encodingStyle"); } } @@ -647,10 +652,11 @@ static sdlPtr load_wsdl(char *struri) tmp = get_attribute(soapBindingNode->properties, "transport"); if (tmp) { - if (strncmp(tmp->children->content, WSDL_HTTP_TRANSPORT, sizeof(WSDL_HTTP_TRANSPORT))) { + if (strncmp(tmp->children->content, WSDL_HTTP_TRANSPORT, sizeof(WSDL_HTTP_TRANSPORT)) == 0) { + soapBinding->transport = SOAP_TRANSPORT_HTTP; + } else { php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: PHP-SOAP doesn't support transport '%s'", tmp->children->content); } - soapBinding->transport = estrdup(tmp->children->content); } } tmpbinding->bindingAttributes = (void *)soapBinding; @@ -722,12 +728,8 @@ static sdlPtr load_wsdl(char *struri) } function = emalloc(sizeof(sdlFunction)); + memset(function, 0, sizeof(sdlFunction)); function->functionName = estrdup(op_name->children->content); - function->requestParameters = NULL; - function->responseParameters = NULL; - function->responseName = NULL; - function->requestName = NULL; - function->bindingAttributes = NULL; if (tmpbinding->bindingType == BINDING_SOAP) { sdlSoapBindingFunctionPtr soapFunctionBinding; @@ -824,9 +826,84 @@ static sdlPtr load_wsdl(char *struri) /* FIXME: */ } - fault = get_node_ex(operation->children, "fault", WSDL_NAMESPACE); - if (!fault) { - /* FIXME: */ + fault = portTypeOperation->children; + while (fault != NULL) { + if (node_is_equal_ex(fault, "fault", WSDL_NAMESPACE)) { + xmlAttrPtr message, name; + sdlFaultPtr f; + + name = get_attribute(fault->properties, "name"); + if (name == NULL) { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Missing name for <fault> of '%s'", op_name->children->content); + } + message = get_attribute(fault->properties, "message"); + if (message == NULL) { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Missing name for <output> of '%s'", op_name->children->content); + } + + f = emalloc(sizeof(sdlFault)); + memset(f, 0, sizeof(sdlFault)); + + f->name = estrdup(name->children->content); + f->details = wsdl_message(&ctx, message->children->content); + if (f->details == NULL || zend_hash_num_elements(f->details) != 1) { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: The fault message '%s' must have a single part", message->children->content); + } + + if (tmpbinding->bindingType == BINDING_SOAP) { + xmlNodePtr soap_fault = get_node_with_attribute_ex(operation->children, "fault", WSDL_NAMESPACE, "name", f->name, NULL); + if (soap_fault != NULL) { + xmlNodePtr trav = soap_fault->children; + while (trav != NULL) { + if (node_is_equal_ex(trav, "fault", wsdl_soap_namespace)) { + xmlAttrPtr tmp; + sdlSoapBindingFunctionFaultPtr binding; + + binding = f->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunctionFault)); + memset(f->bindingAttributes, 0, sizeof(sdlSoapBindingFunctionFault)); + + tmp = get_attribute(trav->properties, "use"); + if (tmp && !strncmp(tmp->children->content, "encoded", sizeof("encoded"))) { + binding->use = SOAP_ENCODED; + } else { + binding->use = SOAP_LITERAL; + } + + tmp = get_attribute(trav->properties, "namespace"); + if (tmp) { + binding->ns = estrdup(tmp->children->content); + } + + if (binding->use == SOAP_ENCODED) { + tmp = get_attribute(trav->properties, "encodingStyle"); + if (tmp) { + if (strncmp(tmp->children->content,SOAP_1_1_ENC_NAMESPACE,sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) { + binding->encodingStyle = SOAP_ENCODING_1_1; + } else if (strncmp(tmp->children->content,SOAP_1_2_ENC_NAMESPACE,sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) { + binding->encodingStyle = SOAP_ENCODING_1_2; + } else { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Unknown encodingStyle '%s'",tmp->children->content); + } + } else { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: Unspecified encodingStyle"); + } + } + } else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) { + php_error(E_ERROR,"SOAP-ERROR: Parsing WSDL: Unexpected WSDL element <%s>",trav->name); + } + trav = trav->next; + } + } + } + if (function->faults == NULL) { + function->faults = emalloc(sizeof(HashTable)); + zend_hash_init(function->faults, 0, NULL, delete_fault, 0); + } + if (zend_hash_add(function->faults, f->name, strlen(f->name)+1, (void**)&f, sizeof(sdlFaultPtr), NULL) != SUCCESS) { + php_error(E_ERROR, "SOAP-ERROR: Parsing WSDL: <fault> with name '%s' already defined in '%s'", f->name, op_name->children->content); + } + } + fault = fault->next; } function->binding = tmpbinding; @@ -877,7 +954,7 @@ static sdlPtr load_wsdl(char *struri) return ctx.sdl; } -#define WSDL_CACHE_VERSION 03 +#define WSDL_CACHE_VERSION 06 #define WSDL_CACHE_GET(ret,type,buf) memcpy(&ret,*buf,sizeof(type)); *buf += sizeof(type); #define WSDL_CACHE_GET_INT(ret,buf) ret = ((int)(*buf)[0])|((int)(*buf)[1]<<8)|((int)(*buf)[2]<<16)|((int)(*buf)[3]<<24); *buf += 4; @@ -1118,9 +1195,13 @@ static void sdl_deserialize_soap_body(sdlSoapBindingFunctionBodyPtr body, encode int i, n; WSDL_CACHE_GET_1(body->use, sdlEncodingUse, in); + if (body->use == SOAP_ENCODED) { + WSDL_CACHE_GET_1(body->encodingStyle, sdlRpcEncodingStyle, in); + } else { + body->encodingStyle = SOAP_ENCODING_DEFAULT; + } body->ns = sdl_deserialize_string(in); body->parts = sdl_deserialize_string(in); - body->encodingStyle = sdl_deserialize_string(in); WSDL_CACHE_GET_INT(i, in); if (i > 0) { body->headers = emalloc(sizeof(HashTable)); @@ -1129,9 +1210,13 @@ static void sdl_deserialize_soap_body(sdlSoapBindingFunctionBodyPtr body, encode sdlSoapBindingFunctionHeaderPtr tmp = emalloc(sizeof(sdlSoapBindingFunctionHeader)); sdl_deserialize_key(body->headers, tmp, in); WSDL_CACHE_GET_1(tmp->use, sdlEncodingUse, in); + if (tmp->use == SOAP_ENCODED) { + WSDL_CACHE_GET_1(tmp->encodingStyle, sdlRpcEncodingStyle, in); + } else { + tmp->encodingStyle = SOAP_ENCODING_DEFAULT; + } tmp->name = sdl_deserialize_string(in); tmp->ns = sdl_deserialize_string(in); - tmp->encodingStyle = sdl_deserialize_string(in); WSDL_CACHE_GET_INT(n, in); tmp->encode = encoders[n]; WSDL_CACHE_GET_INT(n, in); @@ -1315,7 +1400,7 @@ static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t) if (*in != 0) { sdlSoapBindingPtr soap_binding = binding->bindingAttributes = emalloc(sizeof(sdlSoapBinding)); WSDL_CACHE_GET_1(soap_binding->style,sdlEncodingStyle,&in); - soap_binding->transport = sdl_deserialize_string(&in); + WSDL_CACHE_GET_1(soap_binding->transport,sdlTransport,&in); } else { WSDL_CACHE_SKIP(1,&in); } @@ -1329,7 +1414,7 @@ static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t) zend_hash_init(&sdl->functions, num_func, NULL, delete_function, 0); functions = do_alloca(num_func*sizeof(sdlFunctionPtr)); for (i = 0; i < num_func; i++) { - int binding_num; + int binding_num, num_faults; sdlFunctionPtr func = emalloc(sizeof(sdlFunction)); sdl_deserialize_key(&sdl->functions, func, &in); func->functionName = sdl_deserialize_string(&in); @@ -1352,11 +1437,44 @@ static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t) sdl_deserialize_soap_body(&binding->output, encoders, types, &in); } else { WSDL_CACHE_SKIP(1, &in); + func->bindingAttributes = NULL; } } func->requestParameters = sdl_deserialize_parameters(encoders, types, &in); func->responseParameters = sdl_deserialize_parameters(encoders, types, &in); + + WSDL_CACHE_GET_INT(num_faults, &in); + if (num_faults > 0) { + int j; + + func->faults = emalloc(sizeof(HashTable)); + zend_hash_init(func->faults, num_faults, NULL, delete_fault, 0); + + for (j = 0; j < num_faults; j++) { + sdlFaultPtr fault = emalloc(sizeof(sdlFault)); + + sdl_deserialize_key(func->faults, fault, &in); + fault->name =sdl_deserialize_string(&in); + fault->details =sdl_deserialize_parameters(encoders, types, &in); + if (*in != 0) { + sdlSoapBindingFunctionFaultPtr binding = fault->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunctionFault)); + memset(binding, 0, sizeof(sdlSoapBindingFunctionFault)); + WSDL_CACHE_GET_1(binding->use,sdlEncodingUse,&in); + if (binding->use == SOAP_ENCODED) { + WSDL_CACHE_GET_1(binding->encodingStyle, sdlRpcEncodingStyle, &in); + } else { + binding->encodingStyle = SOAP_ENCODING_DEFAULT; + } + binding->ns = sdl_deserialize_string(&in); + } else { + WSDL_CACHE_SKIP(1, &in); + fault->bindingAttributes = NULL; + } + } + } else { + func->faults = NULL; + } functions[i] = func; } @@ -1655,9 +1773,11 @@ static void sdl_serialize_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTabl int i; WSDL_CACHE_PUT_1(body->use, out); + if (body->use == SOAP_ENCODED) { + WSDL_CACHE_PUT_1(body->encodingStyle, out); + } sdl_serialize_string(body->ns, out); sdl_serialize_string(body->parts, out); - sdl_serialize_string(body->encodingStyle, out); if (body->headers) { i = zend_hash_num_elements(body->headers); } else { @@ -1670,9 +1790,11 @@ static void sdl_serialize_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTabl while (zend_hash_get_current_data(body->headers, (void**)&tmp) == SUCCESS) { sdl_serialize_key(body->headers, out); WSDL_CACHE_PUT_1((*tmp)->use, out); + if ((*tmp)->use == SOAP_ENCODED) { + WSDL_CACHE_PUT_1((*tmp)->encodingStyle, out); + } sdl_serialize_string((*tmp)->name, out); sdl_serialize_string((*tmp)->ns, out); - sdl_serialize_string((*tmp)->encodingStyle, out); sdl_serialize_encoder_ref((*tmp)->encode, tmp_encoders, out); sdl_serialize_type_ref((*tmp)->element, tmp_types, out); zend_hash_move_forward(body->headers); @@ -1849,7 +1971,7 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s if ((*tmp)->bindingType == BINDING_SOAP && (*tmp)->bindingAttributes != NULL) { sdlSoapBindingPtr binding = (sdlSoapBindingPtr)(*tmp)->bindingAttributes; WSDL_CACHE_PUT_1(binding->style, out); - sdl_serialize_string(binding->transport, out); + WSDL_CACHE_PUT_1(binding->transport, out); } else { WSDL_CACHE_PUT_1(0,out); } @@ -1893,6 +2015,32 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s sdl_serialize_parameters((*tmp)->requestParameters, &tmp_encoders, &tmp_types, out); sdl_serialize_parameters((*tmp)->responseParameters, &tmp_encoders, &tmp_types, out); + if ((*tmp)->faults) { + sdlFaultPtr *fault; + + WSDL_CACHE_PUT_INT(zend_hash_num_elements((*tmp)->faults), out); + + zend_hash_internal_pointer_reset((*tmp)->faults); + while (zend_hash_get_current_data((*tmp)->faults, (void**)&fault) == SUCCESS) { + sdl_serialize_key((*tmp)->faults, out); + sdl_serialize_string((*fault)->name, out); + sdl_serialize_parameters((*fault)->details, &tmp_encoders, &tmp_types, out); + if ((*tmp)->binding->bindingType == BINDING_SOAP && (*fault)->bindingAttributes != NULL) { + sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)(*fault)->bindingAttributes; + WSDL_CACHE_PUT_1(binding->use, out); + if (binding->use == SOAP_ENCODED) { + WSDL_CACHE_PUT_1(binding->encodingStyle, out); + } + sdl_serialize_string(binding->ns, out); + } else { + WSDL_CACHE_PUT_1(0, out); + } + zend_hash_move_forward((*tmp)->faults); + } + } else { + WSDL_CACHE_PUT_INT(0, out); + } + zend_hash_add(&tmp_functions, (char*)tmp, sizeof(*tmp), (void**)&function_num, sizeof(function_num), NULL); function_num++; zend_hash_move_forward(&sdl->functions); @@ -1935,6 +2083,7 @@ sdlPtr get_sdl(char *uri TSRMLS_DC) char* old_error_code = SOAP_GLOBAL(error_code); SOAP_GLOBAL(error_code) = "WSDL"; + if (SOAP_GLOBAL(cache_enabled)) { char fn[MAXPATHLEN]; @@ -2028,10 +2177,9 @@ static void delete_binding(void *data) if (binding->bindingType == BINDING_SOAP) { sdlSoapBindingPtr soapBind = binding->bindingAttributes; - if (soapBind && soapBind->transport) { - efree(soapBind->transport); + if (soapBind) { + efree(soapBind); } - efree(soapBind); } efree(binding); } @@ -2044,9 +2192,6 @@ static void delete_sdl_soap_binding_function_body(sdlSoapBindingFunctionBody bod if (body.parts) { efree(body.parts); } - if (body.encodingStyle) { - efree(body.encodingStyle); - } if (body.headers) { zend_hash_destroy(body.headers); efree(body.headers); @@ -2074,6 +2219,10 @@ static void delete_function(void *data) zend_hash_destroy(function->responseParameters); efree(function->responseParameters); } + if (function->faults) { + zend_hash_destroy(function->faults); + efree(function->faults); + } if (function->bindingAttributes && function->binding && function->binding->bindingType == BINDING_SOAP) { @@ -2106,12 +2255,30 @@ static void delete_header(void *data) if (hdr->ns) { efree(hdr->ns); } - if (hdr->encodingStyle) { - efree(hdr->encodingStyle); - } efree(hdr); } +static void delete_fault(void *data) +{ + sdlFaultPtr fault = *((sdlFaultPtr*)data); + if (fault->name) { + efree(fault->name); + } + if (fault->details) { + zend_hash_destroy(fault->details); + efree(fault->details); + } + if (fault->bindingAttributes) { + sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes; + + if (binding->ns) { + efree(binding->ns); + } + efree(fault->bindingAttributes); + } + efree(fault); +} + 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 dc04e0aa3f..809af6fdb0 100644 --- a/ext/soap/php_sdl.h +++ b/ext/soap/php_sdl.h @@ -32,15 +32,25 @@ typedef enum _sdlBindingType { } sdlBindingType; typedef enum _sdlEncodingStyle { - SOAP_RPC = 1, + SOAP_RPC = 1, SOAP_DOCUMENT = 2 } sdlEncodingStyle; +typedef enum _sdlRpcEncodingStyle { + SOAP_ENCODING_DEFAULT = 0, + SOAP_ENCODING_1_1 = 1, + SOAP_ENCODING_1_2 = 2 +} sdlRpcEncodingStyle; + typedef enum _sdlEncodingUse { SOAP_ENCODED = 1, SOAP_LITERAL = 2 } sdlEncodingUse; +typedef enum _sdlTransport { + SOAP_TRANSPORT_HTTP = 1 +} sdlTransport; + struct _sdl { HashTable functions; /* array of sdlFunction */ HashTable *types; /* array of sdlTypesPtr */ @@ -76,25 +86,31 @@ struct _sdlBinding { /* Soap Binding Specfic stuff */ struct _sdlSoapBinding { - char *transport; sdlEncodingStyle style; + sdlTransport transport; /* not implemented yet */ }; typedef struct _sdlSoapBindingFunctionHeader { - char *name; - char *ns; - sdlEncodingUse use; - sdlTypePtr element; - encodePtr encode; - char *encodingStyle; /* not implemented yet */ + char *name; + char *ns; + sdlEncodingUse use; + sdlTypePtr element; + encodePtr encode; + sdlRpcEncodingStyle encodingStyle; /* not implemented yet */ } sdlSoapBindingFunctionHeader, *sdlSoapBindingFunctionHeaderPtr; +typedef struct _sdlSoapBindingFunctionFault { + char *ns; + sdlEncodingUse use; + sdlRpcEncodingStyle encodingStyle; /* not implemented yet */ +} sdlSoapBindingFunctionFault, *sdlSoapBindingFunctionFaultPtr; + struct _sdlSoapBindingFunctionBody { - char *ns; - sdlEncodingUse use; - char *parts; /* not implemented yet */ - char *encodingStyle; /* not implemented yet */ - HashTable *headers; /* array of sdlSoapBindingFunctionHeaderPtr */ + char *ns; + sdlEncodingUse use; + char *parts; /* not implemented yet */ + sdlRpcEncodingStyle encodingStyle; /* not implemented yet */ + HashTable *headers; /* array of sdlSoapBindingFunctionHeaderPtr */ }; struct _sdlSoapBindingFunction { @@ -185,6 +201,12 @@ struct _sdlParam { char *paramName; }; +typedef struct _sdlFault { + char *name; + HashTable *details; /* array of sdlParamPtr */ + void *bindingAttributes; /* sdlSoapBindingFunctionFaultPtr */ +} sdlFault, *sdlFaultPtr; + struct _sdlFunction { char *functionName; char *requestName; @@ -193,6 +215,7 @@ struct _sdlFunction { HashTable *responseParameters; /* array of sdlParamPtr (this should only be one) */ struct _sdlBinding *binding; void *bindingAttributes; /* sdlSoapBindingFunctionPtr */ + HashTable *faults; /* array of sdlFaultPtr */ }; typedef enum _sdlUse { diff --git a/ext/soap/soap.c b/ext/soap/soap.c index 4962adf2c3..677ff9c9b1 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -48,9 +48,9 @@ static void function_to_string(sdlFunctionPtr function, smart_str *buf); static void type_to_string(sdlTypePtr type, smart_str *buf, int level); static void clear_soap_fault(zval *obj TSRMLS_DC); -static void set_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail TSRMLS_DC); -static void soap_server_fault(char* code, char* string, char *actor, zval* details TSRMLS_DC); -static void soap_server_fault_ex(zval* fault TSRMLS_DC); +static void set_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail, char *name TSRMLS_DC); +static void soap_server_fault(char* code, char* string, char *actor, zval* details, char *name TSRMLS_DC); +static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault TSRMLS_DC); static sdlParamPtr get_param(sdlFunctionPtr function, char *param_name, int index, int); static sdlFunctionPtr get_function(sdlPtr sdl, const char *function_name); @@ -666,19 +666,20 @@ PHP_METHOD(soapheader,soapheader) /* SoapFault functions */ PHP_METHOD(soapfault,soapfault) { - char *fault_string = NULL, *fault_code = NULL, *fault_actor = NULL; - int fault_string_len, fault_code_len, fault_actor_len; + char *fault_string = NULL, *fault_code = NULL, *fault_actor = NULL, *name = NULL; + int fault_string_len, fault_code_len, fault_actor_len, name_len; zval *details = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s!z!", + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s!z!s", &fault_code, &fault_code_len, &fault_string, &fault_string_len, &fault_actor, &fault_actor_len, - &details) == FAILURE) { + &details, + &name, &name_len) == FAILURE) { php_error(E_ERROR, "Invalid arguments to SoapFault constructor"); } - set_soap_fault(this_ptr, fault_code, fault_string, fault_actor, details TSRMLS_CC); + set_soap_fault(this_ptr, fault_code, fault_string, fault_actor, details, name TSRMLS_CC); } #ifdef ZEND_ENGINE_2 @@ -1327,7 +1328,7 @@ PHP_METHOD(soapserver, handle) if (EG(exception) && Z_TYPE_P(EG(exception)) == IS_OBJECT && Z_OBJCE_P(EG(exception)) == soap_fault_class_entry) { - soap_server_fault_ex(EG(exception) TSRMLS_CC); + soap_server_fault_ex(function, EG(exception) TSRMLS_CC); } #endif zval_dtor(&constructor); @@ -1370,7 +1371,7 @@ PHP_METHOD(soapserver, handle) header = header->next; if (service->sdl && !h->function && !h->hdr) { if (h->mustUnderstand) { - soap_server_fault("MustUnderstand","Header not understood", NULL, NULL TSRMLS_CC); + soap_server_fault("MustUnderstand","Header not understood", NULL, NULL, NULL TSRMLS_CC); } else { continue; } @@ -1387,7 +1388,7 @@ PHP_METHOD(soapserver, handle) php_error(E_ERROR, "Function '%s' call failed", Z_STRVAL(function_name)); } } else if (h->mustUnderstand) { - soap_server_fault("MustUnderstand","Header not understood", NULL, NULL TSRMLS_CC); + soap_server_fault("MustUnderstand","Header not understood", NULL, NULL, NULL TSRMLS_CC); } efree(fn_name); } @@ -1412,7 +1413,7 @@ PHP_METHOD(soapserver, handle) if (EG(exception) && Z_TYPE_P(EG(exception)) == IS_OBJECT && Z_OBJCE_P(EG(exception)) == soap_fault_class_entry) { - soap_server_fault_ex(EG(exception) TSRMLS_CC); + soap_server_fault_ex(function, EG(exception) TSRMLS_CC); } #endif if (call_status == SUCCESS) { @@ -1420,7 +1421,7 @@ PHP_METHOD(soapserver, handle) if (Z_TYPE(retval) == IS_OBJECT && Z_OBJCE(retval) == soap_fault_class_entry) { - soap_server_fault_ex(&retval TSRMLS_CC); + soap_server_fault_ex(function, &retval TSRMLS_CC); } if (function && function->responseName) { @@ -1496,21 +1497,23 @@ PHP_METHOD(soapserver, handle) PHP_METHOD(soapserver, fault) { - char *code, *string, *actor=NULL; - int code_len, string_len, actor_len; + char *code, *string, *actor=NULL, *name=NULL; + int code_len, string_len, actor_len, name_len; zval* details = NULL; SOAP_SERVER_BEGIN_CODE(); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|sz", - &code, &code_len, &string, &string_len, &actor, &actor_len, &details) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|szs", + &code, &code_len, &string, &string_len, &actor, &actor_len, &details, + &name, &name_len) == FAILURE) { php_error(E_ERROR, "Invalid parameters passed to soapserver:fault"); } - soap_server_fault(code, string, actor, details TSRMLS_CC); + + soap_server_fault(code, string, actor, details, name TSRMLS_CC); SOAP_SERVER_END_CODE(); } -static void soap_server_fault_ex(zval* fault TSRMLS_DC) +static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault TSRMLS_DC) { int soap_version; xmlChar *buf, cont_len[30]; @@ -1519,7 +1522,7 @@ static void soap_server_fault_ex(zval* fault TSRMLS_DC) soap_version = SOAP_GLOBAL(soap_version); - doc_return = serialize_response_call(NULL, NULL, NULL, fault, NULL, soap_version TSRMLS_CC); + doc_return = serialize_response_call(function, NULL, NULL, fault, NULL, soap_version TSRMLS_CC); xmlDocDumpMemory(doc_return, &buf, &size); @@ -1542,14 +1545,15 @@ static void soap_server_fault_ex(zval* fault TSRMLS_DC) zend_bailout(); } -static void soap_server_fault(char* code, char* string, char *actor, zval* details TSRMLS_DC) +static void soap_server_fault(char* code, char* string, char *actor, zval* details, char* name TSRMLS_DC) { zval ret; INIT_ZVAL(ret); - set_soap_fault(&ret, code, string, actor, details TSRMLS_CC); - soap_server_fault_ex(&ret TSRMLS_CC); + set_soap_fault(&ret, code, string, actor, details, name TSRMLS_CC); + /* TODO: Which function */ + soap_server_fault_ex(NULL, &ret TSRMLS_CC); } static void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args) @@ -1617,7 +1621,7 @@ static void soap_error_handler(int error_num, const char *error_filename, const } php_end_ob_buffer(0, 0 TSRMLS_CC); - soap_server_fault(code, buffer, NULL, &outbuf TSRMLS_CC); + soap_server_fault(code, buffer, NULL, &outbuf, NULL TSRMLS_CC); } } } @@ -2107,7 +2111,7 @@ zval* add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *faul { zval *fault; MAKE_STD_ZVAL(fault); - set_soap_fault(fault, fault_code, fault_string, fault_actor, fault_detail TSRMLS_CC); + set_soap_fault(fault, fault_code, fault_string, fault_actor, fault_detail, NULL TSRMLS_CC); #ifdef ZEND_ENGINE_2 fault->refcount--; /*FIXME*/ #endif @@ -2115,7 +2119,7 @@ zval* add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *faul return fault; } -static void set_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail TSRMLS_DC) +static void set_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail, char *name TSRMLS_DC) { if (Z_TYPE_P(obj) != IS_OBJECT) { object_init_ex(obj, soap_fault_class_entry); @@ -2164,6 +2168,9 @@ static void set_soap_fault(zval *obj, char *fault_code, char *fault_string, char if (fault_detail != NULL) { add_property_zval(obj, "detail", fault_detail); } + if (name != NULL) { + add_property_string(obj, "_name", name, 1); + } } static void deserialize_parameters(xmlNodePtr params, sdlFunctionPtr function, int *num_params, zval ***parameters) @@ -2245,7 +2252,7 @@ static void deserialize_parameters(xmlNodePtr params, sdlFunctionPtr function, i } if (num_of_params > cur_param) { TSRMLS_FETCH(); - soap_server_fault("Client","Missing parameter", NULL, NULL TSRMLS_CC); + soap_server_fault("Client","Missing parameter", NULL, NULL, NULL TSRMLS_CC); } (*parameters) = tmp_parameters; (*num_params) = num_of_params; @@ -2301,7 +2308,7 @@ static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, c envelope_ns = SOAP_1_2_ENV_NAMESPACE; SOAP_GLOBAL(soap_version) = SOAP_1_2; } else { - soap_server_fault("VersionMismatch","Wrong Version", NULL, NULL TSRMLS_CC); + soap_server_fault("VersionMismatch","Wrong Version", NULL, NULL, NULL TSRMLS_CC); } } trav = trav->next; @@ -2393,18 +2400,18 @@ static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, c if (*version == SOAP_1_1) { attr = get_attribute_ex(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); + soap_server_fault("Client","Unknown Data Encoding Style", NULL, NULL, NULL TSRMLS_CC); } } else { attr = get_attribute_ex(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); + soap_server_fault("DataEncodingUnknown","Unknown Data Encoding Style", NULL, NULL, NULL TSRMLS_CC); } } function = find_function(sdl, func, function_name); if (sdl != NULL && function == NULL) { if (*version == SOAP_1_2) { - soap_server_fault("rpc:ProcedureNotPresent","Procedure not present", NULL, NULL TSRMLS_CC); + soap_server_fault("rpc:ProcedureNotPresent","Procedure not present", NULL, NULL, NULL TSRMLS_CC); } else { php_error(E_ERROR, "Procedure '%s' not present", func->name); } @@ -2438,7 +2445,7 @@ static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, c if (*version == SOAP_1_1) { 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); + soap_server_fault("Client","Unknown Data Encoding Style", NULL, NULL, NULL TSRMLS_CC); } attr = get_attribute_ex(hdr_func->properties,"actor",envelope_ns); if (attr != NULL) { @@ -2450,7 +2457,7 @@ static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, c } else if (*version == SOAP_1_2) { 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); + soap_server_fault("DataEncodingUnknown","Unknown Data Encoding Style", NULL, NULL, NULL TSRMLS_CC); } attr = get_attribute_ex(hdr_func->properties,"role",envelope_ns); if (attr != NULL) { @@ -2470,7 +2477,7 @@ static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, c strcmp(attr->children->content,"false") == 0) { mustUnderstand = 0; } else { - soap_server_fault("Client","mustUnderstand value is not boolean", NULL, NULL TSRMLS_CC); + soap_server_fault("Client","mustUnderstand value is not boolean", NULL, NULL, NULL TSRMLS_CC); } } h = emalloc(sizeof(soapHeader)); @@ -2664,15 +2671,42 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function xmlDocSetRootElement(doc, envelope); if (Z_TYPE_P(ret) == IS_OBJECT && - Z_OBJCE_P(ret) == soap_fault_class_entry) { + Z_OBJCE_P(ret) == soap_fault_class_entry) { + char *detail_name; + HashTable* prop; + zval **tmp; + sdlFaultPtr fault = NULL; + + prop = Z_OBJPROP_P(ret); body = xmlNewChild(envelope, ns, "Body", NULL); + param = xmlNewChild(body, ns, "Fault", NULL); + use = SOAP_LITERAL; - if (version == SOAP_1_1) { - HashTable* prop; - zval **tmp; + if (zend_hash_find(prop, "_name", sizeof("_name"), (void**)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_STRING) { + sdlFaultPtr *tmp_fault; + if (function && function->faults && + zend_hash_find(function->faults, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)+1, (void**)&tmp_fault) == SUCCESS) { + fault = *tmp_fault; + if (function->binding && + function->binding->bindingType == BINDING_SOAP && + fault->bindingAttributes) { + sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes; + use = fb->use; + } + } + } else if (function && function->faults && + zend_hash_num_elements(function->faults) == 1) { - prop = Z_OBJPROP_P(ret); - param = xmlNewChild(body, ns, "Fault", NULL); + fault = *(sdlFaultPtr*)function->faults->pListHead->pData; + if (function->binding && + function->binding->bindingType == BINDING_SOAP && + fault->bindingAttributes) { + sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes; + use = fb->use; + } + } + + if (version == SOAP_1_1) { if (zend_hash_find(prop, "faultcode", sizeof("faultcode"), (void**)&tmp) == SUCCESS) { int new_len; xmlNodePtr node = xmlNewNode(NULL, "faultcode"); @@ -2697,17 +2731,8 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function xmlNodeSetContentLen(node, str, new_len); efree(str); } - if (zend_hash_find(prop, "detail", sizeof("detail"), (void**)&tmp) == SUCCESS && - Z_TYPE_PP(tmp) != IS_NULL) { - /*FIXME: use = SOAP_ENCODED;*/ - serialize_zval(*tmp, NULL, "detail", use, param TSRMLS_CC); - } + detail_name = "detail"; } else { - HashTable* prop; - zval **tmp; - - prop = Z_OBJPROP_P(ret); - param = xmlNewChild(body, ns, "Fault", NULL); if (zend_hash_find(prop, "faultcode", sizeof("faultcode"), (void**)&tmp) == SUCCESS) { int new_len; xmlNodePtr node = xmlNewChild(param, ns, "Code", NULL); @@ -2724,10 +2749,51 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function xmlNodeSetContentLen(node, str, new_len); efree(str); } + detail_name = SOAP_1_2_ENV_NS_PREFIX":Detail"; + } + if (fault && fault->details && zend_hash_num_elements(fault->details) == 1) { + xmlNodePtr node; + zval *detail = NULL; + sdlParamPtr sparam; + xmlNodePtr x; + if (zend_hash_find(prop, "detail", sizeof("detail"), (void**)&tmp) == SUCCESS && Z_TYPE_PP(tmp) != IS_NULL) { - serialize_zval(*tmp, NULL, SOAP_1_2_ENV_NS_PREFIX":Detail", use, param TSRMLS_CC); + detail = *tmp; + } + node = xmlNewNode(NULL, detail_name); + xmlAddChild(param, node); + + sparam = *(sdlParamPtr*)fault->details->pListHead->pData; + x = serialize_parameter(sparam, detail, 1, NULL, use, node TSRMLS_CC); + + if (function && + function->binding && + function->binding->bindingType == BINDING_SOAP && + function->bindingAttributes) { + sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes; + if (fnb->style == SOAP_RPC) { + if (fault->bindingAttributes) { + sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes; + if (fb->ns) { + xmlNsPtr ns = encode_add_ns(x, fb->ns); + xmlSetNs(x, ns); + } + } + } else { + if (sparam->element) { + xmlNsPtr ns = encode_add_ns(x, sparam->element->namens); + xmlNodeSetName(x, sparam->element->name); + xmlSetNs(x, ns); + } + } + } + if (use == SOAP_ENCODED && version == SOAP_1_2) { + xmlSetNsProp(x, envelope->ns, "encodingStyle", SOAP_1_2_ENC_NAMESPACE); } + } else if (zend_hash_find(prop, "detail", sizeof("detail"), (void**)&tmp) == SUCCESS && + Z_TYPE_PP(tmp) != IS_NULL) { + serialize_zval(*tmp, NULL, detail_name, use, param TSRMLS_CC); } } else { @@ -2917,7 +2983,7 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function } } } - + if (function && function->requestParameters) { int n = zend_hash_num_elements(function->requestParameters); |