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