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