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