xref: /PHP-5.5/ext/soap/php_sdl.c (revision 73c1be26)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2015 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 "tsrm_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 = strlen(ns);
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 				zend_hash_add(ctx.sdl->bindings, tmpbinding->name, strlen(tmpbinding->name), &tmpbinding, sizeof(sdlBindingPtr), NULL);
1161 				trav= trav->next;
1162 			}
1163 
1164 			zend_hash_move_forward(&ctx.services);
1165 		}
1166 	} else {
1167 		soap_error0(E_ERROR, "Parsing WSDL: Couldn't bind to service");
1168 	}
1169 
1170 	if (ctx.sdl->bindings == NULL || ctx.sdl->bindings->nNumOfElements == 0) {
1171 		soap_error0(E_ERROR, "Parsing WSDL: Could not find any usable binding services in WSDL.");
1172 	}
1173 
1174 	zend_hash_destroy(&ctx.messages);
1175 	zend_hash_destroy(&ctx.bindings);
1176 	zend_hash_destroy(&ctx.portTypes);
1177 	zend_hash_destroy(&ctx.services);
1178 	zend_hash_destroy(&ctx.docs);
1179 
1180 	return ctx.sdl;
1181 }
1182 
1183 #define WSDL_CACHE_VERSION 0x0e
1184 
1185 #define WSDL_CACHE_GET(ret,type,buf)   memcpy(&ret,*buf,sizeof(type)); *buf += sizeof(type);
1186 #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;
1187 #define WSDL_CACHE_GET_1(ret,type,buf) ret = (type)(**buf); (*buf)++;
1188 #define WSDL_CACHE_GET_N(ret,n,buf)    memcpy(ret,*buf,n); *buf += n;
1189 #define WSDL_CACHE_SKIP(n,buf)         *buf += n;
1190 
1191 #define WSDL_CACHE_PUT_INT(val,buf)    smart_str_appendc(buf,val & 0xff); \
1192                                        smart_str_appendc(buf,(val >> 8) & 0xff); \
1193                                        smart_str_appendc(buf,(val >> 16) & 0xff); \
1194                                        smart_str_appendc(buf,(val >> 24) & 0xff);
1195 #define WSDL_CACHE_PUT_1(val,buf)      smart_str_appendc(buf,val);
1196 #define WSDL_CACHE_PUT_N(val,n,buf)    smart_str_appendl(buf,(char*)val,n);
1197 
sdl_deserialize_string(char ** in)1198 static char* sdl_deserialize_string(char **in)
1199 {
1200 	char *s;
1201 	int len;
1202 
1203 	WSDL_CACHE_GET_INT(len, in);
1204 	if (len == 0x7fffffff) {
1205 		return NULL;
1206 	} else {
1207 		s = emalloc(len+1);
1208 		WSDL_CACHE_GET_N(s, len, in);
1209 		s[len] = '\0';
1210 		return s;
1211 	}
1212 }
1213 
sdl_deserialize_key(HashTable * ht,void * data,char ** in)1214 static void sdl_deserialize_key(HashTable* ht, void* data, char **in)
1215 {
1216 	int len;
1217 
1218 	WSDL_CACHE_GET_INT(len, in);
1219 	if (len == 0) {
1220 		zend_hash_next_index_insert(ht, &data, sizeof(void*), NULL);
1221 	} else {
1222 		zend_hash_add(ht, *in, len, &data, sizeof(void*), NULL);
1223 		WSDL_CACHE_SKIP(len, in);
1224 	}
1225 }
1226 
sdl_deserialize_attribute(sdlAttributePtr attr,encodePtr * encoders,char ** in)1227 static void sdl_deserialize_attribute(sdlAttributePtr attr, encodePtr *encoders, char **in)
1228 {
1229 	int i;
1230 
1231 	attr->name = sdl_deserialize_string(in);
1232 	attr->namens = sdl_deserialize_string(in);
1233 	attr->ref = sdl_deserialize_string(in);
1234 	attr->def = sdl_deserialize_string(in);
1235 	attr->fixed = sdl_deserialize_string(in);
1236 	WSDL_CACHE_GET_1(attr->form, sdlForm, in);
1237 	WSDL_CACHE_GET_1(attr->use, sdlUse, in);
1238 	WSDL_CACHE_GET_INT(i, in);
1239 	attr->encode = encoders[i];
1240 	WSDL_CACHE_GET_INT(i, in);
1241 	if (i > 0) {
1242 		attr->extraAttributes = emalloc(sizeof(HashTable));
1243 		zend_hash_init(attr->extraAttributes, i, NULL, delete_extra_attribute, 0);
1244 		while (i > 0) {
1245 			sdlExtraAttributePtr x = emalloc(sizeof(sdlExtraAttribute));
1246 			sdl_deserialize_key(attr->extraAttributes, x, in);
1247 			x->ns = sdl_deserialize_string(in);
1248 			x->val = sdl_deserialize_string(in);
1249 			--i;
1250 		}
1251 	}
1252 }
1253 
sdl_deserialize_resriction_int(char ** in)1254 static sdlRestrictionIntPtr sdl_deserialize_resriction_int(char **in)
1255 {
1256 	if (**in == 1) {
1257 		sdlRestrictionIntPtr x = emalloc(sizeof(sdlRestrictionInt));
1258 		WSDL_CACHE_SKIP(1, in);
1259 		WSDL_CACHE_GET_INT(x->value, in);
1260 		WSDL_CACHE_GET_1(x->fixed, char, in);
1261 		return x;
1262 	} else {
1263 		WSDL_CACHE_SKIP(1, in);
1264 		return NULL;
1265 	}
1266 }
1267 
sdl_deserialize_resriction_char(char ** in)1268 static sdlRestrictionCharPtr sdl_deserialize_resriction_char(char **in)
1269 {
1270 	if (**in == 1) {
1271 		sdlRestrictionCharPtr x = emalloc(sizeof(sdlRestrictionChar));
1272 		WSDL_CACHE_SKIP(1, in);
1273 		x->value = sdl_deserialize_string(in);
1274 		WSDL_CACHE_GET_1(x->fixed, char, in);
1275 		return x;
1276 	} else {
1277 		WSDL_CACHE_SKIP(1, in);
1278 		return NULL;
1279 	}
1280 }
1281 
sdl_deserialize_model(sdlTypePtr * types,sdlTypePtr * elements,char ** in)1282 static sdlContentModelPtr sdl_deserialize_model(sdlTypePtr *types, sdlTypePtr *elements, char **in)
1283 {
1284 	int i;
1285 	sdlContentModelPtr model = emalloc(sizeof(sdlContentModel));
1286 
1287 	WSDL_CACHE_GET_1(model->kind, sdlContentKind, in);
1288 	WSDL_CACHE_GET_INT(model->min_occurs, in);
1289 	WSDL_CACHE_GET_INT(model->max_occurs, in);
1290 	switch (model->kind) {
1291 		case XSD_CONTENT_ELEMENT:
1292 			WSDL_CACHE_GET_INT(i, in);
1293 			model->u.element = elements[i];
1294 			break;
1295 		case XSD_CONTENT_SEQUENCE:
1296 		case XSD_CONTENT_ALL:
1297 		case XSD_CONTENT_CHOICE:
1298 			WSDL_CACHE_GET_INT(i, in);
1299 			model->u.content = emalloc(sizeof(HashTable));
1300 			zend_hash_init(model->u.content, i, NULL, delete_model, 0);
1301 			while (i > 0) {
1302 				sdlContentModelPtr x = sdl_deserialize_model(types, elements, in);
1303 				zend_hash_next_index_insert(model->u.content,&x,sizeof(sdlContentModelPtr),NULL);
1304 				i--;
1305 			}
1306 			break;
1307 		case XSD_CONTENT_GROUP_REF:
1308 			model->u.group_ref = sdl_deserialize_string(in);
1309 			break;
1310 		case XSD_CONTENT_GROUP:
1311 			WSDL_CACHE_GET_INT(i, in);
1312 			model->u.group = types[i];
1313 			break;
1314 		default:
1315 			break;
1316 	}
1317 	return model;
1318 }
1319 
sdl_deserialize_type(sdlTypePtr type,sdlTypePtr * types,encodePtr * encoders,char ** in)1320 static void sdl_deserialize_type(sdlTypePtr type, sdlTypePtr *types, encodePtr *encoders, char **in)
1321 {
1322 	int i;
1323 	sdlTypePtr *elements = NULL;
1324 
1325 	WSDL_CACHE_GET_1(type->kind, sdlTypeKind, in);
1326 	type->name = sdl_deserialize_string(in);
1327 	type->namens = sdl_deserialize_string(in);
1328 	type->def = sdl_deserialize_string(in);
1329 	type->fixed = sdl_deserialize_string(in);
1330 	type->ref = sdl_deserialize_string(in);
1331 	WSDL_CACHE_GET_1(type->nillable, char, in);
1332 	WSDL_CACHE_GET_1(type->form, sdlForm, in);
1333 
1334 	WSDL_CACHE_GET_INT(i, in);
1335 	type->encode = encoders[i];
1336 
1337 	if (**in == 1) {
1338 		WSDL_CACHE_SKIP(1, in);
1339 		type->restrictions = emalloc(sizeof(sdlRestrictions));
1340 		/*memset(type->restrictions, 0, sizeof(sdlRestrictions));*/
1341 		type->restrictions->minExclusive = sdl_deserialize_resriction_int(in);
1342 		type->restrictions->minInclusive = sdl_deserialize_resriction_int(in);
1343 		type->restrictions->maxExclusive = sdl_deserialize_resriction_int(in);
1344 		type->restrictions->maxInclusive = sdl_deserialize_resriction_int(in);
1345 		type->restrictions->totalDigits = sdl_deserialize_resriction_int(in);
1346 		type->restrictions->fractionDigits = sdl_deserialize_resriction_int(in);
1347 		type->restrictions->length = sdl_deserialize_resriction_int(in);
1348 		type->restrictions->minLength = sdl_deserialize_resriction_int(in);
1349 		type->restrictions->maxLength = sdl_deserialize_resriction_int(in);
1350 		type->restrictions->whiteSpace = sdl_deserialize_resriction_char(in);
1351 		type->restrictions->pattern = sdl_deserialize_resriction_char(in);
1352 		WSDL_CACHE_GET_INT(i, in);
1353 		if (i > 0) {
1354 			type->restrictions->enumeration = emalloc(sizeof(HashTable));
1355 			zend_hash_init(type->restrictions->enumeration, i, NULL, delete_restriction_var_char, 0);
1356 			while (i > 0) {
1357 				sdlRestrictionCharPtr x = sdl_deserialize_resriction_char(in);
1358 				sdl_deserialize_key(type->restrictions->enumeration, x, in);
1359 				--i;
1360 			}
1361 		} else {
1362 			type->restrictions->enumeration = NULL;
1363 		}
1364 	} else {
1365 		WSDL_CACHE_SKIP(1, in);
1366 	}
1367 
1368 	WSDL_CACHE_GET_INT(i, in);
1369 	if (i > 0) {
1370 		elements = safe_emalloc((i+1), sizeof(sdlTypePtr), 0);
1371 		elements[0] = NULL;
1372 		type->elements = emalloc(sizeof(HashTable));
1373 		zend_hash_init(type->elements, i, NULL, delete_type, 0);
1374 		while (i > 0) {
1375 			sdlTypePtr t = emalloc(sizeof(sdlType));
1376 			memset(t, 0, sizeof(sdlType));
1377 			sdl_deserialize_key(type->elements, t, in);
1378 			sdl_deserialize_type(t, types, encoders, in);
1379 			elements[i] = t;
1380 			--i;
1381 		}
1382 	}
1383 
1384 	WSDL_CACHE_GET_INT(i, in);
1385 	if (i > 0) {
1386 		type->attributes = emalloc(sizeof(HashTable));
1387 		zend_hash_init(type->attributes, i, NULL, delete_attribute, 0);
1388 		while (i > 0) {
1389 			sdlAttributePtr attr = emalloc(sizeof(sdlAttribute));
1390 			memset(attr, 0, sizeof(sdlAttribute));
1391 			sdl_deserialize_key(type->attributes, attr, in);
1392 			sdl_deserialize_attribute(attr, encoders, in);
1393 			--i;
1394 		}
1395 	}
1396 
1397 	if (**in != 0) {
1398 		WSDL_CACHE_SKIP(1, in);
1399 		type->model = sdl_deserialize_model(types, elements, in);
1400 	} else {
1401 		WSDL_CACHE_SKIP(1, in);
1402 	}
1403 	if (elements != NULL) {
1404 		efree(elements);
1405 	}
1406 }
1407 
sdl_deserialize_encoder(encodePtr enc,sdlTypePtr * types,char ** in)1408 static void sdl_deserialize_encoder(encodePtr enc, sdlTypePtr *types, char **in)
1409 {
1410 	int i;
1411 
1412 	WSDL_CACHE_GET_INT(enc->details.type, in);
1413 	enc->details.type_str = sdl_deserialize_string(in);
1414 	enc->details.ns = sdl_deserialize_string(in);
1415 	WSDL_CACHE_GET_INT(i, in);
1416 	enc->details.sdl_type = types[i];
1417 	enc->to_xml = sdl_guess_convert_xml;
1418 	enc->to_zval = sdl_guess_convert_zval;
1419 
1420 	if (enc->details.sdl_type == NULL) {
1421 		int ns_len = strlen(enc->details.ns);
1422 		int type_len = strlen(enc->details.type_str);
1423 
1424 		if (((ns_len == sizeof(SOAP_1_1_ENC_NAMESPACE)-1 &&
1425 		      memcmp(enc->details.ns, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)-1) == 0) ||
1426 		     (ns_len == sizeof(SOAP_1_2_ENC_NAMESPACE)-1 &&
1427 		      memcmp(enc->details.ns, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)-1) == 0))) {
1428 			char *enc_nscat;
1429 			int enc_ns_len;
1430 			int enc_len;
1431 			encodePtr real_enc;
1432 
1433 			enc_ns_len = sizeof(XSD_NAMESPACE)-1;
1434 			enc_len = enc_ns_len + type_len + 1;
1435 			enc_nscat = emalloc(enc_len + 1);
1436 			memcpy(enc_nscat, XSD_NAMESPACE, sizeof(XSD_NAMESPACE)-1);
1437 			enc_nscat[enc_ns_len] = ':';
1438 			memcpy(enc_nscat+enc_ns_len+1, enc->details.type_str, type_len);
1439 			enc_nscat[enc_len] = '\0';
1440 
1441 			real_enc = get_encoder_ex(NULL, enc_nscat, enc_len);
1442 			efree(enc_nscat);
1443 			if (real_enc) {
1444 				enc->to_zval = real_enc->to_zval;
1445 				enc->to_xml = real_enc->to_xml;
1446 			}
1447 		}
1448 	}
1449 }
1450 
sdl_deserialize_soap_body(sdlSoapBindingFunctionBodyPtr body,encodePtr * encoders,sdlTypePtr * types,char ** in)1451 static void sdl_deserialize_soap_body(sdlSoapBindingFunctionBodyPtr body, encodePtr *encoders, sdlTypePtr *types, char **in)
1452 {
1453 	int i, j, n;
1454 
1455 	WSDL_CACHE_GET_1(body->use, sdlEncodingUse, in);
1456 	if (body->use == SOAP_ENCODED) {
1457 		WSDL_CACHE_GET_1(body->encodingStyle, sdlRpcEncodingStyle, in);
1458 	} else {
1459 		body->encodingStyle = SOAP_ENCODING_DEFAULT;
1460 	}
1461 	body->ns = sdl_deserialize_string(in);
1462 	WSDL_CACHE_GET_INT(i, in);
1463 	if (i > 0) {
1464 		body->headers = emalloc(sizeof(HashTable));
1465 		zend_hash_init(body->headers, i, NULL, delete_header, 0);
1466 		while (i > 0) {
1467 			sdlSoapBindingFunctionHeaderPtr tmp = emalloc(sizeof(sdlSoapBindingFunctionHeader));
1468 			memset(tmp, 0, sizeof(sdlSoapBindingFunctionHeader));
1469 			sdl_deserialize_key(body->headers, tmp, in);
1470 			WSDL_CACHE_GET_1(tmp->use, sdlEncodingUse, in);
1471 			if (tmp->use == SOAP_ENCODED) {
1472 				WSDL_CACHE_GET_1(tmp->encodingStyle, sdlRpcEncodingStyle, in);
1473 			} else {
1474 				tmp->encodingStyle = SOAP_ENCODING_DEFAULT;
1475 			}
1476 			tmp->name = sdl_deserialize_string(in);
1477 			tmp->ns = sdl_deserialize_string(in);
1478 			WSDL_CACHE_GET_INT(n, in);
1479 			tmp->encode = encoders[n];
1480 			WSDL_CACHE_GET_INT(n, in);
1481 			tmp->element = types[n];
1482 			--i;
1483 			WSDL_CACHE_GET_INT(j, in);
1484 			if (j > 0) {
1485 				tmp->headerfaults = emalloc(sizeof(HashTable));
1486 				zend_hash_init(tmp->headerfaults, i, NULL, delete_header, 0);
1487 				while (j > 0) {
1488 					sdlSoapBindingFunctionHeaderPtr tmp2 = emalloc(sizeof(sdlSoapBindingFunctionHeader));
1489 					memset(tmp2, 0, sizeof(sdlSoapBindingFunctionHeader));
1490 					sdl_deserialize_key(tmp->headerfaults, tmp2, in);
1491 					WSDL_CACHE_GET_1(tmp2->use, sdlEncodingUse, in);
1492 					if (tmp2->use == SOAP_ENCODED) {
1493 						WSDL_CACHE_GET_1(tmp2->encodingStyle, sdlRpcEncodingStyle, in);
1494 					} else {
1495 						tmp2->encodingStyle = SOAP_ENCODING_DEFAULT;
1496 					}
1497 					tmp2->name = sdl_deserialize_string(in);
1498 					tmp2->ns = sdl_deserialize_string(in);
1499 					WSDL_CACHE_GET_INT(n, in);
1500 					tmp2->encode = encoders[n];
1501 					WSDL_CACHE_GET_INT(n, in);
1502 					tmp2->element = types[n];
1503 					--j;
1504 				}
1505 			}
1506 		}
1507 	}
1508 }
1509 
sdl_deserialize_parameters(encodePtr * encoders,sdlTypePtr * types,char ** in)1510 static HashTable* sdl_deserialize_parameters(encodePtr *encoders, sdlTypePtr *types, char **in)
1511 {
1512 	int i, n;
1513 	HashTable *ht;
1514 
1515 	WSDL_CACHE_GET_INT(i, in);
1516 	if (i == 0) {return NULL;}
1517 	ht = emalloc(sizeof(HashTable));
1518 	zend_hash_init(ht, i, NULL, delete_parameter, 0);
1519 	while (i > 0) {
1520 		sdlParamPtr param = emalloc(sizeof(sdlParam));
1521 		sdl_deserialize_key(ht, param, in);
1522 		param->paramName = sdl_deserialize_string(in);
1523 		WSDL_CACHE_GET_INT(param->order, in);
1524 		WSDL_CACHE_GET_INT(n, in);
1525 		param->encode = encoders[n];
1526 		WSDL_CACHE_GET_INT(n, in);
1527 		param->element = types[n];
1528 		--i;
1529 	}
1530 	return ht;
1531 }
1532 
get_sdl_from_cache(const char * fn,const char * uri,time_t t,time_t * cached TSRMLS_DC)1533 static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t, time_t *cached TSRMLS_DC)
1534 {
1535 	sdlPtr sdl;
1536 	time_t old_t;
1537 	int  i, num_groups, num_types, num_elements, num_encoders, num_bindings, num_func;
1538 	sdlFunctionPtr *functions = NULL;
1539 	sdlBindingPtr *bindings;
1540 	sdlTypePtr *types;
1541 	encodePtr *encoders;
1542 	encodePtr enc;
1543 
1544 	int f;
1545 	struct stat st;
1546 	char *in, *buf;
1547 
1548 	f = open(fn, O_RDONLY|O_BINARY);
1549 	if (f < 0) {
1550 		return NULL;
1551 	}
1552 	if (fstat(f, &st) != 0) {
1553 		close(f);
1554 		return NULL;
1555 	}
1556 	buf = in = emalloc(st.st_size);
1557 	if (read(f, in, st.st_size) != st.st_size) {
1558 		close(f);
1559 		efree(in);
1560 		return NULL;
1561 	}
1562 	close(f);
1563 
1564 	if (strncmp(in,"wsdl",4) != 0 || in[4] != WSDL_CACHE_VERSION || in[5] != '\0') {
1565 		unlink(fn);
1566 		efree(buf);
1567 		return NULL;
1568 	}
1569 	in += 6;
1570 
1571 	WSDL_CACHE_GET(old_t, time_t, &in);
1572 	if (old_t < t) {
1573 		unlink(fn);
1574 		efree(buf);
1575 		return NULL;
1576 	}
1577 	*cached = old_t;
1578 
1579 	WSDL_CACHE_GET_INT(i, &in);
1580 	if (i == 0 && strncmp(in, uri, i) != 0) {
1581 		unlink(fn);
1582 		efree(buf);
1583 		return NULL;
1584 	}
1585 	WSDL_CACHE_SKIP(i, &in);
1586 
1587 	sdl = emalloc(sizeof(*sdl));
1588 	memset(sdl, 0, sizeof(*sdl));
1589 
1590 	sdl->source = sdl_deserialize_string(&in);
1591 	sdl->target_ns = sdl_deserialize_string(&in);
1592 
1593 	WSDL_CACHE_GET_INT(num_groups, &in);
1594 	WSDL_CACHE_GET_INT(num_types, &in);
1595 	WSDL_CACHE_GET_INT(num_elements, &in);
1596 	WSDL_CACHE_GET_INT(num_encoders, &in);
1597 
1598 	i = num_groups+num_types+num_elements;
1599 	types = safe_emalloc((i+1), sizeof(sdlTypePtr), 0);
1600 	types[0] = NULL;
1601 	while (i > 0) {
1602 		types[i] = emalloc(sizeof(sdlType));
1603 		memset(types[i], 0, sizeof(sdlType));
1604 		i--;
1605 	}
1606 
1607 	i = num_encoders;
1608 	enc = defaultEncoding;
1609 	while (enc->details.type != END_KNOWN_TYPES) {
1610 		i++; enc++;
1611 	}
1612 	encoders = safe_emalloc((i+1), sizeof(encodePtr), 0);
1613 	i = num_encoders;
1614 	encoders[0] = NULL;
1615 	while (i > 0) {
1616 		encoders[i] = emalloc(sizeof(encode));
1617 		memset(encoders[i], 0, sizeof(encode));
1618 		i--;
1619 	}
1620 	i = num_encoders;
1621 	enc = defaultEncoding;
1622 	while (enc->details.type != END_KNOWN_TYPES) {
1623 		encoders[++i] = enc++;
1624 	}
1625 
1626 	i = 1;
1627 	if (num_groups > 0) {
1628 		sdl->groups = emalloc(sizeof(HashTable));
1629 		zend_hash_init(sdl->groups, num_groups, NULL, delete_type, 0);
1630 		while (i < num_groups+1) {
1631 			sdl_deserialize_key(sdl->groups, types[i], &in);
1632 			sdl_deserialize_type(types[i], types, encoders, &in);
1633 			i++;
1634 		}
1635 	}
1636 
1637 	if (num_types > 0) {
1638 		sdl->types = emalloc(sizeof(HashTable));
1639 		zend_hash_init(sdl->types, num_types, NULL, delete_type, 0);
1640 		while (i < num_groups+num_types+1) {
1641 			sdl_deserialize_key(sdl->types, types[i], &in);
1642 			sdl_deserialize_type(types[i], types, encoders, &in);
1643 			i++;
1644 		}
1645 	}
1646 
1647 	if (num_elements > 0) {
1648 		sdl->elements = emalloc(sizeof(HashTable));
1649 		zend_hash_init(sdl->elements, num_elements, NULL, delete_type, 0);
1650 		while (i < num_groups+num_types+num_elements+1) {
1651 			sdl_deserialize_key(sdl->elements, types[i], &in);
1652 			sdl_deserialize_type(types[i], types, encoders, &in);
1653 			i++;
1654 		}
1655 	}
1656 
1657 	i = 1;
1658 	if (num_encoders > 0) {
1659 		sdl->encoders = emalloc(sizeof(HashTable));
1660 		zend_hash_init(sdl->encoders, num_encoders, NULL, delete_encoder, 0);
1661 		while (i < num_encoders+1) {
1662 			sdl_deserialize_key(sdl->encoders, encoders[i], &in);
1663 			sdl_deserialize_encoder(encoders[i], types, &in);
1664 			i++;
1665 		}
1666 	}
1667 
1668 	/* deserialize bindings */
1669 	WSDL_CACHE_GET_INT(num_bindings, &in);
1670 	bindings = safe_emalloc(num_bindings, sizeof(sdlBindingPtr), 0);
1671 	if (num_bindings > 0) {
1672 		sdl->bindings = emalloc(sizeof(HashTable));
1673 		zend_hash_init(sdl->bindings, num_bindings, NULL, delete_binding, 0);
1674 		for (i = 0; i < num_bindings; i++) {
1675 			sdlBindingPtr binding = emalloc(sizeof(sdlBinding));
1676 			memset(binding, 0, sizeof(sdlBinding));
1677 			sdl_deserialize_key(sdl->bindings, binding, &in);
1678 			binding->name = sdl_deserialize_string(&in);
1679 			binding->location = sdl_deserialize_string(&in);
1680 			WSDL_CACHE_GET_1(binding->bindingType,sdlBindingType,&in);
1681 			if (binding->bindingType == BINDING_SOAP && *in != 0) {
1682 			  sdlSoapBindingPtr soap_binding = binding->bindingAttributes = emalloc(sizeof(sdlSoapBinding));
1683 				WSDL_CACHE_GET_1(soap_binding->style,sdlEncodingStyle,&in);
1684 				WSDL_CACHE_GET_1(soap_binding->transport,sdlTransport,&in);
1685 			} else {
1686 				WSDL_CACHE_SKIP(1,&in);
1687 			}
1688 			bindings[i] = binding;
1689 		}
1690 	}
1691 
1692 	/* deserialize functions */
1693 	WSDL_CACHE_GET_INT(num_func, &in);
1694 	zend_hash_init(&sdl->functions, num_func, NULL, delete_function, 0);
1695 	if (num_func > 0) {
1696 		functions = safe_emalloc(num_func, sizeof(sdlFunctionPtr), 0);
1697 		for (i = 0; i < num_func; i++) {
1698 			int binding_num, num_faults;
1699 			sdlFunctionPtr func = emalloc(sizeof(sdlFunction));
1700 			sdl_deserialize_key(&sdl->functions, func, &in);
1701 			func->functionName = sdl_deserialize_string(&in);
1702 			func->requestName = sdl_deserialize_string(&in);
1703 			func->responseName = sdl_deserialize_string(&in);
1704 
1705 			WSDL_CACHE_GET_INT(binding_num, &in);
1706 			if (binding_num == 0) {
1707 				func->binding = NULL;
1708 			} else {
1709 				func->binding = bindings[binding_num-1];
1710 			}
1711 			if (func->binding && func->binding->bindingType == BINDING_SOAP && *in != 0) {
1712 				sdlSoapBindingFunctionPtr binding = func->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunction));
1713 				memset(binding, 0, sizeof(sdlSoapBindingFunction));
1714 				WSDL_CACHE_GET_1(binding->style,sdlEncodingStyle,&in);
1715 				binding->soapAction = sdl_deserialize_string(&in);
1716 				sdl_deserialize_soap_body(&binding->input, encoders, types, &in);
1717 				sdl_deserialize_soap_body(&binding->output, encoders, types, &in);
1718 			} else {
1719 				WSDL_CACHE_SKIP(1, &in);
1720 				func->bindingAttributes = NULL;
1721 			}
1722 
1723 			func->requestParameters = sdl_deserialize_parameters(encoders, types, &in);
1724 			func->responseParameters = sdl_deserialize_parameters(encoders, types, &in);
1725 
1726 			WSDL_CACHE_GET_INT(num_faults, &in);
1727 			if (num_faults > 0) {
1728 			  int j;
1729 
1730 				func->faults = emalloc(sizeof(HashTable));
1731 				zend_hash_init(func->faults, num_faults, NULL, delete_fault, 0);
1732 
1733 				for (j = 0; j < num_faults; j++) {
1734 					sdlFaultPtr fault = emalloc(sizeof(sdlFault));
1735 
1736 					sdl_deserialize_key(func->faults, fault, &in);
1737 					fault->name =sdl_deserialize_string(&in);
1738 					fault->details =sdl_deserialize_parameters(encoders, types, &in);
1739 					if (*in != 0) {
1740 						sdlSoapBindingFunctionFaultPtr binding = fault->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunctionFault));
1741 						memset(binding, 0, sizeof(sdlSoapBindingFunctionFault));
1742 						WSDL_CACHE_GET_1(binding->use,sdlEncodingUse,&in);
1743 						if (binding->use == SOAP_ENCODED) {
1744 							WSDL_CACHE_GET_1(binding->encodingStyle, sdlRpcEncodingStyle, &in);
1745 						} else {
1746 							binding->encodingStyle = SOAP_ENCODING_DEFAULT;
1747 						}
1748 						binding->ns = sdl_deserialize_string(&in);
1749 					} else {
1750 						WSDL_CACHE_SKIP(1, &in);
1751 						fault->bindingAttributes = NULL;
1752 					}
1753 				}
1754 			} else {
1755 				func->faults = NULL;
1756 			}
1757 			functions[i] = func;
1758 		}
1759 	}
1760 
1761 	/* deserialize requests */
1762 	WSDL_CACHE_GET_INT(i, &in);
1763 	if (i > 0) {
1764 		sdl->requests = emalloc(sizeof(HashTable));
1765 		zend_hash_init(sdl->requests, i, NULL, NULL, 0);
1766 		while (i > 0) {
1767 			int function_num;
1768 
1769 			WSDL_CACHE_GET_INT(function_num, &in);
1770 			sdl_deserialize_key(sdl->requests, functions[function_num-1], &in);
1771 			i--;
1772 		}
1773 	}
1774 
1775 	if (functions) {
1776 		efree(functions);
1777 	}
1778 	efree(bindings);
1779 	efree(encoders);
1780 	efree(types);
1781 	efree(buf);
1782 	return sdl;
1783 }
1784 
sdl_serialize_string(const char * str,smart_str * out)1785 static void sdl_serialize_string(const char *str, smart_str *out)
1786 {
1787 	int i;
1788 
1789 	if (str) {
1790 		i = strlen(str);
1791 		WSDL_CACHE_PUT_INT(i, out);
1792 		if (i > 0) {
1793 			WSDL_CACHE_PUT_N(str, i, out);
1794 		}
1795 	} else {
1796 		WSDL_CACHE_PUT_INT(0x7fffffff, out);
1797 	}
1798 }
1799 
sdl_serialize_key(HashTable * ht,smart_str * out)1800 static void sdl_serialize_key(HashTable *ht, smart_str *out)
1801 {
1802 	char *key;
1803 	uint  key_len;
1804 	ulong index;
1805 
1806 	if (zend_hash_get_current_key_ex(ht, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
1807 		WSDL_CACHE_PUT_INT(key_len, out);
1808 		WSDL_CACHE_PUT_N(key, key_len, out);
1809 	} else {
1810 		WSDL_CACHE_PUT_INT(0, out);
1811 	}
1812 }
1813 
sdl_serialize_encoder_ref(encodePtr enc,HashTable * tmp_encoders,smart_str * out)1814 static void sdl_serialize_encoder_ref(encodePtr enc, HashTable *tmp_encoders, smart_str *out) {
1815 	if (enc) {
1816 		int *encoder_num;
1817 		if (zend_hash_find(tmp_encoders, (char*)&enc, sizeof(enc), (void**)&encoder_num) == SUCCESS) {
1818 			WSDL_CACHE_PUT_INT(*encoder_num, out);
1819 		} else {
1820 			WSDL_CACHE_PUT_INT(0, out);
1821 		}
1822 	} else {
1823 		WSDL_CACHE_PUT_INT(0, out);
1824 	}
1825 }
1826 
sdl_serialize_type_ref(sdlTypePtr type,HashTable * tmp_types,smart_str * out)1827 static void sdl_serialize_type_ref(sdlTypePtr type, HashTable *tmp_types, smart_str *out) {
1828 	if (type) {
1829 		int *type_num;
1830 		if (zend_hash_find(tmp_types, (char*)&type, sizeof(type), (void**)&type_num) == SUCCESS) {
1831 			WSDL_CACHE_PUT_INT(*type_num, out);
1832 		} else {
1833 			WSDL_CACHE_PUT_INT(0, out);
1834 		}
1835 	} else {
1836 		WSDL_CACHE_PUT_INT(0,out);
1837 	}
1838 }
1839 
sdl_serialize_attribute(sdlAttributePtr attr,HashTable * tmp_encoders,smart_str * out)1840 static void sdl_serialize_attribute(sdlAttributePtr attr, HashTable *tmp_encoders, smart_str *out)
1841 {
1842 	int i;
1843 
1844 	sdl_serialize_string(attr->name, out);
1845 	sdl_serialize_string(attr->namens, out);
1846 	sdl_serialize_string(attr->ref, out);
1847 	sdl_serialize_string(attr->def, out);
1848 	sdl_serialize_string(attr->fixed, out);
1849 	WSDL_CACHE_PUT_1(attr->form, out);
1850 	WSDL_CACHE_PUT_1(attr->use, out);
1851 	sdl_serialize_encoder_ref(attr->encode, tmp_encoders, out);
1852 	if (attr->extraAttributes) {
1853 		i = zend_hash_num_elements(attr->extraAttributes);
1854 	} else {
1855 		i = 0;
1856 	}
1857 	WSDL_CACHE_PUT_INT(i, out);
1858 	if (i > 0) {
1859 		sdlExtraAttributePtr *tmp;
1860 		zend_hash_internal_pointer_reset(attr->extraAttributes);
1861 		while (zend_hash_get_current_data(attr->extraAttributes, (void**)&tmp) == SUCCESS) {
1862 			sdl_serialize_key(attr->extraAttributes, out);
1863 			sdl_serialize_string((*tmp)->ns, out);
1864 			sdl_serialize_string((*tmp)->val, out);
1865 			zend_hash_move_forward(attr->extraAttributes);
1866 		}
1867 	}
1868 }
1869 
sdl_serialize_model(sdlContentModelPtr model,HashTable * tmp_types,HashTable * tmp_elements,smart_str * out)1870 static void sdl_serialize_model(sdlContentModelPtr model, HashTable *tmp_types, HashTable *tmp_elements, smart_str *out)
1871 {
1872 	WSDL_CACHE_PUT_1(model->kind, out);
1873 	WSDL_CACHE_PUT_INT(model->min_occurs, out);
1874 	WSDL_CACHE_PUT_INT(model->max_occurs, out);
1875 	switch (model->kind) {
1876 		case XSD_CONTENT_ELEMENT:
1877 			sdl_serialize_type_ref(model->u.element, tmp_elements, out);
1878 			break;
1879 		case XSD_CONTENT_SEQUENCE:
1880 		case XSD_CONTENT_ALL:
1881 		case XSD_CONTENT_CHOICE: {
1882 				sdlContentModelPtr *tmp;
1883 				int i = zend_hash_num_elements(model->u.content);
1884 
1885 				WSDL_CACHE_PUT_INT(i, out);
1886 				zend_hash_internal_pointer_reset(model->u.content);
1887 				while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
1888 					sdl_serialize_model(*tmp, tmp_types, tmp_elements, out);
1889 					zend_hash_move_forward(model->u.content);
1890 				}
1891 			}
1892 			break;
1893 		case XSD_CONTENT_GROUP_REF:
1894 			sdl_serialize_string(model->u.group_ref,out);
1895 			break;
1896 		case XSD_CONTENT_GROUP:
1897 			sdl_serialize_type_ref(model->u.group, tmp_types, out);
1898 			break;
1899 		default:
1900 			break;
1901 	}
1902 }
1903 
sdl_serialize_resriction_int(sdlRestrictionIntPtr x,smart_str * out)1904 static void sdl_serialize_resriction_int(sdlRestrictionIntPtr x, smart_str *out)
1905 {
1906 	if (x) {
1907 		WSDL_CACHE_PUT_1(1, out);
1908 		WSDL_CACHE_PUT_INT(x->value, out);
1909 		WSDL_CACHE_PUT_1(x->fixed, out);
1910 	} else {
1911 		WSDL_CACHE_PUT_1(0, out);
1912 	}
1913 }
1914 
sdl_serialize_resriction_char(sdlRestrictionCharPtr x,smart_str * out)1915 static void sdl_serialize_resriction_char(sdlRestrictionCharPtr x, smart_str *out)
1916 {
1917 	if (x) {
1918 		WSDL_CACHE_PUT_1(1, out);
1919 		sdl_serialize_string(x->value, out);
1920 		WSDL_CACHE_PUT_1(x->fixed, out);
1921 	} else {
1922 		WSDL_CACHE_PUT_1(0, out);
1923 	}
1924 }
1925 
sdl_serialize_type(sdlTypePtr type,HashTable * tmp_encoders,HashTable * tmp_types,smart_str * out)1926 static void sdl_serialize_type(sdlTypePtr type, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
1927 {
1928 	int i;
1929 	HashTable *tmp_elements = NULL;
1930 
1931 	WSDL_CACHE_PUT_1(type->kind, out);
1932 	sdl_serialize_string(type->name, out);
1933 	sdl_serialize_string(type->namens, out);
1934 	sdl_serialize_string(type->def, out);
1935 	sdl_serialize_string(type->fixed, out);
1936 	sdl_serialize_string(type->ref, out);
1937 	WSDL_CACHE_PUT_1(type->nillable, out);
1938 	WSDL_CACHE_PUT_1(type->form, out);
1939 	sdl_serialize_encoder_ref(type->encode, tmp_encoders, out);
1940 
1941 	if (type->restrictions) {
1942 		WSDL_CACHE_PUT_1(1, out);
1943 		sdl_serialize_resriction_int(type->restrictions->minExclusive,out);
1944 		sdl_serialize_resriction_int(type->restrictions->minInclusive,out);
1945 		sdl_serialize_resriction_int(type->restrictions->maxExclusive,out);
1946 		sdl_serialize_resriction_int(type->restrictions->maxInclusive,out);
1947 		sdl_serialize_resriction_int(type->restrictions->totalDigits,out);
1948 		sdl_serialize_resriction_int(type->restrictions->fractionDigits,out);
1949 		sdl_serialize_resriction_int(type->restrictions->length,out);
1950 		sdl_serialize_resriction_int(type->restrictions->minLength,out);
1951 		sdl_serialize_resriction_int(type->restrictions->maxLength,out);
1952 		sdl_serialize_resriction_char(type->restrictions->whiteSpace,out);
1953 		sdl_serialize_resriction_char(type->restrictions->pattern,out);
1954 		if (type->restrictions->enumeration) {
1955 			i = zend_hash_num_elements(type->restrictions->enumeration);
1956 		} else {
1957 			i = 0;
1958 		}
1959 		WSDL_CACHE_PUT_INT(i, out);
1960 		if (i > 0) {
1961 			sdlRestrictionCharPtr *tmp;
1962 
1963 			zend_hash_internal_pointer_reset(type->restrictions->enumeration);
1964 			while (zend_hash_get_current_data(type->restrictions->enumeration, (void**)&tmp) == SUCCESS) {
1965 				sdl_serialize_resriction_char(*tmp, out);
1966 				sdl_serialize_key(type->restrictions->enumeration, out);
1967 				zend_hash_move_forward(type->restrictions->enumeration);
1968 			}
1969 		}
1970 	} else {
1971 		WSDL_CACHE_PUT_1(0, out);
1972 	}
1973 	if (type->elements) {
1974 		i = zend_hash_num_elements(type->elements);
1975 	} else {
1976 		i = 0;
1977 	}
1978 	WSDL_CACHE_PUT_INT(i, out);
1979 	if (i > 0) {
1980 		sdlTypePtr *tmp;
1981 
1982 		tmp_elements = emalloc(sizeof(HashTable));
1983 		zend_hash_init(tmp_elements, i, NULL, NULL, 0);
1984 
1985 		zend_hash_internal_pointer_reset(type->elements);
1986 		while (zend_hash_get_current_data(type->elements, (void**)&tmp) == SUCCESS) {
1987 			sdl_serialize_key(type->elements, out);
1988 			sdl_serialize_type(*tmp, tmp_encoders, tmp_types, out);
1989 			zend_hash_add(tmp_elements, (char*)tmp, sizeof(*tmp), &i, sizeof(int), NULL);
1990 			i--;
1991 			zend_hash_move_forward(type->elements);
1992 		}
1993 	}
1994 
1995 	if (type->attributes) {
1996 		i = zend_hash_num_elements(type->attributes);
1997 	} else {
1998 		i = 0;
1999 	}
2000 	WSDL_CACHE_PUT_INT(i, out);
2001 	if (i > 0) {
2002 		sdlAttributePtr *tmp;
2003 		zend_hash_internal_pointer_reset(type->attributes);
2004 		while (zend_hash_get_current_data(type->attributes, (void**)&tmp) == SUCCESS) {
2005 			sdl_serialize_key(type->attributes, out);
2006 			sdl_serialize_attribute(*tmp, tmp_encoders, out);
2007 			zend_hash_move_forward(type->attributes);
2008 		}
2009 	}
2010 	if (type->model) {
2011 		WSDL_CACHE_PUT_1(1, out);
2012 		sdl_serialize_model(type->model, tmp_types, tmp_elements, out);
2013 	} else {
2014 		WSDL_CACHE_PUT_1(0, out);
2015 	}
2016 	if (tmp_elements != NULL) {
2017 		zend_hash_destroy(tmp_elements);
2018 		efree(tmp_elements);
2019 	}
2020 }
2021 
sdl_serialize_encoder(encodePtr enc,HashTable * tmp_types,smart_str * out)2022 static void sdl_serialize_encoder(encodePtr enc, HashTable *tmp_types, smart_str *out)
2023 {
2024 	WSDL_CACHE_PUT_INT(enc->details.type, out);
2025 	sdl_serialize_string(enc->details.type_str, out);
2026 	sdl_serialize_string(enc->details.ns, out);
2027 	sdl_serialize_type_ref(enc->details.sdl_type, tmp_types, out);
2028 }
2029 
sdl_serialize_parameters(HashTable * ht,HashTable * tmp_encoders,HashTable * tmp_types,smart_str * out)2030 static void sdl_serialize_parameters(HashTable *ht, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
2031 {
2032 	int i;
2033 
2034 	if (ht) {
2035 		i = zend_hash_num_elements(ht);
2036 	} else {
2037 		i = 0;
2038 	}
2039 	WSDL_CACHE_PUT_INT(i, out);
2040 	if (i > 0) {
2041 		sdlParamPtr *tmp;
2042 
2043 		zend_hash_internal_pointer_reset(ht);
2044 		while (zend_hash_get_current_data(ht, (void**)&tmp) == SUCCESS) {
2045 			sdl_serialize_key(ht, out);
2046 			sdl_serialize_string((*tmp)->paramName, out);
2047 			WSDL_CACHE_PUT_INT((*tmp)->order, out);
2048 			sdl_serialize_encoder_ref((*tmp)->encode, tmp_encoders, out);
2049 			sdl_serialize_type_ref((*tmp)->element, tmp_types, out);
2050 			zend_hash_move_forward(ht);
2051 		}
2052 	}
2053 }
2054 
sdl_serialize_soap_body(sdlSoapBindingFunctionBodyPtr body,HashTable * tmp_encoders,HashTable * tmp_types,smart_str * out)2055 static void sdl_serialize_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
2056 {
2057 	int i, j;
2058 
2059 	WSDL_CACHE_PUT_1(body->use, out);
2060 	if (body->use == SOAP_ENCODED) {
2061 		WSDL_CACHE_PUT_1(body->encodingStyle, out);
2062 	}
2063 	sdl_serialize_string(body->ns, out);
2064 	if (body->headers) {
2065 		i = zend_hash_num_elements(body->headers);
2066 	} else {
2067 		i = 0;
2068 	}
2069 	WSDL_CACHE_PUT_INT(i, out);
2070 	if (i > 0) {
2071 		sdlSoapBindingFunctionHeaderPtr *tmp;
2072 		zend_hash_internal_pointer_reset(body->headers);
2073 		while (zend_hash_get_current_data(body->headers, (void**)&tmp) == SUCCESS) {
2074 			sdl_serialize_key(body->headers, out);
2075 			WSDL_CACHE_PUT_1((*tmp)->use, out);
2076 			if ((*tmp)->use == SOAP_ENCODED) {
2077 				WSDL_CACHE_PUT_1((*tmp)->encodingStyle, out);
2078 			}
2079 			sdl_serialize_string((*tmp)->name, out);
2080 			sdl_serialize_string((*tmp)->ns, out);
2081 			sdl_serialize_encoder_ref((*tmp)->encode, tmp_encoders, out);
2082 			sdl_serialize_type_ref((*tmp)->element, tmp_types, out);
2083 			if ((*tmp)->headerfaults) {
2084 				j = zend_hash_num_elements((*tmp)->headerfaults);
2085 			} else {
2086 				j = 0;
2087 			}
2088 			WSDL_CACHE_PUT_INT(j, out);
2089 			if (j > 0) {
2090 				sdlSoapBindingFunctionHeaderPtr *tmp2;
2091 				zend_hash_internal_pointer_reset((*tmp)->headerfaults);
2092 				while (zend_hash_get_current_data((*tmp)->headerfaults, (void**)&tmp2) == SUCCESS) {
2093 					sdl_serialize_key((*tmp)->headerfaults, out);
2094 					WSDL_CACHE_PUT_1((*tmp2)->use, out);
2095 					if ((*tmp2)->use == SOAP_ENCODED) {
2096 						WSDL_CACHE_PUT_1((*tmp2)->encodingStyle, out);
2097 					}
2098 					sdl_serialize_string((*tmp2)->name, out);
2099 					sdl_serialize_string((*tmp2)->ns, out);
2100 					sdl_serialize_encoder_ref((*tmp2)->encode, tmp_encoders, out);
2101 					sdl_serialize_type_ref((*tmp2)->element, tmp_types, out);
2102 					zend_hash_move_forward((*tmp)->headerfaults);
2103 				}
2104 			}
2105 			zend_hash_move_forward(body->headers);
2106 		}
2107 	}
2108 }
2109 
add_sdl_to_cache(const char * fn,const char * uri,time_t t,sdlPtr sdl TSRMLS_DC)2110 static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr sdl TSRMLS_DC)
2111 {
2112 	smart_str buf = {0};
2113 	smart_str *out = &buf;
2114 	int i;
2115 	int type_num = 1;
2116 	int encoder_num = 1;
2117 	int f;
2118 	encodePtr enc;
2119 	HashTable tmp_types;
2120 	HashTable tmp_encoders;
2121 	HashTable tmp_bindings;
2122 	HashTable tmp_functions;
2123 
2124 #ifdef ZEND_WIN32
2125 	f = open(fn,O_CREAT|O_WRONLY|O_EXCL|O_BINARY,S_IREAD|S_IWRITE);
2126 #else
2127 	f = open(fn,O_CREAT|O_WRONLY|O_EXCL|O_BINARY,S_IREAD|S_IWRITE);
2128 #endif
2129 	if (f < 0) {return;}
2130 
2131 	zend_hash_init(&tmp_types, 0, NULL, NULL, 0);
2132 	zend_hash_init(&tmp_encoders, 0, NULL, NULL, 0);
2133 	zend_hash_init(&tmp_bindings, 0, NULL, NULL, 0);
2134 	zend_hash_init(&tmp_functions, 0, NULL, NULL, 0);
2135 
2136 	WSDL_CACHE_PUT_N("wsdl", 4, out);
2137 	WSDL_CACHE_PUT_1(WSDL_CACHE_VERSION,out);
2138 	WSDL_CACHE_PUT_1(0,out);
2139 	WSDL_CACHE_PUT_N(&t, sizeof(t), out);
2140 
2141 	sdl_serialize_string(uri, out);
2142 	sdl_serialize_string(sdl->source, out);
2143 	sdl_serialize_string(sdl->target_ns, out);
2144 
2145 	if (sdl->groups) {
2146 		i = zend_hash_num_elements(sdl->groups);
2147 	} else {
2148 		i = 0;
2149 	}
2150 	WSDL_CACHE_PUT_INT(i, out);
2151 	if (i > 0) {
2152 		sdlTypePtr *tmp;
2153 
2154 		zend_hash_internal_pointer_reset(sdl->groups);
2155 		while (zend_hash_get_current_data(sdl->groups, (void**)&tmp) == SUCCESS) {
2156 			zend_hash_add(&tmp_types, (char*)tmp, sizeof(*tmp), (void**)&type_num, sizeof(type_num), NULL);
2157 			++type_num;
2158 			zend_hash_move_forward(sdl->groups);
2159 		}
2160 	}
2161 
2162 	if (sdl->types) {
2163 		i = zend_hash_num_elements(sdl->types);
2164 	} else {
2165 		i = 0;
2166 	}
2167 	WSDL_CACHE_PUT_INT(i, out);
2168 	if (i > 0) {
2169 		sdlTypePtr *tmp;
2170 
2171 		zend_hash_internal_pointer_reset(sdl->types);
2172 		while (zend_hash_get_current_data(sdl->types, (void**)&tmp) == SUCCESS) {
2173 			zend_hash_add(&tmp_types, (char*)tmp, sizeof(*tmp), (void**)&type_num, sizeof(type_num), NULL);
2174 			++type_num;
2175 			zend_hash_move_forward(sdl->types);
2176 		}
2177 	}
2178 
2179 	if (sdl->elements) {
2180 		i = zend_hash_num_elements(sdl->elements);
2181 	} else {
2182 		i = 0;
2183 	}
2184 	WSDL_CACHE_PUT_INT(i, out);
2185 	if (i > 0) {
2186 		sdlTypePtr *tmp;
2187 
2188 		zend_hash_internal_pointer_reset(sdl->elements);
2189 		while (zend_hash_get_current_data(sdl->elements, (void**)&tmp) == SUCCESS) {
2190 			zend_hash_add(&tmp_types, (char*)tmp, sizeof(*tmp), (void**)&type_num, sizeof(type_num), NULL);
2191 			++type_num;
2192 			zend_hash_move_forward(sdl->elements);
2193 		}
2194 	}
2195 
2196 	if (sdl->encoders) {
2197 		i = zend_hash_num_elements(sdl->encoders);
2198 	} else {
2199 		i = 0;
2200 	}
2201 	WSDL_CACHE_PUT_INT(i, out);
2202 	if (i > 0) {
2203 		encodePtr *tmp;
2204 
2205 		zend_hash_internal_pointer_reset(sdl->encoders);
2206 		while (zend_hash_get_current_data(sdl->encoders, (void**)&tmp) == SUCCESS) {
2207 			zend_hash_add(&tmp_encoders, (char*)tmp, sizeof(*tmp), (void**)&encoder_num, sizeof(encoder_num), NULL);
2208 			++encoder_num;
2209 			zend_hash_move_forward(sdl->encoders);
2210 		}
2211 	}
2212 	enc = defaultEncoding;
2213 	while (enc->details.type != END_KNOWN_TYPES) {
2214 		zend_hash_add(&tmp_encoders, (char*)&enc, sizeof(encodePtr), (void**)&encoder_num, sizeof(encoder_num), NULL);
2215 		enc++;
2216 		++encoder_num;
2217 	}
2218 
2219 	if (sdl->groups) {
2220 		sdlTypePtr *tmp;
2221 		zend_hash_internal_pointer_reset(sdl->groups);
2222 		while (zend_hash_get_current_data(sdl->groups, (void**)&tmp) == SUCCESS) {
2223 			sdl_serialize_key(sdl->groups, out);
2224 			sdl_serialize_type(*tmp, &tmp_encoders, &tmp_types, out);
2225 			zend_hash_move_forward(sdl->groups);
2226 		}
2227 	}
2228 
2229 	if (sdl->types) {
2230 		sdlTypePtr *tmp;
2231 		zend_hash_internal_pointer_reset(sdl->types);
2232 		while (zend_hash_get_current_data(sdl->types, (void**)&tmp) == SUCCESS) {
2233 			sdl_serialize_key(sdl->types, out);
2234 			sdl_serialize_type(*tmp, &tmp_encoders, &tmp_types, out);
2235 			zend_hash_move_forward(sdl->types);
2236 		}
2237 	}
2238 
2239 	if (sdl->elements) {
2240 		sdlTypePtr *tmp;
2241 		zend_hash_internal_pointer_reset(sdl->elements);
2242 		while (zend_hash_get_current_data(sdl->elements, (void**)&tmp) == SUCCESS) {
2243 			sdl_serialize_key(sdl->elements, out);
2244 			sdl_serialize_type(*tmp, &tmp_encoders, &tmp_types, out);
2245 			zend_hash_move_forward(sdl->elements);
2246 		}
2247 	}
2248 
2249 	if (sdl->encoders) {
2250 		encodePtr *tmp;
2251 		zend_hash_internal_pointer_reset(sdl->encoders);
2252 		while (zend_hash_get_current_data(sdl->encoders, (void**)&tmp) == SUCCESS) {
2253 			sdl_serialize_key(sdl->encoders, out);
2254 			sdl_serialize_encoder(*tmp, &tmp_types, out);
2255 			zend_hash_move_forward(sdl->encoders);
2256 		}
2257 	}
2258 
2259 	/* serialize bindings */
2260 	if (sdl->bindings) {
2261 		i = zend_hash_num_elements(sdl->bindings);
2262 	} else {
2263 		i = 0;
2264 	}
2265 	WSDL_CACHE_PUT_INT(i, out);
2266 	if (i > 0) {
2267 		sdlBindingPtr *tmp;
2268 		int binding_num = 1;
2269 
2270 		zend_hash_internal_pointer_reset(sdl->bindings);
2271 		while (zend_hash_get_current_data(sdl->bindings, (void**)&tmp) == SUCCESS) {
2272 			sdl_serialize_key(sdl->bindings, out);
2273 			sdl_serialize_string((*tmp)->name, out);
2274 			sdl_serialize_string((*tmp)->location, out);
2275 			WSDL_CACHE_PUT_1((*tmp)->bindingType,out);
2276 			if ((*tmp)->bindingType == BINDING_SOAP && (*tmp)->bindingAttributes != NULL) {
2277 				sdlSoapBindingPtr binding = (sdlSoapBindingPtr)(*tmp)->bindingAttributes;
2278 				WSDL_CACHE_PUT_1(binding->style, out);
2279 				WSDL_CACHE_PUT_1(binding->transport, out);
2280 			} else {
2281 				WSDL_CACHE_PUT_1(0,out);
2282 			}
2283 
2284 			zend_hash_add(&tmp_bindings, (char*)tmp, sizeof(*tmp), (void**)&binding_num, sizeof(binding_num), NULL);
2285 			binding_num++;
2286 			zend_hash_move_forward(sdl->bindings);
2287 		}
2288 	}
2289 
2290 	/* serialize functions */
2291 	i = zend_hash_num_elements(&sdl->functions);
2292 	WSDL_CACHE_PUT_INT(i, out);
2293 	if (i > 0) {
2294 		sdlFunctionPtr *tmp;
2295 		int *binding_num;
2296 		int function_num = 1;
2297 
2298 		zend_hash_internal_pointer_reset(&sdl->functions);
2299 		while (zend_hash_get_current_data(&sdl->functions, (void**)&tmp) == SUCCESS) {
2300 			sdl_serialize_key(&sdl->functions, out);
2301 			sdl_serialize_string((*tmp)->functionName, out);
2302 			sdl_serialize_string((*tmp)->requestName, out);
2303 			sdl_serialize_string((*tmp)->responseName, out);
2304 
2305 			if ((*tmp)->binding == NULL ||
2306 			    zend_hash_find(&tmp_bindings,(char*)&(*tmp)->binding,sizeof((*tmp)->binding), (void**)&binding_num) != SUCCESS) {
2307 			}
2308 			WSDL_CACHE_PUT_INT(*binding_num, out);
2309 			if (*binding_num >= 0) {
2310 				if ((*tmp)->binding->bindingType == BINDING_SOAP && (*tmp)->bindingAttributes != NULL) {
2311 					sdlSoapBindingFunctionPtr binding = (sdlSoapBindingFunctionPtr)(*tmp)->bindingAttributes;
2312 					WSDL_CACHE_PUT_1(binding->style, out);
2313 					sdl_serialize_string(binding->soapAction, out);
2314 					sdl_serialize_soap_body(&binding->input, &tmp_encoders, &tmp_types, out);
2315 					sdl_serialize_soap_body(&binding->output, &tmp_encoders, &tmp_types, out);
2316 				} else {
2317 					WSDL_CACHE_PUT_1(0,out);
2318 				}
2319 			}
2320 			sdl_serialize_parameters((*tmp)->requestParameters, &tmp_encoders, &tmp_types, out);
2321 			sdl_serialize_parameters((*tmp)->responseParameters, &tmp_encoders, &tmp_types, out);
2322 
2323 			if ((*tmp)->faults) {
2324 				sdlFaultPtr *fault;
2325 
2326 				WSDL_CACHE_PUT_INT(zend_hash_num_elements((*tmp)->faults), out);
2327 
2328 				zend_hash_internal_pointer_reset((*tmp)->faults);
2329 				while (zend_hash_get_current_data((*tmp)->faults, (void**)&fault) == SUCCESS) {
2330 					sdl_serialize_key((*tmp)->faults, out);
2331 					sdl_serialize_string((*fault)->name, out);
2332 					sdl_serialize_parameters((*fault)->details, &tmp_encoders, &tmp_types, out);
2333 					if ((*tmp)->binding->bindingType == BINDING_SOAP && (*fault)->bindingAttributes != NULL) {
2334 						sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)(*fault)->bindingAttributes;
2335 						WSDL_CACHE_PUT_1(binding->use, out);
2336 						if (binding->use == SOAP_ENCODED) {
2337 							WSDL_CACHE_PUT_1(binding->encodingStyle, out);
2338 						}
2339 						sdl_serialize_string(binding->ns, out);
2340 					} else {
2341 						WSDL_CACHE_PUT_1(0, out);
2342 					}
2343 					zend_hash_move_forward((*tmp)->faults);
2344 				}
2345 			} else {
2346 				WSDL_CACHE_PUT_INT(0, out);
2347 			}
2348 
2349 			zend_hash_add(&tmp_functions, (char*)tmp, sizeof(*tmp), (void**)&function_num, sizeof(function_num), NULL);
2350 			function_num++;
2351 			zend_hash_move_forward(&sdl->functions);
2352 		}
2353 	}
2354 
2355 	/* serialize requests */
2356 	if (sdl->requests) {
2357 		i = zend_hash_num_elements(sdl->requests);
2358 	} else {
2359 		i = 0;
2360 	}
2361 	WSDL_CACHE_PUT_INT(i, out);
2362 	if (i > 0) {
2363 		sdlFunctionPtr *tmp;
2364 		int *function_num;
2365 
2366 		zend_hash_internal_pointer_reset(sdl->requests);
2367 		while (zend_hash_get_current_data(sdl->requests, (void**)&tmp) == SUCCESS) {
2368 			if (zend_hash_find(&tmp_functions, (char*)tmp, sizeof(*tmp), (void**)&function_num) != SUCCESS) {
2369 			}
2370 			WSDL_CACHE_PUT_INT(*function_num, out);
2371 			sdl_serialize_key(sdl->requests, out);
2372 			zend_hash_move_forward(sdl->requests);
2373 		}
2374 	}
2375 
2376 	php_ignore_value(write(f, buf.c, buf.len));
2377 	close(f);
2378 	smart_str_free(&buf);
2379 	zend_hash_destroy(&tmp_functions);
2380 	zend_hash_destroy(&tmp_bindings);
2381 	zend_hash_destroy(&tmp_encoders);
2382 	zend_hash_destroy(&tmp_types);
2383 }
2384 
2385 
make_persistent_restriction_int(void * data)2386 static void make_persistent_restriction_int(void *data)
2387 {
2388 	sdlRestrictionIntPtr *rest = (sdlRestrictionIntPtr *)data;
2389 	sdlRestrictionIntPtr prest = NULL;
2390 
2391 	prest = malloc(sizeof(sdlRestrictionInt));
2392 	*prest = **rest;
2393 	*rest = prest;
2394 }
2395 
2396 
make_persistent_restriction_char(void * data)2397 static void make_persistent_restriction_char(void *data)
2398 {
2399 	sdlRestrictionCharPtr *rest = (sdlRestrictionCharPtr *)data;
2400 	sdlRestrictionCharPtr prest = NULL;
2401 
2402 	prest = malloc(sizeof(sdlRestrictionChar));
2403 	memset(prest, 0, sizeof(sdlRestrictionChar));
2404 	prest->value = strdup((*rest)->value);
2405 	prest->fixed = (*rest)->fixed;
2406 	*rest = prest;
2407 }
2408 
2409 
make_persistent_sdl_type_ref(sdlTypePtr * type,HashTable * ptr_map,HashTable * bp_types)2410 static void make_persistent_sdl_type_ref(sdlTypePtr *type, HashTable *ptr_map, HashTable *bp_types)
2411 {
2412 	sdlTypePtr *tmp;
2413 
2414 	if (zend_hash_find(ptr_map, (char *)type, sizeof(sdlTypePtr), (void**)&tmp) == SUCCESS) {
2415 		*type = *tmp;
2416 	} else {
2417 		zend_hash_next_index_insert(bp_types, (void*)&type, sizeof(sdlTypePtr*), NULL);
2418 	}
2419 }
2420 
2421 
make_persistent_sdl_encoder_ref(encodePtr * enc,HashTable * ptr_map,HashTable * bp_encoders)2422 static void make_persistent_sdl_encoder_ref(encodePtr *enc, HashTable *ptr_map, HashTable *bp_encoders)
2423 {
2424 	encodePtr *tmp;
2425 
2426 	/* do not process defaultEncoding's here */
2427 	if ((*enc) >= defaultEncoding && (*enc) < defaultEncoding + numDefaultEncodings) {
2428 		return;
2429 	}
2430 
2431 	if (zend_hash_find(ptr_map, (char *)enc, sizeof(encodePtr), (void**)&tmp) == SUCCESS) {
2432 		*enc = *tmp;
2433 	} else {
2434 		zend_hash_next_index_insert(bp_encoders, (void*)&enc, sizeof(encodePtr*), NULL);
2435 	}
2436 }
2437 
2438 
make_persistent_sdl_function_headers(HashTable * headers,HashTable * ptr_map)2439 static HashTable* make_persistent_sdl_function_headers(HashTable *headers, HashTable *ptr_map)
2440 {
2441 	HashTable *pheaders;
2442 	sdlSoapBindingFunctionHeaderPtr *tmp, pheader;
2443 	encodePtr *penc;
2444 	sdlTypePtr *ptype;
2445 	ulong index;
2446 	char *key;
2447 	uint key_len;
2448 
2449 	pheaders = malloc(sizeof(HashTable));
2450 	zend_hash_init(pheaders, zend_hash_num_elements(headers), NULL, delete_header_persistent, 1);
2451 
2452 	zend_hash_internal_pointer_reset(headers);
2453 	while (zend_hash_get_current_data(headers, (void**)&tmp) == SUCCESS) {
2454 		pheader = malloc(sizeof(sdlSoapBindingFunctionHeader));
2455 		memset(pheader, 0, sizeof(sdlSoapBindingFunctionHeader));
2456 		*pheader = **tmp;
2457 
2458 		if (pheader->name) {
2459 			pheader->name = strdup(pheader->name);
2460 		}
2461 		if (pheader->ns) {
2462 			pheader->ns = strdup(pheader->ns);
2463 		}
2464 
2465 		if (pheader->encode->details.sdl_type) {
2466 			if (zend_hash_find(ptr_map, (char*)&pheader->encode, sizeof(encodePtr), (void**)&penc) == FAILURE) {
2467 				assert(0);
2468 			}
2469 			pheader->encode = *penc;
2470 		}
2471 		if (pheader->element) {
2472 			if (zend_hash_find(ptr_map, (char*)&pheader->element, sizeof(sdlTypePtr), (void**)&ptype) == FAILURE) {
2473 				assert(0);
2474 			}
2475 			pheader->element = *ptype;
2476 		}
2477 
2478 		if (pheader->headerfaults) {
2479 			pheader->headerfaults = make_persistent_sdl_function_headers(pheader->headerfaults, ptr_map);
2480 		}
2481 
2482 		if (zend_hash_get_current_key_ex(headers, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2483 			zend_hash_add(pheaders, key, key_len, (void*)&pheader, sizeof(sdlSoapBindingFunctionHeaderPtr), NULL);
2484 		} else {
2485 			zend_hash_next_index_insert(pheaders, (void*)&pheader, sizeof(sdlSoapBindingFunctionHeaderPtr), NULL);
2486 		}
2487 
2488 		zend_hash_move_forward(headers);
2489 	}
2490 
2491 	return pheaders;
2492 }
2493 
2494 
make_persistent_sdl_soap_body(sdlSoapBindingFunctionBodyPtr body,HashTable * ptr_map)2495 static void make_persistent_sdl_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTable *ptr_map)
2496 {
2497 	if (body->ns) {
2498 		body->ns = strdup(body->ns);
2499 	}
2500 
2501 	if (body->headers) {
2502 		body->headers = make_persistent_sdl_function_headers(body->headers, ptr_map);
2503 	}
2504 }
2505 
2506 
make_persistent_sdl_parameters(HashTable * params,HashTable * ptr_map)2507 static HashTable* make_persistent_sdl_parameters(HashTable *params, HashTable *ptr_map)
2508 {
2509 	HashTable *pparams;
2510 	sdlParamPtr *tmp, pparam;
2511 	sdlTypePtr *ptype;
2512 	encodePtr *penc;
2513 	ulong index;
2514 	char *key;
2515 	uint key_len;
2516 
2517 	pparams = malloc(sizeof(HashTable));
2518 	zend_hash_init(pparams, zend_hash_num_elements(params), NULL, delete_parameter_persistent, 1);
2519 
2520 	zend_hash_internal_pointer_reset(params);
2521 	while (zend_hash_get_current_data(params, (void**)&tmp) == SUCCESS) {
2522 		pparam = malloc(sizeof(sdlParam));
2523 		memset(pparam, 0, sizeof(sdlParam));
2524 		*pparam = **tmp;
2525 
2526 		if (pparam->paramName) {
2527 			pparam->paramName = strdup(pparam->paramName);
2528 		}
2529 
2530 		if (pparam->encode && pparam->encode->details.sdl_type) {
2531 			if (zend_hash_find(ptr_map, (char*)&pparam->encode, sizeof(encodePtr), (void**)&penc) == FAILURE) {
2532 				assert(0);
2533 			}
2534 			pparam->encode = *penc;
2535 		}
2536 		if (pparam->element) {
2537 			if (zend_hash_find(ptr_map, (char*)&pparam->element, sizeof(sdlTypePtr), (void**)&ptype) == FAILURE) {
2538 				assert(0);
2539 			}
2540 			pparam->element = *ptype;
2541 		}
2542 
2543 		if (zend_hash_get_current_key_ex(params, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2544 			zend_hash_add(pparams, key, key_len, (void*)&pparam, sizeof(sdlParamPtr), NULL);
2545 		} else {
2546 			zend_hash_next_index_insert(pparams, (void*)&pparam, sizeof(sdlParamPtr), NULL);
2547 		}
2548 
2549 		zend_hash_move_forward(params);
2550 	}
2551 
2552 
2553 	return pparams;
2554 }
2555 
make_persistent_sdl_function_faults(sdlFunctionPtr func,HashTable * faults,HashTable * ptr_map)2556 static HashTable* make_persistent_sdl_function_faults(sdlFunctionPtr func, HashTable *faults, HashTable *ptr_map)
2557 {
2558 	HashTable *pfaults;
2559 	sdlFaultPtr  *tmp, pfault;
2560 	ulong index;
2561 	char *key;
2562 	uint key_len;
2563 
2564 	pfaults = malloc(sizeof(HashTable));
2565 	zend_hash_init(pfaults, zend_hash_num_elements(faults), NULL, delete_fault_persistent, 1);
2566 
2567 	zend_hash_internal_pointer_reset(faults);
2568 	while (zend_hash_get_current_data(faults, (void**)&tmp) == SUCCESS) {
2569 		pfault = malloc(sizeof(sdlFault));
2570 		memset(pfault, 0, sizeof(sdlFault));
2571 		*pfault = **tmp;
2572 
2573 		if (pfault->name) {
2574 			pfault->name = strdup(pfault->name);
2575 		}
2576 		if (pfault->details) {
2577 			pfault->details = make_persistent_sdl_parameters(pfault->details, ptr_map);
2578 		}
2579 
2580 		if (func->binding->bindingType == BINDING_SOAP && pfault->bindingAttributes) {
2581 			sdlSoapBindingFunctionFaultPtr soap_binding;
2582 
2583 		   	soap_binding = malloc(sizeof(sdlSoapBindingFunctionFault));
2584 			memset(soap_binding, 0, sizeof(sdlSoapBindingFunctionFault));
2585 			*soap_binding = *(sdlSoapBindingFunctionFaultPtr)pfault->bindingAttributes;
2586 			if (soap_binding->ns) {
2587 				soap_binding->ns = strdup(soap_binding->ns);
2588 			}
2589 			pfault->bindingAttributes = soap_binding;
2590 		}
2591 
2592 		if (zend_hash_get_current_key_ex(faults, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2593 			zend_hash_add(pfaults, key, key_len, (void*)&pfault, sizeof(sdlParamPtr), NULL);
2594 		} else {
2595 			zend_hash_next_index_insert(pfaults, (void*)&pfault, sizeof(sdlParamPtr), NULL);
2596 		}
2597 
2598 		zend_hash_move_forward(faults);
2599 	}
2600 
2601 
2602 	return pfaults;
2603 }
2604 
2605 
make_persistent_sdl_attribute(sdlAttributePtr attr,HashTable * ptr_map,HashTable * bp_types,HashTable * bp_encoders)2606 static sdlAttributePtr make_persistent_sdl_attribute(sdlAttributePtr attr, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2607 {
2608 	sdlAttributePtr pattr;
2609 	ulong index;
2610 	char *key;
2611 	uint key_len;
2612 
2613 	pattr = malloc(sizeof(sdlAttribute));
2614 	memset(pattr, 0, sizeof(sdlAttribute));
2615 
2616 	*pattr = *attr;
2617 
2618 	if (pattr->name) {
2619 		pattr->name = strdup(pattr->name);
2620 	}
2621 	if (pattr->namens) {
2622 		pattr->namens = strdup(pattr->namens);
2623 	}
2624 	if (pattr->ref) {
2625 		pattr->ref = strdup(pattr->ref);
2626 	}
2627 	if (pattr->def) {
2628 		pattr->def = strdup(pattr->def);
2629 	}
2630 	if (pattr->fixed) {
2631 		pattr->fixed = strdup(pattr->fixed);
2632 	}
2633 
2634 	/* we do not want to process defaultEncoding's here */
2635 	if (pattr->encode) {
2636 		make_persistent_sdl_encoder_ref(&pattr->encode, ptr_map, bp_encoders);
2637 	}
2638 
2639 	if (pattr->extraAttributes) {
2640 		sdlExtraAttributePtr *tmp, pextra;
2641 
2642 		pattr->extraAttributes = malloc(sizeof(HashTable));
2643 		zend_hash_init(pattr->extraAttributes, zend_hash_num_elements(attr->extraAttributes), NULL, delete_extra_attribute_persistent, 1);
2644 
2645 		zend_hash_internal_pointer_reset(pattr->extraAttributes);
2646 		while (zend_hash_get_current_data(attr->extraAttributes, (void**)&tmp) == SUCCESS) {
2647 			if (zend_hash_get_current_key_ex(attr->extraAttributes, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2648 				pextra = malloc(sizeof(sdlExtraAttribute));
2649 				memset(pextra, 0, sizeof(sdlExtraAttribute));
2650 
2651 				if ((*tmp)->ns) {
2652 					pextra->ns = strdup((*tmp)->ns);
2653 				}
2654 				if ((*tmp)->val) {
2655 					pextra->val = strdup((*tmp)->val);
2656 				}
2657 
2658 				zend_hash_add(pattr->extraAttributes, key, key_len, (void*)&pextra, sizeof(sdlExtraAttributePtr), NULL);
2659 			}
2660 
2661 			zend_hash_move_forward(attr->extraAttributes);
2662 		}
2663 	}
2664 
2665 	return pattr;
2666 }
2667 
2668 
make_persistent_sdl_model(sdlContentModelPtr model,HashTable * ptr_map,HashTable * bp_types,HashTable * bp_encoders)2669 static sdlContentModelPtr make_persistent_sdl_model(sdlContentModelPtr model, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2670 {
2671 	sdlContentModelPtr pmodel;
2672 	sdlContentModelPtr *tmp, pcontent;
2673 
2674 	pmodel = malloc(sizeof(sdlContentModel));
2675 	memset(pmodel, 0, sizeof(sdlContentModel));
2676 	*pmodel = *model;
2677 
2678 	switch (pmodel->kind) {
2679 		case XSD_CONTENT_ELEMENT:
2680 			if (pmodel->u.element) {
2681 				make_persistent_sdl_type_ref(&pmodel->u.element, ptr_map, bp_types);
2682 			}
2683 			break;
2684 
2685 		case XSD_CONTENT_SEQUENCE:
2686 		case XSD_CONTENT_ALL:
2687 		case XSD_CONTENT_CHOICE:
2688 			pmodel->u.content = malloc(sizeof(HashTable));
2689 			zend_hash_init(pmodel->u.content, zend_hash_num_elements(model->u.content), NULL, delete_model_persistent, 1);
2690 
2691 			zend_hash_internal_pointer_reset(model->u.content);
2692 			while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
2693 				pcontent = make_persistent_sdl_model(*tmp, ptr_map, bp_types, bp_encoders);
2694 				zend_hash_next_index_insert(pmodel->u.content, (void*)&pcontent, sizeof(sdlContentModelPtr), NULL);
2695 				zend_hash_move_forward(model->u.content);
2696 			}
2697 			break;
2698 
2699 		case XSD_CONTENT_GROUP_REF:
2700 			if (pmodel->u.group_ref) {
2701 				pmodel->u.group_ref = strdup(pmodel->u.group_ref);
2702 			}
2703 			break;
2704 
2705 		case XSD_CONTENT_GROUP:
2706 			if (pmodel->u.group) {
2707 				make_persistent_sdl_type_ref(&pmodel->u.group, ptr_map, bp_types);
2708 			}
2709 			break;
2710 
2711 		default:
2712 			break;
2713 	}
2714 
2715 	return pmodel;
2716 }
2717 
2718 
make_persistent_sdl_type(sdlTypePtr type,HashTable * ptr_map,HashTable * bp_types,HashTable * bp_encoders)2719 static sdlTypePtr make_persistent_sdl_type(sdlTypePtr type, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2720 {
2721 	ulong index;
2722 	char *key;
2723 	uint key_len;
2724 	sdlTypePtr ptype = NULL;
2725 
2726 	ptype = malloc(sizeof(sdlType));
2727 	memset(ptype, 0, sizeof(sdlType));
2728 
2729 	*ptype = *type;
2730 
2731 	if (ptype->name) {
2732 		ptype->name = strdup(ptype->name);
2733 	}
2734 	if (ptype->namens) {
2735 		ptype->namens = strdup(ptype->namens);
2736 	}
2737 	if (ptype->def) {
2738 		ptype->def = strdup(ptype->def);
2739 	}
2740 	if (ptype->fixed) {
2741 		ptype->fixed = strdup(ptype->fixed);
2742 	}
2743 	if (ptype->ref) {
2744 		ptype->ref = strdup(ptype->ref);
2745 	}
2746 
2747 	/* we do not want to process defaultEncoding's here */
2748 	if (ptype->encode) {
2749 		make_persistent_sdl_encoder_ref(&ptype->encode, ptr_map, bp_encoders);
2750 	}
2751 
2752 	if (ptype->restrictions) {
2753 		ptype->restrictions = malloc(sizeof(sdlRestrictions));
2754 		memset(ptype->restrictions, 0, sizeof(sdlRestrictions));
2755 		*ptype->restrictions = *type->restrictions;
2756 
2757 		if (ptype->restrictions->minExclusive) {
2758 			make_persistent_restriction_int(&ptype->restrictions->minExclusive);
2759 		}
2760 		if (ptype->restrictions->maxExclusive) {
2761 			make_persistent_restriction_int(&ptype->restrictions->maxExclusive);
2762 		}
2763 		if (ptype->restrictions->minInclusive) {
2764 			make_persistent_restriction_int(&ptype->restrictions->minInclusive);
2765 		}
2766 		if (ptype->restrictions->maxInclusive) {
2767 			make_persistent_restriction_int(&ptype->restrictions->maxInclusive);
2768 		}
2769 		if (ptype->restrictions->totalDigits) {
2770 			make_persistent_restriction_int(&ptype->restrictions->totalDigits);
2771 		}
2772 		if (ptype->restrictions->fractionDigits) {
2773 			make_persistent_restriction_int(&ptype->restrictions->fractionDigits);
2774 		}
2775 		if (ptype->restrictions->length) {
2776 			make_persistent_restriction_int(&ptype->restrictions->length);
2777 		}
2778 		if (ptype->restrictions->minLength) {
2779 			make_persistent_restriction_int(&ptype->restrictions->minLength);
2780 		}
2781 		if (ptype->restrictions->maxLength) {
2782 			make_persistent_restriction_int(&ptype->restrictions->maxLength);
2783 		}
2784 		if (ptype->restrictions->whiteSpace) {
2785 			make_persistent_restriction_char(&ptype->restrictions->whiteSpace);
2786 		}
2787 		if (ptype->restrictions->pattern) {
2788 			make_persistent_restriction_char(&ptype->restrictions->pattern);
2789 		}
2790 
2791 		if (type->restrictions->enumeration) {
2792 			sdlRestrictionCharPtr tmp;
2793 
2794 			ptype->restrictions->enumeration = malloc(sizeof(HashTable));
2795 			zend_hash_init(ptype->restrictions->enumeration, zend_hash_num_elements(type->restrictions->enumeration), NULL, delete_restriction_var_char_persistent, 1);
2796 			zend_hash_copy(ptype->restrictions->enumeration, type->restrictions->enumeration, make_persistent_restriction_char, (void*)&tmp, sizeof(sdlRestrictionCharPtr));
2797 		}
2798 	}
2799 
2800 	if (ptype->elements) {
2801 		sdlTypePtr *tmp, pelem;
2802 
2803 		ptype->elements = malloc(sizeof(HashTable));
2804 		zend_hash_init(ptype->elements, zend_hash_num_elements(type->elements), NULL, delete_type_persistent, 1);
2805 
2806 		zend_hash_internal_pointer_reset(type->elements);
2807 		while (zend_hash_get_current_data(type->elements, (void **)&tmp) == SUCCESS) {
2808 			pelem = make_persistent_sdl_type(*tmp, ptr_map, bp_types, bp_encoders);
2809 			if (zend_hash_get_current_key_ex(type->elements, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2810 				zend_hash_add(ptype->elements, key, key_len, (void*)&pelem, sizeof(sdlTypePtr), NULL);
2811 			} else {
2812 				zend_hash_next_index_insert(ptype->elements, (void*)&pelem, sizeof(sdlTypePtr), NULL);
2813 			}
2814 			zend_hash_add(ptr_map, (char*)tmp, sizeof(*tmp), (void*)&pelem, sizeof(sdlTypePtr), NULL);
2815 			zend_hash_move_forward(type->elements);
2816 		}
2817 	}
2818 
2819 	if (ptype->attributes) {
2820 		sdlAttributePtr *tmp, pattr;
2821 
2822 		ptype->attributes = malloc(sizeof(HashTable));
2823 		zend_hash_init(ptype->attributes, zend_hash_num_elements(type->attributes), NULL, delete_attribute_persistent, 1);
2824 
2825 		zend_hash_internal_pointer_reset(type->attributes);
2826 		while (zend_hash_get_current_data(type->attributes, (void **)&tmp) == SUCCESS) {
2827 			pattr = make_persistent_sdl_attribute(*tmp, ptr_map, bp_types, bp_encoders);
2828 			if (zend_hash_get_current_key_ex(type->attributes, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2829 				zend_hash_add(ptype->attributes, key, key_len, (void*)&pattr, sizeof(sdlAttributePtr), NULL);
2830 			} else {
2831 				zend_hash_next_index_insert(ptype->attributes, (void*)&pattr, sizeof(sdlAttributePtr), NULL);
2832 			}
2833 			zend_hash_move_forward(type->attributes);
2834 		}
2835 	}
2836 
2837 	if (type->model) {
2838 		ptype->model = make_persistent_sdl_model(ptype->model, ptr_map, bp_types, bp_encoders);
2839 	}
2840 
2841 	return ptype;
2842 }
2843 
make_persistent_sdl_encoder(encodePtr enc,HashTable * ptr_map,HashTable * bp_types,HashTable * bp_encoders)2844 static encodePtr make_persistent_sdl_encoder(encodePtr enc, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2845 {
2846 	encodePtr penc = NULL;
2847 
2848 	penc = malloc(sizeof(encode));
2849 	memset(penc, 0, sizeof(encode));
2850 
2851 	*penc = *enc;
2852 
2853 	if (penc->details.type_str) {
2854 		penc->details.type_str = strdup(penc->details.type_str);
2855 	}
2856 	if (penc->details.ns) {
2857 		penc->details.ns = strdup(penc->details.ns);
2858 	}
2859 
2860 	if (penc->details.sdl_type) {
2861 		make_persistent_sdl_type_ref(&penc->details.sdl_type, ptr_map, bp_types);
2862 	}
2863 
2864 	return penc;
2865 }
2866 
make_persistent_sdl_binding(sdlBindingPtr bind,HashTable * ptr_map)2867 static sdlBindingPtr make_persistent_sdl_binding(sdlBindingPtr bind, HashTable *ptr_map)
2868 {
2869 	sdlBindingPtr pbind = NULL;
2870 
2871 	pbind = malloc(sizeof(sdlBinding));
2872 	memset(pbind, 0, sizeof(sdlBinding));
2873 
2874 	*pbind = *bind;
2875 
2876 	if (pbind->name) {
2877 		pbind->name = strdup(pbind->name);
2878 	}
2879 	if (pbind->location) {
2880 		pbind->location = strdup(pbind->location);
2881 	}
2882 
2883 	if (pbind->bindingType == BINDING_SOAP && pbind->bindingAttributes) {
2884 		sdlSoapBindingPtr soap_binding;
2885 
2886 		soap_binding = malloc(sizeof(sdlSoapBinding));
2887 		memset(soap_binding, 0, sizeof(sdlSoapBinding));
2888 		*soap_binding = *(sdlSoapBindingPtr)pbind->bindingAttributes;
2889 		pbind->bindingAttributes = soap_binding;
2890 	}
2891 
2892 	return pbind;
2893 }
2894 
make_persistent_sdl_function(sdlFunctionPtr func,HashTable * ptr_map)2895 static sdlFunctionPtr make_persistent_sdl_function(sdlFunctionPtr func, HashTable *ptr_map)
2896 {
2897 	sdlFunctionPtr pfunc = NULL;
2898 
2899 	pfunc = malloc(sizeof(sdlFunction));
2900 	memset(pfunc, 0, sizeof(sdlFunction));
2901 
2902 	*pfunc = *func;
2903 
2904 	if (pfunc->functionName) {
2905 		pfunc->functionName = strdup(pfunc->functionName);
2906 	}
2907 	if (pfunc->requestName) {
2908 		pfunc->requestName = strdup(pfunc->requestName);
2909 	}
2910 	if (pfunc->responseName) {
2911 		pfunc->responseName = strdup(pfunc->responseName);
2912 	}
2913 
2914 	if (pfunc->binding) {
2915 		sdlBindingPtr *tmp;
2916 
2917 		if (zend_hash_find(ptr_map, (char*)&pfunc->binding, sizeof(pfunc->binding), (void**)&tmp) == FAILURE) {
2918 			assert(0);
2919 		}
2920 		pfunc->binding = *tmp;
2921 
2922 		if (pfunc->binding->bindingType == BINDING_SOAP && pfunc->bindingAttributes) {
2923 			sdlSoapBindingFunctionPtr soap_binding;
2924 
2925 		   	soap_binding = malloc(sizeof(sdlSoapBindingFunction));
2926 			memset(soap_binding, 0, sizeof(sdlSoapBindingFunction));
2927 			*soap_binding = *(sdlSoapBindingFunctionPtr)pfunc->bindingAttributes;
2928 			if (soap_binding->soapAction) {
2929 				soap_binding->soapAction = strdup(soap_binding->soapAction);
2930 			}
2931 			make_persistent_sdl_soap_body(&soap_binding->input, ptr_map);
2932 			make_persistent_sdl_soap_body(&soap_binding->output, ptr_map);
2933 			pfunc->bindingAttributes = soap_binding;
2934 		}
2935 
2936 		if (pfunc->requestParameters) {
2937 			pfunc->requestParameters = make_persistent_sdl_parameters(pfunc->requestParameters, ptr_map);
2938 		}
2939 		if (pfunc->responseParameters) {
2940 			pfunc->responseParameters = make_persistent_sdl_parameters(pfunc->responseParameters, ptr_map);
2941 		}
2942 		if (pfunc->faults) {
2943 			pfunc->faults = make_persistent_sdl_function_faults(pfunc, pfunc->faults, ptr_map);
2944 		}
2945 	}
2946 
2947 	return pfunc;
2948 }
2949 
make_persistent_sdl(sdlPtr sdl TSRMLS_DC)2950 static sdlPtr make_persistent_sdl(sdlPtr sdl TSRMLS_DC)
2951 {
2952 	sdlPtr psdl = NULL;
2953 	HashTable ptr_map;
2954 	HashTable bp_types, bp_encoders;
2955 	ulong index;
2956 	char *key;
2957 	uint key_len;
2958 
2959 	zend_hash_init(&bp_types, 0, NULL, NULL, 0);
2960 	zend_hash_init(&bp_encoders, 0, NULL, NULL, 0);
2961 	zend_hash_init(&ptr_map, 0, NULL, NULL, 0);
2962 
2963 	psdl = malloc(sizeof(*sdl));
2964 	memset(psdl, 0, sizeof(*sdl));
2965 
2966 	if (sdl->source) {
2967 		psdl->source = strdup(sdl->source);
2968 	}
2969 	if (sdl->target_ns) {
2970 		psdl->target_ns = strdup(sdl->target_ns);
2971 	}
2972 
2973 	if (sdl->groups) {
2974 		sdlTypePtr *tmp;
2975 		sdlTypePtr ptype;
2976 
2977 		psdl->groups = malloc(sizeof(HashTable));
2978 		zend_hash_init(psdl->groups, zend_hash_num_elements(sdl->groups), NULL, delete_type_persistent, 1);
2979 
2980 		zend_hash_internal_pointer_reset(sdl->groups);
2981 		while (zend_hash_get_current_data(sdl->groups, (void **)&tmp) == SUCCESS) {
2982 			ptype = make_persistent_sdl_type(*tmp, &ptr_map, &bp_types, &bp_encoders);
2983 			if (zend_hash_get_current_key_ex(sdl->groups, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2984 				zend_hash_add(psdl->groups, key, key_len, (void*)&ptype, sizeof(sdlTypePtr), NULL);
2985 			} else {
2986 				zend_hash_next_index_insert(psdl->groups, (void*)&ptype, sizeof(sdlTypePtr), NULL);
2987 			}
2988 			zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&ptype, sizeof(sdlTypePtr), NULL);
2989 			zend_hash_move_forward(sdl->groups);
2990 		}
2991 	}
2992 
2993 	if (sdl->types) {
2994 		sdlTypePtr *tmp;
2995 		sdlTypePtr ptype;
2996 
2997 		psdl->types = malloc(sizeof(HashTable));
2998 		zend_hash_init(psdl->types, zend_hash_num_elements(sdl->types), NULL, delete_type_persistent, 1);
2999 
3000 		zend_hash_internal_pointer_reset(sdl->types);
3001 		while (zend_hash_get_current_data(sdl->types, (void **)&tmp) == SUCCESS) {
3002 			ptype = make_persistent_sdl_type(*tmp, &ptr_map, &bp_types, &bp_encoders);
3003 			if (zend_hash_get_current_key_ex(sdl->types, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3004 				zend_hash_add(psdl->types, key, key_len, (void*)&ptype, sizeof(sdlTypePtr), NULL);
3005 			} else {
3006 				zend_hash_next_index_insert(psdl->types, (void*)&ptype, sizeof(sdlTypePtr), NULL);
3007 			}
3008 			zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&ptype, sizeof(sdlTypePtr), NULL);
3009 			zend_hash_move_forward(sdl->types);
3010 		}
3011 	}
3012 
3013 	if (sdl->elements) {
3014 		sdlTypePtr *tmp;
3015 		sdlTypePtr ptype;
3016 
3017 		psdl->elements = malloc(sizeof(HashTable));
3018 		zend_hash_init(psdl->elements, zend_hash_num_elements(sdl->elements), NULL, delete_type_persistent, 1);
3019 
3020 		zend_hash_internal_pointer_reset(sdl->elements);
3021 		while (zend_hash_get_current_data(sdl->elements, (void **)&tmp) == SUCCESS) {
3022 			ptype = make_persistent_sdl_type(*tmp, &ptr_map, &bp_types, &bp_encoders);
3023 			if (zend_hash_get_current_key_ex(sdl->elements, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3024 				zend_hash_add(psdl->elements, key, key_len, (void*)&ptype, sizeof(sdlTypePtr), NULL);
3025 			} else {
3026 				zend_hash_next_index_insert(psdl->elements, (void*)&ptype, sizeof(sdlTypePtr), NULL);
3027 			}
3028 			zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&ptype, sizeof(sdlTypePtr), NULL);
3029 			zend_hash_move_forward(sdl->elements);
3030 		}
3031 	}
3032 
3033 	if (sdl->encoders) {
3034 		encodePtr *tmp;
3035 		encodePtr penc;
3036 
3037 		psdl->encoders = malloc(sizeof(HashTable));
3038 		zend_hash_init(psdl->encoders, zend_hash_num_elements(sdl->encoders), NULL, delete_encoder_persistent, 1);
3039 
3040 		zend_hash_internal_pointer_reset(sdl->encoders);
3041 		while (zend_hash_get_current_data(sdl->encoders, (void **)&tmp) == SUCCESS) {
3042 			penc = make_persistent_sdl_encoder(*tmp, &ptr_map, &bp_types, &bp_encoders);
3043 			if (zend_hash_get_current_key_ex(sdl->encoders, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3044 				zend_hash_add(psdl->encoders, key, key_len, (void*)&penc, sizeof(encodePtr), NULL);
3045 			} else {
3046 				zend_hash_next_index_insert(psdl->encoders, (void*)&penc, sizeof(encodePtr), NULL);
3047 			}
3048 			zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&penc, sizeof(encodePtr), NULL);
3049 			zend_hash_move_forward(sdl->encoders);
3050 		}
3051 	}
3052 
3053 	/* do backpatching here */
3054 	if (zend_hash_num_elements(&bp_types)) {
3055 		sdlTypePtr **tmp, *ptype = NULL;
3056 
3057 		zend_hash_internal_pointer_reset(&bp_types);
3058 		while (zend_hash_get_current_data(&bp_types, (void**)&tmp) == SUCCESS) {
3059 			if (zend_hash_find(&ptr_map, (char*)(*tmp), sizeof(**tmp), (void**)&ptype) == FAILURE) {
3060 				assert(0);
3061 			}
3062 			**tmp = *ptype;
3063 			zend_hash_move_forward(&bp_types);
3064 		}
3065 	}
3066 	if (zend_hash_num_elements(&bp_encoders)) {
3067 		encodePtr **tmp, *penc = NULL;
3068 
3069 		zend_hash_internal_pointer_reset(&bp_encoders);
3070 		while (zend_hash_get_current_data(&bp_encoders, (void**)&tmp) == SUCCESS) {
3071 			if (zend_hash_find(&ptr_map, (char*)(*tmp), sizeof(**tmp), (void**)&penc) == FAILURE) {
3072 				assert(0);
3073 			}
3074 			**tmp = *penc;
3075 			zend_hash_move_forward(&bp_encoders);
3076 		}
3077 	}
3078 
3079 
3080 	if (sdl->bindings) {
3081 		sdlBindingPtr *tmp;
3082 		sdlBindingPtr pbind;
3083 
3084 		psdl->bindings = malloc(sizeof(HashTable));
3085 		zend_hash_init(psdl->bindings, zend_hash_num_elements(sdl->bindings), NULL, delete_binding_persistent, 1);
3086 
3087 		zend_hash_internal_pointer_reset(sdl->bindings);
3088 		while (zend_hash_get_current_data(sdl->bindings, (void **)&tmp) == SUCCESS) {
3089 			pbind = make_persistent_sdl_binding(*tmp, &ptr_map);
3090 			if (zend_hash_get_current_key_ex(sdl->bindings, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3091 				zend_hash_add(psdl->bindings, key, key_len, (void*)&pbind, sizeof(sdlBindingPtr), NULL);
3092 			} else {
3093 				zend_hash_next_index_insert(psdl->bindings, (void*)&pbind, sizeof(sdlBindingPtr), NULL);
3094 			}
3095 			zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&pbind, sizeof(sdlBindingPtr), NULL);
3096 			zend_hash_move_forward(sdl->bindings);
3097 		}
3098 	}
3099 
3100 	zend_hash_init(&psdl->functions, zend_hash_num_elements(&sdl->functions), NULL, delete_function_persistent, 1);
3101 	if (zend_hash_num_elements(&sdl->functions)) {
3102 		sdlFunctionPtr *tmp;
3103 		sdlFunctionPtr pfunc;
3104 
3105 		zend_hash_internal_pointer_reset(&sdl->functions);
3106 		while (zend_hash_get_current_data(&sdl->functions, (void **)&tmp) == SUCCESS) {
3107 			pfunc = make_persistent_sdl_function(*tmp, &ptr_map);
3108 			if (zend_hash_get_current_key_ex(&sdl->functions, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3109 				zend_hash_add(&psdl->functions, key, key_len, (void*)&pfunc, sizeof(sdlFunctionPtr), NULL);
3110 			} else {
3111 				zend_hash_next_index_insert(&psdl->functions, (void*)&pfunc, sizeof(sdlFunctionPtr), NULL);
3112 			}
3113 			zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&pfunc, sizeof(sdlFunctionPtr), NULL);
3114 			zend_hash_move_forward(&sdl->functions);
3115 		}
3116 	}
3117 
3118 	if (sdl->requests) {
3119 		sdlFunctionPtr *tmp;
3120 		sdlFunctionPtr *preq;
3121 
3122 		psdl->requests = malloc(sizeof(HashTable));
3123 		zend_hash_init(psdl->requests, zend_hash_num_elements(sdl->requests), NULL, NULL, 1);
3124 
3125 		zend_hash_internal_pointer_reset(sdl->requests);
3126 		while (zend_hash_get_current_data(sdl->requests, (void **)&tmp) == SUCCESS) {
3127 			if (zend_hash_find(&ptr_map, (char*)tmp, sizeof(*tmp), (void**)&preq) == FAILURE) {
3128 				assert(0);
3129 			}
3130 			*tmp = *preq;
3131 			if (zend_hash_get_current_key_ex(sdl->requests, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3132 				zend_hash_add(psdl->requests, key, key_len, (void*)&preq, sizeof(sdlFunctionPtr), NULL);
3133 			}
3134 			zend_hash_move_forward(sdl->requests);
3135 		}
3136 	}
3137 
3138 	zend_hash_destroy(&ptr_map);
3139 	zend_hash_destroy(&bp_encoders);
3140 	zend_hash_destroy(&bp_types);
3141 
3142 	return psdl;
3143 }
3144 
3145 typedef struct _sdl_cache_bucket {
3146 	sdlPtr sdl;
3147 	time_t time;
3148 } sdl_cache_bucket;
3149 
delete_psdl(void * data)3150 static void delete_psdl(void *data)
3151 {
3152 	sdl_cache_bucket *p = (sdl_cache_bucket*)data;
3153 	sdlPtr tmp = p->sdl;
3154 
3155 	zend_hash_destroy(&tmp->functions);
3156 	if (tmp->source) {
3157 		free(tmp->source);
3158 	}
3159 	if (tmp->target_ns) {
3160 		free(tmp->target_ns);
3161 	}
3162 	if (tmp->elements) {
3163 		zend_hash_destroy(tmp->elements);
3164 		free(tmp->elements);
3165 	}
3166 	if (tmp->encoders) {
3167 		zend_hash_destroy(tmp->encoders);
3168 		free(tmp->encoders);
3169 	}
3170 	if (tmp->types) {
3171 		zend_hash_destroy(tmp->types);
3172 		free(tmp->types);
3173 	}
3174 	if (tmp->groups) {
3175 		zend_hash_destroy(tmp->groups);
3176 		free(tmp->groups);
3177 	}
3178 	if (tmp->bindings) {
3179 		zend_hash_destroy(tmp->bindings);
3180 		free(tmp->bindings);
3181 	}
3182 	if (tmp->requests) {
3183 		zend_hash_destroy(tmp->requests);
3184 		free(tmp->requests);
3185 	}
3186 	free(tmp);
3187 }
3188 
get_sdl(zval * this_ptr,char * uri,long cache_wsdl TSRMLS_DC)3189 sdlPtr get_sdl(zval *this_ptr, char *uri, long cache_wsdl TSRMLS_DC)
3190 {
3191 	char  fn[MAXPATHLEN];
3192 	sdlPtr sdl = NULL;
3193 	char* old_error_code = SOAP_GLOBAL(error_code);
3194 	int uri_len = 0;
3195 	php_stream_context *context=NULL;
3196 	zval **tmp, **proxy_host, **proxy_port, *orig_context = NULL, *new_context = NULL;
3197 	smart_str headers = {0};
3198 	char* key = NULL;
3199 	time_t t = time(0);
3200 	zend_bool has_proxy_authorization = 0;
3201 	zend_bool has_authorization = 0;
3202 
3203 	if (strchr(uri,':') != NULL || IS_ABSOLUTE_PATH(uri, uri_len)) {
3204 		uri_len = strlen(uri);
3205 	} else if (VCWD_REALPATH(uri, fn) == NULL) {
3206 		cache_wsdl = WSDL_CACHE_NONE;
3207 	} else {
3208 		uri = fn;
3209 		uri_len = strlen(uri);
3210 	}
3211 
3212 	if ((cache_wsdl & WSDL_CACHE_MEMORY) && SOAP_GLOBAL(mem_cache)) {
3213 		sdl_cache_bucket *p;
3214 
3215 		if (SUCCESS == zend_hash_find(SOAP_GLOBAL(mem_cache), uri, uri_len+1, (void*)&p)) {
3216 			if (p->time < t - SOAP_GLOBAL(cache_ttl)) {
3217 				/* in-memory cache entry is expired */
3218 				zend_hash_del(&EG(persistent_list), uri, uri_len+1);
3219 			} else {
3220 				return p->sdl;
3221 			}
3222 		}
3223 	}
3224 
3225 	if ((cache_wsdl & WSDL_CACHE_DISK) && (uri_len < MAXPATHLEN)) {
3226 		time_t t = time(0);
3227 		char md5str[33];
3228 		PHP_MD5_CTX context;
3229 		unsigned char digest[16];
3230 		int len = strlen(SOAP_GLOBAL(cache_dir));
3231 		time_t cached;
3232 		char *user = php_get_current_user(TSRMLS_C);
3233 		int user_len = user ? strlen(user) + 1 : 0;
3234 
3235 		md5str[0] = '\0';
3236 		PHP_MD5Init(&context);
3237 		PHP_MD5Update(&context, (unsigned char*)uri, uri_len);
3238 		PHP_MD5Final(digest, &context);
3239 		make_digest(md5str, digest);
3240 		key = emalloc(len+sizeof("/wsdl-")-1+user_len+sizeof(md5str));
3241 		memcpy(key,SOAP_GLOBAL(cache_dir),len);
3242 		memcpy(key+len,"/wsdl-",sizeof("/wsdl-")-1);
3243 		len += sizeof("/wsdl-")-1;
3244 		if (user_len) {
3245 			memcpy(key+len, user, user_len-1);
3246 			len += user_len-1;
3247 			key[len++] = '-';
3248 		}
3249 		memcpy(key+len,md5str,sizeof(md5str));
3250 
3251 		if ((sdl = get_sdl_from_cache(key, uri, t-SOAP_GLOBAL(cache_ttl), &cached TSRMLS_CC)) != NULL) {
3252 			t = cached;
3253 			efree(key);
3254 			goto cache_in_memory;
3255 		}
3256 	}
3257 
3258 	if (SUCCESS == zend_hash_find(Z_OBJPROP_P(this_ptr),
3259 			"_stream_context", sizeof("_stream_context"), (void**)&tmp)) {
3260 		context = php_stream_context_from_zval(*tmp, 0);
3261 	} else {
3262 		context = php_stream_context_alloc(TSRMLS_C);
3263 	}
3264 
3265 	if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_user_agent", sizeof("_user_agent"), (void **) &tmp) == SUCCESS &&
3266 	    Z_TYPE_PP(tmp) == IS_STRING && Z_STRLEN_PP(tmp) > 0) {
3267 		smart_str_appends(&headers, "User-Agent: ");
3268 		smart_str_appends(&headers, Z_STRVAL_PP(tmp));
3269 		smart_str_appends(&headers, "\r\n");
3270 	}
3271 
3272 	if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_host", sizeof("_proxy_host"), (void **) &proxy_host) == SUCCESS &&
3273 	    Z_TYPE_PP(proxy_host) == IS_STRING &&
3274 	    zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_port", sizeof("_proxy_port"), (void **) &proxy_port) == SUCCESS &&
3275 	    Z_TYPE_PP(proxy_port) == IS_LONG) {
3276 	    	zval str_port, *str_proxy;
3277 	    	smart_str proxy = {0};
3278 		str_port = **proxy_port;
3279 		zval_copy_ctor(&str_port);
3280 		convert_to_string(&str_port);
3281 		smart_str_appends(&proxy,"tcp://");
3282 		smart_str_appends(&proxy,Z_STRVAL_PP(proxy_host));
3283 		smart_str_appends(&proxy,":");
3284 		smart_str_appends(&proxy,Z_STRVAL(str_port));
3285 		smart_str_0(&proxy);
3286 		zval_dtor(&str_port);
3287 		MAKE_STD_ZVAL(str_proxy);
3288 		ZVAL_STRING(str_proxy, proxy.c, 1);
3289 		smart_str_free(&proxy);
3290 
3291 		if (!context) {
3292 			context = php_stream_context_alloc(TSRMLS_C);
3293 		}
3294 		php_stream_context_set_option(context, "http", "proxy", str_proxy);
3295 		zval_ptr_dtor(&str_proxy);
3296 
3297 		if (uri_len < sizeof("https://")-1 ||
3298 		    strncasecmp(uri, "https://", sizeof("https://")-1) != 0) {
3299 			MAKE_STD_ZVAL(str_proxy);
3300 			ZVAL_BOOL(str_proxy, 1);
3301 			php_stream_context_set_option(context, "http", "request_fulluri", str_proxy);
3302 			zval_ptr_dtor(&str_proxy);
3303 		}
3304 
3305 		has_proxy_authorization = proxy_authentication(this_ptr, &headers TSRMLS_CC);
3306 	}
3307 
3308 	has_authorization = basic_authentication(this_ptr, &headers TSRMLS_CC);
3309 
3310 	/* Use HTTP/1.1 with "Connection: close" by default */
3311 	if (php_stream_context_get_option(context, "http", "protocol_version", &tmp) == FAILURE) {
3312     	zval *http_version;
3313 		MAKE_STD_ZVAL(http_version);
3314 		ZVAL_DOUBLE(http_version, 1.1);
3315 		php_stream_context_set_option(context, "http", "protocol_version", http_version);
3316 		zval_ptr_dtor(&http_version);
3317 		smart_str_appendl(&headers, "Connection: close\r\n", sizeof("Connection: close\r\n")-1);
3318 	}
3319 
3320 	if (headers.len > 0) {
3321 		zval *str_headers;
3322 
3323 		if (!context) {
3324 			context = php_stream_context_alloc(TSRMLS_C);
3325 		} else {
3326 			http_context_headers(context, has_authorization, has_proxy_authorization, 0, &headers TSRMLS_CC);
3327 		}
3328 
3329 		smart_str_0(&headers);
3330 		MAKE_STD_ZVAL(str_headers);
3331 		ZVAL_STRING(str_headers, headers.c, 1);
3332 		php_stream_context_set_option(context, "http", "header", str_headers);
3333 		smart_str_free(&headers);
3334 		zval_ptr_dtor(&str_headers);
3335 	}
3336 
3337 	if (context) {
3338 		MAKE_STD_ZVAL(new_context);
3339 		php_stream_context_to_zval(context, new_context);
3340 		orig_context = php_libxml_switch_context(new_context TSRMLS_CC);
3341 	}
3342 
3343 	SOAP_GLOBAL(error_code) = "WSDL";
3344 
3345 	sdl = load_wsdl(this_ptr, uri TSRMLS_CC);
3346 	if (sdl) {
3347 		sdl->is_persistent = 0;
3348 	}
3349 
3350 	SOAP_GLOBAL(error_code) = old_error_code;
3351 
3352 	if (context) {
3353 		php_libxml_switch_context(orig_context TSRMLS_CC);
3354 		zval_ptr_dtor(&new_context);
3355 	}
3356 
3357 	if ((cache_wsdl & WSDL_CACHE_DISK) && key) {
3358 		if (sdl) {
3359 			add_sdl_to_cache(key, uri, t, sdl TSRMLS_CC);
3360 		}
3361 		efree(key);
3362 	}
3363 
3364 cache_in_memory:
3365 	if (cache_wsdl & WSDL_CACHE_MEMORY) {
3366 		if (sdl) {
3367 			sdlPtr psdl;
3368 			sdl_cache_bucket p;
3369 
3370 			if (SOAP_GLOBAL(mem_cache) == NULL) {
3371 				SOAP_GLOBAL(mem_cache) = malloc(sizeof(HashTable));
3372 				zend_hash_init(SOAP_GLOBAL(mem_cache), 0, NULL, delete_psdl, 1);
3373 			} else if (SOAP_GLOBAL(cache_limit) > 0 &&
3374 			           SOAP_GLOBAL(cache_limit) <= zend_hash_num_elements(SOAP_GLOBAL(mem_cache))) {
3375 				/* in-memory cache overflow */
3376 				sdl_cache_bucket *q;
3377 				HashPosition pos;
3378 				time_t latest = t;
3379 				char *key = NULL;
3380 				uint key_len;
3381 				ulong idx;
3382 
3383 				for (zend_hash_internal_pointer_reset_ex(SOAP_GLOBAL(mem_cache), &pos);
3384 					 zend_hash_get_current_data_ex(SOAP_GLOBAL(mem_cache), (void **) &q, &pos) == SUCCESS;
3385 					 zend_hash_move_forward_ex(SOAP_GLOBAL(mem_cache), &pos)) {
3386 					if (q->time < latest) {
3387 						latest = q->time;
3388 						zend_hash_get_current_key_ex(SOAP_GLOBAL(mem_cache), &key, &key_len, &idx, 0, &pos);
3389 					}
3390 				}
3391 				if (key) {
3392 					zend_hash_del(SOAP_GLOBAL(mem_cache), key, key_len);
3393 				} else {
3394 					return sdl;
3395 				}
3396 			}
3397 
3398 			psdl = make_persistent_sdl(sdl TSRMLS_CC);
3399 			psdl->is_persistent = 1;
3400 			p.time = t;
3401 			p.sdl = psdl;
3402 
3403 			if (SUCCESS == zend_hash_update(SOAP_GLOBAL(mem_cache), uri,
3404 											uri_len+1, (void*)&p, sizeof(sdl_cache_bucket), NULL)) {
3405 				/* remove non-persitent sdl structure */
3406 				delete_sdl_impl(sdl);
3407 				/* and replace it with persistent one */
3408 				sdl = psdl;
3409 			} else {
3410 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to register persistent entry");
3411 				/* clean up persistent sdl */
3412 				delete_psdl(&p);
3413 				/* keep non-persistent sdl and return it */
3414 			}
3415 		}
3416 	}
3417 
3418 	return sdl;
3419 }
3420 
3421 /* Deletes */
delete_sdl_impl(void * handle)3422 void delete_sdl_impl(void *handle)
3423 {
3424 	sdlPtr tmp = (sdlPtr)handle;
3425 
3426 	zend_hash_destroy(&tmp->functions);
3427 	if (tmp->source) {
3428 		efree(tmp->source);
3429 	}
3430 	if (tmp->target_ns) {
3431 		efree(tmp->target_ns);
3432 	}
3433 	if (tmp->elements) {
3434 		zend_hash_destroy(tmp->elements);
3435 		efree(tmp->elements);
3436 	}
3437 	if (tmp->encoders) {
3438 		zend_hash_destroy(tmp->encoders);
3439 		efree(tmp->encoders);
3440 	}
3441 	if (tmp->types) {
3442 		zend_hash_destroy(tmp->types);
3443 		efree(tmp->types);
3444 	}
3445 	if (tmp->groups) {
3446 		zend_hash_destroy(tmp->groups);
3447 		efree(tmp->groups);
3448 	}
3449 	if (tmp->bindings) {
3450 		zend_hash_destroy(tmp->bindings);
3451 		efree(tmp->bindings);
3452 	}
3453 	if (tmp->requests) {
3454 		zend_hash_destroy(tmp->requests);
3455 		efree(tmp->requests);
3456 	}
3457 	efree(tmp);
3458 }
3459 
delete_sdl(void * handle)3460 void delete_sdl(void *handle)
3461 {
3462 	sdlPtr tmp = (sdlPtr)handle;
3463 
3464 	if (!tmp->is_persistent) {
3465 		delete_sdl_impl(tmp);
3466 	}
3467 }
3468 
delete_binding(void * data)3469 static void delete_binding(void *data)
3470 {
3471 	sdlBindingPtr binding = *((sdlBindingPtr*)data);
3472 
3473 	if (binding->location) {
3474 		efree(binding->location);
3475 	}
3476 	if (binding->name) {
3477 		efree(binding->name);
3478 	}
3479 
3480 	if (binding->bindingType == BINDING_SOAP) {
3481 		sdlSoapBindingPtr soapBind = binding->bindingAttributes;
3482 		if (soapBind) {
3483 			efree(soapBind);
3484 		}
3485 	}
3486 	efree(binding);
3487 }
3488 
delete_binding_persistent(void * data)3489 static void delete_binding_persistent(void *data)
3490 {
3491 	sdlBindingPtr binding = *((sdlBindingPtr*)data);
3492 
3493 	if (binding->location) {
3494 		free(binding->location);
3495 	}
3496 	if (binding->name) {
3497 		free(binding->name);
3498 	}
3499 
3500 	if (binding->bindingType == BINDING_SOAP) {
3501 		sdlSoapBindingPtr soapBind = binding->bindingAttributes;
3502 		if (soapBind) {
3503 			free(soapBind);
3504 		}
3505 	}
3506 	free(binding);
3507 }
3508 
delete_sdl_soap_binding_function_body(sdlSoapBindingFunctionBody body)3509 static void delete_sdl_soap_binding_function_body(sdlSoapBindingFunctionBody body)
3510 {
3511 	if (body.ns) {
3512 		efree(body.ns);
3513 	}
3514 	if (body.headers) {
3515 		zend_hash_destroy(body.headers);
3516 		efree(body.headers);
3517 	}
3518 }
3519 
delete_sdl_soap_binding_function_body_persistent(sdlSoapBindingFunctionBody body)3520 static void delete_sdl_soap_binding_function_body_persistent(sdlSoapBindingFunctionBody body)
3521 {
3522 	if (body.ns) {
3523 		free(body.ns);
3524 	}
3525 	if (body.headers) {
3526 		zend_hash_destroy(body.headers);
3527 		free(body.headers);
3528 	}
3529 }
3530 
delete_function(void * data)3531 static void delete_function(void *data)
3532 {
3533 	sdlFunctionPtr function = *((sdlFunctionPtr*)data);
3534 
3535 	if (function->functionName) {
3536 		efree(function->functionName);
3537 	}
3538 	if (function->requestName) {
3539 		efree(function->requestName);
3540 	}
3541 	if (function->responseName) {
3542 		efree(function->responseName);
3543 	}
3544 	if (function->requestParameters) {
3545 		zend_hash_destroy(function->requestParameters);
3546 		efree(function->requestParameters);
3547 	}
3548 	if (function->responseParameters) {
3549 		zend_hash_destroy(function->responseParameters);
3550 		efree(function->responseParameters);
3551 	}
3552 	if (function->faults) {
3553 		zend_hash_destroy(function->faults);
3554 		efree(function->faults);
3555 	}
3556 
3557 	if (function->bindingAttributes &&
3558 	    function->binding && function->binding->bindingType == BINDING_SOAP) {
3559 		sdlSoapBindingFunctionPtr soapFunction = function->bindingAttributes;
3560 		if (soapFunction->soapAction) {
3561 			efree(soapFunction->soapAction);
3562 		}
3563 		delete_sdl_soap_binding_function_body(soapFunction->input);
3564 		delete_sdl_soap_binding_function_body(soapFunction->output);
3565 		efree(soapFunction);
3566 	}
3567 	efree(function);
3568 }
3569 
delete_function_persistent(void * data)3570 static void delete_function_persistent(void *data)
3571 {
3572 	sdlFunctionPtr function = *((sdlFunctionPtr*)data);
3573 
3574 	if (function->functionName) {
3575 		free(function->functionName);
3576 	}
3577 	if (function->requestName) {
3578 		free(function->requestName);
3579 	}
3580 	if (function->responseName) {
3581 		free(function->responseName);
3582 	}
3583 	if (function->requestParameters) {
3584 		zend_hash_destroy(function->requestParameters);
3585 		free(function->requestParameters);
3586 	}
3587 	if (function->responseParameters) {
3588 		zend_hash_destroy(function->responseParameters);
3589 		free(function->responseParameters);
3590 	}
3591 	if (function->faults) {
3592 		zend_hash_destroy(function->faults);
3593 		free(function->faults);
3594 	}
3595 
3596 	if (function->bindingAttributes &&
3597 	    function->binding && function->binding->bindingType == BINDING_SOAP) {
3598 		sdlSoapBindingFunctionPtr soapFunction = function->bindingAttributes;
3599 		if (soapFunction->soapAction) {
3600 			free(soapFunction->soapAction);
3601 		}
3602 		delete_sdl_soap_binding_function_body_persistent(soapFunction->input);
3603 		delete_sdl_soap_binding_function_body_persistent(soapFunction->output);
3604 		free(soapFunction);
3605 	}
3606 	free(function);
3607 }
3608 
delete_parameter(void * data)3609 static void delete_parameter(void *data)
3610 {
3611 	sdlParamPtr param = *((sdlParamPtr*)data);
3612 	if (param->paramName) {
3613 		efree(param->paramName);
3614 	}
3615 	efree(param);
3616 }
3617 
delete_parameter_persistent(void * data)3618 static void delete_parameter_persistent(void *data)
3619 {
3620 	sdlParamPtr param = *((sdlParamPtr*)data);
3621 	if (param->paramName) {
3622 		free(param->paramName);
3623 	}
3624 	free(param);
3625 }
3626 
delete_header(void * data)3627 static void delete_header(void *data)
3628 {
3629 	sdlSoapBindingFunctionHeaderPtr hdr = *((sdlSoapBindingFunctionHeaderPtr*)data);
3630 	if (hdr->name) {
3631 		efree(hdr->name);
3632 	}
3633 	if (hdr->ns) {
3634 		efree(hdr->ns);
3635 	}
3636 	if (hdr->headerfaults) {
3637 		zend_hash_destroy(hdr->headerfaults);
3638 		efree(hdr->headerfaults);
3639 	}
3640 	efree(hdr);
3641 }
3642 
delete_header_persistent(void * data)3643 static void delete_header_persistent(void *data)
3644 {
3645 	sdlSoapBindingFunctionHeaderPtr hdr = *((sdlSoapBindingFunctionHeaderPtr*)data);
3646 	if (hdr->name) {
3647 		free(hdr->name);
3648 	}
3649 	if (hdr->ns) {
3650 		free(hdr->ns);
3651 	}
3652 	if (hdr->headerfaults) {
3653 		zend_hash_destroy(hdr->headerfaults);
3654 		free(hdr->headerfaults);
3655 	}
3656 	free(hdr);
3657 }
3658 
delete_fault(void * data)3659 static void delete_fault(void *data)
3660 {
3661 	sdlFaultPtr fault = *((sdlFaultPtr*)data);
3662 	if (fault->name) {
3663 		efree(fault->name);
3664 	}
3665 	if (fault->details) {
3666 		zend_hash_destroy(fault->details);
3667 		efree(fault->details);
3668 	}
3669 	if (fault->bindingAttributes) {
3670 		sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
3671 
3672 		if (binding->ns) {
3673 			efree(binding->ns);
3674 		}
3675 		efree(fault->bindingAttributes);
3676 	}
3677 	efree(fault);
3678 }
3679 
delete_fault_persistent(void * data)3680 static void delete_fault_persistent(void *data)
3681 {
3682 	sdlFaultPtr fault = *((sdlFaultPtr*)data);
3683 	if (fault->name) {
3684 		free(fault->name);
3685 	}
3686 	if (fault->details) {
3687 		zend_hash_destroy(fault->details);
3688 		free(fault->details);
3689 	}
3690 	if (fault->bindingAttributes) {
3691 		sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
3692 
3693 		if (binding->ns) {
3694 			free(binding->ns);
3695 		}
3696 		free(fault->bindingAttributes);
3697 	}
3698 	free(fault);
3699 }
3700 
delete_document(void * doc_ptr)3701 static void delete_document(void *doc_ptr)
3702 {
3703 	xmlDocPtr doc = *((xmlDocPtr*)doc_ptr);
3704 	xmlFreeDoc(doc);
3705 }
3706 
3707