summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@php.net>2004-02-19 08:21:13 +0000
committerDmitry Stogov <dmitry@php.net>2004-02-19 08:21:13 +0000
commit15ccb3be8d6f4497502050565bbf84b87f109fd8 (patch)
treeaddef32fe38bb096e3a5a5bbe3625a6b971a7b51
parent0e692f950664ece1665700a565f4fceec1ecc2a5 (diff)
downloadphp-git-15ccb3be8d6f4497502050565bbf84b87f109fd8.tar.gz
Support for SOAP Fault encoding according to WSDL <fault> and <soap:fault>
-rw-r--r--ext/soap/TODO3
-rw-r--r--ext/soap/php_sdl.c249
-rw-r--r--ext/soap/php_sdl.h49
-rw-r--r--ext/soap/soap.c170
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);