php-src/ext/soap/php_packet_soap.c

279 lines
8.3 KiB
C
Raw Normal View History

2004-01-29 09:27:06 +00:00
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2004 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
2004-01-29 11:51:11 +00:00
| Authors: Brad Lafountain <rodif_bl@yahoo.com> |
| Shane Caraveo <shane@caraveo.com> |
| Dmitry Stogov <dmitry@zend.com> |
2004-01-29 09:27:06 +00:00
+----------------------------------------------------------------------+
*/
/* $Id$ */
#include "php_soap.h"
/* 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)
{
2004-01-19 00:10:41 +00:00
char* envelope_ns = NULL;
xmlDocPtr response;
2004-01-09 14:16:30 +00:00
xmlNodePtr trav, env, head, body, resp, cur, fault;
int param_count = 0;
int old_error_reporting;
int soap_version;
ZVAL_NULL(return_value);
old_error_reporting = EG(error_reporting);
EG(error_reporting) &= ~(E_WARNING|E_NOTICE|E_USER_WARNING|E_USER_NOTICE);
/* Parse XML packet */
response = xmlParseMemory(buffer, buffer_size);
xmlCleanupParser();
EG(error_reporting) = old_error_reporting;
if (!response) {
2004-01-15 10:59:24 +00:00
add_soap_fault(this_ptr, "Client", "looks like we got no XML document", NULL, NULL TSRMLS_CC);
return FALSE;
}
if (xmlGetIntSubset(response) != NULL) {
2004-01-15 10:59:24 +00:00
add_soap_fault(this_ptr, "Client", "DTD are not supported by SOAP", NULL, NULL TSRMLS_CC);
return FALSE;
}
/* Get <Envelope> element */
env = NULL;
trav = response->children;
while (trav != NULL) {
if (trav->type == XML_ELEMENT_NODE) {
2004-01-15 10:59:24 +00:00
if (env == NULL && node_is_equal_ex(trav,"Envelope",SOAP_1_1_ENV_NAMESPACE)) {
2004-01-09 18:22:03 +00:00
env = trav;
2004-01-15 10:59:24 +00:00
envelope_ns = SOAP_1_1_ENV_NAMESPACE;
soap_version = SOAP_1_1;
2004-01-15 10:59:24 +00:00
} else if (env == NULL && node_is_equal_ex(trav,"Envelope",SOAP_1_2_ENV_NAMESPACE)) {
2004-01-09 18:22:03 +00:00
env = trav;
2004-01-15 10:59:24 +00:00
envelope_ns = SOAP_1_2_ENV_NAMESPACE;
soap_version = SOAP_1_2;
2004-01-09 18:22:03 +00:00
} else {
2004-01-15 10:59:24 +00:00
add_soap_fault(this_ptr, "Client", "looks like we got bad SOAP response\n", NULL, NULL TSRMLS_CC);
2004-01-09 14:16:30 +00:00
xmlFreeDoc(response);
return FALSE;
2004-01-09 18:22:03 +00:00
}
}
trav = trav->next;
}
if (env == NULL) {
2004-01-15 10:59:24 +00:00
add_soap_fault(this_ptr, "Client", "looks like we got XML without \"Envelope\" element\n", NULL, NULL TSRMLS_CC);
xmlFreeDoc(response);
return FALSE;
}
2004-01-09 14:16:30 +00:00
/* Get <Header> element */
head = NULL;
trav = env->children;
while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
2004-01-09 18:22:03 +00:00
trav = trav->next;
2004-01-09 14:16:30 +00:00
}
if (trav != NULL && node_is_equal_ex(trav,"Header",envelope_ns)) {
2004-01-09 18:22:03 +00:00
head = trav;
trav = trav->next;
2004-01-09 14:16:30 +00:00
}
/* Get <Body> element */
body = NULL;
while (trav != NULL) {
2004-01-09 14:16:30 +00:00
if (trav->type == XML_ELEMENT_NODE) {
2004-01-09 18:22:03 +00:00
if (body == NULL && node_is_equal_ex(trav,"Body",envelope_ns)) {
body = trav;
} else {
2004-01-15 10:59:24 +00:00
add_soap_fault(this_ptr, "Client", "looks like we got bad SOAP response\n", NULL, NULL TSRMLS_CC);
xmlFreeDoc(response);
return FALSE;
2004-01-09 18:22:03 +00:00
}
}
trav = trav->next;
}
if (body == NULL) {
2004-01-15 10:59:24 +00:00
add_soap_fault(this_ptr, "Client", "looks like we got \"Envelope\" without \"Body\" element\n", NULL, NULL TSRMLS_CC);
xmlFreeDoc(response);
return FALSE;
}
/* Check if <Body> contains <Fault> element */
fault = get_node_ex(body->children,"Fault",envelope_ns);
2004-01-09 18:22:03 +00:00
if (fault != NULL) {
char *faultcode = NULL, *faultstring = NULL, *faultactor = NULL;
zval *details = NULL;
xmlNodePtr tmp;
if (soap_version == SOAP_1_1) {
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) {
details = master_to_zval(NULL, tmp);
}
} else {
tmp = get_node(fault->children,"Code");
if (tmp != NULL && tmp->children != NULL) {
tmp = get_node(tmp->children,"Value");
if (tmp != NULL && tmp->children != NULL) {
faultcode = tmp->children->content;
}
}
tmp = get_node(fault->children,"Reason");
if (tmp != NULL && tmp->children != NULL) {
/* TODO: lang attribute */
tmp = get_node(tmp->children,"Text");
if (tmp != NULL && tmp->children != NULL) {
faultstring = tmp->children->content;
}
}
tmp = get_node(fault->children,"Detail");
if (tmp != NULL) {
details = master_to_zval(NULL, tmp);
}
}
add_soap_fault(this_ptr, faultcode, faultstring, faultactor, details TSRMLS_CC);
xmlFreeDoc(response);
return FALSE;
}
/* Parse content of <Body> element */
2004-01-13 15:58:01 +00:00
array_init(return_value);
resp = body->children;
2004-01-13 15:58:01 +00:00
while (resp != NULL && resp->type != XML_ELEMENT_NODE) {
resp = resp->next;
}
if (resp != NULL) {
if (fn != NULL && fn->binding && fn->binding->bindingType == BINDING_SOAP) {
/* Function has WSDL description */
sdlParamPtr *h_param, param = NULL;
xmlNodePtr val = NULL;
char *name, *ns = NULL;
zval* tmp;
sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes;
int res_count = zend_hash_num_elements(fn->responseParameters);
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 = ? */
}
/* 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");
}
2004-01-09 14:16:30 +00:00
if (val == NULL && res_count == 1) {
val = get_node(cur->children, "result");
}
}
}
if (!val) {
/* TODO: may be "nil" is not OK? */
MAKE_STD_ZVAL(tmp);
ZVAL_NULL(tmp);
/*
2004-01-15 10:59:24 +00:00
add_soap_fault(this_ptr, "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(NULL, val);
}
}
add_assoc_zval(return_value, param->paramName, tmp);
param_count++;
zend_hash_move_forward(fn->responseParameters);
}
2004-01-13 15:58:01 +00:00
} else {
/* Function hasn't WSDL description */
xmlNodePtr val;
2004-01-13 15:58:01 +00:00
val = resp->children;
while (val != NULL) {
2004-01-09 18:22:03 +00:00
while (val && val->type != XML_ELEMENT_NODE) {
val = val->next;
}
if (val != NULL) {
if (!node_is_equal_ex(val,"result",RPC_SOAP12_NAMESPACE)) {
zval *tmp;
tmp = master_to_zval(NULL, 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;
}
}
}
}
if (Z_TYPE_P(return_value) == IS_ARRAY) {
if (param_count == 0) {
2004-01-09 18:22:03 +00:00
zval_dtor(return_value);
ZVAL_NULL(return_value);
} else if (param_count == 1) {
2004-01-09 18:22:03 +00:00
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;
}