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