xref: /PHP-5.6/ext/soap/php_sdl.c (revision 49493a2d)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2016 The PHP Group                                |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.txt                                  |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Authors: Brad Lafountain <rodif_bl@yahoo.com>                        |
16   |          Shane Caraveo <shane@caraveo.com>                           |
17   |          Dmitry Stogov <dmitry@zend.com>                             |
18   +----------------------------------------------------------------------+
19 */
20 /* $Id$ */
21 
22 #include "php_soap.h"
23 #include "ext/libxml/php_libxml.h"
24 #include "libxml/uri.h"
25 
26 #include "ext/standard/md5.h"
27 #include "zend_virtual_cwd.h"
28 
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 
33 #ifndef O_BINARY
34 # define O_BINARY 0
35 #endif
36 
37 static void delete_fault(void *fault);
38 static void delete_fault_persistent(void *fault);
39 static void delete_binding(void *binding);
40 static void delete_binding_persistent(void *binding);
41 static void delete_function(void *function);
42 static void delete_function_persistent(void *function);
43 static void delete_parameter(void *parameter);
44 static void delete_parameter_persistent(void *parameter);
45 static void delete_header(void *header);
46 static void delete_header_persistent(void *header);
47 static void delete_document(void *doc_ptr);
48 
get_encoder_from_prefix(sdlPtr sdl,xmlNodePtr node,const xmlChar * type)49 encodePtr get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr node, const xmlChar *type)
50 {
51 	encodePtr enc = NULL;
52 	xmlNsPtr nsptr;
53 	char *ns, *cptype;
54 
55 	parse_namespace(type, &cptype, &ns);
56 	nsptr = xmlSearchNs(node->doc, node, BAD_CAST(ns));
57 	if (nsptr != NULL) {
58 		enc = get_encoder(sdl, (char*)nsptr->href, cptype);
59 		if (enc == NULL) {
60 			enc = get_encoder_ex(sdl, cptype, strlen(cptype));
61 		}
62 	} else {
63 		enc = get_encoder_ex(sdl, (char*)type, xmlStrlen(type));
64 	}
65 	efree(cptype);
66 	if (ns) {efree(ns);}
67 	return enc;
68 }
69 
get_element(sdlPtr sdl,xmlNodePtr node,const xmlChar * type)70 static sdlTypePtr get_element(sdlPtr sdl, xmlNodePtr node, const xmlChar *type)
71 {
72 	sdlTypePtr ret = NULL;
73 
74 	if (sdl->elements) {
75 		xmlNsPtr nsptr;
76 		char *ns, *cptype;
77 		sdlTypePtr *sdl_type;
78 
79 		parse_namespace(type, &cptype, &ns);
80 		nsptr = xmlSearchNs(node->doc, node, BAD_CAST(ns));
81 		if (nsptr != NULL) {
82 			int ns_len = xmlStrlen(nsptr->href);
83 			int type_len = strlen(cptype);
84 			int len = ns_len + type_len + 1;
85 			char *nscat = emalloc(len + 1);
86 
87 			memcpy(nscat, nsptr->href, ns_len);
88 			nscat[ns_len] = ':';
89 			memcpy(nscat+ns_len+1, cptype, type_len);
90 			nscat[len] = '\0';
91 
92 			if (zend_hash_find(sdl->elements, nscat, len + 1, (void **)&sdl_type) == SUCCESS) {
93 				ret = *sdl_type;
94 			} else if (zend_hash_find(sdl->elements, (char*)type, type_len + 1, (void **)&sdl_type) == SUCCESS) {
95 				ret = *sdl_type;
96 			}
97 			efree(nscat);
98 		} else {
99 			if (zend_hash_find(sdl->elements, (char*)type, xmlStrlen(type) + 1, (void **)&sdl_type) == SUCCESS) {
100 				ret = *sdl_type;
101 			}
102 		}
103 
104 		efree(cptype);
105 		if (ns) {efree(ns);}
106 	}
107 	return ret;
108 }
109 
get_encoder(sdlPtr sdl,const char * ns,const char * type)110 encodePtr get_encoder(sdlPtr sdl, const char *ns, const char *type)
111 {
112 	encodePtr enc = NULL;
113 	char *nscat;
114 	int ns_len = ns ? strlen(ns) : 0;
115 	int type_len = strlen(type);
116 	int len = ns_len + type_len + 1;
117 
118 	nscat = emalloc(len + 1);
119 	memcpy(nscat, ns, ns_len);
120 	nscat[ns_len] = ':';
121 	memcpy(nscat+ns_len+1, type, type_len);
122 	nscat[len] = '\0';
123 
124 	enc = get_encoder_ex(sdl, nscat, len);
125 
126 	if (enc == NULL &&
127 	    ((ns_len == sizeof(SOAP_1_1_ENC_NAMESPACE)-1 &&
128 	      memcmp(ns, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)-1) == 0) ||
129 	     (ns_len == sizeof(SOAP_1_2_ENC_NAMESPACE)-1 &&
130 	      memcmp(ns, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)-1) == 0))) {
131 		char *enc_nscat;
132 		int enc_ns_len;
133 		int enc_len;
134 
135 		enc_ns_len = sizeof(XSD_NAMESPACE)-1;
136 		enc_len = enc_ns_len + type_len + 1;
137 		enc_nscat = emalloc(enc_len + 1);
138 		memcpy(enc_nscat, XSD_NAMESPACE, sizeof(XSD_NAMESPACE)-1);
139 		enc_nscat[enc_ns_len] = ':';
140 		memcpy(enc_nscat+enc_ns_len+1, type, type_len);
141 		enc_nscat[enc_len] = '\0';
142 
143 		enc = get_encoder_ex(NULL, enc_nscat, enc_len);
144 		efree(enc_nscat);
145 		if (enc && sdl) {
146 			encodePtr new_enc	= pemalloc(sizeof(encode), sdl->is_persistent);
147 			memcpy(new_enc, enc, sizeof(encode));
148 			if (sdl->is_persistent) {
149 				new_enc->details.ns = zend_strndup(ns, ns_len);
150 				new_enc->details.type_str = strdup(new_enc->details.type_str);
151 			} else {
152 				new_enc->details.ns = estrndup(ns, ns_len);
153 				new_enc->details.type_str = estrdup(new_enc->details.type_str);
154 			}
155 			if (sdl->encoders == NULL) {
156 				sdl->encoders = pemalloc(sizeof(HashTable), sdl->is_persistent);
157 				zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, sdl->is_persistent);
158 			}
159 			zend_hash_update(sdl->encoders, nscat, len + 1, &new_enc, sizeof(encodePtr), NULL);
160 			enc = new_enc;
161 		}
162 	}
163 	efree(nscat);
164 	return enc;
165 }
166 
get_encoder_ex(sdlPtr sdl,const char * nscat,int len)167 encodePtr get_encoder_ex(sdlPtr sdl, const char *nscat, int len)
168 {
169 	encodePtr *enc;
170 	TSRMLS_FETCH();
171 
172 	if (zend_hash_find(&SOAP_GLOBAL(defEnc), (char*)nscat, len + 1, (void **)&enc) == SUCCESS) {
173 		return (*enc);
174 	} else if (sdl && sdl->encoders && zend_hash_find(sdl->encoders, (char*)nscat, len + 1, (void **)&enc) == SUCCESS) {
175 		return (*enc);
176 	}
177 	return NULL;
178 }
179 
get_binding_from_type(sdlPtr sdl,int type)180 sdlBindingPtr get_binding_from_type(sdlPtr sdl, int type)
181 {
182 	sdlBindingPtr *binding;
183 
184 	if (sdl == NULL) {
185 		return NULL;
186 	}
187 
188 	for (zend_hash_internal_pointer_reset(sdl->bindings);
189 		zend_hash_get_current_data(sdl->bindings, (void **) &binding) == SUCCESS;
190 		zend_hash_move_forward(sdl->bindings)) {
191 		if ((*binding)->bindingType == type) {
192 			return *binding;
193 		}
194 	}
195 	return NULL;
196 }
197 
get_binding_from_name(sdlPtr sdl,char * name,char * ns)198 sdlBindingPtr get_binding_from_name(sdlPtr sdl, char *name, char *ns)
199 {
200 	sdlBindingPtr binding = NULL;
201 	smart_str key = {0};
202 
203 	smart_str_appends(&key, ns);
204 	smart_str_appendc(&key, ':');
205 	smart_str_appends(&key, name);
206 	smart_str_0(&key);
207 
208 	zend_hash_find(sdl->bindings, key.c, key.len, (void **)&binding);
209 
210 	smart_str_free(&key);
211 	return binding;
212 }
213 
is_wsdl_element(xmlNodePtr node)214 static int is_wsdl_element(xmlNodePtr node)
215 {
216 	if (node->ns && strcmp((char*)node->ns->href, WSDL_NAMESPACE) != 0) {
217 		xmlAttrPtr attr;
218 		if ((attr = get_attribute_ex(node->properties, "required", WSDL_NAMESPACE)) != NULL &&
219 		     attr->children && attr->children->content &&
220 		     (strcmp((char*)attr->children->content, "1") == 0 ||
221 		      strcmp((char*)attr->children->content, "true") == 0)) {
222 			soap_error1(E_ERROR, "Parsing WSDL: Unknown required WSDL extension '%s'", node->ns->href);
223 		}
224 		return 0;
225 	}
226 	return 1;
227 }
228 
sdl_set_uri_credentials(sdlCtx * ctx,char * uri TSRMLS_DC)229 void sdl_set_uri_credentials(sdlCtx *ctx, char *uri TSRMLS_DC)
230 {
231 	char *s;
232 	int l1, l2;
233 	zval *context = NULL;
234 	zval **header = NULL;
235 
236 	/* check if we load xsd from the same server */
237 	s = strstr(ctx->sdl->source, "://");
238 	if (!s) return;
239 	s = strchr(s+3, '/');
240 	l1 = s ? (s - ctx->sdl->source) : strlen(ctx->sdl->source);
241 	s = strstr((char*)uri, "://");
242 	if (!s) return;
243 	s = strchr(s+3, '/');
244 	l2 = s ? (s - (char*)uri) : strlen((char*)uri);
245 	if (l1 != l2) {
246 		/* check for http://...:80/ */
247 		if (l1 > 11 &&
248 		    ctx->sdl->source[4] == ':' &&
249 		    ctx->sdl->source[l1-3] == ':' &&
250 		    ctx->sdl->source[l1-2] == '8' &&
251 		    ctx->sdl->source[l1-1] == '0') {
252 			l1 -= 3;
253 		}
254 		if (l2 > 11 &&
255 		    uri[4] == ':' &&
256 		    uri[l2-3] == ':' &&
257 		    uri[l2-2] == '8' &&
258 		    uri[l2-1] == '0') {
259 			l2 -= 3;
260 		}
261 		/* check for https://...:443/ */
262 		if (l1 > 13 &&
263 		    ctx->sdl->source[4] == 's' &&
264 		    ctx->sdl->source[l1-4] == ':' &&
265 		    ctx->sdl->source[l1-3] == '4' &&
266 		    ctx->sdl->source[l1-2] == '4' &&
267 		    ctx->sdl->source[l1-1] == '3') {
268 			l1 -= 4;
269 		}
270 		if (l2 > 13 &&
271 		    uri[4] == 's' &&
272 		    uri[l2-4] == ':' &&
273 		    uri[l2-3] == '4' &&
274 		    uri[l2-2] == '4' &&
275 		    uri[l2-1] == '3') {
276 			l2 -= 4;
277 		}
278 	}
279 	if (l1 != l2 || memcmp(ctx->sdl->source, uri, l1) != 0) {
280 		/* another server. clear authentication credentals */
281 		context = php_libxml_switch_context(NULL TSRMLS_CC);
282 		php_libxml_switch_context(context TSRMLS_CC);
283 		if (context) {
284 			ctx->context = php_stream_context_from_zval(context, 1);
285 
286 			if (ctx->context &&
287 			    php_stream_context_get_option(ctx->context, "http", "header", &header) == SUCCESS) {
288 				s = strstr(Z_STRVAL_PP(header), "Authorization: Basic");
289 				if (s && (s == Z_STRVAL_PP(header) || *(s-1) == '\n' || *(s-1) == '\r')) {
290 					char *rest = strstr(s, "\r\n");
291 					if (rest) {
292 						zval new_header;
293 
294 						rest += 2;
295 						Z_TYPE(new_header) = IS_STRING;
296 						Z_STRLEN(new_header) = Z_STRLEN_PP(header) - (rest - s);
297 						Z_STRVAL(new_header) = emalloc(Z_STRLEN_PP(header) + 1);
298 						memcpy(Z_STRVAL(new_header), Z_STRVAL_PP(header), s - Z_STRVAL_PP(header));
299 						memcpy(Z_STRVAL(new_header) + (s - Z_STRVAL_PP(header)), rest, Z_STRLEN_PP(header) - (rest - Z_STRVAL_PP(header)) + 1);
300 						ctx->old_header = *header;
301 						Z_ADDREF_P(ctx->old_header);
302 						php_stream_context_set_option(ctx->context, "http", "header", &new_header);
303 						zval_dtor(&new_header);
304 					}
305 				}
306 			}
307 		}
308 	}
309 }
310 
sdl_restore_uri_credentials(sdlCtx * ctx TSRMLS_DC)311 void sdl_restore_uri_credentials(sdlCtx *ctx TSRMLS_DC)
312 {
313 	if (ctx->old_header) {
314 	    php_stream_context_set_option(ctx->context, "http", "header", ctx->old_header);
315 	    zval_ptr_dtor(&ctx->old_header);
316 		ctx->old_header = NULL;
317 	}
318 	ctx->context = NULL;
319 }
320 
load_wsdl_ex(zval * this_ptr,char * struri,sdlCtx * ctx,int include TSRMLS_DC)321 static void load_wsdl_ex(zval *this_ptr, char *struri, sdlCtx *ctx, int include TSRMLS_DC)
322 {
323 	sdlPtr tmpsdl = ctx->sdl;
324 	xmlDocPtr wsdl;
325 	xmlNodePtr root, definitions, trav;
326 	xmlAttrPtr targetNamespace;
327 
328 	if (zend_hash_exists(&ctx->docs, struri, strlen(struri)+1)) {
329 		return;
330 	}
331 
332 	sdl_set_uri_credentials(ctx, struri TSRMLS_CC);
333 	wsdl = soap_xmlParseFile(struri TSRMLS_CC);
334 	sdl_restore_uri_credentials(ctx TSRMLS_CC);
335 
336 	if (!wsdl) {
337 		xmlErrorPtr xmlErrorPtr = xmlGetLastError();
338 
339 		if (xmlErrorPtr) {
340 			soap_error2(E_ERROR, "Parsing WSDL: Couldn't load from '%s' : %s", struri, xmlErrorPtr->message);
341 		} else {
342 			soap_error1(E_ERROR, "Parsing WSDL: Couldn't load from '%s'", struri);
343 		}
344 	}
345 
346 	zend_hash_add(&ctx->docs, struri, strlen(struri)+1, (void**)&wsdl, sizeof(xmlDocPtr), NULL);
347 
348 	root = wsdl->children;
349 	definitions = get_node_ex(root, "definitions", WSDL_NAMESPACE);
350 	if (!definitions) {
351 		if (include) {
352 			xmlNodePtr schema = get_node_ex(root, "schema", XSD_NAMESPACE);
353 			if (schema) {
354 				load_schema(ctx, schema TSRMLS_CC);
355 				return;
356 			}
357 		}
358 		soap_error1(E_ERROR, "Parsing WSDL: Couldn't find <definitions> in '%s'", struri);
359 	}
360 
361 	if (!include) {
362 		targetNamespace = get_attribute(definitions->properties, "targetNamespace");
363 		if (targetNamespace) {
364 			tmpsdl->target_ns = estrdup((char*)targetNamespace->children->content);
365 		}
366 	}
367 
368 	trav = definitions->children;
369 	while (trav != NULL) {
370 		if (!is_wsdl_element(trav)) {
371 			trav = trav->next;
372 			continue;
373 		}
374 		if (node_is_equal(trav,"types")) {
375 			/* TODO: Only one "types" is allowed */
376 			xmlNodePtr trav2 = trav->children;
377 
378 			while (trav2 != NULL) {
379 				if (node_is_equal_ex(trav2, "schema", XSD_NAMESPACE)) {
380 					load_schema(ctx, trav2 TSRMLS_CC);
381 				} else if (is_wsdl_element(trav2) && !node_is_equal(trav2,"documentation")) {
382 					soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
383 				}
384 				trav2 = trav2->next;
385 			}
386 		} else if (node_is_equal(trav,"import")) {
387 			/* TODO: namespace ??? */
388 			xmlAttrPtr tmp = get_attribute(trav->properties, "location");
389 			if (tmp) {
390 				xmlChar *uri;
391 				xmlChar *base = xmlNodeGetBase(trav->doc, trav);
392 
393 				if (base == NULL) {
394 					uri = xmlBuildURI(tmp->children->content, trav->doc->URL);
395 				} else {
396 					uri = xmlBuildURI(tmp->children->content, base);
397 					xmlFree(base);
398 				}
399 				load_wsdl_ex(this_ptr, (char*)uri, ctx, 1 TSRMLS_CC);
400 				xmlFree(uri);
401 			}
402 
403 		} else if (node_is_equal(trav,"message")) {
404 			xmlAttrPtr name = get_attribute(trav->properties, "name");
405 			if (name && name->children && name->children->content) {
406 				if (zend_hash_add(&ctx->messages, (char*)name->children->content, xmlStrlen(name->children->content)+1,&trav, sizeof(xmlNodePtr), NULL) != SUCCESS) {
407 					soap_error1(E_ERROR, "Parsing WSDL: <message> '%s' already defined", name->children->content);
408 				}
409 			} else {
410 				soap_error0(E_ERROR, "Parsing WSDL: <message> has no name attribute");
411 			}
412 
413 		} else if (node_is_equal(trav,"portType")) {
414 			xmlAttrPtr name = get_attribute(trav->properties, "name");
415 			if (name && name->children && name->children->content) {
416 				if (zend_hash_add(&ctx->portTypes, (char*)name->children->content, xmlStrlen(name->children->content)+1,&trav, sizeof(xmlNodePtr), NULL) != SUCCESS) {
417 					soap_error1(E_ERROR, "Parsing WSDL: <portType> '%s' already defined", name->children->content);
418 				}
419 			} else {
420 				soap_error0(E_ERROR, "Parsing WSDL: <portType> has no name attribute");
421 			}
422 
423 		} else if (node_is_equal(trav,"binding")) {
424 			xmlAttrPtr name = get_attribute(trav->properties, "name");
425 			if (name && name->children && name->children->content) {
426 				if (zend_hash_add(&ctx->bindings, (char*)name->children->content, xmlStrlen(name->children->content)+1,&trav, sizeof(xmlNodePtr), NULL) != SUCCESS) {
427 					soap_error1(E_ERROR, "Parsing WSDL: <binding> '%s' already defined", name->children->content);
428 				}
429 			} else {
430 				soap_error0(E_ERROR, "Parsing WSDL: <binding> has no name attribute");
431 			}
432 
433 		} else if (node_is_equal(trav,"service")) {
434 			xmlAttrPtr name = get_attribute(trav->properties, "name");
435 			if (name && name->children && name->children->content) {
436 				if (zend_hash_add(&ctx->services, (char*)name->children->content, xmlStrlen(name->children->content)+1,&trav, sizeof(xmlNodePtr), NULL) != SUCCESS) {
437 					soap_error1(E_ERROR, "Parsing WSDL: <service> '%s' already defined", name->children->content);
438 				}
439 			} else {
440 				soap_error0(E_ERROR, "Parsing WSDL: <service> has no name attribute");
441 			}
442 		} else if (!node_is_equal(trav,"documentation")) {
443 			soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
444 		}
445 		trav = trav->next;
446 	}
447 }
448 
wsdl_soap_binding_header(sdlCtx * ctx,xmlNodePtr header,char * wsdl_soap_namespace,int fault)449 static sdlSoapBindingFunctionHeaderPtr wsdl_soap_binding_header(sdlCtx* ctx, xmlNodePtr header, char* wsdl_soap_namespace, int fault)
450 {
451 	xmlAttrPtr tmp;
452 	xmlNodePtr *message, part;
453 	char *ctype;
454 	sdlSoapBindingFunctionHeaderPtr h;
455 
456 	tmp = get_attribute(header->properties, "message");
457 	if (!tmp) {
458 		soap_error0(E_ERROR, "Parsing WSDL: Missing message attribute for <header>");
459 	}
460 
461 	ctype = strrchr((char*)tmp->children->content,':');
462 	if (ctype == NULL) {
463 		ctype = (char*)tmp->children->content;
464 	} else {
465 		++ctype;
466 	}
467 	if (zend_hash_find(&ctx->messages, ctype, strlen(ctype)+1, (void**)&message) != SUCCESS) {
468 		soap_error1(E_ERROR, "Parsing WSDL: Missing <message> with name '%s'", tmp->children->content);
469 	}
470 
471 	tmp = get_attribute(header->properties, "part");
472 	if (!tmp) {
473 		soap_error0(E_ERROR, "Parsing WSDL: Missing part attribute for <header>");
474 	}
475 	part = get_node_with_attribute_ex((*message)->children, "part", WSDL_NAMESPACE, "name", (char*)tmp->children->content, NULL);
476 	if (!part) {
477 		soap_error1(E_ERROR, "Parsing WSDL: Missing part '%s' in <message>", tmp->children->content);
478 	}
479 
480 	h = emalloc(sizeof(sdlSoapBindingFunctionHeader));
481 	memset(h, 0, sizeof(sdlSoapBindingFunctionHeader));
482 	h->name = estrdup((char*)tmp->children->content);
483 
484 	tmp = get_attribute(header->properties, "use");
485 	if (tmp && !strncmp((char*)tmp->children->content, "encoded", sizeof("encoded"))) {
486 		h->use = SOAP_ENCODED;
487 	} else {
488 		h->use = SOAP_LITERAL;
489 	}
490 
491 	tmp = get_attribute(header->properties, "namespace");
492 	if (tmp) {
493 		h->ns = estrdup((char*)tmp->children->content);
494 	}
495 
496 	if (h->use == SOAP_ENCODED) {
497 		tmp = get_attribute(header->properties, "encodingStyle");
498 		if (tmp) {
499 			if (strncmp((char*)tmp->children->content, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) {
500 				h->encodingStyle = SOAP_ENCODING_1_1;
501 			} else if (strncmp((char*)tmp->children->content, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) {
502 				h->encodingStyle = SOAP_ENCODING_1_2;
503 			} else {
504 				soap_error1(E_ERROR, "Parsing WSDL: Unknown encodingStyle '%s'", tmp->children->content);
505 			}
506 		} else {
507 			soap_error0(E_ERROR, "Parsing WSDL: Unspecified encodingStyle");
508 		}
509 	}
510 
511 	tmp = get_attribute(part->properties, "type");
512 	if (tmp != NULL) {
513 		h->encode = get_encoder_from_prefix(ctx->sdl, part, tmp->children->content);
514 	} else {
515 		tmp = get_attribute(part->properties, "element");
516 		if (tmp != NULL) {
517 			h->element = get_element(ctx->sdl, part, tmp->children->content);
518 			if (h->element) {
519 				h->encode = h->element->encode;
520 				if (!h->ns && h->element->namens) {
521 					h->ns = estrdup(h->element->namens);
522 				}
523 				if (h->element->name) {
524 					efree(h->name);
525 					h->name = estrdup(h->element->name);
526 				}
527 			}
528 		}
529 	}
530 	if (!fault) {
531 		xmlNodePtr trav = header->children;
532 		while (trav != NULL) {
533 			if (node_is_equal_ex(trav, "headerfault", wsdl_soap_namespace)) {
534 				sdlSoapBindingFunctionHeaderPtr hf = wsdl_soap_binding_header(ctx, trav, wsdl_soap_namespace, 1);
535 				smart_str key = {0};
536 
537 				if (h->headerfaults == NULL) {
538 					h->headerfaults = emalloc(sizeof(HashTable));
539 					zend_hash_init(h->headerfaults, 0, NULL, delete_header, 0);
540 				}
541 
542 				if (hf->ns) {
543 					smart_str_appends(&key,hf->ns);
544 					smart_str_appendc(&key,':');
545 				}
546 				smart_str_appends(&key,hf->name);
547 				smart_str_0(&key);
548 				if (zend_hash_add(h->headerfaults, key.c, key.len+1, (void**)&hf, sizeof(sdlSoapBindingFunctionHeaderPtr), NULL) != SUCCESS) {
549 					delete_header((void**)&hf);
550 				}
551 				smart_str_free(&key);
552 			} else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
553 				soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
554 			}
555 			trav = trav->next;
556 		}
557 	}
558 	return h;
559 }
560 
wsdl_soap_binding_body(sdlCtx * ctx,xmlNodePtr node,char * wsdl_soap_namespace,sdlSoapBindingFunctionBody * binding,HashTable * params)561 static void wsdl_soap_binding_body(sdlCtx* ctx, xmlNodePtr node, char* wsdl_soap_namespace, sdlSoapBindingFunctionBody *binding, HashTable* params)
562 {
563 	xmlNodePtr body, trav;
564 	xmlAttrPtr tmp;
565 
566 	trav = node->children;
567 	while (trav != NULL) {
568 		if (node_is_equal_ex(trav, "body", wsdl_soap_namespace)) {
569 			body = trav;
570 
571 			tmp = get_attribute(body->properties, "use");
572 			if (tmp && !strncmp((char*)tmp->children->content, "literal", sizeof("literal"))) {
573 				binding->use = SOAP_LITERAL;
574 			} else {
575 				binding->use = SOAP_ENCODED;
576 			}
577 
578 			tmp = get_attribute(body->properties, "namespace");
579 			if (tmp) {
580 				binding->ns = estrdup((char*)tmp->children->content);
581 			}
582 
583 			tmp = get_attribute(body->properties, "parts");
584 			if (tmp) {
585 				HashTable    ht;
586 				char *parts = (char*)tmp->children->content;
587 
588 				/* Delete all parts those are not in the "parts" attribute */
589 				zend_hash_init(&ht, 0, NULL, delete_parameter, 0);
590 				while (*parts) {
591 					HashPosition pos;
592 					sdlParamPtr *param;
593 					int found = 0;
594 					char *end;
595 
596 					while (*parts == ' ') ++parts;
597 					if (*parts == '\0') break;
598 					end = strchr(parts, ' ');
599 					if (end) *end = '\0';
600 					zend_hash_internal_pointer_reset_ex(params, &pos);
601 					while (zend_hash_get_current_data_ex(params, (void **)&param, &pos) != FAILURE) {
602 						if ((*param)->paramName &&
603 						    strcmp(parts, (*param)->paramName) == 0) {
604 					  	sdlParamPtr x_param;
605 					  	x_param = emalloc(sizeof(sdlParam));
606 					  	*x_param = **param;
607 					  	(*param)->paramName = NULL;
608 					  	zend_hash_next_index_insert(&ht, &x_param, sizeof(sdlParamPtr), NULL);
609 					  	found = 1;
610 					  	break;
611 						}
612 						zend_hash_move_forward_ex(params, &pos);
613 					}
614 					if (!found) {
615 						soap_error1(E_ERROR, "Parsing WSDL: Missing part '%s' in <message>", parts);
616 					}
617 					parts += strlen(parts);
618 					if (end) *end = ' ';
619 				}
620 				zend_hash_destroy(params);
621 				*params = ht;
622 			}
623 
624 			if (binding->use == SOAP_ENCODED) {
625 				tmp = get_attribute(body->properties, "encodingStyle");
626 				if (tmp) {
627 					if (strncmp((char*)tmp->children->content, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) {
628 						binding->encodingStyle = SOAP_ENCODING_1_1;
629 					} else if (strncmp((char*)tmp->children->content, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) {
630 						binding->encodingStyle = SOAP_ENCODING_1_2;
631 					} else {
632 						soap_error1(E_ERROR, "Parsing WSDL: Unknown encodingStyle '%s'", tmp->children->content);
633 					}
634 				} else {
635 					soap_error0(E_ERROR, "Parsing WSDL: Unspecified encodingStyle");
636 				}
637 			}
638 		} else if (node_is_equal_ex(trav, "header", wsdl_soap_namespace)) {
639 			sdlSoapBindingFunctionHeaderPtr h = wsdl_soap_binding_header(ctx, trav, wsdl_soap_namespace, 0);
640 			smart_str key = {0};
641 
642 			if (binding->headers == NULL) {
643 				binding->headers = emalloc(sizeof(HashTable));
644 				zend_hash_init(binding->headers, 0, NULL, delete_header, 0);
645 			}
646 
647 			if (h->ns) {
648 				smart_str_appends(&key,h->ns);
649 				smart_str_appendc(&key,':');
650 			}
651 			smart_str_appends(&key,h->name);
652 			smart_str_0(&key);
653 			if (zend_hash_add(binding->headers, key.c, key.len+1, (void**)&h, sizeof(sdlSoapBindingFunctionHeaderPtr), NULL) != SUCCESS) {
654 				delete_header((void**)&h);
655 			}
656 			smart_str_free(&key);
657 		} else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
658 			soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
659 		}
660 		trav = trav->next;
661 	}
662 }
663 
wsdl_message(sdlCtx * ctx,xmlChar * message_name)664 static HashTable* wsdl_message(sdlCtx *ctx, xmlChar* message_name)
665 {
666 	xmlNodePtr trav, part, message = NULL, *tmp;
667 	HashTable* parameters = NULL;
668 	char *ctype;
669 
670 	ctype = strrchr((char*)message_name,':');
671 	if (ctype == NULL) {
672 		ctype = (char*)message_name;
673 	} else {
674 		++ctype;
675 	}
676 	if (zend_hash_find(&ctx->messages, ctype, strlen(ctype)+1, (void**)&tmp) != SUCCESS) {
677 		soap_error1(E_ERROR, "Parsing WSDL: Missing <message> with name '%s'", message_name);
678 	}
679 	message = *tmp;
680 
681 	parameters = emalloc(sizeof(HashTable));
682 	zend_hash_init(parameters, 0, NULL, delete_parameter, 0);
683 
684 	trav = message->children;
685 	while (trav != NULL) {
686 		xmlAttrPtr element, type, name;
687 		sdlParamPtr param;
688 
689 		if (trav->ns != NULL && strcmp((char*)trav->ns->href, WSDL_NAMESPACE) != 0) {
690 			soap_error1(E_ERROR, "Parsing WSDL: Unexpected extensibility element <%s>", trav->name);
691 		}
692 		if (node_is_equal(trav,"documentation")) {
693 			trav = trav->next;
694 			continue;
695 		}
696 		if (!node_is_equal(trav,"part")) {
697 			soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
698 		}
699 		part = trav;
700 		param = emalloc(sizeof(sdlParam));
701 		memset(param,0,sizeof(sdlParam));
702 		param->order = 0;
703 
704 		name = get_attribute(part->properties, "name");
705 		if (name == NULL) {
706 			soap_error1(E_ERROR, "Parsing WSDL: No name associated with <part> '%s'", message->name);
707 		}
708 
709 		param->paramName = estrdup((char*)name->children->content);
710 
711 		type = get_attribute(part->properties, "type");
712 		if (type != NULL) {
713 			param->encode = get_encoder_from_prefix(ctx->sdl, part, type->children->content);
714 		} else {
715 			element = get_attribute(part->properties, "element");
716 			if (element != NULL) {
717 				param->element = get_element(ctx->sdl, part, element->children->content);
718 				if (param->element) {
719 					param->encode = param->element->encode;
720 				}
721 			}
722 		}
723 
724 		zend_hash_next_index_insert(parameters, &param, sizeof(sdlParamPtr), NULL);
725 
726 		trav = trav->next;
727 	}
728 	return parameters;
729 }
730 
load_wsdl(zval * this_ptr,char * struri TSRMLS_DC)731 static sdlPtr load_wsdl(zval *this_ptr, char *struri TSRMLS_DC)
732 {
733 	sdlCtx ctx;
734 	int i,n;
735 
736 	memset(&ctx,0,sizeof(ctx));
737 	ctx.sdl = emalloc(sizeof(sdl));
738 	memset(ctx.sdl, 0, sizeof(sdl));
739 	ctx.sdl->source = estrdup(struri);
740 	zend_hash_init(&ctx.sdl->functions, 0, NULL, delete_function, 0);
741 
742 	zend_hash_init(&ctx.docs, 0, NULL, delete_document, 0);
743 	zend_hash_init(&ctx.messages, 0, NULL, NULL, 0);
744 	zend_hash_init(&ctx.bindings, 0, NULL, NULL, 0);
745 	zend_hash_init(&ctx.portTypes, 0, NULL, NULL, 0);
746 	zend_hash_init(&ctx.services,  0, NULL, NULL, 0);
747 
748 	load_wsdl_ex(this_ptr, struri,&ctx, 0 TSRMLS_CC);
749 	schema_pass2(&ctx);
750 
751 	n = zend_hash_num_elements(&ctx.services);
752 	if (n > 0) {
753 		zend_hash_internal_pointer_reset(&ctx.services);
754 		for (i = 0; i < n; i++) {
755 			xmlNodePtr *tmp, service;
756 			xmlNodePtr trav, port;
757 			int has_soap_port = 0;
758 
759 			zend_hash_get_current_data(&ctx.services, (void **)&tmp);
760 			service = *tmp;
761 
762 			trav = service->children;
763 			while (trav != NULL) {
764 				xmlAttrPtr type, name, bindingAttr, location;
765 				xmlNodePtr portType, operation;
766 				xmlNodePtr address, binding, trav2;
767 				char *ctype;
768 				sdlBindingPtr tmpbinding;
769 				char *wsdl_soap_namespace = NULL;
770 
771 				if (!is_wsdl_element(trav) || node_is_equal(trav,"documentation")) {
772 					trav = trav->next;
773 					continue;
774 				}
775 				if (!node_is_equal(trav,"port")) {
776 					soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
777 				}
778 
779 				port = trav;
780 
781 				tmpbinding = emalloc(sizeof(sdlBinding));
782 				memset(tmpbinding, 0, sizeof(sdlBinding));
783 
784 				bindingAttr = get_attribute(port->properties, "binding");
785 				if (bindingAttr == NULL) {
786 					soap_error0(E_ERROR, "Parsing WSDL: No binding associated with <port>");
787 				}
788 
789 				/* find address and figure out binding type */
790 				address = NULL;
791 				trav2 = port->children;
792 				while (trav2 != NULL) {
793 					if (node_is_equal(trav2,"address") && trav2->ns) {
794 						if (!strncmp((char*)trav2->ns->href, WSDL_SOAP11_NAMESPACE, sizeof(WSDL_SOAP11_NAMESPACE))) {
795 							address = trav2;
796 							wsdl_soap_namespace = WSDL_SOAP11_NAMESPACE;
797 							tmpbinding->bindingType = BINDING_SOAP;
798 						} else if (!strncmp((char*)trav2->ns->href, WSDL_SOAP12_NAMESPACE, sizeof(WSDL_SOAP12_NAMESPACE))) {
799 							address = trav2;
800 							wsdl_soap_namespace = WSDL_SOAP12_NAMESPACE;
801 							tmpbinding->bindingType = BINDING_SOAP;
802 						} else if (!strncmp((char*)trav2->ns->href, RPC_SOAP12_NAMESPACE, sizeof(RPC_SOAP12_NAMESPACE))) {
803 							address = trav2;
804 							wsdl_soap_namespace = RPC_SOAP12_NAMESPACE;
805 							tmpbinding->bindingType = BINDING_SOAP;
806 						} else if (!strncmp((char*)trav2->ns->href, WSDL_HTTP11_NAMESPACE, sizeof(WSDL_HTTP11_NAMESPACE))) {
807 							address = trav2;
808 							tmpbinding->bindingType = BINDING_HTTP;
809 						} else if (!strncmp((char*)trav2->ns->href, WSDL_HTTP12_NAMESPACE, sizeof(WSDL_HTTP12_NAMESPACE))) {
810 							address = trav2;
811 							tmpbinding->bindingType = BINDING_HTTP;
812 						}
813 					}
814 					if (trav2 != address && is_wsdl_element(trav2) && !node_is_equal(trav2,"documentation")) {
815 						soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
816 					}
817 				  trav2 = trav2->next;
818 				}
819 				if (!address || tmpbinding->bindingType == BINDING_HTTP) {
820 					if (has_soap_port || trav->next || i < n-1) {
821 						efree(tmpbinding);
822 						trav = trav->next;
823 						continue;
824 					} else if (!address) {
825 						soap_error0(E_ERROR, "Parsing WSDL: No address associated with <port>");
826 					}
827 				}
828 				has_soap_port = 1;
829 
830 				location = get_attribute(address->properties, "location");
831 				if (!location) {
832 					soap_error0(E_ERROR, "Parsing WSDL: No location associated with <port>");
833 				}
834 
835 				tmpbinding->location = estrdup((char*)location->children->content);
836 
837 				ctype = strrchr((char*)bindingAttr->children->content,':');
838 				if (ctype == NULL) {
839 					ctype = (char*)bindingAttr->children->content;
840 				} else {
841 					++ctype;
842 				}
843 				if (zend_hash_find(&ctx.bindings, ctype, strlen(ctype)+1, (void*)&tmp) != SUCCESS) {
844 					soap_error1(E_ERROR, "Parsing WSDL: No <binding> element with name '%s'", ctype);
845 				}
846 				binding = *tmp;
847 
848 				if (tmpbinding->bindingType == BINDING_SOAP) {
849 					sdlSoapBindingPtr soapBinding;
850 					xmlNodePtr soapBindingNode;
851 					xmlAttrPtr tmp;
852 
853 					soapBinding = emalloc(sizeof(sdlSoapBinding));
854 					memset(soapBinding, 0, sizeof(sdlSoapBinding));
855 					soapBinding->style = SOAP_DOCUMENT;
856 
857 					soapBindingNode = get_node_ex(binding->children, "binding", wsdl_soap_namespace);
858 					if (soapBindingNode) {
859 						tmp = get_attribute(soapBindingNode->properties, "style");
860 						if (tmp && !strncmp((char*)tmp->children->content, "rpc", sizeof("rpc"))) {
861 							soapBinding->style = SOAP_RPC;
862 						}
863 
864 						tmp = get_attribute(soapBindingNode->properties, "transport");
865 						if (tmp) {
866 							if (strncmp((char*)tmp->children->content, WSDL_HTTP_TRANSPORT, sizeof(WSDL_HTTP_TRANSPORT)) == 0) {
867 								soapBinding->transport = SOAP_TRANSPORT_HTTP;
868 							} else {
869 								/* try the next binding */
870 								efree(soapBinding);
871 								efree(tmpbinding->location);
872 								efree(tmpbinding);
873 								trav = trav->next;
874 								continue;
875 							}
876 						}
877 					}
878 					tmpbinding->bindingAttributes = (void *)soapBinding;
879 				}
880 
881 				name = get_attribute(binding->properties, "name");
882 				if (name == NULL) {
883 					soap_error0(E_ERROR, "Parsing WSDL: Missing 'name' attribute for <binding>");
884 				}
885 				tmpbinding->name = estrdup((char*)name->children->content);
886 
887 				type = get_attribute(binding->properties, "type");
888 				if (type == NULL) {
889 					soap_error0(E_ERROR, "Parsing WSDL: Missing 'type' attribute for <binding>");
890 				}
891 
892 				ctype = strrchr((char*)type->children->content,':');
893 				if (ctype == NULL) {
894 					ctype = (char*)type->children->content;
895 				} else {
896 					++ctype;
897 				}
898 				if (zend_hash_find(&ctx.portTypes, ctype, strlen(ctype)+1, (void**)&tmp) != SUCCESS) {
899 					soap_error1(E_ERROR, "Parsing WSDL: Missing <portType> with name '%s'", name->children->content);
900 				}
901 				portType = *tmp;
902 
903 				trav2 = binding->children;
904 				while (trav2 != NULL) {
905 					sdlFunctionPtr function;
906 					xmlNodePtr input, output, fault, portTypeOperation, trav3;
907 					xmlAttrPtr op_name, paramOrder;
908 
909 					if ((tmpbinding->bindingType == BINDING_SOAP &&
910 					    node_is_equal_ex(trav2, "binding", wsdl_soap_namespace)) ||
911 					    !is_wsdl_element(trav2) ||
912 					    node_is_equal(trav2,"documentation")) {
913 						trav2 = trav2->next;
914 						continue;
915 					}
916 					if (!node_is_equal(trav2,"operation")) {
917 						soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
918 					}
919 
920 					operation = trav2;
921 
922 					op_name = get_attribute(operation->properties, "name");
923 					if (op_name == NULL) {
924 						soap_error0(E_ERROR, "Parsing WSDL: Missing 'name' attribute for <operation>");
925 					}
926 
927 					trav3 = operation->children;
928 					while  (trav3 != NULL) {
929 						if (tmpbinding->bindingType == BINDING_SOAP &&
930 						    node_is_equal_ex(trav3, "operation", wsdl_soap_namespace)) {
931 						} else if (is_wsdl_element(trav3) &&
932 						           !node_is_equal(trav3,"input") &&
933 						           !node_is_equal(trav3,"output") &&
934 						           !node_is_equal(trav3,"fault") &&
935 						           !node_is_equal(trav3,"documentation")) {
936 							soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav3->name);
937 						}
938 						trav3 = trav3->next;
939 					}
940 
941 					portTypeOperation = get_node_with_attribute_ex(portType->children, "operation", WSDL_NAMESPACE, "name", (char*)op_name->children->content, NULL);
942 					if (portTypeOperation == NULL) {
943 						soap_error1(E_ERROR, "Parsing WSDL: Missing <portType>/<operation> with name '%s'", op_name->children->content);
944 					}
945 
946 					function = emalloc(sizeof(sdlFunction));
947 					memset(function, 0, sizeof(sdlFunction));
948 					function->functionName = estrdup((char*)op_name->children->content);
949 
950 					if (tmpbinding->bindingType == BINDING_SOAP) {
951 						sdlSoapBindingFunctionPtr soapFunctionBinding;
952 						sdlSoapBindingPtr soapBinding;
953 						xmlNodePtr soapOperation;
954 						xmlAttrPtr tmp;
955 
956 						soapFunctionBinding = emalloc(sizeof(sdlSoapBindingFunction));
957 						memset(soapFunctionBinding, 0, sizeof(sdlSoapBindingFunction));
958 						soapBinding = (sdlSoapBindingPtr)tmpbinding->bindingAttributes;
959 						soapFunctionBinding->style = soapBinding->style;
960 
961 						soapOperation = get_node_ex(operation->children, "operation", wsdl_soap_namespace);
962 						if (soapOperation) {
963 							tmp = get_attribute(soapOperation->properties, "soapAction");
964 							if (tmp) {
965 								soapFunctionBinding->soapAction = estrdup((char*)tmp->children->content);
966 							}
967 
968 							tmp = get_attribute(soapOperation->properties, "style");
969 							if (tmp) {
970 								if (!strncmp((char*)tmp->children->content, "rpc", sizeof("rpc"))) {
971 									soapFunctionBinding->style = SOAP_RPC;
972 								} else {
973 									soapFunctionBinding->style = SOAP_DOCUMENT;
974 								}
975 							} else {
976 								soapFunctionBinding->style = soapBinding->style;
977 							}
978 						}
979 
980 						function->bindingAttributes = (void *)soapFunctionBinding;
981 					}
982 
983 					input = get_node_ex(portTypeOperation->children, "input", WSDL_NAMESPACE);
984 					if (input != NULL) {
985 						xmlAttrPtr message, name;
986 
987 						message = get_attribute(input->properties, "message");
988 						if (message == NULL) {
989 							soap_error1(E_ERROR, "Parsing WSDL: Missing name for <input> of '%s'", op_name->children->content);
990 						}
991 						function->requestParameters = wsdl_message(&ctx, message->children->content);
992 
993 						name = get_attribute(input->properties, "name");
994 /* FIXME
995 						if (name != NULL) {
996 							function->requestName = estrdup(name->children->content);
997 						} else {
998 */
999 						{
1000 							function->requestName = estrdup(function->functionName);
1001 						}
1002 
1003 						if (tmpbinding->bindingType == BINDING_SOAP) {
1004 							input = get_node_ex(operation->children, "input", WSDL_NAMESPACE);
1005 							if (input != NULL) {
1006 								sdlSoapBindingFunctionPtr soapFunctionBinding = function->bindingAttributes;
1007 								wsdl_soap_binding_body(&ctx, input, wsdl_soap_namespace, &soapFunctionBinding->input, function->requestParameters);
1008 							}
1009 						}
1010 					}
1011 
1012 					output = get_node_ex(portTypeOperation->children, "output", WSDL_NAMESPACE);
1013 					if (output != NULL) {
1014 						xmlAttrPtr message, name;
1015 
1016 						message = get_attribute(output->properties, "message");
1017 						if (message == NULL) {
1018 							soap_error1(E_ERROR, "Parsing WSDL: Missing name for <output> of '%s'", op_name->children->content);
1019 						}
1020 						function->responseParameters = wsdl_message(&ctx, message->children->content);
1021 
1022 						name = get_attribute(output->properties, "name");
1023 /* FIXME
1024 						if (name != NULL) {
1025 							function->responseName = estrdup(name->children->content);
1026 						} else if (input == NULL) {
1027 							function->responseName = estrdup(function->functionName);
1028 						} else {
1029 */
1030 						{
1031 							int len = strlen(function->functionName);
1032 							function->responseName = emalloc(len + sizeof("Response"));
1033 							memcpy(function->responseName, function->functionName, len);
1034 							memcpy(function->responseName+len, "Response", sizeof("Response"));
1035 						}
1036 
1037 						if (tmpbinding->bindingType == BINDING_SOAP) {
1038 							output = get_node_ex(operation->children, "output", WSDL_NAMESPACE);
1039 							if (output != NULL) {
1040 								sdlSoapBindingFunctionPtr soapFunctionBinding = function->bindingAttributes;
1041 								wsdl_soap_binding_body(&ctx, output, wsdl_soap_namespace, &soapFunctionBinding->output, function->responseParameters);
1042 							}
1043 						}
1044 					}
1045 
1046 					paramOrder = get_attribute(portTypeOperation->properties, "parameterOrder");
1047 					if (paramOrder) {
1048 						/* FIXME: */
1049 					}
1050 
1051 					fault = portTypeOperation->children;
1052 					while (fault != NULL) {
1053 						if (node_is_equal_ex(fault, "fault", WSDL_NAMESPACE)) {
1054 							xmlAttrPtr message, name;
1055 							sdlFaultPtr f;
1056 
1057 							name = get_attribute(fault->properties, "name");
1058 							if (name == NULL) {
1059 								soap_error1(E_ERROR, "Parsing WSDL: Missing name for <fault> of '%s'", op_name->children->content);
1060 							}
1061 							message = get_attribute(fault->properties, "message");
1062 							if (message == NULL) {
1063 								soap_error1(E_ERROR, "Parsing WSDL: Missing name for <output> of '%s'", op_name->children->content);
1064 							}
1065 
1066 							f = emalloc(sizeof(sdlFault));
1067 							memset(f, 0, sizeof(sdlFault));
1068 
1069 							f->name = estrdup((char*)name->children->content);
1070 							f->details = wsdl_message(&ctx, message->children->content);
1071 							if (f->details == NULL || zend_hash_num_elements(f->details) > 1) {
1072 								soap_error1(E_ERROR, "Parsing WSDL: The fault message '%s' must have a single part", message->children->content);
1073 							}
1074 
1075 							if (tmpbinding->bindingType == BINDING_SOAP) {
1076 								xmlNodePtr soap_fault = get_node_with_attribute_ex(operation->children, "fault", WSDL_NAMESPACE, "name", f->name, NULL);
1077 								if (soap_fault != NULL) {
1078 									xmlNodePtr trav = soap_fault->children;
1079 									while (trav != NULL) {
1080 										if (node_is_equal_ex(trav, "fault", wsdl_soap_namespace)) {
1081 											xmlAttrPtr tmp;
1082 										  sdlSoapBindingFunctionFaultPtr binding;
1083 
1084 											binding = f->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunctionFault));
1085 											memset(f->bindingAttributes, 0, sizeof(sdlSoapBindingFunctionFault));
1086 
1087 											tmp = get_attribute(trav->properties, "use");
1088 											if (tmp && !strncmp((char*)tmp->children->content, "encoded", sizeof("encoded"))) {
1089 												binding->use = SOAP_ENCODED;
1090 											} else {
1091 												binding->use = SOAP_LITERAL;
1092 											}
1093 
1094 											tmp = get_attribute(trav->properties, "namespace");
1095 											if (tmp) {
1096 												binding->ns = estrdup((char*)tmp->children->content);
1097 											}
1098 
1099 											if (binding->use == SOAP_ENCODED) {
1100 												tmp = get_attribute(trav->properties, "encodingStyle");
1101 												if (tmp) {
1102 													if (strncmp((char*)tmp->children->content, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) {
1103 														binding->encodingStyle = SOAP_ENCODING_1_1;
1104 													} else if (strncmp((char*)tmp->children->content, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) {
1105 														binding->encodingStyle = SOAP_ENCODING_1_2;
1106 													} else {
1107 														soap_error1(E_ERROR, "Parsing WSDL: Unknown encodingStyle '%s'", tmp->children->content);
1108 													}
1109 												} else {
1110 													soap_error0(E_ERROR, "Parsing WSDL: Unspecified encodingStyle");
1111 												}
1112 											}
1113 										} else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
1114 											soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
1115 										}
1116 										trav = trav->next;
1117 									}
1118 								}
1119 							}
1120 							if (function->faults == NULL) {
1121 								function->faults = emalloc(sizeof(HashTable));
1122 								zend_hash_init(function->faults, 0, NULL, delete_fault, 0);
1123 							}
1124 							if (zend_hash_add(function->faults, f->name, strlen(f->name)+1, (void**)&f, sizeof(sdlFaultPtr), NULL) != SUCCESS) {
1125 								soap_error2(E_ERROR, "Parsing WSDL: <fault> with name '%s' already defined in '%s'", f->name, op_name->children->content);
1126 							}
1127 						}
1128 						fault = fault->next;
1129 					}
1130 
1131 					function->binding = tmpbinding;
1132 
1133 					{
1134 						char *tmp = estrdup(function->functionName);
1135 						int  len = strlen(tmp);
1136 
1137 						if (zend_hash_add(&ctx.sdl->functions, php_strtolower(tmp, len), len+1, &function, sizeof(sdlFunctionPtr), NULL) != SUCCESS) {
1138 							zend_hash_next_index_insert(&ctx.sdl->functions, &function, sizeof(sdlFunctionPtr), NULL);
1139 						}
1140 						efree(tmp);
1141 						if (function->requestName != NULL && strcmp(function->requestName,function->functionName) != 0) {
1142 							if (ctx.sdl->requests == NULL) {
1143 								ctx.sdl->requests = emalloc(sizeof(HashTable));
1144 								zend_hash_init(ctx.sdl->requests, 0, NULL, NULL, 0);
1145 							}
1146 							tmp = estrdup(function->requestName);
1147 							len = strlen(tmp);
1148 							zend_hash_add(ctx.sdl->requests, php_strtolower(tmp, len), len+1, &function, sizeof(sdlFunctionPtr), NULL);
1149 							efree(tmp);
1150 						}
1151 					}
1152 					trav2 = trav2->next;
1153 				}
1154 
1155 				if (!ctx.sdl->bindings) {
1156 					ctx.sdl->bindings = emalloc(sizeof(HashTable));
1157 					zend_hash_init(ctx.sdl->bindings, 0, NULL, delete_binding, 0);
1158 				}
1159 
1160 				if (zend_hash_add(ctx.sdl->bindings, tmpbinding->name, strlen(tmpbinding->name), &tmpbinding, sizeof(sdlBindingPtr), NULL) != SUCCESS) {
1161 					zend_hash_next_index_insert(ctx.sdl->bindings, &tmpbinding, sizeof(sdlBindingPtr), NULL);
1162 				}
1163 				trav= trav->next;
1164 			}
1165 
1166 			zend_hash_move_forward(&ctx.services);
1167 		}
1168 	} else {
1169 		soap_error0(E_ERROR, "Parsing WSDL: Couldn't bind to service");
1170 	}
1171 
1172 	if (ctx.sdl->bindings == NULL || ctx.sdl->bindings->nNumOfElements == 0) {
1173 		soap_error0(E_ERROR, "Parsing WSDL: Could not find any usable binding services in WSDL.");
1174 	}
1175 
1176 	zend_hash_destroy(&ctx.messages);
1177 	zend_hash_destroy(&ctx.bindings);
1178 	zend_hash_destroy(&ctx.portTypes);
1179 	zend_hash_destroy(&ctx.services);
1180 	zend_hash_destroy(&ctx.docs);
1181 
1182 	return ctx.sdl;
1183 }
1184 
1185 #define WSDL_CACHE_VERSION 0x0e
1186 
1187 #define WSDL_CACHE_GET(ret,type,buf)   memcpy(&ret,*buf,sizeof(type)); *buf += sizeof(type);
1188 #define WSDL_CACHE_GET_INT(ret,buf)    ret = ((unsigned char)(*buf)[0])|((unsigned char)(*buf)[1]<<8)|((unsigned char)(*buf)[2]<<16)|((int)(*buf)[3]<<24); *buf += 4;
1189 #define WSDL_CACHE_GET_1(ret,type,buf) ret = (type)(**buf); (*buf)++;
1190 #define WSDL_CACHE_GET_N(ret,n,buf)    memcpy(ret,*buf,n); *buf += n;
1191 #define WSDL_CACHE_SKIP(n,buf)         *buf += n;
1192 
1193 #define WSDL_CACHE_PUT_INT(val,buf)    smart_str_appendc(buf,val & 0xff); \
1194                                        smart_str_appendc(buf,(val >> 8) & 0xff); \
1195                                        smart_str_appendc(buf,(val >> 16) & 0xff); \
1196                                        smart_str_appendc(buf,(val >> 24) & 0xff);
1197 #define WSDL_CACHE_PUT_1(val,buf)      smart_str_appendc(buf,val);
1198 #define WSDL_CACHE_PUT_N(val,n,buf)    smart_str_appendl(buf,(char*)val,n);
1199 
sdl_deserialize_string(char ** in)1200 static char* sdl_deserialize_string(char **in)
1201 {
1202 	char *s;
1203 	int len;
1204 
1205 	WSDL_CACHE_GET_INT(len, in);
1206 	if (len == 0x7fffffff) {
1207 		return NULL;
1208 	} else {
1209 		s = emalloc(len+1);
1210 		WSDL_CACHE_GET_N(s, len, in);
1211 		s[len] = '\0';
1212 		return s;
1213 	}
1214 }
1215 
sdl_deserialize_key(HashTable * ht,void * data,char ** in)1216 static void sdl_deserialize_key(HashTable* ht, void* data, char **in)
1217 {
1218 	int len;
1219 
1220 	WSDL_CACHE_GET_INT(len, in);
1221 	if (len == 0) {
1222 		zend_hash_next_index_insert(ht, &data, sizeof(void*), NULL);
1223 	} else {
1224 		zend_hash_add(ht, *in, len, &data, sizeof(void*), NULL);
1225 		WSDL_CACHE_SKIP(len, in);
1226 	}
1227 }
1228 
sdl_deserialize_attribute(sdlAttributePtr attr,encodePtr * encoders,char ** in)1229 static void sdl_deserialize_attribute(sdlAttributePtr attr, encodePtr *encoders, char **in)
1230 {
1231 	int i;
1232 
1233 	attr->name = sdl_deserialize_string(in);
1234 	attr->namens = sdl_deserialize_string(in);
1235 	attr->ref = sdl_deserialize_string(in);
1236 	attr->def = sdl_deserialize_string(in);
1237 	attr->fixed = sdl_deserialize_string(in);
1238 	WSDL_CACHE_GET_1(attr->form, sdlForm, in);
1239 	WSDL_CACHE_GET_1(attr->use, sdlUse, in);
1240 	WSDL_CACHE_GET_INT(i, in);
1241 	attr->encode = encoders[i];
1242 	WSDL_CACHE_GET_INT(i, in);
1243 	if (i > 0) {
1244 		attr->extraAttributes = emalloc(sizeof(HashTable));
1245 		zend_hash_init(attr->extraAttributes, i, NULL, delete_extra_attribute, 0);
1246 		while (i > 0) {
1247 			sdlExtraAttributePtr x = emalloc(sizeof(sdlExtraAttribute));
1248 			sdl_deserialize_key(attr->extraAttributes, x, in);
1249 			x->ns = sdl_deserialize_string(in);
1250 			x->val = sdl_deserialize_string(in);
1251 			--i;
1252 		}
1253 	}
1254 }
1255 
sdl_deserialize_resriction_int(char ** in)1256 static sdlRestrictionIntPtr sdl_deserialize_resriction_int(char **in)
1257 {
1258 	if (**in == 1) {
1259 		sdlRestrictionIntPtr x = emalloc(sizeof(sdlRestrictionInt));
1260 		WSDL_CACHE_SKIP(1, in);
1261 		WSDL_CACHE_GET_INT(x->value, in);
1262 		WSDL_CACHE_GET_1(x->fixed, char, in);
1263 		return x;
1264 	} else {
1265 		WSDL_CACHE_SKIP(1, in);
1266 		return NULL;
1267 	}
1268 }
1269 
sdl_deserialize_resriction_char(char ** in)1270 static sdlRestrictionCharPtr sdl_deserialize_resriction_char(char **in)
1271 {
1272 	if (**in == 1) {
1273 		sdlRestrictionCharPtr x = emalloc(sizeof(sdlRestrictionChar));
1274 		WSDL_CACHE_SKIP(1, in);
1275 		x->value = sdl_deserialize_string(in);
1276 		WSDL_CACHE_GET_1(x->fixed, char, in);
1277 		return x;
1278 	} else {
1279 		WSDL_CACHE_SKIP(1, in);
1280 		return NULL;
1281 	}
1282 }
1283 
sdl_deserialize_model(sdlTypePtr * types,sdlTypePtr * elements,char ** in)1284 static sdlContentModelPtr sdl_deserialize_model(sdlTypePtr *types, sdlTypePtr *elements, char **in)
1285 {
1286 	int i;
1287 	sdlContentModelPtr model = emalloc(sizeof(sdlContentModel));
1288 
1289 	WSDL_CACHE_GET_1(model->kind, sdlContentKind, in);
1290 	WSDL_CACHE_GET_INT(model->min_occurs, in);
1291 	WSDL_CACHE_GET_INT(model->max_occurs, in);
1292 	switch (model->kind) {
1293 		case XSD_CONTENT_ELEMENT:
1294 			WSDL_CACHE_GET_INT(i, in);
1295 			model->u.element = elements[i];
1296 			break;
1297 		case XSD_CONTENT_SEQUENCE:
1298 		case XSD_CONTENT_ALL:
1299 		case XSD_CONTENT_CHOICE:
1300 			WSDL_CACHE_GET_INT(i, in);
1301 			model->u.content = emalloc(sizeof(HashTable));
1302 			zend_hash_init(model->u.content, i, NULL, delete_model, 0);
1303 			while (i > 0) {
1304 				sdlContentModelPtr x = sdl_deserialize_model(types, elements, in);
1305 				zend_hash_next_index_insert(model->u.content,&x,sizeof(sdlContentModelPtr),NULL);
1306 				i--;
1307 			}
1308 			break;
1309 		case XSD_CONTENT_GROUP_REF:
1310 			model->u.group_ref = sdl_deserialize_string(in);
1311 			break;
1312 		case XSD_CONTENT_GROUP:
1313 			WSDL_CACHE_GET_INT(i, in);
1314 			model->u.group = types[i];
1315 			break;
1316 		default:
1317 			break;
1318 	}
1319 	return model;
1320 }
1321 
sdl_deserialize_type(sdlTypePtr type,sdlTypePtr * types,encodePtr * encoders,char ** in)1322 static void sdl_deserialize_type(sdlTypePtr type, sdlTypePtr *types, encodePtr *encoders, char **in)
1323 {
1324 	int i;
1325 	sdlTypePtr *elements = NULL;
1326 
1327 	WSDL_CACHE_GET_1(type->kind, sdlTypeKind, in);
1328 	type->name = sdl_deserialize_string(in);
1329 	type->namens = sdl_deserialize_string(in);
1330 	type->def = sdl_deserialize_string(in);
1331 	type->fixed = sdl_deserialize_string(in);
1332 	type->ref = sdl_deserialize_string(in);
1333 	WSDL_CACHE_GET_1(type->nillable, char, in);
1334 	WSDL_CACHE_GET_1(type->form, sdlForm, in);
1335 
1336 	WSDL_CACHE_GET_INT(i, in);
1337 	type->encode = encoders[i];
1338 
1339 	if (**in == 1) {
1340 		WSDL_CACHE_SKIP(1, in);
1341 		type->restrictions = emalloc(sizeof(sdlRestrictions));
1342 		/*memset(type->restrictions, 0, sizeof(sdlRestrictions));*/
1343 		type->restrictions->minExclusive = sdl_deserialize_resriction_int(in);
1344 		type->restrictions->minInclusive = sdl_deserialize_resriction_int(in);
1345 		type->restrictions->maxExclusive = sdl_deserialize_resriction_int(in);
1346 		type->restrictions->maxInclusive = sdl_deserialize_resriction_int(in);
1347 		type->restrictions->totalDigits = sdl_deserialize_resriction_int(in);
1348 		type->restrictions->fractionDigits = sdl_deserialize_resriction_int(in);
1349 		type->restrictions->length = sdl_deserialize_resriction_int(in);
1350 		type->restrictions->minLength = sdl_deserialize_resriction_int(in);
1351 		type->restrictions->maxLength = sdl_deserialize_resriction_int(in);
1352 		type->restrictions->whiteSpace = sdl_deserialize_resriction_char(in);
1353 		type->restrictions->pattern = sdl_deserialize_resriction_char(in);
1354 		WSDL_CACHE_GET_INT(i, in);
1355 		if (i > 0) {
1356 			type->restrictions->enumeration = emalloc(sizeof(HashTable));
1357 			zend_hash_init(type->restrictions->enumeration, i, NULL, delete_restriction_var_char, 0);
1358 			while (i > 0) {
1359 				sdlRestrictionCharPtr x = sdl_deserialize_resriction_char(in);
1360 				sdl_deserialize_key(type->restrictions->enumeration, x, in);
1361 				--i;
1362 			}
1363 		} else {
1364 			type->restrictions->enumeration = NULL;
1365 		}
1366 	} else {
1367 		WSDL_CACHE_SKIP(1, in);
1368 	}
1369 
1370 	WSDL_CACHE_GET_INT(i, in);
1371 	if (i > 0) {
1372 		elements = safe_emalloc((i+1), sizeof(sdlTypePtr), 0);
1373 		elements[0] = NULL;
1374 		type->elements = emalloc(sizeof(HashTable));
1375 		zend_hash_init(type->elements, i, NULL, delete_type, 0);
1376 		while (i > 0) {
1377 			sdlTypePtr t = emalloc(sizeof(sdlType));
1378 			memset(t, 0, sizeof(sdlType));
1379 			sdl_deserialize_key(type->elements, t, in);
1380 			sdl_deserialize_type(t, types, encoders, in);
1381 			elements[i] = t;
1382 			--i;
1383 		}
1384 	}
1385 
1386 	WSDL_CACHE_GET_INT(i, in);
1387 	if (i > 0) {
1388 		type->attributes = emalloc(sizeof(HashTable));
1389 		zend_hash_init(type->attributes, i, NULL, delete_attribute, 0);
1390 		while (i > 0) {
1391 			sdlAttributePtr attr = emalloc(sizeof(sdlAttribute));
1392 			memset(attr, 0, sizeof(sdlAttribute));
1393 			sdl_deserialize_key(type->attributes, attr, in);
1394 			sdl_deserialize_attribute(attr, encoders, in);
1395 			--i;
1396 		}
1397 	}
1398 
1399 	if (**in != 0) {
1400 		WSDL_CACHE_SKIP(1, in);
1401 		type->model = sdl_deserialize_model(types, elements, in);
1402 	} else {
1403 		WSDL_CACHE_SKIP(1, in);
1404 	}
1405 	if (elements != NULL) {
1406 		efree(elements);
1407 	}
1408 }
1409 
sdl_deserialize_encoder(encodePtr enc,sdlTypePtr * types,char ** in)1410 static void sdl_deserialize_encoder(encodePtr enc, sdlTypePtr *types, char **in)
1411 {
1412 	int i;
1413 
1414 	WSDL_CACHE_GET_INT(enc->details.type, in);
1415 	enc->details.type_str = sdl_deserialize_string(in);
1416 	enc->details.ns = sdl_deserialize_string(in);
1417 	WSDL_CACHE_GET_INT(i, in);
1418 	enc->details.sdl_type = types[i];
1419 	enc->to_xml = sdl_guess_convert_xml;
1420 	enc->to_zval = sdl_guess_convert_zval;
1421 
1422 	if (enc->details.sdl_type == NULL) {
1423 		int ns_len = strlen(enc->details.ns);
1424 		int type_len = strlen(enc->details.type_str);
1425 
1426 		if (((ns_len == sizeof(SOAP_1_1_ENC_NAMESPACE)-1 &&
1427 		      memcmp(enc->details.ns, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)-1) == 0) ||
1428 		     (ns_len == sizeof(SOAP_1_2_ENC_NAMESPACE)-1 &&
1429 		      memcmp(enc->details.ns, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)-1) == 0))) {
1430 			char *enc_nscat;
1431 			int enc_ns_len;
1432 			int enc_len;
1433 			encodePtr real_enc;
1434 
1435 			enc_ns_len = sizeof(XSD_NAMESPACE)-1;
1436 			enc_len = enc_ns_len + type_len + 1;
1437 			enc_nscat = emalloc(enc_len + 1);
1438 			memcpy(enc_nscat, XSD_NAMESPACE, sizeof(XSD_NAMESPACE)-1);
1439 			enc_nscat[enc_ns_len] = ':';
1440 			memcpy(enc_nscat+enc_ns_len+1, enc->details.type_str, type_len);
1441 			enc_nscat[enc_len] = '\0';
1442 
1443 			real_enc = get_encoder_ex(NULL, enc_nscat, enc_len);
1444 			efree(enc_nscat);
1445 			if (real_enc) {
1446 				enc->to_zval = real_enc->to_zval;
1447 				enc->to_xml = real_enc->to_xml;
1448 			}
1449 		}
1450 	}
1451 }
1452 
sdl_deserialize_soap_body(sdlSoapBindingFunctionBodyPtr body,encodePtr * encoders,sdlTypePtr * types,char ** in)1453 static void sdl_deserialize_soap_body(sdlSoapBindingFunctionBodyPtr body, encodePtr *encoders, sdlTypePtr *types, char **in)
1454 {
1455 	int i, j, n;
1456 
1457 	WSDL_CACHE_GET_1(body->use, sdlEncodingUse, in);
1458 	if (body->use == SOAP_ENCODED) {
1459 		WSDL_CACHE_GET_1(body->encodingStyle, sdlRpcEncodingStyle, in);
1460 	} else {
1461 		body->encodingStyle = SOAP_ENCODING_DEFAULT;
1462 	}
1463 	body->ns = sdl_deserialize_string(in);
1464 	WSDL_CACHE_GET_INT(i, in);
1465 	if (i > 0) {
1466 		body->headers = emalloc(sizeof(HashTable));
1467 		zend_hash_init(body->headers, i, NULL, delete_header, 0);
1468 		while (i > 0) {
1469 			sdlSoapBindingFunctionHeaderPtr tmp = emalloc(sizeof(sdlSoapBindingFunctionHeader));
1470 			memset(tmp, 0, sizeof(sdlSoapBindingFunctionHeader));
1471 			sdl_deserialize_key(body->headers, tmp, in);
1472 			WSDL_CACHE_GET_1(tmp->use, sdlEncodingUse, in);
1473 			if (tmp->use == SOAP_ENCODED) {
1474 				WSDL_CACHE_GET_1(tmp->encodingStyle, sdlRpcEncodingStyle, in);
1475 			} else {
1476 				tmp->encodingStyle = SOAP_ENCODING_DEFAULT;
1477 			}
1478 			tmp->name = sdl_deserialize_string(in);
1479 			tmp->ns = sdl_deserialize_string(in);
1480 			WSDL_CACHE_GET_INT(n, in);
1481 			tmp->encode = encoders[n];
1482 			WSDL_CACHE_GET_INT(n, in);
1483 			tmp->element = types[n];
1484 			--i;
1485 			WSDL_CACHE_GET_INT(j, in);
1486 			if (j > 0) {
1487 				tmp->headerfaults = emalloc(sizeof(HashTable));
1488 				zend_hash_init(tmp->headerfaults, i, NULL, delete_header, 0);
1489 				while (j > 0) {
1490 					sdlSoapBindingFunctionHeaderPtr tmp2 = emalloc(sizeof(sdlSoapBindingFunctionHeader));
1491 					memset(tmp2, 0, sizeof(sdlSoapBindingFunctionHeader));
1492 					sdl_deserialize_key(tmp->headerfaults, tmp2, in);
1493 					WSDL_CACHE_GET_1(tmp2->use, sdlEncodingUse, in);
1494 					if (tmp2->use == SOAP_ENCODED) {
1495 						WSDL_CACHE_GET_1(tmp2->encodingStyle, sdlRpcEncodingStyle, in);
1496 					} else {
1497 						tmp2->encodingStyle = SOAP_ENCODING_DEFAULT;
1498 					}
1499 					tmp2->name = sdl_deserialize_string(in);
1500 					tmp2->ns = sdl_deserialize_string(in);
1501 					WSDL_CACHE_GET_INT(n, in);
1502 					tmp2->encode = encoders[n];
1503 					WSDL_CACHE_GET_INT(n, in);
1504 					tmp2->element = types[n];
1505 					--j;
1506 				}
1507 			}
1508 		}
1509 	}
1510 }
1511 
sdl_deserialize_parameters(encodePtr * encoders,sdlTypePtr * types,char ** in)1512 static HashTable* sdl_deserialize_parameters(encodePtr *encoders, sdlTypePtr *types, char **in)
1513 {
1514 	int i, n;
1515 	HashTable *ht;
1516 
1517 	WSDL_CACHE_GET_INT(i, in);
1518 	if (i == 0) {return NULL;}
1519 	ht = emalloc(sizeof(HashTable));
1520 	zend_hash_init(ht, i, NULL, delete_parameter, 0);
1521 	while (i > 0) {
1522 		sdlParamPtr param = emalloc(sizeof(sdlParam));
1523 		sdl_deserialize_key(ht, param, in);
1524 		param->paramName = sdl_deserialize_string(in);
1525 		WSDL_CACHE_GET_INT(param->order, in);
1526 		WSDL_CACHE_GET_INT(n, in);
1527 		param->encode = encoders[n];
1528 		WSDL_CACHE_GET_INT(n, in);
1529 		param->element = types[n];
1530 		--i;
1531 	}
1532 	return ht;
1533 }
1534 
get_sdl_from_cache(const char * fn,const char * uri,time_t t,time_t * cached TSRMLS_DC)1535 static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t, time_t *cached TSRMLS_DC)
1536 {
1537 	sdlPtr sdl;
1538 	time_t old_t;
1539 	int  i, num_groups, num_types, num_elements, num_encoders, num_bindings, num_func;
1540 	sdlFunctionPtr *functions = NULL;
1541 	sdlBindingPtr *bindings;
1542 	sdlTypePtr *types;
1543 	encodePtr *encoders;
1544 	encodePtr enc;
1545 
1546 	int f;
1547 	struct stat st;
1548 	char *in, *buf;
1549 
1550 	f = open(fn, O_RDONLY|O_BINARY);
1551 	if (f < 0) {
1552 		return NULL;
1553 	}
1554 	if (fstat(f, &st) != 0) {
1555 		close(f);
1556 		return NULL;
1557 	}
1558 	buf = in = emalloc(st.st_size);
1559 	if (read(f, in, st.st_size) != st.st_size) {
1560 		close(f);
1561 		efree(in);
1562 		return NULL;
1563 	}
1564 	close(f);
1565 
1566 	if (strncmp(in,"wsdl",4) != 0 || in[4] != WSDL_CACHE_VERSION || in[5] != '\0') {
1567 		unlink(fn);
1568 		efree(buf);
1569 		return NULL;
1570 	}
1571 	in += 6;
1572 
1573 	WSDL_CACHE_GET(old_t, time_t, &in);
1574 	if (old_t < t) {
1575 		unlink(fn);
1576 		efree(buf);
1577 		return NULL;
1578 	}
1579 	*cached = old_t;
1580 
1581 	WSDL_CACHE_GET_INT(i, &in);
1582 	if (i == 0 && strncmp(in, uri, i) != 0) {
1583 		unlink(fn);
1584 		efree(buf);
1585 		return NULL;
1586 	}
1587 	WSDL_CACHE_SKIP(i, &in);
1588 
1589 	sdl = emalloc(sizeof(*sdl));
1590 	memset(sdl, 0, sizeof(*sdl));
1591 
1592 	sdl->source = sdl_deserialize_string(&in);
1593 	sdl->target_ns = sdl_deserialize_string(&in);
1594 
1595 	WSDL_CACHE_GET_INT(num_groups, &in);
1596 	WSDL_CACHE_GET_INT(num_types, &in);
1597 	WSDL_CACHE_GET_INT(num_elements, &in);
1598 	WSDL_CACHE_GET_INT(num_encoders, &in);
1599 
1600 	i = num_groups+num_types+num_elements;
1601 	types = safe_emalloc((i+1), sizeof(sdlTypePtr), 0);
1602 	types[0] = NULL;
1603 	while (i > 0) {
1604 		types[i] = emalloc(sizeof(sdlType));
1605 		memset(types[i], 0, sizeof(sdlType));
1606 		i--;
1607 	}
1608 
1609 	i = num_encoders;
1610 	enc = defaultEncoding;
1611 	while (enc->details.type != END_KNOWN_TYPES) {
1612 		i++; enc++;
1613 	}
1614 	encoders = safe_emalloc((i+1), sizeof(encodePtr), 0);
1615 	i = num_encoders;
1616 	encoders[0] = NULL;
1617 	while (i > 0) {
1618 		encoders[i] = emalloc(sizeof(encode));
1619 		memset(encoders[i], 0, sizeof(encode));
1620 		i--;
1621 	}
1622 	i = num_encoders;
1623 	enc = defaultEncoding;
1624 	while (enc->details.type != END_KNOWN_TYPES) {
1625 		encoders[++i] = enc++;
1626 	}
1627 
1628 	i = 1;
1629 	if (num_groups > 0) {
1630 		sdl->groups = emalloc(sizeof(HashTable));
1631 		zend_hash_init(sdl->groups, num_groups, NULL, delete_type, 0);
1632 		while (i < num_groups+1) {
1633 			sdl_deserialize_key(sdl->groups, types[i], &in);
1634 			sdl_deserialize_type(types[i], types, encoders, &in);
1635 			i++;
1636 		}
1637 	}
1638 
1639 	if (num_types > 0) {
1640 		sdl->types = emalloc(sizeof(HashTable));
1641 		zend_hash_init(sdl->types, num_types, NULL, delete_type, 0);
1642 		while (i < num_groups+num_types+1) {
1643 			sdl_deserialize_key(sdl->types, types[i], &in);
1644 			sdl_deserialize_type(types[i], types, encoders, &in);
1645 			i++;
1646 		}
1647 	}
1648 
1649 	if (num_elements > 0) {
1650 		sdl->elements = emalloc(sizeof(HashTable));
1651 		zend_hash_init(sdl->elements, num_elements, NULL, delete_type, 0);
1652 		while (i < num_groups+num_types+num_elements+1) {
1653 			sdl_deserialize_key(sdl->elements, types[i], &in);
1654 			sdl_deserialize_type(types[i], types, encoders, &in);
1655 			i++;
1656 		}
1657 	}
1658 
1659 	i = 1;
1660 	if (num_encoders > 0) {
1661 		sdl->encoders = emalloc(sizeof(HashTable));
1662 		zend_hash_init(sdl->encoders, num_encoders, NULL, delete_encoder, 0);
1663 		while (i < num_encoders+1) {
1664 			sdl_deserialize_key(sdl->encoders, encoders[i], &in);
1665 			sdl_deserialize_encoder(encoders[i], types, &in);
1666 			i++;
1667 		}
1668 	}
1669 
1670 	/* deserialize bindings */
1671 	WSDL_CACHE_GET_INT(num_bindings, &in);
1672 	bindings = safe_emalloc(num_bindings, sizeof(sdlBindingPtr), 0);
1673 	if (num_bindings > 0) {
1674 		sdl->bindings = emalloc(sizeof(HashTable));
1675 		zend_hash_init(sdl->bindings, num_bindings, NULL, delete_binding, 0);
1676 		for (i = 0; i < num_bindings; i++) {
1677 			sdlBindingPtr binding = emalloc(sizeof(sdlBinding));
1678 			memset(binding, 0, sizeof(sdlBinding));
1679 			sdl_deserialize_key(sdl->bindings, binding, &in);
1680 			binding->name = sdl_deserialize_string(&in);
1681 			binding->location = sdl_deserialize_string(&in);
1682 			WSDL_CACHE_GET_1(binding->bindingType,sdlBindingType,&in);
1683 			if (binding->bindingType == BINDING_SOAP && *in != 0) {
1684 			  sdlSoapBindingPtr soap_binding = binding->bindingAttributes = emalloc(sizeof(sdlSoapBinding));
1685 				WSDL_CACHE_GET_1(soap_binding->style,sdlEncodingStyle,&in);
1686 				WSDL_CACHE_GET_1(soap_binding->transport,sdlTransport,&in);
1687 			} else {
1688 				WSDL_CACHE_SKIP(1,&in);
1689 			}
1690 			bindings[i] = binding;
1691 		}
1692 	}
1693 
1694 	/* deserialize functions */
1695 	WSDL_CACHE_GET_INT(num_func, &in);
1696 	zend_hash_init(&sdl->functions, num_func, NULL, delete_function, 0);
1697 	if (num_func > 0) {
1698 		functions = safe_emalloc(num_func, sizeof(sdlFunctionPtr), 0);
1699 		for (i = 0; i < num_func; i++) {
1700 			int binding_num, num_faults;
1701 			sdlFunctionPtr func = emalloc(sizeof(sdlFunction));
1702 			sdl_deserialize_key(&sdl->functions, func, &in);
1703 			func->functionName = sdl_deserialize_string(&in);
1704 			func->requestName = sdl_deserialize_string(&in);
1705 			func->responseName = sdl_deserialize_string(&in);
1706 
1707 			WSDL_CACHE_GET_INT(binding_num, &in);
1708 			if (binding_num == 0) {
1709 				func->binding = NULL;
1710 			} else {
1711 				func->binding = bindings[binding_num-1];
1712 			}
1713 			if (func->binding && func->binding->bindingType == BINDING_SOAP && *in != 0) {
1714 				sdlSoapBindingFunctionPtr binding = func->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunction));
1715 				memset(binding, 0, sizeof(sdlSoapBindingFunction));
1716 				WSDL_CACHE_GET_1(binding->style,sdlEncodingStyle,&in);
1717 				binding->soapAction = sdl_deserialize_string(&in);
1718 				sdl_deserialize_soap_body(&binding->input, encoders, types, &in);
1719 				sdl_deserialize_soap_body(&binding->output, encoders, types, &in);
1720 			} else {
1721 				WSDL_CACHE_SKIP(1, &in);
1722 				func->bindingAttributes = NULL;
1723 			}
1724 
1725 			func->requestParameters = sdl_deserialize_parameters(encoders, types, &in);
1726 			func->responseParameters = sdl_deserialize_parameters(encoders, types, &in);
1727 
1728 			WSDL_CACHE_GET_INT(num_faults, &in);
1729 			if (num_faults > 0) {
1730 			  int j;
1731 
1732 				func->faults = emalloc(sizeof(HashTable));
1733 				zend_hash_init(func->faults, num_faults, NULL, delete_fault, 0);
1734 
1735 				for (j = 0; j < num_faults; j++) {
1736 					sdlFaultPtr fault = emalloc(sizeof(sdlFault));
1737 
1738 					sdl_deserialize_key(func->faults, fault, &in);
1739 					fault->name =sdl_deserialize_string(&in);
1740 					fault->details =sdl_deserialize_parameters(encoders, types, &in);
1741 					if (*in != 0) {
1742 						sdlSoapBindingFunctionFaultPtr binding = fault->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunctionFault));
1743 						memset(binding, 0, sizeof(sdlSoapBindingFunctionFault));
1744 						WSDL_CACHE_GET_1(binding->use,sdlEncodingUse,&in);
1745 						if (binding->use == SOAP_ENCODED) {
1746 							WSDL_CACHE_GET_1(binding->encodingStyle, sdlRpcEncodingStyle, &in);
1747 						} else {
1748 							binding->encodingStyle = SOAP_ENCODING_DEFAULT;
1749 						}
1750 						binding->ns = sdl_deserialize_string(&in);
1751 					} else {
1752 						WSDL_CACHE_SKIP(1, &in);
1753 						fault->bindingAttributes = NULL;
1754 					}
1755 				}
1756 			} else {
1757 				func->faults = NULL;
1758 			}
1759 			functions[i] = func;
1760 		}
1761 	}
1762 
1763 	/* deserialize requests */
1764 	WSDL_CACHE_GET_INT(i, &in);
1765 	if (i > 0) {
1766 		sdl->requests = emalloc(sizeof(HashTable));
1767 		zend_hash_init(sdl->requests, i, NULL, NULL, 0);
1768 		while (i > 0) {
1769 			int function_num;
1770 
1771 			WSDL_CACHE_GET_INT(function_num, &in);
1772 			sdl_deserialize_key(sdl->requests, functions[function_num-1], &in);
1773 			i--;
1774 		}
1775 	}
1776 
1777 	if (functions) {
1778 		efree(functions);
1779 	}
1780 	efree(bindings);
1781 	efree(encoders);
1782 	efree(types);
1783 	efree(buf);
1784 	return sdl;
1785 }
1786 
sdl_serialize_string(const char * str,smart_str * out)1787 static void sdl_serialize_string(const char *str, smart_str *out)
1788 {
1789 	int i;
1790 
1791 	if (str) {
1792 		i = strlen(str);
1793 		WSDL_CACHE_PUT_INT(i, out);
1794 		if (i > 0) {
1795 			WSDL_CACHE_PUT_N(str, i, out);
1796 		}
1797 	} else {
1798 		WSDL_CACHE_PUT_INT(0x7fffffff, out);
1799 	}
1800 }
1801 
sdl_serialize_key(HashTable * ht,smart_str * out)1802 static void sdl_serialize_key(HashTable *ht, smart_str *out)
1803 {
1804 	char *key;
1805 	uint  key_len;
1806 	ulong index;
1807 
1808 	if (zend_hash_get_current_key_ex(ht, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
1809 		WSDL_CACHE_PUT_INT(key_len, out);
1810 		WSDL_CACHE_PUT_N(key, key_len, out);
1811 	} else {
1812 		WSDL_CACHE_PUT_INT(0, out);
1813 	}
1814 }
1815 
sdl_serialize_encoder_ref(encodePtr enc,HashTable * tmp_encoders,smart_str * out)1816 static void sdl_serialize_encoder_ref(encodePtr enc, HashTable *tmp_encoders, smart_str *out) {
1817 	if (enc) {
1818 		int *encoder_num;
1819 		if (zend_hash_find(tmp_encoders, (char*)&enc, sizeof(enc), (void**)&encoder_num) == SUCCESS) {
1820 			WSDL_CACHE_PUT_INT(*encoder_num, out);
1821 		} else {
1822 			WSDL_CACHE_PUT_INT(0, out);
1823 		}
1824 	} else {
1825 		WSDL_CACHE_PUT_INT(0, out);
1826 	}
1827 }
1828 
sdl_serialize_type_ref(sdlTypePtr type,HashTable * tmp_types,smart_str * out)1829 static void sdl_serialize_type_ref(sdlTypePtr type, HashTable *tmp_types, smart_str *out) {
1830 	if (type) {
1831 		int *type_num;
1832 		if (zend_hash_find(tmp_types, (char*)&type, sizeof(type), (void**)&type_num) == SUCCESS) {
1833 			WSDL_CACHE_PUT_INT(*type_num, out);
1834 		} else {
1835 			WSDL_CACHE_PUT_INT(0, out);
1836 		}
1837 	} else {
1838 		WSDL_CACHE_PUT_INT(0,out);
1839 	}
1840 }
1841 
sdl_serialize_attribute(sdlAttributePtr attr,HashTable * tmp_encoders,smart_str * out)1842 static void sdl_serialize_attribute(sdlAttributePtr attr, HashTable *tmp_encoders, smart_str *out)
1843 {
1844 	int i;
1845 
1846 	sdl_serialize_string(attr->name, out);
1847 	sdl_serialize_string(attr->namens, out);
1848 	sdl_serialize_string(attr->ref, out);
1849 	sdl_serialize_string(attr->def, out);
1850 	sdl_serialize_string(attr->fixed, out);
1851 	WSDL_CACHE_PUT_1(attr->form, out);
1852 	WSDL_CACHE_PUT_1(attr->use, out);
1853 	sdl_serialize_encoder_ref(attr->encode, tmp_encoders, out);
1854 	if (attr->extraAttributes) {
1855 		i = zend_hash_num_elements(attr->extraAttributes);
1856 	} else {
1857 		i = 0;
1858 	}
1859 	WSDL_CACHE_PUT_INT(i, out);
1860 	if (i > 0) {
1861 		sdlExtraAttributePtr *tmp;
1862 		zend_hash_internal_pointer_reset(attr->extraAttributes);
1863 		while (zend_hash_get_current_data(attr->extraAttributes, (void**)&tmp) == SUCCESS) {
1864 			sdl_serialize_key(attr->extraAttributes, out);
1865 			sdl_serialize_string((*tmp)->ns, out);
1866 			sdl_serialize_string((*tmp)->val, out);
1867 			zend_hash_move_forward(attr->extraAttributes);
1868 		}
1869 	}
1870 }
1871 
sdl_serialize_model(sdlContentModelPtr model,HashTable * tmp_types,HashTable * tmp_elements,smart_str * out)1872 static void sdl_serialize_model(sdlContentModelPtr model, HashTable *tmp_types, HashTable *tmp_elements, smart_str *out)
1873 {
1874 	WSDL_CACHE_PUT_1(model->kind, out);
1875 	WSDL_CACHE_PUT_INT(model->min_occurs, out);
1876 	WSDL_CACHE_PUT_INT(model->max_occurs, out);
1877 	switch (model->kind) {
1878 		case XSD_CONTENT_ELEMENT:
1879 			sdl_serialize_type_ref(model->u.element, tmp_elements, out);
1880 			break;
1881 		case XSD_CONTENT_SEQUENCE:
1882 		case XSD_CONTENT_ALL:
1883 		case XSD_CONTENT_CHOICE: {
1884 				sdlContentModelPtr *tmp;
1885 				int i = zend_hash_num_elements(model->u.content);
1886 
1887 				WSDL_CACHE_PUT_INT(i, out);
1888 				zend_hash_internal_pointer_reset(model->u.content);
1889 				while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
1890 					sdl_serialize_model(*tmp, tmp_types, tmp_elements, out);
1891 					zend_hash_move_forward(model->u.content);
1892 				}
1893 			}
1894 			break;
1895 		case XSD_CONTENT_GROUP_REF:
1896 			sdl_serialize_string(model->u.group_ref,out);
1897 			break;
1898 		case XSD_CONTENT_GROUP:
1899 			sdl_serialize_type_ref(model->u.group, tmp_types, out);
1900 			break;
1901 		default:
1902 			break;
1903 	}
1904 }
1905 
sdl_serialize_resriction_int(sdlRestrictionIntPtr x,smart_str * out)1906 static void sdl_serialize_resriction_int(sdlRestrictionIntPtr x, smart_str *out)
1907 {
1908 	if (x) {
1909 		WSDL_CACHE_PUT_1(1, out);
1910 		WSDL_CACHE_PUT_INT(x->value, out);
1911 		WSDL_CACHE_PUT_1(x->fixed, out);
1912 	} else {
1913 		WSDL_CACHE_PUT_1(0, out);
1914 	}
1915 }
1916 
sdl_serialize_resriction_char(sdlRestrictionCharPtr x,smart_str * out)1917 static void sdl_serialize_resriction_char(sdlRestrictionCharPtr x, smart_str *out)
1918 {
1919 	if (x) {
1920 		WSDL_CACHE_PUT_1(1, out);
1921 		sdl_serialize_string(x->value, out);
1922 		WSDL_CACHE_PUT_1(x->fixed, out);
1923 	} else {
1924 		WSDL_CACHE_PUT_1(0, out);
1925 	}
1926 }
1927 
sdl_serialize_type(sdlTypePtr type,HashTable * tmp_encoders,HashTable * tmp_types,smart_str * out)1928 static void sdl_serialize_type(sdlTypePtr type, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
1929 {
1930 	int i;
1931 	HashTable *tmp_elements = NULL;
1932 
1933 	WSDL_CACHE_PUT_1(type->kind, out);
1934 	sdl_serialize_string(type->name, out);
1935 	sdl_serialize_string(type->namens, out);
1936 	sdl_serialize_string(type->def, out);
1937 	sdl_serialize_string(type->fixed, out);
1938 	sdl_serialize_string(type->ref, out);
1939 	WSDL_CACHE_PUT_1(type->nillable, out);
1940 	WSDL_CACHE_PUT_1(type->form, out);
1941 	sdl_serialize_encoder_ref(type->encode, tmp_encoders, out);
1942 
1943 	if (type->restrictions) {
1944 		WSDL_CACHE_PUT_1(1, out);
1945 		sdl_serialize_resriction_int(type->restrictions->minExclusive,out);
1946 		sdl_serialize_resriction_int(type->restrictions->minInclusive,out);
1947 		sdl_serialize_resriction_int(type->restrictions->maxExclusive,out);
1948 		sdl_serialize_resriction_int(type->restrictions->maxInclusive,out);
1949 		sdl_serialize_resriction_int(type->restrictions->totalDigits,out);
1950 		sdl_serialize_resriction_int(type->restrictions->fractionDigits,out);
1951 		sdl_serialize_resriction_int(type->restrictions->length,out);
1952 		sdl_serialize_resriction_int(type->restrictions->minLength,out);
1953 		sdl_serialize_resriction_int(type->restrictions->maxLength,out);
1954 		sdl_serialize_resriction_char(type->restrictions->whiteSpace,out);
1955 		sdl_serialize_resriction_char(type->restrictions->pattern,out);
1956 		if (type->restrictions->enumeration) {
1957 			i = zend_hash_num_elements(type->restrictions->enumeration);
1958 		} else {
1959 			i = 0;
1960 		}
1961 		WSDL_CACHE_PUT_INT(i, out);
1962 		if (i > 0) {
1963 			sdlRestrictionCharPtr *tmp;
1964 
1965 			zend_hash_internal_pointer_reset(type->restrictions->enumeration);
1966 			while (zend_hash_get_current_data(type->restrictions->enumeration, (void**)&tmp) == SUCCESS) {
1967 				sdl_serialize_resriction_char(*tmp, out);
1968 				sdl_serialize_key(type->restrictions->enumeration, out);
1969 				zend_hash_move_forward(type->restrictions->enumeration);
1970 			}
1971 		}
1972 	} else {
1973 		WSDL_CACHE_PUT_1(0, out);
1974 	}
1975 	if (type->elements) {
1976 		i = zend_hash_num_elements(type->elements);
1977 	} else {
1978 		i = 0;
1979 	}
1980 	WSDL_CACHE_PUT_INT(i, out);
1981 	if (i > 0) {
1982 		sdlTypePtr *tmp;
1983 
1984 		tmp_elements = emalloc(sizeof(HashTable));
1985 		zend_hash_init(tmp_elements, i, NULL, NULL, 0);
1986 
1987 		zend_hash_internal_pointer_reset(type->elements);
1988 		while (zend_hash_get_current_data(type->elements, (void**)&tmp) == SUCCESS) {
1989 			sdl_serialize_key(type->elements, out);
1990 			sdl_serialize_type(*tmp, tmp_encoders, tmp_types, out);
1991 			zend_hash_add(tmp_elements, (char*)tmp, sizeof(*tmp), &i, sizeof(int), NULL);
1992 			i--;
1993 			zend_hash_move_forward(type->elements);
1994 		}
1995 	}
1996 
1997 	if (type->attributes) {
1998 		i = zend_hash_num_elements(type->attributes);
1999 	} else {
2000 		i = 0;
2001 	}
2002 	WSDL_CACHE_PUT_INT(i, out);
2003 	if (i > 0) {
2004 		sdlAttributePtr *tmp;
2005 		zend_hash_internal_pointer_reset(type->attributes);
2006 		while (zend_hash_get_current_data(type->attributes, (void**)&tmp) == SUCCESS) {
2007 			sdl_serialize_key(type->attributes, out);
2008 			sdl_serialize_attribute(*tmp, tmp_encoders, out);
2009 			zend_hash_move_forward(type->attributes);
2010 		}
2011 	}
2012 	if (type->model) {
2013 		WSDL_CACHE_PUT_1(1, out);
2014 		sdl_serialize_model(type->model, tmp_types, tmp_elements, out);
2015 	} else {
2016 		WSDL_CACHE_PUT_1(0, out);
2017 	}
2018 	if (tmp_elements != NULL) {
2019 		zend_hash_destroy(tmp_elements);
2020 		efree(tmp_elements);
2021 	}
2022 }
2023 
sdl_serialize_encoder(encodePtr enc,HashTable * tmp_types,smart_str * out)2024 static void sdl_serialize_encoder(encodePtr enc, HashTable *tmp_types, smart_str *out)
2025 {
2026 	WSDL_CACHE_PUT_INT(enc->details.type, out);
2027 	sdl_serialize_string(enc->details.type_str, out);
2028 	sdl_serialize_string(enc->details.ns, out);
2029 	sdl_serialize_type_ref(enc->details.sdl_type, tmp_types, out);
2030 }
2031 
sdl_serialize_parameters(HashTable * ht,HashTable * tmp_encoders,HashTable * tmp_types,smart_str * out)2032 static void sdl_serialize_parameters(HashTable *ht, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
2033 {
2034 	int i;
2035 
2036 	if (ht) {
2037 		i = zend_hash_num_elements(ht);
2038 	} else {
2039 		i = 0;
2040 	}
2041 	WSDL_CACHE_PUT_INT(i, out);
2042 	if (i > 0) {
2043 		sdlParamPtr *tmp;
2044 
2045 		zend_hash_internal_pointer_reset(ht);
2046 		while (zend_hash_get_current_data(ht, (void**)&tmp) == SUCCESS) {
2047 			sdl_serialize_key(ht, out);
2048 			sdl_serialize_string((*tmp)->paramName, out);
2049 			WSDL_CACHE_PUT_INT((*tmp)->order, out);
2050 			sdl_serialize_encoder_ref((*tmp)->encode, tmp_encoders, out);
2051 			sdl_serialize_type_ref((*tmp)->element, tmp_types, out);
2052 			zend_hash_move_forward(ht);
2053 		}
2054 	}
2055 }
2056 
sdl_serialize_soap_body(sdlSoapBindingFunctionBodyPtr body,HashTable * tmp_encoders,HashTable * tmp_types,smart_str * out)2057 static void sdl_serialize_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
2058 {
2059 	int i, j;
2060 
2061 	WSDL_CACHE_PUT_1(body->use, out);
2062 	if (body->use == SOAP_ENCODED) {
2063 		WSDL_CACHE_PUT_1(body->encodingStyle, out);
2064 	}
2065 	sdl_serialize_string(body->ns, out);
2066 	if (body->headers) {
2067 		i = zend_hash_num_elements(body->headers);
2068 	} else {
2069 		i = 0;
2070 	}
2071 	WSDL_CACHE_PUT_INT(i, out);
2072 	if (i > 0) {
2073 		sdlSoapBindingFunctionHeaderPtr *tmp;
2074 		zend_hash_internal_pointer_reset(body->headers);
2075 		while (zend_hash_get_current_data(body->headers, (void**)&tmp) == SUCCESS) {
2076 			sdl_serialize_key(body->headers, out);
2077 			WSDL_CACHE_PUT_1((*tmp)->use, out);
2078 			if ((*tmp)->use == SOAP_ENCODED) {
2079 				WSDL_CACHE_PUT_1((*tmp)->encodingStyle, out);
2080 			}
2081 			sdl_serialize_string((*tmp)->name, out);
2082 			sdl_serialize_string((*tmp)->ns, out);
2083 			sdl_serialize_encoder_ref((*tmp)->encode, tmp_encoders, out);
2084 			sdl_serialize_type_ref((*tmp)->element, tmp_types, out);
2085 			if ((*tmp)->headerfaults) {
2086 				j = zend_hash_num_elements((*tmp)->headerfaults);
2087 			} else {
2088 				j = 0;
2089 			}
2090 			WSDL_CACHE_PUT_INT(j, out);
2091 			if (j > 0) {
2092 				sdlSoapBindingFunctionHeaderPtr *tmp2;
2093 				zend_hash_internal_pointer_reset((*tmp)->headerfaults);
2094 				while (zend_hash_get_current_data((*tmp)->headerfaults, (void**)&tmp2) == SUCCESS) {
2095 					sdl_serialize_key((*tmp)->headerfaults, out);
2096 					WSDL_CACHE_PUT_1((*tmp2)->use, out);
2097 					if ((*tmp2)->use == SOAP_ENCODED) {
2098 						WSDL_CACHE_PUT_1((*tmp2)->encodingStyle, out);
2099 					}
2100 					sdl_serialize_string((*tmp2)->name, out);
2101 					sdl_serialize_string((*tmp2)->ns, out);
2102 					sdl_serialize_encoder_ref((*tmp2)->encode, tmp_encoders, out);
2103 					sdl_serialize_type_ref((*tmp2)->element, tmp_types, out);
2104 					zend_hash_move_forward((*tmp)->headerfaults);
2105 				}
2106 			}
2107 			zend_hash_move_forward(body->headers);
2108 		}
2109 	}
2110 }
2111 
add_sdl_to_cache(const char * fn,const char * uri,time_t t,sdlPtr sdl TSRMLS_DC)2112 static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr sdl TSRMLS_DC)
2113 {
2114 	smart_str buf = {0};
2115 	smart_str *out = &buf;
2116 	int i;
2117 	int type_num = 1;
2118 	int encoder_num = 1;
2119 	int f;
2120 	encodePtr enc;
2121 	HashTable tmp_types;
2122 	HashTable tmp_encoders;
2123 	HashTable tmp_bindings;
2124 	HashTable tmp_functions;
2125 
2126 #ifdef ZEND_WIN32
2127 	f = open(fn,O_CREAT|O_WRONLY|O_EXCL|O_BINARY,S_IREAD|S_IWRITE);
2128 #else
2129 	f = open(fn,O_CREAT|O_WRONLY|O_EXCL|O_BINARY,S_IREAD|S_IWRITE);
2130 #endif
2131 	if (f < 0) {return;}
2132 
2133 	zend_hash_init(&tmp_types, 0, NULL, NULL, 0);
2134 	zend_hash_init(&tmp_encoders, 0, NULL, NULL, 0);
2135 	zend_hash_init(&tmp_bindings, 0, NULL, NULL, 0);
2136 	zend_hash_init(&tmp_functions, 0, NULL, NULL, 0);
2137 
2138 	WSDL_CACHE_PUT_N("wsdl", 4, out);
2139 	WSDL_CACHE_PUT_1(WSDL_CACHE_VERSION,out);
2140 	WSDL_CACHE_PUT_1(0,out);
2141 	WSDL_CACHE_PUT_N(&t, sizeof(t), out);
2142 
2143 	sdl_serialize_string(uri, out);
2144 	sdl_serialize_string(sdl->source, out);
2145 	sdl_serialize_string(sdl->target_ns, out);
2146 
2147 	if (sdl->groups) {
2148 		i = zend_hash_num_elements(sdl->groups);
2149 	} else {
2150 		i = 0;
2151 	}
2152 	WSDL_CACHE_PUT_INT(i, out);
2153 	if (i > 0) {
2154 		sdlTypePtr *tmp;
2155 
2156 		zend_hash_internal_pointer_reset(sdl->groups);
2157 		while (zend_hash_get_current_data(sdl->groups, (void**)&tmp) == SUCCESS) {
2158 			zend_hash_add(&tmp_types, (char*)tmp, sizeof(*tmp), (void**)&type_num, sizeof(type_num), NULL);
2159 			++type_num;
2160 			zend_hash_move_forward(sdl->groups);
2161 		}
2162 	}
2163 
2164 	if (sdl->types) {
2165 		i = zend_hash_num_elements(sdl->types);
2166 	} else {
2167 		i = 0;
2168 	}
2169 	WSDL_CACHE_PUT_INT(i, out);
2170 	if (i > 0) {
2171 		sdlTypePtr *tmp;
2172 
2173 		zend_hash_internal_pointer_reset(sdl->types);
2174 		while (zend_hash_get_current_data(sdl->types, (void**)&tmp) == SUCCESS) {
2175 			zend_hash_add(&tmp_types, (char*)tmp, sizeof(*tmp), (void**)&type_num, sizeof(type_num), NULL);
2176 			++type_num;
2177 			zend_hash_move_forward(sdl->types);
2178 		}
2179 	}
2180 
2181 	if (sdl->elements) {
2182 		i = zend_hash_num_elements(sdl->elements);
2183 	} else {
2184 		i = 0;
2185 	}
2186 	WSDL_CACHE_PUT_INT(i, out);
2187 	if (i > 0) {
2188 		sdlTypePtr *tmp;
2189 
2190 		zend_hash_internal_pointer_reset(sdl->elements);
2191 		while (zend_hash_get_current_data(sdl->elements, (void**)&tmp) == SUCCESS) {
2192 			zend_hash_add(&tmp_types, (char*)tmp, sizeof(*tmp), (void**)&type_num, sizeof(type_num), NULL);
2193 			++type_num;
2194 			zend_hash_move_forward(sdl->elements);
2195 		}
2196 	}
2197 
2198 	if (sdl->encoders) {
2199 		i = zend_hash_num_elements(sdl->encoders);
2200 	} else {
2201 		i = 0;
2202 	}
2203 	WSDL_CACHE_PUT_INT(i, out);
2204 	if (i > 0) {
2205 		encodePtr *tmp;
2206 
2207 		zend_hash_internal_pointer_reset(sdl->encoders);
2208 		while (zend_hash_get_current_data(sdl->encoders, (void**)&tmp) == SUCCESS) {
2209 			zend_hash_add(&tmp_encoders, (char*)tmp, sizeof(*tmp), (void**)&encoder_num, sizeof(encoder_num), NULL);
2210 			++encoder_num;
2211 			zend_hash_move_forward(sdl->encoders);
2212 		}
2213 	}
2214 	enc = defaultEncoding;
2215 	while (enc->details.type != END_KNOWN_TYPES) {
2216 		zend_hash_add(&tmp_encoders, (char*)&enc, sizeof(encodePtr), (void**)&encoder_num, sizeof(encoder_num), NULL);
2217 		enc++;
2218 		++encoder_num;
2219 	}
2220 
2221 	if (sdl->groups) {
2222 		sdlTypePtr *tmp;
2223 		zend_hash_internal_pointer_reset(sdl->groups);
2224 		while (zend_hash_get_current_data(sdl->groups, (void**)&tmp) == SUCCESS) {
2225 			sdl_serialize_key(sdl->groups, out);
2226 			sdl_serialize_type(*tmp, &tmp_encoders, &tmp_types, out);
2227 			zend_hash_move_forward(sdl->groups);
2228 		}
2229 	}
2230 
2231 	if (sdl->types) {
2232 		sdlTypePtr *tmp;
2233 		zend_hash_internal_pointer_reset(sdl->types);
2234 		while (zend_hash_get_current_data(sdl->types, (void**)&tmp) == SUCCESS) {
2235 			sdl_serialize_key(sdl->types, out);
2236 			sdl_serialize_type(*tmp, &tmp_encoders, &tmp_types, out);
2237 			zend_hash_move_forward(sdl->types);
2238 		}
2239 	}
2240 
2241 	if (sdl->elements) {
2242 		sdlTypePtr *tmp;
2243 		zend_hash_internal_pointer_reset(sdl->elements);
2244 		while (zend_hash_get_current_data(sdl->elements, (void**)&tmp) == SUCCESS) {
2245 			sdl_serialize_key(sdl->elements, out);
2246 			sdl_serialize_type(*tmp, &tmp_encoders, &tmp_types, out);
2247 			zend_hash_move_forward(sdl->elements);
2248 		}
2249 	}
2250 
2251 	if (sdl->encoders) {
2252 		encodePtr *tmp;
2253 		zend_hash_internal_pointer_reset(sdl->encoders);
2254 		while (zend_hash_get_current_data(sdl->encoders, (void**)&tmp) == SUCCESS) {
2255 			sdl_serialize_key(sdl->encoders, out);
2256 			sdl_serialize_encoder(*tmp, &tmp_types, out);
2257 			zend_hash_move_forward(sdl->encoders);
2258 		}
2259 	}
2260 
2261 	/* serialize bindings */
2262 	if (sdl->bindings) {
2263 		i = zend_hash_num_elements(sdl->bindings);
2264 	} else {
2265 		i = 0;
2266 	}
2267 	WSDL_CACHE_PUT_INT(i, out);
2268 	if (i > 0) {
2269 		sdlBindingPtr *tmp;
2270 		int binding_num = 1;
2271 
2272 		zend_hash_internal_pointer_reset(sdl->bindings);
2273 		while (zend_hash_get_current_data(sdl->bindings, (void**)&tmp) == SUCCESS) {
2274 			sdl_serialize_key(sdl->bindings, out);
2275 			sdl_serialize_string((*tmp)->name, out);
2276 			sdl_serialize_string((*tmp)->location, out);
2277 			WSDL_CACHE_PUT_1((*tmp)->bindingType,out);
2278 			if ((*tmp)->bindingType == BINDING_SOAP && (*tmp)->bindingAttributes != NULL) {
2279 				sdlSoapBindingPtr binding = (sdlSoapBindingPtr)(*tmp)->bindingAttributes;
2280 				WSDL_CACHE_PUT_1(binding->style, out);
2281 				WSDL_CACHE_PUT_1(binding->transport, out);
2282 			} else {
2283 				WSDL_CACHE_PUT_1(0,out);
2284 			}
2285 
2286 			zend_hash_add(&tmp_bindings, (char*)tmp, sizeof(*tmp), (void**)&binding_num, sizeof(binding_num), NULL);
2287 			binding_num++;
2288 			zend_hash_move_forward(sdl->bindings);
2289 		}
2290 	}
2291 
2292 	/* serialize functions */
2293 	i = zend_hash_num_elements(&sdl->functions);
2294 	WSDL_CACHE_PUT_INT(i, out);
2295 	if (i > 0) {
2296 		sdlFunctionPtr *tmp;
2297 		int *binding_num;
2298 		int function_num = 1;
2299 
2300 		zend_hash_internal_pointer_reset(&sdl->functions);
2301 		while (zend_hash_get_current_data(&sdl->functions, (void**)&tmp) == SUCCESS) {
2302 			sdl_serialize_key(&sdl->functions, out);
2303 			sdl_serialize_string((*tmp)->functionName, out);
2304 			sdl_serialize_string((*tmp)->requestName, out);
2305 			sdl_serialize_string((*tmp)->responseName, out);
2306 
2307 			if ((*tmp)->binding == NULL ||
2308 			    zend_hash_find(&tmp_bindings,(char*)&(*tmp)->binding,sizeof((*tmp)->binding), (void**)&binding_num) != SUCCESS) {
2309 			}
2310 			WSDL_CACHE_PUT_INT(*binding_num, out);
2311 			if (*binding_num >= 0) {
2312 				if ((*tmp)->binding->bindingType == BINDING_SOAP && (*tmp)->bindingAttributes != NULL) {
2313 					sdlSoapBindingFunctionPtr binding = (sdlSoapBindingFunctionPtr)(*tmp)->bindingAttributes;
2314 					WSDL_CACHE_PUT_1(binding->style, out);
2315 					sdl_serialize_string(binding->soapAction, out);
2316 					sdl_serialize_soap_body(&binding->input, &tmp_encoders, &tmp_types, out);
2317 					sdl_serialize_soap_body(&binding->output, &tmp_encoders, &tmp_types, out);
2318 				} else {
2319 					WSDL_CACHE_PUT_1(0,out);
2320 				}
2321 			}
2322 			sdl_serialize_parameters((*tmp)->requestParameters, &tmp_encoders, &tmp_types, out);
2323 			sdl_serialize_parameters((*tmp)->responseParameters, &tmp_encoders, &tmp_types, out);
2324 
2325 			if ((*tmp)->faults) {
2326 				sdlFaultPtr *fault;
2327 
2328 				WSDL_CACHE_PUT_INT(zend_hash_num_elements((*tmp)->faults), out);
2329 
2330 				zend_hash_internal_pointer_reset((*tmp)->faults);
2331 				while (zend_hash_get_current_data((*tmp)->faults, (void**)&fault) == SUCCESS) {
2332 					sdl_serialize_key((*tmp)->faults, out);
2333 					sdl_serialize_string((*fault)->name, out);
2334 					sdl_serialize_parameters((*fault)->details, &tmp_encoders, &tmp_types, out);
2335 					if ((*tmp)->binding->bindingType == BINDING_SOAP && (*fault)->bindingAttributes != NULL) {
2336 						sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)(*fault)->bindingAttributes;
2337 						WSDL_CACHE_PUT_1(binding->use, out);
2338 						if (binding->use == SOAP_ENCODED) {
2339 							WSDL_CACHE_PUT_1(binding->encodingStyle, out);
2340 						}
2341 						sdl_serialize_string(binding->ns, out);
2342 					} else {
2343 						WSDL_CACHE_PUT_1(0, out);
2344 					}
2345 					zend_hash_move_forward((*tmp)->faults);
2346 				}
2347 			} else {
2348 				WSDL_CACHE_PUT_INT(0, out);
2349 			}
2350 
2351 			zend_hash_add(&tmp_functions, (char*)tmp, sizeof(*tmp), (void**)&function_num, sizeof(function_num), NULL);
2352 			function_num++;
2353 			zend_hash_move_forward(&sdl->functions);
2354 		}
2355 	}
2356 
2357 	/* serialize requests */
2358 	if (sdl->requests) {
2359 		i = zend_hash_num_elements(sdl->requests);
2360 	} else {
2361 		i = 0;
2362 	}
2363 	WSDL_CACHE_PUT_INT(i, out);
2364 	if (i > 0) {
2365 		sdlFunctionPtr *tmp;
2366 		int *function_num;
2367 
2368 		zend_hash_internal_pointer_reset(sdl->requests);
2369 		while (zend_hash_get_current_data(sdl->requests, (void**)&tmp) == SUCCESS) {
2370 			if (zend_hash_find(&tmp_functions, (char*)tmp, sizeof(*tmp), (void**)&function_num) != SUCCESS) {
2371 			}
2372 			WSDL_CACHE_PUT_INT(*function_num, out);
2373 			sdl_serialize_key(sdl->requests, out);
2374 			zend_hash_move_forward(sdl->requests);
2375 		}
2376 	}
2377 
2378 	php_ignore_value(write(f, buf.c, buf.len));
2379 	close(f);
2380 	smart_str_free(&buf);
2381 	zend_hash_destroy(&tmp_functions);
2382 	zend_hash_destroy(&tmp_bindings);
2383 	zend_hash_destroy(&tmp_encoders);
2384 	zend_hash_destroy(&tmp_types);
2385 }
2386 
2387 
make_persistent_restriction_int(void * data)2388 static void make_persistent_restriction_int(void *data)
2389 {
2390 	sdlRestrictionIntPtr *rest = (sdlRestrictionIntPtr *)data;
2391 	sdlRestrictionIntPtr prest = NULL;
2392 
2393 	prest = malloc(sizeof(sdlRestrictionInt));
2394 	*prest = **rest;
2395 	*rest = prest;
2396 }
2397 
2398 
make_persistent_restriction_char(void * data)2399 static void make_persistent_restriction_char(void *data)
2400 {
2401 	sdlRestrictionCharPtr *rest = (sdlRestrictionCharPtr *)data;
2402 	sdlRestrictionCharPtr prest = NULL;
2403 
2404 	prest = malloc(sizeof(sdlRestrictionChar));
2405 	memset(prest, 0, sizeof(sdlRestrictionChar));
2406 	prest->value = strdup((*rest)->value);
2407 	prest->fixed = (*rest)->fixed;
2408 	*rest = prest;
2409 }
2410 
2411 
make_persistent_sdl_type_ref(sdlTypePtr * type,HashTable * ptr_map,HashTable * bp_types)2412 static void make_persistent_sdl_type_ref(sdlTypePtr *type, HashTable *ptr_map, HashTable *bp_types)
2413 {
2414 	sdlTypePtr *tmp;
2415 
2416 	if (zend_hash_find(ptr_map, (char *)type, sizeof(sdlTypePtr), (void**)&tmp) == SUCCESS) {
2417 		*type = *tmp;
2418 	} else {
2419 		zend_hash_next_index_insert(bp_types, (void*)&type, sizeof(sdlTypePtr*), NULL);
2420 	}
2421 }
2422 
2423 
make_persistent_sdl_encoder_ref(encodePtr * enc,HashTable * ptr_map,HashTable * bp_encoders)2424 static void make_persistent_sdl_encoder_ref(encodePtr *enc, HashTable *ptr_map, HashTable *bp_encoders)
2425 {
2426 	encodePtr *tmp;
2427 
2428 	/* do not process defaultEncoding's here */
2429 	if ((*enc) >= defaultEncoding && (*enc) < defaultEncoding + numDefaultEncodings) {
2430 		return;
2431 	}
2432 
2433 	if (zend_hash_find(ptr_map, (char *)enc, sizeof(encodePtr), (void**)&tmp) == SUCCESS) {
2434 		*enc = *tmp;
2435 	} else {
2436 		zend_hash_next_index_insert(bp_encoders, (void*)&enc, sizeof(encodePtr*), NULL);
2437 	}
2438 }
2439 
2440 
make_persistent_sdl_function_headers(HashTable * headers,HashTable * ptr_map)2441 static HashTable* make_persistent_sdl_function_headers(HashTable *headers, HashTable *ptr_map)
2442 {
2443 	HashTable *pheaders;
2444 	sdlSoapBindingFunctionHeaderPtr *tmp, pheader;
2445 	encodePtr *penc;
2446 	sdlTypePtr *ptype;
2447 	ulong index;
2448 	char *key;
2449 	uint key_len;
2450 
2451 	pheaders = malloc(sizeof(HashTable));
2452 	zend_hash_init(pheaders, zend_hash_num_elements(headers), NULL, delete_header_persistent, 1);
2453 
2454 	zend_hash_internal_pointer_reset(headers);
2455 	while (zend_hash_get_current_data(headers, (void**)&tmp) == SUCCESS) {
2456 		pheader = malloc(sizeof(sdlSoapBindingFunctionHeader));
2457 		memset(pheader, 0, sizeof(sdlSoapBindingFunctionHeader));
2458 		*pheader = **tmp;
2459 
2460 		if (pheader->name) {
2461 			pheader->name = strdup(pheader->name);
2462 		}
2463 		if (pheader->ns) {
2464 			pheader->ns = strdup(pheader->ns);
2465 		}
2466 
2467 		if (pheader->encode->details.sdl_type) {
2468 			if (zend_hash_find(ptr_map, (char*)&pheader->encode, sizeof(encodePtr), (void**)&penc) == FAILURE) {
2469 				assert(0);
2470 			}
2471 			pheader->encode = *penc;
2472 		}
2473 		if (pheader->element) {
2474 			if (zend_hash_find(ptr_map, (char*)&pheader->element, sizeof(sdlTypePtr), (void**)&ptype) == FAILURE) {
2475 				assert(0);
2476 			}
2477 			pheader->element = *ptype;
2478 		}
2479 
2480 		if (pheader->headerfaults) {
2481 			pheader->headerfaults = make_persistent_sdl_function_headers(pheader->headerfaults, ptr_map);
2482 		}
2483 
2484 		if (zend_hash_get_current_key_ex(headers, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2485 			zend_hash_add(pheaders, key, key_len, (void*)&pheader, sizeof(sdlSoapBindingFunctionHeaderPtr), NULL);
2486 		} else {
2487 			zend_hash_next_index_insert(pheaders, (void*)&pheader, sizeof(sdlSoapBindingFunctionHeaderPtr), NULL);
2488 		}
2489 
2490 		zend_hash_move_forward(headers);
2491 	}
2492 
2493 	return pheaders;
2494 }
2495 
2496 
make_persistent_sdl_soap_body(sdlSoapBindingFunctionBodyPtr body,HashTable * ptr_map)2497 static void make_persistent_sdl_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTable *ptr_map)
2498 {
2499 	if (body->ns) {
2500 		body->ns = strdup(body->ns);
2501 	}
2502 
2503 	if (body->headers) {
2504 		body->headers = make_persistent_sdl_function_headers(body->headers, ptr_map);
2505 	}
2506 }
2507 
2508 
make_persistent_sdl_parameters(HashTable * params,HashTable * ptr_map)2509 static HashTable* make_persistent_sdl_parameters(HashTable *params, HashTable *ptr_map)
2510 {
2511 	HashTable *pparams;
2512 	sdlParamPtr *tmp, pparam;
2513 	sdlTypePtr *ptype;
2514 	encodePtr *penc;
2515 	ulong index;
2516 	char *key;
2517 	uint key_len;
2518 
2519 	pparams = malloc(sizeof(HashTable));
2520 	zend_hash_init(pparams, zend_hash_num_elements(params), NULL, delete_parameter_persistent, 1);
2521 
2522 	zend_hash_internal_pointer_reset(params);
2523 	while (zend_hash_get_current_data(params, (void**)&tmp) == SUCCESS) {
2524 		pparam = malloc(sizeof(sdlParam));
2525 		memset(pparam, 0, sizeof(sdlParam));
2526 		*pparam = **tmp;
2527 
2528 		if (pparam->paramName) {
2529 			pparam->paramName = strdup(pparam->paramName);
2530 		}
2531 
2532 		if (pparam->encode && pparam->encode->details.sdl_type) {
2533 			if (zend_hash_find(ptr_map, (char*)&pparam->encode, sizeof(encodePtr), (void**)&penc) == FAILURE) {
2534 				assert(0);
2535 			}
2536 			pparam->encode = *penc;
2537 		}
2538 		if (pparam->element) {
2539 			if (zend_hash_find(ptr_map, (char*)&pparam->element, sizeof(sdlTypePtr), (void**)&ptype) == FAILURE) {
2540 				assert(0);
2541 			}
2542 			pparam->element = *ptype;
2543 		}
2544 
2545 		if (zend_hash_get_current_key_ex(params, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2546 			zend_hash_add(pparams, key, key_len, (void*)&pparam, sizeof(sdlParamPtr), NULL);
2547 		} else {
2548 			zend_hash_next_index_insert(pparams, (void*)&pparam, sizeof(sdlParamPtr), NULL);
2549 		}
2550 
2551 		zend_hash_move_forward(params);
2552 	}
2553 
2554 
2555 	return pparams;
2556 }
2557 
make_persistent_sdl_function_faults(sdlFunctionPtr func,HashTable * faults,HashTable * ptr_map)2558 static HashTable* make_persistent_sdl_function_faults(sdlFunctionPtr func, HashTable *faults, HashTable *ptr_map)
2559 {
2560 	HashTable *pfaults;
2561 	sdlFaultPtr  *tmp, pfault;
2562 	ulong index;
2563 	char *key;
2564 	uint key_len;
2565 
2566 	pfaults = malloc(sizeof(HashTable));
2567 	zend_hash_init(pfaults, zend_hash_num_elements(faults), NULL, delete_fault_persistent, 1);
2568 
2569 	zend_hash_internal_pointer_reset(faults);
2570 	while (zend_hash_get_current_data(faults, (void**)&tmp) == SUCCESS) {
2571 		pfault = malloc(sizeof(sdlFault));
2572 		memset(pfault, 0, sizeof(sdlFault));
2573 		*pfault = **tmp;
2574 
2575 		if (pfault->name) {
2576 			pfault->name = strdup(pfault->name);
2577 		}
2578 		if (pfault->details) {
2579 			pfault->details = make_persistent_sdl_parameters(pfault->details, ptr_map);
2580 		}
2581 
2582 		if (func->binding->bindingType == BINDING_SOAP && pfault->bindingAttributes) {
2583 			sdlSoapBindingFunctionFaultPtr soap_binding;
2584 
2585 		   	soap_binding = malloc(sizeof(sdlSoapBindingFunctionFault));
2586 			memset(soap_binding, 0, sizeof(sdlSoapBindingFunctionFault));
2587 			*soap_binding = *(sdlSoapBindingFunctionFaultPtr)pfault->bindingAttributes;
2588 			if (soap_binding->ns) {
2589 				soap_binding->ns = strdup(soap_binding->ns);
2590 			}
2591 			pfault->bindingAttributes = soap_binding;
2592 		}
2593 
2594 		if (zend_hash_get_current_key_ex(faults, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2595 			zend_hash_add(pfaults, key, key_len, (void*)&pfault, sizeof(sdlParamPtr), NULL);
2596 		} else {
2597 			zend_hash_next_index_insert(pfaults, (void*)&pfault, sizeof(sdlParamPtr), NULL);
2598 		}
2599 
2600 		zend_hash_move_forward(faults);
2601 	}
2602 
2603 
2604 	return pfaults;
2605 }
2606 
2607 
make_persistent_sdl_attribute(sdlAttributePtr attr,HashTable * ptr_map,HashTable * bp_types,HashTable * bp_encoders)2608 static sdlAttributePtr make_persistent_sdl_attribute(sdlAttributePtr attr, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2609 {
2610 	sdlAttributePtr pattr;
2611 	ulong index;
2612 	char *key;
2613 	uint key_len;
2614 
2615 	pattr = malloc(sizeof(sdlAttribute));
2616 	memset(pattr, 0, sizeof(sdlAttribute));
2617 
2618 	*pattr = *attr;
2619 
2620 	if (pattr->name) {
2621 		pattr->name = strdup(pattr->name);
2622 	}
2623 	if (pattr->namens) {
2624 		pattr->namens = strdup(pattr->namens);
2625 	}
2626 	if (pattr->ref) {
2627 		pattr->ref = strdup(pattr->ref);
2628 	}
2629 	if (pattr->def) {
2630 		pattr->def = strdup(pattr->def);
2631 	}
2632 	if (pattr->fixed) {
2633 		pattr->fixed = strdup(pattr->fixed);
2634 	}
2635 
2636 	/* we do not want to process defaultEncoding's here */
2637 	if (pattr->encode) {
2638 		make_persistent_sdl_encoder_ref(&pattr->encode, ptr_map, bp_encoders);
2639 	}
2640 
2641 	if (pattr->extraAttributes) {
2642 		sdlExtraAttributePtr *tmp, pextra;
2643 
2644 		pattr->extraAttributes = malloc(sizeof(HashTable));
2645 		zend_hash_init(pattr->extraAttributes, zend_hash_num_elements(attr->extraAttributes), NULL, delete_extra_attribute_persistent, 1);
2646 
2647 		zend_hash_internal_pointer_reset(pattr->extraAttributes);
2648 		while (zend_hash_get_current_data(attr->extraAttributes, (void**)&tmp) == SUCCESS) {
2649 			if (zend_hash_get_current_key_ex(attr->extraAttributes, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2650 				pextra = malloc(sizeof(sdlExtraAttribute));
2651 				memset(pextra, 0, sizeof(sdlExtraAttribute));
2652 
2653 				if ((*tmp)->ns) {
2654 					pextra->ns = strdup((*tmp)->ns);
2655 				}
2656 				if ((*tmp)->val) {
2657 					pextra->val = strdup((*tmp)->val);
2658 				}
2659 
2660 				zend_hash_add(pattr->extraAttributes, key, key_len, (void*)&pextra, sizeof(sdlExtraAttributePtr), NULL);
2661 			}
2662 
2663 			zend_hash_move_forward(attr->extraAttributes);
2664 		}
2665 	}
2666 
2667 	return pattr;
2668 }
2669 
2670 
make_persistent_sdl_model(sdlContentModelPtr model,HashTable * ptr_map,HashTable * bp_types,HashTable * bp_encoders)2671 static sdlContentModelPtr make_persistent_sdl_model(sdlContentModelPtr model, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2672 {
2673 	sdlContentModelPtr pmodel;
2674 	sdlContentModelPtr *tmp, pcontent;
2675 
2676 	pmodel = malloc(sizeof(sdlContentModel));
2677 	memset(pmodel, 0, sizeof(sdlContentModel));
2678 	*pmodel = *model;
2679 
2680 	switch (pmodel->kind) {
2681 		case XSD_CONTENT_ELEMENT:
2682 			if (pmodel->u.element) {
2683 				make_persistent_sdl_type_ref(&pmodel->u.element, ptr_map, bp_types);
2684 			}
2685 			break;
2686 
2687 		case XSD_CONTENT_SEQUENCE:
2688 		case XSD_CONTENT_ALL:
2689 		case XSD_CONTENT_CHOICE:
2690 			pmodel->u.content = malloc(sizeof(HashTable));
2691 			zend_hash_init(pmodel->u.content, zend_hash_num_elements(model->u.content), NULL, delete_model_persistent, 1);
2692 
2693 			zend_hash_internal_pointer_reset(model->u.content);
2694 			while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
2695 				pcontent = make_persistent_sdl_model(*tmp, ptr_map, bp_types, bp_encoders);
2696 				zend_hash_next_index_insert(pmodel->u.content, (void*)&pcontent, sizeof(sdlContentModelPtr), NULL);
2697 				zend_hash_move_forward(model->u.content);
2698 			}
2699 			break;
2700 
2701 		case XSD_CONTENT_GROUP_REF:
2702 			if (pmodel->u.group_ref) {
2703 				pmodel->u.group_ref = strdup(pmodel->u.group_ref);
2704 			}
2705 			break;
2706 
2707 		case XSD_CONTENT_GROUP:
2708 			if (pmodel->u.group) {
2709 				make_persistent_sdl_type_ref(&pmodel->u.group, ptr_map, bp_types);
2710 			}
2711 			break;
2712 
2713 		default:
2714 			break;
2715 	}
2716 
2717 	return pmodel;
2718 }
2719 
2720 
make_persistent_sdl_type(sdlTypePtr type,HashTable * ptr_map,HashTable * bp_types,HashTable * bp_encoders)2721 static sdlTypePtr make_persistent_sdl_type(sdlTypePtr type, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2722 {
2723 	ulong index;
2724 	char *key;
2725 	uint key_len;
2726 	sdlTypePtr ptype = NULL;
2727 
2728 	ptype = malloc(sizeof(sdlType));
2729 	memset(ptype, 0, sizeof(sdlType));
2730 
2731 	*ptype = *type;
2732 
2733 	if (ptype->name) {
2734 		ptype->name = strdup(ptype->name);
2735 	}
2736 	if (ptype->namens) {
2737 		ptype->namens = strdup(ptype->namens);
2738 	}
2739 	if (ptype->def) {
2740 		ptype->def = strdup(ptype->def);
2741 	}
2742 	if (ptype->fixed) {
2743 		ptype->fixed = strdup(ptype->fixed);
2744 	}
2745 	if (ptype->ref) {
2746 		ptype->ref = strdup(ptype->ref);
2747 	}
2748 
2749 	/* we do not want to process defaultEncoding's here */
2750 	if (ptype->encode) {
2751 		make_persistent_sdl_encoder_ref(&ptype->encode, ptr_map, bp_encoders);
2752 	}
2753 
2754 	if (ptype->restrictions) {
2755 		ptype->restrictions = malloc(sizeof(sdlRestrictions));
2756 		memset(ptype->restrictions, 0, sizeof(sdlRestrictions));
2757 		*ptype->restrictions = *type->restrictions;
2758 
2759 		if (ptype->restrictions->minExclusive) {
2760 			make_persistent_restriction_int(&ptype->restrictions->minExclusive);
2761 		}
2762 		if (ptype->restrictions->maxExclusive) {
2763 			make_persistent_restriction_int(&ptype->restrictions->maxExclusive);
2764 		}
2765 		if (ptype->restrictions->minInclusive) {
2766 			make_persistent_restriction_int(&ptype->restrictions->minInclusive);
2767 		}
2768 		if (ptype->restrictions->maxInclusive) {
2769 			make_persistent_restriction_int(&ptype->restrictions->maxInclusive);
2770 		}
2771 		if (ptype->restrictions->totalDigits) {
2772 			make_persistent_restriction_int(&ptype->restrictions->totalDigits);
2773 		}
2774 		if (ptype->restrictions->fractionDigits) {
2775 			make_persistent_restriction_int(&ptype->restrictions->fractionDigits);
2776 		}
2777 		if (ptype->restrictions->length) {
2778 			make_persistent_restriction_int(&ptype->restrictions->length);
2779 		}
2780 		if (ptype->restrictions->minLength) {
2781 			make_persistent_restriction_int(&ptype->restrictions->minLength);
2782 		}
2783 		if (ptype->restrictions->maxLength) {
2784 			make_persistent_restriction_int(&ptype->restrictions->maxLength);
2785 		}
2786 		if (ptype->restrictions->whiteSpace) {
2787 			make_persistent_restriction_char(&ptype->restrictions->whiteSpace);
2788 		}
2789 		if (ptype->restrictions->pattern) {
2790 			make_persistent_restriction_char(&ptype->restrictions->pattern);
2791 		}
2792 
2793 		if (type->restrictions->enumeration) {
2794 			sdlRestrictionCharPtr tmp;
2795 
2796 			ptype->restrictions->enumeration = malloc(sizeof(HashTable));
2797 			zend_hash_init(ptype->restrictions->enumeration, zend_hash_num_elements(type->restrictions->enumeration), NULL, delete_restriction_var_char_persistent, 1);
2798 			zend_hash_copy(ptype->restrictions->enumeration, type->restrictions->enumeration, make_persistent_restriction_char, (void*)&tmp, sizeof(sdlRestrictionCharPtr));
2799 		}
2800 	}
2801 
2802 	if (ptype->elements) {
2803 		sdlTypePtr *tmp, pelem;
2804 
2805 		ptype->elements = malloc(sizeof(HashTable));
2806 		zend_hash_init(ptype->elements, zend_hash_num_elements(type->elements), NULL, delete_type_persistent, 1);
2807 
2808 		zend_hash_internal_pointer_reset(type->elements);
2809 		while (zend_hash_get_current_data(type->elements, (void **)&tmp) == SUCCESS) {
2810 			pelem = make_persistent_sdl_type(*tmp, ptr_map, bp_types, bp_encoders);
2811 			if (zend_hash_get_current_key_ex(type->elements, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2812 				zend_hash_add(ptype->elements, key, key_len, (void*)&pelem, sizeof(sdlTypePtr), NULL);
2813 			} else {
2814 				zend_hash_next_index_insert(ptype->elements, (void*)&pelem, sizeof(sdlTypePtr), NULL);
2815 			}
2816 			zend_hash_add(ptr_map, (char*)tmp, sizeof(*tmp), (void*)&pelem, sizeof(sdlTypePtr), NULL);
2817 			zend_hash_move_forward(type->elements);
2818 		}
2819 	}
2820 
2821 	if (ptype->attributes) {
2822 		sdlAttributePtr *tmp, pattr;
2823 
2824 		ptype->attributes = malloc(sizeof(HashTable));
2825 		zend_hash_init(ptype->attributes, zend_hash_num_elements(type->attributes), NULL, delete_attribute_persistent, 1);
2826 
2827 		zend_hash_internal_pointer_reset(type->attributes);
2828 		while (zend_hash_get_current_data(type->attributes, (void **)&tmp) == SUCCESS) {
2829 			pattr = make_persistent_sdl_attribute(*tmp, ptr_map, bp_types, bp_encoders);
2830 			if (zend_hash_get_current_key_ex(type->attributes, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2831 				zend_hash_add(ptype->attributes, key, key_len, (void*)&pattr, sizeof(sdlAttributePtr), NULL);
2832 			} else {
2833 				zend_hash_next_index_insert(ptype->attributes, (void*)&pattr, sizeof(sdlAttributePtr), NULL);
2834 			}
2835 			zend_hash_move_forward(type->attributes);
2836 		}
2837 	}
2838 
2839 	if (type->model) {
2840 		ptype->model = make_persistent_sdl_model(ptype->model, ptr_map, bp_types, bp_encoders);
2841 	}
2842 
2843 	return ptype;
2844 }
2845 
make_persistent_sdl_encoder(encodePtr enc,HashTable * ptr_map,HashTable * bp_types,HashTable * bp_encoders)2846 static encodePtr make_persistent_sdl_encoder(encodePtr enc, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2847 {
2848 	encodePtr penc = NULL;
2849 
2850 	penc = malloc(sizeof(encode));
2851 	memset(penc, 0, sizeof(encode));
2852 
2853 	*penc = *enc;
2854 
2855 	if (penc->details.type_str) {
2856 		penc->details.type_str = strdup(penc->details.type_str);
2857 	}
2858 	if (penc->details.ns) {
2859 		penc->details.ns = strdup(penc->details.ns);
2860 	}
2861 
2862 	if (penc->details.sdl_type) {
2863 		make_persistent_sdl_type_ref(&penc->details.sdl_type, ptr_map, bp_types);
2864 	}
2865 
2866 	return penc;
2867 }
2868 
make_persistent_sdl_binding(sdlBindingPtr bind,HashTable * ptr_map)2869 static sdlBindingPtr make_persistent_sdl_binding(sdlBindingPtr bind, HashTable *ptr_map)
2870 {
2871 	sdlBindingPtr pbind = NULL;
2872 
2873 	pbind = malloc(sizeof(sdlBinding));
2874 	memset(pbind, 0, sizeof(sdlBinding));
2875 
2876 	*pbind = *bind;
2877 
2878 	if (pbind->name) {
2879 		pbind->name = strdup(pbind->name);
2880 	}
2881 	if (pbind->location) {
2882 		pbind->location = strdup(pbind->location);
2883 	}
2884 
2885 	if (pbind->bindingType == BINDING_SOAP && pbind->bindingAttributes) {
2886 		sdlSoapBindingPtr soap_binding;
2887 
2888 		soap_binding = malloc(sizeof(sdlSoapBinding));
2889 		memset(soap_binding, 0, sizeof(sdlSoapBinding));
2890 		*soap_binding = *(sdlSoapBindingPtr)pbind->bindingAttributes;
2891 		pbind->bindingAttributes = soap_binding;
2892 	}
2893 
2894 	return pbind;
2895 }
2896 
make_persistent_sdl_function(sdlFunctionPtr func,HashTable * ptr_map)2897 static sdlFunctionPtr make_persistent_sdl_function(sdlFunctionPtr func, HashTable *ptr_map)
2898 {
2899 	sdlFunctionPtr pfunc = NULL;
2900 
2901 	pfunc = malloc(sizeof(sdlFunction));
2902 	memset(pfunc, 0, sizeof(sdlFunction));
2903 
2904 	*pfunc = *func;
2905 
2906 	if (pfunc->functionName) {
2907 		pfunc->functionName = strdup(pfunc->functionName);
2908 	}
2909 	if (pfunc->requestName) {
2910 		pfunc->requestName = strdup(pfunc->requestName);
2911 	}
2912 	if (pfunc->responseName) {
2913 		pfunc->responseName = strdup(pfunc->responseName);
2914 	}
2915 
2916 	if (pfunc->binding) {
2917 		sdlBindingPtr *tmp;
2918 
2919 		if (zend_hash_find(ptr_map, (char*)&pfunc->binding, sizeof(pfunc->binding), (void**)&tmp) == FAILURE) {
2920 			assert(0);
2921 		}
2922 		pfunc->binding = *tmp;
2923 
2924 		if (pfunc->binding->bindingType == BINDING_SOAP && pfunc->bindingAttributes) {
2925 			sdlSoapBindingFunctionPtr soap_binding;
2926 
2927 		   	soap_binding = malloc(sizeof(sdlSoapBindingFunction));
2928 			memset(soap_binding, 0, sizeof(sdlSoapBindingFunction));
2929 			*soap_binding = *(sdlSoapBindingFunctionPtr)pfunc->bindingAttributes;
2930 			if (soap_binding->soapAction) {
2931 				soap_binding->soapAction = strdup(soap_binding->soapAction);
2932 			}
2933 			make_persistent_sdl_soap_body(&soap_binding->input, ptr_map);
2934 			make_persistent_sdl_soap_body(&soap_binding->output, ptr_map);
2935 			pfunc->bindingAttributes = soap_binding;
2936 		}
2937 
2938 		if (pfunc->requestParameters) {
2939 			pfunc->requestParameters = make_persistent_sdl_parameters(pfunc->requestParameters, ptr_map);
2940 		}
2941 		if (pfunc->responseParameters) {
2942 			pfunc->responseParameters = make_persistent_sdl_parameters(pfunc->responseParameters, ptr_map);
2943 		}
2944 		if (pfunc->faults) {
2945 			pfunc->faults = make_persistent_sdl_function_faults(pfunc, pfunc->faults, ptr_map);
2946 		}
2947 	}
2948 
2949 	return pfunc;
2950 }
2951 
make_persistent_sdl(sdlPtr sdl TSRMLS_DC)2952 static sdlPtr make_persistent_sdl(sdlPtr sdl TSRMLS_DC)
2953 {
2954 	sdlPtr psdl = NULL;
2955 	HashTable ptr_map;
2956 	HashTable bp_types, bp_encoders;
2957 	ulong index;
2958 	char *key;
2959 	uint key_len;
2960 
2961 	zend_hash_init(&bp_types, 0, NULL, NULL, 0);
2962 	zend_hash_init(&bp_encoders, 0, NULL, NULL, 0);
2963 	zend_hash_init(&ptr_map, 0, NULL, NULL, 0);
2964 
2965 	psdl = malloc(sizeof(*sdl));
2966 	memset(psdl, 0, sizeof(*sdl));
2967 
2968 	if (sdl->source) {
2969 		psdl->source = strdup(sdl->source);
2970 	}
2971 	if (sdl->target_ns) {
2972 		psdl->target_ns = strdup(sdl->target_ns);
2973 	}
2974 
2975 	if (sdl->groups) {
2976 		sdlTypePtr *tmp;
2977 		sdlTypePtr ptype;
2978 
2979 		psdl->groups = malloc(sizeof(HashTable));
2980 		zend_hash_init(psdl->groups, zend_hash_num_elements(sdl->groups), NULL, delete_type_persistent, 1);
2981 
2982 		zend_hash_internal_pointer_reset(sdl->groups);
2983 		while (zend_hash_get_current_data(sdl->groups, (void **)&tmp) == SUCCESS) {
2984 			ptype = make_persistent_sdl_type(*tmp, &ptr_map, &bp_types, &bp_encoders);
2985 			if (zend_hash_get_current_key_ex(sdl->groups, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2986 				zend_hash_add(psdl->groups, key, key_len, (void*)&ptype, sizeof(sdlTypePtr), NULL);
2987 			} else {
2988 				zend_hash_next_index_insert(psdl->groups, (void*)&ptype, sizeof(sdlTypePtr), NULL);
2989 			}
2990 			zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&ptype, sizeof(sdlTypePtr), NULL);
2991 			zend_hash_move_forward(sdl->groups);
2992 		}
2993 	}
2994 
2995 	if (sdl->types) {
2996 		sdlTypePtr *tmp;
2997 		sdlTypePtr ptype;
2998 
2999 		psdl->types = malloc(sizeof(HashTable));
3000 		zend_hash_init(psdl->types, zend_hash_num_elements(sdl->types), NULL, delete_type_persistent, 1);
3001 
3002 		zend_hash_internal_pointer_reset(sdl->types);
3003 		while (zend_hash_get_current_data(sdl->types, (void **)&tmp) == SUCCESS) {
3004 			ptype = make_persistent_sdl_type(*tmp, &ptr_map, &bp_types, &bp_encoders);
3005 			if (zend_hash_get_current_key_ex(sdl->types, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3006 				zend_hash_add(psdl->types, key, key_len, (void*)&ptype, sizeof(sdlTypePtr), NULL);
3007 			} else {
3008 				zend_hash_next_index_insert(psdl->types, (void*)&ptype, sizeof(sdlTypePtr), NULL);
3009 			}
3010 			zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&ptype, sizeof(sdlTypePtr), NULL);
3011 			zend_hash_move_forward(sdl->types);
3012 		}
3013 	}
3014 
3015 	if (sdl->elements) {
3016 		sdlTypePtr *tmp;
3017 		sdlTypePtr ptype;
3018 
3019 		psdl->elements = malloc(sizeof(HashTable));
3020 		zend_hash_init(psdl->elements, zend_hash_num_elements(sdl->elements), NULL, delete_type_persistent, 1);
3021 
3022 		zend_hash_internal_pointer_reset(sdl->elements);
3023 		while (zend_hash_get_current_data(sdl->elements, (void **)&tmp) == SUCCESS) {
3024 			ptype = make_persistent_sdl_type(*tmp, &ptr_map, &bp_types, &bp_encoders);
3025 			if (zend_hash_get_current_key_ex(sdl->elements, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3026 				zend_hash_add(psdl->elements, key, key_len, (void*)&ptype, sizeof(sdlTypePtr), NULL);
3027 			} else {
3028 				zend_hash_next_index_insert(psdl->elements, (void*)&ptype, sizeof(sdlTypePtr), NULL);
3029 			}
3030 			zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&ptype, sizeof(sdlTypePtr), NULL);
3031 			zend_hash_move_forward(sdl->elements);
3032 		}
3033 	}
3034 
3035 	if (sdl->encoders) {
3036 		encodePtr *tmp;
3037 		encodePtr penc;
3038 
3039 		psdl->encoders = malloc(sizeof(HashTable));
3040 		zend_hash_init(psdl->encoders, zend_hash_num_elements(sdl->encoders), NULL, delete_encoder_persistent, 1);
3041 
3042 		zend_hash_internal_pointer_reset(sdl->encoders);
3043 		while (zend_hash_get_current_data(sdl->encoders, (void **)&tmp) == SUCCESS) {
3044 			penc = make_persistent_sdl_encoder(*tmp, &ptr_map, &bp_types, &bp_encoders);
3045 			if (zend_hash_get_current_key_ex(sdl->encoders, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3046 				zend_hash_add(psdl->encoders, key, key_len, (void*)&penc, sizeof(encodePtr), NULL);
3047 			} else {
3048 				zend_hash_next_index_insert(psdl->encoders, (void*)&penc, sizeof(encodePtr), NULL);
3049 			}
3050 			zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&penc, sizeof(encodePtr), NULL);
3051 			zend_hash_move_forward(sdl->encoders);
3052 		}
3053 	}
3054 
3055 	/* do backpatching here */
3056 	if (zend_hash_num_elements(&bp_types)) {
3057 		sdlTypePtr **tmp, *ptype = NULL;
3058 
3059 		zend_hash_internal_pointer_reset(&bp_types);
3060 		while (zend_hash_get_current_data(&bp_types, (void**)&tmp) == SUCCESS) {
3061 			if (zend_hash_find(&ptr_map, (char*)(*tmp), sizeof(**tmp), (void**)&ptype) == FAILURE) {
3062 				assert(0);
3063 			}
3064 			**tmp = *ptype;
3065 			zend_hash_move_forward(&bp_types);
3066 		}
3067 	}
3068 	if (zend_hash_num_elements(&bp_encoders)) {
3069 		encodePtr **tmp, *penc = NULL;
3070 
3071 		zend_hash_internal_pointer_reset(&bp_encoders);
3072 		while (zend_hash_get_current_data(&bp_encoders, (void**)&tmp) == SUCCESS) {
3073 			if (zend_hash_find(&ptr_map, (char*)(*tmp), sizeof(**tmp), (void**)&penc) == FAILURE) {
3074 				assert(0);
3075 			}
3076 			**tmp = *penc;
3077 			zend_hash_move_forward(&bp_encoders);
3078 		}
3079 	}
3080 
3081 
3082 	if (sdl->bindings) {
3083 		sdlBindingPtr *tmp;
3084 		sdlBindingPtr pbind;
3085 
3086 		psdl->bindings = malloc(sizeof(HashTable));
3087 		zend_hash_init(psdl->bindings, zend_hash_num_elements(sdl->bindings), NULL, delete_binding_persistent, 1);
3088 
3089 		zend_hash_internal_pointer_reset(sdl->bindings);
3090 		while (zend_hash_get_current_data(sdl->bindings, (void **)&tmp) == SUCCESS) {
3091 			pbind = make_persistent_sdl_binding(*tmp, &ptr_map);
3092 			if (zend_hash_get_current_key_ex(sdl->bindings, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3093 				zend_hash_add(psdl->bindings, key, key_len, (void*)&pbind, sizeof(sdlBindingPtr), NULL);
3094 			} else {
3095 				zend_hash_next_index_insert(psdl->bindings, (void*)&pbind, sizeof(sdlBindingPtr), NULL);
3096 			}
3097 			zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&pbind, sizeof(sdlBindingPtr), NULL);
3098 			zend_hash_move_forward(sdl->bindings);
3099 		}
3100 	}
3101 
3102 	zend_hash_init(&psdl->functions, zend_hash_num_elements(&sdl->functions), NULL, delete_function_persistent, 1);
3103 	if (zend_hash_num_elements(&sdl->functions)) {
3104 		sdlFunctionPtr *tmp;
3105 		sdlFunctionPtr pfunc;
3106 
3107 		zend_hash_internal_pointer_reset(&sdl->functions);
3108 		while (zend_hash_get_current_data(&sdl->functions, (void **)&tmp) == SUCCESS) {
3109 			pfunc = make_persistent_sdl_function(*tmp, &ptr_map);
3110 			if (zend_hash_get_current_key_ex(&sdl->functions, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3111 				zend_hash_add(&psdl->functions, key, key_len, (void*)&pfunc, sizeof(sdlFunctionPtr), NULL);
3112 			} else {
3113 				zend_hash_next_index_insert(&psdl->functions, (void*)&pfunc, sizeof(sdlFunctionPtr), NULL);
3114 			}
3115 			zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&pfunc, sizeof(sdlFunctionPtr), NULL);
3116 			zend_hash_move_forward(&sdl->functions);
3117 		}
3118 	}
3119 
3120 	if (sdl->requests) {
3121 		sdlFunctionPtr *tmp;
3122 		sdlFunctionPtr *preq;
3123 
3124 		psdl->requests = malloc(sizeof(HashTable));
3125 		zend_hash_init(psdl->requests, zend_hash_num_elements(sdl->requests), NULL, NULL, 1);
3126 
3127 		zend_hash_internal_pointer_reset(sdl->requests);
3128 		while (zend_hash_get_current_data(sdl->requests, (void **)&tmp) == SUCCESS) {
3129 			if (zend_hash_find(&ptr_map, (char*)tmp, sizeof(*tmp), (void**)&preq) == FAILURE) {
3130 				assert(0);
3131 			}
3132 			*tmp = *preq;
3133 			if (zend_hash_get_current_key_ex(sdl->requests, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3134 				zend_hash_add(psdl->requests, key, key_len, (void*)&preq, sizeof(sdlFunctionPtr), NULL);
3135 			}
3136 			zend_hash_move_forward(sdl->requests);
3137 		}
3138 	}
3139 
3140 	zend_hash_destroy(&ptr_map);
3141 	zend_hash_destroy(&bp_encoders);
3142 	zend_hash_destroy(&bp_types);
3143 
3144 	return psdl;
3145 }
3146 
3147 typedef struct _sdl_cache_bucket {
3148 	sdlPtr sdl;
3149 	time_t time;
3150 } sdl_cache_bucket;
3151 
delete_psdl(void * data)3152 static void delete_psdl(void *data)
3153 {
3154 	sdl_cache_bucket *p = (sdl_cache_bucket*)data;
3155 	sdlPtr tmp = p->sdl;
3156 
3157 	zend_hash_destroy(&tmp->functions);
3158 	if (tmp->source) {
3159 		free(tmp->source);
3160 	}
3161 	if (tmp->target_ns) {
3162 		free(tmp->target_ns);
3163 	}
3164 	if (tmp->elements) {
3165 		zend_hash_destroy(tmp->elements);
3166 		free(tmp->elements);
3167 	}
3168 	if (tmp->encoders) {
3169 		zend_hash_destroy(tmp->encoders);
3170 		free(tmp->encoders);
3171 	}
3172 	if (tmp->types) {
3173 		zend_hash_destroy(tmp->types);
3174 		free(tmp->types);
3175 	}
3176 	if (tmp->groups) {
3177 		zend_hash_destroy(tmp->groups);
3178 		free(tmp->groups);
3179 	}
3180 	if (tmp->bindings) {
3181 		zend_hash_destroy(tmp->bindings);
3182 		free(tmp->bindings);
3183 	}
3184 	if (tmp->requests) {
3185 		zend_hash_destroy(tmp->requests);
3186 		free(tmp->requests);
3187 	}
3188 	free(tmp);
3189 }
3190 
get_sdl(zval * this_ptr,char * uri,long cache_wsdl TSRMLS_DC)3191 sdlPtr get_sdl(zval *this_ptr, char *uri, long cache_wsdl TSRMLS_DC)
3192 {
3193 	char  fn[MAXPATHLEN];
3194 	sdlPtr sdl = NULL;
3195 	char* old_error_code = SOAP_GLOBAL(error_code);
3196 	int uri_len = 0;
3197 	php_stream_context *context=NULL;
3198 	zval **tmp, **proxy_host, **proxy_port, *orig_context = NULL, *new_context = NULL;
3199 	smart_str headers = {0};
3200 	char* key = NULL;
3201 	time_t t = time(0);
3202 	zend_bool has_proxy_authorization = 0;
3203 	zend_bool has_authorization = 0;
3204 
3205 	if (strchr(uri,':') != NULL || IS_ABSOLUTE_PATH(uri, uri_len)) {
3206 		uri_len = strlen(uri);
3207 	} else if (VCWD_REALPATH(uri, fn) == NULL) {
3208 		cache_wsdl = WSDL_CACHE_NONE;
3209 	} else {
3210 		uri = fn;
3211 		uri_len = strlen(uri);
3212 	}
3213 
3214 	if ((cache_wsdl & WSDL_CACHE_MEMORY) && SOAP_GLOBAL(mem_cache)) {
3215 		sdl_cache_bucket *p;
3216 
3217 		if (SUCCESS == zend_hash_find(SOAP_GLOBAL(mem_cache), uri, uri_len+1, (void*)&p)) {
3218 			if (p->time < t - SOAP_GLOBAL(cache_ttl)) {
3219 				/* in-memory cache entry is expired */
3220 				zend_hash_del(&EG(persistent_list), uri, uri_len+1);
3221 			} else {
3222 				return p->sdl;
3223 			}
3224 		}
3225 	}
3226 
3227 	if ((cache_wsdl & WSDL_CACHE_DISK) && (uri_len < MAXPATHLEN)) {
3228 		time_t t = time(0);
3229 		char md5str[33];
3230 		PHP_MD5_CTX context;
3231 		unsigned char digest[16];
3232 		int len = strlen(SOAP_GLOBAL(cache_dir));
3233 		time_t cached;
3234 		char *user = php_get_current_user(TSRMLS_C);
3235 		int user_len = user ? strlen(user) + 1 : 0;
3236 
3237 		md5str[0] = '\0';
3238 		PHP_MD5Init(&context);
3239 		PHP_MD5Update(&context, (unsigned char*)uri, uri_len);
3240 		PHP_MD5Final(digest, &context);
3241 		make_digest(md5str, digest);
3242 		key = emalloc(len+sizeof("/wsdl-")-1+user_len+sizeof(md5str));
3243 		memcpy(key,SOAP_GLOBAL(cache_dir),len);
3244 		memcpy(key+len,"/wsdl-",sizeof("/wsdl-")-1);
3245 		len += sizeof("/wsdl-")-1;
3246 		if (user_len) {
3247 			memcpy(key+len, user, user_len-1);
3248 			len += user_len-1;
3249 			key[len++] = '-';
3250 		}
3251 		memcpy(key+len,md5str,sizeof(md5str));
3252 
3253 		if ((sdl = get_sdl_from_cache(key, uri, t-SOAP_GLOBAL(cache_ttl), &cached TSRMLS_CC)) != NULL) {
3254 			t = cached;
3255 			efree(key);
3256 			goto cache_in_memory;
3257 		}
3258 	}
3259 
3260 	if (SUCCESS == zend_hash_find(Z_OBJPROP_P(this_ptr),
3261 			"_stream_context", sizeof("_stream_context"), (void**)&tmp)) {
3262 		context = php_stream_context_from_zval(*tmp, 0);
3263 	} else {
3264 		context = php_stream_context_alloc(TSRMLS_C);
3265 	}
3266 
3267 	if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_user_agent", sizeof("_user_agent"), (void **) &tmp) == SUCCESS &&
3268 	    Z_TYPE_PP(tmp) == IS_STRING && Z_STRLEN_PP(tmp) > 0) {
3269 		smart_str_appends(&headers, "User-Agent: ");
3270 		smart_str_appends(&headers, Z_STRVAL_PP(tmp));
3271 		smart_str_appends(&headers, "\r\n");
3272 	}
3273 
3274 	if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_host", sizeof("_proxy_host"), (void **) &proxy_host) == SUCCESS &&
3275 	    Z_TYPE_PP(proxy_host) == IS_STRING &&
3276 	    zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_port", sizeof("_proxy_port"), (void **) &proxy_port) == SUCCESS &&
3277 	    Z_TYPE_PP(proxy_port) == IS_LONG) {
3278 	    	zval str_port, *str_proxy;
3279 	    	smart_str proxy = {0};
3280 		str_port = **proxy_port;
3281 		zval_copy_ctor(&str_port);
3282 		convert_to_string(&str_port);
3283 		smart_str_appends(&proxy,"tcp://");
3284 		smart_str_appends(&proxy,Z_STRVAL_PP(proxy_host));
3285 		smart_str_appends(&proxy,":");
3286 		smart_str_appends(&proxy,Z_STRVAL(str_port));
3287 		smart_str_0(&proxy);
3288 		zval_dtor(&str_port);
3289 		MAKE_STD_ZVAL(str_proxy);
3290 		ZVAL_STRING(str_proxy, proxy.c, 1);
3291 		smart_str_free(&proxy);
3292 
3293 		if (!context) {
3294 			context = php_stream_context_alloc(TSRMLS_C);
3295 		}
3296 		php_stream_context_set_option(context, "http", "proxy", str_proxy);
3297 		zval_ptr_dtor(&str_proxy);
3298 
3299 		if (uri_len < sizeof("https://")-1 ||
3300 		    strncasecmp(uri, "https://", sizeof("https://")-1) != 0) {
3301 			MAKE_STD_ZVAL(str_proxy);
3302 			ZVAL_BOOL(str_proxy, 1);
3303 			php_stream_context_set_option(context, "http", "request_fulluri", str_proxy);
3304 			zval_ptr_dtor(&str_proxy);
3305 		}
3306 
3307 		has_proxy_authorization = proxy_authentication(this_ptr, &headers TSRMLS_CC);
3308 	}
3309 
3310 	has_authorization = basic_authentication(this_ptr, &headers TSRMLS_CC);
3311 
3312 	/* Use HTTP/1.1 with "Connection: close" by default */
3313 	if (php_stream_context_get_option(context, "http", "protocol_version", &tmp) == FAILURE) {
3314     	zval *http_version;
3315 		MAKE_STD_ZVAL(http_version);
3316 		ZVAL_DOUBLE(http_version, 1.1);
3317 		php_stream_context_set_option(context, "http", "protocol_version", http_version);
3318 		zval_ptr_dtor(&http_version);
3319 		smart_str_appendl(&headers, "Connection: close\r\n", sizeof("Connection: close\r\n")-1);
3320 	}
3321 
3322 	if (headers.len > 0) {
3323 		zval *str_headers;
3324 
3325 		if (!context) {
3326 			context = php_stream_context_alloc(TSRMLS_C);
3327 		} else {
3328 			http_context_headers(context, has_authorization, has_proxy_authorization, 0, &headers TSRMLS_CC);
3329 		}
3330 
3331 		smart_str_0(&headers);
3332 		MAKE_STD_ZVAL(str_headers);
3333 		ZVAL_STRING(str_headers, headers.c, 1);
3334 		php_stream_context_set_option(context, "http", "header", str_headers);
3335 		smart_str_free(&headers);
3336 		zval_ptr_dtor(&str_headers);
3337 	}
3338 
3339 	if (context) {
3340 		MAKE_STD_ZVAL(new_context);
3341 		php_stream_context_to_zval(context, new_context);
3342 		orig_context = php_libxml_switch_context(new_context TSRMLS_CC);
3343 	}
3344 
3345 	SOAP_GLOBAL(error_code) = "WSDL";
3346 
3347 	sdl = load_wsdl(this_ptr, uri TSRMLS_CC);
3348 	if (sdl) {
3349 		sdl->is_persistent = 0;
3350 	}
3351 
3352 	SOAP_GLOBAL(error_code) = old_error_code;
3353 
3354 	if (context) {
3355 		php_libxml_switch_context(orig_context TSRMLS_CC);
3356 		zval_ptr_dtor(&new_context);
3357 	}
3358 
3359 	if ((cache_wsdl & WSDL_CACHE_DISK) && key) {
3360 		if (sdl) {
3361 			add_sdl_to_cache(key, uri, t, sdl TSRMLS_CC);
3362 		}
3363 		efree(key);
3364 	}
3365 
3366 cache_in_memory:
3367 	if (cache_wsdl & WSDL_CACHE_MEMORY) {
3368 		if (sdl) {
3369 			sdlPtr psdl;
3370 			sdl_cache_bucket p;
3371 
3372 			if (SOAP_GLOBAL(mem_cache) == NULL) {
3373 				SOAP_GLOBAL(mem_cache) = malloc(sizeof(HashTable));
3374 				zend_hash_init(SOAP_GLOBAL(mem_cache), 0, NULL, delete_psdl, 1);
3375 			} else if (SOAP_GLOBAL(cache_limit) > 0 &&
3376 			           SOAP_GLOBAL(cache_limit) <= zend_hash_num_elements(SOAP_GLOBAL(mem_cache))) {
3377 				/* in-memory cache overflow */
3378 				sdl_cache_bucket *q;
3379 				HashPosition pos;
3380 				time_t latest = t;
3381 				char *key = NULL;
3382 				uint key_len;
3383 				ulong idx;
3384 
3385 				for (zend_hash_internal_pointer_reset_ex(SOAP_GLOBAL(mem_cache), &pos);
3386 					 zend_hash_get_current_data_ex(SOAP_GLOBAL(mem_cache), (void **) &q, &pos) == SUCCESS;
3387 					 zend_hash_move_forward_ex(SOAP_GLOBAL(mem_cache), &pos)) {
3388 					if (q->time < latest) {
3389 						latest = q->time;
3390 						zend_hash_get_current_key_ex(SOAP_GLOBAL(mem_cache), &key, &key_len, &idx, 0, &pos);
3391 					}
3392 				}
3393 				if (key) {
3394 					zend_hash_del(SOAP_GLOBAL(mem_cache), key, key_len);
3395 				} else {
3396 					return sdl;
3397 				}
3398 			}
3399 
3400 			psdl = make_persistent_sdl(sdl TSRMLS_CC);
3401 			psdl->is_persistent = 1;
3402 			p.time = t;
3403 			p.sdl = psdl;
3404 
3405 			if (SUCCESS == zend_hash_update(SOAP_GLOBAL(mem_cache), uri,
3406 											uri_len+1, (void*)&p, sizeof(sdl_cache_bucket), NULL)) {
3407 				/* remove non-persitent sdl structure */
3408 				delete_sdl_impl(sdl);
3409 				/* and replace it with persistent one */
3410 				sdl = psdl;
3411 			} else {
3412 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to register persistent entry");
3413 				/* clean up persistent sdl */
3414 				delete_psdl(&p);
3415 				/* keep non-persistent sdl and return it */
3416 			}
3417 		}
3418 	}
3419 
3420 	return sdl;
3421 }
3422 
3423 /* Deletes */
delete_sdl_impl(void * handle)3424 void delete_sdl_impl(void *handle)
3425 {
3426 	sdlPtr tmp = (sdlPtr)handle;
3427 
3428 	zend_hash_destroy(&tmp->functions);
3429 	if (tmp->source) {
3430 		efree(tmp->source);
3431 	}
3432 	if (tmp->target_ns) {
3433 		efree(tmp->target_ns);
3434 	}
3435 	if (tmp->elements) {
3436 		zend_hash_destroy(tmp->elements);
3437 		efree(tmp->elements);
3438 	}
3439 	if (tmp->encoders) {
3440 		zend_hash_destroy(tmp->encoders);
3441 		efree(tmp->encoders);
3442 	}
3443 	if (tmp->types) {
3444 		zend_hash_destroy(tmp->types);
3445 		efree(tmp->types);
3446 	}
3447 	if (tmp->groups) {
3448 		zend_hash_destroy(tmp->groups);
3449 		efree(tmp->groups);
3450 	}
3451 	if (tmp->bindings) {
3452 		zend_hash_destroy(tmp->bindings);
3453 		efree(tmp->bindings);
3454 	}
3455 	if (tmp->requests) {
3456 		zend_hash_destroy(tmp->requests);
3457 		efree(tmp->requests);
3458 	}
3459 	efree(tmp);
3460 }
3461 
delete_sdl(void * handle)3462 void delete_sdl(void *handle)
3463 {
3464 	sdlPtr tmp = (sdlPtr)handle;
3465 
3466 	if (!tmp->is_persistent) {
3467 		delete_sdl_impl(tmp);
3468 	}
3469 }
3470 
delete_binding(void * data)3471 static void delete_binding(void *data)
3472 {
3473 	sdlBindingPtr binding = *((sdlBindingPtr*)data);
3474 
3475 	if (binding->location) {
3476 		efree(binding->location);
3477 	}
3478 	if (binding->name) {
3479 		efree(binding->name);
3480 	}
3481 
3482 	if (binding->bindingType == BINDING_SOAP) {
3483 		sdlSoapBindingPtr soapBind = binding->bindingAttributes;
3484 		if (soapBind) {
3485 			efree(soapBind);
3486 		}
3487 	}
3488 	efree(binding);
3489 }
3490 
delete_binding_persistent(void * data)3491 static void delete_binding_persistent(void *data)
3492 {
3493 	sdlBindingPtr binding = *((sdlBindingPtr*)data);
3494 
3495 	if (binding->location) {
3496 		free(binding->location);
3497 	}
3498 	if (binding->name) {
3499 		free(binding->name);
3500 	}
3501 
3502 	if (binding->bindingType == BINDING_SOAP) {
3503 		sdlSoapBindingPtr soapBind = binding->bindingAttributes;
3504 		if (soapBind) {
3505 			free(soapBind);
3506 		}
3507 	}
3508 	free(binding);
3509 }
3510 
delete_sdl_soap_binding_function_body(sdlSoapBindingFunctionBody body)3511 static void delete_sdl_soap_binding_function_body(sdlSoapBindingFunctionBody body)
3512 {
3513 	if (body.ns) {
3514 		efree(body.ns);
3515 	}
3516 	if (body.headers) {
3517 		zend_hash_destroy(body.headers);
3518 		efree(body.headers);
3519 	}
3520 }
3521 
delete_sdl_soap_binding_function_body_persistent(sdlSoapBindingFunctionBody body)3522 static void delete_sdl_soap_binding_function_body_persistent(sdlSoapBindingFunctionBody body)
3523 {
3524 	if (body.ns) {
3525 		free(body.ns);
3526 	}
3527 	if (body.headers) {
3528 		zend_hash_destroy(body.headers);
3529 		free(body.headers);
3530 	}
3531 }
3532 
delete_function(void * data)3533 static void delete_function(void *data)
3534 {
3535 	sdlFunctionPtr function = *((sdlFunctionPtr*)data);
3536 
3537 	if (function->functionName) {
3538 		efree(function->functionName);
3539 	}
3540 	if (function->requestName) {
3541 		efree(function->requestName);
3542 	}
3543 	if (function->responseName) {
3544 		efree(function->responseName);
3545 	}
3546 	if (function->requestParameters) {
3547 		zend_hash_destroy(function->requestParameters);
3548 		efree(function->requestParameters);
3549 	}
3550 	if (function->responseParameters) {
3551 		zend_hash_destroy(function->responseParameters);
3552 		efree(function->responseParameters);
3553 	}
3554 	if (function->faults) {
3555 		zend_hash_destroy(function->faults);
3556 		efree(function->faults);
3557 	}
3558 
3559 	if (function->bindingAttributes &&
3560 	    function->binding && function->binding->bindingType == BINDING_SOAP) {
3561 		sdlSoapBindingFunctionPtr soapFunction = function->bindingAttributes;
3562 		if (soapFunction->soapAction) {
3563 			efree(soapFunction->soapAction);
3564 		}
3565 		delete_sdl_soap_binding_function_body(soapFunction->input);
3566 		delete_sdl_soap_binding_function_body(soapFunction->output);
3567 		efree(soapFunction);
3568 	}
3569 	efree(function);
3570 }
3571 
delete_function_persistent(void * data)3572 static void delete_function_persistent(void *data)
3573 {
3574 	sdlFunctionPtr function = *((sdlFunctionPtr*)data);
3575 
3576 	if (function->functionName) {
3577 		free(function->functionName);
3578 	}
3579 	if (function->requestName) {
3580 		free(function->requestName);
3581 	}
3582 	if (function->responseName) {
3583 		free(function->responseName);
3584 	}
3585 	if (function->requestParameters) {
3586 		zend_hash_destroy(function->requestParameters);
3587 		free(function->requestParameters);
3588 	}
3589 	if (function->responseParameters) {
3590 		zend_hash_destroy(function->responseParameters);
3591 		free(function->responseParameters);
3592 	}
3593 	if (function->faults) {
3594 		zend_hash_destroy(function->faults);
3595 		free(function->faults);
3596 	}
3597 
3598 	if (function->bindingAttributes &&
3599 	    function->binding && function->binding->bindingType == BINDING_SOAP) {
3600 		sdlSoapBindingFunctionPtr soapFunction = function->bindingAttributes;
3601 		if (soapFunction->soapAction) {
3602 			free(soapFunction->soapAction);
3603 		}
3604 		delete_sdl_soap_binding_function_body_persistent(soapFunction->input);
3605 		delete_sdl_soap_binding_function_body_persistent(soapFunction->output);
3606 		free(soapFunction);
3607 	}
3608 	free(function);
3609 }
3610 
delete_parameter(void * data)3611 static void delete_parameter(void *data)
3612 {
3613 	sdlParamPtr param = *((sdlParamPtr*)data);
3614 	if (param->paramName) {
3615 		efree(param->paramName);
3616 	}
3617 	efree(param);
3618 }
3619 
delete_parameter_persistent(void * data)3620 static void delete_parameter_persistent(void *data)
3621 {
3622 	sdlParamPtr param = *((sdlParamPtr*)data);
3623 	if (param->paramName) {
3624 		free(param->paramName);
3625 	}
3626 	free(param);
3627 }
3628 
delete_header(void * data)3629 static void delete_header(void *data)
3630 {
3631 	sdlSoapBindingFunctionHeaderPtr hdr = *((sdlSoapBindingFunctionHeaderPtr*)data);
3632 	if (hdr->name) {
3633 		efree(hdr->name);
3634 	}
3635 	if (hdr->ns) {
3636 		efree(hdr->ns);
3637 	}
3638 	if (hdr->headerfaults) {
3639 		zend_hash_destroy(hdr->headerfaults);
3640 		efree(hdr->headerfaults);
3641 	}
3642 	efree(hdr);
3643 }
3644 
delete_header_persistent(void * data)3645 static void delete_header_persistent(void *data)
3646 {
3647 	sdlSoapBindingFunctionHeaderPtr hdr = *((sdlSoapBindingFunctionHeaderPtr*)data);
3648 	if (hdr->name) {
3649 		free(hdr->name);
3650 	}
3651 	if (hdr->ns) {
3652 		free(hdr->ns);
3653 	}
3654 	if (hdr->headerfaults) {
3655 		zend_hash_destroy(hdr->headerfaults);
3656 		free(hdr->headerfaults);
3657 	}
3658 	free(hdr);
3659 }
3660 
delete_fault(void * data)3661 static void delete_fault(void *data)
3662 {
3663 	sdlFaultPtr fault = *((sdlFaultPtr*)data);
3664 	if (fault->name) {
3665 		efree(fault->name);
3666 	}
3667 	if (fault->details) {
3668 		zend_hash_destroy(fault->details);
3669 		efree(fault->details);
3670 	}
3671 	if (fault->bindingAttributes) {
3672 		sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
3673 
3674 		if (binding->ns) {
3675 			efree(binding->ns);
3676 		}
3677 		efree(fault->bindingAttributes);
3678 	}
3679 	efree(fault);
3680 }
3681 
delete_fault_persistent(void * data)3682 static void delete_fault_persistent(void *data)
3683 {
3684 	sdlFaultPtr fault = *((sdlFaultPtr*)data);
3685 	if (fault->name) {
3686 		free(fault->name);
3687 	}
3688 	if (fault->details) {
3689 		zend_hash_destroy(fault->details);
3690 		free(fault->details);
3691 	}
3692 	if (fault->bindingAttributes) {
3693 		sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
3694 
3695 		if (binding->ns) {
3696 			free(binding->ns);
3697 		}
3698 		free(fault->bindingAttributes);
3699 	}
3700 	free(fault);
3701 }
3702 
delete_document(void * doc_ptr)3703 static void delete_document(void *doc_ptr)
3704 {
3705 	xmlDocPtr doc = *((xmlDocPtr*)doc_ptr);
3706 	xmlFreeDoc(doc);
3707 }
3708 
3709