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