xref: /PHP-7.4/ext/soap/php_sdl.c (revision 51d76c34)
19d2f84e4SDerick Rethans /*
29d2f84e4SDerick Rethans   +----------------------------------------------------------------------+
3d0cb7153SJohannes Schlüter   | PHP Version 7                                                        |
49d2f84e4SDerick Rethans   +----------------------------------------------------------------------+
50cf7de1cSZeev Suraski   | Copyright (c) The PHP Group                                          |
69d2f84e4SDerick Rethans   +----------------------------------------------------------------------+
75bd93221Sfoobar   | This source file is subject to version 3.01 of the PHP license,      |
89d2f84e4SDerick Rethans   | that is bundled with this package in the file LICENSE, and is        |
99d2f84e4SDerick Rethans   | available through the world-wide-web at the following url:           |
105bd93221Sfoobar   | http://www.php.net/license/3_01.txt                                  |
119d2f84e4SDerick Rethans   | If you did not receive a copy of the PHP license and are unable to   |
129d2f84e4SDerick Rethans   | obtain it through the world-wide-web, please send a note to          |
139d2f84e4SDerick Rethans   | license@php.net so we can mail you a copy immediately.               |
149d2f84e4SDerick Rethans   +----------------------------------------------------------------------+
15e439a1afSDmitry Stogov   | Authors: Brad Lafountain <rodif_bl@yahoo.com>                        |
16e439a1afSDmitry Stogov   |          Shane Caraveo <shane@caraveo.com>                           |
179afce019SZeev Suraski   |          Dmitry Stogov <dmitry@php.net>                              |
189d2f84e4SDerick Rethans   +----------------------------------------------------------------------+
199d2f84e4SDerick Rethans */
209d2f84e4SDerick Rethans 
21f8875adaSShane Caraveo #include "php_soap.h"
229c5661f0SDmitry Stogov #include "ext/libxml/php_libxml.h"
231b6f1762SDmitry Stogov #include "libxml/uri.h"
24f8875adaSShane Caraveo 
2520add786SDmitry Stogov #include "ext/standard/md5.h"
26e30b2aaeSAnatol Belski #include "zend_virtual_cwd.h"
2720add786SDmitry Stogov 
2820add786SDmitry Stogov #include <sys/types.h>
2920add786SDmitry Stogov #include <sys/stat.h>
3020add786SDmitry Stogov #include <fcntl.h>
3120add786SDmitry Stogov 
3220add786SDmitry Stogov #ifndef O_BINARY
3320add786SDmitry Stogov # define O_BINARY 0
3420add786SDmitry Stogov #endif
3520add786SDmitry Stogov 
36c446e575SDmitry Stogov static void delete_fault(zval *zv);
37c446e575SDmitry Stogov static void delete_fault_persistent(zval *zv);
38c446e575SDmitry Stogov static void delete_binding(zval *zv);
39c446e575SDmitry Stogov static void delete_binding_persistent(zval *zv);
40c446e575SDmitry Stogov static void delete_function(zval *zv);
41c446e575SDmitry Stogov static void delete_function_persistent(zval *zv);
42c446e575SDmitry Stogov static void delete_parameter(zval *zv);
43c446e575SDmitry Stogov static void delete_parameter_persistent(zval *zv);
44c446e575SDmitry Stogov static void delete_header(zval *header);
45c446e575SDmitry Stogov static void delete_header_int(sdlSoapBindingFunctionHeaderPtr hdr);
46c446e575SDmitry Stogov static void delete_header_persistent(zval *zv);
47c446e575SDmitry Stogov static void delete_document(zval *zv);
4898ff80dbSDmitry Stogov 
get_encoder_from_prefix(sdlPtr sdl,xmlNodePtr node,const xmlChar * type)49ee1dc90dSDmitry Stogov encodePtr get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr node, const xmlChar *type)
50f8875adaSShane Caraveo {
51f8875adaSShane Caraveo 	encodePtr enc = NULL;
52b21756c1SDmitry Stogov 	xmlNsPtr nsptr;
53b21756c1SDmitry Stogov 	char *ns, *cptype;
54b21756c1SDmitry Stogov 
55b21756c1SDmitry Stogov 	parse_namespace(type, &cptype, &ns);
56ee1dc90dSDmitry Stogov 	nsptr = xmlSearchNs(node->doc, node, BAD_CAST(ns));
57b21756c1SDmitry Stogov 	if (nsptr != NULL) {
58ee1dc90dSDmitry Stogov 		enc = get_encoder(sdl, (char*)nsptr->href, cptype);
59b21756c1SDmitry Stogov 		if (enc == NULL) {
60b41a7ad1SDmitry Stogov 			enc = get_encoder_ex(sdl, cptype, strlen(cptype));
61b21756c1SDmitry Stogov 		}
62b21756c1SDmitry Stogov 	} else {
63ee1dc90dSDmitry Stogov 		enc = get_encoder_ex(sdl, (char*)type, xmlStrlen(type));
649a3cdc64SDmitry Stogov 	}
65b21756c1SDmitry Stogov 	efree(cptype);
66b21756c1SDmitry Stogov 	if (ns) {efree(ns);}
67f8875adaSShane Caraveo 	return enc;
68f8875adaSShane Caraveo }
69f8875adaSShane Caraveo 
get_element(sdlPtr sdl,xmlNodePtr node,const xmlChar * type)70ee1dc90dSDmitry Stogov static sdlTypePtr get_element(sdlPtr sdl, xmlNodePtr node, const xmlChar *type)
711dcf2467SDmitry Stogov {
722238e4b9SDmitry Stogov 	sdlTypePtr ret = NULL;
731dcf2467SDmitry Stogov 
7488c11689SDmitry Stogov 	if (sdl->elements) {
751dcf2467SDmitry Stogov 		xmlNsPtr nsptr;
761dcf2467SDmitry Stogov 		char *ns, *cptype;
77c446e575SDmitry Stogov 		sdlTypePtr sdl_type;
781dcf2467SDmitry Stogov 
791dcf2467SDmitry Stogov 		parse_namespace(type, &cptype, &ns);
80ee1dc90dSDmitry Stogov 		nsptr = xmlSearchNs(node->doc, node, BAD_CAST(ns));
811dcf2467SDmitry Stogov 		if (nsptr != NULL) {
82ee1dc90dSDmitry Stogov 			int ns_len = xmlStrlen(nsptr->href);
83b21756c1SDmitry Stogov 			int type_len = strlen(cptype);
84b21756c1SDmitry Stogov 			int len = ns_len + type_len + 1;
857f7f5663SIlia Alshanetsky 			char *nscat = emalloc(len + 1);
861dcf2467SDmitry Stogov 
87b21756c1SDmitry Stogov 			memcpy(nscat, nsptr->href, ns_len);
88b21756c1SDmitry Stogov 			nscat[ns_len] = ':';
89b21756c1SDmitry Stogov 			memcpy(nscat+ns_len+1, cptype, type_len);
90b21756c1SDmitry Stogov 			nscat[len] = '\0';
911dcf2467SDmitry Stogov 
92c446e575SDmitry Stogov 			if ((sdl_type = zend_hash_str_find_ptr(sdl->elements, nscat, len)) != NULL) {
93c446e575SDmitry Stogov 				ret = sdl_type;
94c446e575SDmitry Stogov 			} else if ((sdl_type = zend_hash_str_find_ptr(sdl->elements, (char*)type, type_len)) != NULL) {
95c446e575SDmitry Stogov 				ret = sdl_type;
961dcf2467SDmitry Stogov 			}
977f7f5663SIlia Alshanetsky 			efree(nscat);
981dcf2467SDmitry Stogov 		} else {
99c446e575SDmitry Stogov 			if ((sdl_type = zend_hash_str_find_ptr(sdl->elements, (char*)type, xmlStrlen(type))) != NULL) {
100c446e575SDmitry Stogov 				ret = sdl_type;
1011dcf2467SDmitry Stogov 			}
1021dcf2467SDmitry Stogov 		}
1031dcf2467SDmitry Stogov 
10459ab20b2SDmitry Stogov 		efree(cptype);
1051dcf2467SDmitry Stogov 		if (ns) {efree(ns);}
1061dcf2467SDmitry Stogov 	}
1072238e4b9SDmitry Stogov 	return ret;
1081dcf2467SDmitry Stogov }
1091dcf2467SDmitry Stogov 
get_encoder(sdlPtr sdl,const char * ns,const char * type)110de6184edSDmitry Stogov encodePtr get_encoder(sdlPtr sdl, const char *ns, const char *type)
111f8875adaSShane Caraveo {
112f8875adaSShane Caraveo 	encodePtr enc = NULL;
113f8875adaSShane Caraveo 	char *nscat;
114fd61666dSMatteo Beccati 	int ns_len = ns ? strlen(ns) : 0;
115b21756c1SDmitry Stogov 	int type_len = strlen(type);
116b21756c1SDmitry Stogov 	int len = ns_len + type_len + 1;
117f8875adaSShane Caraveo 
1187f7f5663SIlia Alshanetsky 	nscat = emalloc(len + 1);
119608097a9SNikita Popov 	if (ns) {
120608097a9SNikita Popov 		memcpy(nscat, ns, ns_len);
121608097a9SNikita Popov 	}
122b21756c1SDmitry Stogov 	nscat[ns_len] = ':';
123b21756c1SDmitry Stogov 	memcpy(nscat+ns_len+1, type, type_len);
124b21756c1SDmitry Stogov 	nscat[len] = '\0';
125f8875adaSShane Caraveo 
126b21756c1SDmitry Stogov 	enc = get_encoder_ex(sdl, nscat, len);
127b41a7ad1SDmitry Stogov 
128b41a7ad1SDmitry Stogov 	if (enc == NULL &&
129b41a7ad1SDmitry Stogov 	    ((ns_len == sizeof(SOAP_1_1_ENC_NAMESPACE)-1 &&
130b41a7ad1SDmitry Stogov 	      memcmp(ns, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)-1) == 0) ||
131b41a7ad1SDmitry Stogov 	     (ns_len == sizeof(SOAP_1_2_ENC_NAMESPACE)-1 &&
132b41a7ad1SDmitry Stogov 	      memcmp(ns, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)-1) == 0))) {
1338b4e1abdSDmitry Stogov 		char *enc_nscat;
1348b4e1abdSDmitry Stogov 		int enc_ns_len;
1358b4e1abdSDmitry Stogov 		int enc_len;
1368b4e1abdSDmitry Stogov 
1378b4e1abdSDmitry Stogov 		enc_ns_len = sizeof(XSD_NAMESPACE)-1;
1388b4e1abdSDmitry Stogov 		enc_len = enc_ns_len + type_len + 1;
1398b4e1abdSDmitry Stogov 		enc_nscat = emalloc(enc_len + 1);
1408b4e1abdSDmitry Stogov 		memcpy(enc_nscat, XSD_NAMESPACE, sizeof(XSD_NAMESPACE)-1);
1418b4e1abdSDmitry Stogov 		enc_nscat[enc_ns_len] = ':';
1428b4e1abdSDmitry Stogov 		memcpy(enc_nscat+enc_ns_len+1, type, type_len);
1438b4e1abdSDmitry Stogov 		enc_nscat[enc_len] = '\0';
1448b4e1abdSDmitry Stogov 
1458b4e1abdSDmitry Stogov 		enc = get_encoder_ex(NULL, enc_nscat, enc_len);
1468b4e1abdSDmitry Stogov 		efree(enc_nscat);
1478b4e1abdSDmitry Stogov 		if (enc && sdl) {
148349bcd74SDmitry Stogov 			encodePtr new_enc	= pemalloc(sizeof(encode), sdl->is_persistent);
1498b4e1abdSDmitry Stogov 			memcpy(new_enc, enc, sizeof(encode));
150349bcd74SDmitry Stogov 			if (sdl->is_persistent) {
151349bcd74SDmitry Stogov 				new_enc->details.ns = zend_strndup(ns, ns_len);
152349bcd74SDmitry Stogov 				new_enc->details.type_str = strdup(new_enc->details.type_str);
153349bcd74SDmitry Stogov 			} else {
154349bcd74SDmitry Stogov 				new_enc->details.ns = estrndup(ns, ns_len);
155349bcd74SDmitry Stogov 				new_enc->details.type_str = estrdup(new_enc->details.type_str);
156349bcd74SDmitry Stogov 			}
1578b4e1abdSDmitry Stogov 			if (sdl->encoders == NULL) {
158349bcd74SDmitry Stogov 				sdl->encoders = pemalloc(sizeof(HashTable), sdl->is_persistent);
159349bcd74SDmitry Stogov 				zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, sdl->is_persistent);
1608b4e1abdSDmitry Stogov 			}
161c446e575SDmitry Stogov 			zend_hash_str_update_ptr(sdl->encoders, nscat, len, new_enc);
1628b4e1abdSDmitry Stogov 			enc = new_enc;
1638b4e1abdSDmitry Stogov 		}
164b41a7ad1SDmitry Stogov 	}
1658b4e1abdSDmitry Stogov 	efree(nscat);
166f8875adaSShane Caraveo 	return enc;
167f8875adaSShane Caraveo }
168f8875adaSShane Caraveo 
get_encoder_ex(sdlPtr sdl,const char * nscat,int len)169b21756c1SDmitry Stogov encodePtr get_encoder_ex(sdlPtr sdl, const char *nscat, int len)
170f8875adaSShane Caraveo {
171c446e575SDmitry Stogov 	encodePtr enc;
172f8875adaSShane Caraveo 
173c446e575SDmitry Stogov 	if ((enc = zend_hash_str_find_ptr(&SOAP_GLOBAL(defEnc), (char*)nscat, len)) != NULL) {
174c446e575SDmitry Stogov 		return enc;
175c446e575SDmitry Stogov 	} else if (sdl && sdl->encoders && (enc = zend_hash_str_find_ptr(sdl->encoders, (char*)nscat, len)) != NULL) {
176c446e575SDmitry Stogov 		return enc;
1779a3cdc64SDmitry Stogov 	}
178b21756c1SDmitry Stogov 	return NULL;
179f8875adaSShane Caraveo }
180f8875adaSShane Caraveo 
get_binding_from_type(sdlPtr sdl,sdlBindingType type)181adc95c51SDmitry Stogov sdlBindingPtr get_binding_from_type(sdlPtr sdl, sdlBindingType type)
182a8326d6fSBrad LaFountain {
183c446e575SDmitry Stogov 	sdlBindingPtr binding;
184a8326d6fSBrad LaFountain 
1858e5aaa0eSWez Furlong 	if (sdl == NULL) {
1868e5aaa0eSWez Furlong 		return NULL;
1878e5aaa0eSWez Furlong 	}
188de6184edSDmitry Stogov 
189c446e575SDmitry Stogov 	ZEND_HASH_FOREACH_PTR(sdl->bindings, binding) {
190c446e575SDmitry Stogov 		if (binding->bindingType == type) {
191c446e575SDmitry Stogov 			return binding;
1929a3cdc64SDmitry Stogov 		}
193c446e575SDmitry Stogov 	} ZEND_HASH_FOREACH_END();
194a8326d6fSBrad LaFountain 	return NULL;
195a8326d6fSBrad LaFountain }
196a8326d6fSBrad LaFountain 
get_binding_from_name(sdlPtr sdl,char * name,char * ns)197a8326d6fSBrad LaFountain sdlBindingPtr get_binding_from_name(sdlPtr sdl, char *name, char *ns)
198a8326d6fSBrad LaFountain {
199c446e575SDmitry Stogov 	sdlBindingPtr binding;
200a8326d6fSBrad LaFountain 	smart_str key = {0};
201a8326d6fSBrad LaFountain 
202a8326d6fSBrad LaFountain 	smart_str_appends(&key, ns);
203a8326d6fSBrad LaFountain 	smart_str_appendc(&key, ':');
204a8326d6fSBrad LaFountain 	smart_str_appends(&key, name);
2059f8d30f2SDmitry Stogov 	smart_str_0(&key);
206a8326d6fSBrad LaFountain 
207c446e575SDmitry Stogov 	binding = zend_hash_find_ptr(sdl->bindings, key.s);
208a8326d6fSBrad LaFountain 
209a8326d6fSBrad LaFountain 	smart_str_free(&key);
210a8326d6fSBrad LaFountain 	return binding;
211a8326d6fSBrad LaFountain }
212a8326d6fSBrad LaFountain 
is_wsdl_element(xmlNodePtr node)213563e769dSDmitry Stogov static int is_wsdl_element(xmlNodePtr node)
214563e769dSDmitry Stogov {
215ee1dc90dSDmitry Stogov 	if (node->ns && strcmp((char*)node->ns->href, WSDL_NAMESPACE) != 0) {
216563e769dSDmitry Stogov 		xmlAttrPtr attr;
217563e769dSDmitry Stogov 		if ((attr = get_attribute_ex(node->properties, "required", WSDL_NAMESPACE)) != NULL &&
218563e769dSDmitry Stogov 		     attr->children && attr->children->content &&
219ee1dc90dSDmitry Stogov 		     (strcmp((char*)attr->children->content, "1") == 0 ||
220ee1dc90dSDmitry Stogov 		      strcmp((char*)attr->children->content, "true") == 0)) {
2217bddbd7bSDmitry Stogov 			soap_error1(E_ERROR, "Parsing WSDL: Unknown required WSDL extension '%s'", node->ns->href);
222563e769dSDmitry Stogov 		}
223563e769dSDmitry Stogov 		return 0;
224563e769dSDmitry Stogov 	}
225563e769dSDmitry Stogov 	return 1;
226563e769dSDmitry Stogov }
227563e769dSDmitry Stogov 
sdl_set_uri_credentials(sdlCtx * ctx,char * uri)228bdeb220fSAnatol Belski void sdl_set_uri_credentials(sdlCtx *ctx, char *uri)
229b06436f1SDmitry Stogov {
230b06436f1SDmitry Stogov 	char *s;
231adc95c51SDmitry Stogov 	size_t l1, l2;
232c446e575SDmitry Stogov 	zval context;
233c446e575SDmitry Stogov 	zval *header = NULL;
234b06436f1SDmitry Stogov 
235b06436f1SDmitry Stogov 	/* check if we load xsd from the same server */
236b06436f1SDmitry Stogov 	s = strstr(ctx->sdl->source, "://");
237b06436f1SDmitry Stogov 	if (!s) return;
238b06436f1SDmitry Stogov 	s = strchr(s+3, '/');
239adc95c51SDmitry Stogov 	l1 = s ? (size_t)(s - ctx->sdl->source) : strlen(ctx->sdl->source);
240b06436f1SDmitry Stogov 	s = strstr((char*)uri, "://");
241b06436f1SDmitry Stogov 	if (!s) return;
242b06436f1SDmitry Stogov 	s = strchr(s+3, '/');
243adc95c51SDmitry Stogov 	l2 = s ? (size_t)(s - (char*)uri) : strlen((char*)uri);
244dc7c5ebaSDmitry Stogov 	if (l1 != l2) {
245dc7c5ebaSDmitry Stogov 		/* check for http://...:80/ */
246dc7c5ebaSDmitry Stogov 		if (l1 > 11 &&
247dc7c5ebaSDmitry Stogov 		    ctx->sdl->source[4] == ':' &&
248dc7c5ebaSDmitry Stogov 		    ctx->sdl->source[l1-3] == ':' &&
249dc7c5ebaSDmitry Stogov 		    ctx->sdl->source[l1-2] == '8' &&
250dc7c5ebaSDmitry Stogov 		    ctx->sdl->source[l1-1] == '0') {
251dc7c5ebaSDmitry Stogov 			l1 -= 3;
252dc7c5ebaSDmitry Stogov 		}
253dc7c5ebaSDmitry Stogov 		if (l2 > 11 &&
254dc7c5ebaSDmitry Stogov 		    uri[4] == ':' &&
255dc7c5ebaSDmitry Stogov 		    uri[l2-3] == ':' &&
256dc7c5ebaSDmitry Stogov 		    uri[l2-2] == '8' &&
257dc7c5ebaSDmitry Stogov 		    uri[l2-1] == '0') {
258dc7c5ebaSDmitry Stogov 			l2 -= 3;
259dc7c5ebaSDmitry Stogov 		}
260dc7c5ebaSDmitry Stogov 		/* check for https://...:443/ */
261dc7c5ebaSDmitry Stogov 		if (l1 > 13 &&
262dc7c5ebaSDmitry Stogov 		    ctx->sdl->source[4] == 's' &&
263dc7c5ebaSDmitry Stogov 		    ctx->sdl->source[l1-4] == ':' &&
264dc7c5ebaSDmitry Stogov 		    ctx->sdl->source[l1-3] == '4' &&
265dc7c5ebaSDmitry Stogov 		    ctx->sdl->source[l1-2] == '4' &&
266dc7c5ebaSDmitry Stogov 		    ctx->sdl->source[l1-1] == '3') {
267dc7c5ebaSDmitry Stogov 			l1 -= 4;
268dc7c5ebaSDmitry Stogov 		}
269dc7c5ebaSDmitry Stogov 		if (l2 > 13 &&
270dc7c5ebaSDmitry Stogov 		    uri[4] == 's' &&
271dc7c5ebaSDmitry Stogov 		    uri[l2-4] == ':' &&
272dc7c5ebaSDmitry Stogov 		    uri[l2-3] == '4' &&
273dc7c5ebaSDmitry Stogov 		    uri[l2-2] == '4' &&
274dc7c5ebaSDmitry Stogov 		    uri[l2-1] == '3') {
275dc7c5ebaSDmitry Stogov 			l2 -= 4;
276dc7c5ebaSDmitry Stogov 		}
277dc7c5ebaSDmitry Stogov 	}
278b06436f1SDmitry Stogov 	if (l1 != l2 || memcmp(ctx->sdl->source, uri, l1) != 0) {
279b06436f1SDmitry Stogov 		/* another server. clear authentication credentals */
280bdeb220fSAnatol Belski 		php_libxml_switch_context(NULL, &context);
281bdeb220fSAnatol Belski 		php_libxml_switch_context(&context, NULL);
282c446e575SDmitry Stogov 		if (Z_TYPE(context) != IS_UNDEF) {
283c446e575SDmitry Stogov 			zval *context_ptr = &context;
284c446e575SDmitry Stogov 			ctx->context = php_stream_context_from_zval(context_ptr, 1);
285b06436f1SDmitry Stogov 
286b06436f1SDmitry Stogov 			if (ctx->context &&
287c446e575SDmitry Stogov 			    (header = php_stream_context_get_option(ctx->context, "http", "header")) != NULL) {
288c446e575SDmitry Stogov 				s = strstr(Z_STRVAL_P(header), "Authorization: Basic");
289c446e575SDmitry Stogov 				if (s && (s == Z_STRVAL_P(header) || *(s-1) == '\n' || *(s-1) == '\r')) {
290b06436f1SDmitry Stogov 					char *rest = strstr(s, "\r\n");
291b06436f1SDmitry Stogov 					if (rest) {
292b06436f1SDmitry Stogov 						zval new_header;
293b7a7b1a6SStanislav Malyshev 
294b06436f1SDmitry Stogov 						rest += 2;
2953bc8a958SDmitry Stogov 						ZVAL_NEW_STR(&new_header, zend_string_alloc(Z_STRLEN_P(header) - (rest - s), 0));
296c446e575SDmitry Stogov 						memcpy(Z_STRVAL(new_header), Z_STRVAL_P(header), s - Z_STRVAL_P(header));
297c3e3c98eSAnatol Belski 						memcpy(Z_STRVAL(new_header) + (s - Z_STRVAL_P(header)), rest, Z_STRLEN_P(header) - (rest - Z_STRVAL_P(header)) + 1);
298c446e575SDmitry Stogov 						ZVAL_COPY(&ctx->old_header, header);
299b06436f1SDmitry Stogov 						php_stream_context_set_option(ctx->context, "http", "header", &new_header);
300c67fc6bbSDmitry Stogov 						zval_ptr_dtor(&new_header);
301b06436f1SDmitry Stogov 					}
302b06436f1SDmitry Stogov 				}
303b06436f1SDmitry Stogov 			}
304b06436f1SDmitry Stogov 		}
305b06436f1SDmitry Stogov 	}
306b06436f1SDmitry Stogov }
307b06436f1SDmitry Stogov 
sdl_restore_uri_credentials(sdlCtx * ctx)308bdeb220fSAnatol Belski void sdl_restore_uri_credentials(sdlCtx *ctx)
309b06436f1SDmitry Stogov {
310c446e575SDmitry Stogov 	if (Z_TYPE(ctx->old_header) != IS_UNDEF) {
311c446e575SDmitry Stogov 	    php_stream_context_set_option(ctx->context, "http", "header", &ctx->old_header);
312b06436f1SDmitry Stogov 	    zval_ptr_dtor(&ctx->old_header);
313c446e575SDmitry Stogov 		ZVAL_UNDEF(&ctx->old_header);
314b06436f1SDmitry Stogov 	}
315b06436f1SDmitry Stogov 	ctx->context = NULL;
316b06436f1SDmitry Stogov }
317b06436f1SDmitry Stogov 
318ab8177deSNikita Popov #define SAFE_STR(a) ((a)?((const char *)a):"")
3193c939e3fSStanislav Malyshev 
load_wsdl_ex(zval * this_ptr,char * struri,sdlCtx * ctx,int include)320bdeb220fSAnatol Belski static void load_wsdl_ex(zval *this_ptr, char *struri, sdlCtx *ctx, int include)
321f8875adaSShane Caraveo {
32288c11689SDmitry Stogov 	sdlPtr tmpsdl = ctx->sdl;
323f8875adaSShane Caraveo 	xmlDocPtr wsdl;
32429fe4588SDmitry Stogov 	xmlNodePtr root, definitions, trav;
325f8875adaSShane Caraveo 	xmlAttrPtr targetNamespace;
326f8875adaSShane Caraveo 
327c446e575SDmitry Stogov 	if (zend_hash_str_exists(&ctx->docs, struri, strlen(struri))) {
328b21756c1SDmitry Stogov 		return;
3292a5593ddSDmitry Stogov 	}
330b7a7b1a6SStanislav Malyshev 
331bdeb220fSAnatol Belski 	sdl_set_uri_credentials(ctx, struri);
332bdeb220fSAnatol Belski 	wsdl = soap_xmlParseFile(struri);
333bdeb220fSAnatol Belski 	sdl_restore_uri_credentials(ctx);
334b7a7b1a6SStanislav Malyshev 
3359a3cdc64SDmitry Stogov 	if (!wsdl) {
336c5b386b8SDavid Coallier 		xmlErrorPtr xmlErrorPtr = xmlGetLastError();
337c5b386b8SDavid Coallier 
338c5b386b8SDavid Coallier 		if (xmlErrorPtr) {
339c5b386b8SDavid Coallier 			soap_error2(E_ERROR, "Parsing WSDL: Couldn't load from '%s' : %s", struri, xmlErrorPtr->message);
340c5b386b8SDavid Coallier 		} else {
341c5b386b8SDavid Coallier 			soap_error1(E_ERROR, "Parsing WSDL: Couldn't load from '%s'", struri);
342c5b386b8SDavid Coallier 		}
3439a3cdc64SDmitry Stogov 	}
344f8875adaSShane Caraveo 
345c446e575SDmitry Stogov 	zend_hash_str_add_ptr(&ctx->docs, struri, strlen(struri), wsdl);
34629fe4588SDmitry Stogov 
347f8875adaSShane Caraveo 	root = wsdl->children;
348563e769dSDmitry Stogov 	definitions = get_node_ex(root, "definitions", WSDL_NAMESPACE);
3499a3cdc64SDmitry Stogov 	if (!definitions) {
3506b32938bSDmitry Stogov 		if (include) {
351563e769dSDmitry Stogov 			xmlNodePtr schema = get_node_ex(root, "schema", XSD_NAMESPACE);
3526b32938bSDmitry Stogov 			if (schema) {
353bdeb220fSAnatol Belski 				load_schema(ctx, schema);
3546b32938bSDmitry Stogov 				return;
3556b32938bSDmitry Stogov 			}
3566b32938bSDmitry Stogov 		}
3577bddbd7bSDmitry Stogov 		soap_error1(E_ERROR, "Parsing WSDL: Couldn't find <definitions> in '%s'", struri);
3589a3cdc64SDmitry Stogov 	}
359f8875adaSShane Caraveo 
36098ff80dbSDmitry Stogov 	if (!include) {
36198ff80dbSDmitry Stogov 		targetNamespace = get_attribute(definitions->properties, "targetNamespace");
36298ff80dbSDmitry Stogov 		if (targetNamespace) {
363ee1dc90dSDmitry Stogov 			tmpsdl->target_ns = estrdup((char*)targetNamespace->children->content);
36498ff80dbSDmitry Stogov 		}
3659a3cdc64SDmitry Stogov 	}
366f8875adaSShane Caraveo 
367a8326d6fSBrad LaFountain 	trav = definitions->children;
36829fe4588SDmitry Stogov 	while (trav != NULL) {
369563e769dSDmitry Stogov 		if (!is_wsdl_element(trav)) {
370563e769dSDmitry Stogov 			trav = trav->next;
371563e769dSDmitry Stogov 			continue;
372563e769dSDmitry Stogov 		}
3732c1dcf32SDmitry Stogov 		if (node_is_equal(trav,"types")) {
3742c1dcf32SDmitry Stogov 			/* TODO: Only one "types" is allowed */
3752c1dcf32SDmitry Stogov 			xmlNodePtr trav2 = trav->children;
376f8875adaSShane Caraveo 
377563e769dSDmitry Stogov 			while (trav2 != NULL) {
378563e769dSDmitry Stogov 				if (node_is_equal_ex(trav2, "schema", XSD_NAMESPACE)) {
379bdeb220fSAnatol Belski 					load_schema(ctx, trav2);
380563e769dSDmitry Stogov 				} else if (is_wsdl_element(trav2) && !node_is_equal(trav2,"documentation")) {
3813c939e3fSStanislav Malyshev 					soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav2->name));
382563e769dSDmitry Stogov 				}
383563e769dSDmitry Stogov 				trav2 = trav2->next;
3842c1dcf32SDmitry Stogov 			}
3852c1dcf32SDmitry Stogov 		} else if (node_is_equal(trav,"import")) {
3862c1dcf32SDmitry Stogov 			/* TODO: namespace ??? */
3872c1dcf32SDmitry Stogov 			xmlAttrPtr tmp = get_attribute(trav->properties, "location");
3882c1dcf32SDmitry Stogov 			if (tmp) {
389b21756c1SDmitry Stogov 				xmlChar *uri;
3902c1dcf32SDmitry Stogov 				xmlChar *base = xmlNodeGetBase(trav->doc, trav);
391f8875adaSShane Caraveo 
3922c1dcf32SDmitry Stogov 				if (base == NULL) {
393b21756c1SDmitry Stogov 					uri = xmlBuildURI(tmp->children->content, trav->doc->URL);
39429fe4588SDmitry Stogov 				} else {
395b21756c1SDmitry Stogov 					uri = xmlBuildURI(tmp->children->content, base);
396b21756c1SDmitry Stogov 					xmlFree(base);
39729fe4588SDmitry Stogov 				}
398bdeb220fSAnatol Belski 				load_wsdl_ex(this_ptr, (char*)uri, ctx, 1);
399b21756c1SDmitry Stogov 				xmlFree(uri);
4002c1dcf32SDmitry Stogov 			}
401f8875adaSShane Caraveo 
4022c1dcf32SDmitry Stogov 		} else if (node_is_equal(trav,"message")) {
4032c1dcf32SDmitry Stogov 			xmlAttrPtr name = get_attribute(trav->properties, "name");
4042c1dcf32SDmitry Stogov 			if (name && name->children && name->children->content) {
405c446e575SDmitry Stogov 				if (zend_hash_str_add_ptr(&ctx->messages, (char*)name->children->content, xmlStrlen(name->children->content), trav) == NULL) {
4067bddbd7bSDmitry Stogov 					soap_error1(E_ERROR, "Parsing WSDL: <message> '%s' already defined", name->children->content);
40729fe4588SDmitry Stogov 				}
4082c1dcf32SDmitry Stogov 			} else {
4098790a491SRasmus Lerdorf 				soap_error0(E_ERROR, "Parsing WSDL: <message> has no name attribute");
4102c1dcf32SDmitry Stogov 			}
411a8326d6fSBrad LaFountain 
4122c1dcf32SDmitry Stogov 		} else if (node_is_equal(trav,"portType")) {
4132c1dcf32SDmitry Stogov 			xmlAttrPtr name = get_attribute(trav->properties, "name");
4142c1dcf32SDmitry Stogov 			if (name && name->children && name->children->content) {
415c446e575SDmitry Stogov 				if (zend_hash_str_add_ptr(&ctx->portTypes, (char*)name->children->content, xmlStrlen(name->children->content), trav) == NULL) {
4167bddbd7bSDmitry Stogov 					soap_error1(E_ERROR, "Parsing WSDL: <portType> '%s' already defined", name->children->content);
41729fe4588SDmitry Stogov 				}
4182c1dcf32SDmitry Stogov 			} else {
4198790a491SRasmus Lerdorf 				soap_error0(E_ERROR, "Parsing WSDL: <portType> has no name attribute");
4202c1dcf32SDmitry Stogov 			}
421f8875adaSShane Caraveo 
4222c1dcf32SDmitry Stogov 		} else if (node_is_equal(trav,"binding")) {
4232c1dcf32SDmitry Stogov 			xmlAttrPtr name = get_attribute(trav->properties, "name");
4242c1dcf32SDmitry Stogov 			if (name && name->children && name->children->content) {
425c446e575SDmitry Stogov 				if (zend_hash_str_add_ptr(&ctx->bindings, (char*)name->children->content, xmlStrlen(name->children->content), trav) == NULL) {
4267bddbd7bSDmitry Stogov 					soap_error1(E_ERROR, "Parsing WSDL: <binding> '%s' already defined", name->children->content);
42729fe4588SDmitry Stogov 				}
4282c1dcf32SDmitry Stogov 			} else {
4298790a491SRasmus Lerdorf 				soap_error0(E_ERROR, "Parsing WSDL: <binding> has no name attribute");
4302c1dcf32SDmitry Stogov 			}
431f8875adaSShane Caraveo 
4322c1dcf32SDmitry Stogov 		} else if (node_is_equal(trav,"service")) {
4332c1dcf32SDmitry Stogov 			xmlAttrPtr name = get_attribute(trav->properties, "name");
4342c1dcf32SDmitry Stogov 			if (name && name->children && name->children->content) {
435c446e575SDmitry Stogov 				if (zend_hash_str_add_ptr(&ctx->services, (char*)name->children->content, xmlStrlen(name->children->content), trav) == NULL) {
4367bddbd7bSDmitry Stogov 					soap_error1(E_ERROR, "Parsing WSDL: <service> '%s' already defined", name->children->content);
4372c1dcf32SDmitry Stogov 				}
43829fe4588SDmitry Stogov 			} else {
4398790a491SRasmus Lerdorf 				soap_error0(E_ERROR, "Parsing WSDL: <service> has no name attribute");
4409a3cdc64SDmitry Stogov 			}
441563e769dSDmitry Stogov 		} else if (!node_is_equal(trav,"documentation")) {
4423c939e3fSStanislav Malyshev 			soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>",  SAFE_STR(trav->name));
44329fe4588SDmitry Stogov 		}
44429fe4588SDmitry Stogov 		trav = trav->next;
44529fe4588SDmitry Stogov 	}
44629fe4588SDmitry Stogov }
447f8875adaSShane Caraveo 
wsdl_soap_binding_header(sdlCtx * ctx,xmlNodePtr header,char * wsdl_soap_namespace,int fault)4480b0eb80fSDmitry Stogov static sdlSoapBindingFunctionHeaderPtr wsdl_soap_binding_header(sdlCtx* ctx, xmlNodePtr header, char* wsdl_soap_namespace, int fault)
4490b0eb80fSDmitry Stogov {
4500b0eb80fSDmitry Stogov 	xmlAttrPtr tmp;
45140a81569SDmitry Stogov 	xmlNodePtr message, part;
4520b0eb80fSDmitry Stogov 	char *ctype;
4530b0eb80fSDmitry Stogov 	sdlSoapBindingFunctionHeaderPtr h;
4540b0eb80fSDmitry Stogov 
4550b0eb80fSDmitry Stogov 	tmp = get_attribute(header->properties, "message");
4560b0eb80fSDmitry Stogov 	if (!tmp) {
4577bddbd7bSDmitry Stogov 		soap_error0(E_ERROR, "Parsing WSDL: Missing message attribute for <header>");
4580b0eb80fSDmitry Stogov 	}
4590b0eb80fSDmitry Stogov 
460ee1dc90dSDmitry Stogov 	ctype = strrchr((char*)tmp->children->content,':');
4610b0eb80fSDmitry Stogov 	if (ctype == NULL) {
462ee1dc90dSDmitry Stogov 		ctype = (char*)tmp->children->content;
4630b0eb80fSDmitry Stogov 	} else {
4640b0eb80fSDmitry Stogov 		++ctype;
4650b0eb80fSDmitry Stogov 	}
466c446e575SDmitry Stogov 	if ((message = zend_hash_str_find_ptr(&ctx->messages, ctype, strlen(ctype))) == NULL) {
4677bddbd7bSDmitry Stogov 		soap_error1(E_ERROR, "Parsing WSDL: Missing <message> with name '%s'", tmp->children->content);
4680b0eb80fSDmitry Stogov 	}
4690b0eb80fSDmitry Stogov 
4700b0eb80fSDmitry Stogov 	tmp = get_attribute(header->properties, "part");
4710b0eb80fSDmitry Stogov 	if (!tmp) {
4727bddbd7bSDmitry Stogov 		soap_error0(E_ERROR, "Parsing WSDL: Missing part attribute for <header>");
4730b0eb80fSDmitry Stogov 	}
47440a81569SDmitry Stogov 	part = get_node_with_attribute_ex(message->children, "part", WSDL_NAMESPACE, "name", (char*)tmp->children->content, NULL);
4750b0eb80fSDmitry Stogov 	if (!part) {
4767bddbd7bSDmitry Stogov 		soap_error1(E_ERROR, "Parsing WSDL: Missing part '%s' in <message>", tmp->children->content);
4770b0eb80fSDmitry Stogov 	}
4780b0eb80fSDmitry Stogov 
4790b0eb80fSDmitry Stogov 	h = emalloc(sizeof(sdlSoapBindingFunctionHeader));
4800b0eb80fSDmitry Stogov 	memset(h, 0, sizeof(sdlSoapBindingFunctionHeader));
481ee1dc90dSDmitry Stogov 	h->name = estrdup((char*)tmp->children->content);
4820b0eb80fSDmitry Stogov 
4830b0eb80fSDmitry Stogov 	tmp = get_attribute(header->properties, "use");
484ee1dc90dSDmitry Stogov 	if (tmp && !strncmp((char*)tmp->children->content, "encoded", sizeof("encoded"))) {
4850b0eb80fSDmitry Stogov 		h->use = SOAP_ENCODED;
4860b0eb80fSDmitry Stogov 	} else {
4870b0eb80fSDmitry Stogov 		h->use = SOAP_LITERAL;
4880b0eb80fSDmitry Stogov 	}
4890b0eb80fSDmitry Stogov 
4900b0eb80fSDmitry Stogov 	tmp = get_attribute(header->properties, "namespace");
4910b0eb80fSDmitry Stogov 	if (tmp) {
492ee1dc90dSDmitry Stogov 		h->ns = estrdup((char*)tmp->children->content);
4930b0eb80fSDmitry Stogov 	}
4940b0eb80fSDmitry Stogov 
4950b0eb80fSDmitry Stogov 	if (h->use == SOAP_ENCODED) {
4960b0eb80fSDmitry Stogov 		tmp = get_attribute(header->properties, "encodingStyle");
4970b0eb80fSDmitry Stogov 		if (tmp) {
498ee1dc90dSDmitry Stogov 			if (strncmp((char*)tmp->children->content, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) {
4990b0eb80fSDmitry Stogov 				h->encodingStyle = SOAP_ENCODING_1_1;
500ee1dc90dSDmitry Stogov 			} else if (strncmp((char*)tmp->children->content, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) {
5010b0eb80fSDmitry Stogov 				h->encodingStyle = SOAP_ENCODING_1_2;
5020b0eb80fSDmitry Stogov 			} else {
5037bddbd7bSDmitry Stogov 				soap_error1(E_ERROR, "Parsing WSDL: Unknown encodingStyle '%s'", tmp->children->content);
5040b0eb80fSDmitry Stogov 			}
5050b0eb80fSDmitry Stogov 		} else {
5067bddbd7bSDmitry Stogov 			soap_error0(E_ERROR, "Parsing WSDL: Unspecified encodingStyle");
5070b0eb80fSDmitry Stogov 		}
5080b0eb80fSDmitry Stogov 	}
5090b0eb80fSDmitry Stogov 
5100b0eb80fSDmitry Stogov 	tmp = get_attribute(part->properties, "type");
5110b0eb80fSDmitry Stogov 	if (tmp != NULL) {
5120b0eb80fSDmitry Stogov 		h->encode = get_encoder_from_prefix(ctx->sdl, part, tmp->children->content);
5130b0eb80fSDmitry Stogov 	} else {
5140b0eb80fSDmitry Stogov 		tmp = get_attribute(part->properties, "element");
5150b0eb80fSDmitry Stogov 		if (tmp != NULL) {
5160b0eb80fSDmitry Stogov 			h->element = get_element(ctx->sdl, part, tmp->children->content);
5170b0eb80fSDmitry Stogov 			if (h->element) {
5180b0eb80fSDmitry Stogov 				h->encode = h->element->encode;
5190b0eb80fSDmitry Stogov 				if (!h->ns && h->element->namens) {
5200b0eb80fSDmitry Stogov 					h->ns = estrdup(h->element->namens);
5210b0eb80fSDmitry Stogov 				}
522eef44c60SDmitry Stogov 				if (h->element->name) {
523eef44c60SDmitry Stogov 					efree(h->name);
524eef44c60SDmitry Stogov 					h->name = estrdup(h->element->name);
525eef44c60SDmitry Stogov 				}
5268dff9911SDmitry Stogov 			}
5270b0eb80fSDmitry Stogov 		}
5280b0eb80fSDmitry Stogov 	}
5290b0eb80fSDmitry Stogov 	if (!fault) {
5300b0eb80fSDmitry Stogov 		xmlNodePtr trav = header->children;
5310b0eb80fSDmitry Stogov 		while (trav != NULL) {
5320b0eb80fSDmitry Stogov 			if (node_is_equal_ex(trav, "headerfault", wsdl_soap_namespace)) {
5330b0eb80fSDmitry Stogov 				sdlSoapBindingFunctionHeaderPtr hf = wsdl_soap_binding_header(ctx, trav, wsdl_soap_namespace, 1);
5340b0eb80fSDmitry Stogov 				smart_str key = {0};
5350b0eb80fSDmitry Stogov 
5360b0eb80fSDmitry Stogov 				if (h->headerfaults == NULL) {
5370b0eb80fSDmitry Stogov 					h->headerfaults = emalloc(sizeof(HashTable));
5380b0eb80fSDmitry Stogov 					zend_hash_init(h->headerfaults, 0, NULL, delete_header, 0);
5390b0eb80fSDmitry Stogov 				}
5400b0eb80fSDmitry Stogov 
5410b0eb80fSDmitry Stogov 				if (hf->ns) {
5420b0eb80fSDmitry Stogov 					smart_str_appends(&key,hf->ns);
5430b0eb80fSDmitry Stogov 					smart_str_appendc(&key,':');
5440b0eb80fSDmitry Stogov 				}
5450b0eb80fSDmitry Stogov 				smart_str_appends(&key,hf->name);
5460b0eb80fSDmitry Stogov 				smart_str_0(&key);
547c446e575SDmitry Stogov 				if (zend_hash_add_ptr(h->headerfaults, key.s, hf) == NULL) {
548c446e575SDmitry Stogov 					delete_header_int(hf);
5490b0eb80fSDmitry Stogov 				}
5500b0eb80fSDmitry Stogov 				smart_str_free(&key);
5510b0eb80fSDmitry Stogov 			} else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
5523c939e3fSStanislav Malyshev 				soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>",  SAFE_STR(trav->name));
5530b0eb80fSDmitry Stogov 			}
5540b0eb80fSDmitry Stogov 			trav = trav->next;
5550b0eb80fSDmitry Stogov 		}
5560b0eb80fSDmitry Stogov 	}
5570b0eb80fSDmitry Stogov 	return h;
5580b0eb80fSDmitry Stogov }
5590b0eb80fSDmitry Stogov 
wsdl_soap_binding_body(sdlCtx * ctx,xmlNodePtr node,char * wsdl_soap_namespace,sdlSoapBindingFunctionBody * binding,HashTable * params)560563e769dSDmitry Stogov static void wsdl_soap_binding_body(sdlCtx* ctx, xmlNodePtr node, char* wsdl_soap_namespace, sdlSoapBindingFunctionBody *binding, HashTable* params)
5619fa7d1c2SDmitry Stogov {
5620b0eb80fSDmitry Stogov 	xmlNodePtr body, trav;
5639fa7d1c2SDmitry Stogov 	xmlAttrPtr tmp;
5649fa7d1c2SDmitry Stogov 
565563e769dSDmitry Stogov 	trav = node->children;
566563e769dSDmitry Stogov 	while (trav != NULL) {
567563e769dSDmitry Stogov 		if (node_is_equal_ex(trav, "body", wsdl_soap_namespace)) {
568563e769dSDmitry Stogov 			body = trav;
5699fa7d1c2SDmitry Stogov 
570563e769dSDmitry Stogov 			tmp = get_attribute(body->properties, "use");
571ee1dc90dSDmitry Stogov 			if (tmp && !strncmp((char*)tmp->children->content, "literal", sizeof("literal"))) {
572563e769dSDmitry Stogov 				binding->use = SOAP_LITERAL;
573563e769dSDmitry Stogov 			} else {
574563e769dSDmitry Stogov 				binding->use = SOAP_ENCODED;
575563e769dSDmitry Stogov 			}
5769fa7d1c2SDmitry Stogov 
577563e769dSDmitry Stogov 			tmp = get_attribute(body->properties, "namespace");
578563e769dSDmitry Stogov 			if (tmp) {
579ee1dc90dSDmitry Stogov 				binding->ns = estrdup((char*)tmp->children->content);
580563e769dSDmitry Stogov 			}
5819fa7d1c2SDmitry Stogov 
582563e769dSDmitry Stogov 			tmp = get_attribute(body->properties, "parts");
583563e769dSDmitry Stogov 			if (tmp) {
584756c5784SDmitry Stogov 				HashTable    ht;
585ee1dc90dSDmitry Stogov 				char *parts = (char*)tmp->children->content;
586756c5784SDmitry Stogov 
587756c5784SDmitry Stogov 				/* Delete all parts those are not in the "parts" attribute */
588756c5784SDmitry Stogov 				zend_hash_init(&ht, 0, NULL, delete_parameter, 0);
589756c5784SDmitry Stogov 				while (*parts) {
590c446e575SDmitry Stogov 					sdlParamPtr param;
591756c5784SDmitry Stogov 					int found = 0;
592756c5784SDmitry Stogov 					char *end;
593756c5784SDmitry Stogov 
594756c5784SDmitry Stogov 					while (*parts == ' ') ++parts;
595756c5784SDmitry Stogov 					if (*parts == '\0') break;
596756c5784SDmitry Stogov 					end = strchr(parts, ' ');
597756c5784SDmitry Stogov 					if (end) *end = '\0';
598c446e575SDmitry Stogov 					ZEND_HASH_FOREACH_PTR(params, param) {
599c446e575SDmitry Stogov 						if (param->paramName &&
600c446e575SDmitry Stogov 						    strcmp(parts, param->paramName) == 0) {
601756c5784SDmitry Stogov 					  	sdlParamPtr x_param;
602756c5784SDmitry Stogov 					  	x_param = emalloc(sizeof(sdlParam));
603c446e575SDmitry Stogov 					  	*x_param = *param;
604c446e575SDmitry Stogov 					  	param->paramName = NULL;
605c446e575SDmitry Stogov 					  	zend_hash_next_index_insert_ptr(&ht, x_param);
606756c5784SDmitry Stogov 					  	found = 1;
607756c5784SDmitry Stogov 					  	break;
608756c5784SDmitry Stogov 						}
609c446e575SDmitry Stogov 					} ZEND_HASH_FOREACH_END();
610756c5784SDmitry Stogov 					if (!found) {
611756c5784SDmitry Stogov 						soap_error1(E_ERROR, "Parsing WSDL: Missing part '%s' in <message>", parts);
612756c5784SDmitry Stogov 					}
613756c5784SDmitry Stogov 					parts += strlen(parts);
614756c5784SDmitry Stogov 					if (end) *end = ' ';
615756c5784SDmitry Stogov 				}
616756c5784SDmitry Stogov 				zend_hash_destroy(params);
617756c5784SDmitry Stogov 				*params = ht;
6189fa7d1c2SDmitry Stogov 			}
6199fa7d1c2SDmitry Stogov 
620563e769dSDmitry Stogov 			if (binding->use == SOAP_ENCODED) {
621563e769dSDmitry Stogov 				tmp = get_attribute(body->properties, "encodingStyle");
62215ccb3beSDmitry Stogov 				if (tmp) {
623ee1dc90dSDmitry Stogov 					if (strncmp((char*)tmp->children->content, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) {
62415ccb3beSDmitry Stogov 						binding->encodingStyle = SOAP_ENCODING_1_1;
625ee1dc90dSDmitry Stogov 					} else if (strncmp((char*)tmp->children->content, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) {
62615ccb3beSDmitry Stogov 						binding->encodingStyle = SOAP_ENCODING_1_2;
62715ccb3beSDmitry Stogov 					} else {
6287bddbd7bSDmitry Stogov 						soap_error1(E_ERROR, "Parsing WSDL: Unknown encodingStyle '%s'", tmp->children->content);
62915ccb3beSDmitry Stogov 					}
630563e769dSDmitry Stogov 				} else {
6317bddbd7bSDmitry Stogov 					soap_error0(E_ERROR, "Parsing WSDL: Unspecified encodingStyle");
632563e769dSDmitry Stogov 				}
633563e769dSDmitry Stogov 			}
634563e769dSDmitry Stogov 		} else if (node_is_equal_ex(trav, "header", wsdl_soap_namespace)) {
6350b0eb80fSDmitry Stogov 			sdlSoapBindingFunctionHeaderPtr h = wsdl_soap_binding_header(ctx, trav, wsdl_soap_namespace, 0);
636563e769dSDmitry Stogov 			smart_str key = {0};
637563e769dSDmitry Stogov 
638563e769dSDmitry Stogov 			if (binding->headers == NULL) {
63981af85c3SDmitry Stogov 				binding->headers = emalloc(sizeof(HashTable));
64081af85c3SDmitry Stogov 				zend_hash_init(binding->headers, 0, NULL, delete_header, 0);
641563e769dSDmitry Stogov 			}
6429fa7d1c2SDmitry Stogov 
643563e769dSDmitry Stogov 			if (h->ns) {
644563e769dSDmitry Stogov 				smart_str_appends(&key,h->ns);
645563e769dSDmitry Stogov 				smart_str_appendc(&key,':');
646563e769dSDmitry Stogov 			}
647563e769dSDmitry Stogov 			smart_str_appends(&key,h->name);
648563e769dSDmitry Stogov 			smart_str_0(&key);
649c446e575SDmitry Stogov 			if (zend_hash_add_ptr(binding->headers, key.s, h) == NULL) {
650c446e575SDmitry Stogov 				delete_header_int(h);
651563e769dSDmitry Stogov 			}
652563e769dSDmitry Stogov 			smart_str_free(&key);
653563e769dSDmitry Stogov 		} else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
6543c939e3fSStanislav Malyshev 			soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>",  SAFE_STR(trav->name));
6559fa7d1c2SDmitry Stogov 		}
656563e769dSDmitry Stogov 		trav = trav->next;
6579fa7d1c2SDmitry Stogov 	}
6589fa7d1c2SDmitry Stogov }
6599fa7d1c2SDmitry Stogov 
wsdl_message(sdlCtx * ctx,xmlChar * message_name)660ee1dc90dSDmitry Stogov static HashTable* wsdl_message(sdlCtx *ctx, xmlChar* message_name)
6619fa7d1c2SDmitry Stogov {
662c446e575SDmitry Stogov 	xmlNodePtr trav, part, message = NULL, tmp;
6639fa7d1c2SDmitry Stogov 	HashTable* parameters = NULL;
66479dc8d5eSDmitry Stogov 	char *ctype;
6659fa7d1c2SDmitry Stogov 
666ee1dc90dSDmitry Stogov 	ctype = strrchr((char*)message_name,':');
66759ab20b2SDmitry Stogov 	if (ctype == NULL) {
668ee1dc90dSDmitry Stogov 		ctype = (char*)message_name;
66959ab20b2SDmitry Stogov 	} else {
670b21756c1SDmitry Stogov 		++ctype;
67159ab20b2SDmitry Stogov 	}
672c446e575SDmitry Stogov 	if ((tmp = zend_hash_str_find_ptr(&ctx->messages, ctype, strlen(ctype))) == NULL) {
6737bddbd7bSDmitry Stogov 		soap_error1(E_ERROR, "Parsing WSDL: Missing <message> with name '%s'", message_name);
6749fa7d1c2SDmitry Stogov 	}
675c446e575SDmitry Stogov 	message = tmp;
6769fa7d1c2SDmitry Stogov 
67781af85c3SDmitry Stogov 	parameters = emalloc(sizeof(HashTable));
67881af85c3SDmitry Stogov 	zend_hash_init(parameters, 0, NULL, delete_parameter, 0);
6799fa7d1c2SDmitry Stogov 
6809fa7d1c2SDmitry Stogov 	trav = message->children;
681563e769dSDmitry Stogov 	while (trav != NULL) {
6829fa7d1c2SDmitry Stogov 		xmlAttrPtr element, type, name;
6839fa7d1c2SDmitry Stogov 		sdlParamPtr param;
6849fa7d1c2SDmitry Stogov 
685ee1dc90dSDmitry Stogov 		if (trav->ns != NULL && strcmp((char*)trav->ns->href, WSDL_NAMESPACE) != 0) {
6863c939e3fSStanislav Malyshev 			soap_error1(E_ERROR, "Parsing WSDL: Unexpected extensibility element <%s>",  SAFE_STR(trav->name));
687563e769dSDmitry Stogov 		}
688563e769dSDmitry Stogov 		if (node_is_equal(trav,"documentation")) {
689563e769dSDmitry Stogov 			trav = trav->next;
690563e769dSDmitry Stogov 			continue;
691563e769dSDmitry Stogov 		}
692563e769dSDmitry Stogov 		if (!node_is_equal(trav,"part")) {
6933c939e3fSStanislav Malyshev 			soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>",  SAFE_STR(trav->name));
694563e769dSDmitry Stogov 		}
695563e769dSDmitry Stogov 		part = trav;
69681af85c3SDmitry Stogov 		param = emalloc(sizeof(sdlParam));
6979fa7d1c2SDmitry Stogov 		memset(param,0,sizeof(sdlParam));
6989fa7d1c2SDmitry Stogov 		param->order = 0;
6999fa7d1c2SDmitry Stogov 
7009fa7d1c2SDmitry Stogov 		name = get_attribute(part->properties, "name");
7019fa7d1c2SDmitry Stogov 		if (name == NULL) {
7023c939e3fSStanislav Malyshev 			soap_error1(E_ERROR, "Parsing WSDL: No name associated with <part> '%s'",  SAFE_STR(message->name));
7039fa7d1c2SDmitry Stogov 		}
7049fa7d1c2SDmitry Stogov 
705ee1dc90dSDmitry Stogov 		param->paramName = estrdup((char*)name->children->content);
7069fa7d1c2SDmitry Stogov 
7079fa7d1c2SDmitry Stogov 		type = get_attribute(part->properties, "type");
7089fa7d1c2SDmitry Stogov 		if (type != NULL) {
70988c11689SDmitry Stogov 			param->encode = get_encoder_from_prefix(ctx->sdl, part, type->children->content);
7109fa7d1c2SDmitry Stogov 		} else {
7119fa7d1c2SDmitry Stogov 			element = get_attribute(part->properties, "element");
7129fa7d1c2SDmitry Stogov 			if (element != NULL) {
71388c11689SDmitry Stogov 				param->element = get_element(ctx->sdl, part, element->children->content);
7149fa7d1c2SDmitry Stogov 				if (param->element) {
7159fa7d1c2SDmitry Stogov 					param->encode = param->element->encode;
7169fa7d1c2SDmitry Stogov 				}
7179fa7d1c2SDmitry Stogov 			}
7189fa7d1c2SDmitry Stogov 		}
7199fa7d1c2SDmitry Stogov 
720c446e575SDmitry Stogov 		zend_hash_next_index_insert_ptr(parameters, param);
721563e769dSDmitry Stogov 
722563e769dSDmitry Stogov 		trav = trav->next;
7239fa7d1c2SDmitry Stogov 	}
7249fa7d1c2SDmitry Stogov 	return parameters;
7259fa7d1c2SDmitry Stogov }
7269fa7d1c2SDmitry Stogov 
load_wsdl(zval * this_ptr,char * struri)727bdeb220fSAnatol Belski static sdlPtr load_wsdl(zval *this_ptr, char *struri)
72829fe4588SDmitry Stogov {
72929fe4588SDmitry Stogov 	sdlCtx ctx;
73029fe4588SDmitry Stogov 	int i,n;
731f8875adaSShane Caraveo 
73288c11689SDmitry Stogov 	memset(&ctx,0,sizeof(ctx));
73381af85c3SDmitry Stogov 	ctx.sdl = emalloc(sizeof(sdl));
73488c11689SDmitry Stogov 	memset(ctx.sdl, 0, sizeof(sdl));
73581af85c3SDmitry Stogov 	ctx.sdl->source = estrdup(struri);
73681af85c3SDmitry Stogov 	zend_hash_init(&ctx.sdl->functions, 0, NULL, delete_function, 0);
737f8875adaSShane Caraveo 
73888c11689SDmitry Stogov 	zend_hash_init(&ctx.docs, 0, NULL, delete_document, 0);
73929fe4588SDmitry Stogov 	zend_hash_init(&ctx.messages, 0, NULL, NULL, 0);
74029fe4588SDmitry Stogov 	zend_hash_init(&ctx.bindings, 0, NULL, NULL, 0);
74129fe4588SDmitry Stogov 	zend_hash_init(&ctx.portTypes, 0, NULL, NULL, 0);
74229fe4588SDmitry Stogov 	zend_hash_init(&ctx.services,  0, NULL, NULL, 0);
743f8875adaSShane Caraveo 
74478375aa5SNikita Popov 	zend_try {
745*51d76c34SNikita Popov 	load_wsdl_ex(this_ptr, struri, &ctx, 0);
74688c11689SDmitry Stogov 	schema_pass2(&ctx);
74767886b83SDmitry Stogov 
74829fe4588SDmitry Stogov 	n = zend_hash_num_elements(&ctx.services);
74929fe4588SDmitry Stogov 	if (n > 0) {
75029fe4588SDmitry Stogov 		zend_hash_internal_pointer_reset(&ctx.services);
75129fe4588SDmitry Stogov 		for (i = 0; i < n; i++) {
752c446e575SDmitry Stogov 			xmlNodePtr service, tmp;
75329fe4588SDmitry Stogov 			xmlNodePtr trav, port;
754fb045249SDmitry Stogov 			int has_soap_port = 0;
755f8875adaSShane Caraveo 
756c446e575SDmitry Stogov 			service = tmp = zend_hash_get_current_data_ptr(&ctx.services);
7572a5593ddSDmitry Stogov 
75829fe4588SDmitry Stogov 			trav = service->children;
759563e769dSDmitry Stogov 			while (trav != NULL) {
76029fe4588SDmitry Stogov 				xmlAttrPtr type, name, bindingAttr, location;
76129fe4588SDmitry Stogov 				xmlNodePtr portType, operation;
76229fe4588SDmitry Stogov 				xmlNodePtr address, binding, trav2;
76379dc8d5eSDmitry Stogov 				char *ctype;
76429fe4588SDmitry Stogov 				sdlBindingPtr tmpbinding;
7658f0ea19fSDmitry Stogov 				char *wsdl_soap_namespace = NULL;
766f8875adaSShane Caraveo 
767563e769dSDmitry Stogov 				if (!is_wsdl_element(trav) || node_is_equal(trav,"documentation")) {
768563e769dSDmitry Stogov 					trav = trav->next;
769563e769dSDmitry Stogov 					continue;
770563e769dSDmitry Stogov 				}
771563e769dSDmitry Stogov 				if (!node_is_equal(trav,"port")) {
7723c939e3fSStanislav Malyshev 					soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>",  SAFE_STR(trav->name));
773563e769dSDmitry Stogov 				}
774563e769dSDmitry Stogov 
775563e769dSDmitry Stogov 				port = trav;
776563e769dSDmitry Stogov 
77781af85c3SDmitry Stogov 				tmpbinding = emalloc(sizeof(sdlBinding));
77829fe4588SDmitry Stogov 				memset(tmpbinding, 0, sizeof(sdlBinding));
7792a5593ddSDmitry Stogov 
78029fe4588SDmitry Stogov 				bindingAttr = get_attribute(port->properties, "binding");
78129fe4588SDmitry Stogov 				if (bindingAttr == NULL) {
7827bddbd7bSDmitry Stogov 					soap_error0(E_ERROR, "Parsing WSDL: No binding associated with <port>");
78329fe4588SDmitry Stogov 				}
784a8326d6fSBrad LaFountain 
78529fe4588SDmitry Stogov 				/* find address and figure out binding type */
786563e769dSDmitry Stogov 				address = NULL;
787563e769dSDmitry Stogov 				trav2 = port->children;
788563e769dSDmitry Stogov 				while (trav2 != NULL) {
789563e769dSDmitry Stogov 					if (node_is_equal(trav2,"address") && trav2->ns) {
790ee1dc90dSDmitry Stogov 						if (!strncmp((char*)trav2->ns->href, WSDL_SOAP11_NAMESPACE, sizeof(WSDL_SOAP11_NAMESPACE))) {
791563e769dSDmitry Stogov 							address = trav2;
792563e769dSDmitry Stogov 							wsdl_soap_namespace = WSDL_SOAP11_NAMESPACE;
793563e769dSDmitry Stogov 							tmpbinding->bindingType = BINDING_SOAP;
794ee1dc90dSDmitry Stogov 						} else if (!strncmp((char*)trav2->ns->href, WSDL_SOAP12_NAMESPACE, sizeof(WSDL_SOAP12_NAMESPACE))) {
795563e769dSDmitry Stogov 							address = trav2;
796563e769dSDmitry Stogov 							wsdl_soap_namespace = WSDL_SOAP12_NAMESPACE;
797563e769dSDmitry Stogov 							tmpbinding->bindingType = BINDING_SOAP;
798ee1dc90dSDmitry Stogov 						} else if (!strncmp((char*)trav2->ns->href, RPC_SOAP12_NAMESPACE, sizeof(RPC_SOAP12_NAMESPACE))) {
799563e769dSDmitry Stogov 							address = trav2;
800563e769dSDmitry Stogov 							wsdl_soap_namespace = RPC_SOAP12_NAMESPACE;
801563e769dSDmitry Stogov 							tmpbinding->bindingType = BINDING_SOAP;
802ee1dc90dSDmitry Stogov 						} else if (!strncmp((char*)trav2->ns->href, WSDL_HTTP11_NAMESPACE, sizeof(WSDL_HTTP11_NAMESPACE))) {
803563e769dSDmitry Stogov 							address = trav2;
804563e769dSDmitry Stogov 							tmpbinding->bindingType = BINDING_HTTP;
805ee1dc90dSDmitry Stogov 						} else if (!strncmp((char*)trav2->ns->href, WSDL_HTTP12_NAMESPACE, sizeof(WSDL_HTTP12_NAMESPACE))) {
806563e769dSDmitry Stogov 							address = trav2;
807563e769dSDmitry Stogov 							tmpbinding->bindingType = BINDING_HTTP;
808563e769dSDmitry Stogov 						}
809563e769dSDmitry Stogov 					}
810563e769dSDmitry Stogov 					if (trav2 != address && is_wsdl_element(trav2) && !node_is_equal(trav2,"documentation")) {
8113c939e3fSStanislav Malyshev 						soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>",  SAFE_STR(trav2->name));
812563e769dSDmitry Stogov 					}
813563e769dSDmitry Stogov 				  trav2 = trav2->next;
814563e769dSDmitry Stogov 				}
8155429bfb5SDmitry Stogov 				if (!address || tmpbinding->bindingType == BINDING_HTTP) {
8167d1dbff7SDmitry Stogov 					if (has_soap_port || trav->next || i < n-1) {
817fb045249SDmitry Stogov 						efree(tmpbinding);
818fb045249SDmitry Stogov 						trav = trav->next;
819fb045249SDmitry Stogov 						continue;
8205429bfb5SDmitry Stogov 					} else if (!address) {
821fb045249SDmitry Stogov 						soap_error0(E_ERROR, "Parsing WSDL: No address associated with <port>");
822fb045249SDmitry Stogov 					}
823a8326d6fSBrad LaFountain 				}
824fb045249SDmitry Stogov 				has_soap_port = 1;
825f8875adaSShane Caraveo 
82629fe4588SDmitry Stogov 				location = get_attribute(address->properties, "location");
82729fe4588SDmitry Stogov 				if (!location) {
8287bddbd7bSDmitry Stogov 					soap_error0(E_ERROR, "Parsing WSDL: No location associated with <port>");
82929fe4588SDmitry Stogov 				}
830f8875adaSShane Caraveo 
831ee1dc90dSDmitry Stogov 				tmpbinding->location = estrdup((char*)location->children->content);
832f8875adaSShane Caraveo 
833ee1dc90dSDmitry Stogov 				ctype = strrchr((char*)bindingAttr->children->content,':');
83459ab20b2SDmitry Stogov 				if (ctype == NULL) {
835ee1dc90dSDmitry Stogov 					ctype = (char*)bindingAttr->children->content;
83659ab20b2SDmitry Stogov 				} else {
837b21756c1SDmitry Stogov 					++ctype;
83859ab20b2SDmitry Stogov 				}
839c446e575SDmitry Stogov 				if ((tmp = zend_hash_str_find_ptr(&ctx.bindings, ctype, strlen(ctype))) == NULL) {
8407bddbd7bSDmitry Stogov 					soap_error1(E_ERROR, "Parsing WSDL: No <binding> element with name '%s'", ctype);
8419a3cdc64SDmitry Stogov 				}
842c446e575SDmitry Stogov 				binding = tmp;
843a8326d6fSBrad LaFountain 
8449a3cdc64SDmitry Stogov 				if (tmpbinding->bindingType == BINDING_SOAP) {
845a8326d6fSBrad LaFountain 					sdlSoapBindingPtr soapBinding;
84629fe4588SDmitry Stogov 					xmlNodePtr soapBindingNode;
847a8326d6fSBrad LaFountain 					xmlAttrPtr tmp;
848a8326d6fSBrad LaFountain 
84981af85c3SDmitry Stogov 					soapBinding = emalloc(sizeof(sdlSoapBinding));
85029fe4588SDmitry Stogov 					memset(soapBinding, 0, sizeof(sdlSoapBinding));
8518f0ea19fSDmitry Stogov 					soapBinding->style = SOAP_DOCUMENT;
852a8326d6fSBrad LaFountain 
8538f0ea19fSDmitry Stogov 					soapBindingNode = get_node_ex(binding->children, "binding", wsdl_soap_namespace);
85429fe4588SDmitry Stogov 					if (soapBindingNode) {
85529fe4588SDmitry Stogov 						tmp = get_attribute(soapBindingNode->properties, "style");
856ee1dc90dSDmitry Stogov 						if (tmp && !strncmp((char*)tmp->children->content, "rpc", sizeof("rpc"))) {
8578f0ea19fSDmitry Stogov 							soapBinding->style = SOAP_RPC;
8589a3cdc64SDmitry Stogov 						}
859a8326d6fSBrad LaFountain 
86029fe4588SDmitry Stogov 						tmp = get_attribute(soapBindingNode->properties, "transport");
86129fe4588SDmitry Stogov 						if (tmp) {
862ee1dc90dSDmitry Stogov 							if (strncmp((char*)tmp->children->content, WSDL_HTTP_TRANSPORT, sizeof(WSDL_HTTP_TRANSPORT)) == 0) {
86315ccb3beSDmitry Stogov 								soapBinding->transport = SOAP_TRANSPORT_HTTP;
86415ccb3beSDmitry Stogov 							} else {
865fa0a07baSDmitry Stogov 								/* try the next binding */
866fa0a07baSDmitry Stogov 								efree(soapBinding);
867fa0a07baSDmitry Stogov 								efree(tmpbinding->location);
868fa0a07baSDmitry Stogov 								efree(tmpbinding);
869fa0a07baSDmitry Stogov 								trav = trav->next;
870fa0a07baSDmitry Stogov 								continue;
87129fe4588SDmitry Stogov 							}
8729a3cdc64SDmitry Stogov 						}
873a8326d6fSBrad LaFountain 					}
8743961fec2SDmitry Stogov 					tmpbinding->bindingAttributes = (void *)soapBinding;
87529fe4588SDmitry Stogov 				}
876a8326d6fSBrad LaFountain 
87729fe4588SDmitry Stogov 				name = get_attribute(binding->properties, "name");
87829fe4588SDmitry Stogov 				if (name == NULL) {
8797bddbd7bSDmitry Stogov 					soap_error0(E_ERROR, "Parsing WSDL: Missing 'name' attribute for <binding>");
880a8326d6fSBrad LaFountain 				}
881ee1dc90dSDmitry Stogov 				tmpbinding->name = estrdup((char*)name->children->content);
882a8326d6fSBrad LaFountain 
88329fe4588SDmitry Stogov 				type = get_attribute(binding->properties, "type");
88429fe4588SDmitry Stogov 				if (type == NULL) {
8857bddbd7bSDmitry Stogov 					soap_error0(E_ERROR, "Parsing WSDL: Missing 'type' attribute for <binding>");
88629fe4588SDmitry Stogov 				}
887a8326d6fSBrad LaFountain 
888ee1dc90dSDmitry Stogov 				ctype = strrchr((char*)type->children->content,':');
88959ab20b2SDmitry Stogov 				if (ctype == NULL) {
890ee1dc90dSDmitry Stogov 					ctype = (char*)type->children->content;
89159ab20b2SDmitry Stogov 				} else {
892b21756c1SDmitry Stogov 					++ctype;
89359ab20b2SDmitry Stogov 				}
894c446e575SDmitry Stogov 				if ((tmp = zend_hash_str_find_ptr(&ctx.portTypes, ctype, strlen(ctype))) == NULL) {
8957bddbd7bSDmitry Stogov 					soap_error1(E_ERROR, "Parsing WSDL: Missing <portType> with name '%s'", name->children->content);
89629fe4588SDmitry Stogov 				}
897c446e575SDmitry Stogov 				portType = tmp;
898a8326d6fSBrad LaFountain 
89929fe4588SDmitry Stogov 				trav2 = binding->children;
900563e769dSDmitry Stogov 				while (trav2 != NULL) {
90129fe4588SDmitry Stogov 					sdlFunctionPtr function;
902563e769dSDmitry Stogov 					xmlNodePtr input, output, fault, portTypeOperation, trav3;
90329fe4588SDmitry Stogov 					xmlAttrPtr op_name, paramOrder;
90429fe4588SDmitry Stogov 
905563e769dSDmitry Stogov 					if ((tmpbinding->bindingType == BINDING_SOAP &&
906563e769dSDmitry Stogov 					    node_is_equal_ex(trav2, "binding", wsdl_soap_namespace)) ||
907563e769dSDmitry Stogov 					    !is_wsdl_element(trav2) ||
908563e769dSDmitry Stogov 					    node_is_equal(trav2,"documentation")) {
909563e769dSDmitry Stogov 						trav2 = trav2->next;
910563e769dSDmitry Stogov 						continue;
911563e769dSDmitry Stogov 					}
912563e769dSDmitry Stogov 					if (!node_is_equal(trav2,"operation")) {
9133c939e3fSStanislav Malyshev 						soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>",  SAFE_STR(trav2->name));
914563e769dSDmitry Stogov 					}
915563e769dSDmitry Stogov 
916563e769dSDmitry Stogov 					operation = trav2;
917563e769dSDmitry Stogov 
91829fe4588SDmitry Stogov 					op_name = get_attribute(operation->properties, "name");
91929fe4588SDmitry Stogov 					if (op_name == NULL) {
9207bddbd7bSDmitry Stogov 						soap_error0(E_ERROR, "Parsing WSDL: Missing 'name' attribute for <operation>");
92129fe4588SDmitry Stogov 					}
92229fe4588SDmitry Stogov 
923563e769dSDmitry Stogov 					trav3 = operation->children;
924563e769dSDmitry Stogov 					while  (trav3 != NULL) {
925563e769dSDmitry Stogov 						if (tmpbinding->bindingType == BINDING_SOAP &&
926563e769dSDmitry Stogov 						    node_is_equal_ex(trav3, "operation", wsdl_soap_namespace)) {
927563e769dSDmitry Stogov 						} else if (is_wsdl_element(trav3) &&
928563e769dSDmitry Stogov 						           !node_is_equal(trav3,"input") &&
929563e769dSDmitry Stogov 						           !node_is_equal(trav3,"output") &&
930563e769dSDmitry Stogov 						           !node_is_equal(trav3,"fault") &&
931563e769dSDmitry Stogov 						           !node_is_equal(trav3,"documentation")) {
9323c939e3fSStanislav Malyshev 							soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>",  SAFE_STR(trav3->name));
933563e769dSDmitry Stogov 						}
934563e769dSDmitry Stogov 						trav3 = trav3->next;
935563e769dSDmitry Stogov 					}
936563e769dSDmitry Stogov 
937ee1dc90dSDmitry Stogov 					portTypeOperation = get_node_with_attribute_ex(portType->children, "operation", WSDL_NAMESPACE, "name", (char*)op_name->children->content, NULL);
93829fe4588SDmitry Stogov 					if (portTypeOperation == NULL) {
9397bddbd7bSDmitry Stogov 						soap_error1(E_ERROR, "Parsing WSDL: Missing <portType>/<operation> with name '%s'", op_name->children->content);
9409a3cdc64SDmitry Stogov 					}
94129fe4588SDmitry Stogov 
94281af85c3SDmitry Stogov 					function = emalloc(sizeof(sdlFunction));
94315ccb3beSDmitry Stogov 					memset(function, 0, sizeof(sdlFunction));
944ee1dc90dSDmitry Stogov 					function->functionName = estrdup((char*)op_name->children->content);
945a8326d6fSBrad LaFountain 
9469a3cdc64SDmitry Stogov 					if (tmpbinding->bindingType == BINDING_SOAP) {
94729fe4588SDmitry Stogov 						sdlSoapBindingFunctionPtr soapFunctionBinding;
94829fe4588SDmitry Stogov 						sdlSoapBindingPtr soapBinding;
94929fe4588SDmitry Stogov 						xmlNodePtr soapOperation;
950a8326d6fSBrad LaFountain 						xmlAttrPtr tmp;
951a8326d6fSBrad LaFountain 
95281af85c3SDmitry Stogov 						soapFunctionBinding = emalloc(sizeof(sdlSoapBindingFunction));
95329fe4588SDmitry Stogov 						memset(soapFunctionBinding, 0, sizeof(sdlSoapBindingFunction));
95429fe4588SDmitry Stogov 						soapBinding = (sdlSoapBindingPtr)tmpbinding->bindingAttributes;
95529fe4588SDmitry Stogov 						soapFunctionBinding->style = soapBinding->style;
956a8326d6fSBrad LaFountain 
9578f0ea19fSDmitry Stogov 						soapOperation = get_node_ex(operation->children, "operation", wsdl_soap_namespace);
95829fe4588SDmitry Stogov 						if (soapOperation) {
95929fe4588SDmitry Stogov 							tmp = get_attribute(soapOperation->properties, "soapAction");
9609a3cdc64SDmitry Stogov 							if (tmp) {
961ee1dc90dSDmitry Stogov 								soapFunctionBinding->soapAction = estrdup((char*)tmp->children->content);
9629a3cdc64SDmitry Stogov 							}
963a8326d6fSBrad LaFountain 
96429fe4588SDmitry Stogov 							tmp = get_attribute(soapOperation->properties, "style");
9658f0ea19fSDmitry Stogov 							if (tmp) {
966ee1dc90dSDmitry Stogov 								if (!strncmp((char*)tmp->children->content, "rpc", sizeof("rpc"))) {
9678f0ea19fSDmitry Stogov 									soapFunctionBinding->style = SOAP_RPC;
9688f0ea19fSDmitry Stogov 								} else {
9698f0ea19fSDmitry Stogov 									soapFunctionBinding->style = SOAP_DOCUMENT;
9708f0ea19fSDmitry Stogov 								}
9718f0ea19fSDmitry Stogov 							} else {
9728f0ea19fSDmitry Stogov 								soapFunctionBinding->style = soapBinding->style;
9739a3cdc64SDmitry Stogov 							}
974a8326d6fSBrad LaFountain 						}
975a8326d6fSBrad LaFountain 
97629fe4588SDmitry Stogov 						function->bindingAttributes = (void *)soapFunctionBinding;
97729fe4588SDmitry Stogov 					}
978f8875adaSShane Caraveo 
979563e769dSDmitry Stogov 					input = get_node_ex(portTypeOperation->children, "input", WSDL_NAMESPACE);
98029fe4588SDmitry Stogov 					if (input != NULL) {
981c7206771SNikita Popov 						xmlAttrPtr message;
982f8875adaSShane Caraveo 
9839fa7d1c2SDmitry Stogov 						message = get_attribute(input->properties, "message");
9849fa7d1c2SDmitry Stogov 						if (message == NULL) {
9857bddbd7bSDmitry Stogov 							soap_error1(E_ERROR, "Parsing WSDL: Missing name for <input> of '%s'", op_name->children->content);
9869fa7d1c2SDmitry Stogov 						}
9879fa7d1c2SDmitry Stogov 						function->requestParameters =