1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2018 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$ */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include "php_soap.h"
26 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
27 #include "ext/session/php_session.h"
28 #endif
29 #include "zend_exceptions.h"
30
31
32 static int le_sdl = 0;
33 int le_url = 0;
34 static int le_service = 0;
35 static int le_typemap = 0;
36
37 typedef struct _soapHeader {
38 sdlFunctionPtr function;
39 zval function_name;
40 int mustUnderstand;
41 int num_params;
42 zval *parameters;
43 zval retval;
44 sdlSoapBindingFunctionHeaderPtr hdr;
45 struct _soapHeader *next;
46 } soapHeader;
47
48 /* Local functions */
49 static void function_to_string(sdlFunctionPtr function, smart_str *buf);
50 static void type_to_string(sdlTypePtr type, smart_str *buf, int level);
51
52 static void clear_soap_fault(zval *obj);
53 static void set_soap_fault(zval *obj, char *fault_code_ns, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail, char *name);
54 static void add_soap_fault_ex(zval *fault, zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail);
55 static void soap_server_fault(char* code, char* string, char *actor, zval* details, char *name);
56 static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeader* hdr);
57
58 static sdlParamPtr get_param(sdlFunctionPtr function, char *param_name, int index, int);
59 static sdlFunctionPtr get_function(sdlPtr sdl, const char *function_name);
60 static sdlFunctionPtr get_doc_function(sdlPtr sdl, xmlNodePtr node);
61
62 static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, char* actor, zval *function_name, int *num_params, zval **parameters, int *version, soapHeader **headers);
63 static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function_name,char *uri,zval *ret, soapHeader *headers, int version);
64 static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function, char *function_name, char *uri, zval *arguments, int arg_count, int version, HashTable *soap_headers);
65 static xmlNodePtr serialize_parameter(sdlParamPtr param,zval *param_val,int index,char *name, int style, xmlNodePtr parent);
66 static xmlNodePtr serialize_zval(zval *val, sdlParamPtr param, char *paramName, int style, xmlNodePtr parent);
67
68 static void delete_service(void *service);
69 static void delete_url(void *handle);
70 static void delete_hashtable(void *hashtable);
71
72 static void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args);
73
74 #define SOAP_SERVER_BEGIN_CODE() \
75 zend_bool _old_handler = SOAP_GLOBAL(use_soap_error_handler);\
76 char* _old_error_code = SOAP_GLOBAL(error_code);\
77 zend_object* _old_error_object = Z_OBJ(SOAP_GLOBAL(error_object));\
78 int _old_soap_version = SOAP_GLOBAL(soap_version);\
79 SOAP_GLOBAL(use_soap_error_handler) = 1;\
80 SOAP_GLOBAL(error_code) = "Server";\
81 Z_OBJ(SOAP_GLOBAL(error_object)) = Z_OBJ(EX(This));
82
83 #define SOAP_SERVER_END_CODE() \
84 SOAP_GLOBAL(use_soap_error_handler) = _old_handler;\
85 SOAP_GLOBAL(error_code) = _old_error_code;\
86 Z_OBJ(SOAP_GLOBAL(error_object)) = _old_error_object;\
87 SOAP_GLOBAL(soap_version) = _old_soap_version;
88
89 #define SOAP_CLIENT_BEGIN_CODE() \
90 zend_bool _old_handler = SOAP_GLOBAL(use_soap_error_handler);\
91 char* _old_error_code = SOAP_GLOBAL(error_code);\
92 zend_object* _old_error_object = Z_OBJ(SOAP_GLOBAL(error_object));\
93 int _old_soap_version = SOAP_GLOBAL(soap_version);\
94 zend_bool _old_in_compilation = CG(in_compilation); \
95 zend_execute_data *_old_current_execute_data = EG(current_execute_data); \
96 zval *_old_stack_top = EG(vm_stack_top); \
97 int _bailout = 0;\
98 SOAP_GLOBAL(use_soap_error_handler) = 1;\
99 SOAP_GLOBAL(error_code) = "Client";\
100 Z_OBJ(SOAP_GLOBAL(error_object)) = Z_OBJ(EX(This));\
101 zend_try {
102
103 #define SOAP_CLIENT_END_CODE() \
104 } zend_catch {\
105 CG(in_compilation) = _old_in_compilation; \
106 EG(current_execute_data) = _old_current_execute_data; \
107 if (EG(exception) == NULL || \
108 !instanceof_function(EG(exception)->ce, soap_fault_class_entry)) {\
109 _bailout = 1;\
110 }\
111 if (_old_stack_top != EG(vm_stack_top)) { \
112 while (EG(vm_stack)->prev != NULL && \
113 ((char*)_old_stack_top < (char*)EG(vm_stack) || \
114 (char*) _old_stack_top > (char*)EG(vm_stack)->end)) { \
115 zend_vm_stack tmp = EG(vm_stack)->prev; \
116 efree(EG(vm_stack)); \
117 EG(vm_stack) = tmp; \
118 EG(vm_stack_end) = tmp->end; \
119 } \
120 EG(vm_stack)->top = _old_stack_top; \
121 } \
122 } zend_end_try();\
123 SOAP_GLOBAL(use_soap_error_handler) = _old_handler;\
124 SOAP_GLOBAL(error_code) = _old_error_code;\
125 Z_OBJ(SOAP_GLOBAL(error_object)) = _old_error_object;\
126 SOAP_GLOBAL(soap_version) = _old_soap_version;\
127 if (_bailout) {\
128 zend_bailout();\
129 }
130
131 #define FETCH_THIS_SDL(ss) \
132 { \
133 zval *__tmp; \
134 if(FIND_SDL_PROPERTY(getThis(), __tmp) != NULL) { \
135 FETCH_SDL_RES(ss,__tmp); \
136 } else { \
137 ss = NULL; \
138 } \
139 }
140
141 #define FIND_SDL_PROPERTY(ss,tmp) (tmp = zend_hash_str_find(Z_OBJPROP_P(ss), "sdl", sizeof("sdl")-1))
142 #define FETCH_SDL_RES(ss,tmp) ss = (sdlPtr) zend_fetch_resource_ex(tmp, "sdl", le_sdl)
143
144 #define FIND_TYPEMAP_PROPERTY(ss,tmp) (tmp = zend_hash_str_find(Z_OBJPROP_P(ss), "typemap", sizeof("typemap")-1))
145 #define FETCH_TYPEMAP_RES(ss,tmp) ss = (HashTable*) zend_fetch_resource_ex(tmp, "typemap", le_typemap)
146
147 #define FETCH_THIS_SERVICE(ss) \
148 { \
149 zval *tmp; \
150 if ((tmp = zend_hash_str_find(Z_OBJPROP_P(getThis()),"service", sizeof("service")-1)) != NULL) { \
151 ss = (soapServicePtr)zend_fetch_resource_ex(tmp, "service", le_service); \
152 } else { \
153 php_error_docref(NULL, E_WARNING, "Can not fetch service object"); \
154 SOAP_SERVER_END_CODE(); \
155 return; \
156 } \
157 }
158
159 static zend_class_entry* soap_class_entry;
160 static zend_class_entry* soap_server_class_entry;
161 static zend_class_entry* soap_fault_class_entry;
162 static zend_class_entry* soap_header_class_entry;
163 static zend_class_entry* soap_param_class_entry;
164 zend_class_entry* soap_var_class_entry;
165
166 ZEND_DECLARE_MODULE_GLOBALS(soap)
167
168 static void (*old_error_handler)(int, const char *, const uint, const char*, va_list);
169
170 #ifdef va_copy
171 #define call_old_error_handler(error_num, error_filename, error_lineno, format, args) \
172 { \
173 va_list copy; \
174 va_copy(copy, args); \
175 old_error_handler(error_num, error_filename, error_lineno, format, copy); \
176 va_end(copy); \
177 }
178 #else
179 #define call_old_error_handler(error_num, error_filename, error_lineno, format, args) \
180 { \
181 old_error_handler(error_num, error_filename, error_lineno, format, args); \
182 }
183 #endif
184
185 #define PHP_SOAP_SERVER_CLASSNAME "SoapServer"
186 #define PHP_SOAP_CLIENT_CLASSNAME "SoapClient"
187 #define PHP_SOAP_VAR_CLASSNAME "SoapVar"
188 #define PHP_SOAP_FAULT_CLASSNAME "SoapFault"
189 #define PHP_SOAP_PARAM_CLASSNAME "SoapParam"
190 #define PHP_SOAP_HEADER_CLASSNAME "SoapHeader"
191
192 PHP_RINIT_FUNCTION(soap);
193 PHP_MINIT_FUNCTION(soap);
194 PHP_MSHUTDOWN_FUNCTION(soap);
195 PHP_MINFO_FUNCTION(soap);
196
197 /*
198 Registry Functions
199 TODO: this!
200 */
201 PHP_FUNCTION(soap_encode_to_xml);
202 PHP_FUNCTION(soap_encode_to_zval);
203 PHP_FUNCTION(use_soap_error_handler);
204 PHP_FUNCTION(is_soap_fault);
205
206
207 /* Server Functions */
208 PHP_METHOD(SoapServer, SoapServer);
209 PHP_METHOD(SoapServer, setClass);
210 PHP_METHOD(SoapServer, setObject);
211 PHP_METHOD(SoapServer, addFunction);
212 PHP_METHOD(SoapServer, getFunctions);
213 PHP_METHOD(SoapServer, handle);
214 PHP_METHOD(SoapServer, setPersistence);
215 PHP_METHOD(SoapServer, fault);
216 PHP_METHOD(SoapServer, addSoapHeader);
217
218 /* Client Functions */
219 PHP_METHOD(SoapClient, SoapClient);
220 PHP_METHOD(SoapClient, __call);
221 PHP_METHOD(SoapClient, __getLastRequest);
222 PHP_METHOD(SoapClient, __getLastResponse);
223 PHP_METHOD(SoapClient, __getLastRequestHeaders);
224 PHP_METHOD(SoapClient, __getLastResponseHeaders);
225 PHP_METHOD(SoapClient, __getFunctions);
226 PHP_METHOD(SoapClient, __getTypes);
227 PHP_METHOD(SoapClient, __doRequest);
228 PHP_METHOD(SoapClient, __setCookie);
229 PHP_METHOD(SoapClient, __getCookies);
230 PHP_METHOD(SoapClient, __setLocation);
231 PHP_METHOD(SoapClient, __setSoapHeaders);
232
233 /* SoapVar Functions */
234 PHP_METHOD(SoapVar, SoapVar);
235
236 /* SoapFault Functions */
237 PHP_METHOD(SoapFault, SoapFault);
238 PHP_METHOD(SoapFault, __toString);
239
240 /* SoapParam Functions */
241 PHP_METHOD(SoapParam, SoapParam);
242
243 /* SoapHeader Functions */
244 PHP_METHOD(SoapHeader, SoapHeader);
245
246 #define SOAP_CTOR(class_name, func_name, arginfo, flags) PHP_ME(class_name, func_name, arginfo, flags)
247
248 /* {{{ arginfo */
249 ZEND_BEGIN_ARG_INFO(arginfo_soap__void, 0)
250 ZEND_END_ARG_INFO()
251
252 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapparam_soapparam, 0, 0, 2)
253 ZEND_ARG_INFO(0, data)
254 ZEND_ARG_INFO(0, name)
255 ZEND_END_ARG_INFO()
256
257 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapheader_soapheader, 0, 0, 2)
258 ZEND_ARG_INFO(0, namespace)
259 ZEND_ARG_INFO(0, name)
260 ZEND_ARG_INFO(0, data)
261 ZEND_ARG_INFO(0, mustunderstand)
262 ZEND_ARG_INFO(0, actor)
263 ZEND_END_ARG_INFO()
264
265 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapfault_soapfault, 0, 0, 2)
266 ZEND_ARG_INFO(0, faultcode)
267 ZEND_ARG_INFO(0, faultstring)
268 ZEND_ARG_INFO(0, faultactor)
269 ZEND_ARG_INFO(0, detail)
270 ZEND_ARG_INFO(0, faultname)
271 ZEND_ARG_INFO(0, headerfault)
272 ZEND_END_ARG_INFO()
273
274 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapvar_soapvar, 0, 0, 2)
275 ZEND_ARG_INFO(0, data)
276 ZEND_ARG_INFO(0, encoding)
277 ZEND_ARG_INFO(0, type_name)
278 ZEND_ARG_INFO(0, type_namespace)
279 ZEND_ARG_INFO(0, node_name)
280 ZEND_ARG_INFO(0, node_namespace)
281 ZEND_END_ARG_INFO()
282
283 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_fault, 0, 0, 2)
284 ZEND_ARG_INFO(0, code)
285 ZEND_ARG_INFO(0, string)
286 ZEND_ARG_INFO(0, actor)
287 ZEND_ARG_INFO(0, details)
288 ZEND_ARG_INFO(0, name)
289 ZEND_END_ARG_INFO()
290
291 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_addsoapheader, 0, 0, 1)
292 ZEND_ARG_INFO(0, object)
293 ZEND_END_ARG_INFO()
294
295 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_soapserver, 0, 0, 1)
296 ZEND_ARG_INFO(0, wsdl)
297 ZEND_ARG_INFO(0, options)
298 ZEND_END_ARG_INFO()
299
300 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_setpersistence, 0, 0, 1)
301 ZEND_ARG_INFO(0, mode)
302 ZEND_END_ARG_INFO()
303
304 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_setclass, 0, 0, 1)
305 ZEND_ARG_INFO(0, class_name)
306 ZEND_ARG_INFO(0, args)
307 ZEND_END_ARG_INFO()
308
309 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_setobject, 0, 0, 1)
310 ZEND_ARG_INFO(0, object)
311 ZEND_END_ARG_INFO()
312
313 ZEND_BEGIN_ARG_INFO(arginfo_soapserver_getfunctions, 0)
314 ZEND_END_ARG_INFO()
315
316 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_addfunction, 0, 0, 1)
317 ZEND_ARG_INFO(0, functions)
318 ZEND_END_ARG_INFO()
319
320 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_handle, 0, 0, 0)
321 ZEND_ARG_INFO(0, soap_request)
322 ZEND_END_ARG_INFO()
323
324 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient_soapclient, 0, 0, 1)
325 ZEND_ARG_INFO(0, wsdl)
326 ZEND_ARG_INFO(0, options)
327 ZEND_END_ARG_INFO()
328
329 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___call, 0, 0, 2)
330 ZEND_ARG_INFO(0, function_name)
331 ZEND_ARG_INFO(0, arguments)
332 ZEND_END_ARG_INFO()
333
334 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___soapcall, 0, 0, 2)
335 ZEND_ARG_INFO(0, function_name)
336 ZEND_ARG_INFO(0, arguments)
337 ZEND_ARG_INFO(0, options)
338 ZEND_ARG_INFO(0, input_headers)
339 ZEND_ARG_INFO(1, output_headers)
340 ZEND_END_ARG_INFO()
341
342 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getfunctions, 0)
343 ZEND_END_ARG_INFO()
344
345 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___gettypes, 0)
346 ZEND_END_ARG_INFO()
347
348 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastrequest, 0)
349 ZEND_END_ARG_INFO()
350
351 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastresponse, 0)
352 ZEND_END_ARG_INFO()
353
354 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastrequestheaders, 0)
355 ZEND_END_ARG_INFO()
356
357 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastresponseheaders, 0)
358 ZEND_END_ARG_INFO()
359
360 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___dorequest, 0, 0, 4)
361 ZEND_ARG_INFO(0, request)
362 ZEND_ARG_INFO(0, location)
363 ZEND_ARG_INFO(0, action)
364 ZEND_ARG_INFO(0, version)
365 ZEND_ARG_INFO(0, one_way)
366 ZEND_END_ARG_INFO()
367
368 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___setcookie, 0, 0, 1)
369 ZEND_ARG_INFO(0, name)
370 ZEND_ARG_INFO(0, value)
371 ZEND_END_ARG_INFO()
372
373 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getcookies, 0)
374 ZEND_END_ARG_INFO()
375
376 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___setsoapheaders, 0, 0, 0)
377 ZEND_ARG_INFO(0, soapheaders)
378 ZEND_END_ARG_INFO()
379
380 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___setlocation, 0, 0, 0)
381 ZEND_ARG_INFO(0, new_location)
382 ZEND_END_ARG_INFO()
383
384 ZEND_BEGIN_ARG_INFO_EX(arginfo_soap_use_soap_error_handler, 0, 0, 0)
385 ZEND_ARG_INFO(0, handler)
386 ZEND_END_ARG_INFO()
387
388 ZEND_BEGIN_ARG_INFO_EX(arginfo_soap_is_soap_fault, 0, 0, 1)
389 ZEND_ARG_INFO(0, object)
390 ZEND_END_ARG_INFO()
391 /* }}} */
392
393 static const zend_function_entry soap_functions[] = {
394 PHP_FE(use_soap_error_handler, arginfo_soap_use_soap_error_handler)
395 PHP_FE(is_soap_fault, arginfo_soap_is_soap_fault)
396 PHP_FE_END
397 };
398
399 static const zend_function_entry soap_fault_functions[] = {
400 SOAP_CTOR(SoapFault, SoapFault, arginfo_soapfault_soapfault, 0)
401 PHP_ME(SoapFault, __toString, arginfo_soap__void, 0)
402 PHP_FE_END
403 };
404
405 static const zend_function_entry soap_server_functions[] = {
406 SOAP_CTOR(SoapServer, SoapServer, arginfo_soapserver_soapserver, 0)
407 PHP_ME(SoapServer, setPersistence, arginfo_soapserver_setpersistence, 0)
408 PHP_ME(SoapServer, setClass, arginfo_soapserver_setclass, 0)
409 PHP_ME(SoapServer, setObject, arginfo_soapserver_setobject, 0)
410 PHP_ME(SoapServer, addFunction, arginfo_soapserver_addfunction, 0)
411 PHP_ME(SoapServer, getFunctions, arginfo_soapserver_getfunctions, 0)
412 PHP_ME(SoapServer, handle, arginfo_soapserver_handle, 0)
413 PHP_ME(SoapServer, fault, arginfo_soapserver_fault, 0)
414 PHP_ME(SoapServer, addSoapHeader, arginfo_soapserver_addsoapheader, 0)
415 PHP_FE_END
416 };
417
418 static const zend_function_entry soap_client_functions[] = {
419 SOAP_CTOR(SoapClient, SoapClient, arginfo_soapclient_soapclient, 0)
420 PHP_ME(SoapClient, __call, arginfo_soapclient___call, 0)
421 ZEND_NAMED_ME(__soapCall, ZEND_MN(SoapClient___call), arginfo_soapclient___soapcall, 0)
422 PHP_ME(SoapClient, __getLastRequest, arginfo_soapclient___getlastrequest, 0)
423 PHP_ME(SoapClient, __getLastResponse, arginfo_soapclient___getlastresponse, 0)
424 PHP_ME(SoapClient, __getLastRequestHeaders, arginfo_soapclient___getlastrequestheaders, 0)
425 PHP_ME(SoapClient, __getLastResponseHeaders, arginfo_soapclient___getlastresponseheaders, 0)
426 PHP_ME(SoapClient, __getFunctions, arginfo_soapclient___getfunctions, 0)
427 PHP_ME(SoapClient, __getTypes, arginfo_soapclient___gettypes, 0)
428 PHP_ME(SoapClient, __doRequest, arginfo_soapclient___dorequest, 0)
429 PHP_ME(SoapClient, __setCookie, arginfo_soapclient___setcookie, 0)
430 PHP_ME(SoapClient, __getCookies, arginfo_soapclient___getcookies, 0)
431 PHP_ME(SoapClient, __setLocation, arginfo_soapclient___setlocation, 0)
432 PHP_ME(SoapClient, __setSoapHeaders, arginfo_soapclient___setsoapheaders, 0)
433 PHP_FE_END
434 };
435
436 static const zend_function_entry soap_var_functions[] = {
437 SOAP_CTOR(SoapVar, SoapVar, arginfo_soapvar_soapvar, 0)
438 PHP_FE_END
439 };
440
441 static const zend_function_entry soap_param_functions[] = {
442 SOAP_CTOR(SoapParam, SoapParam, arginfo_soapparam_soapparam, 0)
443 PHP_FE_END
444 };
445
446 static const zend_function_entry soap_header_functions[] = {
447 SOAP_CTOR(SoapHeader, SoapHeader, arginfo_soapheader_soapheader, 0)
448 PHP_FE_END
449 };
450
451 zend_module_entry soap_module_entry = {
452 #ifdef STANDARD_MODULE_HEADER
453 STANDARD_MODULE_HEADER,
454 #endif
455 "soap",
456 soap_functions,
457 PHP_MINIT(soap),
458 PHP_MSHUTDOWN(soap),
459 PHP_RINIT(soap),
460 NULL,
461 PHP_MINFO(soap),
462 #ifdef STANDARD_MODULE_HEADER
463 PHP_SOAP_VERSION,
464 #endif
465 STANDARD_MODULE_PROPERTIES,
466 };
467
468 #ifdef COMPILE_DL_SOAP
469 #ifdef ZTS
470 ZEND_TSRMLS_CACHE_DEFINE()
471 #endif
ZEND_GET_MODULE(soap)472 ZEND_GET_MODULE(soap)
473 #endif
474
475 ZEND_INI_MH(OnUpdateCacheMode)
476 {
477 char *p;
478 #ifndef ZTS
479 char *base = (char *) mh_arg2;
480 #else
481 char *base = (char *) ts_resource(*((int *) mh_arg2));
482 #endif
483
484 p = (char*) (base+(size_t) mh_arg1);
485
486 *p = (char)atoi(ZSTR_VAL(new_value));
487
488 return SUCCESS;
489 }
490
PHP_INI_MH(OnUpdateCacheDir)491 static PHP_INI_MH(OnUpdateCacheDir)
492 {
493 /* Only do the open_basedir check at runtime */
494 if (stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) {
495 char *p;
496
497 if (memchr(ZSTR_VAL(new_value), '\0', ZSTR_LEN(new_value)) != NULL) {
498 return FAILURE;
499 }
500
501 /* we do not use zend_memrchr() since path can contain ; itself */
502 if ((p = strchr(ZSTR_VAL(new_value), ';'))) {
503 char *p2;
504 p++;
505 if ((p2 = strchr(p, ';'))) {
506 p = p2 + 1;
507 }
508 } else {
509 p = ZSTR_VAL(new_value);
510 }
511
512 if (PG(open_basedir) && *p && php_check_open_basedir(p)) {
513 return FAILURE;
514 }
515 }
516
517 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
518 return SUCCESS;
519 }
520
521 PHP_INI_BEGIN()
522 STD_PHP_INI_ENTRY("soap.wsdl_cache_enabled", "1", PHP_INI_ALL, OnUpdateBool,
523 cache_enabled, zend_soap_globals, soap_globals)
524 STD_PHP_INI_ENTRY("soap.wsdl_cache_dir", "/tmp", PHP_INI_ALL, OnUpdateCacheDir,
525 cache_dir, zend_soap_globals, soap_globals)
526 STD_PHP_INI_ENTRY("soap.wsdl_cache_ttl", "86400", PHP_INI_ALL, OnUpdateLong,
527 cache_ttl, zend_soap_globals, soap_globals)
528 STD_PHP_INI_ENTRY("soap.wsdl_cache", "1", PHP_INI_ALL, OnUpdateCacheMode,
529 cache_mode, zend_soap_globals, soap_globals)
530 STD_PHP_INI_ENTRY("soap.wsdl_cache_limit", "5", PHP_INI_ALL, OnUpdateLong,
531 cache_limit, zend_soap_globals, soap_globals)
532 PHP_INI_END()
533
534 static HashTable defEnc, defEncIndex, defEncNs;
535
php_soap_prepare_globals()536 static void php_soap_prepare_globals()
537 {
538 int i;
539 encodePtr enc;
540
541 zend_hash_init(&defEnc, 0, NULL, NULL, 1);
542 zend_hash_init(&defEncIndex, 0, NULL, NULL, 1);
543 zend_hash_init(&defEncNs, 0, NULL, NULL, 1);
544
545 i = 0;
546 do {
547 enc = &defaultEncoding[i];
548
549 /* If has a ns and a str_type then index it */
550 if (defaultEncoding[i].details.type_str) {
551 if (defaultEncoding[i].details.ns != NULL) {
552 char *ns_type;
553 spprintf(&ns_type, 0, "%s:%s", defaultEncoding[i].details.ns, defaultEncoding[i].details.type_str);
554 zend_hash_str_add_ptr(&defEnc, ns_type, strlen(ns_type), enc);
555 efree(ns_type);
556 } else {
557 zend_hash_str_add_ptr(&defEnc, defaultEncoding[i].details.type_str, strlen(defaultEncoding[i].details.type_str), enc);
558 }
559 }
560 /* Index everything by number */
561 if (!zend_hash_index_exists(&defEncIndex, defaultEncoding[i].details.type)) {
562 zend_hash_index_update_ptr(&defEncIndex, defaultEncoding[i].details.type, enc);
563 }
564 i++;
565 } while (defaultEncoding[i].details.type != END_KNOWN_TYPES);
566
567 /* hash by namespace */
568 zend_hash_str_add_ptr(&defEncNs, XSD_1999_NAMESPACE, sizeof(XSD_1999_NAMESPACE)-1, XSD_NS_PREFIX);
569 zend_hash_str_add_ptr(&defEncNs, XSD_NAMESPACE, sizeof(XSD_NAMESPACE)-1, XSD_NS_PREFIX);
570 zend_hash_str_add_ptr(&defEncNs, XSI_NAMESPACE, sizeof(XSI_NAMESPACE)-1, XSI_NS_PREFIX);
571 zend_hash_str_add_ptr(&defEncNs, XML_NAMESPACE, sizeof(XML_NAMESPACE)-1, XML_NS_PREFIX);
572 zend_hash_str_add_ptr(&defEncNs, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)-1, SOAP_1_1_ENC_NS_PREFIX);
573 zend_hash_str_add_ptr(&defEncNs, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)-1, SOAP_1_2_ENC_NS_PREFIX);
574 }
575
php_soap_init_globals(zend_soap_globals * soap_globals)576 static void php_soap_init_globals(zend_soap_globals *soap_globals)
577 {
578 soap_globals->defEnc = defEnc;
579 soap_globals->defEncIndex = defEncIndex;
580 soap_globals->defEncNs = defEncNs;
581 soap_globals->typemap = NULL;
582 soap_globals->use_soap_error_handler = 0;
583 soap_globals->error_code = NULL;
584 ZVAL_OBJ(&soap_globals->error_object, NULL);
585 soap_globals->sdl = NULL;
586 soap_globals->soap_version = SOAP_1_1;
587 soap_globals->mem_cache = NULL;
588 soap_globals->ref_map = NULL;
589 }
590
PHP_MSHUTDOWN_FUNCTION(soap)591 PHP_MSHUTDOWN_FUNCTION(soap)
592 {
593 zend_error_cb = old_error_handler;
594 zend_hash_destroy(&SOAP_GLOBAL(defEnc));
595 zend_hash_destroy(&SOAP_GLOBAL(defEncIndex));
596 zend_hash_destroy(&SOAP_GLOBAL(defEncNs));
597 if (SOAP_GLOBAL(mem_cache)) {
598 zend_hash_destroy(SOAP_GLOBAL(mem_cache));
599 free(SOAP_GLOBAL(mem_cache));
600 }
601 UNREGISTER_INI_ENTRIES();
602 return SUCCESS;
603 }
604
PHP_RINIT_FUNCTION(soap)605 PHP_RINIT_FUNCTION(soap)
606 {
607 #if defined(COMPILE_DL_SOAP) && defined(ZTS)
608 ZEND_TSRMLS_CACHE_UPDATE();
609 #endif
610 SOAP_GLOBAL(typemap) = NULL;
611 SOAP_GLOBAL(use_soap_error_handler) = 0;
612 SOAP_GLOBAL(error_code) = NULL;
613 ZVAL_OBJ(&SOAP_GLOBAL(error_object), NULL);
614 SOAP_GLOBAL(sdl) = NULL;
615 SOAP_GLOBAL(soap_version) = SOAP_1_1;
616 SOAP_GLOBAL(encoding) = NULL;
617 SOAP_GLOBAL(class_map) = NULL;
618 SOAP_GLOBAL(features) = 0;
619 SOAP_GLOBAL(ref_map) = NULL;
620 return SUCCESS;
621 }
622
delete_sdl_res(zend_resource * res)623 static void delete_sdl_res(zend_resource *res)
624 {
625 delete_sdl(res->ptr);
626 }
627
delete_url_res(zend_resource * res)628 static void delete_url_res(zend_resource *res)
629 {
630 delete_url(res->ptr);
631 }
632
delete_service_res(zend_resource * res)633 static void delete_service_res(zend_resource *res)
634 {
635 delete_service(res->ptr);
636 }
637
delete_hashtable_res(zend_resource * res)638 static void delete_hashtable_res(zend_resource *res)
639 {
640 delete_hashtable(res->ptr);
641 }
642
PHP_MINIT_FUNCTION(soap)643 PHP_MINIT_FUNCTION(soap)
644 {
645 zend_class_entry ce;
646
647 #if defined(COMPILE_DL_SOAP) && defined(ZTS)
648 ZEND_TSRMLS_CACHE_UPDATE();
649 #endif
650 /* TODO: add ini entry for always use soap errors */
651 php_soap_prepare_globals();
652 ZEND_INIT_MODULE_GLOBALS(soap, php_soap_init_globals, NULL);
653 REGISTER_INI_ENTRIES();
654
655 /* Register SoapClient class */
656 /* BIG NOTE : THIS EMITS AN COMPILATION WARNING UNDER ZE2 - handle_function_call deprecated.
657 soap_call_function_handler should be of type struct _zend_function, not (*handle_function_call).
658 */
659 {
660 zend_internal_function fe;
661
662 fe.type = ZEND_INTERNAL_FUNCTION;
663 fe.handler = ZEND_MN(SoapClient___call);
664 fe.function_name = NULL;
665 fe.scope = NULL;
666 fe.fn_flags = 0;
667 fe.prototype = NULL;
668 fe.num_args = 2;
669 fe.arg_info = NULL;
670 zend_set_function_arg_flags((zend_function*)&fe);
671
672 INIT_OVERLOADED_CLASS_ENTRY(ce, PHP_SOAP_CLIENT_CLASSNAME, soap_client_functions,
673 (zend_function *)&fe, NULL, NULL);
674 soap_class_entry = zend_register_internal_class(&ce);
675 }
676 /* Register SoapVar class */
677 INIT_CLASS_ENTRY(ce, PHP_SOAP_VAR_CLASSNAME, soap_var_functions);
678 soap_var_class_entry = zend_register_internal_class(&ce);
679
680 /* Register SoapServer class */
681 INIT_CLASS_ENTRY(ce, PHP_SOAP_SERVER_CLASSNAME, soap_server_functions);
682 soap_server_class_entry = zend_register_internal_class(&ce);
683
684 /* Register SoapFault class */
685 INIT_CLASS_ENTRY(ce, PHP_SOAP_FAULT_CLASSNAME, soap_fault_functions);
686 soap_fault_class_entry = zend_register_internal_class_ex(&ce, zend_ce_exception);
687
688 /* Register SoapParam class */
689 INIT_CLASS_ENTRY(ce, PHP_SOAP_PARAM_CLASSNAME, soap_param_functions);
690 soap_param_class_entry = zend_register_internal_class(&ce);
691
692 INIT_CLASS_ENTRY(ce, PHP_SOAP_HEADER_CLASSNAME, soap_header_functions);
693 soap_header_class_entry = zend_register_internal_class(&ce);
694
695 le_sdl = zend_register_list_destructors_ex(delete_sdl_res, NULL, "SOAP SDL", module_number);
696 le_url = zend_register_list_destructors_ex(delete_url_res, NULL, "SOAP URL", module_number);
697 le_service = zend_register_list_destructors_ex(delete_service_res, NULL, "SOAP service", module_number);
698 le_typemap = zend_register_list_destructors_ex(delete_hashtable_res, NULL, "SOAP table", module_number);
699
700 REGISTER_LONG_CONSTANT("SOAP_1_1", SOAP_1_1, CONST_CS | CONST_PERSISTENT);
701 REGISTER_LONG_CONSTANT("SOAP_1_2", SOAP_1_2, CONST_CS | CONST_PERSISTENT);
702
703 REGISTER_LONG_CONSTANT("SOAP_PERSISTENCE_SESSION", SOAP_PERSISTENCE_SESSION, CONST_CS | CONST_PERSISTENT);
704 REGISTER_LONG_CONSTANT("SOAP_PERSISTENCE_REQUEST", SOAP_PERSISTENCE_REQUEST, CONST_CS | CONST_PERSISTENT);
705 REGISTER_LONG_CONSTANT("SOAP_FUNCTIONS_ALL", SOAP_FUNCTIONS_ALL, CONST_CS | CONST_PERSISTENT);
706
707 REGISTER_LONG_CONSTANT("SOAP_ENCODED", SOAP_ENCODED, CONST_CS | CONST_PERSISTENT);
708 REGISTER_LONG_CONSTANT("SOAP_LITERAL", SOAP_LITERAL, CONST_CS | CONST_PERSISTENT);
709
710 REGISTER_LONG_CONSTANT("SOAP_RPC", SOAP_RPC, CONST_CS | CONST_PERSISTENT);
711 REGISTER_LONG_CONSTANT("SOAP_DOCUMENT", SOAP_DOCUMENT, CONST_CS | CONST_PERSISTENT);
712
713 REGISTER_LONG_CONSTANT("SOAP_ACTOR_NEXT", SOAP_ACTOR_NEXT, CONST_CS | CONST_PERSISTENT);
714 REGISTER_LONG_CONSTANT("SOAP_ACTOR_NONE", SOAP_ACTOR_NONE, CONST_CS | CONST_PERSISTENT);
715 REGISTER_LONG_CONSTANT("SOAP_ACTOR_UNLIMATERECEIVER", SOAP_ACTOR_UNLIMATERECEIVER, CONST_CS | CONST_PERSISTENT);
716
717 REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_ACCEPT", SOAP_COMPRESSION_ACCEPT, CONST_CS | CONST_PERSISTENT);
718 REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_GZIP", SOAP_COMPRESSION_GZIP, CONST_CS | CONST_PERSISTENT);
719 REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_DEFLATE", SOAP_COMPRESSION_DEFLATE, CONST_CS | CONST_PERSISTENT);
720
721 REGISTER_LONG_CONSTANT("SOAP_AUTHENTICATION_BASIC", SOAP_AUTHENTICATION_BASIC, CONST_CS | CONST_PERSISTENT);
722 REGISTER_LONG_CONSTANT("SOAP_AUTHENTICATION_DIGEST", SOAP_AUTHENTICATION_DIGEST, CONST_CS | CONST_PERSISTENT);
723
724 REGISTER_LONG_CONSTANT("UNKNOWN_TYPE", UNKNOWN_TYPE, CONST_CS | CONST_PERSISTENT);
725
726 REGISTER_LONG_CONSTANT("XSD_STRING", XSD_STRING, CONST_CS | CONST_PERSISTENT);
727 REGISTER_LONG_CONSTANT("XSD_BOOLEAN", XSD_BOOLEAN, CONST_CS | CONST_PERSISTENT);
728 REGISTER_LONG_CONSTANT("XSD_DECIMAL", XSD_DECIMAL, CONST_CS | CONST_PERSISTENT);
729 REGISTER_LONG_CONSTANT("XSD_FLOAT", XSD_FLOAT, CONST_CS | CONST_PERSISTENT);
730 REGISTER_LONG_CONSTANT("XSD_DOUBLE", XSD_DOUBLE, CONST_CS | CONST_PERSISTENT);
731 REGISTER_LONG_CONSTANT("XSD_DURATION", XSD_DURATION, CONST_CS | CONST_PERSISTENT);
732 REGISTER_LONG_CONSTANT("XSD_DATETIME", XSD_DATETIME, CONST_CS | CONST_PERSISTENT);
733 REGISTER_LONG_CONSTANT("XSD_TIME", XSD_TIME, CONST_CS | CONST_PERSISTENT);
734 REGISTER_LONG_CONSTANT("XSD_DATE", XSD_DATE, CONST_CS | CONST_PERSISTENT);
735 REGISTER_LONG_CONSTANT("XSD_GYEARMONTH", XSD_GYEARMONTH, CONST_CS | CONST_PERSISTENT);
736 REGISTER_LONG_CONSTANT("XSD_GYEAR", XSD_GYEAR, CONST_CS | CONST_PERSISTENT);
737 REGISTER_LONG_CONSTANT("XSD_GMONTHDAY", XSD_GMONTHDAY, CONST_CS | CONST_PERSISTENT);
738 REGISTER_LONG_CONSTANT("XSD_GDAY", XSD_GDAY, CONST_CS | CONST_PERSISTENT);
739 REGISTER_LONG_CONSTANT("XSD_GMONTH", XSD_GMONTH, CONST_CS | CONST_PERSISTENT);
740 REGISTER_LONG_CONSTANT("XSD_HEXBINARY", XSD_HEXBINARY, CONST_CS | CONST_PERSISTENT);
741 REGISTER_LONG_CONSTANT("XSD_BASE64BINARY", XSD_BASE64BINARY, CONST_CS | CONST_PERSISTENT);
742 REGISTER_LONG_CONSTANT("XSD_ANYURI", XSD_ANYURI, CONST_CS | CONST_PERSISTENT);
743 REGISTER_LONG_CONSTANT("XSD_QNAME", XSD_QNAME, CONST_CS | CONST_PERSISTENT);
744 REGISTER_LONG_CONSTANT("XSD_NOTATION", XSD_NOTATION, CONST_CS | CONST_PERSISTENT);
745 REGISTER_LONG_CONSTANT("XSD_NORMALIZEDSTRING", XSD_NORMALIZEDSTRING, CONST_CS | CONST_PERSISTENT);
746 REGISTER_LONG_CONSTANT("XSD_TOKEN", XSD_TOKEN, CONST_CS | CONST_PERSISTENT);
747 REGISTER_LONG_CONSTANT("XSD_LANGUAGE", XSD_LANGUAGE, CONST_CS | CONST_PERSISTENT);
748 REGISTER_LONG_CONSTANT("XSD_NMTOKEN", XSD_NMTOKEN, CONST_CS | CONST_PERSISTENT);
749 REGISTER_LONG_CONSTANT("XSD_NAME", XSD_NAME, CONST_CS | CONST_PERSISTENT);
750 REGISTER_LONG_CONSTANT("XSD_NCNAME", XSD_NCNAME, CONST_CS | CONST_PERSISTENT);
751 REGISTER_LONG_CONSTANT("XSD_ID", XSD_ID, CONST_CS | CONST_PERSISTENT);
752 REGISTER_LONG_CONSTANT("XSD_IDREF", XSD_IDREF, CONST_CS | CONST_PERSISTENT);
753 REGISTER_LONG_CONSTANT("XSD_IDREFS", XSD_IDREFS, CONST_CS | CONST_PERSISTENT);
754 REGISTER_LONG_CONSTANT("XSD_ENTITY", XSD_ENTITY, CONST_CS | CONST_PERSISTENT);
755 REGISTER_LONG_CONSTANT("XSD_ENTITIES", XSD_ENTITIES, CONST_CS | CONST_PERSISTENT);
756 REGISTER_LONG_CONSTANT("XSD_INTEGER", XSD_INTEGER, CONST_CS | CONST_PERSISTENT);
757 REGISTER_LONG_CONSTANT("XSD_NONPOSITIVEINTEGER", XSD_NONPOSITIVEINTEGER, CONST_CS | CONST_PERSISTENT);
758 REGISTER_LONG_CONSTANT("XSD_NEGATIVEINTEGER", XSD_NEGATIVEINTEGER, CONST_CS | CONST_PERSISTENT);
759 REGISTER_LONG_CONSTANT("XSD_LONG", XSD_LONG, CONST_CS | CONST_PERSISTENT);
760 REGISTER_LONG_CONSTANT("XSD_INT", XSD_INT, CONST_CS | CONST_PERSISTENT);
761 REGISTER_LONG_CONSTANT("XSD_SHORT", XSD_SHORT, CONST_CS | CONST_PERSISTENT);
762 REGISTER_LONG_CONSTANT("XSD_BYTE", XSD_BYTE, CONST_CS | CONST_PERSISTENT);
763 REGISTER_LONG_CONSTANT("XSD_NONNEGATIVEINTEGER", XSD_NONNEGATIVEINTEGER, CONST_CS | CONST_PERSISTENT);
764 REGISTER_LONG_CONSTANT("XSD_UNSIGNEDLONG", XSD_UNSIGNEDLONG, CONST_CS | CONST_PERSISTENT);
765 REGISTER_LONG_CONSTANT("XSD_UNSIGNEDINT", XSD_UNSIGNEDINT, CONST_CS | CONST_PERSISTENT);
766 REGISTER_LONG_CONSTANT("XSD_UNSIGNEDSHORT", XSD_UNSIGNEDSHORT, CONST_CS | CONST_PERSISTENT);
767 REGISTER_LONG_CONSTANT("XSD_UNSIGNEDBYTE", XSD_UNSIGNEDBYTE, CONST_CS | CONST_PERSISTENT);
768 REGISTER_LONG_CONSTANT("XSD_POSITIVEINTEGER", XSD_POSITIVEINTEGER, CONST_CS | CONST_PERSISTENT);
769 REGISTER_LONG_CONSTANT("XSD_NMTOKENS", XSD_NMTOKENS, CONST_CS | CONST_PERSISTENT);
770 REGISTER_LONG_CONSTANT("XSD_ANYTYPE", XSD_ANYTYPE, CONST_CS | CONST_PERSISTENT);
771 REGISTER_LONG_CONSTANT("XSD_ANYXML", XSD_ANYXML, CONST_CS | CONST_PERSISTENT);
772
773 REGISTER_LONG_CONSTANT("APACHE_MAP", APACHE_MAP, CONST_CS | CONST_PERSISTENT);
774
775 REGISTER_LONG_CONSTANT("SOAP_ENC_OBJECT", SOAP_ENC_OBJECT, CONST_CS | CONST_PERSISTENT);
776 REGISTER_LONG_CONSTANT("SOAP_ENC_ARRAY", SOAP_ENC_ARRAY, CONST_CS | CONST_PERSISTENT);
777
778 REGISTER_LONG_CONSTANT("XSD_1999_TIMEINSTANT", XSD_1999_TIMEINSTANT, CONST_CS | CONST_PERSISTENT);
779
780 REGISTER_STRING_CONSTANT("XSD_NAMESPACE", XSD_NAMESPACE, CONST_CS | CONST_PERSISTENT);
781 REGISTER_STRING_CONSTANT("XSD_1999_NAMESPACE", XSD_1999_NAMESPACE, CONST_CS | CONST_PERSISTENT);
782
783 REGISTER_LONG_CONSTANT("SOAP_SINGLE_ELEMENT_ARRAYS", SOAP_SINGLE_ELEMENT_ARRAYS, CONST_CS | CONST_PERSISTENT);
784 REGISTER_LONG_CONSTANT("SOAP_WAIT_ONE_WAY_CALLS", SOAP_WAIT_ONE_WAY_CALLS, CONST_CS | CONST_PERSISTENT);
785 REGISTER_LONG_CONSTANT("SOAP_USE_XSI_ARRAY_TYPE", SOAP_USE_XSI_ARRAY_TYPE, CONST_CS | CONST_PERSISTENT);
786
787 REGISTER_LONG_CONSTANT("WSDL_CACHE_NONE", WSDL_CACHE_NONE, CONST_CS | CONST_PERSISTENT);
788 REGISTER_LONG_CONSTANT("WSDL_CACHE_DISK", WSDL_CACHE_DISK, CONST_CS | CONST_PERSISTENT);
789 REGISTER_LONG_CONSTANT("WSDL_CACHE_MEMORY", WSDL_CACHE_MEMORY, CONST_CS | CONST_PERSISTENT);
790 REGISTER_LONG_CONSTANT("WSDL_CACHE_BOTH", WSDL_CACHE_BOTH, CONST_CS | CONST_PERSISTENT);
791
792 /* New SOAP SSL Method Constants */
793 REGISTER_LONG_CONSTANT("SOAP_SSL_METHOD_TLS", SOAP_SSL_METHOD_TLS, CONST_CS | CONST_PERSISTENT);
794 REGISTER_LONG_CONSTANT("SOAP_SSL_METHOD_SSLv2", SOAP_SSL_METHOD_SSLv2, CONST_CS | CONST_PERSISTENT);
795 REGISTER_LONG_CONSTANT("SOAP_SSL_METHOD_SSLv3", SOAP_SSL_METHOD_SSLv3, CONST_CS | CONST_PERSISTENT);
796 REGISTER_LONG_CONSTANT("SOAP_SSL_METHOD_SSLv23", SOAP_SSL_METHOD_SSLv23, CONST_CS | CONST_PERSISTENT);
797
798 old_error_handler = zend_error_cb;
799 zend_error_cb = soap_error_handler;
800
801 return SUCCESS;
802 }
803
PHP_MINFO_FUNCTION(soap)804 PHP_MINFO_FUNCTION(soap)
805 {
806 php_info_print_table_start();
807 php_info_print_table_row(2, "Soap Client", "enabled");
808 php_info_print_table_row(2, "Soap Server", "enabled");
809 php_info_print_table_end();
810 DISPLAY_INI_ENTRIES();
811 }
812
813
814 /* {{{ proto object SoapParam::SoapParam ( mixed data, string name)
815 SoapParam constructor */
PHP_METHOD(SoapParam,SoapParam)816 PHP_METHOD(SoapParam, SoapParam)
817 {
818 zval *data;
819 char *name;
820 size_t name_length;
821 zval *this_ptr;
822
823 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zs", &data, &name, &name_length) == FAILURE) {
824 return;
825 }
826 if (name_length == 0) {
827 php_error_docref(NULL, E_WARNING, "Invalid parameter name");
828 return;
829 }
830
831 this_ptr = getThis();
832 add_property_stringl(this_ptr, "param_name", name, name_length);
833 add_property_zval(this_ptr, "param_data", data);
834 }
835 /* }}} */
836
837
838 /* {{{ proto object SoapHeader::SoapHeader ( string namespace, string name [, mixed data [, bool mustUnderstand [, mixed actor]]])
839 SoapHeader constructor */
PHP_METHOD(SoapHeader,SoapHeader)840 PHP_METHOD(SoapHeader, SoapHeader)
841 {
842 zval *data = NULL, *actor = NULL;
843 char *name, *ns;
844 size_t name_len, ns_len;
845 zend_bool must_understand = 0;
846 zval *this_ptr;
847
848 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|zbz", &ns, &ns_len, &name, &name_len, &data, &must_understand, &actor) == FAILURE) {
849 return;
850 }
851 if (ns_len == 0) {
852 php_error_docref(NULL, E_WARNING, "Invalid namespace");
853 return;
854 }
855 if (name_len == 0) {
856 php_error_docref(NULL, E_WARNING, "Invalid header name");
857 return;
858 }
859
860 this_ptr = getThis();
861 add_property_stringl(this_ptr, "namespace", ns, ns_len);
862 add_property_stringl(this_ptr, "name", name, name_len);
863 if (data) {
864 add_property_zval(this_ptr, "data", data);
865 }
866 add_property_bool(this_ptr, "mustUnderstand", must_understand);
867 if (actor == NULL) {
868 } else if (Z_TYPE_P(actor) == IS_LONG &&
869 (Z_LVAL_P(actor) == SOAP_ACTOR_NEXT ||
870 Z_LVAL_P(actor) == SOAP_ACTOR_NONE ||
871 Z_LVAL_P(actor) == SOAP_ACTOR_UNLIMATERECEIVER)) {
872 add_property_long(this_ptr, "actor", Z_LVAL_P(actor));
873 } else if (Z_TYPE_P(actor) == IS_STRING && Z_STRLEN_P(actor) > 0) {
874 add_property_stringl(this_ptr, "actor", Z_STRVAL_P(actor), Z_STRLEN_P(actor));
875 } else {
876 php_error_docref(NULL, E_WARNING, "Invalid actor");
877 }
878 }
879
880 /* {{{ proto object SoapFault::SoapFault ( string faultcode, string faultstring [, string faultactor [, mixed detail [, string faultname [, mixed headerfault]]]])
881 SoapFault constructor */
PHP_METHOD(SoapFault,SoapFault)882 PHP_METHOD(SoapFault, SoapFault)
883 {
884 char *fault_string = NULL, *fault_code = NULL, *fault_actor = NULL, *name = NULL, *fault_code_ns = NULL;
885 size_t fault_string_len, fault_actor_len = 0, name_len = 0, fault_code_len = 0;
886 zval *code = NULL, *details = NULL, *headerfault = NULL, *this_ptr;
887
888 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zs|s!z!s!z",
889 &code,
890 &fault_string, &fault_string_len,
891 &fault_actor, &fault_actor_len,
892 &details, &name, &name_len, &headerfault) == FAILURE) {
893 return;
894 }
895
896 if (Z_TYPE_P(code) == IS_NULL) {
897 } else if (Z_TYPE_P(code) == IS_STRING) {
898 fault_code = Z_STRVAL_P(code);
899 fault_code_len = Z_STRLEN_P(code);
900 } else if (Z_TYPE_P(code) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(code)) == 2) {
901 zval *t_ns, *t_code;
902
903 zend_hash_internal_pointer_reset(Z_ARRVAL_P(code));
904 t_ns = zend_hash_get_current_data(Z_ARRVAL_P(code));
905 zend_hash_move_forward(Z_ARRVAL_P(code));
906 t_code = zend_hash_get_current_data(Z_ARRVAL_P(code));
907 if (Z_TYPE_P(t_ns) == IS_STRING && Z_TYPE_P(t_code) == IS_STRING) {
908 fault_code_ns = Z_STRVAL_P(t_ns);
909 fault_code = Z_STRVAL_P(t_code);
910 fault_code_len = Z_STRLEN_P(t_code);
911 } else {
912 php_error_docref(NULL, E_WARNING, "Invalid fault code");
913 return;
914 }
915 } else {
916 php_error_docref(NULL, E_WARNING, "Invalid fault code");
917 return;
918 }
919 if (fault_code != NULL && fault_code_len == 0) {
920 php_error_docref(NULL, E_WARNING, "Invalid fault code");
921 return;
922 }
923 if (name != NULL && name_len == 0) {
924 name = NULL;
925 }
926
927 this_ptr = getThis();
928 set_soap_fault(this_ptr, fault_code_ns, fault_code, fault_string, fault_actor, details, name);
929 if (headerfault != NULL) {
930 add_property_zval(this_ptr, "headerfault", headerfault);
931 }
932 }
933 /* }}} */
934
935
936 /* {{{ proto object SoapFault::SoapFault ( string faultcode, string faultstring [, string faultactor [, mixed detail [, string faultname [, mixed headerfault]]]])
937 SoapFault constructor */
PHP_METHOD(SoapFault,__toString)938 PHP_METHOD(SoapFault, __toString)
939 {
940 zval *faultcode, *faultstring, *file, *line, trace, rv1, rv2, rv3, rv4;
941 zend_string *str;
942 zend_fcall_info fci;
943 zval *this_ptr;
944 zend_string *faultcode_val, *faultstring_val, *file_val;
945 zend_long line_val;
946
947 if (zend_parse_parameters_none() == FAILURE) {
948 return;
949 }
950
951 this_ptr = getThis();
952 faultcode = zend_read_property(soap_fault_class_entry, this_ptr, "faultcode", sizeof("faultcode")-1, 1, &rv1);
953 faultstring = zend_read_property(soap_fault_class_entry, this_ptr, "faultstring", sizeof("faultstring")-1, 1, &rv2);
954 file = zend_read_property(soap_fault_class_entry, this_ptr, "file", sizeof("file")-1, 1, &rv3);
955 line = zend_read_property(soap_fault_class_entry, this_ptr, "line", sizeof("line")-1, 1, &rv4);
956
957 fci.size = sizeof(fci);
958 ZVAL_STRINGL(&fci.function_name, "gettraceasstring", sizeof("gettraceasstring")-1);
959 fci.object = Z_OBJ(EX(This));
960 fci.retval = &trace;
961 fci.param_count = 0;
962 fci.params = NULL;
963 fci.no_separation = 1;
964
965 zend_call_function(&fci, NULL);
966
967 zval_ptr_dtor(&fci.function_name);
968
969 faultcode_val = zval_get_string(faultcode);
970 faultstring_val = zval_get_string(faultstring);
971 file_val = zval_get_string(file);
972 line_val = zval_get_long(line);
973 convert_to_string(&trace);
974
975 str = strpprintf(0, "SoapFault exception: [%s] %s in %s:" ZEND_LONG_FMT "\nStack trace:\n%s",
976 ZSTR_VAL(faultcode_val), ZSTR_VAL(faultstring_val), ZSTR_VAL(file_val), line_val,
977 Z_STRLEN(trace) ? Z_STRVAL(trace) : "#0 {main}\n");
978
979 zend_string_release(file_val);
980 zend_string_release(faultstring_val);
981 zend_string_release(faultcode_val);
982 zval_ptr_dtor(&trace);
983
984 RETVAL_STR(str);
985 }
986 /* }}} */
987
988 /* {{{ proto object SoapVar::SoapVar ( mixed data, int encoding [, string type_name [, string type_namespace [, string node_name [, string node_namespace]]]])
989 SoapVar constructor */
PHP_METHOD(SoapVar,SoapVar)990 PHP_METHOD(SoapVar, SoapVar)
991 {
992 zval *data, *type, *this_ptr;
993 char *stype = NULL, *ns = NULL, *name = NULL, *namens = NULL;
994 size_t stype_len = 0, ns_len = 0, name_len = 0, namens_len = 0;
995
996 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z!z|ssss", &data, &type, &stype, &stype_len, &ns, &ns_len, &name, &name_len, &namens, &namens_len) == FAILURE) {
997 return;
998 }
999
1000 this_ptr = getThis();
1001 if (Z_TYPE_P(type) == IS_NULL) {
1002 add_property_long(this_ptr, "enc_type", UNKNOWN_TYPE);
1003 } else {
1004 if (zend_hash_index_exists(&SOAP_GLOBAL(defEncIndex), Z_LVAL_P(type))) {
1005 add_property_long(this_ptr, "enc_type", Z_LVAL_P(type));
1006 } else {
1007 php_error_docref(NULL, E_WARNING, "Invalid type ID");
1008 return;
1009 }
1010 }
1011
1012 if (data) {
1013 add_property_zval(this_ptr, "enc_value", data);
1014 }
1015
1016 if (stype && stype_len > 0) {
1017 add_property_stringl(this_ptr, "enc_stype", stype, stype_len);
1018 }
1019 if (ns && ns_len > 0) {
1020 add_property_stringl(this_ptr, "enc_ns", ns, ns_len);
1021 }
1022 if (name && name_len > 0) {
1023 add_property_stringl(this_ptr, "enc_name", name, name_len);
1024 }
1025 if (namens && namens_len > 0) {
1026 add_property_stringl(this_ptr, "enc_namens", namens, namens_len);
1027 }
1028 }
1029 /* }}} */
1030
soap_create_typemap(sdlPtr sdl,HashTable * ht)1031 static HashTable* soap_create_typemap(sdlPtr sdl, HashTable *ht)
1032 {
1033 zval *tmp;
1034 HashTable *ht2;
1035 HashTable *typemap = NULL;
1036
1037 ZEND_HASH_FOREACH_VAL(ht, tmp) {
1038 char *type_name = NULL;
1039 char *type_ns = NULL;
1040 zval *to_xml = NULL;
1041 zval *to_zval = NULL;
1042 encodePtr enc, new_enc;
1043 zend_string *name;
1044
1045 if (Z_TYPE_P(tmp) != IS_ARRAY) {
1046 php_error_docref(NULL, E_WARNING, "Wrong 'typemap' option");
1047 return NULL;
1048 }
1049 ht2 = Z_ARRVAL_P(tmp);
1050
1051 ZEND_HASH_FOREACH_STR_KEY_VAL(ht2, name, tmp) {
1052 if (name) {
1053 if (ZSTR_LEN(name) == sizeof("type_name")-1 &&
1054 strncmp(ZSTR_VAL(name), "type_name", sizeof("type_name")-1) == 0) {
1055 if (Z_TYPE_P(tmp) == IS_STRING) {
1056 type_name = Z_STRVAL_P(tmp);
1057 } else if (Z_TYPE_P(tmp) != IS_NULL) {
1058 }
1059 } else if (ZSTR_LEN(name) == sizeof("type_ns")-1 &&
1060 strncmp(ZSTR_VAL(name), "type_ns", sizeof("type_ns")-1) == 0) {
1061 if (Z_TYPE_P(tmp) == IS_STRING) {
1062 type_ns = Z_STRVAL_P(tmp);
1063 } else if (Z_TYPE_P(tmp) != IS_NULL) {
1064 }
1065 } else if (ZSTR_LEN(name) == sizeof("to_xml")-1 &&
1066 strncmp(ZSTR_VAL(name), "to_xml", sizeof("to_xml")-1) == 0) {
1067 to_xml = tmp;
1068 } else if (ZSTR_LEN(name) == sizeof("from_xml")-1 &&
1069 strncmp(ZSTR_VAL(name), "from_xml", sizeof("from_xml")-1) == 0) {
1070 to_zval = tmp;
1071 }
1072 }
1073 } ZEND_HASH_FOREACH_END();
1074
1075 if (type_name) {
1076 smart_str nscat = {0};
1077
1078 if (type_ns) {
1079 enc = get_encoder(sdl, type_ns, type_name);
1080 } else {
1081 enc = get_encoder_ex(sdl, type_name, strlen(type_name));
1082 }
1083
1084 new_enc = emalloc(sizeof(encode));
1085 memset(new_enc, 0, sizeof(encode));
1086
1087 if (enc) {
1088 new_enc->details.type = enc->details.type;
1089 new_enc->details.ns = estrdup(enc->details.ns);
1090 new_enc->details.type_str = estrdup(enc->details.type_str);
1091 new_enc->details.sdl_type = enc->details.sdl_type;
1092 } else {
1093 enc = get_conversion(UNKNOWN_TYPE);
1094 new_enc->details.type = enc->details.type;
1095 if (type_ns) {
1096 new_enc->details.ns = estrdup(type_ns);
1097 }
1098 new_enc->details.type_str = estrdup(type_name);
1099 }
1100 new_enc->to_xml = enc->to_xml;
1101 new_enc->to_zval = enc->to_zval;
1102 new_enc->details.map = emalloc(sizeof(soapMapping));
1103 memset(new_enc->details.map, 0, sizeof(soapMapping));
1104 if (to_xml) {
1105 ZVAL_COPY(&new_enc->details.map->to_xml, to_xml);
1106 new_enc->to_xml = to_xml_user;
1107 } else if (enc->details.map && Z_TYPE(enc->details.map->to_xml) != IS_UNDEF) {
1108 ZVAL_COPY(&new_enc->details.map->to_xml, &enc->details.map->to_xml);
1109 }
1110 if (to_zval) {
1111 ZVAL_COPY(&new_enc->details.map->to_zval, to_zval);
1112 new_enc->to_zval = to_zval_user;
1113 } else if (enc->details.map && Z_TYPE(enc->details.map->to_zval) != IS_UNDEF) {
1114 ZVAL_COPY(&new_enc->details.map->to_zval, &enc->details.map->to_zval);
1115 }
1116 if (!typemap) {
1117 typemap = emalloc(sizeof(HashTable));
1118 zend_hash_init(typemap, 0, NULL, delete_encoder, 0);
1119 }
1120
1121 if (type_ns) {
1122 smart_str_appends(&nscat, type_ns);
1123 smart_str_appendc(&nscat, ':');
1124 }
1125 smart_str_appends(&nscat, type_name);
1126 smart_str_0(&nscat);
1127 zend_hash_update_ptr(typemap, nscat.s, new_enc);
1128 smart_str_free(&nscat);
1129 }
1130 } ZEND_HASH_FOREACH_END();
1131 return typemap;
1132 }
1133
1134
1135 /* {{{ proto object SoapServer::SoapServer ( mixed wsdl [, array options])
1136 SoapServer constructor */
PHP_METHOD(SoapServer,SoapServer)1137 PHP_METHOD(SoapServer, SoapServer)
1138 {
1139 soapServicePtr service;
1140 zval *wsdl = NULL, *options = NULL;
1141 zend_resource *res;
1142 int version = SOAP_1_1;
1143 zend_long cache_wsdl;
1144 HashTable *typemap_ht = NULL;
1145
1146 SOAP_SERVER_BEGIN_CODE();
1147
1148 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "z|a", &wsdl, &options) == FAILURE) {
1149 php_error_docref(NULL, E_ERROR, "Invalid parameters");
1150 }
1151
1152 if (Z_TYPE_P(wsdl) != IS_STRING && Z_TYPE_P(wsdl) != IS_NULL) {
1153 php_error_docref(NULL, E_ERROR, "Invalid parameters");
1154 }
1155
1156 service = emalloc(sizeof(soapService));
1157 memset(service, 0, sizeof(soapService));
1158 service->send_errors = 1;
1159
1160 cache_wsdl = SOAP_GLOBAL(cache_enabled) ? SOAP_GLOBAL(cache_mode) : 0;
1161
1162 if (options != NULL) {
1163 HashTable *ht = Z_ARRVAL_P(options);
1164 zval *tmp;
1165
1166 if ((tmp = zend_hash_str_find(ht, "soap_version", sizeof("soap_version")-1)) != NULL) {
1167 if (Z_TYPE_P(tmp) == IS_LONG &&
1168 (Z_LVAL_P(tmp) == SOAP_1_1 || Z_LVAL_P(tmp) == SOAP_1_2)) {
1169 version = Z_LVAL_P(tmp);
1170 } else {
1171 php_error_docref(NULL, E_ERROR, "'soap_version' option must be SOAP_1_1 or SOAP_1_2");
1172 }
1173 }
1174
1175 if ((tmp = zend_hash_str_find(ht, "uri", sizeof("uri")-1)) != NULL &&
1176 Z_TYPE_P(tmp) == IS_STRING) {
1177 service->uri = estrndup(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
1178 } else if (Z_TYPE_P(wsdl) == IS_NULL) {
1179 php_error_docref(NULL, E_ERROR, "'uri' option is required in nonWSDL mode");
1180 }
1181
1182 if ((tmp = zend_hash_str_find(ht, "actor", sizeof("actor")-1)) != NULL &&
1183 Z_TYPE_P(tmp) == IS_STRING) {
1184 service->actor = estrndup(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
1185 }
1186
1187 if ((tmp = zend_hash_str_find(ht, "encoding", sizeof("encoding")-1)) != NULL &&
1188 Z_TYPE_P(tmp) == IS_STRING) {
1189 xmlCharEncodingHandlerPtr encoding;
1190
1191 encoding = xmlFindCharEncodingHandler(Z_STRVAL_P(tmp));
1192 if (encoding == NULL) {
1193 php_error_docref(NULL, E_ERROR, "Invalid 'encoding' option - '%s'", Z_STRVAL_P(tmp));
1194 } else {
1195 service->encoding = encoding;
1196 }
1197 }
1198
1199 if ((tmp = zend_hash_str_find(ht, "classmap", sizeof("classmap")-1)) != NULL &&
1200 Z_TYPE_P(tmp) == IS_ARRAY) {
1201 service->class_map = zend_array_dup(Z_ARRVAL_P(tmp));
1202 }
1203
1204 if ((tmp = zend_hash_str_find(ht, "typemap", sizeof("typemap")-1)) != NULL &&
1205 Z_TYPE_P(tmp) == IS_ARRAY &&
1206 zend_hash_num_elements(Z_ARRVAL_P(tmp)) > 0) {
1207 typemap_ht = Z_ARRVAL_P(tmp);
1208 }
1209
1210 if ((tmp = zend_hash_str_find(ht, "features", sizeof("features")-1)) != NULL &&
1211 Z_TYPE_P(tmp) == IS_LONG) {
1212 service->features = Z_LVAL_P(tmp);
1213 }
1214
1215 if ((tmp = zend_hash_str_find(ht, "cache_wsdl", sizeof("cache_wsdl")-1)) != NULL &&
1216 Z_TYPE_P(tmp) == IS_LONG) {
1217 cache_wsdl = Z_LVAL_P(tmp);
1218 }
1219
1220 if ((tmp = zend_hash_str_find(ht, "send_errors", sizeof("send_errors")-1)) != NULL) {
1221 if (Z_TYPE_P(tmp) == IS_FALSE) {
1222 service->send_errors = 0;
1223 } else if (Z_TYPE_P(tmp) == IS_TRUE) {
1224 service->send_errors = 1;
1225 } else if (Z_TYPE_P(tmp) == IS_LONG) {
1226 service->send_errors = Z_LVAL_P(tmp);
1227 }
1228 }
1229
1230 } else if (Z_TYPE_P(wsdl) == IS_NULL) {
1231 php_error_docref(NULL, E_ERROR, "'uri' option is required in nonWSDL mode");
1232 }
1233
1234 service->version = version;
1235 service->type = SOAP_FUNCTIONS;
1236 service->soap_functions.functions_all = FALSE;
1237 service->soap_functions.ft = emalloc(sizeof(HashTable));
1238 zend_hash_init(service->soap_functions.ft, 0, NULL, ZVAL_PTR_DTOR, 0);
1239
1240 if (Z_TYPE_P(wsdl) != IS_NULL) {
1241 service->sdl = get_sdl(getThis(), Z_STRVAL_P(wsdl), cache_wsdl);
1242 if (service->uri == NULL) {
1243 if (service->sdl->target_ns) {
1244 service->uri = estrdup(service->sdl->target_ns);
1245 } else {
1246 /*FIXME*/
1247 service->uri = estrdup("http://unknown-uri/");
1248 }
1249 }
1250 }
1251
1252 if (typemap_ht) {
1253 service->typemap = soap_create_typemap(service->sdl, typemap_ht);
1254 }
1255
1256 res = zend_register_resource(service, le_service);
1257 add_property_resource(getThis(), "service", res);
1258
1259 SOAP_SERVER_END_CODE();
1260 }
1261 /* }}} */
1262
1263
1264 /* {{{ proto object SoapServer::setPersistence ( int mode )
1265 Sets persistence mode of SoapServer */
PHP_METHOD(SoapServer,setPersistence)1266 PHP_METHOD(SoapServer, setPersistence)
1267 {
1268 soapServicePtr service;
1269 zend_long value;
1270
1271 SOAP_SERVER_BEGIN_CODE();
1272
1273 FETCH_THIS_SERVICE(service);
1274
1275 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &value) != FAILURE) {
1276 if (service->type == SOAP_CLASS) {
1277 if (value == SOAP_PERSISTENCE_SESSION ||
1278 value == SOAP_PERSISTENCE_REQUEST) {
1279 service->soap_class.persistence = value;
1280 } else {
1281 php_error_docref(NULL, E_WARNING, "Tried to set persistence with bogus value (" ZEND_LONG_FMT ")", value);
1282 return;
1283 }
1284 } else {
1285 php_error_docref(NULL, E_WARNING, "Tried to set persistence when you are using you SOAP SERVER in function mode, no persistence needed");
1286 return;
1287 }
1288 }
1289
1290 SOAP_SERVER_END_CODE();
1291 }
1292 /* }}} */
1293
1294
1295 /* {{{ proto void SoapServer::setClass(string class_name [, mixed args])
1296 Sets class which will handle SOAP requests */
PHP_METHOD(SoapServer,setClass)1297 PHP_METHOD(SoapServer, setClass)
1298 {
1299 soapServicePtr service;
1300 zend_string *classname;
1301 zend_class_entry *ce;
1302 int num_args = 0;
1303 zval *argv = NULL;
1304
1305 SOAP_SERVER_BEGIN_CODE();
1306
1307 FETCH_THIS_SERVICE(service);
1308
1309 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S*", &classname, &argv, &num_args) == FAILURE) {
1310 return;
1311 }
1312
1313 ce = zend_lookup_class(classname);
1314
1315 if (ce) {
1316 service->type = SOAP_CLASS;
1317 service->soap_class.ce = ce;
1318
1319 service->soap_class.persistence = SOAP_PERSISTENCE_REQUEST;
1320 service->soap_class.argc = num_args;
1321 if (service->soap_class.argc > 0) {
1322 int i;
1323 service->soap_class.argv = safe_emalloc(sizeof(zval), service->soap_class.argc, 0);
1324 for (i = 0;i < service->soap_class.argc;i++) {
1325 ZVAL_COPY(&service->soap_class.argv[i], &argv[i]);
1326 }
1327 }
1328 } else {
1329 php_error_docref(NULL, E_WARNING, "Tried to set a non existent class (%s)", ZSTR_VAL(classname));
1330 return;
1331 }
1332
1333 SOAP_SERVER_END_CODE();
1334 }
1335 /* }}} */
1336
1337
1338 /* {{{ proto void SoapServer::setObject(object obj)
1339 Sets object which will handle SOAP requests */
PHP_METHOD(SoapServer,setObject)1340 PHP_METHOD(SoapServer, setObject)
1341 {
1342 soapServicePtr service;
1343 zval *obj;
1344
1345 SOAP_SERVER_BEGIN_CODE();
1346
1347 FETCH_THIS_SERVICE(service);
1348
1349 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) {
1350 return;
1351 }
1352
1353 service->type = SOAP_OBJECT;
1354
1355 ZVAL_COPY(&service->soap_object, obj);
1356
1357 SOAP_SERVER_END_CODE();
1358 }
1359 /* }}} */
1360
1361
1362 /* {{{ proto array SoapServer::getFunctions(void)
1363 Returns list of defined functions */
PHP_METHOD(SoapServer,getFunctions)1364 PHP_METHOD(SoapServer, getFunctions)
1365 {
1366 soapServicePtr service;
1367 HashTable *ft = NULL;
1368
1369 SOAP_SERVER_BEGIN_CODE();
1370
1371 if (zend_parse_parameters_none() == FAILURE) {
1372 return;
1373 }
1374
1375 FETCH_THIS_SERVICE(service);
1376
1377 array_init(return_value);
1378 if (service->type == SOAP_OBJECT) {
1379 ft = &(Z_OBJCE(service->soap_object)->function_table);
1380 } else if (service->type == SOAP_CLASS) {
1381 ft = &service->soap_class.ce->function_table;
1382 } else if (service->soap_functions.functions_all == TRUE) {
1383 ft = EG(function_table);
1384 } else if (service->soap_functions.ft != NULL) {
1385 zval *name;
1386
1387 ZEND_HASH_FOREACH_VAL(service->soap_functions.ft, name) {
1388 add_next_index_str(return_value, zend_string_copy(Z_STR_P(name)));
1389 } ZEND_HASH_FOREACH_END();
1390 }
1391 if (ft != NULL) {
1392 zend_function *f;
1393
1394 ZEND_HASH_FOREACH_PTR(ft, f) {
1395 if ((service->type != SOAP_OBJECT && service->type != SOAP_CLASS) || (f->common.fn_flags & ZEND_ACC_PUBLIC)) {
1396 add_next_index_str(return_value, zend_string_copy(f->common.function_name));
1397 }
1398 } ZEND_HASH_FOREACH_END();
1399 }
1400
1401 SOAP_SERVER_END_CODE();
1402 }
1403 /* }}} */
1404
1405
1406 /* {{{ proto void SoapServer::addFunction(mixed functions)
1407 Adds one or several functions those will handle SOAP requests */
PHP_METHOD(SoapServer,addFunction)1408 PHP_METHOD(SoapServer, addFunction)
1409 {
1410 soapServicePtr service;
1411 zval *function_name, function_copy;
1412
1413 SOAP_SERVER_BEGIN_CODE();
1414
1415 FETCH_THIS_SERVICE(service);
1416
1417 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &function_name) == FAILURE) {
1418 return;
1419 }
1420
1421 /* TODO: could use zend_is_callable here */
1422
1423 if (Z_TYPE_P(function_name) == IS_ARRAY) {
1424 if (service->type == SOAP_FUNCTIONS) {
1425 zval *tmp_function;
1426
1427 if (service->soap_functions.ft == NULL) {
1428 service->soap_functions.functions_all = FALSE;
1429 service->soap_functions.ft = emalloc(sizeof(HashTable));
1430 zend_hash_init(service->soap_functions.ft, zend_hash_num_elements(Z_ARRVAL_P(function_name)), NULL, ZVAL_PTR_DTOR, 0);
1431 }
1432
1433 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(function_name), tmp_function) {
1434 zend_string *key;
1435 zend_function *f;
1436
1437 if (Z_TYPE_P(tmp_function) != IS_STRING) {
1438 php_error_docref(NULL, E_WARNING, "Tried to add a function that isn't a string");
1439 return;
1440 }
1441
1442 key = zend_string_alloc(Z_STRLEN_P(tmp_function), 0);
1443 zend_str_tolower_copy(ZSTR_VAL(key), Z_STRVAL_P(tmp_function), Z_STRLEN_P(tmp_function));
1444
1445 if ((f = zend_hash_find_ptr(EG(function_table), key)) == NULL) {
1446 php_error_docref(NULL, E_WARNING, "Tried to add a non existent function '%s'", Z_STRVAL_P(tmp_function));
1447 return;
1448 }
1449
1450 ZVAL_STR_COPY(&function_copy, f->common.function_name);
1451 zend_hash_update(service->soap_functions.ft, key, &function_copy);
1452
1453 zend_string_release(key);
1454 } ZEND_HASH_FOREACH_END();
1455 }
1456 } else if (Z_TYPE_P(function_name) == IS_STRING) {
1457 zend_string *key;
1458 zend_function *f;
1459
1460 key = zend_string_alloc(Z_STRLEN_P(function_name), 0);
1461 zend_str_tolower_copy(ZSTR_VAL(key), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name));
1462
1463 if ((f = zend_hash_find_ptr(EG(function_table), key)) == NULL) {
1464 php_error_docref(NULL, E_WARNING, "Tried to add a non existent function '%s'", Z_STRVAL_P(function_name));
1465 return;
1466 }
1467 if (service->soap_functions.ft == NULL) {
1468 service->soap_functions.functions_all = FALSE;
1469 service->soap_functions.ft = emalloc(sizeof(HashTable));
1470 zend_hash_init(service->soap_functions.ft, 0, NULL, ZVAL_PTR_DTOR, 0);
1471 }
1472
1473 ZVAL_STR_COPY(&function_copy, f->common.function_name);
1474 zend_hash_update(service->soap_functions.ft, key, &function_copy);
1475 zend_string_release(key);
1476 } else if (Z_TYPE_P(function_name) == IS_LONG) {
1477 if (Z_LVAL_P(function_name) == SOAP_FUNCTIONS_ALL) {
1478 if (service->soap_functions.ft != NULL) {
1479 zend_hash_destroy(service->soap_functions.ft);
1480 efree(service->soap_functions.ft);
1481 service->soap_functions.ft = NULL;
1482 }
1483 service->soap_functions.functions_all = TRUE;
1484 } else {
1485 php_error_docref(NULL, E_WARNING, "Invalid value passed");
1486 return;
1487 }
1488 }
1489
1490 SOAP_SERVER_END_CODE();
1491 }
1492 /* }}} */
1493
_soap_server_exception(soapServicePtr service,sdlFunctionPtr function,zval * this_ptr)1494 static void _soap_server_exception(soapServicePtr service, sdlFunctionPtr function, zval *this_ptr) /* {{{ */
1495 {
1496 zval exception_object;
1497
1498 ZVAL_OBJ(&exception_object, EG(exception));
1499 if (instanceof_function(Z_OBJCE(exception_object), soap_fault_class_entry)) {
1500 soap_server_fault_ex(function, &exception_object, NULL);
1501 } else if (instanceof_function(Z_OBJCE(exception_object), zend_ce_error)) {
1502 if (service->send_errors) {
1503 zval rv;
1504 zend_string *msg = zval_get_string(zend_read_property(zend_ce_error, &exception_object, "message", sizeof("message")-1, 0, &rv));
1505 add_soap_fault_ex(&exception_object, this_ptr, "Server", ZSTR_VAL(msg), NULL, NULL);
1506 zend_string_release(msg);
1507 } else {
1508 add_soap_fault_ex(&exception_object, this_ptr, "Server", "Internal Error", NULL, NULL);
1509 }
1510 soap_server_fault_ex(function, &exception_object, NULL);
1511 }
1512 }
1513 /* }}} */
1514
1515 /* {{{ proto void SoapServer::handle ( [string soap_request])
1516 Handles a SOAP request */
PHP_METHOD(SoapServer,handle)1517 PHP_METHOD(SoapServer, handle)
1518 {
1519 int soap_version, old_soap_version;
1520 sdlPtr old_sdl = NULL;
1521 soapServicePtr service;
1522 xmlDocPtr doc_request=NULL, doc_return;
1523 zval function_name, *params, *soap_obj, retval;
1524 char *fn_name, cont_len[30];
1525 int num_params = 0, size, i, call_status = 0;
1526 xmlChar *buf;
1527 HashTable *function_table;
1528 soapHeader *soap_headers = NULL;
1529 sdlFunctionPtr function;
1530 char *arg = NULL;
1531 size_t arg_len = 0;
1532 xmlCharEncodingHandlerPtr old_encoding;
1533 HashTable *old_class_map, *old_typemap;
1534 int old_features;
1535 zval tmp_soap;
1536
1537 SOAP_SERVER_BEGIN_CODE();
1538
1539 FETCH_THIS_SERVICE(service);
1540 SOAP_GLOBAL(soap_version) = service->version;
1541
1542 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &arg, &arg_len) == FAILURE) {
1543 return;
1544 }
1545
1546 if (ZEND_NUM_ARGS() > 0 && ZEND_SIZE_T_INT_OVFL(arg_len)) {
1547 soap_server_fault("Server", "Input string is too long", NULL, NULL, NULL);
1548 return;
1549 }
1550
1551 if (SG(request_info).request_method &&
1552 strcmp(SG(request_info).request_method, "GET") == 0 &&
1553 SG(request_info).query_string &&
1554 stricmp(SG(request_info).query_string, "wsdl") == 0) {
1555
1556 if (service->sdl) {
1557 /*
1558 char *hdr = emalloc(sizeof("Location: ")+strlen(service->sdl->source));
1559 strcpy(hdr,"Location: ");
1560 strcat(hdr,service->sdl->source);
1561 sapi_add_header(hdr, sizeof("Location: ")+strlen(service->sdl->source)-1, 1);
1562 efree(hdr);
1563 */
1564 zval readfile, readfile_ret, param;
1565
1566 sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
1567 ZVAL_STRING(¶m, service->sdl->source);
1568 ZVAL_STRING(&readfile, "readfile");
1569 if (call_user_function(EG(function_table), NULL, &readfile, &readfile_ret, 1, ¶m ) == FAILURE) {
1570 soap_server_fault("Server", "Couldn't find WSDL", NULL, NULL, NULL);
1571 }
1572
1573 zval_ptr_dtor(¶m);
1574 zval_dtor(&readfile);
1575 zval_dtor(&readfile_ret);
1576
1577 SOAP_SERVER_END_CODE();
1578 return;
1579 } else {
1580 soap_server_fault("Server", "WSDL generation is not supported yet", NULL, NULL, NULL);
1581 /*
1582 sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8"), 1);
1583 PUTS("<?xml version=\"1.0\" ?>\n<definitions\n");
1584 PUTS(" xmlns=\"http://schemas.xmlsoap.org/wsdl/\"\n");
1585 PUTS(" targetNamespace=\"");
1586 PUTS(service->uri);
1587 PUTS("\">\n");
1588 PUTS("</definitions>");
1589 */
1590 SOAP_SERVER_END_CODE();
1591 return;
1592 }
1593 }
1594
1595 ZVAL_NULL(&retval);
1596
1597 if (php_output_start_default() != SUCCESS) {
1598 php_error_docref(NULL, E_ERROR,"ob_start failed");
1599 }
1600
1601 if (ZEND_NUM_ARGS() == 0) {
1602 if (SG(request_info).request_body && 0 == php_stream_rewind(SG(request_info).request_body)) {
1603 zval *server_vars, *encoding;
1604 php_stream_filter *zf = NULL;
1605 zend_string *server = zend_string_init("_SERVER", sizeof("_SERVER") - 1, 0);
1606
1607 zend_is_auto_global(server);
1608 if ((server_vars = zend_hash_find(&EG(symbol_table), server)) != NULL &&
1609 Z_TYPE_P(server_vars) == IS_ARRAY &&
1610 (encoding = zend_hash_str_find(Z_ARRVAL_P(server_vars), "HTTP_CONTENT_ENCODING", sizeof("HTTP_CONTENT_ENCODING")-1)) != NULL &&
1611 Z_TYPE_P(encoding) == IS_STRING) {
1612
1613 if (strcmp(Z_STRVAL_P(encoding),"gzip") == 0
1614 || strcmp(Z_STRVAL_P(encoding),"x-gzip") == 0
1615 || strcmp(Z_STRVAL_P(encoding),"deflate") == 0
1616 ) {
1617 zval filter_params;
1618
1619 array_init_size(&filter_params, 1);
1620 add_assoc_long_ex(&filter_params, "window", sizeof("window")-1, 0x2f); /* ANY WBITS */
1621
1622 zf = php_stream_filter_create("zlib.inflate", &filter_params, 0);
1623 zval_dtor(&filter_params);
1624
1625 if (zf) {
1626 php_stream_filter_append(&SG(request_info).request_body->readfilters, zf);
1627 } else {
1628 php_error_docref(NULL, E_WARNING,"Can't uncompress compressed request");
1629 zend_string_release(server);
1630 return;
1631 }
1632 } else {
1633 php_error_docref(NULL, E_WARNING,"Request is compressed with unknown compression '%s'",Z_STRVAL_P(encoding));
1634 zend_string_release(server);
1635 return;
1636 }
1637 }
1638 zend_string_release(server);
1639
1640 doc_request = soap_xmlParseFile("php://input");
1641
1642 if (zf) {
1643 php_stream_filter_remove(zf, 1);
1644 }
1645 } else {
1646 zval_ptr_dtor(&retval);
1647 return;
1648 }
1649 } else {
1650 doc_request = soap_xmlParseMemory(arg,arg_len);
1651 }
1652
1653 if (doc_request == NULL) {
1654 soap_server_fault("Client", "Bad Request", NULL, NULL, NULL);
1655 }
1656 if (xmlGetIntSubset(doc_request) != NULL) {
1657 xmlNodePtr env = get_node(doc_request->children,"Envelope");
1658 if (env && env->ns) {
1659 if (strcmp((char*)env->ns->href, SOAP_1_1_ENV_NAMESPACE) == 0) {
1660 SOAP_GLOBAL(soap_version) = SOAP_1_1;
1661 } else if (strcmp((char*)env->ns->href,SOAP_1_2_ENV_NAMESPACE) == 0) {
1662 SOAP_GLOBAL(soap_version) = SOAP_1_2;
1663 }
1664 }
1665 xmlFreeDoc(doc_request);
1666 soap_server_fault("Server", "DTD are not supported by SOAP", NULL, NULL, NULL);
1667 }
1668
1669 old_sdl = SOAP_GLOBAL(sdl);
1670 SOAP_GLOBAL(sdl) = service->sdl;
1671 old_encoding = SOAP_GLOBAL(encoding);
1672 SOAP_GLOBAL(encoding) = service->encoding;
1673 old_class_map = SOAP_GLOBAL(class_map);
1674 SOAP_GLOBAL(class_map) = service->class_map;
1675 old_typemap = SOAP_GLOBAL(typemap);
1676 SOAP_GLOBAL(typemap) = service->typemap;
1677 old_features = SOAP_GLOBAL(features);
1678 SOAP_GLOBAL(features) = service->features;
1679 old_soap_version = SOAP_GLOBAL(soap_version);
1680 function = deserialize_function_call(service->sdl, doc_request, service->actor, &function_name, &num_params, ¶ms, &soap_version, &soap_headers);
1681 xmlFreeDoc(doc_request);
1682
1683 if (EG(exception)) {
1684 php_output_discard();
1685 _soap_server_exception(service, function, getThis());
1686 goto fail;
1687 }
1688
1689 service->soap_headers_ptr = &soap_headers;
1690
1691 soap_obj = NULL;
1692 if (service->type == SOAP_OBJECT) {
1693 soap_obj = &service->soap_object;
1694 function_table = &((Z_OBJCE_P(soap_obj))->function_table);
1695 } else if (service->type == SOAP_CLASS) {
1696 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
1697 /* If persistent then set soap_obj from from the previous created session (if available) */
1698 if (service->soap_class.persistence == SOAP_PERSISTENCE_SESSION) {
1699 zval *session_vars, *tmp_soap_p;
1700
1701 if (PS(session_status) != php_session_active &&
1702 PS(session_status) != php_session_disabled) {
1703 php_session_start();
1704 }
1705
1706 /* Find the soap object and assign */
1707 session_vars = &PS(http_session_vars);
1708 ZVAL_DEREF(session_vars);
1709 if (Z_TYPE_P(session_vars) == IS_ARRAY &&
1710 (tmp_soap_p = zend_hash_str_find(Z_ARRVAL_P(session_vars), "_bogus_session_name", sizeof("_bogus_session_name")-1)) != NULL &&
1711 Z_TYPE_P(tmp_soap_p) == IS_OBJECT &&
1712 Z_OBJCE_P(tmp_soap_p) == service->soap_class.ce) {
1713 soap_obj = tmp_soap_p;
1714 }
1715 }
1716 #endif
1717 /* If new session or something weird happned */
1718 if (soap_obj == NULL) {
1719
1720 object_init_ex(&tmp_soap, service->soap_class.ce);
1721
1722 /* Call constructor */
1723 if (zend_hash_str_exists(&Z_OBJCE(tmp_soap)->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1)) {
1724 zval c_ret, constructor;
1725
1726 ZVAL_STRING(&constructor, ZEND_CONSTRUCTOR_FUNC_NAME);
1727 if (call_user_function(NULL, &tmp_soap, &constructor, &c_ret, service->soap_class.argc, service->soap_class.argv) == FAILURE) {
1728 php_error_docref(NULL, E_ERROR, "Error calling constructor");
1729 }
1730 if (EG(exception)) {
1731 php_output_discard();
1732 _soap_server_exception(service, function, getThis());
1733 zval_dtor(&constructor);
1734 zval_dtor(&c_ret);
1735 zval_ptr_dtor(&tmp_soap);
1736 goto fail;
1737 }
1738 zval_dtor(&constructor);
1739 zval_dtor(&c_ret);
1740 } else {
1741 int class_name_len = ZSTR_LEN(service->soap_class.ce->name);
1742 char *class_name = emalloc(class_name_len+1);
1743
1744 memcpy(class_name, ZSTR_VAL(service->soap_class.ce->name), class_name_len+1);
1745 if (zend_hash_str_exists(&Z_OBJCE(tmp_soap)->function_table, php_strtolower(class_name, class_name_len), class_name_len)) {
1746 zval c_ret, constructor;
1747
1748 ZVAL_STR_COPY(&constructor, service->soap_class.ce->name);
1749 if (call_user_function(NULL, &tmp_soap, &constructor, &c_ret, service->soap_class.argc, service->soap_class.argv) == FAILURE) {
1750 php_error_docref(NULL, E_ERROR, "Error calling constructor");
1751 }
1752
1753 if (EG(exception)) {
1754 php_output_discard();
1755 _soap_server_exception(service, function, getThis());
1756 zval_dtor(&constructor);
1757 zval_dtor(&c_ret);
1758 efree(class_name);
1759 zval_ptr_dtor(&tmp_soap);
1760 goto fail;
1761 }
1762
1763 zval_dtor(&constructor);
1764 zval_dtor(&c_ret);
1765 }
1766 efree(class_name);
1767 }
1768 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
1769 /* If session then update session hash with new object */
1770 if (service->soap_class.persistence == SOAP_PERSISTENCE_SESSION) {
1771 zval *session_vars = &PS(http_session_vars), *tmp_soap_p;
1772
1773 ZVAL_DEREF(session_vars);
1774 if (Z_TYPE_P(session_vars) == IS_ARRAY &&
1775 (tmp_soap_p = zend_hash_str_update(Z_ARRVAL_P(session_vars), "_bogus_session_name", sizeof("_bogus_session_name")-1, &tmp_soap)) != NULL) {
1776 soap_obj = tmp_soap_p;
1777 } else {
1778 soap_obj = &tmp_soap;
1779 }
1780 } else {
1781 soap_obj = &tmp_soap;
1782 }
1783 #else
1784 soap_obj = &tmp_soap;
1785 #endif
1786
1787 }
1788 function_table = &((Z_OBJCE_P(soap_obj))->function_table);
1789 } else {
1790 if (service->soap_functions.functions_all == TRUE) {
1791 function_table = EG(function_table);
1792 } else {
1793 function_table = service->soap_functions.ft;
1794 }
1795 }
1796
1797 doc_return = NULL;
1798
1799 /* Process soap headers */
1800 if (soap_headers != NULL) {
1801 soapHeader *header = soap_headers;
1802 while (header != NULL) {
1803 soapHeader *h = header;
1804
1805 header = header->next;
1806 #if 0
1807 if (service->sdl && !h->function && !h->hdr) {
1808 if (h->mustUnderstand) {
1809 soap_server_fault("MustUnderstand","Header not understood", NULL, NULL, NULL);
1810 } else {
1811 continue;
1812 }
1813 }
1814 #endif
1815 fn_name = estrndup(Z_STRVAL(h->function_name),Z_STRLEN(h->function_name));
1816 if (zend_hash_str_exists(function_table, php_strtolower(fn_name, Z_STRLEN(h->function_name)), Z_STRLEN(h->function_name)) ||
1817 ((service->type == SOAP_CLASS || service->type == SOAP_OBJECT) &&
1818 zend_hash_str_exists(function_table, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
1819 if (service->type == SOAP_CLASS || service->type == SOAP_OBJECT) {
1820 call_status = call_user_function(NULL, soap_obj, &h->function_name, &h->retval, h->num_params, h->parameters);
1821 } else {
1822 call_status = call_user_function(EG(function_table), NULL, &h->function_name, &h->retval, h->num_params, h->parameters);
1823 }
1824 if (call_status != SUCCESS) {
1825 php_error_docref(NULL, E_WARNING, "Function '%s' call failed", Z_STRVAL(h->function_name));
1826 return;
1827 }
1828 if (Z_TYPE(h->retval) == IS_OBJECT &&
1829 instanceof_function(Z_OBJCE(h->retval), soap_fault_class_entry)) {
1830 zval *tmp;
1831
1832 if ((tmp = zend_hash_str_find(Z_OBJPROP(h->retval), "headerfault", sizeof("headerfault")-1)) != NULL &&
1833 Z_TYPE_P(tmp) != IS_NULL) {
1834 }
1835 php_output_discard();
1836 soap_server_fault_ex(function, &h->retval, h);
1837 efree(fn_name);
1838 if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj);}
1839 goto fail;
1840 } else if (EG(exception)) {
1841 php_output_discard();
1842 _soap_server_exception(service, function, getThis());
1843 efree(fn_name);
1844 if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj);}
1845 goto fail;
1846 }
1847 } else if (h->mustUnderstand) {
1848 soap_server_fault("MustUnderstand","Header not understood", NULL, NULL, NULL);
1849 }
1850 efree(fn_name);
1851 }
1852 }
1853
1854 fn_name = estrndup(Z_STRVAL(function_name),Z_STRLEN(function_name));
1855 if (zend_hash_str_exists(function_table, php_strtolower(fn_name, Z_STRLEN(function_name)), Z_STRLEN(function_name)) ||
1856 ((service->type == SOAP_CLASS || service->type == SOAP_OBJECT) &&
1857 zend_hash_str_exists(function_table, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
1858 if (service->type == SOAP_CLASS || service->type == SOAP_OBJECT) {
1859 call_status = call_user_function(NULL, soap_obj, &function_name, &retval, num_params, params);
1860 if (service->type == SOAP_CLASS) {
1861 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
1862 if (service->soap_class.persistence != SOAP_PERSISTENCE_SESSION) {
1863 zval_ptr_dtor(soap_obj);
1864 soap_obj = NULL;
1865 }
1866 #else
1867 zval_ptr_dtor(soap_obj);
1868 soap_obj = NULL;
1869 #endif
1870 }
1871 } else {
1872 call_status = call_user_function(EG(function_table), NULL, &function_name, &retval, num_params, params);
1873 }
1874 } else {
1875 php_error(E_ERROR, "Function '%s' doesn't exist", Z_STRVAL(function_name));
1876 }
1877 efree(fn_name);
1878
1879 if (EG(exception)) {
1880 php_output_discard();
1881 _soap_server_exception(service, function, getThis());
1882 if (service->type == SOAP_CLASS) {
1883 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
1884 if (soap_obj && service->soap_class.persistence != SOAP_PERSISTENCE_SESSION) {
1885 #else
1886 if (soap_obj) {
1887 #endif
1888 zval_ptr_dtor(soap_obj);
1889 }
1890 }
1891 goto fail;
1892 }
1893
1894 if (call_status == SUCCESS) {
1895 char *response_name;
1896
1897 if (Z_TYPE(retval) == IS_OBJECT &&
1898 instanceof_function(Z_OBJCE(retval), soap_fault_class_entry)) {
1899 php_output_discard();
1900 soap_server_fault_ex(function, &retval, NULL);
1901 goto fail;
1902 }
1903
1904 if (function && function->responseName) {
1905 response_name = estrdup(function->responseName);
1906 } else {
1907 response_name = emalloc(Z_STRLEN(function_name) + sizeof("Response"));
1908 memcpy(response_name,Z_STRVAL(function_name),Z_STRLEN(function_name));
1909 memcpy(response_name+Z_STRLEN(function_name),"Response",sizeof("Response"));
1910 }
1911 doc_return = serialize_response_call(function, response_name, service->uri, &retval, soap_headers, soap_version);
1912 efree(response_name);
1913 } else {
1914 php_error_docref(NULL, E_WARNING, "Function '%s' call failed", Z_STRVAL(function_name));
1915 return;
1916 }
1917
1918 if (EG(exception)) {
1919 php_output_discard();
1920 _soap_server_exception(service, function, getThis());
1921 if (service->type == SOAP_CLASS) {
1922 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
1923 if (soap_obj && service->soap_class.persistence != SOAP_PERSISTENCE_SESSION) {
1924 #else
1925 if (soap_obj) {
1926 #endif
1927 zval_ptr_dtor(soap_obj);
1928 }
1929 }
1930 goto fail;
1931 }
1932
1933 /* Flush buffer */
1934 php_output_discard();
1935
1936 if (doc_return) {
1937 /* xmlDocDumpMemoryEnc(doc_return, &buf, &size, XML_CHAR_ENCODING_UTF8); */
1938 xmlDocDumpMemory(doc_return, &buf, &size);
1939
1940 if (size == 0) {
1941 php_error_docref(NULL, E_ERROR, "Dump memory failed");
1942 }
1943
1944 if (soap_version == SOAP_1_2) {
1945 sapi_add_header("Content-Type: application/soap+xml; charset=utf-8", sizeof("Content-Type: application/soap+xml; charset=utf-8")-1, 1);
1946 } else {
1947 sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
1948 }
1949
1950 xmlFreeDoc(doc_return);
1951
1952 if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0)) {
1953 sapi_add_header("Connection: close", sizeof("Connection: close")-1, 1);
1954 } else {
1955 snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", size);
1956 sapi_add_header(cont_len, strlen(cont_len), 1);
1957 }
1958 php_write(buf, size);
1959 xmlFree(buf);
1960 } else {
1961 sapi_add_header("HTTP/1.1 202 Accepted", sizeof("HTTP/1.1 202 Accepted")-1, 1);
1962 sapi_add_header("Content-Length: 0", sizeof("Content-Length: 0")-1, 1);
1963 }
1964
1965 fail:
1966 SOAP_GLOBAL(soap_version) = old_soap_version;
1967 SOAP_GLOBAL(encoding) = old_encoding;
1968 SOAP_GLOBAL(sdl) = old_sdl;
1969 SOAP_GLOBAL(class_map) = old_class_map;
1970 SOAP_GLOBAL(typemap) = old_typemap;
1971 SOAP_GLOBAL(features) = old_features;
1972
1973 /* Free soap headers */
1974 zval_ptr_dtor(&retval);
1975 while (soap_headers != NULL) {
1976 soapHeader *h = soap_headers;
1977 int i;
1978
1979 soap_headers = soap_headers->next;
1980 if (h->parameters) {
1981 i = h->num_params;
1982 while (i > 0) {
1983 zval_ptr_dtor(&h->parameters[--i]);
1984 }
1985 efree(h->parameters);
1986 }
1987 zval_dtor(&h->function_name);
1988 zval_dtor(&h->retval);
1989 efree(h);
1990 }
1991 service->soap_headers_ptr = NULL;
1992
1993 /* Free Memory */
1994 if (num_params > 0) {
1995 for (i = 0; i < num_params;i++) {
1996 zval_ptr_dtor(¶ms[i]);
1997 }
1998 efree(params);
1999 }
2000 zval_dtor(&function_name);
2001
2002 SOAP_SERVER_END_CODE();
2003 }
2004 /* }}} */
2005
2006
2007 /* {{{ proto SoapServer::fault ( staring code, string string [, string actor [, mixed details [, string name]]] )
2008 Issue SoapFault indicating an error */
2009 PHP_METHOD(SoapServer, fault)
2010 {
2011 char *code, *string, *actor=NULL, *name=NULL;
2012 size_t code_len, string_len, actor_len = 0, name_len = 0;
2013 zval* details = NULL;
2014 soapServicePtr service;
2015 xmlCharEncodingHandlerPtr old_encoding;
2016
2017 SOAP_SERVER_BEGIN_CODE();
2018 FETCH_THIS_SERVICE(service);
2019 old_encoding = SOAP_GLOBAL(encoding);
2020 SOAP_GLOBAL(encoding) = service->encoding;
2021
2022 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|szs",
2023 &code, &code_len, &string, &string_len, &actor, &actor_len, &details,
2024 &name, &name_len) == FAILURE) {
2025 return;
2026 }
2027
2028 soap_server_fault(code, string, actor, details, name);
2029
2030 SOAP_GLOBAL(encoding) = old_encoding;
2031 SOAP_SERVER_END_CODE();
2032 }
2033 /* }}} */
2034
2035 PHP_METHOD(SoapServer, addSoapHeader)
2036 {
2037 soapServicePtr service;
2038 zval *fault;
2039 soapHeader **p;
2040
2041 SOAP_SERVER_BEGIN_CODE();
2042
2043 FETCH_THIS_SERVICE(service);
2044
2045 if (!service || !service->soap_headers_ptr) {
2046 php_error_docref(NULL, E_WARNING, "The SoapServer::addSoapHeader function may be called only during SOAP request processing");
2047 return;
2048 }
2049
2050 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &fault, soap_header_class_entry) == FAILURE) {
2051 return;
2052 }
2053
2054 p = service->soap_headers_ptr;
2055 while (*p != NULL) {
2056 p = &(*p)->next;
2057 }
2058 *p = emalloc(sizeof(soapHeader));
2059 memset(*p, 0, sizeof(soapHeader));
2060 ZVAL_NULL(&(*p)->function_name);
2061 (*p)->retval = *fault;
2062 zval_copy_ctor(&(*p)->retval);
2063
2064 SOAP_SERVER_END_CODE();
2065 }
2066
2067 static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeader *hdr)
2068 {
2069 int soap_version;
2070 xmlChar *buf;
2071 char cont_len[30];
2072 int size;
2073 xmlDocPtr doc_return;
2074 zval *agent_name;
2075 int use_http_error_status = 1;
2076
2077 soap_version = SOAP_GLOBAL(soap_version);
2078
2079 doc_return = serialize_response_call(function, NULL, NULL, fault, hdr, soap_version);
2080
2081 xmlDocDumpMemory(doc_return, &buf, &size);
2082
2083 if ((Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY || zend_is_auto_global_str(ZEND_STRL("_SERVER"))) &&
2084 (agent_name = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT")-1)) != NULL &&
2085 Z_TYPE_P(agent_name) == IS_STRING) {
2086 if (strncmp(Z_STRVAL_P(agent_name), "Shockwave Flash", sizeof("Shockwave Flash")-1) == 0) {
2087 use_http_error_status = 0;
2088 }
2089 }
2090 /*
2091 Want to return HTTP 500 but apache wants to over write
2092 our fault code with their own handling... Figure this out later
2093 */
2094 if (use_http_error_status) {
2095 sapi_add_header("HTTP/1.1 500 Internal Service Error", sizeof("HTTP/1.1 500 Internal Service Error")-1, 1);
2096 }
2097 if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0)) {
2098 sapi_add_header("Connection: close", sizeof("Connection: close")-1, 1);
2099 } else {
2100 snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", size);
2101 sapi_add_header(cont_len, strlen(cont_len), 1);
2102 }
2103 if (soap_version == SOAP_1_2) {
2104 sapi_add_header("Content-Type: application/soap+xml; charset=utf-8", sizeof("Content-Type: application/soap+xml; charset=utf-8")-1, 1);
2105 } else {
2106 sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
2107 }
2108
2109 php_write(buf, size);
2110
2111 xmlFreeDoc(doc_return);
2112 xmlFree(buf);
2113 zend_clear_exception();
2114 }
2115
2116 static void soap_server_fault(char* code, char* string, char *actor, zval* details, char* name)
2117 {
2118 zval ret;
2119
2120 ZVAL_NULL(&ret);
2121 set_soap_fault(&ret, NULL, code, string, actor, details, name);
2122 /* TODO: Which function */
2123 soap_server_fault_ex(NULL, &ret, NULL);
2124 zend_bailout();
2125 }
2126
2127 static void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args)
2128 {
2129 zend_bool _old_in_compilation;
2130 zend_execute_data *_old_current_execute_data;
2131 int _old_http_response_code;
2132 char *_old_http_status_line;
2133
2134 _old_in_compilation = CG(in_compilation);
2135 _old_current_execute_data = EG(current_execute_data);
2136 _old_http_response_code = SG(sapi_headers).http_response_code;
2137 _old_http_status_line = SG(sapi_headers).http_status_line;
2138
2139 if (!PG(modules_activated) || !SOAP_GLOBAL(use_soap_error_handler) || !EG(objects_store).object_buckets) {
2140 call_old_error_handler(error_num, error_filename, error_lineno, format, args);
2141 return;
2142 }
2143
2144 if (Z_OBJ(SOAP_GLOBAL(error_object)) &&
2145 instanceof_function(Z_OBJCE(SOAP_GLOBAL(error_object)), soap_class_entry)) {
2146 zval *tmp;
2147 int use_exceptions = 0;
2148
2149 if ((tmp = zend_hash_str_find(Z_OBJPROP(SOAP_GLOBAL(error_object)), "_exceptions", sizeof("_exceptions")-1)) == NULL ||
2150 Z_TYPE_P(tmp) != IS_FALSE) {
2151 use_exceptions = 1;
2152 }
2153
2154 if ((error_num == E_USER_ERROR ||
2155 error_num == E_COMPILE_ERROR ||
2156 error_num == E_CORE_ERROR ||
2157 error_num == E_ERROR ||
2158 error_num == E_PARSE) &&
2159 use_exceptions) {
2160 zval fault;
2161 char* code = SOAP_GLOBAL(error_code);
2162 char buffer[1024];
2163 size_t buffer_len;
2164 #ifdef va_copy
2165 va_list argcopy;
2166 #endif
2167
2168 #ifdef va_copy
2169 va_copy(argcopy, args);
2170 buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, argcopy);
2171 va_end(argcopy);
2172 #else
2173 buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, args);
2174 #endif
2175 buffer[sizeof(buffer)-1]=0;
2176 if (buffer_len > sizeof(buffer) - 1 || buffer_len == (size_t)-1) {
2177 buffer_len = sizeof(buffer) - 1;
2178 }
2179
2180 if (code == NULL) {
2181 code = "Client";
2182 }
2183 add_soap_fault_ex(&fault, &SOAP_GLOBAL(error_object), code, buffer, NULL, NULL);
2184 Z_ADDREF(fault);
2185 zend_throw_exception_object(&fault);
2186 zend_bailout();
2187 } else if (!use_exceptions ||
2188 !SOAP_GLOBAL(error_code) ||
2189 strcmp(SOAP_GLOBAL(error_code),"WSDL") != 0) {
2190 /* Ignore libxml warnings during WSDL parsing */
2191 call_old_error_handler(error_num, error_filename, error_lineno, format, args);
2192 }
2193 } else {
2194 int old = PG(display_errors);
2195 int fault = 0;
2196 zval fault_obj;
2197 #ifdef va_copy
2198 va_list argcopy;
2199 #endif
2200
2201 if (error_num == E_USER_ERROR ||
2202 error_num == E_COMPILE_ERROR ||
2203 error_num == E_CORE_ERROR ||
2204 error_num == E_ERROR ||
2205 error_num == E_PARSE) {
2206
2207 char* code = SOAP_GLOBAL(error_code);
2208 char buffer[1024];
2209 zval outbuf;
2210 zval *tmp;
2211 soapServicePtr service;
2212
2213 ZVAL_UNDEF(&outbuf);
2214 if (code == NULL) {
2215 code = "Server";
2216 }
2217 if (Z_OBJ(SOAP_GLOBAL(error_object)) &&
2218 instanceof_function(Z_OBJCE(SOAP_GLOBAL(error_object)), soap_server_class_entry) &&
2219 (tmp = zend_hash_str_find(Z_OBJPROP(SOAP_GLOBAL(error_object)), "service", sizeof("service")-1)) != NULL &&
2220 (service = (soapServicePtr)zend_fetch_resource_ex(tmp, "service", le_service)) &&
2221 !service->send_errors) {
2222 strcpy(buffer, "Internal Error");
2223 } else {
2224 size_t buffer_len;
2225 zval outbuflen;
2226
2227 #ifdef va_copy
2228 va_copy(argcopy, args);
2229 buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, argcopy);
2230 va_end(argcopy);
2231 #else
2232 buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, args);
2233 #endif
2234 buffer[sizeof(buffer)-1]=0;
2235 if (buffer_len > sizeof(buffer) - 1 || buffer_len == (size_t)-1) {
2236 buffer_len = sizeof(buffer) - 1;
2237 }
2238
2239 /* Get output buffer and send as fault detials */
2240 if (php_output_get_length(&outbuflen) != FAILURE && Z_LVAL(outbuflen) != 0) {
2241 php_output_get_contents(&outbuf);
2242 }
2243 php_output_discard();
2244
2245 }
2246 ZVAL_NULL(&fault_obj);
2247 set_soap_fault(&fault_obj, NULL, code, buffer, NULL, &outbuf, NULL);
2248 fault = 1;
2249 }
2250
2251 PG(display_errors) = 0;
2252 SG(sapi_headers).http_status_line = NULL;
2253 zend_try {
2254 call_old_error_handler(error_num, error_filename, error_lineno, format, args);
2255 } zend_catch {
2256 CG(in_compilation) = _old_in_compilation;
2257 EG(current_execute_data) = _old_current_execute_data;
2258 if (SG(sapi_headers).http_status_line) {
2259 efree(SG(sapi_headers).http_status_line);
2260 }
2261 SG(sapi_headers).http_status_line = _old_http_status_line;
2262 SG(sapi_headers).http_response_code = _old_http_response_code;
2263 } zend_end_try();
2264 PG(display_errors) = old;
2265
2266 if (fault) {
2267 soap_server_fault_ex(NULL, &fault_obj, NULL);
2268 zend_bailout();
2269 }
2270 }
2271 }
2272
2273 PHP_FUNCTION(use_soap_error_handler)
2274 {
2275 zend_bool handler = 1;
2276
2277 ZVAL_BOOL(return_value, SOAP_GLOBAL(use_soap_error_handler));
2278 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &handler) == SUCCESS) {
2279 SOAP_GLOBAL(use_soap_error_handler) = handler;
2280 }
2281 }
2282
2283 PHP_FUNCTION(is_soap_fault)
2284 {
2285 zval *fault;
2286
2287 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &fault) == SUCCESS &&
2288 Z_TYPE_P(fault) == IS_OBJECT &&
2289 instanceof_function(Z_OBJCE_P(fault), soap_fault_class_entry)) {
2290 RETURN_TRUE;
2291 }
2292 RETURN_FALSE
2293 }
2294
2295 /* SoapClient functions */
2296
2297 /* {{{ proto object SoapClient::SoapClient ( mixed wsdl [, array options])
2298 SoapClient constructor */
2299 PHP_METHOD(SoapClient, SoapClient)
2300 {
2301
2302 zval *wsdl, *options = NULL;
2303 int soap_version = SOAP_1_1;
2304 php_stream_context *context = NULL;
2305 zend_long cache_wsdl;
2306 sdlPtr sdl = NULL;
2307 HashTable *typemap_ht = NULL;
2308 zval *this_ptr = getThis();
2309
2310 SOAP_CLIENT_BEGIN_CODE();
2311
2312 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "z|a", &wsdl, &options) == FAILURE) {
2313 php_error_docref(NULL, E_ERROR, "Invalid parameters");
2314 }
2315
2316 if (Z_TYPE_P(wsdl) != IS_STRING && Z_TYPE_P(wsdl) != IS_NULL) {
2317 php_error_docref(NULL, E_ERROR, "$wsdl must be string or null");
2318 }
2319
2320 cache_wsdl = SOAP_GLOBAL(cache_enabled) ? SOAP_GLOBAL(cache_mode) : 0;
2321
2322 if (options != NULL) {
2323 HashTable *ht = Z_ARRVAL_P(options);
2324 zval *tmp, tmp2;
2325
2326 if (Z_TYPE_P(wsdl) == IS_NULL) {
2327 /* Fetching non-WSDL mode options */
2328 if ((tmp = zend_hash_str_find(ht, "uri", sizeof("uri")-1)) != NULL &&
2329 Z_TYPE_P(tmp) == IS_STRING) {
2330 add_property_str(this_ptr, "uri", zend_string_copy(Z_STR_P(tmp)));
2331 } else {
2332 php_error_docref(NULL, E_ERROR, "'uri' option is required in nonWSDL mode");
2333 }
2334
2335 if ((tmp = zend_hash_str_find(ht, "style", sizeof("style")-1)) != NULL &&
2336 Z_TYPE_P(tmp) == IS_LONG &&
2337 (Z_LVAL_P(tmp) == SOAP_RPC || Z_LVAL_P(tmp) == SOAP_DOCUMENT)) {
2338 add_property_long(this_ptr, "style", Z_LVAL_P(tmp));
2339 }
2340
2341 if ((tmp = zend_hash_str_find(ht, "use", sizeof("use")-1)) != NULL &&
2342 Z_TYPE_P(tmp) == IS_LONG &&
2343 (Z_LVAL_P(tmp) == SOAP_LITERAL || Z_LVAL_P(tmp) == SOAP_ENCODED)) {
2344 add_property_long(this_ptr, "use", Z_LVAL_P(tmp));
2345 }
2346 }
2347
2348 if ((tmp = zend_hash_str_find(ht, "stream_context", sizeof("stream_context")-1)) != NULL &&
2349 Z_TYPE_P(tmp) == IS_RESOURCE) {
2350 context = php_stream_context_from_zval(tmp, 1);
2351 Z_ADDREF_P(tmp);
2352 } else {
2353 context = php_stream_context_alloc();
2354 }
2355
2356 if ((tmp = zend_hash_str_find(ht, "location", sizeof("location")-1)) != NULL &&
2357 Z_TYPE_P(tmp) == IS_STRING) {
2358 add_property_str(this_ptr, "location", zend_string_copy(Z_STR_P(tmp)));
2359 } else if (Z_TYPE_P(wsdl) == IS_NULL) {
2360 php_error_docref(NULL, E_ERROR, "'location' option is required in nonWSDL mode");
2361 }
2362
2363 if ((tmp = zend_hash_str_find(ht, "soap_version", sizeof("soap_version")-1)) != NULL) {
2364 if (Z_TYPE_P(tmp) == IS_LONG ||
2365 (Z_LVAL_P(tmp) == SOAP_1_1 && Z_LVAL_P(tmp) == SOAP_1_2)) {
2366 soap_version = Z_LVAL_P(tmp);
2367 }
2368 }
2369 if ((tmp = zend_hash_str_find(ht, "login", sizeof("login")-1)) != NULL &&
2370 Z_TYPE_P(tmp) == IS_STRING) {
2371 add_property_str(this_ptr, "_login", zend_string_copy(Z_STR_P(tmp)));
2372 if ((tmp = zend_hash_str_find(ht, "password", sizeof("password")-1)) != NULL &&
2373 Z_TYPE_P(tmp) == IS_STRING) {
2374 add_property_str(this_ptr, "_password", zend_string_copy(Z_STR_P(tmp)));
2375 }
2376 if ((tmp = zend_hash_str_find(ht, "authentication", sizeof("authentication")-1)) != NULL &&
2377 Z_TYPE_P(tmp) == IS_LONG &&
2378 Z_LVAL_P(tmp) == SOAP_AUTHENTICATION_DIGEST) {
2379 add_property_null(this_ptr, "_digest");
2380 }
2381 }
2382 if ((tmp = zend_hash_str_find(ht, "proxy_host", sizeof("proxy_host")-1)) != NULL &&
2383 Z_TYPE_P(tmp) == IS_STRING) {
2384 add_property_str(this_ptr, "_proxy_host", zend_string_copy(Z_STR_P(tmp)));
2385 if ((tmp = zend_hash_str_find(ht, "proxy_port", sizeof("proxy_port")-1)) != NULL) {
2386 if (Z_TYPE_P(tmp) != IS_LONG) {
2387 ZVAL_LONG(&tmp2, zval_get_long(tmp));
2388 tmp = &tmp2;
2389 }
2390 add_property_long(this_ptr, "_proxy_port", Z_LVAL_P(tmp));
2391 }
2392 if ((tmp = zend_hash_str_find(ht, "proxy_login", sizeof("proxy_login")-1)) != NULL &&
2393 Z_TYPE_P(tmp) == IS_STRING) {
2394 add_property_str(this_ptr, "_proxy_login", zend_string_copy(Z_STR_P(tmp)));
2395 if ((tmp = zend_hash_str_find(ht, "proxy_password", sizeof("proxy_password")-1)) != NULL &&
2396 Z_TYPE_P(tmp) == IS_STRING) {
2397 add_property_str(this_ptr, "_proxy_password", zend_string_copy(Z_STR_P(tmp)));
2398 }
2399 }
2400 }
2401 if ((tmp = zend_hash_str_find(ht, "local_cert", sizeof("local_cert")-1)) != NULL &&
2402 Z_TYPE_P(tmp) == IS_STRING) {
2403 if (!context) {
2404 context = php_stream_context_alloc();
2405 }
2406 php_stream_context_set_option(context, "ssl", "local_cert", tmp);
2407 if ((tmp = zend_hash_str_find(ht, "passphrase", sizeof("passphrase")-1)) != NULL &&
2408 Z_TYPE_P(tmp) == IS_STRING) {
2409 php_stream_context_set_option(context, "ssl", "passphrase", tmp);
2410 }
2411 }
2412 if ((tmp = zend_hash_str_find(ht, "trace", sizeof("trace")-1)) != NULL &&
2413 (Z_TYPE_P(tmp) == IS_TRUE ||
2414 (Z_TYPE_P(tmp) == IS_LONG && Z_LVAL_P(tmp) == 1))) {
2415 add_property_long(this_ptr, "trace", 1);
2416 }
2417
2418 if ((tmp = zend_hash_str_find(ht, "exceptions", sizeof("exceptions")-1)) != NULL &&
2419 (Z_TYPE_P(tmp) == IS_FALSE ||
2420 (Z_TYPE_P(tmp) == IS_LONG && Z_LVAL_P(tmp) == 0))) {
2421 add_property_bool(this_ptr, "_exceptions", 0);
2422 }
2423
2424 if ((tmp = zend_hash_str_find(ht, "compression", sizeof("compression")-1)) != NULL &&
2425 Z_TYPE_P(tmp) == IS_LONG &&
2426 zend_hash_str_exists(EG(function_table), "gzinflate", sizeof("gzinflate")-1) &&
2427 zend_hash_str_exists(EG(function_table), "gzdeflate", sizeof("gzdeflate")-1) &&
2428 zend_hash_str_exists(EG(function_table), "gzuncompress", sizeof("gzuncompress")-1) &&
2429 zend_hash_str_exists(EG(function_table), "gzcompress", sizeof("gzcompress")-1) &&
2430 zend_hash_str_exists(EG(function_table), "gzencode", sizeof("gzencode")-1)) {
2431 add_property_long(this_ptr, "compression", Z_LVAL_P(tmp));
2432 }
2433 if ((tmp = zend_hash_str_find(ht, "encoding", sizeof("encoding")-1)) != NULL &&
2434 Z_TYPE_P(tmp) == IS_STRING) {
2435 xmlCharEncodingHandlerPtr encoding;
2436
2437 encoding = xmlFindCharEncodingHandler(Z_STRVAL_P(tmp));
2438 if (encoding == NULL) {
2439 php_error_docref(NULL, E_ERROR, "Invalid 'encoding' option - '%s'", Z_STRVAL_P(tmp));
2440 } else {
2441 xmlCharEncCloseFunc(encoding);
2442 add_property_str(this_ptr, "_encoding", zend_string_copy(Z_STR_P(tmp)));
2443 }
2444 }
2445 if ((tmp = zend_hash_str_find(ht, "classmap", sizeof("classmap")-1)) != NULL &&
2446 Z_TYPE_P(tmp) == IS_ARRAY) {
2447 add_property_zval(this_ptr, "_classmap", tmp);
2448 }
2449
2450 if ((tmp = zend_hash_str_find(ht, "typemap", sizeof("typemap")-1)) != NULL &&
2451 Z_TYPE_P(tmp) == IS_ARRAY &&
2452 zend_hash_num_elements(Z_ARRVAL_P(tmp)) > 0) {
2453 typemap_ht = Z_ARRVAL_P(tmp);
2454 }
2455
2456 if ((tmp = zend_hash_str_find(ht, "features", sizeof("features")-1)) != NULL &&
2457 Z_TYPE_P(tmp) == IS_LONG) {
2458 add_property_long(this_ptr, "_features", Z_LVAL_P(tmp));
2459 }
2460
2461 if ((tmp = zend_hash_str_find(ht, "connection_timeout", sizeof("connection_timeout")-1)) != NULL) {
2462 if (Z_TYPE_P(tmp) != IS_LONG) {
2463 ZVAL_LONG(&tmp2, zval_get_long(tmp));
2464 tmp = &tmp2;
2465 }
2466 if (Z_LVAL_P(tmp) > 0) {
2467 add_property_long(this_ptr, "_connection_timeout", Z_LVAL_P(tmp));
2468 }
2469 }
2470
2471 if (context) {
2472 add_property_resource(this_ptr, "_stream_context", context->res);
2473 }
2474
2475 if ((tmp = zend_hash_str_find(ht, "cache_wsdl", sizeof("cache_wsdl")-1)) != NULL &&
2476 Z_TYPE_P(tmp) == IS_LONG) {
2477 cache_wsdl = Z_LVAL_P(tmp);
2478 }
2479
2480 if ((tmp = zend_hash_str_find(ht, "user_agent", sizeof("user_agent")-1)) != NULL &&
2481 Z_TYPE_P(tmp) == IS_STRING) {
2482 add_property_str(this_ptr, "_user_agent", zend_string_copy(Z_STR_P(tmp)));
2483 }
2484
2485 if ((tmp = zend_hash_str_find(ht, "keep_alive", sizeof("keep_alive")-1)) != NULL &&
2486 (Z_TYPE_P(tmp) == IS_FALSE ||
2487 (Z_TYPE_P(tmp) == IS_LONG && Z_LVAL_P(tmp) == 0))) {
2488 add_property_long(this_ptr, "_keep_alive", 0);
2489 }
2490
2491 if ((tmp = zend_hash_str_find(ht, "ssl_method", sizeof("ssl_method")-1)) != NULL &&
2492 Z_TYPE_P(tmp) == IS_LONG) {
2493 add_property_long(this_ptr, "_ssl_method", Z_LVAL_P(tmp));
2494 }
2495 } else if (Z_TYPE_P(wsdl) == IS_NULL) {
2496 php_error_docref(NULL, E_ERROR, "'location' and 'uri' options are required in nonWSDL mode");
2497 }
2498
2499 add_property_long(this_ptr, "_soap_version", soap_version);
2500
2501 if (Z_TYPE_P(wsdl) != IS_NULL) {
2502 int old_soap_version;
2503 zend_resource *res;
2504
2505 old_soap_version = SOAP_GLOBAL(soap_version);
2506 SOAP_GLOBAL(soap_version) = soap_version;
2507
2508 sdl = get_sdl(this_ptr, Z_STRVAL_P(wsdl), cache_wsdl);
2509 res = zend_register_resource(sdl, le_sdl);
2510
2511 add_property_resource(this_ptr, "sdl", res);
2512
2513 SOAP_GLOBAL(soap_version) = old_soap_version;
2514 }
2515
2516 if (typemap_ht) {
2517 HashTable *typemap = soap_create_typemap(sdl, typemap_ht);
2518 if (typemap) {
2519 zend_resource *res;
2520
2521 res = zend_register_resource(typemap, le_typemap);
2522 add_property_resource(this_ptr, "typemap", res);
2523 }
2524 }
2525 SOAP_CLIENT_END_CODE();
2526 }
2527 /* }}} */
2528
2529 static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *action, int version, int one_way, zval *response)
2530 {
2531 int ret = TRUE;
2532 char *buf;
2533 int buf_size;
2534 zval func;
2535 zval params[5];
2536 zval *trace;
2537 zval *fault;
2538 int _bailout = 0;
2539
2540 ZVAL_NULL(response);
2541
2542 xmlDocDumpMemory(request, (xmlChar**)&buf, &buf_size);
2543 if (!buf) {
2544 add_soap_fault(this_ptr, "HTTP", "Error build soap request", NULL, NULL);
2545 return FALSE;
2546 }
2547
2548 zend_try {
2549 if ((trace = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace")-1)) != NULL &&
2550 (Z_TYPE_P(trace) == IS_TRUE || (Z_TYPE_P(trace) == IS_LONG && Z_LVAL_P(trace) != 0))) {
2551 add_property_stringl(this_ptr, "__last_request", buf, buf_size);
2552 }
2553
2554 ZVAL_STRINGL(&func,"__doRequest",sizeof("__doRequest")-1);
2555 ZVAL_STRINGL(¶ms[0], buf, buf_size);
2556 if (location == NULL) {
2557 ZVAL_NULL(¶ms[1]);
2558 } else {
2559 ZVAL_STRING(¶ms[1], location);
2560 }
2561 if (action == NULL) {
2562 ZVAL_NULL(¶ms[2]);
2563 } else {
2564 ZVAL_STRING(¶ms[2], action);
2565 }
2566 ZVAL_LONG(¶ms[3], version);
2567 ZVAL_LONG(¶ms[4], one_way);
2568
2569 if (call_user_function(NULL, this_ptr, &func, response, 5, params) != SUCCESS) {
2570 add_soap_fault(this_ptr, "Client", "SoapClient::__doRequest() failed", NULL, NULL);
2571 ret = FALSE;
2572 } else if (Z_TYPE_P(response) != IS_STRING) {
2573 if (EG(exception) && instanceof_function(EG(exception)->ce, zend_ce_error)) {
2574 zval rv;
2575 zend_string *msg;
2576 zval exception_object;
2577
2578 ZVAL_OBJ(&exception_object, EG(exception));
2579 msg = zval_get_string(zend_read_property(zend_ce_error, &exception_object, "message", sizeof("message")-1, 0, &rv));
2580 /* change class */
2581 EG(exception)->ce = soap_fault_class_entry;
2582 set_soap_fault(&exception_object, NULL, "Client", ZSTR_VAL(msg), NULL, NULL, NULL);
2583 zend_string_release(msg);
2584 } else if ((fault = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault")-1)) == NULL) {
2585 add_soap_fault(this_ptr, "Client", "SoapClient::__doRequest() returned non string value", NULL, NULL);
2586 }
2587 ret = FALSE;
2588 } else if ((trace = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace")-1)) != NULL &&
2589 (Z_TYPE_P(trace) == IS_TRUE || (Z_TYPE_P(trace) == IS_LONG && Z_LVAL_P(trace) != 0))) {
2590 add_property_str(this_ptr, "__last_response", zend_string_copy(Z_STR_P(response)));
2591 }
2592 } zend_catch {
2593 _bailout = 1;
2594 } zend_end_try();
2595 zval_ptr_dtor(&func);
2596 zval_ptr_dtor(¶ms[4]);
2597 zval_ptr_dtor(¶ms[3]);
2598 zval_ptr_dtor(¶ms[2]);
2599 zval_ptr_dtor(¶ms[1]);
2600 zval_ptr_dtor(¶ms[0]);
2601 xmlFree(buf);
2602 if (_bailout) {
2603 zend_bailout();
2604 }
2605 if (ret && (fault = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault")-1)) != NULL) {
2606 ret = FALSE;
2607 }
2608 return ret;
2609 }
2610
2611 static void do_soap_call(zend_execute_data *execute_data,
2612 zval* this_ptr,
2613 char* function,
2614 size_t function_len,
2615 int arg_count,
2616 zval* real_args,
2617 zval* return_value,
2618 char* location,
2619 char* soap_action,
2620 char* call_uri,
2621 HashTable* soap_headers,
2622 zval* output_headers
2623 )
2624 {
2625 zval *tmp;
2626 zval *trace;
2627 sdlPtr sdl = NULL;
2628 sdlPtr old_sdl = NULL;
2629 sdlFunctionPtr fn;
2630 xmlDocPtr request = NULL;
2631 int ret = FALSE;
2632 int soap_version;
2633 zval response;
2634 xmlCharEncodingHandlerPtr old_encoding;
2635 HashTable *old_class_map;
2636 int old_features;
2637 HashTable *old_typemap, *typemap = NULL;
2638 smart_str action = {0};
2639
2640 SOAP_CLIENT_BEGIN_CODE();
2641
2642 if ((trace = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace")-1)) != NULL &&
2643 (Z_TYPE_P(trace) == IS_TRUE || (Z_TYPE_P(trace) == IS_LONG && Z_LVAL_P(trace) != 0))) {
2644 zend_hash_str_del(Z_OBJPROP_P(this_ptr), "__last_request", sizeof("__last_request")-1);
2645 zend_hash_str_del(Z_OBJPROP_P(this_ptr), "__last_response", sizeof("__last_response")-1);
2646 }
2647 if ((tmp = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "_soap_version", sizeof("_soap_version")-1)) != NULL &&
2648 Z_TYPE_P(tmp) == IS_LONG && Z_LVAL_P(tmp) == SOAP_1_2) {
2649 soap_version = SOAP_1_2;
2650 } else {
2651 soap_version = SOAP_1_1;
2652 }
2653
2654 if (location == NULL) {
2655 if ((tmp = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "location", sizeof("location")-1)) != NULL &&
2656 Z_TYPE_P(tmp) == IS_STRING) {
2657 location = Z_STRVAL_P(tmp);
2658 }
2659 }
2660
2661 if (FIND_SDL_PROPERTY(this_ptr,tmp) != NULL) {
2662 FETCH_SDL_RES(sdl,tmp);
2663 }
2664 if (FIND_TYPEMAP_PROPERTY(this_ptr,tmp) != NULL) {
2665 FETCH_TYPEMAP_RES(typemap,tmp);
2666 }
2667
2668 clear_soap_fault(this_ptr);
2669
2670 SOAP_GLOBAL(soap_version) = soap_version;
2671 old_sdl = SOAP_GLOBAL(sdl);
2672 SOAP_GLOBAL(sdl) = sdl;
2673 old_encoding = SOAP_GLOBAL(encoding);
2674 if ((tmp = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "_encoding", sizeof("_encoding")-1)) != NULL &&
2675 Z_TYPE_P(tmp) == IS_STRING) {
2676 SOAP_GLOBAL(encoding) = xmlFindCharEncodingHandler(Z_STRVAL_P(tmp));
2677 } else {
2678 SOAP_GLOBAL(encoding) = NULL;
2679 }
2680 old_class_map = SOAP_GLOBAL(class_map);
2681 if ((tmp = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "_classmap", sizeof("_classmap")-1)) != NULL &&
2682 Z_TYPE_P(tmp) == IS_ARRAY) {
2683 SOAP_GLOBAL(class_map) = Z_ARRVAL_P(tmp);
2684 } else {
2685 SOAP_GLOBAL(class_map) = NULL;
2686 }
2687 old_typemap = SOAP_GLOBAL(typemap);
2688 SOAP_GLOBAL(typemap) = typemap;
2689 old_features = SOAP_GLOBAL(features);
2690 if ((tmp = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "_features", sizeof("_features")-1)) != NULL &&
2691 Z_TYPE_P(tmp) == IS_LONG) {
2692 SOAP_GLOBAL(features) = Z_LVAL_P(tmp);
2693 } else {
2694 SOAP_GLOBAL(features) = 0;
2695 }
2696
2697 zend_try {
2698 if (sdl != NULL) {
2699 fn = get_function(sdl, function);
2700 if (fn != NULL) {
2701 sdlBindingPtr binding = fn->binding;
2702 int one_way = 0;
2703
2704 if (fn->responseName == NULL &&
2705 fn->responseParameters == NULL &&
2706 soap_headers == NULL) {
2707 one_way = 1;
2708 }
2709
2710 if (location == NULL) {
2711 location = binding->location;
2712 }
2713 if (binding->bindingType == BINDING_SOAP) {
2714 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes;
2715 request = serialize_function_call(this_ptr, fn, NULL, fnb->input.ns, real_args, arg_count, soap_version, soap_headers);
2716 ret = do_request(this_ptr, request, location, fnb->soapAction, soap_version, one_way, &response);
2717 } else {
2718 request = serialize_function_call(this_ptr, fn, NULL, sdl->target_ns, real_args, arg_count, soap_version, soap_headers);
2719 ret = do_request(this_ptr, request, location, NULL, soap_version, one_way, &response);
2720 }
2721
2722 xmlFreeDoc(request);
2723 request = NULL;
2724
2725 if (ret && Z_TYPE(response) == IS_STRING) {
2726 encode_reset_ns();
2727 ret = parse_packet_soap(this_ptr, Z_STRVAL(response), Z_STRLEN(response), fn, NULL, return_value, output_headers);
2728 encode_finish();
2729 }
2730
2731 zval_dtor(&response);
2732
2733 } else {
2734 smart_str error = {0};
2735 smart_str_appends(&error,"Function (\"");
2736 smart_str_appends(&error,function);
2737 smart_str_appends(&error,"\") is not a valid method for this service");
2738 smart_str_0(&error);
2739 add_soap_fault(this_ptr, "Client", ZSTR_VAL(error.s), NULL, NULL);
2740 smart_str_free(&error);
2741 }
2742 } else {
2743 zval *uri;
2744
2745 if ((uri = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "uri", sizeof("uri")-1)) == NULL || Z_TYPE_P(uri) != IS_STRING) {
2746 add_soap_fault(this_ptr, "Client", "Error finding \"uri\" property", NULL, NULL);
2747 } else if (location == NULL) {
2748 add_soap_fault(this_ptr, "Client", "Error could not find \"location\" property", NULL, NULL);
2749 } else {
2750 if (call_uri == NULL) {
2751 call_uri = Z_STRVAL_P(uri);
2752 }
2753 request = serialize_function_call(this_ptr, NULL, function, call_uri, real_args, arg_count, soap_version, soap_headers);
2754
2755 if (soap_action == NULL) {
2756 smart_str_appends(&action, call_uri);
2757 smart_str_appendc(&action, '#');
2758 smart_str_appends(&action, function);
2759 } else {
2760 smart_str_appends(&action, soap_action);
2761 }
2762 smart_str_0(&action);
2763
2764 ret = do_request(this_ptr, request, location, ZSTR_VAL(action.s), soap_version, 0, &response);
2765
2766 smart_str_free(&action);
2767 xmlFreeDoc(request);
2768 request = NULL;
2769
2770 if (ret && Z_TYPE(response) == IS_STRING) {
2771 encode_reset_ns();
2772 ret = parse_packet_soap(this_ptr, Z_STRVAL(response), Z_STRLEN(response), NULL, function, return_value, output_headers);
2773 encode_finish();
2774 }
2775
2776 zval_dtor(&response);
2777 }
2778 }
2779
2780 if (!ret) {
2781 zval* fault;
2782 if ((fault = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault")-1)) != NULL) {
2783 ZVAL_COPY(return_value, fault);
2784 } else {
2785 add_soap_fault_ex(return_value, this_ptr, "Client", "Unknown Error", NULL, NULL);
2786 Z_ADDREF_P(return_value);
2787 }
2788 } else {
2789 zval* fault;
2790 if ((fault = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault")-1)) != NULL) {
2791 ZVAL_COPY(return_value, fault);
2792 }
2793 }
2794
2795 if (!EG(exception) &&
2796 Z_TYPE_P(return_value) == IS_OBJECT &&
2797 instanceof_function(Z_OBJCE_P(return_value), soap_fault_class_entry) &&
2798 ((tmp = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "_exceptions", sizeof("_exceptions")-1)) == NULL ||
2799 Z_TYPE_P(tmp) != IS_FALSE)) {
2800 Z_ADDREF_P(return_value);
2801 zend_throw_exception_object(return_value);
2802 }
2803
2804 } zend_catch {
2805 _bailout = 1;
2806 } zend_end_try();
2807
2808 if (SOAP_GLOBAL(encoding) != NULL) {
2809 xmlCharEncCloseFunc(SOAP_GLOBAL(encoding));
2810 }
2811
2812 SOAP_GLOBAL(features) = old_features;
2813 SOAP_GLOBAL(typemap) = old_typemap;
2814 SOAP_GLOBAL(class_map) = old_class_map;
2815 SOAP_GLOBAL(encoding) = old_encoding;
2816 SOAP_GLOBAL(sdl) = old_sdl;
2817 if (_bailout) {
2818 smart_str_free(&action);
2819 if (request) {
2820 xmlFreeDoc(request);
2821 }
2822 _bailout = 0;
2823 zend_bailout();
2824 }
2825 SOAP_CLIENT_END_CODE();
2826 }
2827
2828 static void verify_soap_headers_array(HashTable *ht)
2829 {
2830 zval *tmp;
2831
2832 ZEND_HASH_FOREACH_VAL(ht, tmp) {
2833 if (Z_TYPE_P(tmp) != IS_OBJECT ||
2834 !instanceof_function(Z_OBJCE_P(tmp), soap_header_class_entry)) {
2835 php_error_docref(NULL, E_ERROR, "Invalid SOAP header");
2836 }
2837 } ZEND_HASH_FOREACH_END();
2838 }
2839
2840
2841 /* {{{ proto mixed SoapClient::__call ( string function_name, array arguments [, array options [, array input_headers [, array output_headers]]])
2842 Calls a SOAP function */
2843 PHP_METHOD(SoapClient, __call)
2844 {
2845 char *function, *location=NULL, *soap_action = NULL, *uri = NULL;
2846 size_t function_len;
2847 int i = 0;
2848 HashTable* soap_headers = NULL;
2849 zval *options = NULL;
2850 zval *headers = NULL;
2851 zval *output_headers = NULL;
2852 zval *args;
2853 zval *real_args = NULL;
2854 zval *param;
2855 int arg_count;
2856 zval *tmp;
2857 zend_bool free_soap_headers = 0;
2858 zval *this_ptr;
2859
2860 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sa|a!zz/",
2861 &function, &function_len, &args, &options, &headers, &output_headers) == FAILURE) {
2862 return;
2863 }
2864
2865 if (options) {
2866 HashTable *hto = Z_ARRVAL_P(options);
2867 if ((tmp = zend_hash_str_find(hto, "location", sizeof("location")-1)) != NULL &&
2868 Z_TYPE_P(tmp) == IS_STRING) {
2869 location = Z_STRVAL_P(tmp);
2870 }
2871
2872 if ((tmp = zend_hash_str_find(hto, "soapaction", sizeof("soapaction")-1)) != NULL &&
2873 Z_TYPE_P(tmp) == IS_STRING) {
2874 soap_action = Z_STRVAL_P(tmp);
2875 }
2876
2877 if ((tmp = zend_hash_str_find(hto, "uri", sizeof("uri")-1)) != NULL &&
2878 Z_TYPE_P(tmp) == IS_STRING) {
2879 uri = Z_STRVAL_P(tmp);
2880 }
2881 }
2882
2883 if (headers == NULL || Z_TYPE_P(headers) == IS_NULL) {
2884 } else if (Z_TYPE_P(headers) == IS_ARRAY) {
2885 soap_headers = Z_ARRVAL_P(headers);
2886 verify_soap_headers_array(soap_headers);
2887 free_soap_headers = 0;
2888 } else if (Z_TYPE_P(headers) == IS_OBJECT &&
2889 instanceof_function(Z_OBJCE_P(headers), soap_header_class_entry)) {
2890 soap_headers = emalloc(sizeof(HashTable));
2891 zend_hash_init(soap_headers, 0, NULL, ZVAL_PTR_DTOR, 0);
2892 zend_hash_next_index_insert(soap_headers, headers);
2893 Z_ADDREF_P(headers);
2894 free_soap_headers = 1;
2895 } else{
2896 php_error_docref(NULL, E_WARNING, "Invalid SOAP header");
2897 return;
2898 }
2899
2900 /* Add default headers */
2901 this_ptr = getThis();
2902 if ((tmp = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_headers")-1)) != NULL && Z_TYPE_P(tmp) == IS_ARRAY) {
2903 HashTable *default_headers = Z_ARRVAL_P(tmp);
2904 if (soap_headers) {
2905 if (!free_soap_headers) {
2906 soap_headers = zend_array_dup(soap_headers);
2907 free_soap_headers = 1;
2908 }
2909 ZEND_HASH_FOREACH_VAL(default_headers, tmp) {
2910 if(Z_TYPE_P(tmp) == IS_OBJECT) {
2911 Z_ADDREF_P(tmp);
2912 zend_hash_next_index_insert(soap_headers, tmp);
2913 }
2914 } ZEND_HASH_FOREACH_END();
2915 } else {
2916 soap_headers = Z_ARRVAL_P(tmp);
2917 free_soap_headers = 0;
2918 }
2919 }
2920
2921 arg_count = zend_hash_num_elements(Z_ARRVAL_P(args));
2922
2923 if (arg_count > 0) {
2924 real_args = safe_emalloc(sizeof(zval), arg_count, 0);
2925 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args), param) {
2926 /*zval_add_ref(param);*/
2927 ZVAL_DEREF(param);
2928 ZVAL_COPY_VALUE(&real_args[i], param);
2929 i++;
2930 } ZEND_HASH_FOREACH_END();
2931 }
2932 if (output_headers) {
2933 array_init(output_headers);
2934 }
2935 do_soap_call(execute_data, this_ptr, function, function_len, arg_count, real_args, return_value, location, soap_action, uri, soap_headers, output_headers);
2936 if (arg_count > 0) {
2937 efree(real_args);
2938 }
2939
2940 if (soap_headers && free_soap_headers) {
2941 zend_hash_destroy(soap_headers);
2942 efree(soap_headers);
2943 }
2944 }
2945 /* }}} */
2946
2947
2948 /* {{{ proto array SoapClient::__getFunctions ( void )
2949 Returns list of SOAP functions */
2950 PHP_METHOD(SoapClient, __getFunctions)
2951 {
2952 sdlPtr sdl;
2953
2954 FETCH_THIS_SDL(sdl);
2955
2956 if (zend_parse_parameters_none() == FAILURE) {
2957 return;
2958 }
2959
2960 if (sdl) {
2961 smart_str buf = {0};
2962 sdlFunctionPtr function;
2963
2964 array_init(return_value);
2965 ZEND_HASH_FOREACH_PTR(&sdl->functions, function) {
2966 function_to_string(function, &buf);
2967 add_next_index_stringl(return_value, ZSTR_VAL(buf.s), ZSTR_LEN(buf.s));
2968 smart_str_free(&buf);
2969 } ZEND_HASH_FOREACH_END();
2970 }
2971 }
2972 /* }}} */
2973
2974
2975 /* {{{ proto array SoapClient::__getTypes ( void )
2976 Returns list of SOAP types */
2977 PHP_METHOD(SoapClient, __getTypes)
2978 {
2979 sdlPtr sdl;
2980
2981 FETCH_THIS_SDL(sdl);
2982
2983 if (zend_parse_parameters_none() == FAILURE) {
2984 return;
2985 }
2986
2987 if (sdl) {
2988 sdlTypePtr type;
2989 smart_str buf = {0};
2990
2991 array_init(return_value);
2992 if (sdl->types) {
2993 ZEND_HASH_FOREACH_PTR(sdl->types, type) {
2994 type_to_string(type, &buf, 0);
2995 add_next_index_stringl(return_value, ZSTR_VAL(buf.s), ZSTR_LEN(buf.s));
2996 smart_str_free(&buf);
2997 } ZEND_HASH_FOREACH_END();
2998 }
2999 }
3000 }
3001 /* }}} */
3002
3003
3004 /* {{{ proto string SoapClient::__getLastRequest ( void )
3005 Returns last SOAP request */
3006 PHP_METHOD(SoapClient, __getLastRequest)
3007 {
3008 zval *tmp;
3009
3010 if (zend_parse_parameters_none() == FAILURE) {
3011 return;
3012 }
3013
3014 if ((tmp = zend_hash_str_find(Z_OBJPROP_P(getThis()), "__last_request", sizeof("__last_request")-1)) != NULL &&
3015 Z_TYPE_P(tmp) == IS_STRING) {
3016 RETURN_STR_COPY(Z_STR_P(tmp));
3017 }
3018 RETURN_NULL();
3019 }
3020 /* }}} */
3021
3022
3023 /* {{{ proto object SoapClient::__getLastResponse ( void )
3024 Returns last SOAP response */
3025 PHP_METHOD(SoapClient, __getLastResponse)
3026 {
3027 zval *tmp;
3028
3029 if (zend_parse_parameters_none() == FAILURE) {
3030 return;
3031 }
3032
3033 if ((tmp = zend_hash_str_find(Z_OBJPROP_P(getThis()), "__last_response", sizeof("__last_response")-1)) != NULL &&
3034 Z_TYPE_P(tmp) == IS_STRING) {
3035 RETURN_STR_COPY(Z_STR_P(tmp));
3036 }
3037 RETURN_NULL();
3038 }
3039 /* }}} */
3040
3041
3042 /* {{{ proto string SoapClient::__getLastRequestHeaders(void)
3043 Returns last SOAP request headers */
3044 PHP_METHOD(SoapClient, __getLastRequestHeaders)
3045 {
3046 zval *tmp;
3047
3048 if (zend_parse_parameters_none() == FAILURE) {
3049 return;
3050 }
3051
3052 if ((tmp = zend_hash_str_find(Z_OBJPROP_P(getThis()), "__last_request_headers", sizeof("__last_request_headers")-1)) != NULL &&
3053 Z_TYPE_P(tmp) == IS_STRING) {
3054 RETURN_STR_COPY(Z_STR_P(tmp));
3055 }
3056 RETURN_NULL();
3057 }
3058 /* }}} */
3059
3060
3061 /* {{{ proto string SoapClient::__getLastResponseHeaders(void)
3062 Returns last SOAP response headers */
3063 PHP_METHOD(SoapClient, __getLastResponseHeaders)
3064 {
3065 zval *tmp;
3066
3067 if (zend_parse_parameters_none() == FAILURE) {
3068 return;
3069 }
3070
3071 if ((tmp = zend_hash_str_find(Z_OBJPROP_P(getThis()), "__last_response_headers", sizeof("__last_response_headers")-1)) != NULL &&
3072 Z_TYPE_P(tmp) == IS_STRING) {
3073 RETURN_STR_COPY(Z_STR_P(tmp));
3074 }
3075 RETURN_NULL();
3076 }
3077 /* }}} */
3078
3079
3080 /* {{{ proto string SoapClient::__doRequest()
3081 SoapClient::__doRequest() */
3082 PHP_METHOD(SoapClient, __doRequest)
3083 {
3084 zend_string *buf;
3085 char *location, *action;
3086 size_t location_size, action_size;
3087 zend_long version;
3088 zend_long one_way = 0;
3089 zval *this_ptr = getThis();
3090
3091 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sssl|l",
3092 &buf,
3093 &location, &location_size,
3094 &action, &action_size,
3095 &version, &one_way) == FAILURE) {
3096 return;
3097 }
3098 if (SOAP_GLOBAL(features) & SOAP_WAIT_ONE_WAY_CALLS) {
3099 one_way = 0;
3100 }
3101 if (one_way) {
3102 if (make_http_soap_request(this_ptr, buf, location, action, version, NULL)) {
3103 RETURN_EMPTY_STRING();
3104 }
3105 } else if (make_http_soap_request(this_ptr, buf, location, action, version,
3106 return_value)) {
3107 return;
3108 }
3109 RETURN_NULL();
3110 }
3111 /* }}} */
3112
3113 /* {{{ proto void SoapClient::__setCookie(string name [, strung value])
3114 Sets cookie thet will sent with SOAP request.
3115 The call to this function will effect all following calls of SOAP methods.
3116 If value is not specified cookie is removed. */
3117 PHP_METHOD(SoapClient, __setCookie)
3118 {
3119 char *name;
3120 char *val = NULL;
3121 size_t name_len, val_len = 0;
3122 zval *cookies;
3123 zval *this_ptr = getThis();
3124
3125 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", &name, &name_len, &val, &val_len) == FAILURE) {
3126 return;
3127 }
3128
3129 if (val == NULL) {
3130 if ((cookies = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies")-1)) != NULL &&
3131 Z_TYPE_P(cookies) == IS_ARRAY) {
3132 zend_hash_str_del(Z_ARRVAL_P(cookies), name, name_len);
3133 }
3134 } else {
3135 zval zcookie;
3136
3137 if ((cookies = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies")-1)) == NULL ||
3138 Z_TYPE_P(cookies) != IS_ARRAY) {
3139 zval tmp_cookies;
3140
3141 array_init(&tmp_cookies);
3142 cookies = zend_hash_str_update(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies")-1, &tmp_cookies);
3143 }
3144
3145 array_init(&zcookie);
3146 add_index_stringl(&zcookie, 0, val, val_len);
3147 add_assoc_zval_ex(cookies, name, name_len, &zcookie);
3148 }
3149 }
3150 /* }}} */
3151
3152 /* {{{ proto array SoapClient::__getCookies ( void )
3153 Returns list of cookies */
3154 PHP_METHOD(SoapClient, __getCookies)
3155 {
3156 zval *cookies;
3157
3158 if (zend_parse_parameters_none() == FAILURE) {
3159 return;
3160 }
3161
3162
3163 if ((cookies = zend_hash_str_find(Z_OBJPROP_P(getThis()), "_cookies", sizeof("_cookies")-1)) != NULL &&
3164 Z_TYPE_P(cookies) == IS_ARRAY) {
3165 RETURN_ARR(zend_array_dup(Z_ARRVAL_P(cookies)));
3166 } else {
3167 array_init(return_value);
3168 }
3169 }
3170 /* }}} */
3171
3172 /* {{{ proto void SoapClient::__setSoapHeaders(array SoapHeaders)
3173 Sets SOAP headers for subsequent calls (replaces any previous
3174 values).
3175 If no value is specified, all of the headers are removed. */
3176 PHP_METHOD(SoapClient, __setSoapHeaders)
3177 {
3178 zval *headers = NULL;
3179 zval *this_ptr = getThis();
3180
3181 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|z", &headers) == FAILURE) {
3182 return;
3183 }
3184
3185 if (headers == NULL || Z_TYPE_P(headers) == IS_NULL) {
3186 zend_hash_str_del(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_headers")-1);
3187 } else if (Z_TYPE_P(headers) == IS_ARRAY) {
3188 verify_soap_headers_array(Z_ARRVAL_P(headers));
3189 add_property_zval(this_ptr, "__default_headers", headers);
3190 } else if (Z_TYPE_P(headers) == IS_OBJECT &&
3191 instanceof_function(Z_OBJCE_P(headers), soap_header_class_entry)) {
3192 zval default_headers;
3193
3194 array_init(&default_headers);
3195 Z_ADDREF_P(headers);
3196 add_next_index_zval(&default_headers, headers);
3197 add_property_zval(this_ptr, "__default_headers", &default_headers);
3198 Z_DELREF_P(&default_headers);
3199 } else{
3200 php_error_docref(NULL, E_WARNING, "Invalid SOAP header");
3201 }
3202 RETURN_TRUE;
3203 }
3204 /* }}} */
3205
3206
3207
3208 /* {{{ proto string SoapClient::__setLocation([string new_location])
3209 Sets the location option (the endpoint URL that will be touched by the
3210 following SOAP requests).
3211 If new_location is not specified or null then SoapClient will use endpoint
3212 from WSDL file.
3213 The function returns old value of location options. */
3214 PHP_METHOD(SoapClient, __setLocation)
3215 {
3216 char *location = NULL;
3217 size_t location_len = 0;
3218 zval *tmp;
3219 zval *this_ptr = getThis();
3220
3221 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &location, &location_len) == FAILURE) {
3222 return;
3223 }
3224
3225 if ((tmp = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "location", sizeof("location")-1)) != NULL && Z_TYPE_P(tmp) == IS_STRING) {
3226 RETVAL_STR_COPY(Z_STR_P(tmp));
3227 } else {
3228 RETVAL_NULL();
3229 }
3230
3231 if (location && location_len) {
3232 add_property_stringl(this_ptr, "location", location, location_len);
3233 } else {
3234 zend_hash_str_del(Z_OBJPROP_P(this_ptr), "location", sizeof("location")-1);
3235 }
3236 }
3237 /* }}} */
3238
3239 static void clear_soap_fault(zval *obj)
3240 {
3241 if (obj != NULL && Z_TYPE_P(obj) == IS_OBJECT) {
3242 zend_hash_str_del(Z_OBJPROP_P(obj), "__soap_fault", sizeof("__soap_fault")-1);
3243 }
3244 }
3245
3246 static void add_soap_fault_ex(zval *fault, zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail)
3247 {
3248 ZVAL_NULL(fault);
3249 set_soap_fault(fault, NULL, fault_code, fault_string, fault_actor, fault_detail, NULL);
3250 add_property_zval(obj, "__soap_fault", fault);
3251 Z_DELREF_P(fault);
3252 }
3253
3254 void add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail)
3255 {
3256 zval fault;
3257
3258 ZVAL_NULL(&fault);
3259 set_soap_fault(&fault, NULL, fault_code, fault_string, fault_actor, fault_detail, NULL);
3260 add_property_zval(obj, "__soap_fault", &fault);
3261 Z_DELREF(fault);
3262 }
3263
3264 static void set_soap_fault(zval *obj, char *fault_code_ns, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail, char *name)
3265 {
3266 if (Z_TYPE_P(obj) != IS_OBJECT) {
3267 object_init_ex(obj, soap_fault_class_entry);
3268 }
3269
3270 add_property_string(obj, "faultstring", fault_string ? fault_string : "");
3271 zend_update_property_string(zend_ce_exception, obj, "message", sizeof("message")-1, (fault_string ? fault_string : ""));
3272
3273 if (fault_code != NULL) {
3274 int soap_version = SOAP_GLOBAL(soap_version);
3275
3276 if (fault_code_ns) {
3277 add_property_string(obj, "faultcode", fault_code);
3278 add_property_string(obj, "faultcodens", fault_code_ns);
3279 } else {
3280 if (soap_version == SOAP_1_1) {
3281 add_property_string(obj, "faultcode", fault_code);
3282 if (strcmp(fault_code,"Client") == 0 ||
3283 strcmp(fault_code,"Server") == 0 ||
3284 strcmp(fault_code,"VersionMismatch") == 0 ||
3285 strcmp(fault_code,"MustUnderstand") == 0) {
3286 add_property_string(obj, "faultcodens", SOAP_1_1_ENV_NAMESPACE);
3287 }
3288 } else if (soap_version == SOAP_1_2) {
3289 if (strcmp(fault_code,"Client") == 0) {
3290 add_property_string(obj, "faultcode", "Sender");
3291 add_property_string(obj, "faultcodens", SOAP_1_2_ENV_NAMESPACE);
3292 } else if (strcmp(fault_code,"Server") == 0) {
3293 add_property_string(obj, "faultcode", "Receiver");
3294 add_property_string(obj, "faultcodens", SOAP_1_2_ENV_NAMESPACE);
3295 } else if (strcmp(fault_code,"VersionMismatch") == 0 ||
3296 strcmp(fault_code,"MustUnderstand") == 0 ||
3297 strcmp(fault_code,"DataEncodingUnknown") == 0) {
3298 add_property_string(obj, "faultcode", fault_code);
3299 add_property_string(obj, "faultcodens", SOAP_1_2_ENV_NAMESPACE);
3300 } else {
3301 add_property_string(obj, "faultcode", fault_code);
3302 }
3303 }
3304 }
3305 }
3306 if (fault_actor != NULL) {
3307 add_property_string(obj, "faultactor", fault_actor);
3308 }
3309 if (fault_detail != NULL && Z_TYPE_P(fault_detail) != IS_UNDEF) {
3310 add_property_zval(obj, "detail", fault_detail);
3311 }
3312 if (name != NULL) {
3313 add_property_string(obj, "_name", name);
3314 }
3315 }
3316
3317 static void deserialize_parameters(xmlNodePtr params, sdlFunctionPtr function, int *num_params, zval **parameters)
3318 {
3319 int cur_param = 0,num_of_params = 0;
3320 zval *tmp_parameters = NULL;
3321
3322 if (function != NULL) {
3323 sdlParamPtr param;
3324 xmlNodePtr val;
3325 int use_names = 0;
3326
3327 if (function->requestParameters == NULL) {
3328 return;
3329 }
3330 num_of_params = zend_hash_num_elements(function->requestParameters);
3331 ZEND_HASH_FOREACH_PTR(function->requestParameters, param) {
3332 if (get_node(params, param->paramName) != NULL) {
3333 use_names = 1;
3334 }
3335 } ZEND_HASH_FOREACH_END();
3336 if (use_names) {
3337 tmp_parameters = safe_emalloc(num_of_params, sizeof(zval), 0);
3338 ZEND_HASH_FOREACH_PTR(function->requestParameters, param) {
3339 val = get_node(params, param->paramName);
3340 if (!val) {
3341 /* TODO: may be "nil" is not OK? */
3342 ZVAL_NULL(&tmp_parameters[cur_param]);
3343 } else {
3344 master_to_zval(&tmp_parameters[cur_param], param->encode, val);
3345 }
3346 cur_param++;
3347 } ZEND_HASH_FOREACH_END();
3348 *parameters = tmp_parameters;
3349 *num_params = num_of_params;
3350 return;
3351 }
3352 }
3353 if (params) {
3354 xmlNodePtr trav;
3355
3356 num_of_params = 0;
3357 trav = params;
3358 while (trav != NULL) {
3359 if (trav->type == XML_ELEMENT_NODE) {
3360 num_of_params++;
3361 }
3362 trav = trav->next;
3363 }
3364
3365 if (num_of_params == 1 &&
3366 function &&
3367 function->binding &&
3368 function->binding->bindingType == BINDING_SOAP &&
3369 ((sdlSoapBindingFunctionPtr)function->bindingAttributes)->style == SOAP_DOCUMENT &&
3370 (function->requestParameters == NULL ||
3371 zend_hash_num_elements(function->requestParameters) == 0) &&
3372 strcmp((char *)params->name, function->functionName) == 0) {
3373 num_of_params = 0;
3374 } else if (num_of_params > 0) {
3375 tmp_parameters = safe_emalloc(num_of_params, sizeof(zval), 0);
3376
3377 trav = params;
3378 while (trav != 0 && cur_param < num_of_params) {
3379 if (trav->type == XML_ELEMENT_NODE) {
3380 encodePtr enc;
3381 sdlParamPtr param = NULL;
3382 if (function != NULL &&
3383 (param = zend_hash_index_find_ptr(function->requestParameters, cur_param)) == NULL) {
3384 soap_server_fault("Client", "Error cannot find parameter", NULL, NULL, NULL);
3385 }
3386 if (param == NULL) {
3387 enc = NULL;
3388 } else {
3389 enc = param->encode;
3390 }
3391 master_to_zval(&tmp_parameters[cur_param], enc, trav);
3392 cur_param++;
3393 }
3394 trav = trav->next;
3395 }
3396 }
3397 }
3398 if (num_of_params > cur_param) {
3399 soap_server_fault("Client","Missing parameter", NULL, NULL, NULL);
3400 }
3401 (*parameters) = tmp_parameters;
3402 (*num_params) = num_of_params;
3403 }
3404
3405 static sdlFunctionPtr find_function(sdlPtr sdl, xmlNodePtr func, zval* function_name)
3406 {
3407 sdlFunctionPtr function;
3408
3409 function = get_function(sdl, (char*)func->name);
3410 if (function && function->binding && function->binding->bindingType == BINDING_SOAP) {
3411 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
3412 if (fnb->style == SOAP_DOCUMENT) {
3413 if (func->children != NULL ||
3414 (function->requestParameters != NULL &&
3415 zend_hash_num_elements(function->requestParameters) > 0)) {
3416 function = NULL;
3417 }
3418 }
3419 }
3420 if (sdl != NULL && function == NULL) {
3421 function = get_doc_function(sdl, func);
3422 }
3423
3424 if (function != NULL) {
3425 ZVAL_STRING(function_name, (char *)function->functionName);
3426 } else {
3427 ZVAL_STRING(function_name, (char *)func->name);
3428 }
3429
3430 return function;
3431 }
3432
3433 static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, char* actor, zval *function_name, int *num_params, zval **parameters, int *version, soapHeader **headers)
3434 {
3435 char* envelope_ns = NULL;
3436 xmlNodePtr trav,env,head,body,func;
3437 xmlAttrPtr attr;
3438 sdlFunctionPtr function;
3439
3440 encode_reset_ns();
3441
3442 /* Get <Envelope> element */
3443 env = NULL;
3444 trav = request->children;
3445 while (trav != NULL) {
3446 if (trav->type == XML_ELEMENT_NODE) {
3447 if (env == NULL && node_is_equal_ex(trav,"Envelope",SOAP_1_1_ENV_NAMESPACE)) {
3448 env = trav;
3449 *version = SOAP_1_1;
3450 envelope_ns = SOAP_1_1_ENV_NAMESPACE;
3451 SOAP_GLOBAL(soap_version) = SOAP_1_1;
3452 } else if (env == NULL && node_is_equal_ex(trav,"Envelope",SOAP_1_2_ENV_NAMESPACE)) {
3453 env = trav;
3454 *version = SOAP_1_2;
3455 envelope_ns = SOAP_1_2_ENV_NAMESPACE;
3456 SOAP_GLOBAL(soap_version) = SOAP_1_2;
3457 } else {
3458 soap_server_fault("VersionMismatch", "Wrong Version", NULL, NULL, NULL);
3459 }
3460 }
3461 trav = trav->next;
3462 }
3463 if (env == NULL) {
3464 soap_server_fault("Client", "looks like we got XML without \"Envelope\" element", NULL, NULL, NULL);
3465 }
3466
3467 attr = env->properties;
3468 while (attr != NULL) {
3469 if (attr->ns == NULL) {
3470 soap_server_fault("Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL, NULL);
3471 } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
3472 if (*version == SOAP_1_2) {
3473 soap_server_fault("Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL, NULL);
3474 } else if (strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
3475 soap_server_fault("Client", "Unknown data encoding style", NULL, NULL, NULL);
3476 }
3477 }
3478 attr = attr->next;
3479 }
3480
3481 /* Get <Header> element */
3482 head = NULL;
3483 trav = env->children;
3484 while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
3485 trav = trav->next;
3486 }
3487 if (trav != NULL && node_is_equal_ex(trav,"Header",envelope_ns)) {
3488 head = trav;
3489 trav = trav->next;
3490 }
3491
3492 /* Get <Body> element */
3493 body = NULL;
3494 while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
3495 trav = trav->next;
3496 }
3497 if (trav != NULL && node_is_equal_ex(trav,"Body",envelope_ns)) {
3498 body = trav;
3499 trav = trav->next;
3500 }
3501 while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
3502 trav = trav->next;
3503 }
3504 if (body == NULL) {
3505 soap_server_fault("Client", "Body must be present in a SOAP envelope", NULL, NULL, NULL);
3506 }
3507 attr = body->properties;
3508 while (attr != NULL) {
3509 if (attr->ns == NULL) {
3510 if (*version == SOAP_1_2) {
3511 soap_server_fault("Client", "A SOAP Body element cannot have non Namespace qualified attributes", NULL, NULL, NULL);
3512 }
3513 } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
3514 if (*version == SOAP_1_2) {
3515 soap_server_fault("Client", "encodingStyle cannot be specified on the Body", NULL, NULL, NULL);
3516 } else if (strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
3517 soap_server_fault("Client", "Unknown data encoding style", NULL, NULL, NULL);
3518 }
3519 }
3520 attr = attr->next;
3521 }
3522
3523 if (trav != NULL && *version == SOAP_1_2) {
3524 soap_server_fault("Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL, NULL);
3525 }
3526
3527 func = NULL;
3528 trav = body->children;
3529 while (trav != NULL) {
3530 if (trav->type == XML_ELEMENT_NODE) {
3531 /*
3532 if (func != NULL) {
3533 soap_server_fault("Client", "looks like we got \"Body\" with several functions call", NULL, NULL, NULL);
3534 }
3535 */
3536 func = trav;
3537 break; /* FIXME: the rest of body is ignored */
3538 }
3539 trav = trav->next;
3540 }
3541 if (func == NULL) {
3542 function = get_doc_function(sdl, NULL);
3543 if (function != NULL) {
3544 ZVAL_STRING(function_name, (char *)function->functionName);
3545 } else {
3546 soap_server_fault("Client", "looks like we got \"Body\" without function call", NULL, NULL, NULL);
3547 }
3548 } else {
3549 if (*version == SOAP_1_1) {
3550 attr = get_attribute_ex(func->properties,"encodingStyle",SOAP_1_1_ENV_NAMESPACE);
3551 if (attr && strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
3552 soap_server_fault("Client","Unknown Data Encoding Style", NULL, NULL, NULL);
3553 }
3554 } else {
3555 attr = get_attribute_ex(func->properties,"encodingStyle",SOAP_1_2_ENV_NAMESPACE);
3556 if (attr && strcmp((char*)attr->children->content,SOAP_1_2_ENC_NAMESPACE) != 0) {
3557 soap_server_fault("DataEncodingUnknown","Unknown Data Encoding Style", NULL, NULL, NULL);
3558 }
3559 }
3560 function = find_function(sdl, func, function_name);
3561 if (sdl != NULL && function == NULL) {
3562 if (*version == SOAP_1_2) {
3563 soap_server_fault("rpc:ProcedureNotPresent","Procedure not present", NULL, NULL, NULL);
3564 } else {
3565 php_error(E_ERROR, "Procedure '%s' not present", func->name);
3566 }
3567 }
3568 }
3569
3570 *headers = NULL;
3571 if (head) {
3572 soapHeader *h, *last = NULL;
3573
3574 attr = head->properties;
3575 while (attr != NULL) {
3576 if (attr->ns == NULL) {
3577 soap_server_fault("Client", "A SOAP Header element cannot have non Namespace qualified attributes", NULL, NULL, NULL);
3578 } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
3579 if (*version == SOAP_1_2) {
3580 soap_server_fault("Client", "encodingStyle cannot be specified on the Header", NULL, NULL, NULL);
3581 } else if (strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
3582 soap_server_fault("Client", "Unknown data encoding style", NULL, NULL, NULL);
3583 }
3584 }
3585 attr = attr->next;
3586 }
3587 trav = head->children;
3588 while (trav != NULL) {
3589 if (trav->type == XML_ELEMENT_NODE) {
3590 xmlNodePtr hdr_func = trav;
3591 int mustUnderstand = 0;
3592
3593 if (*version == SOAP_1_1) {
3594 attr = get_attribute_ex(hdr_func->properties,"encodingStyle",SOAP_1_1_ENV_NAMESPACE);
3595 if (attr && strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
3596 soap_server_fault("Client","Unknown Data Encoding Style", NULL, NULL, NULL);
3597 }
3598 attr = get_attribute_ex(hdr_func->properties,"actor",envelope_ns);
3599 if (attr != NULL) {
3600 if (strcmp((char*)attr->children->content,SOAP_1_1_ACTOR_NEXT) != 0 &&
3601 (actor == NULL || strcmp((char*)attr->children->content,actor) != 0)) {
3602 goto ignore_header;
3603 }
3604 }
3605 } else if (*version == SOAP_1_2) {
3606 attr = get_attribute_ex(hdr_func->properties,"encodingStyle",SOAP_1_2_ENV_NAMESPACE);
3607 if (attr && strcmp((char*)attr->children->content,SOAP_1_2_ENC_NAMESPACE) != 0) {
3608 soap_server_fault("DataEncodingUnknown","Unknown Data Encoding Style", NULL, NULL, NULL);
3609 }
3610 attr = get_attribute_ex(hdr_func->properties,"role",envelope_ns);
3611 if (attr != NULL) {
3612 if (strcmp((char*)attr->children->content,SOAP_1_2_ACTOR_UNLIMATERECEIVER) != 0 &&
3613 strcmp((char*)attr->children->content,SOAP_1_2_ACTOR_NEXT) != 0 &&
3614 (actor == NULL || strcmp((char*)attr->children->content,actor) != 0)) {
3615 goto ignore_header;
3616 }
3617 }
3618 }
3619 attr = get_attribute_ex(hdr_func->properties,"mustUnderstand",envelope_ns);
3620 if (attr) {
3621 if (strcmp((char*)attr->children->content,"1") == 0 ||
3622 strcmp((char*)attr->children->content,"true") == 0) {
3623 mustUnderstand = 1;
3624 } else if (strcmp((char*)attr->children->content,"0") == 0 ||
3625 strcmp((char*)attr->children->content,"false") == 0) {
3626 mustUnderstand = 0;
3627 } else {
3628 soap_server_fault("Client","mustUnderstand value is not boolean", NULL, NULL, NULL);
3629 }
3630 }
3631 h = emalloc(sizeof(soapHeader));
3632 memset(h, 0, sizeof(soapHeader));
3633 h->mustUnderstand = mustUnderstand;
3634 h->function = find_function(sdl, hdr_func, &h->function_name);
3635 if (!h->function && sdl && function && function->binding && function->binding->bindingType == BINDING_SOAP) {
3636 sdlSoapBindingFunctionHeaderPtr hdr;
3637 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
3638 if (fnb->input.headers) {
3639 smart_str key = {0};
3640
3641 if (hdr_func->ns) {
3642 smart_str_appends(&key, (char*)hdr_func->ns->href);
3643 smart_str_appendc(&key, ':');
3644 }
3645 smart_str_appendl(&key, Z_STRVAL(h->function_name), Z_STRLEN(h->function_name));
3646 smart_str_0(&key);
3647 if ((hdr = zend_hash_find_ptr(fnb->input.headers, key.s)) != NULL) {
3648 h->hdr = hdr;
3649 }
3650 smart_str_free(&key);
3651 }
3652 }
3653 if (h->hdr) {
3654 h->num_params = 1;
3655 h->parameters = emalloc(sizeof(zval));
3656 master_to_zval(&h->parameters[0], h->hdr->encode, hdr_func);
3657 } else {
3658 if (h->function && h->function->binding && h->function->binding->bindingType == BINDING_SOAP) {
3659 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)h->function->bindingAttributes;
3660 if (fnb->style == SOAP_RPC) {
3661 hdr_func = hdr_func->children;
3662 }
3663 }
3664 deserialize_parameters(hdr_func, h->function, &h->num_params, &h->parameters);
3665 }
3666 ZVAL_NULL(&h->retval);
3667 if (last == NULL) {
3668 *headers = h;
3669 } else {
3670 last->next = h;
3671 }
3672 last = h;
3673 }
3674 ignore_header:
3675 trav = trav->next;
3676 }
3677 }
3678
3679 if (function && function->binding && function->binding->bindingType == BINDING_SOAP) {
3680 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
3681 if (fnb->style == SOAP_RPC) {
3682 func = func->children;
3683 }
3684 } else {
3685 func = func->children;
3686 }
3687 deserialize_parameters(func, function, num_params, parameters);
3688
3689 encode_finish();
3690
3691 return function;
3692 }
3693
3694 static void set_soap_header_attributes(xmlNodePtr h, HashTable *ht, int version)
3695 {
3696 zval *tmp;
3697
3698 if ((tmp = zend_hash_str_find(ht, "mustUnderstand", sizeof("mustUnderstand")-1)) != NULL &&
3699 Z_TYPE_P(tmp) == IS_TRUE) {
3700 if (version == SOAP_1_1) {
3701 xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":mustUnderstand"), BAD_CAST("1"));
3702 } else {
3703 xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":mustUnderstand"), BAD_CAST("true"));
3704 }
3705 }
3706 if ((tmp = zend_hash_str_find(ht, "actor", sizeof("actor")-1)) != NULL) {
3707 if (Z_TYPE_P(tmp) == IS_STRING) {
3708 if (version == SOAP_1_1) {
3709 xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(Z_STRVAL_P(tmp)));
3710 } else {
3711 xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(Z_STRVAL_P(tmp)));
3712 }
3713 } else if (Z_TYPE_P(tmp) == IS_LONG) {
3714 if (version == SOAP_1_1) {
3715 if (Z_LVAL_P(tmp) == SOAP_ACTOR_NEXT) {
3716 xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(SOAP_1_1_ACTOR_NEXT));
3717 }
3718 } else {
3719 if (Z_LVAL_P(tmp) == SOAP_ACTOR_NEXT) {
3720 xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_NEXT));
3721 } else if (Z_LVAL_P(tmp) == SOAP_ACTOR_NONE) {
3722 xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_NONE));
3723 } else if (Z_LVAL_P(tmp) == SOAP_ACTOR_UNLIMATERECEIVER) {
3724 xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_UNLIMATERECEIVER));
3725 }
3726 }
3727 }
3728 }
3729 }
3730
3731 static int serialize_response_call2(xmlNodePtr body, sdlFunctionPtr function, char *function_name, char *uri, zval *ret, int version, int main, xmlNodePtr *node)
3732 {
3733 xmlNodePtr method = NULL, param;
3734 sdlParamPtr parameter = NULL;
3735 int param_count;
3736 int style, use;
3737 xmlNsPtr ns = NULL;
3738
3739 if (function != NULL && function->binding->bindingType == BINDING_SOAP) {
3740 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
3741
3742 style = fnb->style;
3743 use = fnb->output.use;
3744 if (style == SOAP_RPC) {
3745 ns = encode_add_ns(body, fnb->output.ns);
3746 if (function->responseName) {
3747 method = xmlNewChild(body, ns, BAD_CAST(function->responseName), NULL);
3748 } else if (function->responseParameters) {
3749 method = xmlNewChild(body, ns, BAD_CAST(function->functionName), NULL);
3750 }
3751 }
3752 } else {
3753 style = main?SOAP_RPC:SOAP_DOCUMENT;
3754 use = main?SOAP_ENCODED:SOAP_LITERAL;
3755 if (style == SOAP_RPC) {
3756 ns = encode_add_ns(body, uri);
3757 method = xmlNewChild(body, ns, BAD_CAST(function_name), NULL);
3758 }
3759 }
3760
3761 if (function != NULL) {
3762 if (function->responseParameters) {
3763 param_count = zend_hash_num_elements(function->responseParameters);
3764 } else {
3765 param_count = 0;
3766 }
3767 } else {
3768 param_count = 1;
3769 }
3770
3771 if (param_count == 1) {
3772 parameter = get_param(function, NULL, 0, TRUE);
3773
3774 if (style == SOAP_RPC) {
3775 xmlNode *rpc_result;
3776 if (main && version == SOAP_1_2) {
3777 xmlNs *rpc_ns = xmlNewNs(body, BAD_CAST(RPC_SOAP12_NAMESPACE), BAD_CAST(RPC_SOAP12_NS_PREFIX));
3778 rpc_result = xmlNewChild(method, rpc_ns, BAD_CAST("result"), NULL);
3779 param = serialize_parameter(parameter, ret, 0, "return", use, method);
3780 xmlNodeSetContent(rpc_result,param->name);
3781 } else {
3782 param = serialize_parameter(parameter, ret, 0, "return", use, method);
3783 }
3784 } else {
3785 param = serialize_parameter(parameter, ret, 0, "return", use, body);
3786 if (function && function->binding->bindingType == BINDING_SOAP) {
3787 if (parameter && parameter->element) {
3788 ns = encode_add_ns(param, parameter->element->namens);
3789 xmlNodeSetName(param, BAD_CAST(parameter->element->name));
3790 xmlSetNs(param, ns);
3791 }
3792 } else if (strcmp((char*)param->name,"return") == 0) {
3793 ns = encode_add_ns(param, uri);
3794 xmlNodeSetName(param, BAD_CAST(function_name));
3795 xmlSetNs(param, ns);
3796 }
3797 }
3798 } else if (param_count > 1 && Z_TYPE_P(ret) == IS_ARRAY) {
3799 zval *data;
3800 int i = 0;
3801 zend_string *param_name;
3802 zend_ulong param_index = i;
3803
3804 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(ret), param_index, param_name, data) {
3805 parameter = get_param(function, ZSTR_VAL(param_name), param_index, TRUE);
3806 if (style == SOAP_RPC) {
3807 param = serialize_parameter(parameter, data, i, ZSTR_VAL(param_name), use, method);
3808 } else {
3809 param = serialize_parameter(parameter, data, i, ZSTR_VAL(param_name), use, body);
3810 if (function && function->binding->bindingType == BINDING_SOAP) {
3811 if (parameter && parameter->element) {
3812 ns = encode_add_ns(param, parameter->element->namens);
3813 xmlNodeSetName(param, BAD_CAST(parameter->element->name));
3814 xmlSetNs(param, ns);
3815 }
3816 }
3817 }
3818
3819 i++;
3820 param_index = i;
3821 } ZEND_HASH_FOREACH_END();
3822 }
3823 if (use == SOAP_ENCODED && version == SOAP_1_2 && method != NULL) {
3824 xmlSetNsProp(method, body->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_2_ENC_NAMESPACE));
3825 }
3826 if (node) {
3827 *node = method;
3828 }
3829 return use;
3830 }
3831
3832 static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function_name, char *uri, zval *ret, soapHeader* headers, int version)
3833 {
3834 xmlDocPtr doc;
3835 xmlNodePtr envelope = NULL, body, param;
3836 xmlNsPtr ns = NULL;
3837 int use = SOAP_LITERAL;
3838 xmlNodePtr head = NULL;
3839
3840 encode_reset_ns();
3841
3842 doc = xmlNewDoc(BAD_CAST("1.0"));
3843 doc->charset = XML_CHAR_ENCODING_UTF8;
3844 doc->encoding = xmlCharStrdup("UTF-8");
3845
3846 if (version == SOAP_1_1) {
3847 envelope = xmlNewDocNode(doc, NULL, BAD_CAST("Envelope"), NULL);
3848 ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_1_ENV_NAMESPACE), BAD_CAST(SOAP_1_1_ENV_NS_PREFIX));
3849 xmlSetNs(envelope,ns);
3850 } else if (version == SOAP_1_2) {
3851 envelope = xmlNewDocNode(doc, NULL, BAD_CAST("Envelope"), NULL);
3852 ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENV_NAMESPACE), BAD_CAST(SOAP_1_2_ENV_NS_PREFIX));
3853 xmlSetNs(envelope,ns);
3854 } else {
3855 soap_server_fault("Server", "Unknown SOAP version", NULL, NULL, NULL);
3856 }
3857 xmlDocSetRootElement(doc, envelope);
3858
3859 if (Z_TYPE_P(ret) == IS_OBJECT &&
3860 instanceof_function(Z_OBJCE_P(ret), soap_fault_class_entry)) {
3861 char *detail_name;
3862 HashTable* prop;
3863 zval *tmp;
3864 sdlFaultPtr fault = NULL;
3865 char *fault_ns = NULL;
3866
3867 prop = Z_OBJPROP_P(ret);
3868
3869 if (headers &&
3870 (tmp = zend_hash_str_find(prop, "headerfault", sizeof("headerfault")-1)) != NULL) {
3871 encodePtr hdr_enc = NULL;
3872 int hdr_use = SOAP_LITERAL;
3873 zval *hdr_ret = tmp;
3874 char *hdr_ns = headers->hdr?headers->hdr->ns:NULL;
3875 char *hdr_name = Z_STRVAL(headers->function_name);
3876
3877 head = xmlNewChild(envelope, ns, BAD_CAST("Header"), NULL);
3878 if (Z_TYPE_P(hdr_ret) == IS_OBJECT &&
3879 instanceof_function(Z_OBJCE_P(hdr_ret), soap_header_class_entry)) {
3880 HashTable* ht = Z_OBJPROP_P(hdr_ret);
3881 sdlSoapBindingFunctionHeaderPtr hdr;
3882 smart_str key = {0};
3883
3884 if ((tmp = zend_hash_str_find(ht, "namespace", sizeof("namespace")-1)) != NULL &&
3885 Z_TYPE_P(tmp) == IS_STRING) {
3886 smart_str_appendl(&key, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
3887 smart_str_appendc(&key, ':');
3888 hdr_ns = Z_STRVAL_P(tmp);
3889 }
3890 if ((tmp = zend_hash_str_find(ht, "name", sizeof("name")-1)) != NULL &&
3891 Z_TYPE_P(tmp) == IS_STRING) {
3892 smart_str_appendl(&key, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
3893 hdr_name = Z_STRVAL_P(tmp);
3894 }
3895 smart_str_0(&key);
3896 if (headers->hdr && headers->hdr->headerfaults &&
3897 (hdr = zend_hash_find_ptr(headers->hdr->headerfaults, key.s)) != NULL) {
3898 hdr_enc = hdr->encode;
3899 hdr_use = hdr->use;
3900 }
3901 smart_str_free(&key);
3902 if ((tmp = zend_hash_str_find(ht, "data", sizeof("data")-1)) != NULL) {
3903 hdr_ret = tmp;
3904 } else {
3905 hdr_ret = NULL;
3906 }
3907 }
3908
3909 if (headers->function) {
3910 if (serialize_response_call2(head, headers->function, Z_STRVAL(headers->function_name), uri, hdr_ret, version, 0, NULL) == SOAP_ENCODED) {
3911 use = SOAP_ENCODED;
3912 }
3913 } else {
3914 xmlNodePtr xmlHdr = master_to_xml(hdr_enc, hdr_ret, hdr_use, head);
3915 if (hdr_name) {
3916 xmlNodeSetName(xmlHdr, BAD_CAST(hdr_name));
3917 }
3918 if (hdr_ns) {
3919 xmlNsPtr nsptr = encode_add_ns(xmlHdr, hdr_ns);
3920 xmlSetNs(xmlHdr, nsptr);
3921 }
3922 }
3923 }
3924
3925 body = xmlNewChild(envelope, ns, BAD_CAST("Body"), NULL);
3926 param = xmlNewChild(body, ns, BAD_CAST("Fault"), NULL);
3927
3928 if ((tmp = zend_hash_str_find(prop, "faultcodens", sizeof("faultcodens")-1)) != NULL && Z_TYPE_P(tmp) == IS_STRING) {
3929 fault_ns = Z_STRVAL_P(tmp);
3930 }
3931 use = SOAP_LITERAL;
3932 if ((tmp = zend_hash_str_find(prop, "_name", sizeof("_name")-1)) != NULL && Z_TYPE_P(tmp) == IS_STRING) {
3933 sdlFaultPtr tmp_fault;
3934 if (function && function->faults &&
3935 (tmp_fault = zend_hash_find_ptr(function->faults, Z_STR_P(tmp))) != NULL) {
3936 fault = tmp_fault;
3937 if (function->binding &&
3938 function->binding->bindingType == BINDING_SOAP &&
3939 fault->bindingAttributes) {
3940 sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
3941 use = fb->use;
3942 if (fault_ns == NULL) {
3943 fault_ns = fb->ns;
3944 }
3945 }
3946 }
3947 } else if (function && function->faults &&
3948 zend_hash_num_elements(function->faults) == 1) {
3949
3950 zend_hash_internal_pointer_reset(function->faults);
3951 fault = zend_hash_get_current_data_ptr(function->faults);
3952 if (function->binding &&
3953 function->binding->bindingType == BINDING_SOAP &&
3954 fault->bindingAttributes) {
3955 sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
3956 use = fb->use;
3957 if (fault_ns == NULL) {
3958 fault_ns = fb->ns;
3959 }
3960 }
3961 }
3962
3963 if (fault_ns == NULL &&
3964 fault &&
3965 fault->details &&
3966 zend_hash_num_elements(fault->details) == 1) {
3967 sdlParamPtr sparam;
3968
3969 zend_hash_internal_pointer_reset(fault->details);
3970 sparam = zend_hash_get_current_data_ptr(fault->details);
3971 if (sparam->element) {
3972 fault_ns = sparam->element->namens;
3973 }
3974 }
3975
3976 if (version == SOAP_1_1) {
3977 if ((tmp = zend_hash_str_find(prop, "faultcode", sizeof("faultcode")-1)) != NULL &&
3978 Z_TYPE_P(tmp) == IS_STRING) {
3979 xmlNodePtr node = xmlNewNode(NULL, BAD_CAST("faultcode"));
3980 zend_string *str = php_escape_html_entities((unsigned char*)Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), 0, 0, NULL);
3981 xmlAddChild(param, node);
3982 if (fault_ns) {
3983 xmlNsPtr nsptr = encode_add_ns(node, fault_ns);
3984 xmlChar *code = xmlBuildQName(BAD_CAST(ZSTR_VAL(str)), nsptr->prefix, NULL, 0);
3985 xmlNodeSetContent(node, code);
3986 xmlFree(code);
3987 } else {
3988 xmlNodeSetContentLen(node, BAD_CAST(ZSTR_VAL(str)), (int)ZSTR_LEN(str));
3989 }
3990 zend_string_release(str);
3991 }
3992 if ((tmp = zend_hash_str_find(prop, "faultstring", sizeof("faultstring")-1)) != NULL) {
3993 xmlNodePtr node = master_to_xml(get_conversion(IS_STRING), tmp, SOAP_LITERAL, param);
3994 xmlNodeSetName(node, BAD_CAST("faultstring"));
3995 }
3996 if ((tmp = zend_hash_str_find(prop, "faultactor", sizeof("faultactor")-1)) != NULL) {
3997 xmlNodePtr node = master_to_xml(get_conversion(IS_STRING), tmp, SOAP_LITERAL, param);
3998 xmlNodeSetName(node, BAD_CAST("faultactor"));
3999 }
4000 detail_name = "detail";
4001 } else {
4002 if ((tmp = zend_hash_str_find(prop, "faultcode", sizeof("faultcode")-1)) != NULL &&
4003 Z_TYPE_P(tmp) == IS_STRING) {
4004 xmlNodePtr node = xmlNewChild(param, ns, BAD_CAST("Code"), NULL);
4005 zend_string *str = php_escape_html_entities((unsigned char*)Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), 0, 0, NULL);
4006 node = xmlNewChild(node, ns, BAD_CAST("Value"), NULL);
4007 if (fault_ns) {
4008 xmlNsPtr nsptr = encode_add_ns(node, fault_ns);
4009 xmlChar *code = xmlBuildQName(BAD_CAST(ZSTR_VAL(str)), nsptr->prefix, NULL, 0);
4010 xmlNodeSetContent(node, code);
4011 xmlFree(code);
4012 } else {
4013 xmlNodeSetContentLen(node, BAD_CAST(ZSTR_VAL(str)), (int)ZSTR_LEN(str));
4014 }
4015 zend_string_release(str);
4016 }
4017 if ((tmp = zend_hash_str_find(prop, "faultstring", sizeof("faultstring")-1)) != NULL) {
4018 xmlNodePtr node = xmlNewChild(param, ns, BAD_CAST("Reason"), NULL);
4019 node = master_to_xml(get_conversion(IS_STRING), tmp, SOAP_LITERAL, node);
4020 xmlNodeSetName(node, BAD_CAST("Text"));
4021 xmlSetNs(node, ns);
4022 }
4023 detail_name = SOAP_1_2_ENV_NS_PREFIX":Detail";
4024 }
4025 if (fault && fault->details && zend_hash_num_elements(fault->details) == 1) {
4026 xmlNodePtr node;
4027 zval *detail = NULL;
4028 sdlParamPtr sparam;
4029 xmlNodePtr x;
4030
4031 if ((tmp = zend_hash_str_find(prop, "detail", sizeof("detail")-1)) != NULL &&
4032 Z_TYPE_P(tmp) != IS_NULL) {
4033 detail = tmp;
4034 }
4035 node = xmlNewNode(NULL, BAD_CAST(detail_name));
4036 xmlAddChild(param, node);
4037
4038 zend_hash_internal_pointer_reset(fault->details);
4039 sparam = zend_hash_get_current_data_ptr(fault->details);
4040
4041 if (detail &&
4042 Z_TYPE_P(detail) == IS_OBJECT &&
4043 sparam->element &&
4044 zend_hash_num_elements(Z_OBJPROP_P(detail)) == 1 &&
4045 (tmp = zend_hash_str_find(Z_OBJPROP_P(detail), sparam->element->name, strlen(sparam->element->name))) != NULL) {
4046 detail = tmp;
4047 }
4048
4049 x = serialize_parameter(sparam, detail, 1, NULL, use, node);
4050
4051 if (function &&
4052 function->binding &&
4053 function->binding->bindingType == BINDING_SOAP &&
4054 function->bindingAttributes) {
4055 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
4056 if (fnb->style == SOAP_RPC && !sparam->element) {
4057 if (fault->bindingAttributes) {
4058 sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
4059 if (fb->ns) {
4060 xmlNsPtr ns = encode_add_ns(x, fb->ns);
4061 xmlSetNs(x, ns);
4062 }
4063 }
4064 } else {
4065 if (sparam->element) {
4066 ns = encode_add_ns(x, sparam->element->namens);
4067 xmlNodeSetName(x, BAD_CAST(sparam->element->name));
4068 xmlSetNs(x, ns);
4069 }
4070 }
4071 }
4072 if (use == SOAP_ENCODED && version == SOAP_1_2) {
4073 xmlSetNsProp(x, envelope->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_2_ENC_NAMESPACE));
4074 }
4075 } else if ((tmp = zend_hash_str_find(prop, "detail", sizeof("detail")-1)) != NULL &&
4076 Z_TYPE_P(tmp) != IS_NULL) {
4077 serialize_zval(tmp, NULL, detail_name, use, param);
4078 }
4079 } else {
4080
4081 if (headers) {
4082 soapHeader *h;
4083
4084 head = xmlNewChild(envelope, ns, BAD_CAST("Header"), NULL);
4085 h = headers;
4086 while (h != NULL) {
4087 if (Z_TYPE(h->retval) != IS_NULL) {
4088 encodePtr hdr_enc = NULL;
4089 int hdr_use = SOAP_LITERAL;
4090 zval *hdr_ret = &h->retval;
4091 char *hdr_ns = h->hdr?h->hdr->ns:NULL;
4092 char *hdr_name = Z_STRVAL(h->function_name);
4093 HashTable *ht = NULL;
4094
4095 if (Z_TYPE(h->retval) == IS_OBJECT &&
4096 instanceof_function(Z_OBJCE(h->retval), soap_header_class_entry)) {
4097 zval *tmp;
4098 sdlSoapBindingFunctionHeaderPtr hdr;
4099 smart_str key = {0};
4100
4101 ht = Z_OBJPROP(h->retval);
4102 if ((tmp = zend_hash_str_find(ht, "namespace", sizeof("namespace")-1)) != NULL &&
4103 Z_TYPE_P(tmp) == IS_STRING) {
4104 smart_str_appendl(&key, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
4105 smart_str_appendc(&key, ':');
4106 hdr_ns = Z_STRVAL_P(tmp);
4107 }
4108 if ((tmp = zend_hash_str_find(ht, "name", sizeof("name")-1)) != NULL &&
4109 Z_TYPE_P(tmp) == IS_STRING) {
4110 smart_str_appendl(&key, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
4111 hdr_name = Z_STRVAL_P(tmp);
4112 }
4113 smart_str_0(&key);
4114 if (function && function->binding && function->binding->bindingType == BINDING_SOAP) {
4115 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
4116
4117 if (fnb->output.headers &&
4118 (hdr = zend_hash_find_ptr(fnb->output.headers, key.s)) != NULL) {
4119 hdr_enc = hdr->encode;
4120 hdr_use = hdr->use;
4121 }
4122 }
4123 smart_str_free(&key);
4124 if ((tmp = zend_hash_str_find(ht, "data", sizeof("data")-1)) != NULL) {
4125 hdr_ret = tmp;
4126 } else {
4127 hdr_ret = NULL;
4128 }
4129 }
4130
4131 if (h->function) {
4132 xmlNodePtr xmlHdr = NULL;
4133
4134 if (serialize_response_call2(head, h->function, Z_STRVAL(h->function_name), uri, hdr_ret, version, 0, &xmlHdr) == SOAP_ENCODED) {
4135 use = SOAP_ENCODED;
4136 }
4137 if (ht) {
4138 set_soap_header_attributes(xmlHdr, ht, version);
4139 }
4140 } else {
4141 xmlNodePtr xmlHdr = master_to_xml(hdr_enc, hdr_ret, hdr_use, head);
4142 if (hdr_name) {
4143 xmlNodeSetName(xmlHdr, BAD_CAST(hdr_name));
4144 }
4145 if (hdr_ns) {
4146 xmlNsPtr nsptr = encode_add_ns(xmlHdr,hdr_ns);
4147 xmlSetNs(xmlHdr, nsptr);
4148 }
4149 if (ht) {
4150 set_soap_header_attributes(xmlHdr, ht, version);
4151 }
4152 }
4153 }
4154 h = h->next;
4155 }
4156
4157 if (head->children == NULL) {
4158 xmlUnlinkNode(head);
4159 xmlFreeNode(head);
4160 }
4161 }
4162
4163 body = xmlNewChild(envelope, ns, BAD_CAST("Body"), NULL);
4164
4165 if (serialize_response_call2(body, function, function_name, uri, ret, version, 1, NULL) == SOAP_ENCODED) {
4166 use = SOAP_ENCODED;
4167 }
4168
4169 }
4170
4171 if (use == SOAP_ENCODED) {
4172 xmlNewNs(envelope, BAD_CAST(XSD_NAMESPACE), BAD_CAST(XSD_NS_PREFIX));
4173 if (version == SOAP_1_1) {
4174 xmlNewNs(envelope, BAD_CAST(SOAP_1_1_ENC_NAMESPACE), BAD_CAST(SOAP_1_1_ENC_NS_PREFIX));
4175 xmlSetNsProp(envelope, envelope->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_1_ENC_NAMESPACE));
4176 } else if (version == SOAP_1_2) {
4177 xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENC_NAMESPACE), BAD_CAST(SOAP_1_2_ENC_NS_PREFIX));
4178 }
4179 }
4180
4181 encode_finish();
4182
4183 if (function && function->responseName == NULL &&
4184 body->children == NULL && head == NULL) {
4185 xmlFreeDoc(doc);
4186 return NULL;
4187 }
4188 return doc;
4189 }
4190
4191 static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function, char *function_name, char *uri, zval *arguments, int arg_count, int version, HashTable *soap_headers)
4192 {
4193 xmlDoc *doc;
4194 xmlNodePtr envelope = NULL, body, method = NULL, head = NULL;
4195 xmlNsPtr ns = NULL;
4196 zval *zstyle, *zuse;
4197 int i, style, use;
4198 HashTable *hdrs = NULL;
4199
4200 encode_reset_ns();
4201
4202 doc = xmlNewDoc(BAD_CAST("1.0"));
4203 doc->encoding = xmlCharStrdup("UTF-8");
4204 doc->charset = XML_CHAR_ENCODING_UTF8;
4205 if (version == SOAP_1_1) {
4206 envelope = xmlNewDocNode(doc, NULL, BAD_CAST("Envelope"), NULL);
4207 ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_1_ENV_NAMESPACE), BAD_CAST(SOAP_1_1_ENV_NS_PREFIX));
4208 xmlSetNs(envelope, ns);
4209 } else if (version == SOAP_1_2) {
4210 envelope = xmlNewDocNode(doc, NULL, BAD_CAST("Envelope"), NULL);
4211 ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENV_NAMESPACE), BAD_CAST(SOAP_1_2_ENV_NS_PREFIX));
4212 xmlSetNs(envelope, ns);
4213 } else {
4214 soap_error0(E_ERROR, "Unknown SOAP version");
4215 }
4216 xmlDocSetRootElement(doc, envelope);
4217
4218 if (soap_headers) {
4219 head = xmlNewChild(envelope, ns, BAD_CAST("Header"), NULL);
4220 }
4221
4222 body = xmlNewChild(envelope, ns, BAD_CAST("Body"), NULL);
4223
4224 if (function && function->binding->bindingType == BINDING_SOAP) {
4225 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
4226
4227 hdrs = fnb->input.headers;
4228 style = fnb->style;
4229 /*FIXME: how to pass method name if style is SOAP_DOCUMENT */
4230 /*style = SOAP_RPC;*/
4231 use = fnb->input.use;
4232 if (style == SOAP_RPC) {
4233 ns = encode_add_ns(body, fnb->input.ns);
4234 if (function->requestName) {
4235 method = xmlNewChild(body, ns, BAD_CAST(function->requestName), NULL);
4236 } else {
4237 method = xmlNewChild(body, ns, BAD_CAST(function->functionName), NULL);
4238 }
4239 }
4240 } else {
4241 if ((zstyle = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "style", sizeof("style")-1)) != NULL &&
4242 Z_TYPE_P(zstyle) == IS_LONG) {
4243 style = Z_LVAL_P(zstyle);
4244 } else {
4245 style = SOAP_RPC;
4246 }
4247 /*FIXME: how to pass method name if style is SOAP_DOCUMENT */
4248 /*style = SOAP_RPC;*/
4249 if (style == SOAP_RPC) {
4250 ns = encode_add_ns(body, uri);
4251 if (function_name) {
4252 method = xmlNewChild(body, ns, BAD_CAST(function_name), NULL);
4253 } else if (function && function->requestName) {
4254 method = xmlNewChild(body, ns, BAD_CAST(function->requestName), NULL);
4255 } else if (function && function->functionName) {
4256 method = xmlNewChild(body, ns, BAD_CAST(function->functionName), NULL);
4257 } else {
4258 method = body;
4259 }
4260 } else {
4261 method = body;
4262 }
4263
4264 if ((zuse = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "use", sizeof("use")-1)) != NULL &&
4265 Z_TYPE_P(zuse) == IS_LONG && Z_LVAL_P(zuse) == SOAP_LITERAL) {
4266 use = SOAP_LITERAL;
4267 } else {
4268 use = SOAP_ENCODED;
4269 }
4270 }
4271
4272 for (i = 0;i < arg_count;i++) {
4273 xmlNodePtr param;
4274 sdlParamPtr parameter = get_param(function, NULL, i, FALSE);
4275
4276 if (style == SOAP_RPC) {
4277 param = serialize_parameter(parameter, &arguments[i], i, NULL, use, method);
4278 } else if (style == SOAP_DOCUMENT) {
4279 param = serialize_parameter(parameter, &arguments[i], i, NULL, use, body);
4280 if (function && function->binding->bindingType == BINDING_SOAP) {
4281 if (parameter && parameter->element) {
4282 ns = encode_add_ns(param, parameter->element->namens);
4283 xmlNodeSetName(param, BAD_CAST(parameter->element->name));
4284 xmlSetNs(param, ns);
4285 }
4286 }
4287 }
4288 }
4289
4290 if (function && function->requestParameters) {
4291 int n = zend_hash_num_elements(function->requestParameters);
4292
4293 if (n > arg_count) {
4294 for (i = arg_count; i < n; i++) {
4295 xmlNodePtr param;
4296 sdlParamPtr parameter = get_param(function, NULL, i, FALSE);
4297
4298 if (style == SOAP_RPC) {
4299 param = serialize_parameter(parameter, NULL, i, NULL, use, method);
4300 } else if (style == SOAP_DOCUMENT) {
4301 param = serialize_parameter(parameter, NULL, i, NULL, use, body);
4302 if (function && function->binding->bindingType == BINDING_SOAP) {
4303 if (parameter && parameter->element) {
4304 ns = encode_add_ns(param, parameter->element->namens);
4305 xmlNodeSetName(param, BAD_CAST(parameter->element->name));
4306 xmlSetNs(param, ns);
4307 }
4308 }
4309 }
4310 }
4311 }
4312 }
4313
4314 if (head) {
4315 zval* header;
4316
4317 ZEND_HASH_FOREACH_VAL(soap_headers, header) {
4318 HashTable *ht;
4319 zval *name, *ns, *tmp;
4320
4321 if (Z_TYPE_P(header) != IS_OBJECT) {
4322 continue;
4323 }
4324
4325 ht = Z_OBJPROP_P(header);
4326 if ((name = zend_hash_str_find(ht, "name", sizeof("name")-1)) != NULL &&
4327 Z_TYPE_P(name) == IS_STRING &&
4328 (ns = zend_hash_str_find(ht, "namespace", sizeof("namespace")-1)) != NULL &&
4329 Z_TYPE_P(ns) == IS_STRING) {
4330 xmlNodePtr h;
4331 xmlNsPtr nsptr;
4332 int hdr_use = SOAP_LITERAL;
4333 encodePtr enc = NULL;
4334
4335 if (hdrs) {
4336 smart_str key = {0};
4337 sdlSoapBindingFunctionHeaderPtr hdr;
4338
4339 smart_str_appendl(&key, Z_STRVAL_P(ns), Z_STRLEN_P(ns));
4340 smart_str_appendc(&key, ':');
4341 smart_str_appendl(&key, Z_STRVAL_P(name), Z_STRLEN_P(name));
4342 smart_str_0(&key);
4343 if ((hdr = zend_hash_find_ptr(hdrs, key.s)) != NULL) {
4344 hdr_use = hdr->use;
4345 enc = hdr->encode;
4346 if (hdr_use == SOAP_ENCODED) {
4347 use = SOAP_ENCODED;
4348 }
4349 }
4350 smart_str_free(&key);
4351 }
4352
4353 if ((tmp = zend_hash_str_find(ht, "data", sizeof("data")-1)) != NULL) {
4354 h = master_to_xml(enc, tmp, hdr_use, head);
4355 xmlNodeSetName(h, BAD_CAST(Z_STRVAL_P(name)));
4356 } else {
4357 h = xmlNewNode(NULL, BAD_CAST(Z_STRVAL_P(name)));
4358 xmlAddChild(head, h);
4359 }
4360 nsptr = encode_add_ns(h, Z_STRVAL_P(ns));
4361 xmlSetNs(h, nsptr);
4362 set_soap_header_attributes(h, ht, version);
4363 }
4364 } ZEND_HASH_FOREACH_END();
4365 }
4366
4367 if (use == SOAP_ENCODED) {
4368 xmlNewNs(envelope, BAD_CAST(XSD_NAMESPACE), BAD_CAST(XSD_NS_PREFIX));
4369 if (version == SOAP_1_1) {
4370 xmlNewNs(envelope, BAD_CAST(SOAP_1_1_ENC_NAMESPACE), BAD_CAST(SOAP_1_1_ENC_NS_PREFIX));
4371 xmlSetNsProp(envelope, envelope->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_1_ENC_NAMESPACE));
4372 } else if (version == SOAP_1_2) {
4373 xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENC_NAMESPACE), BAD_CAST(SOAP_1_2_ENC_NS_PREFIX));
4374 if (method) {
4375 xmlSetNsProp(method, envelope->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_2_ENC_NAMESPACE));
4376 }
4377 }
4378 }
4379
4380 encode_finish();
4381
4382 return doc;
4383 }
4384
4385 static xmlNodePtr serialize_parameter(sdlParamPtr param, zval *param_val, int index, char *name, int style, xmlNodePtr parent)
4386 {
4387 char *paramName;
4388 xmlNodePtr xmlParam;
4389 char paramNameBuf[10];
4390
4391 if (param_val &&
4392 Z_TYPE_P(param_val) == IS_OBJECT &&
4393 Z_OBJCE_P(param_val) == soap_param_class_entry) {
4394 zval *param_name;
4395 zval *param_data;
4396
4397 if ((param_name = zend_hash_str_find(Z_OBJPROP_P(param_val), "param_name", sizeof("param_name")-1)) != NULL &&
4398 Z_TYPE_P(param_name) == IS_STRING &&
4399 (param_data = zend_hash_str_find(Z_OBJPROP_P(param_val), "param_data", sizeof("param_data")-1)) != NULL) {
4400 param_val = param_data;
4401 name = Z_STRVAL_P(param_name);
4402 }
4403 }
4404
4405 if (param != NULL && param->paramName != NULL) {
4406 paramName = param->paramName;
4407 } else {
4408 if (name == NULL) {
4409 paramName = paramNameBuf;
4410 snprintf(paramName, sizeof(paramNameBuf), "param%d",index);
4411 } else {
4412 paramName = name;
4413 }
4414 }
4415
4416 xmlParam = serialize_zval(param_val, param, paramName, style, parent);
4417
4418 return xmlParam;
4419 }
4420
4421 static xmlNodePtr serialize_zval(zval *val, sdlParamPtr param, char *paramName, int style, xmlNodePtr parent)
4422 {
4423 xmlNodePtr xmlParam;
4424 encodePtr enc;
4425 zval defval;
4426
4427 ZVAL_UNDEF(&defval);
4428 if (param != NULL) {
4429 enc = param->encode;
4430 if (val == NULL) {
4431 if (param->element) {
4432 if (param->element->fixed) {
4433 ZVAL_STRING(&defval, param->element->fixed);
4434 val = &defval;
4435 } else if (param->element->def && !param->element->nillable) {
4436 ZVAL_STRING(&defval, param->element->def);
4437 val = &defval;
4438 }
4439 }
4440 }
4441 } else {
4442 enc = NULL;
4443 }
4444 xmlParam = master_to_xml(enc, val, style, parent);
4445 zval_ptr_dtor(&defval);
4446 if (!strcmp((char*)xmlParam->name, "BOGUS")) {
4447 xmlNodeSetName(xmlParam, BAD_CAST(paramName));
4448 }
4449 return xmlParam;
4450 }
4451
4452 static sdlParamPtr get_param(sdlFunctionPtr function, char *param_name, int index, int response)
4453 {
4454 sdlParamPtr tmp;
4455 HashTable *ht;
4456
4457 if (function == NULL) {
4458 return NULL;
4459 }
4460
4461 if (response == FALSE) {
4462 ht = function->requestParameters;
4463 } else {
4464 ht = function->responseParameters;
4465 }
4466
4467 if (ht == NULL) {
4468 return NULL;
4469 }
4470
4471 if (param_name != NULL) {
4472 if ((tmp = zend_hash_str_find_ptr(ht, param_name, strlen(param_name))) != NULL) {
4473 return tmp;
4474 } else {
4475 ZEND_HASH_FOREACH_PTR(ht, tmp) {
4476 if (tmp->paramName && strcmp(param_name, tmp->paramName) == 0) {
4477 return tmp;
4478 }
4479 } ZEND_HASH_FOREACH_END();
4480 }
4481 } else {
4482 if ((tmp = zend_hash_index_find_ptr(ht, index)) != NULL) {
4483 return tmp;
4484 }
4485 }
4486 return NULL;
4487 }
4488
4489 static sdlFunctionPtr get_function(sdlPtr sdl, const char *function_name)
4490 {
4491 sdlFunctionPtr tmp;
4492
4493 int len = strlen(function_name);
4494 char *str = estrndup(function_name,len);
4495 php_strtolower(str,len);
4496 if (sdl != NULL) {
4497 if ((tmp = zend_hash_str_find_ptr(&sdl->functions, str, len)) != NULL) {
4498 efree(str);
4499 return tmp;
4500 } else if (sdl->requests != NULL && (tmp = zend_hash_str_find_ptr(sdl->requests, str, len)) != NULL) {
4501 efree(str);
4502 return tmp;
4503 }
4504 }
4505 efree(str);
4506 return NULL;
4507 }
4508
4509 static sdlFunctionPtr get_doc_function(sdlPtr sdl, xmlNodePtr params)
4510 {
4511 if (sdl) {
4512 sdlFunctionPtr tmp;
4513 sdlParamPtr param;
4514
4515 ZEND_HASH_FOREACH_PTR(&sdl->functions, tmp) {
4516 if (tmp->binding && tmp->binding->bindingType == BINDING_SOAP) {
4517 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)tmp->bindingAttributes;
4518 if (fnb->style == SOAP_DOCUMENT) {
4519 if (params == NULL) {
4520 if (tmp->requestParameters == NULL ||
4521 zend_hash_num_elements(tmp->requestParameters) == 0) {
4522 return tmp;
4523 }
4524 } else if (tmp->requestParameters != NULL &&
4525 zend_hash_num_elements(tmp->requestParameters) > 0) {
4526 int ok = 1;
4527 xmlNodePtr node = params;
4528
4529 ZEND_HASH_FOREACH_PTR(tmp->requestParameters, param) {
4530 if (param->element) {
4531 if (strcmp(param->element->name, (char*)node->name) != 0) {
4532 ok = 0;
4533 break;
4534 }
4535 if (param->element->namens != NULL && node->ns != NULL) {
4536 if (strcmp(param->element->namens, (char*)node->ns->href) != 0) {
4537 ok = 0;
4538 break;
4539 }
4540 } else if ((void*)param->element->namens != (void*)node->ns) {
4541 ok = 0;
4542 break;
4543 }
4544 } else if (strcmp(param->paramName, (char*)node->name) != 0) {
4545 ok = 0;
4546 break;
4547 }
4548 node = node->next;
4549 } ZEND_HASH_FOREACH_END();
4550 if (ok /*&& node == NULL*/) {
4551 return tmp;
4552 }
4553 }
4554 }
4555 }
4556 } ZEND_HASH_FOREACH_END();
4557 }
4558 return NULL;
4559 }
4560
4561 static void function_to_string(sdlFunctionPtr function, smart_str *buf)
4562 {
4563 int i = 0;
4564 sdlParamPtr param;
4565
4566 if (function->responseParameters &&
4567 zend_hash_num_elements(function->responseParameters) > 0) {
4568 if (zend_hash_num_elements(function->responseParameters) == 1) {
4569 zend_hash_internal_pointer_reset(function->responseParameters);
4570 param = zend_hash_get_current_data_ptr(function->responseParameters);
4571 if (param->encode && param->encode->details.type_str) {
4572 smart_str_appendl(buf, param->encode->details.type_str, strlen(param->encode->details.type_str));
4573 smart_str_appendc(buf, ' ');
4574 } else {
4575 smart_str_appendl(buf, "UNKNOWN ", 8);
4576 }
4577 } else {
4578 i = 0;
4579 smart_str_appendl(buf, "list(", 5);
4580 ZEND_HASH_FOREACH_PTR(function->responseParameters, param) {
4581 if (i > 0) {
4582 smart_str_appendl(buf, ", ", 2);
4583 }
4584 if (param->encode && param->encode->details.type_str) {
4585 smart_str_appendl(buf, param->encode->details.type_str, strlen(param->encode->details.type_str));
4586 } else {
4587 smart_str_appendl(buf, "UNKNOWN", 7);
4588 }
4589 smart_str_appendl(buf, " $", 2);
4590 smart_str_appendl(buf, param->paramName, strlen(param->paramName));
4591 i++;
4592 } ZEND_HASH_FOREACH_END();
4593 smart_str_appendl(buf, ") ", 2);
4594 }
4595 } else {
4596 smart_str_appendl(buf, "void ", 5);
4597 }
4598
4599 smart_str_appendl(buf, function->functionName, strlen(function->functionName));
4600
4601 smart_str_appendc(buf, '(');
4602 if (function->requestParameters) {
4603 i = 0;
4604 ZEND_HASH_FOREACH_PTR(function->requestParameters, param) {
4605 if (i > 0) {
4606 smart_str_appendl(buf, ", ", 2);
4607 }
4608 if (param->encode && param->encode->details.type_str) {
4609 smart_str_appendl(buf, param->encode->details.type_str, strlen(param->encode->details.type_str));
4610 } else {
4611 smart_str_appendl(buf, "UNKNOWN", 7);
4612 }
4613 smart_str_appendl(buf, " $", 2);
4614 smart_str_appendl(buf, param->paramName, strlen(param->paramName));
4615 i++;
4616 } ZEND_HASH_FOREACH_END();
4617 }
4618 smart_str_appendc(buf, ')');
4619 smart_str_0(buf);
4620 }
4621
4622 static void model_to_string(sdlContentModelPtr model, smart_str *buf, int level)
4623 {
4624 int i;
4625
4626 switch (model->kind) {
4627 case XSD_CONTENT_ELEMENT:
4628 type_to_string(model->u.element, buf, level);
4629 smart_str_appendl(buf, ";\n", 2);
4630 break;
4631 case XSD_CONTENT_ANY:
4632 for (i = 0;i < level;i++) {
4633 smart_str_appendc(buf, ' ');
4634 }
4635 smart_str_appendl(buf, "<anyXML> any;\n", sizeof("<anyXML> any;\n")-1);
4636 break;
4637 case XSD_CONTENT_SEQUENCE:
4638 case XSD_CONTENT_ALL:
4639 case XSD_CONTENT_CHOICE: {
4640 sdlContentModelPtr tmp;
4641
4642 ZEND_HASH_FOREACH_PTR(model->u.content, tmp) {
4643 model_to_string(tmp, buf, level);
4644 } ZEND_HASH_FOREACH_END();
4645 break;
4646 }
4647 case XSD_CONTENT_GROUP:
4648 model_to_string(model->u.group->model, buf, level);
4649 default:
4650 break;
4651 }
4652 }
4653
4654 static void type_to_string(sdlTypePtr type, smart_str *buf, int level)
4655 {
4656 int i;
4657 smart_str spaces = {0};
4658
4659 for (i = 0;i < level;i++) {
4660 smart_str_appendc(&spaces, ' ');
4661 }
4662 if (spaces.s) {
4663 smart_str_appendl(buf, ZSTR_VAL(spaces.s), ZSTR_LEN(spaces.s));
4664 }
4665 switch (type->kind) {
4666 case XSD_TYPEKIND_SIMPLE:
4667 if (type->encode) {
4668 smart_str_appendl(buf, type->encode->details.type_str, strlen(type->encode->details.type_str));
4669 smart_str_appendc(buf, ' ');
4670 } else {
4671 smart_str_appendl(buf, "anyType ", sizeof("anyType ")-1);
4672 }
4673 smart_str_appendl(buf, type->name, strlen(type->name));
4674 break;
4675 case XSD_TYPEKIND_LIST:
4676 smart_str_appendl(buf, "list ", 5);
4677 smart_str_appendl(buf, type->name, strlen(type->name));
4678 if (type->elements) {
4679 sdlTypePtr item_type;
4680
4681 smart_str_appendl(buf, " {", 2);
4682 ZEND_HASH_FOREACH_PTR(type->elements, item_type) {
4683 smart_str_appendl(buf, item_type->name, strlen(item_type->name));
4684 } ZEND_HASH_FOREACH_END();
4685 smart_str_appendc(buf, '}');
4686 }
4687 break;
4688 case XSD_TYPEKIND_UNION:
4689 smart_str_appendl(buf, "union ", 6);
4690 smart_str_appendl(buf, type->name, strlen(type->name));
4691 if (type->elements) {
4692 sdlTypePtr item_type;
4693 int first = 0;
4694
4695 smart_str_appendl(buf, " {", 2);
4696 ZEND_HASH_FOREACH_PTR(type->elements, item_type) {
4697 if (!first) {
4698 smart_str_appendc(buf, ',');
4699 first = 0;
4700 }
4701 smart_str_appendl(buf, item_type->name, strlen(item_type->name));
4702 } ZEND_HASH_FOREACH_END();
4703 smart_str_appendc(buf, '}');
4704 }
4705 break;
4706 case XSD_TYPEKIND_COMPLEX:
4707 case XSD_TYPEKIND_RESTRICTION:
4708 case XSD_TYPEKIND_EXTENSION:
4709 if (type->encode &&
4710 (type->encode->details.type == IS_ARRAY ||
4711 type->encode->details.type == SOAP_ENC_ARRAY)) {
4712 sdlAttributePtr attr;
4713 sdlExtraAttributePtr ext;
4714
4715 if (type->attributes &&
4716 (attr = zend_hash_str_find_ptr(type->attributes, SOAP_1_1_ENC_NAMESPACE":arrayType",
4717 sizeof(SOAP_1_1_ENC_NAMESPACE":arrayType")-1)) != NULL &&
4718 attr->extraAttributes &&
4719 (ext = zend_hash_str_find_ptr(attr->extraAttributes, WSDL_NAMESPACE":arrayType", sizeof(WSDL_NAMESPACE":arrayType")-1)) != NULL) {
4720 char *end = strchr(ext->val, '[');
4721 int len;
4722 if (end == NULL) {
4723 len = strlen(ext->val);
4724 } else {
4725 len = end - ext->val;
4726 }
4727 if (len == 0) {
4728 smart_str_appendl(buf, "anyType", sizeof("anyType")-1);
4729 } else {
4730 smart_str_appendl(buf, ext->val, len);
4731 }
4732 smart_str_appendc(buf, ' ');
4733 smart_str_appendl(buf, type->name, strlen(type->name));
4734 if (end != NULL) {
4735 smart_str_appends(buf, end);
4736 }
4737 } else {
4738 sdlTypePtr elementType;
4739 if (type->attributes &&
4740 (attr = zend_hash_str_find_ptr(type->attributes, SOAP_1_2_ENC_NAMESPACE":itemType",
4741 sizeof(SOAP_1_2_ENC_NAMESPACE":itemType")-1)) != NULL &&
4742 attr->extraAttributes &&
4743 (ext = zend_hash_str_find_ptr(attr->extraAttributes, WSDL_NAMESPACE":itemType", sizeof(WSDL_NAMESPACE":arrayType")-1)) != NULL) {
4744 smart_str_appends(buf, ext->val);
4745 smart_str_appendc(buf, ' ');
4746 } else if (type->elements &&
4747 zend_hash_num_elements(type->elements) == 1 &&
4748 (zend_hash_internal_pointer_reset(type->elements),
4749 (elementType = zend_hash_get_current_data_ptr(type->elements)) != NULL) &&
4750 elementType->encode && elementType->encode->details.type_str) {
4751 smart_str_appends(buf, elementType->encode->details.type_str);
4752 smart_str_appendc(buf, ' ');
4753 } else {
4754 smart_str_appendl(buf, "anyType ", 8);
4755 }
4756 smart_str_appendl(buf, type->name, strlen(type->name));
4757 if (type->attributes &&
4758 (attr = zend_hash_str_find_ptr(type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
4759 sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize")-1)) != NULL &&
4760 attr->extraAttributes &&
4761 (ext = zend_hash_str_find_ptr(attr->extraAttributes, WSDL_NAMESPACE":itemType", sizeof(WSDL_NAMESPACE":arraySize")-1)) != NULL) {
4762 smart_str_appendc(buf, '[');
4763 smart_str_appends(buf, ext->val);
4764 smart_str_appendc(buf, ']');
4765 } else {
4766 smart_str_appendl(buf, "[]", 2);
4767 }
4768 }
4769 } else {
4770 smart_str_appendl(buf, "struct ", 7);
4771 smart_str_appendl(buf, type->name, strlen(type->name));
4772 smart_str_appendc(buf, ' ');
4773 smart_str_appendl(buf, "{\n", 2);
4774 if ((type->kind == XSD_TYPEKIND_RESTRICTION ||
4775 type->kind == XSD_TYPEKIND_EXTENSION) && type->encode) {
4776 encodePtr enc = type->encode;
4777 while (enc && enc->details.sdl_type &&
4778 enc != enc->details.sdl_type->encode &&
4779 enc->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
4780 enc->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
4781 enc->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
4782 enc = enc->details.sdl_type->encode;
4783 }
4784 if (enc) {
4785 if (spaces.s) {
4786 smart_str_appendl(buf, ZSTR_VAL(spaces.s), ZSTR_LEN(spaces.s));
4787 }
4788 smart_str_appendc(buf, ' ');
4789 smart_str_appendl(buf, type->encode->details.type_str, strlen(type->encode->details.type_str));
4790 smart_str_appendl(buf, " _;\n", 4);
4791 }
4792 }
4793 if (type->model) {
4794 model_to_string(type->model, buf, level+1);
4795 }
4796 if (type->attributes) {
4797 sdlAttributePtr attr;
4798
4799 ZEND_HASH_FOREACH_PTR(type->attributes, attr) {
4800 if (spaces.s) {
4801 smart_str_appendl(buf, ZSTR_VAL(spaces.s), ZSTR_LEN(spaces.s));
4802 }
4803 smart_str_appendc(buf, ' ');
4804 if (attr->encode && attr->encode->details.type_str) {
4805 smart_str_appends(buf, attr->encode->details.type_str);
4806 smart_str_appendc(buf, ' ');
4807 } else {
4808 smart_str_appendl(buf, "UNKNOWN ", 8);
4809 }
4810 smart_str_appends(buf, attr->name);
4811 smart_str_appendl(buf, ";\n", 2);
4812 } ZEND_HASH_FOREACH_END();
4813 }
4814 if (spaces.s) {
4815 smart_str_appendl(buf, ZSTR_VAL(spaces.s), ZSTR_LEN(spaces.s));
4816 }
4817 smart_str_appendc(buf, '}');
4818 }
4819 break;
4820 default:
4821 break;
4822 }
4823 smart_str_free(&spaces);
4824 smart_str_0(buf);
4825 }
4826
4827 static void delete_url(void *handle)
4828 {
4829 php_url_free((php_url*)handle);
4830 }
4831
4832 static void delete_service(void *data)
4833 {
4834 soapServicePtr service = (soapServicePtr)data;
4835
4836 if (service->soap_functions.ft) {
4837 zend_hash_destroy(service->soap_functions.ft);
4838 efree(service->soap_functions.ft);
4839 }
4840
4841 if (service->typemap) {
4842 zend_hash_destroy(service->typemap);
4843 efree(service->typemap);
4844 }
4845
4846 if (service->soap_class.argc) {
4847 int i;
4848 for (i = 0; i < service->soap_class.argc;i++) {
4849 zval_ptr_dtor(&service->soap_class.argv[i]);
4850 }
4851 efree(service->soap_class.argv);
4852 }
4853
4854 if (service->actor) {
4855 efree(service->actor);
4856 }
4857 if (service->uri) {
4858 efree(service->uri);
4859 }
4860 if (service->sdl) {
4861 delete_sdl(service->sdl);
4862 }
4863 if (service->encoding) {
4864 xmlCharEncCloseFunc(service->encoding);
4865 }
4866 if (service->class_map) {
4867 zend_hash_destroy(service->class_map);
4868 FREE_HASHTABLE(service->class_map);
4869 }
4870 zval_ptr_dtor(&service->soap_object);
4871 efree(service);
4872 }
4873
4874 static void delete_hashtable(void *data)
4875 {
4876 HashTable *ht = (HashTable*)data;
4877 zend_hash_destroy(ht);
4878 efree(ht);
4879 }
4880