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