Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / php / ext / soap / soap.c
blob7df84e5b2a6c960d3e044f83d55b4e02411468cf
1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2013 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 +----------------------------------------------------------------------+
20 /* $Id$ */
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"
32 static int le_sdl = 0;
33 int le_url = 0;
34 static int le_service = 0;
35 static int le_typemap = 0;
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;
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);
52 static void clear_soap_fault(zval *obj TSRMLS_DC);
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 TSRMLS_DC);
54 static void soap_server_fault(char* code, char* string, char *actor, zval* details, char *name TSRMLS_DC);
55 static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeader* hdr TSRMLS_DC);
57 static sdlParamPtr get_param(sdlFunctionPtr function, char *param_name, int index, int);
58 static sdlFunctionPtr get_function(sdlPtr sdl, const char *function_name);
59 static sdlFunctionPtr get_doc_function(sdlPtr sdl, xmlNodePtr node);
61 static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, char* actor, zval *function_name, int *num_params, zval **parameters[], int *version, soapHeader **headers TSRMLS_DC);
62 static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function_name,char *uri,zval *ret, soapHeader *headers, int version TSRMLS_DC);
63 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 TSRMLS_DC);
64 static xmlNodePtr serialize_parameter(sdlParamPtr param,zval *param_val,int index,char *name, int style, xmlNodePtr parent TSRMLS_DC);
65 static xmlNodePtr serialize_zval(zval *val, sdlParamPtr param, char *paramName, int style, xmlNodePtr parent TSRMLS_DC);
67 static void delete_service(void *service);
68 static void delete_url(void *handle);
69 static void delete_hashtable(void *hashtable);
71 static void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args);
73 #define SOAP_SERVER_BEGIN_CODE() \
74 zend_bool _old_handler = SOAP_GLOBAL(use_soap_error_handler);\
75 char* _old_error_code = SOAP_GLOBAL(error_code);\
76 zval* _old_error_object = SOAP_GLOBAL(error_object);\
77 int _old_soap_version = SOAP_GLOBAL(soap_version);\
78 SOAP_GLOBAL(use_soap_error_handler) = 1;\
79 SOAP_GLOBAL(error_code) = "Server";\
80 SOAP_GLOBAL(error_object) = this_ptr;
82 #define SOAP_SERVER_END_CODE() \
83 SOAP_GLOBAL(use_soap_error_handler) = _old_handler;\
84 SOAP_GLOBAL(error_code) = _old_error_code;\
85 SOAP_GLOBAL(error_object) = _old_error_object;\
86 SOAP_GLOBAL(soap_version) = _old_soap_version;
88 #define SOAP_CLIENT_BEGIN_CODE() \
89 zend_bool _old_handler = SOAP_GLOBAL(use_soap_error_handler);\
90 char* _old_error_code = SOAP_GLOBAL(error_code);\
91 zval* _old_error_object = SOAP_GLOBAL(error_object);\
92 int _old_soap_version = SOAP_GLOBAL(soap_version);\
93 zend_bool _old_in_compilation = CG(in_compilation); \
94 zend_bool _old_in_execution = EG(in_execution); \
95 zend_execute_data *_old_current_execute_data = EG(current_execute_data); \
96 void **_old_stack_top = EG(argument_stack)->top; \
97 int _bailout = 0;\
98 SOAP_GLOBAL(use_soap_error_handler) = 1;\
99 SOAP_GLOBAL(error_code) = "Client";\
100 SOAP_GLOBAL(error_object) = this_ptr;\
101 zend_try {
103 #define SOAP_CLIENT_END_CODE() \
104 } zend_catch {\
105 CG(in_compilation) = _old_in_compilation; \
106 EG(in_execution) = _old_in_execution; \
107 EG(current_execute_data) = _old_current_execute_data; \
108 if (EG(exception) == NULL || \
109 Z_TYPE_P(EG(exception)) != IS_OBJECT || \
110 !instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {\
111 _bailout = 1;\
113 if (_old_stack_top != EG(argument_stack)->top) { \
114 while (EG(argument_stack)->prev != NULL && \
115 ((char*)_old_stack_top < (char*)EG(argument_stack) || \
116 (char*) _old_stack_top > (char*)EG(argument_stack)->end)) { \
117 zend_vm_stack tmp = EG(argument_stack)->prev; \
118 efree(EG(argument_stack)); \
119 EG(argument_stack) = tmp; \
121 EG(argument_stack)->top = _old_stack_top; \
123 } zend_end_try();\
124 SOAP_GLOBAL(use_soap_error_handler) = _old_handler;\
125 SOAP_GLOBAL(error_code) = _old_error_code;\
126 SOAP_GLOBAL(error_object) = _old_error_object;\
127 SOAP_GLOBAL(soap_version) = _old_soap_version;\
128 if (_bailout) {\
129 zend_bailout();\
132 #define FETCH_THIS_SDL(ss) \
134 zval **__tmp; \
135 if(FIND_SDL_PROPERTY(this_ptr,__tmp) != FAILURE) { \
136 FETCH_SDL_RES(ss,__tmp); \
137 } else { \
138 ss = NULL; \
142 #define FIND_SDL_PROPERTY(ss,tmp) zend_hash_find(Z_OBJPROP_P(ss), "sdl", sizeof("sdl"), (void **)&tmp)
143 #define FETCH_SDL_RES(ss,tmp) ss = (sdlPtr) zend_fetch_resource(tmp TSRMLS_CC, -1, "sdl", NULL, 1, le_sdl)
145 #define FIND_TYPEMAP_PROPERTY(ss,tmp) zend_hash_find(Z_OBJPROP_P(ss), "typemap", sizeof("typemap"), (void **)&tmp)
146 #define FETCH_TYPEMAP_RES(ss,tmp) ss = (HashTable*) zend_fetch_resource(tmp TSRMLS_CC, -1, "typemap", NULL, 1, le_typemap)
148 #define FETCH_THIS_SERVICE(ss) \
150 zval **tmp; \
151 if (zend_hash_find(Z_OBJPROP_P(this_ptr),"service", sizeof("service"), (void **)&tmp) != FAILURE) { \
152 ss = (soapServicePtr)zend_fetch_resource(tmp TSRMLS_CC, -1, "service", NULL, 1, le_service); \
153 } else { \
154 ss = NULL; \
158 static zend_class_entry* soap_class_entry;
159 static zend_class_entry* soap_server_class_entry;
160 static zend_class_entry* soap_fault_class_entry;
161 static zend_class_entry* soap_header_class_entry;
162 static zend_class_entry* soap_param_class_entry;
163 zend_class_entry* soap_var_class_entry;
165 ZEND_DECLARE_MODULE_GLOBALS(soap)
167 static void (*old_error_handler)(int, const char *, const uint, const char*, va_list);
169 #ifdef va_copy
170 #define call_old_error_handler(error_num, error_filename, error_lineno, format, args) \
172 va_list copy; \
173 va_copy(copy, args); \
174 old_error_handler(error_num, error_filename, error_lineno, format, copy); \
175 va_end(copy); \
177 #else
178 #define call_old_error_handler(error_num, error_filename, error_lineno, format, args) \
180 old_error_handler(error_num, error_filename, error_lineno, format, args); \
182 #endif
184 #define PHP_SOAP_SERVER_CLASSNAME "SoapServer"
185 #define PHP_SOAP_CLIENT_CLASSNAME "SoapClient"
186 #define PHP_SOAP_VAR_CLASSNAME "SoapVar"
187 #define PHP_SOAP_FAULT_CLASSNAME "SoapFault"
188 #define PHP_SOAP_PARAM_CLASSNAME "SoapParam"
189 #define PHP_SOAP_HEADER_CLASSNAME "SoapHeader"
191 PHP_RINIT_FUNCTION(soap);
192 PHP_MINIT_FUNCTION(soap);
193 PHP_MSHUTDOWN_FUNCTION(soap);
194 PHP_MINFO_FUNCTION(soap);
197 Registry Functions
198 TODO: this!
200 PHP_FUNCTION(soap_encode_to_xml);
201 PHP_FUNCTION(soap_encode_to_zval);
202 PHP_FUNCTION(use_soap_error_handler);
203 PHP_FUNCTION(is_soap_fault);
206 /* Server Functions */
207 PHP_METHOD(SoapServer, SoapServer);
208 PHP_METHOD(SoapServer, setClass);
209 PHP_METHOD(SoapServer, setObject);
210 PHP_METHOD(SoapServer, addFunction);
211 PHP_METHOD(SoapServer, getFunctions);
212 PHP_METHOD(SoapServer, handle);
213 PHP_METHOD(SoapServer, setPersistence);
214 PHP_METHOD(SoapServer, fault);
215 PHP_METHOD(SoapServer, addSoapHeader);
217 /* Client Functions */
218 PHP_METHOD(SoapClient, SoapClient);
219 PHP_METHOD(SoapClient, __call);
220 PHP_METHOD(SoapClient, __getLastRequest);
221 PHP_METHOD(SoapClient, __getLastResponse);
222 PHP_METHOD(SoapClient, __getLastRequestHeaders);
223 PHP_METHOD(SoapClient, __getLastResponseHeaders);
224 PHP_METHOD(SoapClient, __getFunctions);
225 PHP_METHOD(SoapClient, __getTypes);
226 PHP_METHOD(SoapClient, __doRequest);
227 PHP_METHOD(SoapClient, __setCookie);
228 PHP_METHOD(SoapClient, __setLocation);
229 PHP_METHOD(SoapClient, __setSoapHeaders);
231 /* SoapVar Functions */
232 PHP_METHOD(SoapVar, SoapVar);
234 /* SoapFault Functions */
235 PHP_METHOD(SoapFault, SoapFault);
236 PHP_METHOD(SoapFault, __toString);
238 /* SoapParam Functions */
239 PHP_METHOD(SoapParam, SoapParam);
241 /* SoapHeader Functions */
242 PHP_METHOD(SoapHeader, SoapHeader);
244 #define SOAP_CTOR(class_name, func_name, arginfo, flags) PHP_ME(class_name, func_name, arginfo, flags)
246 /* {{{ arginfo */
247 ZEND_BEGIN_ARG_INFO(arginfo_soap__void, 0)
248 ZEND_END_ARG_INFO()
250 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapparam_soapparam, 0, 0, 2)
251 ZEND_ARG_INFO(0, data)
252 ZEND_ARG_INFO(0, name)
253 ZEND_END_ARG_INFO()
255 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapheader_soapheader, 0, 0, 2)
256 ZEND_ARG_INFO(0, namespace)
257 ZEND_ARG_INFO(0, name)
258 ZEND_ARG_INFO(0, data)
259 ZEND_ARG_INFO(0, mustunderstand)
260 ZEND_ARG_INFO(0, actor)
261 ZEND_END_ARG_INFO()
263 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapfault_soapfault, 0, 0, 2)
264 ZEND_ARG_INFO(0, faultcode)
265 ZEND_ARG_INFO(0, faultstring)
266 ZEND_ARG_INFO(0, faultactor)
267 ZEND_ARG_INFO(0, detail)
268 ZEND_ARG_INFO(0, faultname)
269 ZEND_ARG_INFO(0, headerfault)
270 ZEND_END_ARG_INFO()
272 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapvar_soapvar, 0, 0, 2)
273 ZEND_ARG_INFO(0, data)
274 ZEND_ARG_INFO(0, encoding)
275 ZEND_ARG_INFO(0, type_name)
276 ZEND_ARG_INFO(0, type_namespace)
277 ZEND_ARG_INFO(0, node_name)
278 ZEND_ARG_INFO(0, node_namespace)
279 ZEND_END_ARG_INFO()
281 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_fault, 0, 0, 2)
282 ZEND_ARG_INFO(0, code)
283 ZEND_ARG_INFO(0, string)
284 ZEND_ARG_INFO(0, actor)
285 ZEND_ARG_INFO(0, details)
286 ZEND_ARG_INFO(0, name)
287 ZEND_END_ARG_INFO()
289 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_addsoapheader, 0, 0, 1)
290 ZEND_ARG_INFO(0, object)
291 ZEND_END_ARG_INFO()
293 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_soapserver, 0, 0, 1)
294 ZEND_ARG_INFO(0, wsdl)
295 ZEND_ARG_INFO(0, options)
296 ZEND_END_ARG_INFO()
298 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_setpersistence, 0, 0, 1)
299 ZEND_ARG_INFO(0, mode)
300 ZEND_END_ARG_INFO()
302 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_setclass, 0, 0, 1)
303 ZEND_ARG_INFO(0, class_name)
304 ZEND_ARG_INFO(0, args)
305 ZEND_END_ARG_INFO()
307 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_setobject, 0, 0, 1)
308 ZEND_ARG_INFO(0, object)
309 ZEND_END_ARG_INFO()
311 ZEND_BEGIN_ARG_INFO(arginfo_soapserver_getfunctions, 0)
312 ZEND_END_ARG_INFO()
314 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_addfunction, 0, 0, 1)
315 ZEND_ARG_INFO(0, functions)
316 ZEND_END_ARG_INFO()
318 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_handle, 0, 0, 0)
319 ZEND_ARG_INFO(0, soap_request)
320 ZEND_END_ARG_INFO()
322 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient_soapclient, 0, 0, 1)
323 ZEND_ARG_INFO(0, wsdl)
324 ZEND_ARG_INFO(0, options)
325 ZEND_END_ARG_INFO()
327 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___call, 0, 0, 2)
328 ZEND_ARG_INFO(0, function_name)
329 ZEND_ARG_INFO(0, arguments)
330 ZEND_END_ARG_INFO()
332 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___soapcall, 0, 0, 2)
333 ZEND_ARG_INFO(0, function_name)
334 ZEND_ARG_INFO(0, arguments)
335 ZEND_ARG_INFO(0, options)
336 ZEND_ARG_INFO(0, input_headers)
337 ZEND_ARG_INFO(1, output_headers)
338 ZEND_END_ARG_INFO()
340 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getfunctions, 0)
341 ZEND_END_ARG_INFO()
343 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___gettypes, 0)
344 ZEND_END_ARG_INFO()
346 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastrequest, 0)
347 ZEND_END_ARG_INFO()
349 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastresponse, 0)
350 ZEND_END_ARG_INFO()
352 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastrequestheaders, 0)
353 ZEND_END_ARG_INFO()
355 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastresponseheaders, 0)
356 ZEND_END_ARG_INFO()
358 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___dorequest, 0, 0, 4)
359 ZEND_ARG_INFO(0, request)
360 ZEND_ARG_INFO(0, location)
361 ZEND_ARG_INFO(0, action)
362 ZEND_ARG_INFO(0, version)
363 ZEND_ARG_INFO(0, one_way)
364 ZEND_END_ARG_INFO()
366 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___setcookie, 0, 0, 1)
367 ZEND_ARG_INFO(0, name)
368 ZEND_ARG_INFO(0, value)
369 ZEND_END_ARG_INFO()
371 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___setsoapheaders, 0, 0, 1)
372 ZEND_ARG_INFO(0, soapheaders)
373 ZEND_END_ARG_INFO()
375 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___setlocation, 0, 0, 0)
376 ZEND_ARG_INFO(0, new_location)
377 ZEND_END_ARG_INFO()
379 ZEND_BEGIN_ARG_INFO_EX(arginfo_soap_use_soap_error_handler, 0, 0, 0)
380 ZEND_ARG_INFO(0, handler)
381 ZEND_END_ARG_INFO()
383 ZEND_BEGIN_ARG_INFO_EX(arginfo_soap_is_soap_fault, 0, 0, 1)
384 ZEND_ARG_INFO(0, object)
385 ZEND_END_ARG_INFO()
386 /* }}} */
388 static const zend_function_entry soap_functions[] = {
389 PHP_FE(use_soap_error_handler, arginfo_soap_use_soap_error_handler)
390 PHP_FE(is_soap_fault, arginfo_soap_is_soap_fault)
391 PHP_FE_END
394 static const zend_function_entry soap_fault_functions[] = {
395 SOAP_CTOR(SoapFault, SoapFault, arginfo_soapfault_soapfault, 0)
396 PHP_ME(SoapFault, __toString, arginfo_soap__void, 0)
397 PHP_FE_END
400 static const zend_function_entry soap_server_functions[] = {
401 SOAP_CTOR(SoapServer, SoapServer, arginfo_soapserver_soapserver, 0)
402 PHP_ME(SoapServer, setPersistence, arginfo_soapserver_setpersistence, 0)
403 PHP_ME(SoapServer, setClass, arginfo_soapserver_setclass, 0)
404 PHP_ME(SoapServer, setObject, arginfo_soapserver_setobject, 0)
405 PHP_ME(SoapServer, addFunction, arginfo_soapserver_addfunction, 0)
406 PHP_ME(SoapServer, getFunctions, arginfo_soapserver_getfunctions, 0)
407 PHP_ME(SoapServer, handle, arginfo_soapserver_handle, 0)
408 PHP_ME(SoapServer, fault, arginfo_soapserver_fault, 0)
409 PHP_ME(SoapServer, addSoapHeader, arginfo_soapserver_addsoapheader, 0)
410 PHP_FE_END
413 static const zend_function_entry soap_client_functions[] = {
414 SOAP_CTOR(SoapClient, SoapClient, arginfo_soapclient_soapclient, 0)
415 PHP_ME(SoapClient, __call, arginfo_soapclient___call, 0)
416 ZEND_NAMED_ME(__soapCall, ZEND_MN(SoapClient___call), arginfo_soapclient___soapcall, 0)
417 PHP_ME(SoapClient, __getLastRequest, arginfo_soapclient___getlastrequest, 0)
418 PHP_ME(SoapClient, __getLastResponse, arginfo_soapclient___getlastresponse, 0)
419 PHP_ME(SoapClient, __getLastRequestHeaders, arginfo_soapclient___getlastrequestheaders, 0)
420 PHP_ME(SoapClient, __getLastResponseHeaders, arginfo_soapclient___getlastresponseheaders, 0)
421 PHP_ME(SoapClient, __getFunctions, arginfo_soapclient___getfunctions, 0)
422 PHP_ME(SoapClient, __getTypes, arginfo_soapclient___gettypes, 0)
423 PHP_ME(SoapClient, __doRequest, arginfo_soapclient___dorequest, 0)
424 PHP_ME(SoapClient, __setCookie, arginfo_soapclient___setcookie, 0)
425 PHP_ME(SoapClient, __setLocation, arginfo_soapclient___setlocation, 0)
426 PHP_ME(SoapClient, __setSoapHeaders, arginfo_soapclient___setsoapheaders, 0)
427 PHP_FE_END
430 static const zend_function_entry soap_var_functions[] = {
431 SOAP_CTOR(SoapVar, SoapVar, arginfo_soapvar_soapvar, 0)
432 PHP_FE_END
435 static const zend_function_entry soap_param_functions[] = {
436 SOAP_CTOR(SoapParam, SoapParam, arginfo_soapparam_soapparam, 0)
437 PHP_FE_END
440 static const zend_function_entry soap_header_functions[] = {
441 SOAP_CTOR(SoapHeader, SoapHeader, arginfo_soapheader_soapheader, 0)
442 PHP_FE_END
445 zend_module_entry soap_module_entry = {
446 #ifdef STANDARD_MODULE_HEADER
447 STANDARD_MODULE_HEADER,
448 #endif
449 "soap",
450 soap_functions,
451 PHP_MINIT(soap),
452 PHP_MSHUTDOWN(soap),
453 PHP_RINIT(soap),
454 NULL,
455 PHP_MINFO(soap),
456 #ifdef STANDARD_MODULE_HEADER
457 NO_VERSION_YET,
458 #endif
459 STANDARD_MODULE_PROPERTIES,
462 #ifdef COMPILE_DL_SOAP
463 ZEND_GET_MODULE(soap)
464 #endif
466 ZEND_INI_MH(OnUpdateCacheMode)
468 char *p;
469 #ifndef ZTS
470 char *base = (char *) mh_arg2;
471 #else
472 char *base = (char *) ts_resource(*((int *) mh_arg2));
473 #endif
475 p = (char*) (base+(size_t) mh_arg1);
477 *p = (char)atoi(new_value);
479 return SUCCESS;
482 static PHP_INI_MH(OnUpdateCacheDir)
484 /* Only do the open_basedir check at runtime */
485 if (stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) {
486 char *p;
488 if (memchr(new_value, '\0', new_value_length) != NULL) {
489 return FAILURE;
492 /* we do not use zend_memrchr() since path can contain ; itself */
493 if ((p = strchr(new_value, ';'))) {
494 char *p2;
495 p++;
496 if ((p2 = strchr(p, ';'))) {
497 p = p2 + 1;
499 } else {
500 p = new_value;
503 if (PG(open_basedir) && *p && php_check_open_basedir(p TSRMLS_CC)) {
504 return FAILURE;
508 OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
509 return SUCCESS;
512 PHP_INI_BEGIN()
513 STD_PHP_INI_ENTRY("soap.wsdl_cache_enabled", "1", PHP_INI_ALL, OnUpdateBool,
514 cache_enabled, zend_soap_globals, soap_globals)
515 STD_PHP_INI_ENTRY("soap.wsdl_cache_dir", "/tmp", PHP_INI_ALL, OnUpdateCacheDir,
516 cache_dir, zend_soap_globals, soap_globals)
517 STD_PHP_INI_ENTRY("soap.wsdl_cache_ttl", "86400", PHP_INI_ALL, OnUpdateLong,
518 cache_ttl, zend_soap_globals, soap_globals)
519 STD_PHP_INI_ENTRY("soap.wsdl_cache", "1", PHP_INI_ALL, OnUpdateCacheMode,
520 cache_mode, zend_soap_globals, soap_globals)
521 STD_PHP_INI_ENTRY("soap.wsdl_cache_limit", "5", PHP_INI_ALL, OnUpdateLong,
522 cache_limit, zend_soap_globals, soap_globals)
523 PHP_INI_END()
525 static HashTable defEnc, defEncIndex, defEncNs;
527 static void php_soap_prepare_globals()
529 int i;
530 encodePtr enc;
532 zend_hash_init(&defEnc, 0, NULL, NULL, 1);
533 zend_hash_init(&defEncIndex, 0, NULL, NULL, 1);
534 zend_hash_init(&defEncNs, 0, NULL, NULL, 1);
536 i = 0;
537 do {
538 enc = &defaultEncoding[i];
540 /* If has a ns and a str_type then index it */
541 if (defaultEncoding[i].details.type_str) {
542 if (defaultEncoding[i].details.ns != NULL) {
543 char *ns_type;
544 spprintf(&ns_type, 0, "%s:%s", defaultEncoding[i].details.ns, defaultEncoding[i].details.type_str);
545 zend_hash_add(&defEnc, ns_type, strlen(ns_type) + 1, &enc, sizeof(encodePtr), NULL);
546 efree(ns_type);
547 } else {
548 zend_hash_add(&defEnc, defaultEncoding[i].details.type_str, strlen(defaultEncoding[i].details.type_str) + 1, &enc, sizeof(encodePtr), NULL);
551 /* Index everything by number */
552 if (!zend_hash_index_exists(&defEncIndex, defaultEncoding[i].details.type)) {
553 zend_hash_index_update(&defEncIndex, defaultEncoding[i].details.type, &enc, sizeof(encodePtr), NULL);
555 i++;
556 } while (defaultEncoding[i].details.type != END_KNOWN_TYPES);
558 /* hash by namespace */
559 zend_hash_add(&defEncNs, XSD_1999_NAMESPACE, sizeof(XSD_1999_NAMESPACE), XSD_NS_PREFIX, sizeof(XSD_NS_PREFIX), NULL);
560 zend_hash_add(&defEncNs, XSD_NAMESPACE, sizeof(XSD_NAMESPACE), XSD_NS_PREFIX, sizeof(XSD_NS_PREFIX), NULL);
561 zend_hash_add(&defEncNs, XSI_NAMESPACE, sizeof(XSI_NAMESPACE), XSI_NS_PREFIX, sizeof(XSI_NS_PREFIX), NULL);
562 zend_hash_add(&defEncNs, XML_NAMESPACE, sizeof(XML_NAMESPACE), XML_NS_PREFIX, sizeof(XML_NS_PREFIX), NULL);
563 zend_hash_add(&defEncNs, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE), SOAP_1_1_ENC_NS_PREFIX, sizeof(SOAP_1_1_ENC_NS_PREFIX), NULL);
564 zend_hash_add(&defEncNs, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE), SOAP_1_2_ENC_NS_PREFIX, sizeof(SOAP_1_2_ENC_NS_PREFIX), NULL);
567 static void php_soap_init_globals(zend_soap_globals *soap_globals TSRMLS_DC)
569 soap_globals->defEnc = defEnc;
570 soap_globals->defEncIndex = defEncIndex;
571 soap_globals->defEncNs = defEncNs;
572 soap_globals->typemap = NULL;
573 soap_globals->use_soap_error_handler = 0;
574 soap_globals->error_code = NULL;
575 soap_globals->error_object = NULL;
576 soap_globals->sdl = NULL;
577 soap_globals->soap_version = SOAP_1_1;
578 soap_globals->mem_cache = NULL;
579 soap_globals->ref_map = NULL;
582 PHP_MSHUTDOWN_FUNCTION(soap)
584 zend_error_cb = old_error_handler;
585 zend_hash_destroy(&SOAP_GLOBAL(defEnc));
586 zend_hash_destroy(&SOAP_GLOBAL(defEncIndex));
587 zend_hash_destroy(&SOAP_GLOBAL(defEncNs));
588 if (SOAP_GLOBAL(mem_cache)) {
589 zend_hash_destroy(SOAP_GLOBAL(mem_cache));
590 free(SOAP_GLOBAL(mem_cache));
592 UNREGISTER_INI_ENTRIES();
593 return SUCCESS;
596 PHP_RINIT_FUNCTION(soap)
598 SOAP_GLOBAL(typemap) = NULL;
599 SOAP_GLOBAL(use_soap_error_handler) = 0;
600 SOAP_GLOBAL(error_code) = NULL;
601 SOAP_GLOBAL(error_object) = NULL;
602 SOAP_GLOBAL(sdl) = NULL;
603 SOAP_GLOBAL(soap_version) = SOAP_1_1;
604 SOAP_GLOBAL(encoding) = NULL;
605 SOAP_GLOBAL(class_map) = NULL;
606 SOAP_GLOBAL(features) = 0;
607 SOAP_GLOBAL(ref_map) = NULL;
608 return SUCCESS;
611 PHP_MINIT_FUNCTION(soap)
613 zend_class_entry ce;
615 /* TODO: add ini entry for always use soap errors */
616 php_soap_prepare_globals();
617 ZEND_INIT_MODULE_GLOBALS(soap, php_soap_init_globals, NULL);
618 REGISTER_INI_ENTRIES();
620 /* Register SoapClient class */
621 /* BIG NOTE : THIS EMITS AN COMPILATION WARNING UNDER ZE2 - handle_function_call deprecated.
622 soap_call_function_handler should be of type struct _zend_function, not (*handle_function_call).
625 zend_internal_function fe;
627 fe.type = ZEND_INTERNAL_FUNCTION;
628 fe.handler = ZEND_MN(SoapClient___call);
629 fe.function_name = NULL;
630 fe.scope = NULL;
631 fe.fn_flags = 0;
632 fe.prototype = NULL;
633 fe.num_args = 2;
634 fe.arg_info = NULL;
636 INIT_OVERLOADED_CLASS_ENTRY(ce, PHP_SOAP_CLIENT_CLASSNAME, soap_client_functions,
637 (zend_function *)&fe, NULL, NULL);
638 soap_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
640 /* Register SoapVar class */
641 INIT_CLASS_ENTRY(ce, PHP_SOAP_VAR_CLASSNAME, soap_var_functions);
642 soap_var_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
644 /* Register SoapServer class */
645 INIT_CLASS_ENTRY(ce, PHP_SOAP_SERVER_CLASSNAME, soap_server_functions);
646 soap_server_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
648 /* Register SoapFault class */
649 INIT_CLASS_ENTRY(ce, PHP_SOAP_FAULT_CLASSNAME, soap_fault_functions);
650 soap_fault_class_entry = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
652 /* Register SoapParam class */
653 INIT_CLASS_ENTRY(ce, PHP_SOAP_PARAM_CLASSNAME, soap_param_functions);
654 soap_param_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
656 INIT_CLASS_ENTRY(ce, PHP_SOAP_HEADER_CLASSNAME, soap_header_functions);
657 soap_header_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
659 le_sdl = register_list_destructors(delete_sdl, NULL);
660 le_url = register_list_destructors(delete_url, NULL);
661 le_service = register_list_destructors(delete_service, NULL);
662 le_typemap = register_list_destructors(delete_hashtable, NULL);
664 REGISTER_LONG_CONSTANT("SOAP_1_1", SOAP_1_1, CONST_CS | CONST_PERSISTENT);
665 REGISTER_LONG_CONSTANT("SOAP_1_2", SOAP_1_2, CONST_CS | CONST_PERSISTENT);
667 REGISTER_LONG_CONSTANT("SOAP_PERSISTENCE_SESSION", SOAP_PERSISTENCE_SESSION, CONST_CS | CONST_PERSISTENT);
668 REGISTER_LONG_CONSTANT("SOAP_PERSISTENCE_REQUEST", SOAP_PERSISTENCE_REQUEST, CONST_CS | CONST_PERSISTENT);
669 REGISTER_LONG_CONSTANT("SOAP_FUNCTIONS_ALL", SOAP_FUNCTIONS_ALL, CONST_CS | CONST_PERSISTENT);
671 REGISTER_LONG_CONSTANT("SOAP_ENCODED", SOAP_ENCODED, CONST_CS | CONST_PERSISTENT);
672 REGISTER_LONG_CONSTANT("SOAP_LITERAL", SOAP_LITERAL, CONST_CS | CONST_PERSISTENT);
674 REGISTER_LONG_CONSTANT("SOAP_RPC", SOAP_RPC, CONST_CS | CONST_PERSISTENT);
675 REGISTER_LONG_CONSTANT("SOAP_DOCUMENT", SOAP_DOCUMENT, CONST_CS | CONST_PERSISTENT);
677 REGISTER_LONG_CONSTANT("SOAP_ACTOR_NEXT", SOAP_ACTOR_NEXT, CONST_CS | CONST_PERSISTENT);
678 REGISTER_LONG_CONSTANT("SOAP_ACTOR_NONE", SOAP_ACTOR_NONE, CONST_CS | CONST_PERSISTENT);
679 REGISTER_LONG_CONSTANT("SOAP_ACTOR_UNLIMATERECEIVER", SOAP_ACTOR_UNLIMATERECEIVER, CONST_CS | CONST_PERSISTENT);
681 REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_ACCEPT", SOAP_COMPRESSION_ACCEPT, CONST_CS | CONST_PERSISTENT);
682 REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_GZIP", SOAP_COMPRESSION_GZIP, CONST_CS | CONST_PERSISTENT);
683 REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_DEFLATE", SOAP_COMPRESSION_DEFLATE, CONST_CS | CONST_PERSISTENT);
685 REGISTER_LONG_CONSTANT("SOAP_AUTHENTICATION_BASIC", SOAP_AUTHENTICATION_BASIC, CONST_CS | CONST_PERSISTENT);
686 REGISTER_LONG_CONSTANT("SOAP_AUTHENTICATION_DIGEST", SOAP_AUTHENTICATION_DIGEST, CONST_CS | CONST_PERSISTENT);
688 REGISTER_LONG_CONSTANT("UNKNOWN_TYPE", UNKNOWN_TYPE, CONST_CS | CONST_PERSISTENT);
690 REGISTER_LONG_CONSTANT("XSD_STRING", XSD_STRING, CONST_CS | CONST_PERSISTENT);
691 REGISTER_LONG_CONSTANT("XSD_BOOLEAN", XSD_BOOLEAN, CONST_CS | CONST_PERSISTENT);
692 REGISTER_LONG_CONSTANT("XSD_DECIMAL", XSD_DECIMAL, CONST_CS | CONST_PERSISTENT);
693 REGISTER_LONG_CONSTANT("XSD_FLOAT", XSD_FLOAT, CONST_CS | CONST_PERSISTENT);
694 REGISTER_LONG_CONSTANT("XSD_DOUBLE", XSD_DOUBLE, CONST_CS | CONST_PERSISTENT);
695 REGISTER_LONG_CONSTANT("XSD_DURATION", XSD_DURATION, CONST_CS | CONST_PERSISTENT);
696 REGISTER_LONG_CONSTANT("XSD_DATETIME", XSD_DATETIME, CONST_CS | CONST_PERSISTENT);
697 REGISTER_LONG_CONSTANT("XSD_TIME", XSD_TIME, CONST_CS | CONST_PERSISTENT);
698 REGISTER_LONG_CONSTANT("XSD_DATE", XSD_DATE, CONST_CS | CONST_PERSISTENT);
699 REGISTER_LONG_CONSTANT("XSD_GYEARMONTH", XSD_GYEARMONTH, CONST_CS | CONST_PERSISTENT);
700 REGISTER_LONG_CONSTANT("XSD_GYEAR", XSD_GYEAR, CONST_CS | CONST_PERSISTENT);
701 REGISTER_LONG_CONSTANT("XSD_GMONTHDAY", XSD_GMONTHDAY, CONST_CS | CONST_PERSISTENT);
702 REGISTER_LONG_CONSTANT("XSD_GDAY", XSD_GDAY, CONST_CS | CONST_PERSISTENT);
703 REGISTER_LONG_CONSTANT("XSD_GMONTH", XSD_GMONTH, CONST_CS | CONST_PERSISTENT);
704 REGISTER_LONG_CONSTANT("XSD_HEXBINARY", XSD_HEXBINARY, CONST_CS | CONST_PERSISTENT);
705 REGISTER_LONG_CONSTANT("XSD_BASE64BINARY", XSD_BASE64BINARY, CONST_CS | CONST_PERSISTENT);
706 REGISTER_LONG_CONSTANT("XSD_ANYURI", XSD_ANYURI, CONST_CS | CONST_PERSISTENT);
707 REGISTER_LONG_CONSTANT("XSD_QNAME", XSD_QNAME, CONST_CS | CONST_PERSISTENT);
708 REGISTER_LONG_CONSTANT("XSD_NOTATION", XSD_NOTATION, CONST_CS | CONST_PERSISTENT);
709 REGISTER_LONG_CONSTANT("XSD_NORMALIZEDSTRING", XSD_NORMALIZEDSTRING, CONST_CS | CONST_PERSISTENT);
710 REGISTER_LONG_CONSTANT("XSD_TOKEN", XSD_TOKEN, CONST_CS | CONST_PERSISTENT);
711 REGISTER_LONG_CONSTANT("XSD_LANGUAGE", XSD_LANGUAGE, CONST_CS | CONST_PERSISTENT);
712 REGISTER_LONG_CONSTANT("XSD_NMTOKEN", XSD_NMTOKEN, CONST_CS | CONST_PERSISTENT);
713 REGISTER_LONG_CONSTANT("XSD_NAME", XSD_NAME, CONST_CS | CONST_PERSISTENT);
714 REGISTER_LONG_CONSTANT("XSD_NCNAME", XSD_NCNAME, CONST_CS | CONST_PERSISTENT);
715 REGISTER_LONG_CONSTANT("XSD_ID", XSD_ID, CONST_CS | CONST_PERSISTENT);
716 REGISTER_LONG_CONSTANT("XSD_IDREF", XSD_IDREF, CONST_CS | CONST_PERSISTENT);
717 REGISTER_LONG_CONSTANT("XSD_IDREFS", XSD_IDREFS, CONST_CS | CONST_PERSISTENT);
718 REGISTER_LONG_CONSTANT("XSD_ENTITY", XSD_ENTITY, CONST_CS | CONST_PERSISTENT);
719 REGISTER_LONG_CONSTANT("XSD_ENTITIES", XSD_ENTITIES, CONST_CS | CONST_PERSISTENT);
720 REGISTER_LONG_CONSTANT("XSD_INTEGER", XSD_INTEGER, CONST_CS | CONST_PERSISTENT);
721 REGISTER_LONG_CONSTANT("XSD_NONPOSITIVEINTEGER", XSD_NONPOSITIVEINTEGER, CONST_CS | CONST_PERSISTENT);
722 REGISTER_LONG_CONSTANT("XSD_NEGATIVEINTEGER", XSD_NEGATIVEINTEGER, CONST_CS | CONST_PERSISTENT);
723 REGISTER_LONG_CONSTANT("XSD_LONG", XSD_LONG, CONST_CS | CONST_PERSISTENT);
724 REGISTER_LONG_CONSTANT("XSD_INT", XSD_INT, CONST_CS | CONST_PERSISTENT);
725 REGISTER_LONG_CONSTANT("XSD_SHORT", XSD_SHORT, CONST_CS | CONST_PERSISTENT);
726 REGISTER_LONG_CONSTANT("XSD_BYTE", XSD_BYTE, CONST_CS | CONST_PERSISTENT);
727 REGISTER_LONG_CONSTANT("XSD_NONNEGATIVEINTEGER", XSD_NONNEGATIVEINTEGER, CONST_CS | CONST_PERSISTENT);
728 REGISTER_LONG_CONSTANT("XSD_UNSIGNEDLONG", XSD_UNSIGNEDLONG, CONST_CS | CONST_PERSISTENT);
729 REGISTER_LONG_CONSTANT("XSD_UNSIGNEDINT", XSD_UNSIGNEDINT, CONST_CS | CONST_PERSISTENT);
730 REGISTER_LONG_CONSTANT("XSD_UNSIGNEDSHORT", XSD_UNSIGNEDSHORT, CONST_CS | CONST_PERSISTENT);
731 REGISTER_LONG_CONSTANT("XSD_UNSIGNEDBYTE", XSD_UNSIGNEDBYTE, CONST_CS | CONST_PERSISTENT);
732 REGISTER_LONG_CONSTANT("XSD_POSITIVEINTEGER", XSD_POSITIVEINTEGER, CONST_CS | CONST_PERSISTENT);
733 REGISTER_LONG_CONSTANT("XSD_NMTOKENS", XSD_NMTOKENS, CONST_CS | CONST_PERSISTENT);
734 REGISTER_LONG_CONSTANT("XSD_ANYTYPE", XSD_ANYTYPE, CONST_CS | CONST_PERSISTENT);
735 REGISTER_LONG_CONSTANT("XSD_ANYXML", XSD_ANYXML, CONST_CS | CONST_PERSISTENT);
737 REGISTER_LONG_CONSTANT("APACHE_MAP", APACHE_MAP, CONST_CS | CONST_PERSISTENT);
739 REGISTER_LONG_CONSTANT("SOAP_ENC_OBJECT", SOAP_ENC_OBJECT, CONST_CS | CONST_PERSISTENT);
740 REGISTER_LONG_CONSTANT("SOAP_ENC_ARRAY", SOAP_ENC_ARRAY, CONST_CS | CONST_PERSISTENT);
742 REGISTER_LONG_CONSTANT("XSD_1999_TIMEINSTANT", XSD_1999_TIMEINSTANT, CONST_CS | CONST_PERSISTENT);
744 REGISTER_STRING_CONSTANT("XSD_NAMESPACE", XSD_NAMESPACE, CONST_CS | CONST_PERSISTENT);
745 REGISTER_STRING_CONSTANT("XSD_1999_NAMESPACE", XSD_1999_NAMESPACE, CONST_CS | CONST_PERSISTENT);
747 REGISTER_LONG_CONSTANT("SOAP_SINGLE_ELEMENT_ARRAYS", SOAP_SINGLE_ELEMENT_ARRAYS, CONST_CS | CONST_PERSISTENT);
748 REGISTER_LONG_CONSTANT("SOAP_WAIT_ONE_WAY_CALLS", SOAP_WAIT_ONE_WAY_CALLS, CONST_CS | CONST_PERSISTENT);
749 REGISTER_LONG_CONSTANT("SOAP_USE_XSI_ARRAY_TYPE", SOAP_USE_XSI_ARRAY_TYPE, CONST_CS | CONST_PERSISTENT);
751 REGISTER_LONG_CONSTANT("WSDL_CACHE_NONE", WSDL_CACHE_NONE, CONST_CS | CONST_PERSISTENT);
752 REGISTER_LONG_CONSTANT("WSDL_CACHE_DISK", WSDL_CACHE_DISK, CONST_CS | CONST_PERSISTENT);
753 REGISTER_LONG_CONSTANT("WSDL_CACHE_MEMORY", WSDL_CACHE_MEMORY, CONST_CS | CONST_PERSISTENT);
754 REGISTER_LONG_CONSTANT("WSDL_CACHE_BOTH", WSDL_CACHE_BOTH, CONST_CS | CONST_PERSISTENT);
756 old_error_handler = zend_error_cb;
757 zend_error_cb = soap_error_handler;
759 return SUCCESS;
762 PHP_MINFO_FUNCTION(soap)
764 php_info_print_table_start();
765 php_info_print_table_row(2, "Soap Client", "enabled");
766 php_info_print_table_row(2, "Soap Server", "enabled");
767 php_info_print_table_end();
768 DISPLAY_INI_ENTRIES();
772 /* {{{ proto object SoapParam::SoapParam ( mixed data, string name)
773 SoapParam constructor */
774 PHP_METHOD(SoapParam, SoapParam)
776 zval *data;
777 char *name;
778 int name_length;
780 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &data, &name, &name_length) == FAILURE) {
781 return;
783 if (name_length == 0) {
784 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parameter name");
785 return;
788 add_property_stringl(this_ptr, "param_name", name, name_length, 1);
789 add_property_zval(this_ptr, "param_data", data);
791 /* }}} */
794 /* {{{ proto object SoapHeader::SoapHeader ( string namespace, string name [, mixed data [, bool mustUnderstand [, mixed actor]]])
795 SoapHeader constructor */
796 PHP_METHOD(SoapHeader, SoapHeader)
798 zval *data = NULL, *actor = NULL;
799 char *name, *ns;
800 int name_len, ns_len;
801 zend_bool must_understand = 0;
803 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|zbz", &ns, &ns_len, &name, &name_len, &data, &must_understand, &actor) == FAILURE) {
804 return;
806 if (ns_len == 0) {
807 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid namespace");
808 return;
810 if (name_len == 0) {
811 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid header name");
812 return;
815 add_property_stringl(this_ptr, "namespace", ns, ns_len, 1);
816 add_property_stringl(this_ptr, "name", name, name_len, 1);
817 if (data) {
818 add_property_zval(this_ptr, "data", data);
820 add_property_bool(this_ptr, "mustUnderstand", must_understand);
821 if (actor == NULL) {
822 } else if (Z_TYPE_P(actor) == IS_LONG &&
823 (Z_LVAL_P(actor) == SOAP_ACTOR_NEXT ||
824 Z_LVAL_P(actor) == SOAP_ACTOR_NONE ||
825 Z_LVAL_P(actor) == SOAP_ACTOR_UNLIMATERECEIVER)) {
826 add_property_long(this_ptr, "actor", Z_LVAL_P(actor));
827 } else if (Z_TYPE_P(actor) == IS_STRING && Z_STRLEN_P(actor) > 0) {
828 add_property_stringl(this_ptr, "actor", Z_STRVAL_P(actor), Z_STRLEN_P(actor), 1);
829 } else {
830 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid actor");
834 /* {{{ proto object SoapFault::SoapFault ( string faultcode, string faultstring [, string faultactor [, mixed detail [, string faultname [, mixed headerfault]]]])
835 SoapFault constructor */
836 PHP_METHOD(SoapFault, SoapFault)
838 char *fault_string = NULL, *fault_code = NULL, *fault_actor = NULL, *name = NULL, *fault_code_ns = NULL;
839 int fault_string_len, fault_actor_len = 0, name_len = 0, fault_code_len = 0;
840 zval *code = NULL, *details = NULL, *headerfault = NULL;
842 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs|s!z!s!z",
843 &code,
844 &fault_string, &fault_string_len,
845 &fault_actor, &fault_actor_len,
846 &details, &name, &name_len, &headerfault) == FAILURE) {
847 return;
850 if (Z_TYPE_P(code) == IS_NULL) {
851 } else if (Z_TYPE_P(code) == IS_STRING) {
852 fault_code = Z_STRVAL_P(code);
853 fault_code_len = Z_STRLEN_P(code);
854 } else if (Z_TYPE_P(code) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(code)) == 2) {
855 zval **t_ns, **t_code;
857 zend_hash_internal_pointer_reset(Z_ARRVAL_P(code));
858 zend_hash_get_current_data(Z_ARRVAL_P(code), (void**)&t_ns);
859 zend_hash_move_forward(Z_ARRVAL_P(code));
860 zend_hash_get_current_data(Z_ARRVAL_P(code), (void**)&t_code);
861 if (Z_TYPE_PP(t_ns) == IS_STRING && Z_TYPE_PP(t_code) == IS_STRING) {
862 fault_code_ns = Z_STRVAL_PP(t_ns);
863 fault_code = Z_STRVAL_PP(t_code);
864 fault_code_len = Z_STRLEN_PP(t_code);
865 } else {
866 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid fault code");
867 return;
869 } else {
870 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid fault code");
871 return;
873 if (fault_code != NULL && fault_code_len == 0) {
874 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid fault code");
875 return;
877 if (name != NULL && name_len == 0) {
878 name = NULL;
881 set_soap_fault(this_ptr, fault_code_ns, fault_code, fault_string, fault_actor, details, name TSRMLS_CC);
882 if (headerfault != NULL) {
883 add_property_zval(this_ptr, "headerfault", headerfault);
886 /* }}} */
889 /* {{{ proto object SoapFault::SoapFault ( string faultcode, string faultstring [, string faultactor [, mixed detail [, string faultname [, mixed headerfault]]]])
890 SoapFault constructor */
891 PHP_METHOD(SoapFault, __toString)
893 zval *faultcode, *faultstring, *file, *line, *trace;
894 char *str;
895 int len;
896 zend_fcall_info fci;
897 zval fname;
899 if (zend_parse_parameters_none() == FAILURE) {
900 return;
903 faultcode = zend_read_property(soap_fault_class_entry, this_ptr, "faultcode", sizeof("faultcode")-1, 1 TSRMLS_CC);
904 faultstring = zend_read_property(soap_fault_class_entry, this_ptr, "faultstring", sizeof("faultstring")-1, 1 TSRMLS_CC);
905 file = zend_read_property(soap_fault_class_entry, this_ptr, "file", sizeof("file")-1, 1 TSRMLS_CC);
906 line = zend_read_property(soap_fault_class_entry, this_ptr, "line", sizeof("line")-1, 1 TSRMLS_CC);
908 ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1, 0);
910 fci.size = sizeof(fci);
911 fci.function_table = &Z_OBJCE_P(getThis())->function_table;
912 fci.function_name = &fname;
913 fci.symbol_table = NULL;
914 fci.object_ptr = getThis();
915 fci.retval_ptr_ptr = &trace;
916 fci.param_count = 0;
917 fci.params = NULL;
918 fci.no_separation = 1;
920 zend_call_function(&fci, NULL TSRMLS_CC);
922 len = spprintf(&str, 0, "SoapFault exception: [%s] %s in %s:%ld\nStack trace:\n%s",
923 Z_STRVAL_P(faultcode), Z_STRVAL_P(faultstring), Z_STRVAL_P(file), Z_LVAL_P(line),
924 Z_STRLEN_P(trace) ? Z_STRVAL_P(trace) : "#0 {main}\n");
926 zval_ptr_dtor(&trace);
928 RETURN_STRINGL(str, len, 0);
930 /* }}} */
932 /* {{{ proto object SoapVar::SoapVar ( mixed data, int encoding [, string type_name [, string type_namespace [, string node_name [, string node_namespace]]]])
933 SoapVar constructor */
934 PHP_METHOD(SoapVar, SoapVar)
936 zval *data, *type;
937 char *stype = NULL, *ns = NULL, *name = NULL, *namens = NULL;
938 int stype_len = 0, ns_len = 0, name_len = 0, namens_len = 0;
940 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!z|ssss", &data, &type, &stype, &stype_len, &ns, &ns_len, &name, &name_len, &namens, &namens_len) == FAILURE) {
941 return;
944 if (Z_TYPE_P(type) == IS_NULL) {
945 add_property_long(this_ptr, "enc_type", UNKNOWN_TYPE);
946 } else {
947 if (zend_hash_index_exists(&SOAP_GLOBAL(defEncIndex), Z_LVAL_P(type))) {
948 add_property_long(this_ptr, "enc_type", Z_LVAL_P(type));
949 } else {
950 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type ID");
951 return;
955 if (data) {
956 add_property_zval(this_ptr, "enc_value", data);
959 if (stype && stype_len > 0) {
960 add_property_stringl(this_ptr, "enc_stype", stype, stype_len, 1);
962 if (ns && ns_len > 0) {
963 add_property_stringl(this_ptr, "enc_ns", ns, ns_len, 1);
965 if (name && name_len > 0) {
966 add_property_stringl(this_ptr, "enc_name", name, name_len, 1);
968 if (namens && namens_len > 0) {
969 add_property_stringl(this_ptr, "enc_namens", namens, namens_len, 1);
972 /* }}} */
975 static HashTable* soap_create_typemap(sdlPtr sdl, HashTable *ht TSRMLS_DC)
977 zval **tmp;
978 HashTable *ht2;
979 HashPosition pos1, pos2;
980 HashTable *typemap = NULL;
982 zend_hash_internal_pointer_reset_ex(ht, &pos1);
983 while (zend_hash_get_current_data_ex(ht, (void**)&tmp, &pos1) == SUCCESS) {
984 char *type_name = NULL;
985 char *type_ns = NULL;
986 zval *to_xml = NULL;
987 zval *to_zval = NULL;
988 encodePtr enc, new_enc;
990 if (Z_TYPE_PP(tmp) != IS_ARRAY) {
991 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Wrong 'typemap' option");
992 return NULL;
994 ht2 = Z_ARRVAL_PP(tmp);
996 zend_hash_internal_pointer_reset_ex(ht2, &pos2);
997 while (zend_hash_get_current_data_ex(ht2, (void**)&tmp, &pos2) == SUCCESS) {
998 char *name = NULL;
999 unsigned int name_len;
1000 ulong index;
1002 zend_hash_get_current_key_ex(ht2, &name, &name_len, &index, 0, &pos2);
1003 if (name) {
1004 if (name_len == sizeof("type_name") &&
1005 strncmp(name, "type_name", sizeof("type_name")-1) == 0) {
1006 if (Z_TYPE_PP(tmp) == IS_STRING) {
1007 type_name = Z_STRVAL_PP(tmp);
1008 } else if (Z_TYPE_PP(tmp) != IS_NULL) {
1010 } else if (name_len == sizeof("type_ns") &&
1011 strncmp(name, "type_ns", sizeof("type_ns")-1) == 0) {
1012 if (Z_TYPE_PP(tmp) == IS_STRING) {
1013 type_ns = Z_STRVAL_PP(tmp);
1014 } else if (Z_TYPE_PP(tmp) != IS_NULL) {
1016 } else if (name_len == sizeof("to_xml") &&
1017 strncmp(name, "to_xml", sizeof("to_xml")-1) == 0) {
1018 to_xml = *tmp;
1019 } else if (name_len == sizeof("from_xml") &&
1020 strncmp(name, "from_xml", sizeof("from_xml")-1) == 0) {
1021 to_zval = *tmp;
1024 zend_hash_move_forward_ex(ht2, &pos2);
1027 if (type_name) {
1028 smart_str nscat = {0};
1030 if (type_ns) {
1031 enc = get_encoder(sdl, type_ns, type_name);
1032 } else {
1033 enc = get_encoder_ex(sdl, type_name, strlen(type_name));
1036 new_enc = emalloc(sizeof(encode));
1037 memset(new_enc, 0, sizeof(encode));
1039 if (enc) {
1040 new_enc->details.type = enc->details.type;
1041 new_enc->details.ns = estrdup(enc->details.ns);
1042 new_enc->details.type_str = estrdup(enc->details.type_str);
1043 new_enc->details.sdl_type = enc->details.sdl_type;
1044 } else {
1045 enc = get_conversion(UNKNOWN_TYPE);
1046 new_enc->details.type = enc->details.type;
1047 if (type_ns) {
1048 new_enc->details.ns = estrdup(type_ns);
1050 new_enc->details.type_str = estrdup(type_name);
1052 new_enc->to_xml = enc->to_xml;
1053 new_enc->to_zval = enc->to_zval;
1054 new_enc->details.map = emalloc(sizeof(soapMapping));
1055 memset(new_enc->details.map, 0, sizeof(soapMapping));
1056 if (to_xml) {
1057 zval_add_ref(&to_xml);
1058 new_enc->details.map->to_xml = to_xml;
1059 new_enc->to_xml = to_xml_user;
1060 } else if (enc->details.map && enc->details.map->to_xml) {
1061 zval_add_ref(&enc->details.map->to_xml);
1062 new_enc->details.map->to_xml = enc->details.map->to_xml;
1064 if (to_zval) {
1065 zval_add_ref(&to_zval);
1066 new_enc->details.map->to_zval = to_zval;
1067 new_enc->to_zval = to_zval_user;
1068 } else if (enc->details.map && enc->details.map->to_zval) {
1069 zval_add_ref(&enc->details.map->to_zval);
1070 new_enc->details.map->to_zval = enc->details.map->to_zval;
1072 if (!typemap) {
1073 typemap = emalloc(sizeof(HashTable));
1074 zend_hash_init(typemap, 0, NULL, delete_encoder, 0);
1077 if (type_ns) {
1078 smart_str_appends(&nscat, type_ns);
1079 smart_str_appendc(&nscat, ':');
1081 smart_str_appends(&nscat, type_name);
1082 smart_str_0(&nscat);
1083 zend_hash_update(typemap, nscat.c, nscat.len + 1, &new_enc, sizeof(encodePtr), NULL);
1084 smart_str_free(&nscat);
1086 zend_hash_move_forward_ex(ht, &pos1);
1088 return typemap;
1092 /* {{{ proto object SoapServer::SoapServer ( mixed wsdl [, array options])
1093 SoapServer constructor */
1094 PHP_METHOD(SoapServer, SoapServer)
1096 soapServicePtr service;
1097 zval *wsdl = NULL, *options = NULL;
1098 int ret;
1099 int version = SOAP_1_1;
1100 long cache_wsdl;
1101 HashTable *typemap_ht = NULL;
1103 SOAP_SERVER_BEGIN_CODE();
1105 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &wsdl, &options) == FAILURE) {
1106 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
1109 if (Z_TYPE_P(wsdl) != IS_STRING && Z_TYPE_P(wsdl) != IS_NULL) {
1110 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
1113 service = emalloc(sizeof(soapService));
1114 memset(service, 0, sizeof(soapService));
1115 service->send_errors = 1;
1117 cache_wsdl = SOAP_GLOBAL(cache_enabled) ? SOAP_GLOBAL(cache_mode) : 0;
1119 if (options != NULL) {
1120 HashTable *ht = Z_ARRVAL_P(options);
1121 zval **tmp;
1123 if (zend_hash_find(ht, "soap_version", sizeof("soap_version"), (void**)&tmp) == SUCCESS) {
1124 if (Z_TYPE_PP(tmp) == IS_LONG &&
1125 (Z_LVAL_PP(tmp) == SOAP_1_1 || Z_LVAL_PP(tmp) == SOAP_1_2)) {
1126 version = Z_LVAL_PP(tmp);
1127 } else {
1128 php_error_docref(NULL TSRMLS_CC, E_ERROR, "'soap_version' option must be SOAP_1_1 or SOAP_1_2");
1132 if (zend_hash_find(ht, "uri", sizeof("uri"), (void**)&tmp) == SUCCESS &&
1133 Z_TYPE_PP(tmp) == IS_STRING) {
1134 service->uri = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
1135 } else if (Z_TYPE_P(wsdl) == IS_NULL) {
1136 php_error_docref(NULL TSRMLS_CC, E_ERROR, "'uri' option is required in nonWSDL mode");
1139 if (zend_hash_find(ht, "actor", sizeof("actor"), (void**)&tmp) == SUCCESS &&
1140 Z_TYPE_PP(tmp) == IS_STRING) {
1141 service->actor = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
1144 if (zend_hash_find(ht, "encoding", sizeof("encoding"), (void**)&tmp) == SUCCESS &&
1145 Z_TYPE_PP(tmp) == IS_STRING) {
1146 xmlCharEncodingHandlerPtr encoding;
1148 encoding = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
1149 if (encoding == NULL) {
1150 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid 'encoding' option - '%s'", Z_STRVAL_PP(tmp));
1151 } else {
1152 service->encoding = encoding;
1156 if (zend_hash_find(ht, "classmap", sizeof("classmap"), (void**)&tmp) == SUCCESS &&
1157 Z_TYPE_PP(tmp) == IS_ARRAY) {
1158 zval *ztmp;
1160 ALLOC_HASHTABLE(service->class_map);
1161 zend_hash_init(service->class_map, zend_hash_num_elements((*tmp)->value.ht), NULL, ZVAL_PTR_DTOR, 0);
1162 zend_hash_copy(service->class_map, (*tmp)->value.ht, (copy_ctor_func_t) zval_add_ref, (void *) &ztmp, sizeof(zval *));
1165 if (zend_hash_find(ht, "typemap", sizeof("typemap"), (void**)&tmp) == SUCCESS &&
1166 Z_TYPE_PP(tmp) == IS_ARRAY &&
1167 zend_hash_num_elements(Z_ARRVAL_PP(tmp)) > 0) {
1168 typemap_ht = Z_ARRVAL_PP(tmp);
1171 if (zend_hash_find(ht, "features", sizeof("features"), (void**)&tmp) == SUCCESS &&
1172 Z_TYPE_PP(tmp) == IS_LONG) {
1173 service->features = Z_LVAL_PP(tmp);
1176 if (zend_hash_find(ht, "cache_wsdl", sizeof("cache_wsdl"), (void**)&tmp) == SUCCESS &&
1177 Z_TYPE_PP(tmp) == IS_LONG) {
1178 cache_wsdl = Z_LVAL_PP(tmp);
1181 if (zend_hash_find(ht, "send_errors", sizeof("send_errors"), (void**)&tmp) == SUCCESS &&
1182 (Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG)) {
1183 service->send_errors = Z_LVAL_PP(tmp);
1186 } else if (Z_TYPE_P(wsdl) == IS_NULL) {
1187 php_error_docref(NULL TSRMLS_CC, E_ERROR, "'uri' option is required in nonWSDL mode");
1190 service->version = version;
1191 service->type = SOAP_FUNCTIONS;
1192 service->soap_functions.functions_all = FALSE;
1193 service->soap_functions.ft = emalloc(sizeof(HashTable));
1194 zend_hash_init(service->soap_functions.ft, 0, NULL, ZVAL_PTR_DTOR, 0);
1196 if (Z_TYPE_P(wsdl) != IS_NULL) {
1197 service->sdl = get_sdl(this_ptr, Z_STRVAL_P(wsdl), cache_wsdl TSRMLS_CC);
1198 if (service->uri == NULL) {
1199 if (service->sdl->target_ns) {
1200 service->uri = estrdup(service->sdl->target_ns);
1201 } else {
1202 /*FIXME*/
1203 service->uri = estrdup("http://unknown-uri/");
1208 if (typemap_ht) {
1209 service->typemap = soap_create_typemap(service->sdl, typemap_ht TSRMLS_CC);
1212 ret = zend_list_insert(service, le_service TSRMLS_CC);
1213 add_property_resource(this_ptr, "service", ret);
1215 SOAP_SERVER_END_CODE();
1217 /* }}} */
1220 /* {{{ proto object SoapServer::setPersistence ( int mode )
1221 Sets persistence mode of SoapServer */
1222 PHP_METHOD(SoapServer, setPersistence)
1224 soapServicePtr service;
1225 long value;
1227 SOAP_SERVER_BEGIN_CODE();
1229 FETCH_THIS_SERVICE(service);
1231 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) != FAILURE) {
1232 if (service->type == SOAP_CLASS) {
1233 if (value == SOAP_PERSISTENCE_SESSION ||
1234 value == SOAP_PERSISTENCE_REQUEST) {
1235 service->soap_class.persistance = value;
1236 } else {
1237 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to set persistence with bogus value (%ld)", value);
1238 return;
1240 } else {
1241 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to set persistence when you are using you SOAP SERVER in function mode, no persistence needed");
1242 return;
1246 SOAP_SERVER_END_CODE();
1248 /* }}} */
1251 /* {{{ proto void SoapServer::setClass(string class_name [, mixed args])
1252 Sets class which will handle SOAP requests */
1253 PHP_METHOD(SoapServer, setClass)
1255 soapServicePtr service;
1256 char *classname;
1257 zend_class_entry **ce;
1259 int classname_len, found, num_args = 0;
1260 zval ***argv = NULL;
1262 SOAP_SERVER_BEGIN_CODE();
1264 FETCH_THIS_SERVICE(service);
1266 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s*", &classname, &classname_len, &argv, &num_args) == FAILURE) {
1267 return;
1270 found = zend_lookup_class(classname, classname_len, &ce TSRMLS_CC);
1272 if (found != FAILURE) {
1273 service->type = SOAP_CLASS;
1274 service->soap_class.ce = *ce;
1276 service->soap_class.persistance = SOAP_PERSISTENCE_REQUEST;
1277 service->soap_class.argc = num_args;
1278 if (service->soap_class.argc > 0) {
1279 int i;
1280 service->soap_class.argv = safe_emalloc(sizeof(zval), service->soap_class.argc, 0);
1281 for (i = 0;i < service->soap_class.argc;i++) {
1282 service->soap_class.argv[i] = *(argv[i]);
1283 zval_add_ref(&service->soap_class.argv[i]);
1286 } else {
1287 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to set a non existant class (%s)", classname);
1288 return;
1291 if (argv) {
1292 efree(argv);
1295 SOAP_SERVER_END_CODE();
1297 /* }}} */
1300 /* {{{ proto void SoapServer::setObject(object)
1301 Sets object which will handle SOAP requests */
1302 PHP_METHOD(SoapServer, setObject)
1304 soapServicePtr service;
1305 zval *obj;
1307 SOAP_SERVER_BEGIN_CODE();
1309 FETCH_THIS_SERVICE(service);
1311 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
1312 return;
1315 service->type = SOAP_OBJECT;
1317 MAKE_STD_ZVAL(service->soap_object);
1318 MAKE_COPY_ZVAL(&obj, service->soap_object);
1320 SOAP_SERVER_END_CODE();
1322 /* }}} */
1325 /* {{{ proto array SoapServer::getFunctions(void)
1326 Returns list of defined functions */
1327 PHP_METHOD(SoapServer, getFunctions)
1329 soapServicePtr service;
1330 HashTable *ft = NULL;
1332 SOAP_SERVER_BEGIN_CODE();
1334 if (zend_parse_parameters_none() == FAILURE) {
1335 return;
1338 FETCH_THIS_SERVICE(service);
1340 array_init(return_value);
1341 if (service->type == SOAP_OBJECT) {
1342 ft = &(Z_OBJCE_P(service->soap_object)->function_table);
1343 } else if (service->type == SOAP_CLASS) {
1344 ft = &service->soap_class.ce->function_table;
1345 } else if (service->soap_functions.functions_all == TRUE) {
1346 ft = EG(function_table);
1347 } else if (service->soap_functions.ft != NULL) {
1348 zval **name;
1349 HashPosition pos;
1351 zend_hash_internal_pointer_reset_ex(service->soap_functions.ft, &pos);
1352 while (zend_hash_get_current_data_ex(service->soap_functions.ft, (void **)&name, &pos) != FAILURE) {
1353 add_next_index_string(return_value, Z_STRVAL_PP(name), 1);
1354 zend_hash_move_forward_ex(service->soap_functions.ft, &pos);
1357 if (ft != NULL) {
1358 zend_function *f;
1359 HashPosition pos;
1360 zend_hash_internal_pointer_reset_ex(ft, &pos);
1361 while (zend_hash_get_current_data_ex(ft, (void **)&f, &pos) != FAILURE) {
1362 if ((service->type != SOAP_OBJECT && service->type != SOAP_CLASS) || (f->common.fn_flags & ZEND_ACC_PUBLIC)) {
1363 add_next_index_string(return_value, f->common.function_name, 1);
1365 zend_hash_move_forward_ex(ft, &pos);
1369 SOAP_SERVER_END_CODE();
1371 /* }}} */
1374 /* {{{ proto void SoapServer::addFunction(mixed functions)
1375 Adds one or several functions those will handle SOAP requests */
1376 PHP_METHOD(SoapServer, addFunction)
1378 soapServicePtr service;
1379 zval *function_name, *function_copy;
1380 HashPosition pos;
1382 SOAP_SERVER_BEGIN_CODE();
1384 FETCH_THIS_SERVICE(service);
1386 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &function_name) == FAILURE) {
1387 return;
1390 /* TODO: could use zend_is_callable here */
1392 if (function_name->type == IS_ARRAY) {
1393 if (service->type == SOAP_FUNCTIONS) {
1394 zval **tmp_function, *function_copy;
1396 if (service->soap_functions.ft == NULL) {
1397 service->soap_functions.functions_all = FALSE;
1398 service->soap_functions.ft = emalloc(sizeof(HashTable));
1399 zend_hash_init(service->soap_functions.ft, zend_hash_num_elements(Z_ARRVAL_P(function_name)), NULL, ZVAL_PTR_DTOR, 0);
1402 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(function_name), &pos);
1403 while (zend_hash_get_current_data_ex(Z_ARRVAL_P(function_name), (void **)&tmp_function, &pos) != FAILURE) {
1404 char *key;
1405 int key_len;
1406 zend_function *f;
1408 if (Z_TYPE_PP(tmp_function) != IS_STRING) {
1409 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to add a function that isn't a string");
1410 return;
1413 key_len = Z_STRLEN_PP(tmp_function);
1414 key = emalloc(key_len + 1);
1415 zend_str_tolower_copy(key, Z_STRVAL_PP(tmp_function), key_len);
1417 if (zend_hash_find(EG(function_table), key, key_len+1, (void**)&f) == FAILURE) {
1418 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to add a non existant function '%s'", Z_STRVAL_PP(tmp_function));
1419 return;
1422 MAKE_STD_ZVAL(function_copy);
1423 ZVAL_STRING(function_copy, f->common.function_name, 1);
1424 zend_hash_update(service->soap_functions.ft, key, key_len+1, &function_copy, sizeof(zval *), NULL);
1426 efree(key);
1427 zend_hash_move_forward_ex(Z_ARRVAL_P(function_name), &pos);
1430 } else if (function_name->type == IS_STRING) {
1431 char *key;
1432 int key_len;
1433 zend_function *f;
1435 key_len = Z_STRLEN_P(function_name);
1436 key = emalloc(key_len + 1);
1437 zend_str_tolower_copy(key, Z_STRVAL_P(function_name), key_len);
1439 if (zend_hash_find(EG(function_table), key, key_len+1, (void**)&f) == FAILURE) {
1440 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to add a non existant function '%s'", Z_STRVAL_P(function_name));
1441 return;
1443 if (service->soap_functions.ft == NULL) {
1444 service->soap_functions.functions_all = FALSE;
1445 service->soap_functions.ft = emalloc(sizeof(HashTable));
1446 zend_hash_init(service->soap_functions.ft, 0, NULL, ZVAL_PTR_DTOR, 0);
1449 MAKE_STD_ZVAL(function_copy);
1450 ZVAL_STRING(function_copy, f->common.function_name, 1);
1451 zend_hash_update(service->soap_functions.ft, key, key_len+1, &function_copy, sizeof(zval *), NULL);
1452 efree(key);
1453 } else if (function_name->type == IS_LONG) {
1454 if (Z_LVAL_P(function_name) == SOAP_FUNCTIONS_ALL) {
1455 if (service->soap_functions.ft != NULL) {
1456 zend_hash_destroy(service->soap_functions.ft);
1457 efree(service->soap_functions.ft);
1458 service->soap_functions.ft = NULL;
1460 service->soap_functions.functions_all = TRUE;
1461 } else {
1462 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value passed");
1463 return;
1467 SOAP_SERVER_END_CODE();
1469 /* }}} */
1472 /* {{{ proto void SoapServer::handle ( [string soap_request])
1473 Handles a SOAP request */
1474 PHP_METHOD(SoapServer, handle)
1476 int soap_version, old_soap_version;
1477 sdlPtr old_sdl = NULL;
1478 soapServicePtr service;
1479 xmlDocPtr doc_request=NULL, doc_return;
1480 zval function_name, **params, *soap_obj, *retval;
1481 char *fn_name, cont_len[30];
1482 int num_params = 0, size, i, call_status = 0;
1483 xmlChar *buf;
1484 HashTable *function_table;
1485 soapHeader *soap_headers = NULL;
1486 sdlFunctionPtr function;
1487 char *arg = NULL;
1488 int arg_len = 0;
1489 xmlCharEncodingHandlerPtr old_encoding;
1490 HashTable *old_class_map, *old_typemap;
1491 int old_features;
1493 SOAP_SERVER_BEGIN_CODE();
1495 FETCH_THIS_SERVICE(service);
1496 SOAP_GLOBAL(soap_version) = service->version;
1498 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &arg, &arg_len) == FAILURE) {
1499 return;
1502 if (SG(request_info).request_method &&
1503 strcmp(SG(request_info).request_method, "GET") == 0 &&
1504 SG(request_info).query_string &&
1505 stricmp(SG(request_info).query_string, "wsdl") == 0) {
1507 if (service->sdl) {
1509 char *hdr = emalloc(sizeof("Location: ")+strlen(service->sdl->source));
1510 strcpy(hdr,"Location: ");
1511 strcat(hdr,service->sdl->source);
1512 sapi_add_header(hdr, sizeof("Location: ")+strlen(service->sdl->source)-1, 1);
1513 efree(hdr);
1515 zval readfile, readfile_ret, *param;
1517 INIT_ZVAL(readfile);
1518 INIT_ZVAL(readfile_ret);
1519 MAKE_STD_ZVAL(param);
1521 sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
1522 ZVAL_STRING(param, service->sdl->source, 1);
1523 ZVAL_STRING(&readfile, "readfile", 1);
1524 if (call_user_function(EG(function_table), NULL, &readfile, &readfile_ret, 1, &param TSRMLS_CC) == FAILURE) {
1525 soap_server_fault("Server", "Couldn't find WSDL", NULL, NULL, NULL TSRMLS_CC);
1528 zval_ptr_dtor(&param);
1529 zval_dtor(&readfile);
1530 zval_dtor(&readfile_ret);
1532 SOAP_SERVER_END_CODE();
1533 return;
1534 } else {
1535 soap_server_fault("Server", "WSDL generation is not supported yet", NULL, NULL, NULL TSRMLS_CC);
1537 sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8"), 1);
1538 PUTS("<?xml version=\"1.0\" ?>\n<definitions\n");
1539 PUTS(" xmlns=\"http://schemas.xmlsoap.org/wsdl/\"\n");
1540 PUTS(" targetNamespace=\"");
1541 PUTS(service->uri);
1542 PUTS("\">\n");
1543 PUTS("</definitions>");
1545 SOAP_SERVER_END_CODE();
1546 return;
1550 ALLOC_INIT_ZVAL(retval);
1552 if (php_output_start_default(TSRMLS_C) != SUCCESS) {
1553 php_error_docref(NULL TSRMLS_CC, E_ERROR,"ob_start failed");
1556 if (ZEND_NUM_ARGS() == 0) {
1557 if (SG(request_info).raw_post_data) {
1558 char *post_data = SG(request_info).raw_post_data;
1559 int post_data_length = SG(request_info).raw_post_data_length;
1560 zval **server_vars, **encoding;
1562 zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
1563 if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &server_vars) == SUCCESS &&
1564 Z_TYPE_PP(server_vars) == IS_ARRAY &&
1565 zend_hash_find(Z_ARRVAL_PP(server_vars), "HTTP_CONTENT_ENCODING", sizeof("HTTP_CONTENT_ENCODING"), (void **) &encoding)==SUCCESS &&
1566 Z_TYPE_PP(encoding) == IS_STRING) {
1567 zval func;
1568 zval retval;
1569 zval param;
1570 zval *params[1];
1572 if ((strcmp(Z_STRVAL_PP(encoding),"gzip") == 0 ||
1573 strcmp(Z_STRVAL_PP(encoding),"x-gzip") == 0) &&
1574 zend_hash_exists(EG(function_table), "gzinflate", sizeof("gzinflate"))) {
1575 ZVAL_STRING(&func, "gzinflate", 0);
1576 params[0] = &param;
1577 ZVAL_STRINGL(params[0], post_data+10, post_data_length-10, 0);
1578 INIT_PZVAL(params[0]);
1579 } else if (strcmp(Z_STRVAL_PP(encoding),"deflate") == 0 &&
1580 zend_hash_exists(EG(function_table), "gzuncompress", sizeof("gzuncompress"))) {
1581 ZVAL_STRING(&func, "gzuncompress", 0);
1582 params[0] = &param;
1583 ZVAL_STRINGL(params[0], post_data, post_data_length, 0);
1584 INIT_PZVAL(params[0]);
1585 } else {
1586 php_error_docref(NULL TSRMLS_CC, E_WARNING,"Request is compressed with unknown compression '%s'",Z_STRVAL_PP(encoding));
1587 return;
1589 if (call_user_function(CG(function_table), (zval**)NULL, &func, &retval, 1, params TSRMLS_CC) == SUCCESS &&
1590 Z_TYPE(retval) == IS_STRING) {
1591 doc_request = soap_xmlParseMemory(Z_STRVAL(retval),Z_STRLEN(retval));
1592 zval_dtor(&retval);
1593 } else {
1594 php_error_docref(NULL TSRMLS_CC, E_WARNING,"Can't uncompress compressed request");
1595 return;
1597 } else {
1598 doc_request = soap_xmlParseMemory(post_data, post_data_length);
1600 } else {
1601 zval_ptr_dtor(&retval);
1602 return;
1604 } else {
1605 doc_request = soap_xmlParseMemory(arg,arg_len);
1608 if (doc_request == NULL) {
1609 soap_server_fault("Client", "Bad Request", NULL, NULL, NULL TSRMLS_CC);
1611 if (xmlGetIntSubset(doc_request) != NULL) {
1612 xmlNodePtr env = get_node(doc_request->children,"Envelope");
1613 if (env && env->ns) {
1614 if (strcmp((char*)env->ns->href, SOAP_1_1_ENV_NAMESPACE) == 0) {
1615 SOAP_GLOBAL(soap_version) = SOAP_1_1;
1616 } else if (strcmp((char*)env->ns->href,SOAP_1_2_ENV_NAMESPACE) == 0) {
1617 SOAP_GLOBAL(soap_version) = SOAP_1_2;
1620 xmlFreeDoc(doc_request);
1621 soap_server_fault("Server", "DTD are not supported by SOAP", NULL, NULL, NULL TSRMLS_CC);
1624 old_sdl = SOAP_GLOBAL(sdl);
1625 SOAP_GLOBAL(sdl) = service->sdl;
1626 old_encoding = SOAP_GLOBAL(encoding);
1627 SOAP_GLOBAL(encoding) = service->encoding;
1628 old_class_map = SOAP_GLOBAL(class_map);
1629 SOAP_GLOBAL(class_map) = service->class_map;
1630 old_typemap = SOAP_GLOBAL(typemap);
1631 SOAP_GLOBAL(typemap) = service->typemap;
1632 old_features = SOAP_GLOBAL(features);
1633 SOAP_GLOBAL(features) = service->features;
1634 old_soap_version = SOAP_GLOBAL(soap_version);
1635 function = deserialize_function_call(service->sdl, doc_request, service->actor, &function_name, &num_params, &params, &soap_version, &soap_headers TSRMLS_CC);
1636 xmlFreeDoc(doc_request);
1638 if (EG(exception)) {
1639 php_output_discard(TSRMLS_C);
1640 if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
1641 instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
1642 soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
1644 goto fail;
1647 service->soap_headers_ptr = &soap_headers;
1649 soap_obj = NULL;
1650 if (service->type == SOAP_OBJECT) {
1651 soap_obj = service->soap_object;
1652 function_table = &((Z_OBJCE_P(soap_obj))->function_table);
1653 } else if (service->type == SOAP_CLASS) {
1654 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
1655 /* If persistent then set soap_obj from from the previous created session (if available) */
1656 if (service->soap_class.persistance == SOAP_PERSISTENCE_SESSION) {
1657 zval **tmp_soap;
1659 if (PS(session_status) != php_session_active &&
1660 PS(session_status) != php_session_disabled) {
1661 php_session_start(TSRMLS_C);
1664 /* Find the soap object and assign */
1665 if (zend_hash_find(Z_ARRVAL_P(PS(http_session_vars)), "_bogus_session_name", sizeof("_bogus_session_name"), (void **) &tmp_soap) == SUCCESS &&
1666 Z_TYPE_PP(tmp_soap) == IS_OBJECT &&
1667 Z_OBJCE_PP(tmp_soap) == service->soap_class.ce) {
1668 soap_obj = *tmp_soap;
1671 #endif
1672 /* If new session or something wierd happned */
1673 if (soap_obj == NULL) {
1674 zval *tmp_soap;
1676 MAKE_STD_ZVAL(tmp_soap);
1677 object_init_ex(tmp_soap, service->soap_class.ce);
1679 /* Call constructor */
1680 if (zend_hash_exists(&Z_OBJCE_P(tmp_soap)->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {
1681 zval c_ret, constructor;
1683 INIT_ZVAL(c_ret);
1684 INIT_ZVAL(constructor);
1686 ZVAL_STRING(&constructor, ZEND_CONSTRUCTOR_FUNC_NAME, 1);
1687 if (call_user_function(NULL, &tmp_soap, &constructor, &c_ret, service->soap_class.argc, service->soap_class.argv TSRMLS_CC) == FAILURE) {
1688 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error calling constructor");
1690 if (EG(exception)) {
1691 php_output_discard(TSRMLS_C);
1692 if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
1693 instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
1694 soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
1696 zval_dtor(&constructor);
1697 zval_dtor(&c_ret);
1698 zval_ptr_dtor(&tmp_soap);
1699 goto fail;
1701 zval_dtor(&constructor);
1702 zval_dtor(&c_ret);
1703 } else {
1704 int class_name_len = strlen(service->soap_class.ce->name);
1705 char *class_name = emalloc(class_name_len+1);
1707 memcpy(class_name, service->soap_class.ce->name,class_name_len+1);
1708 if (zend_hash_exists(&Z_OBJCE_P(tmp_soap)->function_table, php_strtolower(class_name, class_name_len), class_name_len+1)) {
1709 zval c_ret, constructor;
1711 INIT_ZVAL(c_ret);
1712 INIT_ZVAL(constructor);
1714 ZVAL_STRING(&constructor, service->soap_class.ce->name, 1);
1715 if (call_user_function(NULL, &tmp_soap, &constructor, &c_ret, service->soap_class.argc, service->soap_class.argv TSRMLS_CC) == FAILURE) {
1716 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error calling constructor");
1719 if (EG(exception)) {
1720 php_output_discard(TSRMLS_C);
1721 if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
1722 instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
1723 soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
1725 zval_dtor(&constructor);
1726 zval_dtor(&c_ret);
1727 efree(class_name);
1728 zval_ptr_dtor(&tmp_soap);
1729 goto fail;
1732 zval_dtor(&constructor);
1733 zval_dtor(&c_ret);
1735 efree(class_name);
1737 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
1738 /* If session then update session hash with new object */
1739 if (service->soap_class.persistance == SOAP_PERSISTENCE_SESSION) {
1740 zval **tmp_soap_pp;
1741 if (zend_hash_update(Z_ARRVAL_P(PS(http_session_vars)), "_bogus_session_name", sizeof("_bogus_session_name"), &tmp_soap, sizeof(zval *), (void **)&tmp_soap_pp) == SUCCESS) {
1742 soap_obj = *tmp_soap_pp;
1744 } else {
1745 soap_obj = tmp_soap;
1747 #else
1748 soap_obj = tmp_soap;
1749 #endif
1752 function_table = &((Z_OBJCE_P(soap_obj))->function_table);
1753 } else {
1754 if (service->soap_functions.functions_all == TRUE) {
1755 function_table = EG(function_table);
1756 } else {
1757 function_table = service->soap_functions.ft;
1761 doc_return = NULL;
1763 /* Process soap headers */
1764 if (soap_headers != NULL) {
1765 soapHeader *header = soap_headers;
1766 while (header != NULL) {
1767 soapHeader *h = header;
1769 header = header->next;
1770 #if 0
1771 if (service->sdl && !h->function && !h->hdr) {
1772 if (h->mustUnderstand) {
1773 soap_server_fault("MustUnderstand","Header not understood", NULL, NULL, NULL TSRMLS_CC);
1774 } else {
1775 continue;
1778 #endif
1779 fn_name = estrndup(Z_STRVAL(h->function_name),Z_STRLEN(h->function_name));
1780 if (zend_hash_exists(function_table, php_strtolower(fn_name, Z_STRLEN(h->function_name)), Z_STRLEN(h->function_name) + 1) ||
1781 ((service->type == SOAP_CLASS || service->type == SOAP_OBJECT) &&
1782 zend_hash_exists(function_table, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) {
1783 if (service->type == SOAP_CLASS || service->type == SOAP_OBJECT) {
1784 call_status = call_user_function(NULL, &soap_obj, &h->function_name, &h->retval, h->num_params, h->parameters TSRMLS_CC);
1785 } else {
1786 call_status = call_user_function(EG(function_table), NULL, &h->function_name, &h->retval, h->num_params, h->parameters TSRMLS_CC);
1788 if (call_status != SUCCESS) {
1789 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function '%s' call failed", Z_STRVAL(h->function_name));
1790 return;
1792 if (Z_TYPE(h->retval) == IS_OBJECT &&
1793 instanceof_function(Z_OBJCE(h->retval), soap_fault_class_entry TSRMLS_CC)) {
1794 zval *headerfault = NULL, **tmp;
1796 if (zend_hash_find(Z_OBJPROP(h->retval), "headerfault", sizeof("headerfault"), (void**)&tmp) == SUCCESS &&
1797 Z_TYPE_PP(tmp) != IS_NULL) {
1798 headerfault = *tmp;
1800 php_output_discard(TSRMLS_C);
1801 soap_server_fault_ex(function, &h->retval, h TSRMLS_CC);
1802 efree(fn_name);
1803 if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(&soap_obj);}
1804 goto fail;
1805 } else if (EG(exception)) {
1806 php_output_discard(TSRMLS_C);
1807 if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
1808 instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
1809 zval *headerfault = NULL, **tmp;
1811 if (zend_hash_find(Z_OBJPROP_P(EG(exception)), "headerfault", sizeof("headerfault"), (void**)&tmp) == SUCCESS &&
1812 Z_TYPE_PP(tmp) != IS_NULL) {
1813 headerfault = *tmp;
1815 soap_server_fault_ex(function, EG(exception), h TSRMLS_CC);
1817 efree(fn_name);
1818 if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(&soap_obj);}
1819 goto fail;
1821 } else if (h->mustUnderstand) {
1822 soap_server_fault("MustUnderstand","Header not understood", NULL, NULL, NULL TSRMLS_CC);
1824 efree(fn_name);
1828 fn_name = estrndup(Z_STRVAL(function_name),Z_STRLEN(function_name));
1829 if (zend_hash_exists(function_table, php_strtolower(fn_name, Z_STRLEN(function_name)), Z_STRLEN(function_name) + 1) ||
1830 ((service->type == SOAP_CLASS || service->type == SOAP_OBJECT) &&
1831 zend_hash_exists(function_table, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) {
1832 if (service->type == SOAP_CLASS || service->type == SOAP_OBJECT) {
1833 call_status = call_user_function(NULL, &soap_obj, &function_name, retval, num_params, params TSRMLS_CC);
1834 if (service->type == SOAP_CLASS) {
1835 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
1836 if (service->soap_class.persistance != SOAP_PERSISTENCE_SESSION) {
1837 zval_ptr_dtor(&soap_obj);
1838 soap_obj = NULL;
1840 #else
1841 zval_ptr_dtor(&soap_obj);
1842 soap_obj = NULL;
1843 #endif
1845 } else {
1846 call_status = call_user_function(EG(function_table), NULL, &function_name, retval, num_params, params TSRMLS_CC);
1848 } else {
1849 php_error(E_ERROR, "Function '%s' doesn't exist", Z_STRVAL(function_name));
1851 efree(fn_name);
1853 if (EG(exception)) {
1854 php_output_discard(TSRMLS_C);
1855 if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
1856 instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
1857 soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
1859 if (service->type == SOAP_CLASS) {
1860 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
1861 if (soap_obj && service->soap_class.persistance != SOAP_PERSISTENCE_SESSION) {
1862 #else
1863 if (soap_obj) {
1864 #endif
1865 zval_ptr_dtor(&soap_obj);
1868 goto fail;
1871 if (call_status == SUCCESS) {
1872 char *response_name;
1874 if (Z_TYPE_P(retval) == IS_OBJECT &&
1875 instanceof_function(Z_OBJCE_P(retval), soap_fault_class_entry TSRMLS_CC)) {
1876 php_output_discard(TSRMLS_C);
1877 soap_server_fault_ex(function, retval, NULL TSRMLS_CC);
1878 goto fail;
1881 if (function && function->responseName) {
1882 response_name = estrdup(function->responseName);
1883 } else {
1884 response_name = emalloc(Z_STRLEN(function_name) + sizeof("Response"));
1885 memcpy(response_name,Z_STRVAL(function_name),Z_STRLEN(function_name));
1886 memcpy(response_name+Z_STRLEN(function_name),"Response",sizeof("Response"));
1888 doc_return = serialize_response_call(function, response_name, service->uri, retval, soap_headers, soap_version TSRMLS_CC);
1889 efree(response_name);
1890 } else {
1891 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function '%s' call failed", Z_STRVAL(function_name));
1892 return;
1895 if (EG(exception)) {
1896 php_output_discard(TSRMLS_C);
1897 if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
1898 instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
1899 soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
1901 if (service->type == SOAP_CLASS) {
1902 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
1903 if (soap_obj && service->soap_class.persistance != SOAP_PERSISTENCE_SESSION) {
1904 #else
1905 if (soap_obj) {
1906 #endif
1907 zval_ptr_dtor(&soap_obj);
1910 goto fail;
1913 /* Flush buffer */
1914 php_output_discard(TSRMLS_C);
1916 if (doc_return) {
1917 /* xmlDocDumpMemoryEnc(doc_return, &buf, &size, XML_CHAR_ENCODING_UTF8); */
1918 xmlDocDumpMemory(doc_return, &buf, &size);
1920 if (size == 0) {
1921 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Dump memory failed");
1924 if (soap_version == SOAP_1_2) {
1925 sapi_add_header("Content-Type: application/soap+xml; charset=utf-8", sizeof("Content-Type: application/soap+xml; charset=utf-8")-1, 1);
1926 } else {
1927 sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
1930 xmlFreeDoc(doc_return);
1932 if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0)) {
1933 sapi_add_header("Connection: close", sizeof("Connection: close")-1, 1);
1934 } else {
1935 snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", size);
1936 sapi_add_header(cont_len, strlen(cont_len), 1);
1938 php_write(buf, size TSRMLS_CC);
1939 xmlFree(buf);
1940 } else {
1941 sapi_add_header("HTTP/1.1 202 Accepted", sizeof("HTTP/1.1 202 Accepted")-1, 1);
1942 sapi_add_header("Content-Length: 0", sizeof("Content-Length: 0")-1, 1);
1945 fail:
1946 SOAP_GLOBAL(soap_version) = old_soap_version;
1947 SOAP_GLOBAL(encoding) = old_encoding;
1948 SOAP_GLOBAL(sdl) = old_sdl;
1949 SOAP_GLOBAL(class_map) = old_class_map;
1950 SOAP_GLOBAL(typemap) = old_typemap;
1951 SOAP_GLOBAL(features) = old_features;
1953 /* Free soap headers */
1954 zval_ptr_dtor(&retval);
1955 while (soap_headers != NULL) {
1956 soapHeader *h = soap_headers;
1957 int i;
1959 soap_headers = soap_headers->next;
1960 if (h->parameters) {
1961 i = h->num_params;
1962 while (i > 0) {
1963 zval_ptr_dtor(&h->parameters[--i]);
1965 efree(h->parameters);
1967 zval_dtor(&h->function_name);
1968 zval_dtor(&h->retval);
1969 efree(h);
1971 service->soap_headers_ptr = NULL;
1973 /* Free Memory */
1974 if (num_params > 0) {
1975 for (i = 0; i < num_params;i++) {
1976 zval_ptr_dtor(&params[i]);
1978 efree(params);
1980 zval_dtor(&function_name);
1982 SOAP_SERVER_END_CODE();
1984 /* }}} */
1987 /* {{{ proto SoapServer::fault ( staring code, string string [, string actor [, mixed details [, string name]]] )
1988 Issue SoapFault indicating an error */
1989 PHP_METHOD(SoapServer, fault)
1991 char *code, *string, *actor=NULL, *name=NULL;
1992 int code_len, string_len, actor_len = 0, name_len = 0;
1993 zval* details = NULL;
1994 soapServicePtr service;
1995 xmlCharEncodingHandlerPtr old_encoding;
1997 SOAP_SERVER_BEGIN_CODE();
1998 FETCH_THIS_SERVICE(service);
1999 old_encoding = SOAP_GLOBAL(encoding);
2000 SOAP_GLOBAL(encoding) = service->encoding;
2002 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|szs",
2003 &code, &code_len, &string, &string_len, &actor, &actor_len, &details,
2004 &name, &name_len) == FAILURE) {
2005 return;
2008 soap_server_fault(code, string, actor, details, name TSRMLS_CC);
2010 SOAP_GLOBAL(encoding) = old_encoding;
2011 SOAP_SERVER_END_CODE();
2013 /* }}} */
2015 PHP_METHOD(SoapServer, addSoapHeader)
2017 soapServicePtr service;
2018 zval *fault;
2019 soapHeader **p;
2021 SOAP_SERVER_BEGIN_CODE();
2023 FETCH_THIS_SERVICE(service);
2025 if (!service || !service->soap_headers_ptr) {
2026 php_error_docref(NULL TSRMLS_CC, E_WARNING, "The SoapServer::addSoapHeader function may be called only during SOAP request processing");
2027 return;
2030 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &fault, soap_header_class_entry) == FAILURE) {
2031 return;
2034 p = service->soap_headers_ptr;
2035 while (*p != NULL) {
2036 p = &(*p)->next;
2038 *p = emalloc(sizeof(soapHeader));
2039 memset(*p, 0, sizeof(soapHeader));
2040 ZVAL_NULL(&(*p)->function_name);
2041 (*p)->retval = *fault;
2042 zval_copy_ctor(&(*p)->retval);
2044 SOAP_SERVER_END_CODE();
2047 static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeader *hdr TSRMLS_DC)
2049 int soap_version;
2050 xmlChar *buf;
2051 char cont_len[30];
2052 int size;
2053 xmlDocPtr doc_return;
2054 zval **agent_name;
2055 int use_http_error_status = 1;
2057 soap_version = SOAP_GLOBAL(soap_version);
2059 doc_return = serialize_response_call(function, NULL, NULL, fault, hdr, soap_version TSRMLS_CC);
2061 xmlDocDumpMemory(doc_return, &buf, &size);
2063 zend_is_auto_global("_SERVER", sizeof("_SERVER") - 1 TSRMLS_CC);
2064 if (PG(http_globals)[TRACK_VARS_SERVER] &&
2065 zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT"), (void **) &agent_name) == SUCCESS &&
2066 Z_TYPE_PP(agent_name) == IS_STRING) {
2067 if (strncmp(Z_STRVAL_PP(agent_name), "Shockwave Flash", sizeof("Shockwave Flash")-1) == 0) {
2068 use_http_error_status = 0;
2072 Want to return HTTP 500 but apache wants to over write
2073 our fault code with their own handling... Figure this out later
2075 if (use_http_error_status) {
2076 sapi_add_header("HTTP/1.1 500 Internal Service Error", sizeof("HTTP/1.1 500 Internal Service Error")-1, 1);
2078 if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0)) {
2079 sapi_add_header("Connection: close", sizeof("Connection: close")-1, 1);
2080 } else {
2081 snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", size);
2082 sapi_add_header(cont_len, strlen(cont_len), 1);
2084 if (soap_version == SOAP_1_2) {
2085 sapi_add_header("Content-Type: application/soap+xml; charset=utf-8", sizeof("Content-Type: application/soap+xml; charset=utf-8")-1, 1);
2086 } else {
2087 sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
2090 php_write(buf, size TSRMLS_CC);
2092 xmlFreeDoc(doc_return);
2093 xmlFree(buf);
2094 zend_clear_exception(TSRMLS_C);
2097 static void soap_server_fault(char* code, char* string, char *actor, zval* details, char* name TSRMLS_DC)
2099 zval ret;
2101 INIT_ZVAL(ret);
2103 set_soap_fault(&ret, NULL, code, string, actor, details, name TSRMLS_CC);
2104 /* TODO: Which function */
2105 soap_server_fault_ex(NULL, &ret, NULL TSRMLS_CC);
2106 zend_bailout();
2109 static void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args)
2111 zend_bool _old_in_compilation, _old_in_execution;
2112 zend_execute_data *_old_current_execute_data;
2113 int _old_http_response_code;
2114 char *_old_http_status_line;
2115 TSRMLS_FETCH();
2117 _old_in_compilation = CG(in_compilation);
2118 _old_in_execution = EG(in_execution);
2119 _old_current_execute_data = EG(current_execute_data);
2120 _old_http_response_code = SG(sapi_headers).http_response_code;
2121 _old_http_status_line = SG(sapi_headers).http_status_line;
2123 if (!SOAP_GLOBAL(use_soap_error_handler) || !EG(objects_store).object_buckets) {
2124 call_old_error_handler(error_num, error_filename, error_lineno, format, args);
2125 return;
2128 if (SOAP_GLOBAL(error_object) &&
2129 Z_TYPE_P(SOAP_GLOBAL(error_object)) == IS_OBJECT &&
2130 instanceof_function(Z_OBJCE_P(SOAP_GLOBAL(error_object)), soap_class_entry TSRMLS_CC)) {
2131 zval **tmp;
2132 int use_exceptions = 0;
2134 if (zend_hash_find(Z_OBJPROP_P(SOAP_GLOBAL(error_object)), "_exceptions", sizeof("_exceptions"), (void **) &tmp) != SUCCESS ||
2135 Z_TYPE_PP(tmp) != IS_BOOL || Z_LVAL_PP(tmp) != 0) {
2136 use_exceptions = 1;
2139 if ((error_num == E_USER_ERROR ||
2140 error_num == E_COMPILE_ERROR ||
2141 error_num == E_CORE_ERROR ||
2142 error_num == E_ERROR ||
2143 error_num == E_PARSE) &&
2144 use_exceptions) {
2145 zval *fault, *exception;
2146 char* code = SOAP_GLOBAL(error_code);
2147 char buffer[1024];
2148 int buffer_len;
2149 zval outbuf, outbuflen;
2150 #ifdef va_copy
2151 va_list argcopy;
2152 #endif
2153 zend_object_store_bucket *old_objects;
2154 int old = PG(display_errors);
2156 INIT_ZVAL(outbuf);
2157 INIT_ZVAL(outbuflen);
2158 #ifdef va_copy
2159 va_copy(argcopy, args);
2160 buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, argcopy);
2161 va_end(argcopy);
2162 #else
2163 buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, args);
2164 #endif
2165 buffer[sizeof(buffer)-1]=0;
2166 if (buffer_len > sizeof(buffer) - 1 || buffer_len < 0) {
2167 buffer_len = sizeof(buffer) - 1;
2170 if (code == NULL) {
2171 code = "Client";
2173 fault = add_soap_fault(SOAP_GLOBAL(error_object), code, buffer, NULL, NULL TSRMLS_CC);
2174 MAKE_STD_ZVAL(exception);
2175 MAKE_COPY_ZVAL(&fault, exception);
2176 zend_throw_exception_object(exception TSRMLS_CC);
2178 old_objects = EG(objects_store).object_buckets;
2179 EG(objects_store).object_buckets = NULL;
2180 PG(display_errors) = 0;
2181 SG(sapi_headers).http_status_line = NULL;
2182 zend_try {
2183 call_old_error_handler(error_num, error_filename, error_lineno, format, args);
2184 } zend_catch {
2185 CG(in_compilation) = _old_in_compilation;
2186 EG(in_execution) = _old_in_execution;
2187 EG(current_execute_data) = _old_current_execute_data;
2188 if (SG(sapi_headers).http_status_line) {
2189 efree(SG(sapi_headers).http_status_line);
2191 SG(sapi_headers).http_status_line = _old_http_status_line;
2192 SG(sapi_headers).http_response_code = _old_http_response_code;
2193 } zend_end_try();
2194 EG(objects_store).object_buckets = old_objects;
2195 PG(display_errors) = old;
2196 zend_bailout();
2197 } else if (!use_exceptions ||
2198 !SOAP_GLOBAL(error_code) ||
2199 strcmp(SOAP_GLOBAL(error_code),"WSDL") != 0) {
2200 /* Ignore libxml warnings during WSDL parsing */
2201 call_old_error_handler(error_num, error_filename, error_lineno, format, args);
2203 } else {
2204 int old = PG(display_errors);
2205 int fault = 0;
2206 zval fault_obj;
2207 #ifdef va_copy
2208 va_list argcopy;
2209 #endif
2211 if (error_num == E_USER_ERROR ||
2212 error_num == E_COMPILE_ERROR ||
2213 error_num == E_CORE_ERROR ||
2214 error_num == E_ERROR ||
2215 error_num == E_PARSE) {
2217 char* code = SOAP_GLOBAL(error_code);
2218 char buffer[1024];
2219 zval *outbuf = NULL;
2220 zval **tmp;
2221 soapServicePtr service;
2223 if (code == NULL) {
2224 code = "Server";
2226 if (SOAP_GLOBAL(error_object) &&
2227 Z_TYPE_P(SOAP_GLOBAL(error_object)) == IS_OBJECT &&
2228 instanceof_function(Z_OBJCE_P(SOAP_GLOBAL(error_object)), soap_server_class_entry TSRMLS_CC) &&
2229 zend_hash_find(Z_OBJPROP_P(SOAP_GLOBAL(error_object)), "service", sizeof("service"), (void **)&tmp) != FAILURE &&
2230 (service = (soapServicePtr)zend_fetch_resource(tmp TSRMLS_CC, -1, "service", NULL, 1, le_service)) &&
2231 !service->send_errors) {
2232 strcpy(buffer, "Internal Error");
2233 } else {
2234 int buffer_len;
2235 zval outbuflen;
2237 INIT_ZVAL(outbuflen);
2239 #ifdef va_copy
2240 va_copy(argcopy, args);
2241 buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, argcopy);
2242 va_end(argcopy);
2243 #else
2244 buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, args);
2245 #endif
2246 buffer[sizeof(buffer)-1]=0;
2247 if (buffer_len > sizeof(buffer) - 1 || buffer_len < 0) {
2248 buffer_len = sizeof(buffer) - 1;
2251 /* Get output buffer and send as fault detials */
2252 if (php_output_get_length(&outbuflen TSRMLS_CC) != FAILURE && Z_LVAL(outbuflen) != 0) {
2253 ALLOC_INIT_ZVAL(outbuf);
2254 php_output_get_contents(outbuf TSRMLS_CC);
2256 php_output_discard(TSRMLS_C);
2259 INIT_ZVAL(fault_obj);
2260 set_soap_fault(&fault_obj, NULL, code, buffer, NULL, outbuf, NULL TSRMLS_CC);
2261 fault = 1;
2264 PG(display_errors) = 0;
2265 SG(sapi_headers).http_status_line = NULL;
2266 zend_try {
2267 call_old_error_handler(error_num, error_filename, error_lineno, format, args);
2268 } zend_catch {
2269 CG(in_compilation) = _old_in_compilation;
2270 EG(in_execution) = _old_in_execution;
2271 EG(current_execute_data) = _old_current_execute_data;
2272 if (SG(sapi_headers).http_status_line) {
2273 efree(SG(sapi_headers).http_status_line);
2275 SG(sapi_headers).http_status_line = _old_http_status_line;
2276 SG(sapi_headers).http_response_code = _old_http_response_code;
2277 } zend_end_try();
2278 PG(display_errors) = old;
2280 if (fault) {
2281 soap_server_fault_ex(NULL, &fault_obj, NULL TSRMLS_CC);
2282 zend_bailout();
2287 PHP_FUNCTION(use_soap_error_handler)
2289 zend_bool handler = 1;
2291 ZVAL_BOOL(return_value, SOAP_GLOBAL(use_soap_error_handler));
2292 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &handler) == SUCCESS) {
2293 SOAP_GLOBAL(use_soap_error_handler) = handler;
2297 PHP_FUNCTION(is_soap_fault)
2299 zval *fault;
2301 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &fault) == SUCCESS &&
2302 Z_TYPE_P(fault) == IS_OBJECT &&
2303 instanceof_function(Z_OBJCE_P(fault), soap_fault_class_entry TSRMLS_CC)) {
2304 RETURN_TRUE;
2306 RETURN_FALSE
2309 /* SoapClient functions */
2311 /* {{{ proto object SoapClient::SoapClient ( mixed wsdl [, array options])
2312 SoapClient constructor */
2313 PHP_METHOD(SoapClient, SoapClient)
2316 zval *wsdl, *options = NULL;
2317 int soap_version = SOAP_1_1;
2318 php_stream_context *context = NULL;
2319 long cache_wsdl;
2320 sdlPtr sdl = NULL;
2321 HashTable *typemap_ht = NULL;
2323 SOAP_CLIENT_BEGIN_CODE();
2325 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &wsdl, &options) == FAILURE) {
2326 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
2329 if (Z_TYPE_P(wsdl) != IS_STRING && Z_TYPE_P(wsdl) != IS_NULL) {
2330 php_error_docref(NULL TSRMLS_CC, E_ERROR, "$wsdl must be string or null");
2333 cache_wsdl = SOAP_GLOBAL(cache_enabled) ? SOAP_GLOBAL(cache_mode) : 0;
2335 if (options != NULL) {
2336 HashTable *ht = Z_ARRVAL_P(options);
2337 zval **tmp;
2339 if (Z_TYPE_P(wsdl) == IS_NULL) {
2340 /* Fetching non-WSDL mode options */
2341 if (zend_hash_find(ht, "uri", sizeof("uri"), (void**)&tmp) == SUCCESS &&
2342 Z_TYPE_PP(tmp) == IS_STRING) {
2343 add_property_stringl(this_ptr, "uri", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2344 } else {
2345 php_error_docref(NULL TSRMLS_CC, E_ERROR, "'uri' option is required in nonWSDL mode");
2348 if (zend_hash_find(ht, "style", sizeof("style"), (void**)&tmp) == SUCCESS &&
2349 Z_TYPE_PP(tmp) == IS_LONG &&
2350 (Z_LVAL_PP(tmp) == SOAP_RPC || Z_LVAL_PP(tmp) == SOAP_DOCUMENT)) {
2351 add_property_long(this_ptr, "style", Z_LVAL_PP(tmp));
2354 if (zend_hash_find(ht, "use", sizeof("use"), (void**)&tmp) == SUCCESS &&
2355 Z_TYPE_PP(tmp) == IS_LONG &&
2356 (Z_LVAL_PP(tmp) == SOAP_LITERAL || Z_LVAL_PP(tmp) == SOAP_ENCODED)) {
2357 add_property_long(this_ptr, "use", Z_LVAL_PP(tmp));
2361 if (zend_hash_find(ht, "stream_context", sizeof("stream_context"), (void**)&tmp) == SUCCESS &&
2362 Z_TYPE_PP(tmp) == IS_RESOURCE) {
2363 context = php_stream_context_from_zval(*tmp, 1);
2364 zend_list_addref(context->rsrc_id);
2367 if (zend_hash_find(ht, "location", sizeof("location"), (void**)&tmp) == SUCCESS &&
2368 Z_TYPE_PP(tmp) == IS_STRING) {
2369 add_property_stringl(this_ptr, "location", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2370 } else if (Z_TYPE_P(wsdl) == IS_NULL) {
2371 php_error_docref(NULL TSRMLS_CC, E_ERROR, "'location' option is required in nonWSDL mode");
2374 if (zend_hash_find(ht, "soap_version", sizeof("soap_version"), (void**)&tmp) == SUCCESS) {
2375 if (Z_TYPE_PP(tmp) == IS_LONG ||
2376 (Z_LVAL_PP(tmp) == SOAP_1_1 && Z_LVAL_PP(tmp) == SOAP_1_2)) {
2377 soap_version = Z_LVAL_PP(tmp);
2380 if (zend_hash_find(ht, "login", sizeof("login"), (void**)&tmp) == SUCCESS &&
2381 Z_TYPE_PP(tmp) == IS_STRING) {
2382 add_property_stringl(this_ptr, "_login", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2383 if (zend_hash_find(ht, "password", sizeof("password"), (void**)&tmp) == SUCCESS &&
2384 Z_TYPE_PP(tmp) == IS_STRING) {
2385 add_property_stringl(this_ptr, "_password", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2387 if (zend_hash_find(ht, "authentication", sizeof("authentication"), (void**)&tmp) == SUCCESS &&
2388 Z_TYPE_PP(tmp) == IS_LONG &&
2389 Z_LVAL_PP(tmp) == SOAP_AUTHENTICATION_DIGEST) {
2390 add_property_null(this_ptr, "_digest");
2393 if (zend_hash_find(ht, "proxy_host", sizeof("proxy_host"), (void**)&tmp) == SUCCESS &&
2394 Z_TYPE_PP(tmp) == IS_STRING) {
2395 add_property_stringl(this_ptr, "_proxy_host", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2396 if (zend_hash_find(ht, "proxy_port", sizeof("proxy_port"), (void**)&tmp) == SUCCESS) {
2397 convert_to_long(*tmp);
2398 add_property_long(this_ptr, "_proxy_port", Z_LVAL_PP(tmp));
2400 if (zend_hash_find(ht, "proxy_login", sizeof("proxy_login"), (void**)&tmp) == SUCCESS &&
2401 Z_TYPE_PP(tmp) == IS_STRING) {
2402 add_property_stringl(this_ptr, "_proxy_login", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2403 if (zend_hash_find(ht, "proxy_password", sizeof("proxy_password"), (void**)&tmp) == SUCCESS &&
2404 Z_TYPE_PP(tmp) == IS_STRING) {
2405 add_property_stringl(this_ptr, "_proxy_password", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2409 if (zend_hash_find(ht, "local_cert", sizeof("local_cert"), (void**)&tmp) == SUCCESS &&
2410 Z_TYPE_PP(tmp) == IS_STRING) {
2411 if (!context) {
2412 context = php_stream_context_alloc(TSRMLS_C);
2414 php_stream_context_set_option(context, "ssl", "local_cert", *tmp);
2415 if (zend_hash_find(ht, "passphrase", sizeof("passphrase"), (void**)&tmp) == SUCCESS &&
2416 Z_TYPE_PP(tmp) == IS_STRING) {
2417 php_stream_context_set_option(context, "ssl", "passphrase", *tmp);
2420 if (zend_hash_find(ht, "trace", sizeof("trace"), (void**)&tmp) == SUCCESS &&
2421 (Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG) &&
2422 Z_LVAL_PP(tmp) == 1) {
2423 add_property_long(this_ptr, "trace", 1);
2426 if (zend_hash_find(ht, "exceptions", sizeof("exceptions"), (void**)&tmp) == SUCCESS &&
2427 (Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG) &&
2428 Z_LVAL_PP(tmp) == 0) {
2429 add_property_bool(this_ptr, "_exceptions", 0);
2432 if (zend_hash_find(ht, "compression", sizeof("compression"), (void**)&tmp) == SUCCESS &&
2433 Z_TYPE_PP(tmp) == IS_LONG &&
2434 zend_hash_exists(EG(function_table), "gzinflate", sizeof("gzinflate")) &&
2435 zend_hash_exists(EG(function_table), "gzdeflate", sizeof("gzdeflate")) &&
2436 zend_hash_exists(EG(function_table), "gzuncompress", sizeof("gzuncompress")) &&
2437 zend_hash_exists(EG(function_table), "gzcompress", sizeof("gzcompress")) &&
2438 zend_hash_exists(EG(function_table), "gzencode", sizeof("gzencode"))) {
2439 add_property_long(this_ptr, "compression", Z_LVAL_PP(tmp));
2441 if (zend_hash_find(ht, "encoding", sizeof("encoding"), (void**)&tmp) == SUCCESS &&
2442 Z_TYPE_PP(tmp) == IS_STRING) {
2443 xmlCharEncodingHandlerPtr encoding;
2445 encoding = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
2446 if (encoding == NULL) {
2447 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid 'encoding' option - '%s'", Z_STRVAL_PP(tmp));
2448 } else {
2449 xmlCharEncCloseFunc(encoding);
2450 add_property_stringl(this_ptr, "_encoding", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2453 if (zend_hash_find(ht, "classmap", sizeof("classmap"), (void**)&tmp) == SUCCESS &&
2454 Z_TYPE_PP(tmp) == IS_ARRAY) {
2455 zval *class_map;
2457 MAKE_STD_ZVAL(class_map);
2458 MAKE_COPY_ZVAL(tmp, class_map);
2459 Z_DELREF_P(class_map);
2461 add_property_zval(this_ptr, "_classmap", class_map);
2464 if (zend_hash_find(ht, "typemap", sizeof("typemap"), (void**)&tmp) == SUCCESS &&
2465 Z_TYPE_PP(tmp) == IS_ARRAY &&
2466 zend_hash_num_elements(Z_ARRVAL_PP(tmp)) > 0) {
2467 typemap_ht = Z_ARRVAL_PP(tmp);
2470 if (zend_hash_find(ht, "features", sizeof("features"), (void**)&tmp) == SUCCESS &&
2471 Z_TYPE_PP(tmp) == IS_LONG) {
2472 add_property_long(this_ptr, "_features", Z_LVAL_PP(tmp));
2475 if (zend_hash_find(ht, "connection_timeout", sizeof("connection_timeout"), (void**)&tmp) == SUCCESS) {
2476 convert_to_long(*tmp);
2477 if (Z_LVAL_PP(tmp) > 0) {
2478 add_property_long(this_ptr, "_connection_timeout", Z_LVAL_PP(tmp));
2482 if (context) {
2483 add_property_resource(this_ptr, "_stream_context", context->rsrc_id);
2486 if (zend_hash_find(ht, "cache_wsdl", sizeof("cache_wsdl"), (void**)&tmp) == SUCCESS &&
2487 Z_TYPE_PP(tmp) == IS_LONG) {
2488 cache_wsdl = Z_LVAL_PP(tmp);
2491 if (zend_hash_find(ht, "user_agent", sizeof("user_agent"), (void**)&tmp) == SUCCESS &&
2492 Z_TYPE_PP(tmp) == IS_STRING) {
2493 add_property_stringl(this_ptr, "_user_agent", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2496 if (zend_hash_find(ht, "keep_alive", sizeof("keep_alive"), (void**)&tmp) == SUCCESS &&
2497 (Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG) && Z_LVAL_PP(tmp) == 0) {
2498 add_property_long(this_ptr, "_keep_alive", 0);
2500 } else if (Z_TYPE_P(wsdl) == IS_NULL) {
2501 php_error_docref(NULL TSRMLS_CC, E_ERROR, "'location' and 'uri' options are required in nonWSDL mode");
2504 add_property_long(this_ptr, "_soap_version", soap_version);
2506 if (Z_TYPE_P(wsdl) != IS_NULL) {
2507 int old_soap_version, ret;
2509 old_soap_version = SOAP_GLOBAL(soap_version);
2510 SOAP_GLOBAL(soap_version) = soap_version;
2512 sdl = get_sdl(this_ptr, Z_STRVAL_P(wsdl), cache_wsdl TSRMLS_CC);
2513 ret = zend_list_insert(sdl, le_sdl TSRMLS_CC);
2515 add_property_resource(this_ptr, "sdl", ret);
2517 SOAP_GLOBAL(soap_version) = old_soap_version;
2520 if (typemap_ht) {
2521 HashTable *typemap = soap_create_typemap(sdl, typemap_ht TSRMLS_CC);
2522 if (typemap) {
2523 int ret;
2525 ret = zend_list_insert(typemap, le_typemap TSRMLS_CC);
2526 add_property_resource(this_ptr, "typemap", ret);
2529 SOAP_CLIENT_END_CODE();
2531 /* }}} */
2533 static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *action, int version, int one_way, zval *response TSRMLS_DC)
2535 int ret = TRUE;
2536 char *buf;
2537 int buf_size;
2538 zval func, param0, param1, param2, param3, param4;
2539 zval *params[5];
2540 zval **trace;
2541 zval **fault;
2543 INIT_ZVAL(*response);
2545 xmlDocDumpMemory(request, (xmlChar**)&buf, &buf_size);
2546 if (!buf) {
2547 add_soap_fault(this_ptr, "HTTP", "Error build soap request", NULL, NULL TSRMLS_CC);
2548 return FALSE;
2551 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS &&
2552 Z_LVAL_PP(trace) > 0) {
2553 add_property_stringl(this_ptr, "__last_request", buf, buf_size, 1);
2556 INIT_ZVAL(func);
2557 ZVAL_STRINGL(&func,"__doRequest",sizeof("__doRequest")-1,0);
2558 INIT_ZVAL(param0);
2559 params[0] = &param0;
2560 ZVAL_STRINGL(params[0], buf, buf_size, 0);
2561 INIT_ZVAL(param1);
2562 params[1] = &param1;
2563 if (location == NULL) {
2564 ZVAL_NULL(params[1]);
2565 } else {
2566 ZVAL_STRING(params[1], location, 0);
2568 INIT_ZVAL(param2);
2569 params[2] = &param2;
2570 if (action == NULL) {
2571 ZVAL_NULL(params[2]);
2572 } else {
2573 ZVAL_STRING(params[2], action, 0);
2575 INIT_ZVAL(param3);
2576 params[3] = &param3;
2577 ZVAL_LONG(params[3], version);
2579 INIT_ZVAL(param4);
2580 params[4] = &param4;
2581 ZVAL_LONG(params[4], one_way);
2583 if (call_user_function(NULL, &this_ptr, &func, response, 5, params TSRMLS_CC) != SUCCESS) {
2584 add_soap_fault(this_ptr, "Client", "SoapClient::__doRequest() failed", NULL, NULL TSRMLS_CC);
2585 ret = FALSE;
2586 } else if (Z_TYPE_P(response) != IS_STRING) {
2587 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault"), (void **) &fault) == FAILURE) {
2588 add_soap_fault(this_ptr, "Client", "SoapClient::__doRequest() returned non string value", NULL, NULL TSRMLS_CC);
2590 ret = FALSE;
2591 } else if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS &&
2592 Z_LVAL_PP(trace) > 0) {
2593 add_property_stringl(this_ptr, "__last_response", Z_STRVAL_P(response), Z_STRLEN_P(response), 1);
2595 xmlFree(buf);
2596 if (ret && zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault"), (void **) &fault) == SUCCESS) {
2597 return FALSE;
2599 return ret;
2602 static void do_soap_call(zval* this_ptr,
2603 char* function,
2604 int function_len,
2605 int arg_count,
2606 zval** real_args,
2607 zval* return_value,
2608 char* location,
2609 char* soap_action,
2610 char* call_uri,
2611 HashTable* soap_headers,
2612 zval* output_headers
2613 TSRMLS_DC)
2615 zval **tmp;
2616 zval **trace;
2617 sdlPtr sdl = NULL;
2618 sdlPtr old_sdl = NULL;
2619 sdlFunctionPtr fn;
2620 xmlDocPtr request = NULL;
2621 int ret = FALSE;
2622 int soap_version;
2623 zval response;
2624 xmlCharEncodingHandlerPtr old_encoding;
2625 HashTable *old_class_map;
2626 int old_features;
2627 HashTable *old_typemap, *typemap = NULL;
2629 SOAP_CLIENT_BEGIN_CODE();
2631 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS
2632 && Z_LVAL_PP(trace) > 0) {
2633 zend_hash_del(Z_OBJPROP_P(this_ptr), "__last_request", sizeof("__last_request"));
2634 zend_hash_del(Z_OBJPROP_P(this_ptr), "__last_response", sizeof("__last_response"));
2636 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_soap_version", sizeof("_soap_version"), (void **) &tmp) == SUCCESS
2637 && Z_LVAL_PP(tmp) == SOAP_1_2) {
2638 soap_version = SOAP_1_2;
2639 } else {
2640 soap_version = SOAP_1_1;
2643 if (location == NULL) {
2644 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "location", sizeof("location"),(void **) &tmp) == SUCCESS &&
2645 Z_TYPE_PP(tmp) == IS_STRING) {
2646 location = Z_STRVAL_PP(tmp);
2650 if (FIND_SDL_PROPERTY(this_ptr,tmp) != FAILURE) {
2651 FETCH_SDL_RES(sdl,tmp);
2653 if (FIND_TYPEMAP_PROPERTY(this_ptr,tmp) != FAILURE) {
2654 FETCH_TYPEMAP_RES(typemap,tmp);
2657 clear_soap_fault(this_ptr TSRMLS_CC);
2659 SOAP_GLOBAL(soap_version) = soap_version;
2660 old_sdl = SOAP_GLOBAL(sdl);
2661 SOAP_GLOBAL(sdl) = sdl;
2662 old_encoding = SOAP_GLOBAL(encoding);
2663 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_encoding", sizeof("_encoding"), (void **) &tmp) == SUCCESS &&
2664 Z_TYPE_PP(tmp) == IS_STRING) {
2665 SOAP_GLOBAL(encoding) = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
2666 } else {
2667 SOAP_GLOBAL(encoding) = NULL;
2669 old_class_map = SOAP_GLOBAL(class_map);
2670 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_classmap", sizeof("_classmap"), (void **) &tmp) == SUCCESS &&
2671 Z_TYPE_PP(tmp) == IS_ARRAY) {
2672 SOAP_GLOBAL(class_map) = (*tmp)->value.ht;
2673 } else {
2674 SOAP_GLOBAL(class_map) = NULL;
2676 old_typemap = SOAP_GLOBAL(typemap);
2677 SOAP_GLOBAL(typemap) = typemap;
2678 old_features = SOAP_GLOBAL(features);
2679 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_features", sizeof("_features"), (void **) &tmp) == SUCCESS &&
2680 Z_TYPE_PP(tmp) == IS_LONG) {
2681 SOAP_GLOBAL(features) = Z_LVAL_PP(tmp);
2682 } else {
2683 SOAP_GLOBAL(features) = 0;
2686 if (sdl != NULL) {
2687 fn = get_function(sdl, function);
2688 if (fn != NULL) {
2689 sdlBindingPtr binding = fn->binding;
2690 int one_way = 0;
2692 if (fn->responseName == NULL &&
2693 fn->responseParameters == NULL &&
2694 soap_headers == NULL) {
2695 one_way = 1;
2698 if (location == NULL) {
2699 location = binding->location;
2701 if (binding->bindingType == BINDING_SOAP) {
2702 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes;
2703 request = serialize_function_call(this_ptr, fn, NULL, fnb->input.ns, real_args, arg_count, soap_version, soap_headers TSRMLS_CC);
2704 ret = do_request(this_ptr, request, location, fnb->soapAction, soap_version, one_way, &response TSRMLS_CC);
2705 } else {
2706 request = serialize_function_call(this_ptr, fn, NULL, sdl->target_ns, real_args, arg_count, soap_version, soap_headers TSRMLS_CC);
2707 ret = do_request(this_ptr, request, location, NULL, soap_version, one_way, &response TSRMLS_CC);
2710 xmlFreeDoc(request);
2712 if (ret && Z_TYPE(response) == IS_STRING) {
2713 encode_reset_ns();
2714 ret = parse_packet_soap(this_ptr, Z_STRVAL(response), Z_STRLEN(response), fn, NULL, return_value, output_headers TSRMLS_CC);
2715 encode_finish();
2718 zval_dtor(&response);
2720 } else {
2721 smart_str error = {0};
2722 smart_str_appends(&error,"Function (\"");
2723 smart_str_appends(&error,function);
2724 smart_str_appends(&error,"\") is not a valid method for this service");
2725 smart_str_0(&error);
2726 add_soap_fault(this_ptr, "Client", error.c, NULL, NULL TSRMLS_CC);
2727 smart_str_free(&error);
2729 } else {
2730 zval **uri;
2731 smart_str action = {0};
2733 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "uri", sizeof("uri"), (void *)&uri) == FAILURE) {
2734 add_soap_fault(this_ptr, "Client", "Error finding \"uri\" property", NULL, NULL TSRMLS_CC);
2735 } else if (location == NULL) {
2736 add_soap_fault(this_ptr, "Client", "Error could not find \"location\" property", NULL, NULL TSRMLS_CC);
2737 } else {
2738 if (call_uri == NULL) {
2739 call_uri = Z_STRVAL_PP(uri);
2741 request = serialize_function_call(this_ptr, NULL, function, call_uri, real_args, arg_count, soap_version, soap_headers TSRMLS_CC);
2743 if (soap_action == NULL) {
2744 smart_str_appends(&action, call_uri);
2745 smart_str_appendc(&action, '#');
2746 smart_str_appends(&action, function);
2747 } else {
2748 smart_str_appends(&action, soap_action);
2750 smart_str_0(&action);
2752 ret = do_request(this_ptr, request, location, action.c, soap_version, 0, &response TSRMLS_CC);
2754 smart_str_free(&action);
2755 xmlFreeDoc(request);
2757 if (ret && Z_TYPE(response) == IS_STRING) {
2758 encode_reset_ns();
2759 ret = parse_packet_soap(this_ptr, Z_STRVAL(response), Z_STRLEN(response), NULL, function, return_value, output_headers TSRMLS_CC);
2760 encode_finish();
2763 zval_dtor(&response);
2767 if (!ret) {
2768 zval** fault;
2769 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault"), (void **) &fault) == SUCCESS) {
2770 *return_value = **fault;
2771 zval_copy_ctor(return_value);
2772 } else {
2773 *return_value = *add_soap_fault(this_ptr, "Client", "Unknown Error", NULL, NULL TSRMLS_CC);
2774 zval_copy_ctor(return_value);
2776 } else {
2777 zval** fault;
2778 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault"), (void **) &fault) == SUCCESS) {
2779 *return_value = **fault;
2780 zval_copy_ctor(return_value);
2784 if (!EG(exception) &&
2785 Z_TYPE_P(return_value) == IS_OBJECT &&
2786 instanceof_function(Z_OBJCE_P(return_value), soap_fault_class_entry TSRMLS_CC) &&
2787 (zend_hash_find(Z_OBJPROP_P(this_ptr), "_exceptions", sizeof("_exceptions"), (void **) &tmp) != SUCCESS ||
2788 Z_TYPE_PP(tmp) != IS_BOOL || Z_LVAL_PP(tmp) != 0)) {
2789 zval *exception;
2791 MAKE_STD_ZVAL(exception);
2792 MAKE_COPY_ZVAL(&return_value, exception);
2793 zend_throw_exception_object(exception TSRMLS_CC);
2796 if (SOAP_GLOBAL(encoding) != NULL) {
2797 xmlCharEncCloseFunc(SOAP_GLOBAL(encoding));
2799 SOAP_GLOBAL(features) = old_features;
2800 SOAP_GLOBAL(typemap) = old_typemap;
2801 SOAP_GLOBAL(class_map) = old_class_map;
2802 SOAP_GLOBAL(encoding) = old_encoding;
2803 SOAP_GLOBAL(sdl) = old_sdl;
2804 SOAP_CLIENT_END_CODE();
2807 static void verify_soap_headers_array(HashTable *ht TSRMLS_DC)
2809 zval **tmp;
2811 zend_hash_internal_pointer_reset(ht);
2812 while (zend_hash_get_current_data(ht, (void**)&tmp) == SUCCESS) {
2813 if (Z_TYPE_PP(tmp) != IS_OBJECT ||
2814 !instanceof_function(Z_OBJCE_PP(tmp), soap_header_class_entry TSRMLS_CC)) {
2815 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid SOAP header");
2817 zend_hash_move_forward(ht);
2822 /* {{{ proto mixed SoapClient::__call ( string function_name, array arguments [, array options [, array input_headers [, array output_headers]]])
2823 Calls a SOAP function */
2824 PHP_METHOD(SoapClient, __call)
2826 char *function, *location=NULL, *soap_action = NULL, *uri = NULL;
2827 int function_len, i = 0;
2828 HashTable* soap_headers = NULL;
2829 zval *options = NULL;
2830 zval *headers = NULL;
2831 zval *output_headers = NULL;
2832 zval *args;
2833 zval **real_args = NULL;
2834 zval **param;
2835 int arg_count;
2836 zval **tmp;
2837 zend_bool free_soap_headers = 0;
2839 HashPosition pos;
2841 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|a!zz",
2842 &function, &function_len, &args, &options, &headers, &output_headers) == FAILURE) {
2843 return;
2846 if (options) {
2847 HashTable *hto = Z_ARRVAL_P(options);
2848 if (zend_hash_find(hto, "location", sizeof("location"), (void**)&tmp) == SUCCESS &&
2849 Z_TYPE_PP(tmp) == IS_STRING) {
2850 location = Z_STRVAL_PP(tmp);
2853 if (zend_hash_find(hto, "soapaction", sizeof("soapaction"), (void**)&tmp) == SUCCESS &&
2854 Z_TYPE_PP(tmp) == IS_STRING) {
2855 soap_action = Z_STRVAL_PP(tmp);
2858 if (zend_hash_find(hto, "uri", sizeof("uri"), (void**)&tmp) == SUCCESS &&
2859 Z_TYPE_PP(tmp) == IS_STRING) {
2860 uri = Z_STRVAL_PP(tmp);
2864 if (headers == NULL || Z_TYPE_P(headers) == IS_NULL) {
2865 } else if (Z_TYPE_P(headers) == IS_ARRAY) {
2866 soap_headers = Z_ARRVAL_P(headers);
2867 verify_soap_headers_array(soap_headers TSRMLS_CC);
2868 free_soap_headers = 0;
2869 } else if (Z_TYPE_P(headers) == IS_OBJECT &&
2870 instanceof_function(Z_OBJCE_P(headers), soap_header_class_entry TSRMLS_CC)) {
2871 soap_headers = emalloc(sizeof(HashTable));
2872 zend_hash_init(soap_headers, 0, NULL, ZVAL_PTR_DTOR, 0);
2873 zend_hash_next_index_insert(soap_headers, &headers, sizeof(zval*), NULL);
2874 Z_ADDREF_P(headers);
2875 free_soap_headers = 1;
2876 } else{
2877 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid SOAP header");
2878 return;
2881 /* Add default headers */
2882 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_headers"), (void **) &tmp)==SUCCESS) {
2883 HashTable *default_headers = Z_ARRVAL_P(*tmp);
2884 if (soap_headers) {
2885 if (!free_soap_headers) {
2886 HashTable *t = emalloc(sizeof(HashTable));
2887 zend_hash_init(t, 0, NULL, ZVAL_PTR_DTOR, 0);
2888 zend_hash_copy(t, soap_headers, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
2889 soap_headers = t;
2890 free_soap_headers = 1;
2892 zend_hash_internal_pointer_reset(default_headers);
2893 while (zend_hash_get_current_data(default_headers, (void**)&tmp) == SUCCESS) {
2894 Z_ADDREF_PP(tmp);
2895 zend_hash_next_index_insert(soap_headers, tmp, sizeof(zval *), NULL);
2896 zend_hash_move_forward(default_headers);
2898 } else {
2899 soap_headers = Z_ARRVAL_P(*tmp);
2900 free_soap_headers = 0;
2904 arg_count = zend_hash_num_elements(Z_ARRVAL_P(args));
2906 if (arg_count > 0) {
2907 real_args = safe_emalloc(sizeof(zval *), arg_count, 0);
2908 for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos);
2909 zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void **) &param, &pos) == SUCCESS;
2910 zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos)) {
2911 /*zval_add_ref(param);*/
2912 real_args[i++] = *param;
2915 if (output_headers) {
2916 array_init(output_headers);
2918 do_soap_call(this_ptr, function, function_len, arg_count, real_args, return_value, location, soap_action, uri, soap_headers, output_headers TSRMLS_CC);
2919 if (arg_count > 0) {
2920 efree(real_args);
2923 if (soap_headers && free_soap_headers) {
2924 zend_hash_destroy(soap_headers);
2925 efree(soap_headers);
2928 /* }}} */
2931 /* {{{ proto array SoapClient::__getFunctions ( void )
2932 Returns list of SOAP functions */
2933 PHP_METHOD(SoapClient, __getFunctions)
2935 sdlPtr sdl;
2936 HashPosition pos;
2938 FETCH_THIS_SDL(sdl);
2940 if (zend_parse_parameters_none() == FAILURE) {
2941 return;
2944 if (sdl) {
2945 smart_str buf = {0};
2946 sdlFunctionPtr *function;
2948 array_init(return_value);
2949 zend_hash_internal_pointer_reset_ex(&sdl->functions, &pos);
2950 while (zend_hash_get_current_data_ex(&sdl->functions, (void **)&function, &pos) != FAILURE) {
2951 function_to_string((*function), &buf);
2952 add_next_index_stringl(return_value, buf.c, buf.len, 1);
2953 smart_str_free(&buf);
2954 zend_hash_move_forward_ex(&sdl->functions, &pos);
2958 /* }}} */
2961 /* {{{ proto array SoapClient::__getTypes ( void )
2962 Returns list of SOAP types */
2963 PHP_METHOD(SoapClient, __getTypes)
2965 sdlPtr sdl;
2966 HashPosition pos;
2968 FETCH_THIS_SDL(sdl);
2970 if (zend_parse_parameters_none() == FAILURE) {
2971 return;
2974 if (sdl) {
2975 sdlTypePtr *type;
2976 smart_str buf = {0};
2978 array_init(return_value);
2979 if (sdl->types) {
2980 zend_hash_internal_pointer_reset_ex(sdl->types, &pos);
2981 while (zend_hash_get_current_data_ex(sdl->types, (void **)&type, &pos) != FAILURE) {
2982 type_to_string((*type), &buf, 0);
2983 add_next_index_stringl(return_value, buf.c, buf.len, 1);
2984 smart_str_free(&buf);
2985 zend_hash_move_forward_ex(sdl->types, &pos);
2990 /* }}} */
2993 /* {{{ proto string SoapClient::__getLastRequest ( void )
2994 Returns last SOAP request */
2995 PHP_METHOD(SoapClient, __getLastRequest)
2997 zval **tmp;
2999 if (zend_parse_parameters_none() == FAILURE) {
3000 return;
3003 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_request", sizeof("__last_request"), (void **)&tmp) == SUCCESS) {
3004 RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
3006 RETURN_NULL();
3008 /* }}} */
3011 /* {{{ proto object SoapClient::__getLastResponse ( void )
3012 Returns last SOAP response */
3013 PHP_METHOD(SoapClient, __getLastResponse)
3015 zval **tmp;
3017 if (zend_parse_parameters_none() == FAILURE) {
3018 return;
3021 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_response", sizeof("__last_response"), (void **)&tmp) == SUCCESS) {
3022 RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
3024 RETURN_NULL();
3026 /* }}} */
3029 /* {{{ proto string SoapClient::__getLastRequestHeaders(void)
3030 Returns last SOAP request headers */
3031 PHP_METHOD(SoapClient, __getLastRequestHeaders)
3033 zval **tmp;
3035 if (zend_parse_parameters_none() == FAILURE) {
3036 return;
3039 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_request_headers", sizeof("__last_request_headers"), (void **)&tmp) == SUCCESS) {
3040 RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
3042 RETURN_NULL();
3044 /* }}} */
3047 /* {{{ proto string SoapClient::__getLastResponseHeaders(void)
3048 Returns last SOAP response headers */
3049 PHP_METHOD(SoapClient, __getLastResponseHeaders)
3051 zval **tmp;
3053 if (zend_parse_parameters_none() == FAILURE) {
3054 return;
3057 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_response_headers", sizeof("__last_response_headers"), (void **)&tmp) == SUCCESS) {
3058 RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
3060 RETURN_NULL();
3062 /* }}} */
3065 /* {{{ proto string SoapClient::__doRequest()
3066 SoapClient::__doRequest() */
3067 PHP_METHOD(SoapClient, __doRequest)
3069 char *buf, *location, *action;
3070 int buf_size, location_size, action_size;
3071 long version;
3072 long one_way = 0;
3074 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssl|l",
3075 &buf, &buf_size,
3076 &location, &location_size,
3077 &action, &action_size,
3078 &version, &one_way) == FAILURE) {
3079 return;
3081 if (SOAP_GLOBAL(features) & SOAP_WAIT_ONE_WAY_CALLS) {
3082 one_way = 0;
3084 if (one_way) {
3085 if (make_http_soap_request(this_ptr, buf, buf_size, location, action, version, NULL, NULL TSRMLS_CC)) {
3086 RETURN_EMPTY_STRING();
3088 } else if (make_http_soap_request(this_ptr, buf, buf_size, location, action, version,
3089 &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value) TSRMLS_CC)) {
3090 return_value->type = IS_STRING;
3091 return;
3093 RETURN_NULL();
3095 /* }}} */
3097 /* {{{ proto void SoapClient::__setCookie(string name [, strung value])
3098 Sets cookie thet will sent with SOAP request.
3099 The call to this function will effect all folowing calls of SOAP methods.
3100 If value is not specified cookie is removed. */
3101 PHP_METHOD(SoapClient, __setCookie)
3103 char *name;
3104 char *val = NULL;
3105 int name_len, val_len = 0;
3106 zval **cookies;
3108 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &name, &name_len, &val, &val_len) == FAILURE) {
3109 return;
3112 if (val == NULL) {
3113 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), (void **)&cookies) == SUCCESS) {
3114 zend_hash_del(Z_ARRVAL_PP(cookies), name, name_len+1);
3116 } else {
3117 zval *zcookie;
3119 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), (void **)&cookies) == FAILURE) {
3120 zval *tmp_cookies;
3122 MAKE_STD_ZVAL(tmp_cookies);
3123 array_init(tmp_cookies);
3124 zend_hash_update(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), &tmp_cookies, sizeof(zval *), (void **)&cookies);
3127 ALLOC_INIT_ZVAL(zcookie);
3128 array_init(zcookie);
3129 add_index_stringl(zcookie, 0, val, val_len, 1);
3130 add_assoc_zval_ex(*cookies, name, name_len+1, zcookie);
3133 /* }}} */
3135 /* {{{ proto void SoapClient::__setSoapHeaders(array SoapHeaders)
3136 Sets SOAP headers for subsequent calls (replaces any previous
3137 values).
3138 If no value is specified, all of the headers are removed. */
3139 PHP_METHOD(SoapClient, __setSoapHeaders)
3141 zval *headers = NULL;
3143 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &headers) == FAILURE) {
3144 return;
3147 if (headers == NULL || Z_TYPE_P(headers) == IS_NULL) {
3148 zend_hash_del(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_headers"));
3149 } else if (Z_TYPE_P(headers) == IS_ARRAY) {
3150 zval *default_headers;
3152 verify_soap_headers_array(Z_ARRVAL_P(headers) TSRMLS_CC);
3153 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_headers"), (void **) &default_headers)==FAILURE) {
3154 add_property_zval(this_ptr, "__default_headers", headers);
3156 } else if (Z_TYPE_P(headers) == IS_OBJECT &&
3157 instanceof_function(Z_OBJCE_P(headers), soap_header_class_entry TSRMLS_CC)) {
3158 zval *default_headers;
3159 ALLOC_INIT_ZVAL(default_headers);
3160 array_init(default_headers);
3161 Z_ADDREF_P(headers);
3162 add_next_index_zval(default_headers, headers);
3163 Z_DELREF_P(default_headers);
3164 add_property_zval(this_ptr, "__default_headers", default_headers);
3165 } else{
3166 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid SOAP header");
3168 RETURN_TRUE;
3170 /* }}} */
3174 /* {{{ proto string SoapClient::__setLocation([string new_location])
3175 Sets the location option (the endpoint URL that will be touched by the
3176 following SOAP requests).
3177 If new_location is not specified or null then SoapClient will use endpoint
3178 from WSDL file.
3179 The function returns old value of location options. */
3180 PHP_METHOD(SoapClient, __setLocation)
3182 char *location = NULL;
3183 int location_len = 0;
3184 zval **tmp;
3186 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &location, &location_len) == FAILURE) {
3187 return;
3190 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "location", sizeof("location"),(void **) &tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_STRING) {
3191 RETVAL_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
3192 } else {
3193 RETVAL_NULL();
3196 if (location && location_len) {
3197 add_property_stringl(this_ptr, "location", location, location_len, 1);
3198 } else {
3199 zend_hash_del(Z_OBJPROP_P(this_ptr), "location", sizeof("location"));
3202 /* }}} */
3204 static void clear_soap_fault(zval *obj TSRMLS_DC)
3206 if (obj != NULL && obj->type == IS_OBJECT) {
3207 zend_hash_del(Z_OBJPROP_P(obj), "__soap_fault", sizeof("__soap_fault"));
3211 zval* add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail TSRMLS_DC)
3213 zval *fault;
3214 ALLOC_INIT_ZVAL(fault);
3215 set_soap_fault(fault, NULL, fault_code, fault_string, fault_actor, fault_detail, NULL TSRMLS_CC);
3216 Z_DELREF_P(fault);
3218 add_property_zval(obj, "__soap_fault", fault);
3219 return fault;
3222 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 TSRMLS_DC)
3224 if (Z_TYPE_P(obj) != IS_OBJECT) {
3225 object_init_ex(obj, soap_fault_class_entry);
3228 add_property_string(obj, "faultstring", fault_string ? fault_string : "", 1);
3229 zend_update_property_string(zend_exception_get_default(TSRMLS_C), obj, "message", sizeof("message")-1, (fault_string ? fault_string : "") TSRMLS_CC);
3231 if (fault_code != NULL) {
3232 int soap_version = SOAP_GLOBAL(soap_version);
3234 if (fault_code_ns) {
3235 add_property_string(obj, "faultcode", fault_code, 1);
3236 add_property_string(obj, "faultcodens", fault_code_ns, 1);
3237 } else {
3238 if (soap_version == SOAP_1_1) {
3239 add_property_string(obj, "faultcode", fault_code, 1);
3240 if (strcmp(fault_code,"Client") == 0 ||
3241 strcmp(fault_code,"Server") == 0 ||
3242 strcmp(fault_code,"VersionMismatch") == 0 ||
3243 strcmp(fault_code,"MustUnderstand") == 0) {
3244 add_property_string(obj, "faultcodens", SOAP_1_1_ENV_NAMESPACE, 1);
3246 } else if (soap_version == SOAP_1_2) {
3247 if (strcmp(fault_code,"Client") == 0) {
3248 add_property_string(obj, "faultcode", "Sender", 1);
3249 add_property_string(obj, "faultcodens", SOAP_1_2_ENV_NAMESPACE, 1);
3250 } else if (strcmp(fault_code,"Server") == 0) {
3251 add_property_string(obj, "faultcode", "Receiver", 1);
3252 add_property_string(obj, "faultcodens", SOAP_1_2_ENV_NAMESPACE, 1);
3253 } else if (strcmp(fault_code,"VersionMismatch") == 0 ||
3254 strcmp(fault_code,"MustUnderstand") == 0 ||
3255 strcmp(fault_code,"DataEncodingUnknown") == 0) {
3256 add_property_string(obj, "faultcode", fault_code, 1);
3257 add_property_string(obj, "faultcodens", SOAP_1_2_ENV_NAMESPACE, 1);
3258 } else {
3259 add_property_string(obj, "faultcode", fault_code, 1);
3264 if (fault_actor != NULL) {
3265 add_property_string(obj, "faultactor", fault_actor, 1);
3267 if (fault_detail != NULL) {
3268 add_property_zval(obj, "detail", fault_detail);
3270 if (name != NULL) {
3271 add_property_string(obj, "_name", name, 1);
3275 static void deserialize_parameters(xmlNodePtr params, sdlFunctionPtr function, int *num_params, zval ***parameters TSRMLS_DC)
3277 int cur_param = 0,num_of_params = 0;
3278 zval **tmp_parameters = NULL;
3280 if (function != NULL) {
3281 sdlParamPtr *param;
3282 xmlNodePtr val;
3283 int use_names = 0;
3285 if (function->requestParameters == NULL) {
3286 return;
3288 num_of_params = zend_hash_num_elements(function->requestParameters);
3289 zend_hash_internal_pointer_reset(function->requestParameters);
3290 while (zend_hash_get_current_data(function->requestParameters, (void **)&param) == SUCCESS) {
3291 if (get_node(params, (*param)->paramName) != NULL) {
3292 use_names = 1;
3294 zend_hash_move_forward(function->requestParameters);
3296 if (use_names) {
3297 tmp_parameters = safe_emalloc(num_of_params, sizeof(zval *), 0);
3298 zend_hash_internal_pointer_reset(function->requestParameters);
3299 while (zend_hash_get_current_data(function->requestParameters, (void **)&param) == SUCCESS) {
3300 val = get_node(params, (*param)->paramName);
3301 if (!val) {
3302 /* TODO: may be "nil" is not OK? */
3303 MAKE_STD_ZVAL(tmp_parameters[cur_param]);
3304 ZVAL_NULL(tmp_parameters[cur_param]);
3305 } else {
3306 tmp_parameters[cur_param] = master_to_zval((*param)->encode, val TSRMLS_CC);
3308 cur_param++;
3310 zend_hash_move_forward(function->requestParameters);
3312 (*parameters) = tmp_parameters;
3313 (*num_params) = num_of_params;
3314 return;
3317 if (params) {
3318 xmlNodePtr trav;
3320 num_of_params = 0;
3321 trav = params;
3322 while (trav != NULL) {
3323 if (trav->type == XML_ELEMENT_NODE) {
3324 num_of_params++;
3326 trav = trav->next;
3329 if (num_of_params == 1 &&
3330 function &&
3331 function->binding &&
3332 function->binding->bindingType == BINDING_SOAP &&
3333 ((sdlSoapBindingFunctionPtr)function->bindingAttributes)->style == SOAP_DOCUMENT &&
3334 (function->requestParameters == NULL ||
3335 zend_hash_num_elements(function->requestParameters) == 0) &&
3336 strcmp((char *)params->name, function->functionName) == 0) {
3337 num_of_params = 0;
3338 } else if (num_of_params > 0) {
3339 tmp_parameters = safe_emalloc(num_of_params, sizeof(zval *), 0);
3341 trav = params;
3342 while (trav != 0 && cur_param < num_of_params) {
3343 if (trav->type == XML_ELEMENT_NODE) {
3344 encodePtr enc;
3345 sdlParamPtr *param = NULL;
3346 if (function != NULL &&
3347 zend_hash_index_find(function->requestParameters, cur_param, (void **)&param) == FAILURE) {
3348 TSRMLS_FETCH();
3349 soap_server_fault("Client", "Error cannot find parameter", NULL, NULL, NULL TSRMLS_CC);
3351 if (param == NULL) {
3352 enc = NULL;
3353 } else {
3354 enc = (*param)->encode;
3356 tmp_parameters[cur_param] = master_to_zval(enc, trav TSRMLS_CC);
3357 cur_param++;
3359 trav = trav->next;
3363 if (num_of_params > cur_param) {
3364 soap_server_fault("Client","Missing parameter", NULL, NULL, NULL TSRMLS_CC);
3366 (*parameters) = tmp_parameters;
3367 (*num_params) = num_of_params;
3370 static sdlFunctionPtr find_function(sdlPtr sdl, xmlNodePtr func, zval* function_name)
3372 sdlFunctionPtr function;
3374 function = get_function(sdl, (char*)func->name);
3375 if (function && function->binding && function->binding->bindingType == BINDING_SOAP) {
3376 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
3377 if (fnb->style == SOAP_DOCUMENT) {
3378 if (func->children != NULL ||
3379 (function->requestParameters != NULL &&
3380 zend_hash_num_elements(function->requestParameters) > 0)) {
3381 function = NULL;
3385 if (sdl != NULL && function == NULL) {
3386 function = get_doc_function(sdl, func);
3389 INIT_ZVAL(*function_name);
3390 if (function != NULL) {
3391 ZVAL_STRING(function_name, (char *)function->functionName, 1);
3392 } else {
3393 ZVAL_STRING(function_name, (char *)func->name, 1);
3396 return function;
3399 static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, char* actor, zval *function_name, int *num_params, zval ***parameters, int *version, soapHeader **headers TSRMLS_DC)
3401 char* envelope_ns = NULL;
3402 xmlNodePtr trav,env,head,body,func;
3403 xmlAttrPtr attr;
3404 sdlFunctionPtr function;
3406 encode_reset_ns();
3408 /* Get <Envelope> element */
3409 env = NULL;
3410 trav = request->children;
3411 while (trav != NULL) {
3412 if (trav->type == XML_ELEMENT_NODE) {
3413 if (env == NULL && node_is_equal_ex(trav,"Envelope",SOAP_1_1_ENV_NAMESPACE)) {
3414 env = trav;
3415 *version = SOAP_1_1;
3416 envelope_ns = SOAP_1_1_ENV_NAMESPACE;
3417 SOAP_GLOBAL(soap_version) = SOAP_1_1;
3418 } else if (env == NULL && node_is_equal_ex(trav,"Envelope",SOAP_1_2_ENV_NAMESPACE)) {
3419 env = trav;
3420 *version = SOAP_1_2;
3421 envelope_ns = SOAP_1_2_ENV_NAMESPACE;
3422 SOAP_GLOBAL(soap_version) = SOAP_1_2;
3423 } else {
3424 soap_server_fault("VersionMismatch", "Wrong Version", NULL, NULL, NULL TSRMLS_CC);
3427 trav = trav->next;
3429 if (env == NULL) {
3430 soap_server_fault("Client", "looks like we got XML without \"Envelope\" element", NULL, NULL, NULL TSRMLS_CC);
3433 attr = env->properties;
3434 while (attr != NULL) {
3435 if (attr->ns == NULL) {
3436 soap_server_fault("Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL, NULL TSRMLS_CC);
3437 } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
3438 if (*version == SOAP_1_2) {
3439 soap_server_fault("Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL, NULL TSRMLS_CC);
3440 } else if (strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
3441 soap_server_fault("Client", "Unknown data encoding style", NULL, NULL, NULL TSRMLS_CC);
3444 attr = attr->next;
3447 /* Get <Header> element */
3448 head = NULL;
3449 trav = env->children;
3450 while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
3451 trav = trav->next;
3453 if (trav != NULL && node_is_equal_ex(trav,"Header",envelope_ns)) {
3454 head = trav;
3455 trav = trav->next;
3458 /* Get <Body> element */
3459 body = NULL;
3460 while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
3461 trav = trav->next;
3463 if (trav != NULL && node_is_equal_ex(trav,"Body",envelope_ns)) {
3464 body = trav;
3465 trav = trav->next;
3467 while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
3468 trav = trav->next;
3470 if (body == NULL) {
3471 soap_server_fault("Client", "Body must be present in a SOAP envelope", NULL, NULL, NULL TSRMLS_CC);
3473 attr = body->properties;
3474 while (attr != NULL) {
3475 if (attr->ns == NULL) {
3476 if (*version == SOAP_1_2) {
3477 soap_server_fault("Client", "A SOAP Body element cannot have non Namespace qualified attributes", NULL, NULL, NULL TSRMLS_CC);
3479 } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
3480 if (*version == SOAP_1_2) {
3481 soap_server_fault("Client", "encodingStyle cannot be specified on the Body", NULL, NULL, NULL TSRMLS_CC);
3482 } else if (strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
3483 soap_server_fault("Client", "Unknown data encoding style", NULL, NULL, NULL TSRMLS_CC);
3486 attr = attr->next;
3489 if (trav != NULL && *version == SOAP_1_2) {
3490 soap_server_fault("Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL, NULL TSRMLS_CC);
3493 func = NULL;
3494 trav = body->children;
3495 while (trav != NULL) {
3496 if (trav->type == XML_ELEMENT_NODE) {
3498 if (func != NULL) {
3499 soap_server_fault("Client", "looks like we got \"Body\" with several functions call", NULL, NULL, NULL TSRMLS_CC);
3502 func = trav;
3503 break; /* FIXME: the rest of body is ignored */
3505 trav = trav->next;
3507 if (func == NULL) {
3508 function = get_doc_function(sdl, NULL);
3509 if (function != NULL) {
3510 INIT_ZVAL(*function_name);
3511 ZVAL_STRING(function_name, (char *)function->functionName, 1);
3512 } else {
3513 soap_server_fault("Client", "looks like we got \"Body\" without function call", NULL, NULL, NULL TSRMLS_CC);
3515 } else {
3516 if (*version == SOAP_1_1) {
3517 attr = get_attribute_ex(func->properties,"encodingStyle",SOAP_1_1_ENV_NAMESPACE);
3518 if (attr && strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
3519 soap_server_fault("Client","Unknown Data Encoding Style", NULL, NULL, NULL TSRMLS_CC);
3521 } else {
3522 attr = get_attribute_ex(func->properties,"encodingStyle",SOAP_1_2_ENV_NAMESPACE);
3523 if (attr && strcmp((char*)attr->children->content,SOAP_1_2_ENC_NAMESPACE) != 0) {
3524 soap_server_fault("DataEncodingUnknown","Unknown Data Encoding Style", NULL, NULL, NULL TSRMLS_CC);
3527 function = find_function(sdl, func, function_name);
3528 if (sdl != NULL && function == NULL) {
3529 if (*version == SOAP_1_2) {
3530 soap_server_fault("rpc:ProcedureNotPresent","Procedure not present", NULL, NULL, NULL TSRMLS_CC);
3531 } else {
3532 php_error(E_ERROR, "Procedure '%s' not present", func->name);
3537 *headers = NULL;
3538 if (head) {
3539 soapHeader *h, *last = NULL;
3541 attr = head->properties;
3542 while (attr != NULL) {
3543 if (attr->ns == NULL) {
3544 soap_server_fault("Client", "A SOAP Header element cannot have non Namespace qualified attributes", NULL, NULL, NULL TSRMLS_CC);
3545 } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
3546 if (*version == SOAP_1_2) {
3547 soap_server_fault("Client", "encodingStyle cannot be specified on the Header", NULL, NULL, NULL TSRMLS_CC);
3548 } else if (strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
3549 soap_server_fault("Client", "Unknown data encoding style", NULL, NULL, NULL TSRMLS_CC);
3552 attr = attr->next;
3554 trav = head->children;
3555 while (trav != NULL) {
3556 if (trav->type == XML_ELEMENT_NODE) {
3557 xmlNodePtr hdr_func = trav;
3558 int mustUnderstand = 0;
3560 if (*version == SOAP_1_1) {
3561 attr = get_attribute_ex(hdr_func->properties,"encodingStyle",SOAP_1_1_ENV_NAMESPACE);
3562 if (attr && strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
3563 soap_server_fault("Client","Unknown Data Encoding Style", NULL, NULL, NULL TSRMLS_CC);
3565 attr = get_attribute_ex(hdr_func->properties,"actor",envelope_ns);
3566 if (attr != NULL) {
3567 if (strcmp((char*)attr->children->content,SOAP_1_1_ACTOR_NEXT) != 0 &&
3568 (actor == NULL || strcmp((char*)attr->children->content,actor) != 0)) {
3569 goto ignore_header;
3572 } else if (*version == SOAP_1_2) {
3573 attr = get_attribute_ex(hdr_func->properties,"encodingStyle",SOAP_1_2_ENV_NAMESPACE);
3574 if (attr && strcmp((char*)attr->children->content,SOAP_1_2_ENC_NAMESPACE) != 0) {
3575 soap_server_fault("DataEncodingUnknown","Unknown Data Encoding Style", NULL, NULL, NULL TSRMLS_CC);
3577 attr = get_attribute_ex(hdr_func->properties,"role",envelope_ns);
3578 if (attr != NULL) {
3579 if (strcmp((char*)attr->children->content,SOAP_1_2_ACTOR_UNLIMATERECEIVER) != 0 &&
3580 strcmp((char*)attr->children->content,SOAP_1_2_ACTOR_NEXT) != 0 &&
3581 (actor == NULL || strcmp((char*)attr->children->content,actor) != 0)) {
3582 goto ignore_header;
3586 attr = get_attribute_ex(hdr_func->properties,"mustUnderstand",envelope_ns);
3587 if (attr) {
3588 if (strcmp((char*)attr->children->content,"1") == 0 ||
3589 strcmp((char*)attr->children->content,"true") == 0) {
3590 mustUnderstand = 1;
3591 } else if (strcmp((char*)attr->children->content,"0") == 0 ||
3592 strcmp((char*)attr->children->content,"false") == 0) {
3593 mustUnderstand = 0;
3594 } else {
3595 soap_server_fault("Client","mustUnderstand value is not boolean", NULL, NULL, NULL TSRMLS_CC);
3598 h = emalloc(sizeof(soapHeader));
3599 memset(h, 0, sizeof(soapHeader));
3600 h->mustUnderstand = mustUnderstand;
3601 h->function = find_function(sdl, hdr_func, &h->function_name);
3602 if (!h->function && sdl && function && function->binding && function->binding->bindingType == BINDING_SOAP) {
3603 sdlSoapBindingFunctionHeaderPtr *hdr;
3604 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
3605 if (fnb->input.headers) {
3606 smart_str key = {0};
3608 if (hdr_func->ns) {
3609 smart_str_appends(&key, (char*)hdr_func->ns->href);
3610 smart_str_appendc(&key, ':');
3612 smart_str_appendl(&key, Z_STRVAL(h->function_name), Z_STRLEN(h->function_name));
3613 smart_str_0(&key);
3614 if (zend_hash_find(fnb->input.headers, key.c, key.len+1, (void**)&hdr) == SUCCESS) {
3615 h->hdr = *hdr;
3617 smart_str_free(&key);
3620 if (h->hdr) {
3621 h->num_params = 1;
3622 h->parameters = emalloc(sizeof(zval*));
3623 h->parameters[0] = master_to_zval(h->hdr->encode, hdr_func TSRMLS_CC);
3624 } else {
3625 if (h->function && h->function->binding && h->function->binding->bindingType == BINDING_SOAP) {
3626 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)h->function->bindingAttributes;
3627 if (fnb->style == SOAP_RPC) {
3628 hdr_func = hdr_func->children;
3631 deserialize_parameters(hdr_func, h->function, &h->num_params, &h->parameters TSRMLS_CC);
3633 INIT_ZVAL(h->retval);
3634 if (last == NULL) {
3635 *headers = h;
3636 } else {
3637 last->next = h;
3639 last = h;
3641 ignore_header:
3642 trav = trav->next;
3646 if (function && function->binding && function->binding->bindingType == BINDING_SOAP) {
3647 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
3648 if (fnb->style == SOAP_RPC) {
3649 func = func->children;
3651 } else {
3652 func = func->children;
3654 deserialize_parameters(func, function, num_params, parameters TSRMLS_CC);
3656 encode_finish();
3658 return function;
3661 static int serialize_response_call2(xmlNodePtr body, sdlFunctionPtr function, char *function_name, char *uri, zval *ret, int version, int main TSRMLS_DC)
3663 xmlNodePtr method = NULL, param;
3664 sdlParamPtr parameter = NULL;
3665 int param_count;
3666 int style, use;
3667 xmlNsPtr ns = NULL;
3669 if (function != NULL && function->binding->bindingType == BINDING_SOAP) {
3670 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
3672 style = fnb->style;
3673 use = fnb->output.use;
3674 if (style == SOAP_RPC) {
3675 ns = encode_add_ns(body, fnb->output.ns);
3676 if (function->responseName) {
3677 method = xmlNewChild(body, ns, BAD_CAST(function->responseName), NULL);
3678 } else if (function->responseParameters) {
3679 method = xmlNewChild(body, ns, BAD_CAST(function->functionName), NULL);
3682 } else {
3683 style = main?SOAP_RPC:SOAP_DOCUMENT;
3684 use = main?SOAP_ENCODED:SOAP_LITERAL;
3685 if (style == SOAP_RPC) {
3686 ns = encode_add_ns(body, uri);
3687 method = xmlNewChild(body, ns, BAD_CAST(function_name), NULL);
3691 if (function != NULL) {
3692 if (function->responseParameters) {
3693 param_count = zend_hash_num_elements(function->responseParameters);
3694 } else {
3695 param_count = 0;
3697 } else {
3698 param_count = 1;
3701 if (param_count == 1) {
3702 parameter = get_param(function, NULL, 0, TRUE);
3704 if (style == SOAP_RPC) {
3705 xmlNode *rpc_result;
3706 if (main && version == SOAP_1_2) {
3707 xmlNs *rpc_ns = xmlNewNs(body, BAD_CAST(RPC_SOAP12_NAMESPACE), BAD_CAST(RPC_SOAP12_NS_PREFIX));
3708 rpc_result = xmlNewChild(method, rpc_ns, BAD_CAST("result"), NULL);
3709 param = serialize_parameter(parameter, ret, 0, "return", use, method TSRMLS_CC);
3710 xmlNodeSetContent(rpc_result,param->name);
3711 } else {
3712 param = serialize_parameter(parameter, ret, 0, "return", use, method TSRMLS_CC);
3714 } else {
3715 param = serialize_parameter(parameter, ret, 0, "return", use, body TSRMLS_CC);
3716 if (function && function->binding->bindingType == BINDING_SOAP) {
3717 if (parameter && parameter->element) {
3718 ns = encode_add_ns(param, parameter->element->namens);
3719 xmlNodeSetName(param, BAD_CAST(parameter->element->name));
3720 xmlSetNs(param, ns);
3722 } else if (strcmp((char*)param->name,"return") == 0) {
3723 ns = encode_add_ns(param, uri);
3724 xmlNodeSetName(param, BAD_CAST(function_name));
3725 xmlSetNs(param, ns);
3728 } else if (param_count > 1 && Z_TYPE_P(ret) == IS_ARRAY) {
3729 HashPosition pos;
3730 zval **data;
3731 int i = 0;
3733 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(ret), &pos);
3734 while (zend_hash_get_current_data_ex(Z_ARRVAL_P(ret), (void **)&data, &pos) != FAILURE) {
3735 char *param_name = NULL;
3736 unsigned int param_name_len;
3737 ulong param_index = i;
3739 zend_hash_get_current_key_ex(Z_ARRVAL_P(ret), &param_name, &param_name_len, &param_index, 0, &pos);
3740 parameter = get_param(function, param_name, param_index, TRUE);
3741 if (style == SOAP_RPC) {
3742 param = serialize_parameter(parameter, *data, i, param_name, use, method TSRMLS_CC);
3743 } else {
3744 param = serialize_parameter(parameter, *data, i, param_name, use, body TSRMLS_CC);
3745 if (function && function->binding->bindingType == BINDING_SOAP) {
3746 if (parameter && parameter->element) {
3747 ns = encode_add_ns(param, parameter->element->namens);
3748 xmlNodeSetName(param, BAD_CAST(parameter->element->name));
3749 xmlSetNs(param, ns);
3754 zend_hash_move_forward_ex(Z_ARRVAL_P(ret), &pos);
3755 i++;
3758 if (use == SOAP_ENCODED && version == SOAP_1_2 && method != NULL) {
3759 xmlSetNsProp(method, body->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_2_ENC_NAMESPACE));
3761 return use;
3764 static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function_name, char *uri, zval *ret, soapHeader* headers, int version TSRMLS_DC)
3766 xmlDocPtr doc;
3767 xmlNodePtr envelope = NULL, body, param;
3768 xmlNsPtr ns = NULL;
3769 int use = SOAP_LITERAL;
3770 xmlNodePtr head = NULL;
3772 encode_reset_ns();
3774 doc = xmlNewDoc(BAD_CAST("1.0"));
3775 doc->charset = XML_CHAR_ENCODING_UTF8;
3776 doc->encoding = xmlCharStrdup("UTF-8");
3778 if (version == SOAP_1_1) {
3779 envelope = xmlNewDocNode(doc, NULL, BAD_CAST("Envelope"), NULL);
3780 ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_1_ENV_NAMESPACE), BAD_CAST(SOAP_1_1_ENV_NS_PREFIX));
3781 xmlSetNs(envelope,ns);
3782 } else if (version == SOAP_1_2) {
3783 envelope = xmlNewDocNode(doc, NULL, BAD_CAST("Envelope"), NULL);
3784 ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENV_NAMESPACE), BAD_CAST(SOAP_1_2_ENV_NS_PREFIX));
3785 xmlSetNs(envelope,ns);
3786 } else {
3787 soap_server_fault("Server", "Unknown SOAP version", NULL, NULL, NULL TSRMLS_CC);
3789 xmlDocSetRootElement(doc, envelope);
3791 if (Z_TYPE_P(ret) == IS_OBJECT &&
3792 instanceof_function(Z_OBJCE_P(ret), soap_fault_class_entry TSRMLS_CC)) {
3793 char *detail_name;
3794 HashTable* prop;
3795 zval **tmp;
3796 sdlFaultPtr fault = NULL;
3797 char *fault_ns = NULL;
3799 prop = Z_OBJPROP_P(ret);
3801 if (headers &&
3802 zend_hash_find(prop, "headerfault", sizeof("headerfault"), (void**)&tmp) == SUCCESS) {
3803 encodePtr hdr_enc = NULL;
3804 int hdr_use = SOAP_LITERAL;
3805 zval *hdr_ret = *tmp;
3806 char *hdr_ns = headers->hdr?headers->hdr->ns:NULL;
3807 char *hdr_name = Z_STRVAL(headers->function_name);
3809 head = xmlNewChild(envelope, ns, BAD_CAST("Header"), NULL);
3810 if (Z_TYPE_P(hdr_ret) == IS_OBJECT &&
3811 instanceof_function(Z_OBJCE_P(hdr_ret), soap_header_class_entry TSRMLS_CC)) {
3812 HashTable* ht = Z_OBJPROP_P(hdr_ret);
3813 sdlSoapBindingFunctionHeaderPtr *hdr;
3814 smart_str key = {0};
3816 if (zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&tmp) == SUCCESS &&
3817 Z_TYPE_PP(tmp) == IS_STRING) {
3818 smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
3819 smart_str_appendc(&key, ':');
3820 hdr_ns = Z_STRVAL_PP(tmp);
3822 if (zend_hash_find(ht, "name", sizeof("name"), (void**)&tmp) == SUCCESS &&
3823 Z_TYPE_PP(tmp) == IS_STRING) {
3824 smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
3825 hdr_name = Z_STRVAL_PP(tmp);
3827 smart_str_0(&key);
3828 if (headers->hdr && headers->hdr->headerfaults &&
3829 zend_hash_find(headers->hdr->headerfaults, key.c, key.len+1, (void**)&hdr) == SUCCESS) {
3830 hdr_enc = (*hdr)->encode;
3831 hdr_use = (*hdr)->use;
3833 smart_str_free(&key);
3834 if (zend_hash_find(ht, "data", sizeof("data"), (void**)&tmp) == SUCCESS) {
3835 hdr_ret = *tmp;
3836 } else {
3837 hdr_ret = NULL;
3841 if (headers->function) {
3842 if (serialize_response_call2(head, headers->function, Z_STRVAL(headers->function_name), uri, hdr_ret, version, 0 TSRMLS_CC) == SOAP_ENCODED) {
3843 use = SOAP_ENCODED;
3845 } else {
3846 xmlNodePtr xmlHdr = master_to_xml(hdr_enc, hdr_ret, hdr_use, head TSRMLS_CC);
3847 if (hdr_name) {
3848 xmlNodeSetName(xmlHdr, BAD_CAST(hdr_name));
3850 if (hdr_ns) {
3851 xmlNsPtr nsptr = encode_add_ns(xmlHdr, hdr_ns);
3852 xmlSetNs(xmlHdr, nsptr);
3857 body = xmlNewChild(envelope, ns, BAD_CAST("Body"), NULL);
3858 param = xmlNewChild(body, ns, BAD_CAST("Fault"), NULL);
3860 if (zend_hash_find(prop, "faultcodens", sizeof("faultcodens"), (void**)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_STRING) {
3861 fault_ns = Z_STRVAL_PP(tmp);
3863 use = SOAP_LITERAL;
3864 if (zend_hash_find(prop, "_name", sizeof("_name"), (void**)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_STRING) {
3865 sdlFaultPtr *tmp_fault;
3866 if (function && function->faults &&
3867 zend_hash_find(function->faults, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)+1, (void**)&tmp_fault) == SUCCESS) {
3868 fault = *tmp_fault;
3869 if (function->binding &&
3870 function->binding->bindingType == BINDING_SOAP &&
3871 fault->bindingAttributes) {
3872 sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
3873 use = fb->use;
3874 if (fault_ns == NULL) {
3875 fault_ns = fb->ns;
3879 } else if (function && function->faults &&
3880 zend_hash_num_elements(function->faults) == 1) {
3882 zend_hash_internal_pointer_reset(function->faults);
3883 zend_hash_get_current_data(function->faults, (void**)&fault);
3884 fault = *(sdlFaultPtr*)fault;
3885 if (function->binding &&
3886 function->binding->bindingType == BINDING_SOAP &&
3887 fault->bindingAttributes) {
3888 sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
3889 use = fb->use;
3890 if (fault_ns == NULL) {
3891 fault_ns = fb->ns;
3896 if (fault_ns == NULL &&
3897 fault &&
3898 fault->details &&
3899 zend_hash_num_elements(fault->details) == 1) {
3900 sdlParamPtr sparam;
3902 zend_hash_internal_pointer_reset(fault->details);
3903 zend_hash_get_current_data(fault->details, (void**)&sparam);
3904 sparam = *(sdlParamPtr*)sparam;
3905 if (sparam->element) {
3906 fault_ns = sparam->element->namens;
3910 if (version == SOAP_1_1) {
3911 if (zend_hash_find(prop, "faultcode", sizeof("faultcode"), (void**)&tmp) == SUCCESS) {
3912 int new_len;
3913 xmlNodePtr node = xmlNewNode(NULL, BAD_CAST("faultcode"));
3914 char *str = php_escape_html_entities((unsigned char*)Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), &new_len, 0, 0, NULL TSRMLS_CC);
3915 xmlAddChild(param, node);
3916 if (fault_ns) {
3917 xmlNsPtr nsptr = encode_add_ns(node, fault_ns);
3918 xmlChar *code = xmlBuildQName(BAD_CAST(str), nsptr->prefix, NULL, 0);
3919 xmlNodeSetContent(node, code);
3920 xmlFree(code);
3921 } else {
3922 xmlNodeSetContentLen(node, BAD_CAST(str), new_len);
3924 efree(str);
3926 if (zend_hash_find(prop, "faultstring", sizeof("faultstring"), (void**)&tmp) == SUCCESS) {
3927 xmlNodePtr node = master_to_xml(get_conversion(IS_STRING), *tmp, SOAP_LITERAL, param TSRMLS_CC);
3928 xmlNodeSetName(node, BAD_CAST("faultstring"));
3930 if (zend_hash_find(prop, "faultactor", sizeof("faultactor"), (void**)&tmp) == SUCCESS) {
3931 xmlNodePtr node = master_to_xml(get_conversion(IS_STRING), *tmp, SOAP_LITERAL, param TSRMLS_CC);
3932 xmlNodeSetName(node, BAD_CAST("faultactor"));
3934 detail_name = "detail";
3935 } else {
3936 if (zend_hash_find(prop, "faultcode", sizeof("faultcode"), (void**)&tmp) == SUCCESS) {
3937 int new_len;
3938 xmlNodePtr node = xmlNewChild(param, ns, BAD_CAST("Code"), NULL);
3939 char *str = php_escape_html_entities((unsigned char*)Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), &new_len, 0, 0, NULL TSRMLS_CC);
3940 node = xmlNewChild(node, ns, BAD_CAST("Value"), NULL);
3941 if (fault_ns) {
3942 xmlNsPtr nsptr = encode_add_ns(node, fault_ns);
3943 xmlChar *code = xmlBuildQName(BAD_CAST(str), nsptr->prefix, NULL, 0);
3944 xmlNodeSetContent(node, code);
3945 xmlFree(code);
3946 } else {
3947 xmlNodeSetContentLen(node, BAD_CAST(str), new_len);
3949 efree(str);
3951 if (zend_hash_find(prop, "faultstring", sizeof("faultstring"), (void**)&tmp) == SUCCESS) {
3952 xmlNodePtr node = xmlNewChild(param, ns, BAD_CAST("Reason"), NULL);
3953 node = master_to_xml(get_conversion(IS_STRING), *tmp, SOAP_LITERAL, node TSRMLS_CC);
3954 xmlNodeSetName(node, BAD_CAST("Text"));
3955 xmlSetNs(node, ns);
3957 detail_name = SOAP_1_2_ENV_NS_PREFIX":Detail";
3959 if (fault && fault->details && zend_hash_num_elements(fault->details) == 1) {
3960 xmlNodePtr node;
3961 zval *detail = NULL;
3962 sdlParamPtr sparam;
3963 xmlNodePtr x;
3965 if (zend_hash_find(prop, "detail", sizeof("detail"), (void**)&tmp) == SUCCESS &&
3966 Z_TYPE_PP(tmp) != IS_NULL) {
3967 detail = *tmp;
3969 node = xmlNewNode(NULL, BAD_CAST(detail_name));
3970 xmlAddChild(param, node);
3972 zend_hash_internal_pointer_reset(fault->details);
3973 zend_hash_get_current_data(fault->details, (void**)&sparam);
3974 sparam = *(sdlParamPtr*)sparam;
3976 if (detail &&
3977 Z_TYPE_P(detail) == IS_OBJECT &&
3978 sparam->element &&
3979 zend_hash_num_elements(Z_OBJPROP_P(detail)) == 1 &&
3980 zend_hash_find(Z_OBJPROP_P(detail), sparam->element->name, strlen(sparam->element->name)+1, (void**)&tmp) == SUCCESS) {
3981 detail = *tmp;
3984 x = serialize_parameter(sparam, detail, 1, NULL, use, node TSRMLS_CC);
3986 if (function &&
3987 function->binding &&
3988 function->binding->bindingType == BINDING_SOAP &&
3989 function->bindingAttributes) {
3990 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
3991 if (fnb->style == SOAP_RPC && !sparam->element) {
3992 if (fault->bindingAttributes) {
3993 sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
3994 if (fb->ns) {
3995 xmlNsPtr ns = encode_add_ns(x, fb->ns);
3996 xmlSetNs(x, ns);
3999 } else {
4000 if (sparam->element) {
4001 ns = encode_add_ns(x, sparam->element->namens);
4002 xmlNodeSetName(x, BAD_CAST(sparam->element->name));
4003 xmlSetNs(x, ns);
4007 if (use == SOAP_ENCODED && version == SOAP_1_2) {
4008 xmlSetNsProp(x, envelope->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_2_ENC_NAMESPACE));
4010 } else if (zend_hash_find(prop, "detail", sizeof("detail"), (void**)&tmp) == SUCCESS &&
4011 Z_TYPE_PP(tmp) != IS_NULL) {
4012 serialize_zval(*tmp, NULL, detail_name, use, param TSRMLS_CC);
4014 } else {
4016 if (headers) {
4017 soapHeader *h;
4019 head = xmlNewChild(envelope, ns, BAD_CAST("Header"), NULL);
4020 h = headers;
4021 while (h != NULL) {
4022 if (Z_TYPE(h->retval) != IS_NULL) {
4023 encodePtr hdr_enc = NULL;
4024 int hdr_use = SOAP_LITERAL;
4025 zval *hdr_ret = &h->retval;
4026 char *hdr_ns = h->hdr?h->hdr->ns:NULL;
4027 char *hdr_name = Z_STRVAL(h->function_name);
4030 if (Z_TYPE(h->retval) == IS_OBJECT &&
4031 instanceof_function(Z_OBJCE(h->retval), soap_header_class_entry TSRMLS_CC)) {
4032 HashTable* ht = Z_OBJPROP(h->retval);
4033 zval **tmp;
4034 sdlSoapBindingFunctionHeaderPtr *hdr;
4035 smart_str key = {0};
4037 if (zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&tmp) == SUCCESS &&
4038 Z_TYPE_PP(tmp) == IS_STRING) {
4039 smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
4040 smart_str_appendc(&key, ':');
4041 hdr_ns = Z_STRVAL_PP(tmp);
4043 if (zend_hash_find(ht, "name", sizeof("name"), (void**)&tmp) == SUCCESS &&
4044 Z_TYPE_PP(tmp) == IS_STRING) {
4045 smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
4046 hdr_name = Z_STRVAL_PP(tmp);
4048 smart_str_0(&key);
4049 if (function && function->binding && function->binding->bindingType == BINDING_SOAP) {
4050 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
4052 if (fnb->output.headers &&
4053 zend_hash_find(fnb->output.headers, key.c, key.len+1, (void**)&hdr) == SUCCESS) {
4054 hdr_enc = (*hdr)->encode;
4055 hdr_use = (*hdr)->use;
4058 smart_str_free(&key);
4059 if (zend_hash_find(ht, "data", sizeof("data"), (void**)&tmp) == SUCCESS) {
4060 hdr_ret = *tmp;
4061 } else {
4062 hdr_ret = NULL;
4066 if (h->function) {
4067 if (serialize_response_call2(head, h->function, Z_STRVAL(h->function_name), uri, hdr_ret, version, 0 TSRMLS_CC) == SOAP_ENCODED) {
4068 use = SOAP_ENCODED;
4070 } else {
4071 xmlNodePtr xmlHdr = master_to_xml(hdr_enc, hdr_ret, hdr_use, head TSRMLS_CC);
4072 if (hdr_name) {
4073 xmlNodeSetName(xmlHdr, BAD_CAST(hdr_name));
4075 if (hdr_ns) {
4076 xmlNsPtr nsptr = encode_add_ns(xmlHdr,hdr_ns);
4077 xmlSetNs(xmlHdr, nsptr);
4081 h = h->next;
4084 if (head->children == NULL) {
4085 xmlUnlinkNode(head);
4086 xmlFreeNode(head);
4090 body = xmlNewChild(envelope, ns, BAD_CAST("Body"), NULL);
4092 if (serialize_response_call2(body, function, function_name, uri, ret, version, 1 TSRMLS_CC) == SOAP_ENCODED) {
4093 use = SOAP_ENCODED;
4098 if (use == SOAP_ENCODED) {
4099 xmlNewNs(envelope, BAD_CAST(XSD_NAMESPACE), BAD_CAST(XSD_NS_PREFIX));
4100 if (version == SOAP_1_1) {
4101 xmlNewNs(envelope, BAD_CAST(SOAP_1_1_ENC_NAMESPACE), BAD_CAST(SOAP_1_1_ENC_NS_PREFIX));
4102 xmlSetNsProp(envelope, envelope->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_1_ENC_NAMESPACE));
4103 } else if (version == SOAP_1_2) {
4104 xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENC_NAMESPACE), BAD_CAST(SOAP_1_2_ENC_NS_PREFIX));
4108 encode_finish();
4110 if (function && function->responseName == NULL &&
4111 body->children == NULL && head == NULL) {
4112 xmlFreeDoc(doc);
4113 return NULL;
4115 return doc;
4118 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 TSRMLS_DC)
4120 xmlDoc *doc;
4121 xmlNodePtr envelope = NULL, body, method = NULL, head = NULL;
4122 xmlNsPtr ns = NULL;
4123 zval **zstyle, **zuse;
4124 int i, style, use;
4125 HashTable *hdrs = NULL;
4127 encode_reset_ns();
4129 doc = xmlNewDoc(BAD_CAST("1.0"));
4130 doc->encoding = xmlCharStrdup("UTF-8");
4131 doc->charset = XML_CHAR_ENCODING_UTF8;
4132 if (version == SOAP_1_1) {
4133 envelope = xmlNewDocNode(doc, NULL, BAD_CAST("Envelope"), NULL);
4134 ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_1_ENV_NAMESPACE), BAD_CAST(SOAP_1_1_ENV_NS_PREFIX));
4135 xmlSetNs(envelope, ns);
4136 } else if (version == SOAP_1_2) {
4137 envelope = xmlNewDocNode(doc, NULL, BAD_CAST("Envelope"), NULL);
4138 ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENV_NAMESPACE), BAD_CAST(SOAP_1_2_ENV_NS_PREFIX));
4139 xmlSetNs(envelope, ns);
4140 } else {
4141 soap_error0(E_ERROR, "Unknown SOAP version");
4143 xmlDocSetRootElement(doc, envelope);
4145 if (soap_headers) {
4146 head = xmlNewChild(envelope, ns, BAD_CAST("Header"), NULL);
4149 body = xmlNewChild(envelope, ns, BAD_CAST("Body"), NULL);
4151 if (function && function->binding->bindingType == BINDING_SOAP) {
4152 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
4154 hdrs = fnb->input.headers;
4155 style = fnb->style;
4156 /*FIXME: how to pass method name if style is SOAP_DOCUMENT */
4157 /*style = SOAP_RPC;*/
4158 use = fnb->input.use;
4159 if (style == SOAP_RPC) {
4160 ns = encode_add_ns(body, fnb->input.ns);
4161 if (function->requestName) {
4162 method = xmlNewChild(body, ns, BAD_CAST(function->requestName), NULL);
4163 } else {
4164 method = xmlNewChild(body, ns, BAD_CAST(function->functionName), NULL);
4167 } else {
4168 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "style", sizeof("style"), (void **)&zstyle) == SUCCESS) {
4169 style = Z_LVAL_PP(zstyle);
4170 } else {
4171 style = SOAP_RPC;
4173 /*FIXME: how to pass method name if style is SOAP_DOCUMENT */
4174 /*style = SOAP_RPC;*/
4175 if (style == SOAP_RPC) {
4176 ns = encode_add_ns(body, uri);
4177 if (function_name) {
4178 method = xmlNewChild(body, ns, BAD_CAST(function_name), NULL);
4179 } else if (function && function->requestName) {
4180 method = xmlNewChild(body, ns, BAD_CAST(function->requestName), NULL);
4181 } else if (function && function->functionName) {
4182 method = xmlNewChild(body, ns, BAD_CAST(function->functionName), NULL);
4183 } else {
4184 method = body;
4186 } else {
4187 method = body;
4190 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "use", sizeof("use"), (void **)&zuse) == SUCCESS &&
4191 Z_LVAL_PP(zuse) == SOAP_LITERAL) {
4192 use = SOAP_LITERAL;
4193 } else {
4194 use = SOAP_ENCODED;
4198 for (i = 0;i < arg_count;i++) {
4199 xmlNodePtr param;
4200 sdlParamPtr parameter = get_param(function, NULL, i, FALSE);
4202 if (style == SOAP_RPC) {
4203 param = serialize_parameter(parameter, arguments[i], i, NULL, use, method TSRMLS_CC);
4204 } else if (style == SOAP_DOCUMENT) {
4205 param = serialize_parameter(parameter, arguments[i], i, NULL, use, body TSRMLS_CC);
4206 if (function && function->binding->bindingType == BINDING_SOAP) {
4207 if (parameter && parameter->element) {
4208 ns = encode_add_ns(param, parameter->element->namens);
4209 xmlNodeSetName(param, BAD_CAST(parameter->element->name));
4210 xmlSetNs(param, ns);
4216 if (function && function->requestParameters) {
4217 int n = zend_hash_num_elements(function->requestParameters);
4219 if (n > arg_count) {
4220 for (i = arg_count; i < n; i++) {
4221 xmlNodePtr param;
4222 sdlParamPtr parameter = get_param(function, NULL, i, FALSE);
4224 if (style == SOAP_RPC) {
4225 param = serialize_parameter(parameter, NULL, i, NULL, use, method TSRMLS_CC);
4226 } else if (style == SOAP_DOCUMENT) {
4227 param = serialize_parameter(parameter, NULL, i, NULL, use, body TSRMLS_CC);
4228 if (function && function->binding->bindingType == BINDING_SOAP) {
4229 if (parameter && parameter->element) {
4230 ns = encode_add_ns(param, parameter->element->namens);
4231 xmlNodeSetName(param, BAD_CAST(parameter->element->name));
4232 xmlSetNs(param, ns);
4240 if (head) {
4241 zval** header;
4243 zend_hash_internal_pointer_reset(soap_headers);
4244 while (zend_hash_get_current_data(soap_headers,(void**)&header) == SUCCESS) {
4245 HashTable *ht = Z_OBJPROP_PP(header);
4246 zval **name, **ns, **tmp;
4248 if (zend_hash_find(ht, "name", sizeof("name"), (void**)&name) == SUCCESS &&
4249 Z_TYPE_PP(name) == IS_STRING &&
4250 zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&ns) == SUCCESS &&
4251 Z_TYPE_PP(ns) == IS_STRING) {
4252 xmlNodePtr h;
4253 xmlNsPtr nsptr;
4254 int hdr_use = SOAP_LITERAL;
4255 encodePtr enc = NULL;
4257 if (hdrs) {
4258 smart_str key = {0};
4259 sdlSoapBindingFunctionHeaderPtr *hdr;
4261 smart_str_appendl(&key, Z_STRVAL_PP(ns), Z_STRLEN_PP(ns));
4262 smart_str_appendc(&key, ':');
4263 smart_str_appendl(&key, Z_STRVAL_PP(name), Z_STRLEN_PP(name));
4264 smart_str_0(&key);
4265 if (zend_hash_find(hdrs, key.c, key.len+1,(void**)&hdr) == SUCCESS) {
4266 hdr_use = (*hdr)->use;
4267 enc = (*hdr)->encode;
4268 if (hdr_use == SOAP_ENCODED) {
4269 use = SOAP_ENCODED;
4272 smart_str_free(&key);
4275 if (zend_hash_find(ht, "data", sizeof("data"), (void**)&tmp) == SUCCESS) {
4276 h = master_to_xml(enc, *tmp, hdr_use, head TSRMLS_CC);
4277 xmlNodeSetName(h, BAD_CAST(Z_STRVAL_PP(name)));
4278 } else {
4279 h = xmlNewNode(NULL, BAD_CAST(Z_STRVAL_PP(name)));
4280 xmlAddChild(head, h);
4282 nsptr = encode_add_ns(h, Z_STRVAL_PP(ns));
4283 xmlSetNs(h, nsptr);
4285 if (zend_hash_find(ht, "mustUnderstand", sizeof("mustUnderstand"), (void**)&tmp) == SUCCESS &&
4286 Z_TYPE_PP(tmp) == IS_BOOL && Z_LVAL_PP(tmp)) {
4287 if (version == SOAP_1_1) {
4288 xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":mustUnderstand"), BAD_CAST("1"));
4289 } else {
4290 xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":mustUnderstand"), BAD_CAST("true"));
4293 if (zend_hash_find(ht, "actor", sizeof("actor"), (void**)&tmp) == SUCCESS) {
4294 if (Z_TYPE_PP(tmp) == IS_STRING) {
4295 if (version == SOAP_1_1) {
4296 xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(Z_STRVAL_PP(tmp)));
4297 } else {
4298 xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(Z_STRVAL_PP(tmp)));
4300 } else if (Z_TYPE_PP(tmp) == IS_LONG) {
4301 if (version == SOAP_1_1) {
4302 if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NEXT) {
4303 xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(SOAP_1_1_ACTOR_NEXT));
4305 } else {
4306 if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NEXT) {
4307 xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_NEXT));
4308 } else if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NONE) {
4309 xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_NONE));
4310 } else if (Z_LVAL_PP(tmp) == SOAP_ACTOR_UNLIMATERECEIVER) {
4311 xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_UNLIMATERECEIVER));
4317 zend_hash_move_forward(soap_headers);
4321 if (use == SOAP_ENCODED) {
4322 xmlNewNs(envelope, BAD_CAST(XSD_NAMESPACE), BAD_CAST(XSD_NS_PREFIX));
4323 if (version == SOAP_1_1) {
4324 xmlNewNs(envelope, BAD_CAST(SOAP_1_1_ENC_NAMESPACE), BAD_CAST(SOAP_1_1_ENC_NS_PREFIX));
4325 xmlSetNsProp(envelope, envelope->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_1_ENC_NAMESPACE));
4326 } else if (version == SOAP_1_2) {
4327 xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENC_NAMESPACE), BAD_CAST(SOAP_1_2_ENC_NS_PREFIX));
4328 if (method) {
4329 xmlSetNsProp(method, envelope->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_2_ENC_NAMESPACE));
4334 encode_finish();
4336 return doc;
4339 static xmlNodePtr serialize_parameter(sdlParamPtr param, zval *param_val, int index, char *name, int style, xmlNodePtr parent TSRMLS_DC)
4341 char *paramName;
4342 xmlNodePtr xmlParam;
4343 char paramNameBuf[10];
4345 if (param_val &&
4346 Z_TYPE_P(param_val) == IS_OBJECT &&
4347 Z_OBJCE_P(param_val) == soap_param_class_entry) {
4348 zval **param_name;
4349 zval **param_data;
4351 if (zend_hash_find(Z_OBJPROP_P(param_val), "param_name", sizeof("param_name"), (void **)&param_name) == SUCCESS &&
4352 zend_hash_find(Z_OBJPROP_P(param_val), "param_data", sizeof("param_data"), (void **)&param_data) == SUCCESS) {
4353 param_val = *param_data;
4354 name = Z_STRVAL_PP(param_name);
4358 if (param != NULL && param->paramName != NULL) {
4359 paramName = param->paramName;
4360 } else {
4361 if (name == NULL) {
4362 paramName = paramNameBuf;
4363 snprintf(paramName, sizeof(paramNameBuf), "param%d",index);
4364 } else {
4365 paramName = name;
4369 xmlParam = serialize_zval(param_val, param, paramName, style, parent TSRMLS_CC);
4371 return xmlParam;
4374 static xmlNodePtr serialize_zval(zval *val, sdlParamPtr param, char *paramName, int style, xmlNodePtr parent TSRMLS_DC)
4376 xmlNodePtr xmlParam;
4377 encodePtr enc;
4378 zval defval;
4380 if (param != NULL) {
4381 enc = param->encode;
4382 if (val == NULL) {
4383 if (param->element) {
4384 if (param->element->fixed) {
4385 ZVAL_STRING(&defval, param->element->fixed, 0);
4386 val = &defval;
4387 } else if (param->element->def && !param->element->nillable) {
4388 ZVAL_STRING(&defval, param->element->def, 0);
4389 val = &defval;
4393 } else {
4394 enc = NULL;
4396 xmlParam = master_to_xml(enc, val, style, parent TSRMLS_CC);
4397 if (!strcmp((char*)xmlParam->name, "BOGUS")) {
4398 xmlNodeSetName(xmlParam, BAD_CAST(paramName));
4400 return xmlParam;
4403 static sdlParamPtr get_param(sdlFunctionPtr function, char *param_name, int index, int response)
4405 sdlParamPtr *tmp;
4406 HashTable *ht;
4408 if (function == NULL) {
4409 return NULL;
4412 if (response == FALSE) {
4413 ht = function->requestParameters;
4414 } else {
4415 ht = function->responseParameters;
4418 if (ht == NULL) {
4419 return NULL;
4422 if (param_name != NULL) {
4423 if (zend_hash_find(ht, param_name, strlen(param_name), (void **)&tmp) != FAILURE) {
4424 return *tmp;
4425 } else {
4426 HashPosition pos;
4428 zend_hash_internal_pointer_reset_ex(ht, &pos);
4429 while (zend_hash_get_current_data_ex(ht, (void **)&tmp, &pos) != FAILURE) {
4430 if ((*tmp)->paramName && strcmp(param_name, (*tmp)->paramName) == 0) {
4431 return *tmp;
4433 zend_hash_move_forward_ex(ht, &pos);
4436 } else {
4437 if (zend_hash_index_find(ht, index, (void **)&tmp) != FAILURE) {
4438 return (*tmp);
4441 return NULL;
4444 static sdlFunctionPtr get_function(sdlPtr sdl, const char *function_name)
4446 sdlFunctionPtr *tmp;
4448 int len = strlen(function_name);
4449 char *str = estrndup(function_name,len);
4450 php_strtolower(str,len);
4451 if (sdl != NULL) {
4452 if (zend_hash_find(&sdl->functions, str, len+1, (void **)&tmp) != FAILURE) {
4453 efree(str);
4454 return (*tmp);
4455 } else if (sdl->requests != NULL && zend_hash_find(sdl->requests, str, len+1, (void **)&tmp) != FAILURE) {
4456 efree(str);
4457 return (*tmp);
4460 efree(str);
4461 return NULL;
4464 static sdlFunctionPtr get_doc_function(sdlPtr sdl, xmlNodePtr params)
4466 if (sdl) {
4467 sdlFunctionPtr *tmp;
4468 sdlParamPtr *param;
4470 zend_hash_internal_pointer_reset(&sdl->functions);
4471 while (zend_hash_get_current_data(&sdl->functions, (void**)&tmp) == SUCCESS) {
4472 if ((*tmp)->binding && (*tmp)->binding->bindingType == BINDING_SOAP) {
4473 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)(*tmp)->bindingAttributes;
4474 if (fnb->style == SOAP_DOCUMENT) {
4475 if (params == NULL) {
4476 if ((*tmp)->requestParameters == NULL ||
4477 zend_hash_num_elements((*tmp)->requestParameters) == 0) {
4478 return *tmp;
4480 } else if ((*tmp)->requestParameters != NULL &&
4481 zend_hash_num_elements((*tmp)->requestParameters) > 0) {
4482 int ok = 1;
4483 xmlNodePtr node = params;
4485 zend_hash_internal_pointer_reset((*tmp)->requestParameters);
4486 while (zend_hash_get_current_data((*tmp)->requestParameters, (void**)&param) == SUCCESS) {
4487 if ((*param)->element) {
4488 if (strcmp((*param)->element->name, (char*)node->name) != 0) {
4489 ok = 0;
4490 break;
4492 if ((*param)->element->namens != NULL && node->ns != NULL) {
4493 if (strcmp((*param)->element->namens, (char*)node->ns->href) != 0) {
4494 ok = 0;
4495 break;
4497 } else if ((void*)(*param)->element->namens != (void*)node->ns) {
4498 ok = 0;
4499 break;
4501 } else if (strcmp((*param)->paramName, (char*)node->name) != 0) {
4502 ok = 0;
4503 break;
4505 zend_hash_move_forward((*tmp)->requestParameters);
4506 node = node->next;
4508 if (ok /*&& node == NULL*/) {
4509 return (*tmp);
4514 zend_hash_move_forward(&sdl->functions);
4517 return NULL;
4520 static void function_to_string(sdlFunctionPtr function, smart_str *buf)
4522 int i = 0;
4523 HashPosition pos;
4524 sdlParamPtr *param;
4526 if (function->responseParameters &&
4527 zend_hash_num_elements(function->responseParameters) > 0) {
4528 if (zend_hash_num_elements(function->responseParameters) == 1) {
4529 zend_hash_internal_pointer_reset(function->responseParameters);
4530 zend_hash_get_current_data(function->responseParameters, (void**)&param);
4531 if ((*param)->encode && (*param)->encode->details.type_str) {
4532 smart_str_appendl(buf, (*param)->encode->details.type_str, strlen((*param)->encode->details.type_str));
4533 smart_str_appendc(buf, ' ');
4534 } else {
4535 smart_str_appendl(buf, "UNKNOWN ", 8);
4537 } else {
4538 i = 0;
4539 smart_str_appendl(buf, "list(", 5);
4540 zend_hash_internal_pointer_reset_ex(function->responseParameters, &pos);
4541 while (zend_hash_get_current_data_ex(function->responseParameters, (void **)&param, &pos) != FAILURE) {
4542 if (i > 0) {
4543 smart_str_appendl(buf, ", ", 2);
4545 if ((*param)->encode && (*param)->encode->details.type_str) {
4546 smart_str_appendl(buf, (*param)->encode->details.type_str, strlen((*param)->encode->details.type_str));
4547 } else {
4548 smart_str_appendl(buf, "UNKNOWN", 7);
4550 smart_str_appendl(buf, " $", 2);
4551 smart_str_appendl(buf, (*param)->paramName, strlen((*param)->paramName));
4552 zend_hash_move_forward_ex(function->responseParameters, &pos);
4553 i++;
4555 smart_str_appendl(buf, ") ", 2);
4557 } else {
4558 smart_str_appendl(buf, "void ", 5);
4561 smart_str_appendl(buf, function->functionName, strlen(function->functionName));
4563 smart_str_appendc(buf, '(');
4564 if (function->requestParameters) {
4565 i = 0;
4566 zend_hash_internal_pointer_reset_ex(function->requestParameters, &pos);
4567 while (zend_hash_get_current_data_ex(function->requestParameters, (void **)&param, &pos) != FAILURE) {
4568 if (i > 0) {
4569 smart_str_appendl(buf, ", ", 2);
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 } else {
4574 smart_str_appendl(buf, "UNKNOWN", 7);
4576 smart_str_appendl(buf, " $", 2);
4577 smart_str_appendl(buf, (*param)->paramName, strlen((*param)->paramName));
4578 zend_hash_move_forward_ex(function->requestParameters, &pos);
4579 i++;
4582 smart_str_appendc(buf, ')');
4583 smart_str_0(buf);
4586 static void model_to_string(sdlContentModelPtr model, smart_str *buf, int level)
4588 int i;
4590 switch (model->kind) {
4591 case XSD_CONTENT_ELEMENT:
4592 type_to_string(model->u.element, buf, level);
4593 smart_str_appendl(buf, ";\n", 2);
4594 break;
4595 case XSD_CONTENT_ANY:
4596 for (i = 0;i < level;i++) {
4597 smart_str_appendc(buf, ' ');
4599 smart_str_appendl(buf, "<anyXML> any;\n", sizeof("<anyXML> any;\n")-1);
4600 break;
4601 case XSD_CONTENT_SEQUENCE:
4602 case XSD_CONTENT_ALL:
4603 case XSD_CONTENT_CHOICE: {
4604 sdlContentModelPtr *tmp;
4606 zend_hash_internal_pointer_reset(model->u.content);
4607 while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
4608 model_to_string(*tmp, buf, level);
4609 zend_hash_move_forward(model->u.content);
4611 break;
4613 case XSD_CONTENT_GROUP:
4614 model_to_string(model->u.group->model, buf, level);
4615 default:
4616 break;
4620 static void type_to_string(sdlTypePtr type, smart_str *buf, int level)
4622 int i;
4623 smart_str spaces = {0};
4624 HashPosition pos;
4626 for (i = 0;i < level;i++) {
4627 smart_str_appendc(&spaces, ' ');
4629 smart_str_appendl(buf, spaces.c, spaces.len);
4631 switch (type->kind) {
4632 case XSD_TYPEKIND_SIMPLE:
4633 if (type->encode) {
4634 smart_str_appendl(buf, type->encode->details.type_str, strlen(type->encode->details.type_str));
4635 smart_str_appendc(buf, ' ');
4636 } else {
4637 smart_str_appendl(buf, "anyType ", sizeof("anyType ")-1);
4639 smart_str_appendl(buf, type->name, strlen(type->name));
4640 break;
4641 case XSD_TYPEKIND_LIST:
4642 smart_str_appendl(buf, "list ", 5);
4643 smart_str_appendl(buf, type->name, strlen(type->name));
4644 if (type->elements) {
4645 sdlTypePtr *item_type;
4647 smart_str_appendl(buf, " {", 2);
4648 zend_hash_internal_pointer_reset_ex(type->elements, &pos);
4649 if (zend_hash_get_current_data_ex(type->elements, (void **)&item_type, &pos) != FAILURE) {
4650 smart_str_appendl(buf, (*item_type)->name, strlen((*item_type)->name));
4652 smart_str_appendc(buf, '}');
4654 break;
4655 case XSD_TYPEKIND_UNION:
4656 smart_str_appendl(buf, "union ", 6);
4657 smart_str_appendl(buf, type->name, strlen(type->name));
4658 if (type->elements) {
4659 sdlTypePtr *item_type;
4660 int first = 0;
4662 smart_str_appendl(buf, " {", 2);
4663 zend_hash_internal_pointer_reset_ex(type->elements, &pos);
4664 while (zend_hash_get_current_data_ex(type->elements, (void **)&item_type, &pos) != FAILURE) {
4665 if (!first) {
4666 smart_str_appendc(buf, ',');
4667 first = 0;
4669 smart_str_appendl(buf, (*item_type)->name, strlen((*item_type)->name));
4670 zend_hash_move_forward_ex(type->elements, &pos);
4672 smart_str_appendc(buf, '}');
4674 break;
4675 case XSD_TYPEKIND_COMPLEX:
4676 case XSD_TYPEKIND_RESTRICTION:
4677 case XSD_TYPEKIND_EXTENSION:
4678 if (type->encode &&
4679 (type->encode->details.type == IS_ARRAY ||
4680 type->encode->details.type == SOAP_ENC_ARRAY)) {
4681 sdlAttributePtr *attr;
4682 sdlExtraAttributePtr *ext;
4684 if (type->attributes &&
4685 zend_hash_find(type->attributes, SOAP_1_1_ENC_NAMESPACE":arrayType",
4686 sizeof(SOAP_1_1_ENC_NAMESPACE":arrayType"),
4687 (void **)&attr) == SUCCESS &&
4688 zend_hash_find((*attr)->extraAttributes, WSDL_NAMESPACE":arrayType", sizeof(WSDL_NAMESPACE":arrayType"), (void **)&ext) == SUCCESS) {
4689 char *end = strchr((*ext)->val, '[');
4690 int len;
4691 if (end == NULL) {
4692 len = strlen((*ext)->val);
4693 } else {
4694 len = end-(*ext)->val;
4696 if (len == 0) {
4697 smart_str_appendl(buf, "anyType", sizeof("anyType")-1);
4698 } else {
4699 smart_str_appendl(buf, (*ext)->val, len);
4701 smart_str_appendc(buf, ' ');
4702 smart_str_appendl(buf, type->name, strlen(type->name));
4703 if (end != NULL) {
4704 smart_str_appends(buf, end);
4706 } else {
4707 sdlTypePtr elementType;
4708 if (type->attributes &&
4709 zend_hash_find(type->attributes, SOAP_1_2_ENC_NAMESPACE":itemType",
4710 sizeof(SOAP_1_2_ENC_NAMESPACE":itemType"),
4711 (void **)&attr) == SUCCESS &&
4712 zend_hash_find((*attr)->extraAttributes, WSDL_NAMESPACE":itemType", sizeof(WSDL_NAMESPACE":arrayType"), (void **)&ext) == SUCCESS) {
4713 smart_str_appends(buf, (*ext)->val);
4714 smart_str_appendc(buf, ' ');
4715 } else if (type->elements &&
4716 zend_hash_num_elements(type->elements) == 1 &&
4717 (zend_hash_internal_pointer_reset(type->elements),
4718 zend_hash_get_current_data(type->elements, (void**)&elementType) == SUCCESS) &&
4719 (elementType = *(sdlTypePtr*)elementType) != NULL &&
4720 elementType->encode && elementType->encode->details.type_str) {
4721 smart_str_appends(buf, elementType->encode->details.type_str);
4722 smart_str_appendc(buf, ' ');
4723 } else {
4724 smart_str_appendl(buf, "anyType ", 8);
4726 smart_str_appendl(buf, type->name, strlen(type->name));
4727 if (type->attributes &&
4728 zend_hash_find(type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
4729 sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize"),
4730 (void **)&attr) == SUCCESS &&
4731 zend_hash_find((*attr)->extraAttributes, WSDL_NAMESPACE":itemType", sizeof(WSDL_NAMESPACE":arraySize"), (void **)&ext) == SUCCESS) {
4732 smart_str_appendc(buf, '[');
4733 smart_str_appends(buf, (*ext)->val);
4734 smart_str_appendc(buf, ']');
4735 } else {
4736 smart_str_appendl(buf, "[]", 2);
4739 } else {
4740 smart_str_appendl(buf, "struct ", 7);
4741 smart_str_appendl(buf, type->name, strlen(type->name));
4742 smart_str_appendc(buf, ' ');
4743 smart_str_appendl(buf, "{\n", 2);
4744 if ((type->kind == XSD_TYPEKIND_RESTRICTION ||
4745 type->kind == XSD_TYPEKIND_EXTENSION) && type->encode) {
4746 encodePtr enc = type->encode;
4747 while (enc && enc->details.sdl_type &&
4748 enc != enc->details.sdl_type->encode &&
4749 enc->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
4750 enc->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
4751 enc->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
4752 enc = enc->details.sdl_type->encode;
4754 if (enc) {
4755 smart_str_appendl(buf, spaces.c, spaces.len);
4756 smart_str_appendc(buf, ' ');
4757 smart_str_appendl(buf, type->encode->details.type_str, strlen(type->encode->details.type_str));
4758 smart_str_appendl(buf, " _;\n", 4);
4761 if (type->model) {
4762 model_to_string(type->model, buf, level+1);
4764 if (type->attributes) {
4765 sdlAttributePtr *attr;
4767 zend_hash_internal_pointer_reset_ex(type->attributes, &pos);
4768 while (zend_hash_get_current_data_ex(type->attributes, (void **)&attr, &pos) != FAILURE) {
4769 smart_str_appendl(buf, spaces.c, spaces.len);
4770 smart_str_appendc(buf, ' ');
4771 if ((*attr)->encode && (*attr)->encode->details.type_str) {
4772 smart_str_appends(buf, (*attr)->encode->details.type_str);
4773 smart_str_appendc(buf, ' ');
4774 } else {
4775 smart_str_appendl(buf, "UNKNOWN ", 8);
4777 smart_str_appends(buf, (*attr)->name);
4778 smart_str_appendl(buf, ";\n", 2);
4779 zend_hash_move_forward_ex(type->attributes, &pos);
4782 smart_str_appendl(buf, spaces.c, spaces.len);
4783 smart_str_appendc(buf, '}');
4785 break;
4786 default:
4787 break;
4789 smart_str_free(&spaces);
4790 smart_str_0(buf);
4793 static void delete_url(void *handle)
4795 php_url_free((php_url*)handle);
4798 static void delete_service(void *data)
4800 soapServicePtr service = (soapServicePtr)data;
4802 if (service->soap_functions.ft) {
4803 zend_hash_destroy(service->soap_functions.ft);
4804 efree(service->soap_functions.ft);
4807 if (service->typemap) {
4808 zend_hash_destroy(service->typemap);
4809 efree(service->typemap);
4812 if (service->soap_class.argc) {
4813 int i;
4814 for (i = 0; i < service->soap_class.argc;i++) {
4815 zval_ptr_dtor(&service->soap_class.argv[i]);
4817 efree(service->soap_class.argv);
4820 if (service->actor) {
4821 efree(service->actor);
4823 if (service->uri) {
4824 efree(service->uri);
4826 if (service->sdl) {
4827 delete_sdl(service->sdl);
4829 if (service->encoding) {
4830 xmlCharEncCloseFunc(service->encoding);
4832 if (service->class_map) {
4833 zend_hash_destroy(service->class_map);
4834 FREE_HASHTABLE(service->class_map);
4836 if (service->soap_object) {
4837 zval_ptr_dtor(&service->soap_object);
4839 efree(service);
4842 static void delete_hashtable(void *data)
4844 HashTable *ht = (HashTable*)data;
4845 zend_hash_destroy(ht);
4846 efree(ht);