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