summaryrefslogtreecommitdiff
path: root/ext/soap/php_packet_soap.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/soap/php_packet_soap.c')
-rw-r--r--ext/soap/php_packet_soap.c288
1 files changed, 178 insertions, 110 deletions
diff --git a/ext/soap/php_packet_soap.c b/ext/soap/php_packet_soap.c
index 5411c31ee9..dc036285d6 100644
--- a/ext/soap/php_packet_soap.c
+++ b/ext/soap/php_packet_soap.c
@@ -1,141 +1,209 @@
#include "php_soap.h"
-int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctionPtr fn, char *fn_name, zval ***ret, int *num_params TSRMLS_DC)
+/* SOAP client calls this function to parse response from SOAP server */
+int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctionPtr fn, char *fn_name, zval *return_value TSRMLS_DC)
{
xmlDocPtr response;
- xmlNodePtr trav, trav2, env, body, resp, cur, fault;
- zval **tmp_ret;
+ xmlNodePtr trav, /*trav2,*/ env, body, resp, cur, fault;
+ int param_count = 0;
+ ZVAL_NULL(return_value);
+
+ /* Parse XML packet */
response = xmlParseMemory(buffer, buffer_size);
xmlCleanupParser();
-
if (!response) {
- php_error(E_ERROR, "looks like we got no XML document");
+ add_soap_fault(this_ptr, "SOAP-ENV:Client", "looks like we got no XML document", NULL, NULL TSRMLS_CC);
+ return FALSE;
}
- (*num_params) = 0;
-
+ /* Get <Envelope> element */
+ env = NULL;
trav = response->children;
- FOREACHNODE(trav,"Envelope",env)
- {
- trav2 = env->children;
- FOREACHNODE(trav2,"Body",body)
- {
- fault = get_node(body->children,"Fault");
- if(fault != NULL)
- {
- char *faultcode = NULL, *faultstring = NULL, *faultactor = NULL;
- zval *details = NULL;
- xmlNodePtr tmp;
-
- tmp = get_node(fault->children,"faultcode");
- if(tmp != NULL && tmp->children != NULL)
- faultcode = tmp->children->content;
-
- tmp = get_node(fault->children,"faultstring");
- if(tmp != NULL && tmp->children != NULL)
- faultstring = tmp->children->content;
-
- tmp = get_node(fault->children,"faultactor");
- if(tmp != NULL && tmp->children != NULL)
- faultactor = tmp->children->content;
-
- tmp = get_node(fault->children,"detail");
- if(tmp != NULL)
- {
- encodePtr enc;
- enc = get_conversion(UNKNOWN_TYPE);
- details = enc->to_zval(enc->details, tmp);
- }
+ while (trav != NULL) {
+ if (trav->type == XML_ELEMENT_NODE &&
+ node_is_equal_ex(trav,"Envelope","http://schemas.xmlsoap.org/soap/envelope/")) {
+ if (env != NULL) {
+ add_soap_fault(this_ptr, "SOAP-ENV:Client", "looks like we got XML with several \"Envelope\" elements\n", NULL, NULL TSRMLS_CC);
+ xmlFreeDoc(response);
+ return FALSE;
+ }
+ env = trav;
+ }
+ trav = trav->next;
+ }
+ if (env == NULL) {
+ add_soap_fault(this_ptr, "SOAP-ENV:Client", "looks like we got XML without \"Envelope\" element\n", NULL, NULL TSRMLS_CC);
+ xmlFreeDoc(response);
+ return FALSE;
+ }
- add_soap_fault(this_ptr, faultcode, faultstring, faultactor, details TSRMLS_CC);
- }
- else
- {
- resp = body->children;
- if(fn != NULL)
- {
- sdlParamPtr *h_param, param = NULL;
- xmlNodePtr val = NULL;
- encodePtr enc;
- char *name, *ns = NULL;
+ /* Get <Body> element */
+ body = NULL;
+ trav = env->children;
+ while (trav != NULL) {
+ if (trav->type == XML_ELEMENT_NODE &&
+ node_is_equal_ex(trav,"Body","http://schemas.xmlsoap.org/soap/envelope/")) {
+ if (body != NULL) {
+ add_soap_fault(this_ptr, "SOAP-ENV:Client", "looks like we got \"Envelope\" with several \"Body\" elements\n", NULL, NULL TSRMLS_CC);
+ xmlFreeDoc(response);
+ return FALSE;
+ }
+ body = trav;
+ }
+ trav = trav->next;
+ }
+ if (body == NULL) {
+ add_soap_fault(this_ptr, "SOAP-ENV:Client", "looks like we got \"Envelope\" without \"Body\" element\n", NULL, NULL TSRMLS_CC);
+ xmlFreeDoc(response);
+ return FALSE;
+ }
- if(fn->bindingType == BINDING_SOAP)
- {
- sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes;
+ /* Check if <Body> contains <Fault> element */
+ fault = get_node_ex(body->children,"Fault","http://schemas.xmlsoap.org/soap/envelope/");
+ if(fault != NULL) {
+ char *faultcode = NULL, *faultstring = NULL, *faultactor = NULL;
+ zval *details = NULL;
+ xmlNodePtr tmp;
- zend_hash_internal_pointer_reset(fn->responseParameters);
- if(zend_hash_get_current_data(fn->responseParameters, (void **)&h_param) != SUCCESS)
- php_error(E_ERROR, "Can't find response parameter \"%s\"", param->paramName);
+ tmp = get_node(fault->children,"faultcode");
+ if (tmp != NULL && tmp->children != NULL) {
+ faultcode = tmp->children->content;
+ }
- param = (*h_param);
- if(fnb->style == SOAP_DOCUMENT)
- {
- name = (*h_param)->encode->details.type_str;
- ns = (*h_param)->encode->details.ns;
- }
- else
- {
- name = fn->responseName;
- /* ns = ? */
- }
+ tmp = get_node(fault->children,"faultstring");
+ if (tmp != NULL && tmp->children != NULL) {
+ faultstring = tmp->children->content;
+ }
- cur = get_node_ex(resp, name, ns);
- /* TODO: produce warning invalid ns */
- if(!cur)
- cur = get_node(resp, name);
-
- if(!cur)
- php_error(E_ERROR, "Can't find response data");
+ tmp = get_node(fault->children,"faultactor");
+ if (tmp != NULL && tmp->children != NULL) {
+ faultactor = tmp->children->content;
+ }
+ tmp = get_node(fault->children,"detail");
+ if (tmp != NULL) {
+ encodePtr enc;
+ enc = get_conversion(UNKNOWN_TYPE);
+ details = enc->to_zval(enc->details, tmp);
+ }
- if(fnb->style == SOAP_DOCUMENT)
- val = cur;
- else
- val = get_node(cur->children, param->paramName);
+ add_soap_fault(this_ptr, faultcode, faultstring, faultactor, details TSRMLS_CC);
+ xmlFreeDoc(response);
+ return FALSE;
+ }
- if(!val)
- php_error(E_ERROR, "Can't find response data");
+ /* Parse content of <Body> element */
+ resp = body->children;
+ if (fn != NULL) {
+ /* Function has WSDL description */
+ sdlParamPtr *h_param, param = NULL;
+ xmlNodePtr val = NULL;
+ char *name, *ns = NULL;
+ zval* tmp;
+
+ if (fn->bindingType == BINDING_SOAP) {
+ sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes;
+ int res_count = zend_hash_num_elements(fn->responseParameters);
+
+ array_init(return_value);
+ zend_hash_internal_pointer_reset(fn->responseParameters);
+ while (zend_hash_get_current_data(fn->responseParameters, (void **)&h_param) == SUCCESS) {
+ param = (*h_param);
+ if (fnb->style == SOAP_DOCUMENT) {
+ name = param->encode->details.type_str;
+ ns = param->encode->details.ns;
+ } else {
+ name = fn->responseName;
+ /* ns = ? */
+ }
- tmp_ret = emalloc(sizeof(zval **));
- if(param != NULL)
- enc = param->encode;
- else
- enc = get_conversion(UNKNOWN_TYPE);
+ /* Get value of parameter */
+ cur = get_node_ex(resp, name, ns);
+ if (!cur) {
+ cur = get_node(resp, name);
+ /* TODO: produce warning invalid ns */
+ }
+ if (cur) {
+ if (fnb->style == SOAP_DOCUMENT) {
+ val = cur;
+ } else {
+ val = get_node(cur->children, param->paramName);
+ if (val == NULL && res_count == 1) {
+ val = get_node(cur->children, "return");
+ }
+ }
+ }
- tmp_ret[0] = master_to_zval(enc, val);
- (*ret) = tmp_ret;
- (*num_params) = 1;
+ if (!val) {
+ /* TODO: may be "nil" is not OK? */
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_NULL(tmp);
+/*
+ add_soap_fault(this_ptr, "SOAP-ENV:Client", "Can't find response data", NULL, NULL TSRMLS_CC);
+ xmlFreeDoc(response);
+ return FALSE;
+*/
+ } else {
+ /* Decoding value of parameter */
+ if (param != NULL) {
+ tmp = master_to_zval(param->encode, val);
+ } else {
+ tmp = master_to_zval(get_conversion(UNKNOWN_TYPE), val);
}
}
- else
- {
- cur = resp;
- while(cur && cur->type != XML_ELEMENT_NODE)
- cur = cur->next;
- if(cur != NULL)
- {
- xmlNodePtr val;
- val = cur->children;
- while(val && val->type != XML_ELEMENT_NODE)
- val = val->next;
-
- if(val != NULL)
- {
- encodePtr enc;
- enc = get_conversion(UNKNOWN_TYPE);
- tmp_ret = emalloc(sizeof(zval **));
- tmp_ret[0] = master_to_zval(enc, val);
- (*ret) = tmp_ret;
- (*num_params) = 1;
- }
+ add_assoc_zval(return_value, param->paramName, tmp);
+ /*add_assoc_zval(return_value, (char*)val->name, tmp);*/
+
+ param_count++;
+
+ zend_hash_move_forward(fn->responseParameters);
+ }
+ }
+ } else {
+ /* Function hasn't WSDL description */
+ cur = resp;
+ array_init(return_value);
+ while(cur && cur->type != XML_ELEMENT_NODE) {
+ cur = cur->next;
+ }
+ if (cur != NULL) {
+ xmlNodePtr val;
+ val = cur->children;
+ while (val != NULL) {
+ while(val && val->type != XML_ELEMENT_NODE) {
+ val = val->next;
+ }
+ if (val != NULL) {
+ encodePtr enc;
+ zval *tmp;
+ enc = get_conversion(UNKNOWN_TYPE);
+ tmp = master_to_zval(enc, val);
+ if (val->name) {
+ add_assoc_zval(return_value, (char*)val->name, tmp);
+ } else {
+ add_next_index_zval(return_value, tmp);
}
+ ++param_count;
+ val = val->next;
}
}
}
- ENDFOREACH(trav2);
}
- ENDFOREACH(trav);
+
+ if (Z_TYPE_P(return_value) == IS_ARRAY) {
+ if (param_count == 0) {
+ zval_dtor(return_value);
+ ZVAL_NULL(return_value);
+ } else if (param_count == 1) {
+ zval *tmp = *(zval**)Z_ARRVAL_P(return_value)->pListHead->pData;
+ tmp->refcount++;
+ zval_dtor(return_value);
+ *return_value = *tmp;
+ FREE_ZVAL(tmp);
+ }
+ }
+
xmlFreeDoc(response);
return TRUE;
}