php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
php_packet_soap.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Brad Lafountain <rodif_bl@yahoo.com> |
14 | Shane Caraveo <shane@caraveo.com> |
15 | Dmitry Stogov <dmitry@php.net> |
16 +----------------------------------------------------------------------+
17*/
18
19#include "php_soap.h"
20
21/* SOAP client calls this function to parse response from SOAP server */
22bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctionPtr fn, char *fn_name, zval *return_value, zval *soap_headers)
23{
24 char* envelope_ns = NULL;
25 xmlDocPtr response;
26 xmlNodePtr trav, env, head, body, resp, cur, fault;
27 xmlAttrPtr attr;
28 int param_count = 0;
30 HashTable *hdrs = NULL;
31
33
34 /* Response for one-way opearation */
35 if (buffer_size == 0) {
36 return true;
37 }
38
39 /* Parse XML packet */
40 response = soap_xmlParseMemory(buffer, buffer_size);
41
42 if (!response) {
43 add_soap_fault(this_ptr, "Client", "looks like we got no XML document", NULL, NULL);
44 return false;
45 }
46 if (xmlGetIntSubset(response) != NULL) {
47 add_soap_fault(this_ptr, "Client", "DTD are not supported by SOAP", NULL, NULL);
48 xmlFreeDoc(response);
49 return false;
50 }
51
52 /* Get <Envelope> element */
53 env = NULL;
54 trav = response->children;
55 while (trav != NULL) {
56 if (trav->type == XML_ELEMENT_NODE) {
57 if (env == NULL && node_is_equal_ex(trav,"Envelope",SOAP_1_1_ENV_NAMESPACE)) {
58 env = trav;
59 envelope_ns = SOAP_1_1_ENV_NAMESPACE;
61 } else if (env == NULL && node_is_equal_ex(trav,"Envelope",SOAP_1_2_ENV_NAMESPACE)) {
62 env = trav;
63 envelope_ns = SOAP_1_2_ENV_NAMESPACE;
65 } else {
66 add_soap_fault(this_ptr, "VersionMismatch", "Wrong Version", NULL, NULL);
67 xmlFreeDoc(response);
68 return false;
69 }
70 }
71 trav = trav->next;
72 }
73 if (env == NULL) {
74 add_soap_fault(this_ptr, "Client", "looks like we got XML without \"Envelope\" element", NULL, NULL);
75 xmlFreeDoc(response);
76 return false;
77 }
78
79 attr = env->properties;
80 while (attr != NULL) {
81 if (attr->ns == NULL) {
82 add_soap_fault(this_ptr, "Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL);
83 xmlFreeDoc(response);
84 return false;
85 } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
86 if (soap_version == SOAP_1_2) {
87 add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL);
88 xmlFreeDoc(response);
89 return false;
90 } else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
91 add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL);
92 xmlFreeDoc(response);
93 return false;
94 }
95 }
96 attr = attr->next;
97 }
98
99 /* Get <Header> element */
100 head = NULL;
101 trav = env->children;
102 while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
103 trav = trav->next;
104 }
105 if (trav != NULL && node_is_equal_ex(trav,"Header",envelope_ns)) {
106 head = trav;
107 trav = trav->next;
108 }
109
110 /* Get <Body> element */
111 body = NULL;
112 while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
113 trav = trav->next;
114 }
115 if (trav != NULL && node_is_equal_ex(trav,"Body",envelope_ns)) {
116 body = trav;
117 trav = trav->next;
118 }
119 while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
120 trav = trav->next;
121 }
122 if (body == NULL) {
123 add_soap_fault(this_ptr, "Client", "Body must be present in a SOAP envelope", NULL, NULL);
124 xmlFreeDoc(response);
125 return false;
126 }
127 attr = body->properties;
128 while (attr != NULL) {
129 if (attr->ns == NULL) {
130 if (soap_version == SOAP_1_2) {
131 add_soap_fault(this_ptr, "Client", "A SOAP Body element cannot have non Namespace qualified attributes", NULL, NULL);
132 xmlFreeDoc(response);
133 return false;
134 }
135 } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
136 if (soap_version == SOAP_1_2) {
137 add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Body", NULL, NULL);
138 xmlFreeDoc(response);
139 return false;
140 } else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
141 add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL);
142 xmlFreeDoc(response);
143 return false;
144 }
145 }
146 attr = attr->next;
147 }
148 if (trav != NULL && soap_version == SOAP_1_2) {
149 add_soap_fault(this_ptr, "Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL);
150 xmlFreeDoc(response);
151 return false;
152 }
153
154 if (head != NULL) {
155 attr = head->properties;
156 while (attr != NULL) {
157 if (attr->ns == NULL) {
158 add_soap_fault(this_ptr, "Client", "A SOAP Header element cannot have non Namespace qualified attributes", NULL, NULL);
159 xmlFreeDoc(response);
160 return false;
161 } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
162 if (soap_version == SOAP_1_2) {
163 add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Header", NULL, NULL);
164 xmlFreeDoc(response);
165 return false;
166 } else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
167 add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL);
168 xmlFreeDoc(response);
169 return false;
170 }
171 }
172 attr = attr->next;
173 }
174 }
175
176 /* Check if <Body> contains <Fault> element */
177 fault = get_node_ex(body->children,"Fault",envelope_ns);
178 if (fault != NULL) {
179 char *faultcode = NULL;
180 zend_string *faultstring = NULL, *faultactor = NULL;
181 zval details;
182 xmlNodePtr tmp;
183
184 ZVAL_UNDEF(&details);
185 if (soap_version == SOAP_1_1) {
186 tmp = get_node(fault->children, "faultcode");
187 if (tmp != NULL && tmp->children != NULL) {
188 faultcode = (char*)tmp->children->content;
189 }
190
191 tmp = get_node(fault->children, "faultstring");
192 if (tmp != NULL && tmp->children != NULL) {
193 zval zv;
196 faultstring = Z_STR(zv);
197 }
198
199 tmp = get_node(fault->children, "faultactor");
200 if (tmp != NULL && tmp->children != NULL) {
201 zval zv;
204 faultactor = Z_STR(zv);
205 }
206
207 tmp = get_node(fault->children, "detail");
208 if (tmp != NULL) {
209 master_to_zval(&details, NULL, tmp);
210 }
211 } else {
212 tmp = get_node(fault->children, "Code");
213 if (tmp != NULL && tmp->children != NULL) {
214 tmp = get_node(tmp->children, "Value");
215 if (tmp != NULL && tmp->children != NULL) {
216 faultcode = (char*)tmp->children->content;
217 }
218 }
219
220 tmp = get_node(fault->children,"Reason");
221 if (tmp != NULL && tmp->children != NULL) {
222 /* TODO: lang attribute */
223 tmp = get_node(tmp->children,"Text");
224 if (tmp != NULL && tmp->children != NULL) {
225 zval zv;
228 faultstring = Z_STR(zv);
229 }
230 }
231
232 tmp = get_node(fault->children,"Detail");
233 if (tmp != NULL) {
234 master_to_zval(&details, NULL, tmp);
235 }
236 }
237 add_soap_fault(this_ptr, faultcode, faultstring ? ZSTR_VAL(faultstring) : NULL, faultactor ? ZSTR_VAL(faultactor) : NULL, &details);
238 if (faultstring) {
239 zend_string_release_ex(faultstring, 0);
240 }
241 if (faultactor) {
242 zend_string_release_ex(faultactor, 0);
243 }
244 if (Z_REFCOUNTED(details)) {
245 Z_DELREF(details);
246 }
247 xmlFreeDoc(response);
248 return false;
249 }
250
251 /* Parse content of <Body> element */
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 param = NULL;
261 xmlNodePtr val = NULL;
262 char *name, *ns = NULL;
263 zval tmp;
265 int res_count;
266
267 hdrs = fnb->output.headers;
268
269 if (fn->responseParameters) {
270 res_count = zend_hash_num_elements(fn->responseParameters);
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 ZVAL_NULL(&tmp);
319/*
320 add_soap_fault(this_ptr, "Client", "Can't find response data", NULL, NULL);
321 xmlFreeDoc(response);
322 return false;
323*/
324 } else {
325 /* Decoding value of parameter */
326 if (param != NULL) {
327 master_to_zval(&tmp, param->encode, val);
328 } else {
329 master_to_zval(&tmp, NULL, val);
330 }
331 }
332 add_assoc_zval(return_value, param->paramName, &tmp);
333
334 param_count++;
336 }
337 } else {
338 /* Function has no WSDL description */
339 xmlNodePtr val;
340 val = resp->children;
341 while (val != NULL) {
342 while (val && val->type != XML_ELEMENT_NODE) {
343 val = val->next;
344 }
345 if (val != NULL) {
347 zval tmp;
348 zval *arr;
349
350 master_to_zval(&tmp, NULL, val);
351 if (val->name) {
352 if ((arr = zend_hash_str_find(Z_ARRVAL_P(return_value), (char*)val->name, strlen((char*)val->name))) != NULL) {
353 add_next_index_zval(arr, &tmp);
354 } else if (val->next && get_node(val->next, (char*)val->name)) {
355 zval arr;
356
357 array_init(&arr);
358 add_next_index_zval(&arr, &tmp);
359 add_assoc_zval(return_value, (char*)val->name, &arr);
360 } else {
361 add_assoc_zval(return_value, (char*)val->name, &tmp);
362 }
363 } else {
364 add_next_index_zval(return_value, &tmp);
365 }
366 ++param_count;
367 }
368 val = val->next;
369 }
370 }
371 }
372 }
373
375 if (param_count == 0) {
378 } else if (param_count == 1) {
379 zval *tmp;
380
381 zend_hash_internal_pointer_reset(Z_ARRVAL_P(return_value));
382 tmp = zend_hash_get_current_data(Z_ARRVAL_P(return_value));
385 } else {
389 }
390 }
391 }
392
393 if (soap_headers && head) {
394 trav = head->children;
395 while (trav != NULL) {
396 if (trav->type == XML_ELEMENT_NODE) {
397 encodePtr enc = NULL;
398 zval val;
399
400 if (hdrs) {
401 smart_str key = {0};
403
404 if (trav->ns) {
405 smart_str_appends(&key, (char*)trav->ns->href);
406 smart_str_appendc(&key,':');
407 }
408 smart_str_appends(&key, (char*)trav->name);
409 smart_str_0(&key);
410 if ((hdr = zend_hash_find_ptr(hdrs, key.s)) != NULL) {
411 enc = hdr->encode;
412 }
413 smart_str_free(&key);
414 }
415 master_to_zval(&val, enc, trav);
416 add_assoc_zval(soap_headers, (char*)trav->name, &val);
417 }
418 trav = trav->next;
419 }
420 }
421
422 xmlFreeDoc(response);
423 return true;
424}
zval * zv
Definition ffi.c:3975
new_type attr
Definition ffi.c:4364
zval * val
Definition ffi.c:4262
#define NULL
Definition gdcache.h:45
const XML_ELEMENT_NODE
encodePtr get_conversion(int encode)
zval * master_to_zval(zval *ret, encodePtr encode, xmlNodePtr data)
#define RPC_SOAP12_NAMESPACE
#define SOAP_1_1_ENC_NAMESPACE
#define SOAP_1_1_ENV_NAMESPACE
#define SOAP_1_2_ENV_NAMESPACE
bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctionPtr fn, char *fn_name, zval *return_value, zval *soap_headers)
struct php_pcntl_pending_signal * head
Definition php_pcntl.h:47
unsigned char key[REFLECTION_KEY_LEN]
struct _sdlSoapBindingFunctionHeader * sdlSoapBindingFunctionHeaderPtr
@ SOAP_DOCUMENT
Definition php_sdl.h:33
@ SOAP_RPC
Definition php_sdl.h:32
@ BINDING_SOAP
Definition php_sdl.h:27
struct _encode * encodePtr
Definition php_soap.h:42
void add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail)
Definition soap.c:2920
struct _sdlFunction * sdlFunctionPtr
Definition php_soap.h:50
struct _sdlSoapBindingFunction * sdlSoapBindingFunctionPtr
Definition php_soap.h:54
#define SOAP_1_2
Definition php_soap.h:118
struct _sdlParam * sdlParamPtr
Definition php_soap.h:49
int soap_version
Definition php_soap.h:159
#define SOAP_1_1
Definition php_soap.h:117
int node_is_equal_ex(xmlNodePtr node, char *name, char *ns)
Definition php_xml.c:222
xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size)
Definition php_xml.c:133
int attr_is_equal_ex(xmlAttrPtr node, char *name, char *ns)
Definition php_xml.c:206
xmlNodePtr get_node_ex(xmlNodePtr node, char *name, char *ns)
Definition php_xml.c:250
@ body
#define get_node(node, name)
Definition php_xml.h:23
sdlBindingType bindingType
Definition php_sdl.h:83
char * responseName
Definition php_sdl.h:228
void * bindingAttributes
Definition php_sdl.h:232
HashTable * responseParameters
Definition php_sdl.h:230
struct _sdlBinding * binding
Definition php_sdl.h:231
char * paramName
Definition php_sdl.h:216
encodePtr encode
Definition php_sdl.h:215
sdlTypePtr element
Definition php_sdl.h:214
sdlEncodingStyle style
Definition php_sdl.h:118
sdlSoapBindingFunctionBody output
Definition php_sdl.h:121
char * name
Definition php_sdl.h:199
char * namens
Definition php_sdl.h:200
Definition file.h:177
#define array_init(arg)
Definition zend_API.h:537
struct _zval_struct zval
strlen(string $string)
strcmp(string $string1, string $string2)
zend_string_release_ex(func->internal_function.function_name, 0)
ZEND_API zval *ZEND_FASTCALL zend_hash_str_find(const HashTable *ht, const char *str, size_t len)
Definition zend_hash.c:2689
ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
Definition zend_hash.c:1808
#define ZEND_HASH_FOREACH_PTR(ht, _ptr)
Definition zend_hash.h:1118
#define ZEND_HASH_FOREACH_END()
Definition zend_hash.h:1086
struct _zend_string zend_string
#define convert_to_string(op)
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define ZVAL_UNDEF(z)
#define Z_ARRVAL_P(zval_p)
Definition zend_types.h:987
#define ZVAL_NULL(z)
#define IS_STRING
Definition zend_types.h:606
#define Z_REFCOUNTED_P(zval_p)
Definition zend_types.h:921
struct _zend_array HashTable
Definition zend_types.h:386
#define IS_ARRAY
Definition zend_types.h:607
#define Z_COUNTED_P(zval_p)
Definition zend_types.h:699
#define Z_STR(zval)
Definition zend_types.h:971
#define Z_REFCOUNTED(zval)
Definition zend_types.h:917
#define ZVAL_COPY(z, v)
struct _zend_refcounted zend_refcounted
Definition zend_types.h:95
#define Z_ARR_P(zval_p)
Definition zend_types.h:984
#define Z_DELREF(z)
ZEND_API void ZEND_FASTCALL rc_dtor_func(zend_refcounted *p)
zval * return_value
zend_string * name
zend_refcounted * garbage