Annotation of embedaddon/php/ext/soap/php_packet_soap.c, revision 1.1.1.1
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: */
20: /* $Id: php_packet_soap.c 321634 2012-01-01 13:15:04Z felipe $ */
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) {
194: zval *zv = master_to_zval(get_conversion(IS_STRING), tmp);
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) {
201: zval *zv = master_to_zval(get_conversion(IS_STRING), tmp);
202: faultactor = Z_STRVAL_P(zv);
203: FREE_ZVAL(zv);
204: }
205:
206: tmp = get_node(fault->children, "detail");
207: if (tmp != NULL) {
208: details = master_to_zval(NULL, tmp);
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) {
224: zval *zv = master_to_zval(get_conversion(IS_STRING), tmp);
225: faultstring = Z_STRVAL_P(zv);
226: FREE_ZVAL(zv);
227: }
228: }
229:
230: tmp = get_node(fault->children,"Detail");
231: if (tmp != NULL) {
232: details = master_to_zval(NULL, tmp);
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: #ifdef ZEND_ENGINE_2
243: if (details) {
244: Z_DELREF_P(details);
245: }
246: #endif
247: xmlFreeDoc(response);
248: return FALSE;
249: }
250:
251: /* Parse content of <Body> element */
252: array_init(return_value);
253: resp = body->children;
254: while (resp != NULL && resp->type != XML_ELEMENT_NODE) {
255: resp = resp->next;
256: }
257: if (resp != NULL) {
258: if (fn != NULL && fn->binding && fn->binding->bindingType == BINDING_SOAP) {
259: /* Function has WSDL description */
260: sdlParamPtr *h_param, param = NULL;
261: xmlNodePtr val = NULL;
262: char *name, *ns = NULL;
263: zval* tmp;
264: sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes;
265: int res_count;
266:
267: hdrs = fnb->output.headers;
268:
269: if (fn->responseParameters) {
270: res_count = zend_hash_num_elements(fn->responseParameters);
271: zend_hash_internal_pointer_reset(fn->responseParameters);
272: while (zend_hash_get_current_data(fn->responseParameters, (void **)&h_param) == SUCCESS) {
273: param = (*h_param);
274: if (fnb->style == SOAP_DOCUMENT) {
275: if (param->element) {
276: name = param->element->name;
277: ns = param->element->namens;
278: /*
279: name = param->encode->details.type_str;
280: ns = param->encode->details.ns;
281: */
282: } else {
283: name = param->paramName;
284: }
285: } else {
286: name = fn->responseName;
287: /* ns = ? */
288: }
289:
290: /* Get value of parameter */
291: cur = get_node_ex(resp, name, ns);
292: if (!cur) {
293: cur = get_node(resp, name);
294: /* TODO: produce warning invalid ns */
295: }
296: if (!cur && fnb->style == SOAP_RPC) {
297: cur = resp;
298: }
299: if (cur) {
300: if (fnb->style == SOAP_DOCUMENT) {
301: val = cur;
302: } else {
303: val = get_node(cur->children, param->paramName);
304: if (res_count == 1) {
305: if (val == NULL) {
306: val = get_node(cur->children, "return");
307: }
308: if (val == NULL) {
309: val = get_node(cur->children, "result");
310: }
311: if (val == NULL && cur->children && cur->children->next == NULL) {
312: val = cur->children;
313: }
314: }
315: }
316: }
317:
318: if (!val) {
319: /* TODO: may be "nil" is not OK? */
320: MAKE_STD_ZVAL(tmp);
321: ZVAL_NULL(tmp);
322: /*
323: add_soap_fault(this_ptr, "Client", "Can't find response data", NULL, NULL TSRMLS_CC);
324: xmlFreeDoc(response);
325: return FALSE;
326: */
327: } else {
328: /* Decoding value of parameter */
329: if (param != NULL) {
330: tmp = master_to_zval(param->encode, val);
331: } else {
332: tmp = master_to_zval(NULL, val);
333: }
334: }
335: add_assoc_zval(return_value, param->paramName, tmp);
336:
337: param_count++;
338:
339: zend_hash_move_forward(fn->responseParameters);
340: }
341: }
342: } else {
343: /* Function has no WSDL description */
344: xmlNodePtr val;
345: val = resp->children;
346: while (val != NULL) {
347: while (val && val->type != XML_ELEMENT_NODE) {
348: val = val->next;
349: }
350: if (val != NULL) {
351: if (!node_is_equal_ex(val,"result",RPC_SOAP12_NAMESPACE)) {
352: zval *tmp;
353: zval **arr;
354:
355: tmp = master_to_zval(NULL, val);
356: if (val->name) {
357: if (zend_hash_find(Z_ARRVAL_P(return_value), (char*)val->name, strlen((char*)val->name)+1, (void**)&arr) == SUCCESS) {
358: add_next_index_zval(*arr, tmp);
359: } else if (val->next && get_node(val->next, (char*)val->name)) {
360: zval *arr;
361:
362: MAKE_STD_ZVAL(arr);
363: array_init(arr);
364: add_next_index_zval(arr, tmp);
365: add_assoc_zval(return_value, (char*)val->name, arr);
366: } else {
367: add_assoc_zval(return_value, (char*)val->name, tmp);
368: }
369: } else {
370: add_next_index_zval(return_value, tmp);
371: }
372: ++param_count;
373: }
374: val = val->next;
375: }
376: }
377: }
378: }
379:
380: if (Z_TYPE_P(return_value) == IS_ARRAY) {
381: if (param_count == 0) {
382: zval_dtor(return_value);
383: ZVAL_NULL(return_value);
384: } else if (param_count == 1) {
385: zval *tmp;
386:
387: zend_hash_internal_pointer_reset(Z_ARRVAL_P(return_value));
388: zend_hash_get_current_data(Z_ARRVAL_P(return_value), (void**)&tmp);
389: tmp = *(zval**)tmp;
390: Z_ADDREF_P(tmp);
391: zval_dtor(return_value);
392: *return_value = *tmp;
393: FREE_ZVAL(tmp);
394: }
395: }
396:
397: if (soap_headers && head) {
398: trav = head->children;
399: while (trav != NULL) {
400: if (trav->type == XML_ELEMENT_NODE) {
401: encodePtr enc = NULL;
402: zval* val;
403:
404: if (hdrs) {
405: smart_str key = {0};
406: sdlSoapBindingFunctionHeaderPtr *hdr;
407:
408: if (trav->ns) {
409: smart_str_appends(&key, (char*)trav->ns->href);
410: smart_str_appendc(&key,':');
411: }
412: smart_str_appends(&key, (char*)trav->name);
413: smart_str_0(&key);
414: if (zend_hash_find(hdrs, key.c, key.len+1, (void**)&hdr) == SUCCESS) {
415: enc = (*hdr)->encode;
416: }
417: smart_str_free(&key);
418: }
419: val = master_to_zval(enc, trav);
420: add_assoc_zval(soap_headers, (char*)trav->name, val);
421: }
422: trav = trav->next;
423: }
424: }
425:
426: xmlFreeDoc(response);
427: return TRUE;
428: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>