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