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