Annotation of embedaddon/php/ext/soap/php_packet_soap.c, revision 1.1.1.2
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
5: | Copyright (c) 1997-2012 The PHP Group |
6: +----------------------------------------------------------------------+
7: | This source file is subject to version 3.01 of the PHP license, |
8: | that is bundled with this package in the file LICENSE, and is |
9: | available through the world-wide-web at the following url: |
10: | http://www.php.net/license/3_01.txt |
11: | If you did not receive a copy of the PHP license and are unable to |
12: | obtain it through the world-wide-web, please send a note to |
13: | license@php.net so we can mail you a copy immediately. |
14: +----------------------------------------------------------------------+
15: | Authors: Brad Lafountain <rodif_bl@yahoo.com> |
16: | Shane Caraveo <shane@caraveo.com> |
17: | Dmitry Stogov <dmitry@zend.com> |
18: +----------------------------------------------------------------------+
19: */
1.1.1.2 ! misho 20: /* $Id$ */
1.1 misho 21:
22: #include "php_soap.h"
23:
24: /* SOAP client calls this function to parse response from SOAP server */
25: int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctionPtr fn, char *fn_name, zval *return_value, zval *soap_headers TSRMLS_DC)
26: {
27: char* envelope_ns = NULL;
28: xmlDocPtr response;
29: xmlNodePtr trav, env, head, body, resp, cur, fault;
30: xmlAttrPtr attr;
31: int param_count = 0;
32: int soap_version = SOAP_1_1;
33: HashTable *hdrs = NULL;
34:
35: ZVAL_NULL(return_value);
36:
37: /* Response for one-way opearation */
38: if (buffer_size == 0) {
39: return TRUE;
40: }
41:
42: /* Parse XML packet */
43: response = soap_xmlParseMemory(buffer, buffer_size);
44:
45: if (!response) {
46: add_soap_fault(this_ptr, "Client", "looks like we got no XML document", NULL, NULL TSRMLS_CC);
47: return FALSE;
48: }
49: if (xmlGetIntSubset(response) != NULL) {
50: add_soap_fault(this_ptr, "Client", "DTD are not supported by SOAP", NULL, NULL TSRMLS_CC);
51: xmlFreeDoc(response);
52: return FALSE;
53: }
54:
55: /* Get <Envelope> element */
56: env = NULL;
57: trav = response->children;
58: while (trav != NULL) {
59: if (trav->type == XML_ELEMENT_NODE) {
60: if (env == NULL && node_is_equal_ex(trav,"Envelope",SOAP_1_1_ENV_NAMESPACE)) {
61: env = trav;
62: envelope_ns = SOAP_1_1_ENV_NAMESPACE;
63: soap_version = SOAP_1_1;
64: } else if (env == NULL && node_is_equal_ex(trav,"Envelope",SOAP_1_2_ENV_NAMESPACE)) {
65: env = trav;
66: envelope_ns = SOAP_1_2_ENV_NAMESPACE;
67: soap_version = SOAP_1_2;
68: } else {
69: add_soap_fault(this_ptr, "VersionMismatch", "Wrong Version", NULL, NULL TSRMLS_CC);
70: xmlFreeDoc(response);
71: return FALSE;
72: }
73: }
74: trav = trav->next;
75: }
76: if (env == NULL) {
77: add_soap_fault(this_ptr, "Client", "looks like we got XML without \"Envelope\" element", NULL, NULL TSRMLS_CC);
78: xmlFreeDoc(response);
79: return FALSE;
80: }
81:
82: attr = env->properties;
83: while (attr != NULL) {
84: if (attr->ns == NULL) {
85: add_soap_fault(this_ptr, "Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL TSRMLS_CC);
86: xmlFreeDoc(response);
87: return FALSE;
88: } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
89: if (soap_version == SOAP_1_2) {
90: add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL TSRMLS_CC);
91: xmlFreeDoc(response);
92: return FALSE;
93: } else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
94: add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL TSRMLS_CC);
95: xmlFreeDoc(response);
96: return FALSE;
97: }
98: }
99: attr = attr->next;
100: }
101:
102: /* Get <Header> element */
103: head = NULL;
104: trav = env->children;
105: while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
106: trav = trav->next;
107: }
108: if (trav != NULL && node_is_equal_ex(trav,"Header",envelope_ns)) {
109: head = trav;
110: trav = trav->next;
111: }
112:
113: /* Get <Body> element */
114: body = NULL;
115: while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
116: trav = trav->next;
117: }
118: if (trav != NULL && node_is_equal_ex(trav,"Body",envelope_ns)) {
119: body = trav;
120: trav = trav->next;
121: }
122: while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
123: trav = trav->next;
124: }
125: if (body == NULL) {
126: add_soap_fault(this_ptr, "Client", "Body must be present in a SOAP envelope", NULL, NULL TSRMLS_CC);
127: xmlFreeDoc(response);
128: return FALSE;
129: }
130: attr = body->properties;
131: while (attr != NULL) {
132: if (attr->ns == NULL) {
133: if (soap_version == SOAP_1_2) {
134: add_soap_fault(this_ptr, "Client", "A SOAP Body element cannot have non Namespace qualified attributes", NULL, NULL TSRMLS_CC);
135: xmlFreeDoc(response);
136: return FALSE;
137: }
138: } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
139: if (soap_version == SOAP_1_2) {
140: add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Body", NULL, NULL TSRMLS_CC);
141: xmlFreeDoc(response);
142: return FALSE;
143: } else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
144: add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL TSRMLS_CC);
145: xmlFreeDoc(response);
146: return FALSE;
147: }
148: }
149: attr = attr->next;
150: }
151: if (trav != NULL && soap_version == SOAP_1_2) {
152: add_soap_fault(this_ptr, "Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL TSRMLS_CC);
153: xmlFreeDoc(response);
154: return FALSE;
155: }
156:
157: if (head != NULL) {
158: attr = head->properties;
159: while (attr != NULL) {
160: if (attr->ns == NULL) {
161: add_soap_fault(this_ptr, "Client", "A SOAP Header element cannot have non Namespace qualified attributes", NULL, NULL TSRMLS_CC);
162: xmlFreeDoc(response);
163: return FALSE;
164: } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
165: if (soap_version == SOAP_1_2) {
166: add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Header", NULL, NULL TSRMLS_CC);
167: xmlFreeDoc(response);
168: return FALSE;
169: } else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
170: add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL TSRMLS_CC);
171: xmlFreeDoc(response);
172: return FALSE;
173: }
174: }
175: attr = attr->next;
176: }
177: }
178:
179: /* Check if <Body> contains <Fault> element */
180: fault = get_node_ex(body->children,"Fault",envelope_ns);
181: if (fault != NULL) {
182: char *faultcode = NULL, *faultstring = NULL, *faultactor = NULL;
183: zval *details = NULL;
184: xmlNodePtr tmp;
185:
186: if (soap_version == SOAP_1_1) {
187: tmp = get_node(fault->children, "faultcode");
188: if (tmp != NULL && tmp->children != NULL) {
189: faultcode = (char*)tmp->children->content;
190: }
191:
192: tmp = get_node(fault->children, "faultstring");
193: if (tmp != NULL && tmp->children != NULL) {
1.1.1.2 ! misho 194: zval *zv = master_to_zval(get_conversion(IS_STRING), tmp TSRMLS_CC);
1.1 misho 195: faultstring = Z_STRVAL_P(zv);
196: FREE_ZVAL(zv);
197: }
198:
199: tmp = get_node(fault->children, "faultactor");
200: if (tmp != NULL && tmp->children != NULL) {
1.1.1.2 ! misho 201: zval *zv = master_to_zval(get_conversion(IS_STRING), tmp TSRMLS_CC);
1.1 misho 202: faultactor = Z_STRVAL_P(zv);
203: FREE_ZVAL(zv);
204: }
205:
206: tmp = get_node(fault->children, "detail");
207: if (tmp != NULL) {
1.1.1.2 ! misho 208: details = master_to_zval(NULL, tmp TSRMLS_CC);
1.1 misho 209: }
210: } else {
211: tmp = get_node(fault->children, "Code");
212: if (tmp != NULL && tmp->children != NULL) {
213: tmp = get_node(tmp->children, "Value");
214: if (tmp != NULL && tmp->children != NULL) {
215: faultcode = (char*)tmp->children->content;
216: }
217: }
218:
219: tmp = get_node(fault->children,"Reason");
220: if (tmp != NULL && tmp->children != NULL) {
221: /* TODO: lang attribute */
222: tmp = get_node(tmp->children,"Text");
223: if (tmp != NULL && tmp->children != NULL) {
1.1.1.2 ! misho 224: zval *zv = master_to_zval(get_conversion(IS_STRING), tmp TSRMLS_CC);
1.1 misho 225: faultstring = Z_STRVAL_P(zv);
226: FREE_ZVAL(zv);
227: }
228: }
229:
230: tmp = get_node(fault->children,"Detail");
231: if (tmp != NULL) {
1.1.1.2 ! misho 232: details = master_to_zval(NULL, tmp TSRMLS_CC);
1.1 misho 233: }
234: }
235: add_soap_fault(this_ptr, faultcode, faultstring, faultactor, details TSRMLS_CC);
236: if (faultstring) {
237: efree(faultstring);
238: }
239: if (faultactor) {
240: efree(faultactor);
241: }
242: if (details) {
243: Z_DELREF_P(details);
244: }
245: xmlFreeDoc(response);
246: return FALSE;
247: }
248:
249: /* Parse content of <Body> element */
250: array_init(return_value);
251: resp = body->children;
252: while (resp != NULL && resp->type != XML_ELEMENT_NODE) {
253: resp = resp->next;
254: }
255: if (resp != NULL) {
256: if (fn != NULL && fn->binding && fn->binding->bindingType == BINDING_SOAP) {
257: /* Function has WSDL description */
258: sdlParamPtr *h_param, param = NULL;
259: xmlNodePtr val = NULL;
260: char *name, *ns = NULL;
261: zval* tmp;
262: sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes;
263: int res_count;
264:
265: hdrs = fnb->output.headers;
266:
267: if (fn->responseParameters) {
268: res_count = zend_hash_num_elements(fn->responseParameters);
269: zend_hash_internal_pointer_reset(fn->responseParameters);
270: while (zend_hash_get_current_data(fn->responseParameters, (void **)&h_param) == SUCCESS) {
271: param = (*h_param);
272: if (fnb->style == SOAP_DOCUMENT) {
273: if (param->element) {
274: name = param->element->name;
275: ns = param->element->namens;
276: /*
277: name = param->encode->details.type_str;
278: ns = param->encode->details.ns;
279: */
280: } else {
281: name = param->paramName;
282: }
283: } else {
284: name = fn->responseName;
285: /* ns = ? */
286: }
287:
288: /* Get value of parameter */
289: cur = get_node_ex(resp, name, ns);
290: if (!cur) {
291: cur = get_node(resp, name);
292: /* TODO: produce warning invalid ns */
293: }
294: if (!cur && fnb->style == SOAP_RPC) {
295: cur = resp;
296: }
297: if (cur) {
298: if (fnb->style == SOAP_DOCUMENT) {
299: val = cur;
300: } else {
301: val = get_node(cur->children, param->paramName);
302: if (res_count == 1) {
303: if (val == NULL) {
304: val = get_node(cur->children, "return");
305: }
306: if (val == NULL) {
307: val = get_node(cur->children, "result");
308: }
309: if (val == NULL && cur->children && cur->children->next == NULL) {
310: val = cur->children;
311: }
312: }
313: }
314: }
315:
316: if (!val) {
317: /* TODO: may be "nil" is not OK? */
318: MAKE_STD_ZVAL(tmp);
319: ZVAL_NULL(tmp);
320: /*
321: add_soap_fault(this_ptr, "Client", "Can't find response data", NULL, NULL TSRMLS_CC);
322: xmlFreeDoc(response);
323: return FALSE;
324: */
325: } else {
326: /* Decoding value of parameter */
327: if (param != NULL) {
1.1.1.2 ! misho 328: tmp = master_to_zval(param->encode, val TSRMLS_CC);
1.1 misho 329: } else {
1.1.1.2 ! misho 330: tmp = master_to_zval(NULL, val TSRMLS_CC);
1.1 misho 331: }
332: }
333: add_assoc_zval(return_value, param->paramName, tmp);
334:
335: param_count++;
336:
337: zend_hash_move_forward(fn->responseParameters);
338: }
339: }
340: } else {
341: /* Function has no WSDL description */
342: xmlNodePtr val;
343: val = resp->children;
344: while (val != NULL) {
345: while (val && val->type != XML_ELEMENT_NODE) {
346: val = val->next;
347: }
348: if (val != NULL) {
349: if (!node_is_equal_ex(val,"result",RPC_SOAP12_NAMESPACE)) {
350: zval *tmp;
351: zval **arr;
352:
1.1.1.2 ! misho 353: tmp = master_to_zval(NULL, val TSRMLS_CC);
1.1 misho 354: if (val->name) {
355: if (zend_hash_find(Z_ARRVAL_P(return_value), (char*)val->name, strlen((char*)val->name)+1, (void**)&arr) == SUCCESS) {
356: add_next_index_zval(*arr, tmp);
357: } else if (val->next && get_node(val->next, (char*)val->name)) {
358: zval *arr;
359:
360: MAKE_STD_ZVAL(arr);
361: array_init(arr);
362: add_next_index_zval(arr, tmp);
363: add_assoc_zval(return_value, (char*)val->name, arr);
364: } else {
365: add_assoc_zval(return_value, (char*)val->name, tmp);
366: }
367: } else {
368: add_next_index_zval(return_value, tmp);
369: }
370: ++param_count;
371: }
372: val = val->next;
373: }
374: }
375: }
376: }
377:
378: if (Z_TYPE_P(return_value) == IS_ARRAY) {
379: if (param_count == 0) {
380: zval_dtor(return_value);
381: ZVAL_NULL(return_value);
382: } else if (param_count == 1) {
383: zval *tmp;
384:
385: zend_hash_internal_pointer_reset(Z_ARRVAL_P(return_value));
386: zend_hash_get_current_data(Z_ARRVAL_P(return_value), (void**)&tmp);
387: tmp = *(zval**)tmp;
388: Z_ADDREF_P(tmp);
389: zval_dtor(return_value);
390: *return_value = *tmp;
391: FREE_ZVAL(tmp);
392: }
393: }
394:
395: if (soap_headers && head) {
396: trav = head->children;
397: while (trav != NULL) {
398: if (trav->type == XML_ELEMENT_NODE) {
399: encodePtr enc = NULL;
400: zval* val;
401:
402: if (hdrs) {
403: smart_str key = {0};
404: sdlSoapBindingFunctionHeaderPtr *hdr;
405:
406: if (trav->ns) {
407: smart_str_appends(&key, (char*)trav->ns->href);
408: smart_str_appendc(&key,':');
409: }
410: smart_str_appends(&key, (char*)trav->name);
411: smart_str_0(&key);
412: if (zend_hash_find(hdrs, key.c, key.len+1, (void**)&hdr) == SUCCESS) {
413: enc = (*hdr)->encode;
414: }
415: smart_str_free(&key);
416: }
1.1.1.2 ! misho 417: val = master_to_zval(enc, trav TSRMLS_CC);
1.1 misho 418: add_assoc_zval(soap_headers, (char*)trav->name, val);
419: }
420: trav = trav->next;
421: }
422: }
423:
424: xmlFreeDoc(response);
425: return TRUE;
426: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>