1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 7                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) The PHP Group                                          |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.txt                                  |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Authors: Brad Lafountain <rodif_bl@yahoo.com>                        |
16   |          Shane Caraveo <shane@caraveo.com>                           |
17   |          Dmitry Stogov <dmitry@php.net>                              |
18   +----------------------------------------------------------------------+
19 */
20 
21 #include "php_soap.h"
22 #include "ext/libxml/php_libxml.h"
23 #include "libxml/uri.h"
24 
25 #include "ext/standard/md5.h"
26 #include "zend_virtual_cwd.h"
27 
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 
32 #ifndef O_BINARY
33 # define O_BINARY 0
34 #endif
35 
36 static void delete_fault(zval *zv);
37 static void delete_fault_persistent(zval *zv);
38 static void delete_binding(zval *zv);
39 static void delete_binding_persistent(zval *zv);
40 static void delete_function(zval *zv);
41 static void delete_function_persistent(zval *zv);
42 static void delete_parameter(zval *zv);
43 static void delete_parameter_persistent(zval *zv);
44 static void delete_header(zval *header);
45 static void delete_header_int(sdlSoapBindingFunctionHeaderPtr hdr);
46 static void delete_header_persistent(zval *zv);
47 static void delete_document(zval *zv);
48 
get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr node, const xmlChar *type)49 encodePtr get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr node, const xmlChar *type)
50 {
51 	encodePtr enc = NULL;
52 	xmlNsPtr nsptr;
53 	char *ns, *cptype;
54 
55 	parse_namespace(type, &cptype, &ns);
56 	nsptr = xmlSearchNs(node->doc, node, BAD_CAST(ns));
57 	if (nsptr != NULL) {
58 		enc = get_encoder(sdl, (char*)nsptr->href, cptype);
59 		if (enc == NULL) {
60 			enc = get_encoder_ex(sdl, cptype, strlen(cptype));
61 		}
62 	} else {
63 		enc = get_encoder_ex(sdl, (char*)type, xmlStrlen(type));
64 	}
65 	efree(cptype);
66 	if (ns) {efree(ns);}
67 	return enc;
68 }
69 
get_element(sdlPtr sdl, xmlNodePtr node, const xmlChar *type)70 static sdlTypePtr get_element(sdlPtr sdl, xmlNodePtr node, const xmlChar *type)
71 {
72 	sdlTypePtr ret = NULL;
73 
74 	if (sdl->elements) {
75 		xmlNsPtr nsptr;
76 		char *ns, *cptype;
77 		sdlTypePtr sdl_type;
78 
79 		parse_namespace(type, &cptype, &ns);
80 		nsptr = xmlSearchNs(node->doc, node, BAD_CAST(ns));
81 		if (nsptr != NULL) {
82 			int ns_len = xmlStrlen(nsptr->href);
83 			int type_len = strlen(cptype);
84 			int len = ns_len + type_len + 1;
85 			char *nscat = emalloc(len + 1);
86 
87 			memcpy(nscat, nsptr->href, ns_len);
88 			nscat[ns_len] = ':';
89 			memcpy(nscat+ns_len+1, cptype, type_len);
90 			nscat[len] = '\0';
91 
92 			if ((sdl_type = zend_hash_str_find_ptr(sdl->elements, nscat, len)) != NULL) {
93 				ret = sdl_type;
94 			} else if ((sdl_type = zend_hash_str_find_ptr(sdl->elements, (char*)type, type_len)) != NULL) {
95 				ret = sdl_type;
96 			}
97 			efree(nscat);
98 		} else {
99 			if ((sdl_type = zend_hash_str_find_ptr(sdl->elements, (char*)type, xmlStrlen(type))) != NULL) {
100 				ret = sdl_type;
101 			}
102 		}
103 
104 		efree(cptype);
105 		if (ns) {efree(ns);}
106 	}
107 	return ret;
108 }
109 
get_encoder(sdlPtr sdl, const char *ns, const char *type)110 encodePtr get_encoder(sdlPtr sdl, const char *ns, const char *type)
111 {
112 	encodePtr enc = NULL;
113 	char *nscat;
114 	int ns_len = ns ? strlen(ns) : 0;
115 	int type_len = strlen(type);
116 	int len = ns_len + type_len + 1;
117 
118 	nscat = emalloc(len + 1);
119 	if (ns) {
120 		memcpy(nscat, ns, ns_len);
121 	}
122 	nscat[ns_len] = ':';
123 	memcpy(nscat+ns_len+1, type, type_len);
124 	nscat[len] = '\0';
125 
126 	enc = get_encoder_ex(sdl, nscat, len);
127 
128 	if (enc == NULL &&
129 	    ((ns_len == sizeof(SOAP_1_1_ENC_NAMESPACE)-1 &&
130 	      memcmp(ns, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)-1) == 0) ||
131 	     (ns_len == sizeof(SOAP_1_2_ENC_NAMESPACE)-1 &&
132 	      memcmp(ns, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)-1) == 0))) {
133 		char *enc_nscat;
134 		int enc_ns_len;
135 		int enc_len;
136 
137 		enc_ns_len = sizeof(XSD_NAMESPACE)-1;
138 		enc_len = enc_ns_len + type_len + 1;
139 		enc_nscat = emalloc(enc_len + 1);
140 		memcpy(enc_nscat, XSD_NAMESPACE, sizeof(XSD_NAMESPACE)-1);
141 		enc_nscat[enc_ns_len] = ':';
142 		memcpy(enc_nscat+enc_ns_len+1, type, type_len);
143 		enc_nscat[enc_len] = '\0';
144 
145 		enc = get_encoder_ex(NULL, enc_nscat, enc_len);
146 		efree(enc_nscat);
147 		if (enc && sdl) {
148 			encodePtr new_enc	= pemalloc(sizeof(encode), sdl->is_persistent);
149 			memcpy(new_enc, enc, sizeof(encode));
150 			if (sdl->is_persistent) {
151 				new_enc->details.ns = zend_strndup(ns, ns_len);
152 				new_enc->details.type_str = strdup(new_enc->details.type_str);
153 			} else {
154 				new_enc->details.ns = estrndup(ns, ns_len);
155 				new_enc->details.type_str = estrdup(new_enc->details.type_str);
156 			}
157 			if (sdl->encoders == NULL) {
158 				sdl->encoders = pemalloc(sizeof(HashTable), sdl->is_persistent);
159 				zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, sdl->is_persistent);
160 			}
161 			zend_hash_str_update_ptr(sdl->encoders, nscat, len, new_enc);
162 			enc = new_enc;
163 		}
164 	}
165 	efree(nscat);
166 	return enc;
167 }
168 
get_encoder_ex(sdlPtr sdl, const char *nscat, int len)169 encodePtr get_encoder_ex(sdlPtr sdl, const char *nscat, int len)
170 {
171 	encodePtr enc;
172 
173 	if ((enc = zend_hash_str_find_ptr(&SOAP_GLOBAL(defEnc), (char*)nscat, len)) != NULL) {
174 		return enc;
175 	} else if (sdl && sdl->encoders && (enc = zend_hash_str_find_ptr(sdl->encoders, (char*)nscat, len)) != NULL) {
176 		return enc;
177 	}
178 	return NULL;
179 }
180 
get_binding_from_type(sdlPtr sdl, sdlBindingType type)181 sdlBindingPtr get_binding_from_type(sdlPtr sdl, sdlBindingType type)
182 {
183 	sdlBindingPtr binding;
184 
185 	if (sdl == NULL) {
186 		return NULL;
187 	}
188 
189 	ZEND_HASH_FOREACH_PTR(sdl->bindings, binding) {
190 		if (binding->bindingType == type) {
191 			return binding;
192 		}
193 	} ZEND_HASH_FOREACH_END();
194 	return NULL;
195 }
196 
get_binding_from_name(sdlPtr sdl, char *name, char *ns)197 sdlBindingPtr get_binding_from_name(sdlPtr sdl, char *name, char *ns)
198 {
199 	sdlBindingPtr binding;
200 	smart_str key = {0};
201 
202 	smart_str_appends(&key, ns);
203 	smart_str_appendc(&key, ':');
204 	smart_str_appends(&key, name);
205 	smart_str_0(&key);
206 
207 	binding = zend_hash_find_ptr(sdl->bindings, key.s);
208 
209 	smart_str_free(&key);
210 	return binding;
211 }
212 
is_wsdl_element(xmlNodePtr node)213 static int is_wsdl_element(xmlNodePtr node)
214 {
215 	if (node->ns && strcmp((char*)node->ns->href, WSDL_NAMESPACE) != 0) {
216 		xmlAttrPtr attr;
217 		if ((attr = get_attribute_ex(node->properties, "required", WSDL_NAMESPACE)) != NULL &&
218 		     attr->children && attr->children->content &&
219 		     (strcmp((char*)attr->children->content, "1") == 0 ||
220 		      strcmp((char*)attr->children->content, "true") == 0)) {
221 			soap_error1(E_ERROR, "Parsing WSDL: Unknown required WSDL extension '%s'", node->ns->href);
222 		}
223 		return 0;
224 	}
225 	return 1;
226 }
227 
sdl_set_uri_credentials(sdlCtx *ctx, char *uri)228 void sdl_set_uri_credentials(sdlCtx *ctx, char *uri)
229 {
230 	char *s;
231 	size_t l1, l2;
232 	zval context;
233 	zval *header = NULL;
234 
235 	/* check if we load xsd from the same server */
236 	s = strstr(ctx->sdl->source, "://");
237 	if (!s) return;
238 	s = strchr(s+3, '/');
239 	l1 = s ? (size_t)(s - ctx->sdl->source) : strlen(ctx->sdl->source);
240 	s = strstr((char*)uri, "://");
241 	if (!s) return;
242 	s = strchr(s+3, '/');
243 	l2 = s ? (size_t)(s - (char*)uri) : strlen((char*)uri);
244 	if (l1 != l2) {
245 		/* check for http://...:80/ */
246 		if (l1 > 11 &&
247 		    ctx->sdl->source[4] == ':' &&
248 		    ctx->sdl->source[l1-3] == ':' &&
249 		    ctx->sdl->source[l1-2] == '8' &&
250 		    ctx->sdl->source[l1-1] == '0') {
251 			l1 -= 3;
252 		}
253 		if (l2 > 11 &&
254 		    uri[4] == ':' &&
255 		    uri[l2-3] == ':' &&
256 		    uri[l2-2] == '8' &&
257 		    uri[l2-1] == '0') {
258 			l2 -= 3;
259 		}
260 		/* check for https://...:443/ */
261 		if (l1 > 13 &&
262 		    ctx->sdl->source[4] == 's' &&
263 		    ctx->sdl->source[l1-4] == ':' &&
264 		    ctx->sdl->source[l1-3] == '4' &&
265 		    ctx->sdl->source[l1-2] == '4' &&
266 		    ctx->sdl->source[l1-1] == '3') {
267 			l1 -= 4;
268 		}
269 		if (l2 > 13 &&
270 		    uri[4] == 's' &&
271 		    uri[l2-4] == ':' &&
272 		    uri[l2-3] == '4' &&
273 		    uri[l2-2] == '4' &&
274 		    uri[l2-1] == '3') {
275 			l2 -= 4;
276 		}
277 	}
278 	if (l1 != l2 || memcmp(ctx->sdl->source, uri, l1) != 0) {
279 		/* another server. clear authentication credentals */
280 		php_libxml_switch_context(NULL, &context);
281 		php_libxml_switch_context(&context, NULL);
282 		if (Z_TYPE(context) != IS_UNDEF) {
283 			zval *context_ptr = &context;
284 			ctx->context = php_stream_context_from_zval(context_ptr, 1);
285 
286 			if (ctx->context &&
287 			    (header = php_stream_context_get_option(ctx->context, "http", "header")) != NULL) {
288 				s = strstr(Z_STRVAL_P(header), "Authorization: Basic");
289 				if (s && (s == Z_STRVAL_P(header) || *(s-1) == '\n' || *(s-1) == '\r')) {
290 					char *rest = strstr(s, "\r\n");
291 					if (rest) {
292 						zval new_header;
293 
294 						rest += 2;
295 						ZVAL_NEW_STR(&new_header, zend_string_alloc(Z_STRLEN_P(header) - (rest - s), 0));
296 						memcpy(Z_STRVAL(new_header), Z_STRVAL_P(header), s - Z_STRVAL_P(header));
297 						memcpy(Z_STRVAL(new_header) + (s - Z_STRVAL_P(header)), rest, Z_STRLEN_P(header) - (rest - Z_STRVAL_P(header)) + 1);
298 						ZVAL_COPY(&ctx->old_header, header);
299 						php_stream_context_set_option(ctx->context, "http", "header", &new_header);
300 						zval_ptr_dtor(&new_header);
301 					}
302 				}
303 			}
304 		}
305 	}
306 }
307 
sdl_restore_uri_credentials(sdlCtx *ctx)308 void sdl_restore_uri_credentials(sdlCtx *ctx)
309 {
310 	if (Z_TYPE(ctx->old_header) != IS_UNDEF) {
311 	    php_stream_context_set_option(ctx->context, "http", "header", &ctx->old_header);
312 	    zval_ptr_dtor(&ctx->old_header);
313 		ZVAL_UNDEF(&ctx->old_header);
314 	}
315 	ctx->context = NULL;
316 }
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>", 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>", 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>", 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>", 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>", 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>", 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'", 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 	load_wsdl_ex(this_ptr, struri, &ctx, 0);
743 	zend_try {
744 
745 	schema_pass2(&ctx);
746 
747 	n = zend_hash_num_elements(&ctx.services);
748 	if (n > 0) {
749 		zend_hash_internal_pointer_reset(&ctx.services);
750 		for (i = 0; i < n; i++) {
751 			xmlNodePtr service, tmp;
752 			xmlNodePtr trav, port;
753 			int has_soap_port = 0;
754 
755 			service = tmp = zend_hash_get_current_data_ptr(&ctx.services);
756 
757 			trav = service->children;
758 			while (trav != NULL) {
759 				xmlAttrPtr type, name, bindingAttr, location;
760 				xmlNodePtr portType, operation;
761 				xmlNodePtr address, binding, trav2;
762 				char *ctype;
763 				sdlBindingPtr tmpbinding;
764 				char *wsdl_soap_namespace = NULL;
765 
766 				if (!is_wsdl_element(trav) || node_is_equal(trav,"documentation")) {
767 					trav = trav->next;
768 					continue;
769 				}
770 				if (!node_is_equal(trav,"port")) {
771 					soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
772 				}
773 
774 				port = trav;
775 
776 				tmpbinding = emalloc(sizeof(sdlBinding));
777 				memset(tmpbinding, 0, sizeof(sdlBinding));
778 
779 				bindingAttr = get_attribute(port->properties, "binding");
780 				if (bindingAttr == NULL) {
781 					soap_error0(E_ERROR, "Parsing WSDL: No binding associated with <port>");
782 				}
783 
784 				/* find address and figure out binding type */
785 				address = NULL;
786 				trav2 = port->children;
787 				while (trav2 != NULL) {
788 					if (node_is_equal(trav2,"address") && trav2->ns) {
789 						if (!strncmp((char*)trav2->ns->href, WSDL_SOAP11_NAMESPACE, sizeof(WSDL_SOAP11_NAMESPACE))) {
790 							address = trav2;
791 							wsdl_soap_namespace = WSDL_SOAP11_NAMESPACE;
792 							tmpbinding->bindingType = BINDING_SOAP;
793 						} else if (!strncmp((char*)trav2->ns->href, WSDL_SOAP12_NAMESPACE, sizeof(WSDL_SOAP12_NAMESPACE))) {
794 							address = trav2;
795 							wsdl_soap_namespace = WSDL_SOAP12_NAMESPACE;
796 							tmpbinding->bindingType = BINDING_SOAP;
797 						} else if (!strncmp((char*)trav2->ns->href, RPC_SOAP12_NAMESPACE, sizeof(RPC_SOAP12_NAMESPACE))) {
798 							address = trav2;
799 							wsdl_soap_namespace = RPC_SOAP12_NAMESPACE;
800 							tmpbinding->bindingType = BINDING_SOAP;
801 						} else if (!strncmp((char*)trav2->ns->href, WSDL_HTTP11_NAMESPACE, sizeof(WSDL_HTTP11_NAMESPACE))) {
802 							address = trav2;
803 							tmpbinding->bindingType = BINDING_HTTP;
804 						} else if (!strncmp((char*)trav2->ns->href, WSDL_HTTP12_NAMESPACE, sizeof(WSDL_HTTP12_NAMESPACE))) {
805 							address = trav2;
806 							tmpbinding->bindingType = BINDING_HTTP;
807 						}
808 					}
809 					if (trav2 != address && is_wsdl_element(trav2) && !node_is_equal(trav2,"documentation")) {
810 						soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
811 					}
812 				  trav2 = trav2->next;
813 				}
814 				if (!address || tmpbinding->bindingType == BINDING_HTTP) {
815 					if (has_soap_port || trav->next || i < n-1) {
816 						efree(tmpbinding);
817 						trav = trav->next;
818 						continue;
819 					} else if (!address) {
820 						soap_error0(E_ERROR, "Parsing WSDL: No address associated with <port>");
821 					}
822 				}
823 				has_soap_port = 1;
824 
825 				location = get_attribute(address->properties, "location");
826 				if (!location) {
827 					soap_error0(E_ERROR, "Parsing WSDL: No location associated with <port>");
828 				}
829 
830 				tmpbinding->location = estrdup((char*)location->children->content);
831 
832 				ctype = strrchr((char*)bindingAttr->children->content,':');
833 				if (ctype == NULL) {
834 					ctype = (char*)bindingAttr->children->content;
835 				} else {
836 					++ctype;
837 				}
838 				if ((tmp = zend_hash_str_find_ptr(&ctx.bindings, ctype, strlen(ctype))) == NULL) {
839 					soap_error1(E_ERROR, "Parsing WSDL: No <binding> element with name '%s'", ctype);
840 				}
841 				binding = tmp;
842 
843 				if (tmpbinding->bindingType == BINDING_SOAP) {
844 					sdlSoapBindingPtr soapBinding;
845 					xmlNodePtr soapBindingNode;
846 					xmlAttrPtr tmp;
847 
848 					soapBinding = emalloc(sizeof(sdlSoapBinding));
849 					memset(soapBinding, 0, sizeof(sdlSoapBinding));
850 					soapBinding->style = SOAP_DOCUMENT;
851 
852 					soapBindingNode = get_node_ex(binding->children, "binding", wsdl_soap_namespace);
853 					if (soapBindingNode) {
854 						tmp = get_attribute(soapBindingNode->properties, "style");
855 						if (tmp && !strncmp((char*)tmp->children->content, "rpc", sizeof("rpc"))) {
856 							soapBinding->style = SOAP_RPC;
857 						}
858 
859 						tmp = get_attribute(soapBindingNode->properties, "transport");
860 						if (tmp) {
861 							if (strncmp((char*)tmp->children->content, WSDL_HTTP_TRANSPORT, sizeof(WSDL_HTTP_TRANSPORT)) == 0) {
862 								soapBinding->transport = SOAP_TRANSPORT_HTTP;
863 							} else {
864 								/* try the next binding */
865 								efree(soapBinding);
866 								efree(tmpbinding->location);
867 								efree(tmpbinding);
868 								trav = trav->next;
869 								continue;
870 							}
871 						}
872 					}
873 					tmpbinding->bindingAttributes = (void *)soapBinding;
874 				}
875 
876 				name = get_attribute(binding->properties, "name");
877 				if (name == NULL) {
878 					soap_error0(E_ERROR, "Parsing WSDL: Missing 'name' attribute for <binding>");
879 				}
880 				tmpbinding->name = estrdup((char*)name->children->content);
881 
882 				type = get_attribute(binding->properties, "type");
883 				if (type == NULL) {
884 					soap_error0(E_ERROR, "Parsing WSDL: Missing 'type' attribute for <binding>");
885 				}
886 
887 				ctype = strrchr((char*)type->children->content,':');
888 				if (ctype == NULL) {
889 					ctype = (char*)type->children->content;
890 				} else {
891 					++ctype;
892 				}
893 				if ((tmp = zend_hash_str_find_ptr(&ctx.portTypes, ctype, strlen(ctype))) == NULL) {
894 					soap_error1(E_ERROR, "Parsing WSDL: Missing <portType> with name '%s'", name->children->content);
895 				}
896 				portType = tmp;
897 
898 				trav2 = binding->children;
899 				while (trav2 != NULL) {
900 					sdlFunctionPtr function;
901 					xmlNodePtr input, output, fault, portTypeOperation, trav3;
902 					xmlAttrPtr op_name, paramOrder;
903 
904 					if ((tmpbinding->bindingType == BINDING_SOAP &&
905 					    node_is_equal_ex(trav2, "binding", wsdl_soap_namespace)) ||
906 					    !is_wsdl_element(trav2) ||
907 					    node_is_equal(trav2,"documentation")) {
908 						trav2 = trav2->next;
909 						continue;
910 					}
911 					if (!node_is_equal(trav2,"operation")) {
912 						soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
913 					}
914 
915 					operation = trav2;
916 
917 					op_name = get_attribute(operation->properties, "name");
918 					if (op_name == NULL) {
919 						soap_error0(E_ERROR, "Parsing WSDL: Missing 'name' attribute for <operation>");
920 					}
921 
922 					trav3 = operation->children;
923 					while  (trav3 != NULL) {
924 						if (tmpbinding->bindingType == BINDING_SOAP &&
925 						    node_is_equal_ex(trav3, "operation", wsdl_soap_namespace)) {
926 						} else if (is_wsdl_element(trav3) &&
927 						           !node_is_equal(trav3,"input") &&
928 						           !node_is_equal(trav3,"output") &&
929 						           !node_is_equal(trav3,"fault") &&
930 						           !node_is_equal(trav3,"documentation")) {
931 							soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav3->name);
932 						}
933 						trav3 = trav3->next;
934 					}
935 
936 					portTypeOperation = get_node_with_attribute_ex(portType->children, "operation", WSDL_NAMESPACE, "name", (char*)op_name->children->content, NULL);
937 					if (portTypeOperation == NULL) {
938 						soap_error1(E_ERROR, "Parsing WSDL: Missing <portType>/<operation> with name '%s'", op_name->children->content);
939 					}
940 
941 					function = emalloc(sizeof(sdlFunction));
942 					memset(function, 0, sizeof(sdlFunction));
943 					function->functionName = estrdup((char*)op_name->children->content);
944 
945 					if (tmpbinding->bindingType == BINDING_SOAP) {
946 						sdlSoapBindingFunctionPtr soapFunctionBinding;
947 						sdlSoapBindingPtr soapBinding;
948 						xmlNodePtr soapOperation;
949 						xmlAttrPtr tmp;
950 
951 						soapFunctionBinding = emalloc(sizeof(sdlSoapBindingFunction));
952 						memset(soapFunctionBinding, 0, sizeof(sdlSoapBindingFunction));
953 						soapBinding = (sdlSoapBindingPtr)tmpbinding->bindingAttributes;
954 						soapFunctionBinding->style = soapBinding->style;
955 
956 						soapOperation = get_node_ex(operation->children, "operation", wsdl_soap_namespace);
957 						if (soapOperation) {
958 							tmp = get_attribute(soapOperation->properties, "soapAction");
959 							if (tmp) {
960 								soapFunctionBinding->soapAction = estrdup((char*)tmp->children->content);
961 							}
962 
963 							tmp = get_attribute(soapOperation->properties, "style");
964 							if (tmp) {
965 								if (!strncmp((char*)tmp->children->content, "rpc", sizeof("rpc"))) {
966 									soapFunctionBinding->style = SOAP_RPC;
967 								} else {
968 									soapFunctionBinding->style = SOAP_DOCUMENT;
969 								}
970 							} else {
971 								soapFunctionBinding->style = soapBinding->style;
972 							}
973 						}
974 
975 						function->bindingAttributes = (void *)soapFunctionBinding;
976 					}
977 
978 					input = get_node_ex(portTypeOperation->children, "input", WSDL_NAMESPACE);
979 					if (input != NULL) {
980 						xmlAttrPtr message;
981 
982 						message = get_attribute(input->properties, "message");
983 						if (message == NULL) {
984 							soap_error1(E_ERROR, "Parsing WSDL: Missing name for <input> of '%s'", op_name->children->content);
985 						}
986 						function->requestParameters = wsdl_message(&ctx, message->children->content);
987 
988 /* FIXME
989 						xmlAttrPtr name = get_attribute(input->properties, "name");
990 						if (name != NULL) {
991 							function->requestName = estrdup(name->children->content);
992 						} else {
993 */
994 						{
995 							function->requestName = estrdup(function->functionName);
996 						}
997 
998 						if (tmpbinding->bindingType == BINDING_SOAP) {
999 							input = get_node_ex(operation->children, "input", WSDL_NAMESPACE);
1000 							if (input != NULL) {
1001 								sdlSoapBindingFunctionPtr soapFunctionBinding = function->bindingAttributes;
1002 								wsdl_soap_binding_body(&ctx, input, wsdl_soap_namespace, &soapFunctionBinding->input, function->requestParameters);
1003 							}
1004 						}
1005 					}
1006 
1007 					output = get_node_ex(portTypeOperation->children, "output", WSDL_NAMESPACE);
1008 					if (output != NULL) {
1009 						xmlAttrPtr message;
1010 
1011 						message = get_attribute(output->properties, "message");
1012 						if (message == NULL) {
1013 							soap_error1(E_ERROR, "Parsing WSDL: Missing name for <output> of '%s'", op_name->children->content);
1014 						}
1015 						function->responseParameters = wsdl_message(&ctx, message->children->content);
1016 
1017 /* FIXME
1018 						xmlAttrPtr name = get_attribute(output->properties, "name");
1019 						if (name != NULL) {
1020 							function->responseName = estrdup(name->children->content);
1021 						} else if (input == NULL) {
1022 							function->responseName = estrdup(function->functionName);
1023 						} else {
1024 */
1025 						{
1026 							int len = strlen(function->functionName);
1027 							function->responseName = emalloc(len + sizeof("Response"));
1028 							memcpy(function->responseName, function->functionName, len);
1029 							memcpy(function->responseName+len, "Response", sizeof("Response"));
1030 						}
1031 
1032 						if (tmpbinding->bindingType == BINDING_SOAP) {
1033 							output = get_node_ex(operation->children, "output", WSDL_NAMESPACE);
1034 							if (output != NULL) {
1035 								sdlSoapBindingFunctionPtr soapFunctionBinding = function->bindingAttributes;
1036 								wsdl_soap_binding_body(&ctx, output, wsdl_soap_namespace, &soapFunctionBinding->output, function->responseParameters);
1037 							}
1038 						}
1039 					}
1040 
1041 					paramOrder = get_attribute(portTypeOperation->properties, "parameterOrder");
1042 					if (paramOrder) {
1043 						/* FIXME: */
1044 					}
1045 
1046 					fault = portTypeOperation->children;
1047 					while (fault != NULL) {
1048 						if (node_is_equal_ex(fault, "fault", WSDL_NAMESPACE)) {
1049 							xmlAttrPtr message, name;
1050 							sdlFaultPtr f;
1051 
1052 							name = get_attribute(fault->properties, "name");
1053 							if (name == NULL) {
1054 								soap_error1(E_ERROR, "Parsing WSDL: Missing name for <fault> of '%s'", op_name->children->content);
1055 							}
1056 							message = get_attribute(fault->properties, "message");
1057 							if (message == NULL) {
1058 								soap_error1(E_ERROR, "Parsing WSDL: Missing name for <output> of '%s'", op_name->children->content);
1059 							}
1060 
1061 							f = emalloc(sizeof(sdlFault));
1062 							memset(f, 0, sizeof(sdlFault));
1063 
1064 							f->name = estrdup((char*)name->children->content);
1065 							f->details = wsdl_message(&ctx, message->children->content);
1066 							if (f->details == NULL || zend_hash_num_elements(f->details) > 1) {
1067 								soap_error1(E_ERROR, "Parsing WSDL: The fault message '%s' must have a single part", message->children->content);
1068 							}
1069 
1070 							if (tmpbinding->bindingType == BINDING_SOAP) {
1071 								xmlNodePtr soap_fault = get_node_with_attribute_ex(operation->children, "fault", WSDL_NAMESPACE, "name", f->name, NULL);
1072 								if (soap_fault != NULL) {
1073 									xmlNodePtr trav = soap_fault->children;
1074 									while (trav != NULL) {
1075 										if (node_is_equal_ex(trav, "fault", wsdl_soap_namespace)) {
1076 											xmlAttrPtr tmp;
1077 										  sdlSoapBindingFunctionFaultPtr binding;
1078 
1079 											binding = f->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunctionFault));
1080 											memset(f->bindingAttributes, 0, sizeof(sdlSoapBindingFunctionFault));
1081 
1082 											tmp = get_attribute(trav->properties, "use");
1083 											if (tmp && !strncmp((char*)tmp->children->content, "encoded", sizeof("encoded"))) {
1084 												binding->use = SOAP_ENCODED;
1085 											} else {
1086 												binding->use = SOAP_LITERAL;
1087 											}
1088 
1089 											tmp = get_attribute(trav->properties, "namespace");
1090 											if (tmp) {
1091 												binding->ns = estrdup((char*)tmp->children->content);
1092 											}
1093 
1094 											if (binding->use == SOAP_ENCODED) {
1095 												tmp = get_attribute(trav->properties, "encodingStyle");
1096 												if (tmp) {
1097 													if (strncmp((char*)tmp->children->content, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) {
1098 														binding->encodingStyle = SOAP_ENCODING_1_1;
1099 													} else if (strncmp((char*)tmp->children->content, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) {
1100 														binding->encodingStyle = SOAP_ENCODING_1_2;
1101 													} else {
1102 														soap_error1(E_ERROR, "Parsing WSDL: Unknown encodingStyle '%s'", tmp->children->content);
1103 													}
1104 												} else {
1105 													soap_error0(E_ERROR, "Parsing WSDL: Unspecified encodingStyle");
1106 												}
1107 											}
1108 										} else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
1109 											soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
1110 										}
1111 										trav = trav->next;
1112 									}
1113 								}
1114 							}
1115 							if (function->faults == NULL) {
1116 								function->faults = emalloc(sizeof(HashTable));
1117 								zend_hash_init(function->faults, 0, NULL, delete_fault, 0);
1118 							}
1119 							if (zend_hash_str_add_ptr(function->faults, f->name, strlen(f->name), f) == NULL) {
1120 								soap_error2(E_ERROR, "Parsing WSDL: <fault> with name '%s' already defined in '%s'", f->name, op_name->children->content);
1121 							}
1122 						}
1123 						fault = fault->next;
1124 					}
1125 
1126 					function->binding = tmpbinding;
1127 
1128 					{
1129 						char *tmp = estrdup(function->functionName);
1130 						int  len = strlen(tmp);
1131 
1132 						if (zend_hash_str_add_ptr(&ctx.sdl->functions, php_strtolower(tmp, len), len, function) == NULL) {
1133 							zend_hash_next_index_insert_ptr(&ctx.sdl->functions, function);
1134 						}
1135 						efree(tmp);
1136 						if (function->requestName != NULL && strcmp(function->requestName,function->functionName) != 0) {
1137 							if (ctx.sdl->requests == NULL) {
1138 								ctx.sdl->requests = emalloc(sizeof(HashTable));
1139 								zend_hash_init(ctx.sdl->requests, 0, NULL, NULL, 0);
1140 							}
1141 							tmp = estrdup(function->requestName);
1142 							len = strlen(tmp);
1143 							zend_hash_str_add_ptr(ctx.sdl->requests, php_strtolower(tmp, len), len, function);
1144 							efree(tmp);
1145 						}
1146 					}
1147 					trav2 = trav2->next;
1148 				}
1149 
1150 				if (!ctx.sdl->bindings) {
1151 					ctx.sdl->bindings = emalloc(sizeof(HashTable));
1152 					zend_hash_init(ctx.sdl->bindings, 0, NULL, delete_binding, 0);
1153 				}
1154 
1155 				if (!zend_hash_str_add_ptr(ctx.sdl->bindings, tmpbinding->name, strlen(tmpbinding->name), tmpbinding)) {
1156 					zend_hash_next_index_insert_ptr(ctx.sdl->bindings, tmpbinding);
1157 				}
1158 				trav= trav->next;
1159 			}
1160 
1161 			zend_hash_move_forward(&ctx.services);
1162 		}
1163 	} else {
1164 		soap_error0(E_ERROR, "Parsing WSDL: Couldn't bind to service");
1165 	}
1166 
1167 	if (ctx.sdl->bindings == NULL || ctx.sdl->bindings->nNumOfElements == 0) {
1168 		soap_error0(E_ERROR, "Parsing WSDL: Could not find any usable binding services in WSDL.");
1169 	}
1170 
1171 	} zend_catch {
1172 		/* Avoid persistent memory leak. */
1173 		zend_hash_destroy(&ctx.docs);
1174 		zend_bailout();
1175 	} zend_end_try();
1176 
1177 	zend_hash_destroy(&ctx.messages);
1178 	zend_hash_destroy(&ctx.bindings);
1179 	zend_hash_destroy(&ctx.portTypes);
1180 	zend_hash_destroy(&ctx.services);
1181 	zend_hash_destroy(&ctx.docs);
1182 
1183 	return ctx.sdl;
1184 }
1185 
1186 #define WSDL_CACHE_VERSION 0x10
1187 
1188 #define WSDL_CACHE_GET(ret,type,buf)   memcpy(&ret,*buf,sizeof(type)); *buf += sizeof(type);
1189 #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;
1190 #define WSDL_CACHE_GET_1(ret,type,buf) ret = (type)(**buf); (*buf)++;
1191 #define WSDL_CACHE_GET_N(ret,n,buf)    memcpy(ret,*buf,n); *buf += n;
1192 #define WSDL_CACHE_SKIP(n,buf)         *buf += n;
1193 
1194 #define WSDL_CACHE_PUT_INT(val,buf)    smart_str_appendc(buf,(char)(val & 0xff)); \
1195                                        smart_str_appendc(buf,(char)((val >> 8) & 0xff)); \
1196                                        smart_str_appendc(buf,(char)((val >> 16) & 0xff)); \
1197                                        smart_str_appendc(buf,(char)((val >> 24) & 0xff));
1198 #define WSDL_CACHE_PUT_1(val,buf)      smart_str_appendc(buf,val);
1199 #define WSDL_CACHE_PUT_N(val,n,buf)    smart_str_appendl(buf,(char*)val,n);
1200 
1201 #define WSDL_NO_STRING_MARKER 0x7fffffff
1202 
sdl_deserialize_string(char **in)1203 static char* sdl_deserialize_string(char **in)
1204 {
1205 	char *s;
1206 	int len;
1207 
1208 	WSDL_CACHE_GET_INT(len, in);
1209 	if (len == WSDL_NO_STRING_MARKER) {
1210 		return NULL;
1211 	} else {
1212 		s = emalloc(len+1);
1213 		WSDL_CACHE_GET_N(s, len, in);
1214 		s[len] = '\0';
1215 		return s;
1216 	}
1217 }
1218 
sdl_deserialize_key(HashTable* ht, void* data, char **in)1219 static void sdl_deserialize_key(HashTable* ht, void* data, char **in)
1220 {
1221 	int len;
1222 
1223 	WSDL_CACHE_GET_INT(len, in);
1224 	if (len == WSDL_NO_STRING_MARKER) {
1225 		zend_hash_next_index_insert_ptr(ht, data);
1226 	} else {
1227 		zend_hash_str_add_ptr(ht, *in, len, data);
1228 		WSDL_CACHE_SKIP(len, in);
1229 	}
1230 }
1231 
sdl_deserialize_attribute(sdlAttributePtr attr, encodePtr *encoders, char **in)1232 static void sdl_deserialize_attribute(sdlAttributePtr attr, encodePtr *encoders, char **in)
1233 {
1234 	int i;
1235 
1236 	attr->name = sdl_deserialize_string(in);
1237 	attr->namens = sdl_deserialize_string(in);
1238 	attr->ref = sdl_deserialize_string(in);
1239 	attr->def = sdl_deserialize_string(in);
1240 	attr->fixed = sdl_deserialize_string(in);
1241 	WSDL_CACHE_GET_1(attr->form, sdlForm, in);
1242 	WSDL_CACHE_GET_1(attr->use, sdlUse, in);
1243 	WSDL_CACHE_GET_INT(i, in);
1244 	attr->encode = encoders[i];
1245 	WSDL_CACHE_GET_INT(i, in);
1246 	if (i > 0) {
1247 		attr->extraAttributes = emalloc(sizeof(HashTable));
1248 		zend_hash_init(attr->extraAttributes, i, NULL, delete_extra_attribute, 0);
1249 		while (i > 0) {
1250 			sdlExtraAttributePtr x = emalloc(sizeof(sdlExtraAttribute));
1251 			sdl_deserialize_key(attr->extraAttributes, x, in);
1252 			x->ns = sdl_deserialize_string(in);
1253 			x->val = sdl_deserialize_string(in);
1254 			--i;
1255 		}
1256 	}
1257 }
1258 
sdl_deserialize_resriction_int(char **in)1259 static sdlRestrictionIntPtr sdl_deserialize_resriction_int(char **in)
1260 {
1261 	if (**in == 1) {
1262 		sdlRestrictionIntPtr x = emalloc(sizeof(sdlRestrictionInt));
1263 		WSDL_CACHE_SKIP(1, in);
1264 		WSDL_CACHE_GET_INT(x->value, in);
1265 		WSDL_CACHE_GET_1(x->fixed, char, in);
1266 		return x;
1267 	} else {
1268 		WSDL_CACHE_SKIP(1, in);
1269 		return NULL;
1270 	}
1271 }
1272 
sdl_deserialize_resriction_char(char **in)1273 static sdlRestrictionCharPtr sdl_deserialize_resriction_char(char **in)
1274 {
1275 	if (**in == 1) {
1276 		sdlRestrictionCharPtr x = emalloc(sizeof(sdlRestrictionChar));
1277 		WSDL_CACHE_SKIP(1, in);
1278 		x->value = sdl_deserialize_string(in);
1279 		WSDL_CACHE_GET_1(x->fixed, char, in);
1280 		return x;
1281 	} else {
1282 		WSDL_CACHE_SKIP(1, in);
1283 		return NULL;
1284 	}
1285 }
1286 
sdl_deserialize_model(sdlTypePtr *types, sdlTypePtr *elements, char **in)1287 static sdlContentModelPtr sdl_deserialize_model(sdlTypePtr *types, sdlTypePtr *elements, char **in)
1288 {
1289 	int i;
1290 	sdlContentModelPtr model = emalloc(sizeof(sdlContentModel));
1291 
1292 	WSDL_CACHE_GET_1(model->kind, sdlContentKind, in);
1293 	WSDL_CACHE_GET_INT(model->min_occurs, in);
1294 	WSDL_CACHE_GET_INT(model->max_occurs, in);
1295 	switch (model->kind) {
1296 		case XSD_CONTENT_ELEMENT:
1297 			WSDL_CACHE_GET_INT(i, in);
1298 			model->u.element = elements[i];
1299 			break;
1300 		case XSD_CONTENT_SEQUENCE:
1301 		case XSD_CONTENT_ALL:
1302 		case XSD_CONTENT_CHOICE:
1303 			WSDL_CACHE_GET_INT(i, in);
1304 			model->u.content = emalloc(sizeof(HashTable));
1305 			zend_hash_init(model->u.content, i, NULL, delete_model, 0);
1306 			while (i > 0) {
1307 				sdlContentModelPtr x = sdl_deserialize_model(types, elements, in);
1308 				zend_hash_next_index_insert_ptr(model->u.content, x);
1309 				i--;
1310 			}
1311 			break;
1312 		case XSD_CONTENT_GROUP_REF:
1313 			model->u.group_ref = sdl_deserialize_string(in);
1314 			break;
1315 		case XSD_CONTENT_GROUP:
1316 			WSDL_CACHE_GET_INT(i, in);
1317 			model->u.group = types[i];
1318 			break;
1319 		default:
1320 			break;
1321 	}
1322 	return model;
1323 }
1324 
sdl_deserialize_type(sdlTypePtr type, sdlTypePtr *types, encodePtr *encoders, char **in)1325 static void sdl_deserialize_type(sdlTypePtr type, sdlTypePtr *types, encodePtr *encoders, char **in)
1326 {
1327 	int i;
1328 	sdlTypePtr *elements = NULL;
1329 
1330 	WSDL_CACHE_GET_1(type->kind, sdlTypeKind, in);
1331 	type->name = sdl_deserialize_string(in);
1332 	type->namens = sdl_deserialize_string(in);
1333 	type->def = sdl_deserialize_string(in);
1334 	type->fixed = sdl_deserialize_string(in);
1335 	type->ref = sdl_deserialize_string(in);
1336 	WSDL_CACHE_GET_1(type->nillable, char, in);
1337 	WSDL_CACHE_GET_1(type->form, sdlForm, in);
1338 
1339 	WSDL_CACHE_GET_INT(i, in);
1340 	type->encode = encoders[i];
1341 
1342 	if (**in == 1) {
1343 		WSDL_CACHE_SKIP(1, in);
1344 		type->restrictions = emalloc(sizeof(sdlRestrictions));
1345 		/*memset(type->restrictions, 0, sizeof(sdlRestrictions));*/
1346 		type->restrictions->minExclusive = sdl_deserialize_resriction_int(in);
1347 		type->restrictions->minInclusive = sdl_deserialize_resriction_int(in);
1348 		type->restrictions->maxExclusive = sdl_deserialize_resriction_int(in);
1349 		type->restrictions->maxInclusive = sdl_deserialize_resriction_int(in);
1350 		type->restrictions->totalDigits = sdl_deserialize_resriction_int(in);
1351 		type->restrictions->fractionDigits = sdl_deserialize_resriction_int(in);
1352 		type->restrictions->length = sdl_deserialize_resriction_int(in);
1353 		type->restrictions->minLength = sdl_deserialize_resriction_int(in);
1354 		type->restrictions->maxLength = sdl_deserialize_resriction_int(in);
1355 		type->restrictions->whiteSpace = sdl_deserialize_resriction_char(in);
1356 		type->restrictions->pattern = sdl_deserialize_resriction_char(in);
1357 		WSDL_CACHE_GET_INT(i, in);
1358 		if (i > 0) {
1359 			type->restrictions->enumeration = emalloc(sizeof(HashTable));
1360 			zend_hash_init(type->restrictions->enumeration, i, NULL, delete_restriction_var_char, 0);
1361 			while (i > 0) {
1362 				sdlRestrictionCharPtr x = sdl_deserialize_resriction_char(in);
1363 				sdl_deserialize_key(type->restrictions->enumeration, x, in);
1364 				--i;
1365 			}
1366 		} else {
1367 			type->restrictions->enumeration = NULL;
1368 		}
1369 	} else {
1370 		WSDL_CACHE_SKIP(1, in);
1371 	}
1372 
1373 	WSDL_CACHE_GET_INT(i, in);
1374 	if (i > 0) {
1375 		elements = safe_emalloc((i+1), sizeof(sdlTypePtr), 0);
1376 		elements[0] = NULL;
1377 		type->elements = emalloc(sizeof(HashTable));
1378 		zend_hash_init(type->elements, i, NULL, delete_type, 0);
1379 		while (i > 0) {
1380 			sdlTypePtr t = emalloc(sizeof(sdlType));
1381 			memset(t, 0, sizeof(sdlType));
1382 			sdl_deserialize_key(type->elements, t, in);
1383 			sdl_deserialize_type(t, types, encoders, in);
1384 			elements[i] = t;
1385 			--i;
1386 		}
1387 	}
1388 
1389 	WSDL_CACHE_GET_INT(i, in);
1390 	if (i > 0) {
1391 		type->attributes = emalloc(sizeof(HashTable));
1392 		zend_hash_init(type->attributes, i, NULL, delete_attribute, 0);
1393 		while (i > 0) {
1394 			sdlAttributePtr attr = emalloc(sizeof(sdlAttribute));
1395 			memset(attr, 0, sizeof(sdlAttribute));
1396 			sdl_deserialize_key(type->attributes, attr, in);
1397 			sdl_deserialize_attribute(attr, encoders, in);
1398 			--i;
1399 		}
1400 	}
1401 
1402 	if (**in != 0) {
1403 		WSDL_CACHE_SKIP(1, in);
1404 		type->model = sdl_deserialize_model(types, elements, in);
1405 	} else {
1406 		WSDL_CACHE_SKIP(1, in);
1407 	}
1408 	if (elements != NULL) {
1409 		efree(elements);
1410 	}
1411 }
1412 
sdl_deserialize_encoder(encodePtr enc, sdlTypePtr *types, char **in)1413 static void sdl_deserialize_encoder(encodePtr enc, sdlTypePtr *types, char **in)
1414 {
1415 	int i;
1416 
1417 	WSDL_CACHE_GET_INT(enc->details.type, in);
1418 	enc->details.type_str = sdl_deserialize_string(in);
1419 	enc->details.ns = sdl_deserialize_string(in);
1420 	WSDL_CACHE_GET_INT(i, in);
1421 	enc->details.sdl_type = types[i];
1422 	enc->to_xml = sdl_guess_convert_xml;
1423 	enc->to_zval = sdl_guess_convert_zval;
1424 
1425 	if (enc->details.sdl_type == NULL) {
1426 		int ns_len = strlen(enc->details.ns);
1427 		int type_len = strlen(enc->details.type_str);
1428 
1429 		if (((ns_len == sizeof(SOAP_1_1_ENC_NAMESPACE)-1 &&
1430 		      memcmp(enc->details.ns, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)-1) == 0) ||
1431 		     (ns_len == sizeof(SOAP_1_2_ENC_NAMESPACE)-1 &&
1432 		      memcmp(enc->details.ns, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)-1) == 0))) {
1433 			char *enc_nscat;
1434 			int enc_ns_len;
1435 			int enc_len;
1436 			encodePtr real_enc;
1437 
1438 			enc_ns_len = sizeof(XSD_NAMESPACE)-1;
1439 			enc_len = enc_ns_len + type_len + 1;
1440 			enc_nscat = emalloc(enc_len + 1);
1441 			memcpy(enc_nscat, XSD_NAMESPACE, sizeof(XSD_NAMESPACE)-1);
1442 			enc_nscat[enc_ns_len] = ':';
1443 			memcpy(enc_nscat+enc_ns_len+1, enc->details.type_str, type_len);
1444 			enc_nscat[enc_len] = '\0';
1445 
1446 			real_enc = get_encoder_ex(NULL, enc_nscat, enc_len);
1447 			efree(enc_nscat);
1448 			if (real_enc) {
1449 				enc->to_zval = real_enc->to_zval;
1450 				enc->to_xml = real_enc->to_xml;
1451 			}
1452 		}
1453 	}
1454 }
1455 
sdl_deserialize_soap_body(sdlSoapBindingFunctionBodyPtr body, encodePtr *encoders, sdlTypePtr *types, char **in)1456 static void sdl_deserialize_soap_body(sdlSoapBindingFunctionBodyPtr body, encodePtr *encoders, sdlTypePtr *types, char **in)
1457 {
1458 	int i, j, n;
1459 
1460 	WSDL_CACHE_GET_1(body->use, sdlEncodingUse, in);
1461 	if (body->use == SOAP_ENCODED) {
1462 		WSDL_CACHE_GET_1(body->encodingStyle, sdlRpcEncodingStyle, in);
1463 	} else {
1464 		body->encodingStyle = SOAP_ENCODING_DEFAULT;
1465 	}
1466 	body->ns = sdl_deserialize_string(in);
1467 	WSDL_CACHE_GET_INT(i, in);
1468 	if (i > 0) {
1469 		body->headers = emalloc(sizeof(HashTable));
1470 		zend_hash_init(body->headers, i, NULL, delete_header, 0);
1471 		while (i > 0) {
1472 			sdlSoapBindingFunctionHeaderPtr tmp = emalloc(sizeof(sdlSoapBindingFunctionHeader));
1473 			memset(tmp, 0, sizeof(sdlSoapBindingFunctionHeader));
1474 			sdl_deserialize_key(body->headers, tmp, in);
1475 			WSDL_CACHE_GET_1(tmp->use, sdlEncodingUse, in);
1476 			if (tmp->use == SOAP_ENCODED) {
1477 				WSDL_CACHE_GET_1(tmp->encodingStyle, sdlRpcEncodingStyle, in);
1478 			} else {
1479 				tmp->encodingStyle = SOAP_ENCODING_DEFAULT;
1480 			}
1481 			tmp->name = sdl_deserialize_string(in);
1482 			tmp->ns = sdl_deserialize_string(in);
1483 			WSDL_CACHE_GET_INT(n, in);
1484 			tmp->encode = encoders[n];
1485 			WSDL_CACHE_GET_INT(n, in);
1486 			tmp->element = types[n];
1487 			--i;
1488 			WSDL_CACHE_GET_INT(j, in);
1489 			if (j > 0) {
1490 				tmp->headerfaults = emalloc(sizeof(HashTable));
1491 				zend_hash_init(tmp->headerfaults, i, NULL, delete_header, 0);
1492 				while (j > 0) {
1493 					sdlSoapBindingFunctionHeaderPtr tmp2 = emalloc(sizeof(sdlSoapBindingFunctionHeader));
1494 					memset(tmp2, 0, sizeof(sdlSoapBindingFunctionHeader));
1495 					sdl_deserialize_key(tmp->headerfaults, tmp2, in);
1496 					WSDL_CACHE_GET_1(tmp2->use, sdlEncodingUse, in);
1497 					if (tmp2->use == SOAP_ENCODED) {
1498 						WSDL_CACHE_GET_1(tmp2->encodingStyle, sdlRpcEncodingStyle, in);
1499 					} else {
1500 						tmp2->encodingStyle = SOAP_ENCODING_DEFAULT;
1501 					}
1502 					tmp2->name = sdl_deserialize_string(in);
1503 					tmp2->ns = sdl_deserialize_string(in);
1504 					WSDL_CACHE_GET_INT(n, in);
1505 					tmp2->encode = encoders[n];
1506 					WSDL_CACHE_GET_INT(n, in);
1507 					tmp2->element = types[n];
1508 					--j;
1509 				}
1510 			}
1511 		}
1512 	}
1513 }
1514 
sdl_deserialize_parameters(encodePtr *encoders, sdlTypePtr *types, char **in)1515 static HashTable* sdl_deserialize_parameters(encodePtr *encoders, sdlTypePtr *types, char **in)
1516 {
1517 	int i, n;
1518 	HashTable *ht;
1519 
1520 	WSDL_CACHE_GET_INT(i, in);
1521 	if (i == 0) {return NULL;}
1522 	ht = emalloc(sizeof(HashTable));
1523 	zend_hash_init(ht, i, NULL, delete_parameter, 0);
1524 	while (i > 0) {
1525 		sdlParamPtr param = emalloc(sizeof(sdlParam));
1526 		sdl_deserialize_key(ht, param, in);
1527 		param->paramName = sdl_deserialize_string(in);
1528 		WSDL_CACHE_GET_INT(param->order, in);
1529 		WSDL_CACHE_GET_INT(n, in);
1530 		param->encode = encoders[n];
1531 		WSDL_CACHE_GET_INT(n, in);
1532 		param->element = types[n];
1533 		--i;
1534 	}
1535 	return ht;
1536 }
1537 
get_sdl_from_cache(const char *fn, const char *uri, time_t t, time_t *cached)1538 static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t, time_t *cached)
1539 {
1540 	sdlPtr sdl;
1541 	time_t old_t;
1542 	int  i, num_groups, num_types, num_elements, num_encoders, num_bindings, num_func;
1543 	sdlFunctionPtr *functions = NULL;
1544 	sdlBindingPtr *bindings;
1545 	sdlTypePtr *types;
1546 	encodePtr *encoders;
1547 	const encode *enc;
1548 
1549 	int f;
1550 	struct stat st;
1551 	char *in, *buf;
1552 
1553 	f = open(fn, O_RDONLY|O_BINARY);
1554 	if (f < 0) {
1555 		return NULL;
1556 	}
1557 	if (fstat(f, &st) != 0) {
1558 		close(f);
1559 		return NULL;
1560 	}
1561 	buf = in = emalloc(st.st_size);
1562 	if (read(f, in, st.st_size) != st.st_size) {
1563 		close(f);
1564 		efree(in);
1565 		return NULL;
1566 	}
1567 	close(f);
1568 
1569 	if (strncmp(in,"wsdl",4) != 0 || in[4] != WSDL_CACHE_VERSION || in[5] != '\0') {
1570 		unlink(fn);
1571 		efree(buf);
1572 		return NULL;
1573 	}
1574 	in += 6;
1575 
1576 	WSDL_CACHE_GET(old_t, time_t, &in);
1577 	if (old_t < t) {
1578 		unlink(fn);
1579 		efree(buf);
1580 		return NULL;
1581 	}
1582 	*cached = old_t;
1583 
1584 	WSDL_CACHE_GET_INT(i, &in);
1585 	if (i == 0 && strncmp(in, uri, i) != 0) {
1586 		unlink(fn);
1587 		efree(buf);
1588 		return NULL;
1589 	}
1590 	WSDL_CACHE_SKIP(i, &in);
1591 
1592 	sdl = emalloc(sizeof(*sdl));
1593 	memset(sdl, 0, sizeof(*sdl));
1594 
1595 	sdl->source = sdl_deserialize_string(&in);
1596 	sdl->target_ns = sdl_deserialize_string(&in);
1597 
1598 	WSDL_CACHE_GET_INT(num_groups, &in);
1599 	WSDL_CACHE_GET_INT(num_types, &in);
1600 	WSDL_CACHE_GET_INT(num_elements, &in);
1601 	WSDL_CACHE_GET_INT(num_encoders, &in);
1602 
1603 	i = num_groups+num_types+num_elements;
1604 	types = safe_emalloc((i+1), sizeof(sdlTypePtr), 0);
1605 	types[0] = NULL;
1606 	while (i > 0) {
1607 		types[i] = emalloc(sizeof(sdlType));
1608 		memset(types[i], 0, sizeof(sdlType));
1609 		i--;
1610 	}
1611 
1612 	i = num_encoders;
1613 	enc = defaultEncoding;
1614 	while (enc->details.type != END_KNOWN_TYPES) {
1615 		i++; enc++;
1616 	}
1617 	encoders = safe_emalloc((i+1), sizeof(encodePtr), 0);
1618 	i = num_encoders;
1619 	encoders[0] = NULL;
1620 	while (i > 0) {
1621 		encoders[i] = emalloc(sizeof(encode));
1622 		memset(encoders[i], 0, sizeof(encode));
1623 		i--;
1624 	}
1625 	i = num_encoders;
1626 	enc = defaultEncoding;
1627 	while (enc->details.type != END_KNOWN_TYPES) {
1628 		encoders[++i] = (encodePtr)enc++;
1629 	}
1630 
1631 	i = 1;
1632 	if (num_groups > 0) {
1633 		sdl->groups = emalloc(sizeof(HashTable));
1634 		zend_hash_init(sdl->groups, num_groups, NULL, delete_type, 0);
1635 		while (i < num_groups+1) {
1636 			sdl_deserialize_key(sdl->groups, types[i], &in);
1637 			sdl_deserialize_type(types[i], types, encoders, &in);
1638 			i++;
1639 		}
1640 	}
1641 
1642 	if (num_types > 0) {
1643 		sdl->types = emalloc(sizeof(HashTable));
1644 		zend_hash_init(sdl->types, num_types, NULL, delete_type, 0);
1645 		while (i < num_groups+num_types+1) {
1646 			sdl_deserialize_key(sdl->types, types[i], &in);
1647 			sdl_deserialize_type(types[i], types, encoders, &in);
1648 			i++;
1649 		}
1650 	}
1651 
1652 	if (num_elements > 0) {
1653 		sdl->elements = emalloc(sizeof(HashTable));
1654 		zend_hash_init(sdl->elements, num_elements, NULL, delete_type, 0);
1655 		while (i < num_groups+num_types+num_elements+1) {
1656 			sdl_deserialize_key(sdl->elements, types[i], &in);
1657 			sdl_deserialize_type(types[i], types, encoders, &in);
1658 			i++;
1659 		}
1660 	}
1661 
1662 	i = 1;
1663 	if (num_encoders > 0) {
1664 		sdl->encoders = emalloc(sizeof(HashTable));
1665 		zend_hash_init(sdl->encoders, num_encoders, NULL, delete_encoder, 0);
1666 		while (i < num_encoders+1) {
1667 			sdl_deserialize_key(sdl->encoders, encoders[i], &in);
1668 			sdl_deserialize_encoder(encoders[i], types, &in);
1669 			i++;
1670 		}
1671 	}
1672 
1673 	/* deserialize bindings */
1674 	WSDL_CACHE_GET_INT(num_bindings, &in);
1675 	bindings = safe_emalloc(num_bindings, sizeof(sdlBindingPtr), 0);
1676 	if (num_bindings > 0) {
1677 		sdl->bindings = emalloc(sizeof(HashTable));
1678 		zend_hash_init(sdl->bindings, num_bindings, NULL, delete_binding, 0);
1679 		for (i = 0; i < num_bindings; i++) {
1680 			sdlBindingPtr binding = emalloc(sizeof(sdlBinding));
1681 			memset(binding, 0, sizeof(sdlBinding));
1682 			sdl_deserialize_key(sdl->bindings, binding, &in);
1683 			binding->name = sdl_deserialize_string(&in);
1684 			binding->location = sdl_deserialize_string(&in);
1685 			WSDL_CACHE_GET_1(binding->bindingType,sdlBindingType,&in);
1686 			if (binding->bindingType == BINDING_SOAP && *in != 0) {
1687 			  sdlSoapBindingPtr soap_binding = binding->bindingAttributes = emalloc(sizeof(sdlSoapBinding));
1688 				WSDL_CACHE_GET_1(soap_binding->style,sdlEncodingStyle,&in);
1689 				WSDL_CACHE_GET_1(soap_binding->transport,sdlTransport,&in);
1690 			} else {
1691 				WSDL_CACHE_SKIP(1,&in);
1692 			}
1693 			bindings[i] = binding;
1694 		}
1695 	}
1696 
1697 	/* deserialize functions */
1698 	WSDL_CACHE_GET_INT(num_func, &in);
1699 	zend_hash_init(&sdl->functions, num_func, NULL, delete_function, 0);
1700 	if (num_func > 0) {
1701 		functions = safe_emalloc(num_func, sizeof(sdlFunctionPtr), 0);
1702 		for (i = 0; i < num_func; i++) {
1703 			int binding_num, num_faults;
1704 			sdlFunctionPtr func = emalloc(sizeof(sdlFunction));
1705 			sdl_deserialize_key(&sdl->functions, func, &in);
1706 			func->functionName = sdl_deserialize_string(&in);
1707 			func->requestName = sdl_deserialize_string(&in);
1708 			func->responseName = sdl_deserialize_string(&in);
1709 
1710 			WSDL_CACHE_GET_INT(binding_num, &in);
1711 			if (binding_num == 0) {
1712 				func->binding = NULL;
1713 			} else {
1714 				func->binding = bindings[binding_num-1];
1715 			}
1716 			if (func->binding && func->binding->bindingType == BINDING_SOAP && *in != 0) {
1717 				sdlSoapBindingFunctionPtr binding = func->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunction));
1718 				memset(binding, 0, sizeof(sdlSoapBindingFunction));
1719 				WSDL_CACHE_GET_1(binding->style,sdlEncodingStyle,&in);
1720 				binding->soapAction = sdl_deserialize_string(&in);
1721 				sdl_deserialize_soap_body(&binding->input, encoders, types, &in);
1722 				sdl_deserialize_soap_body(&binding->output, encoders, types, &in);
1723 			} else {
1724 				WSDL_CACHE_SKIP(1, &in);
1725 				func->bindingAttributes = NULL;
1726 			}
1727 
1728 			func->requestParameters = sdl_deserialize_parameters(encoders, types, &in);
1729 			func->responseParameters = sdl_deserialize_parameters(encoders, types, &in);
1730 
1731 			WSDL_CACHE_GET_INT(num_faults, &in);
1732 			if (num_faults > 0) {
1733 			  int j;
1734 
1735 				func->faults = emalloc(sizeof(HashTable));
1736 				zend_hash_init(func->faults, num_faults, NULL, delete_fault, 0);
1737 
1738 				for (j = 0; j < num_faults; j++) {
1739 					sdlFaultPtr fault = emalloc(sizeof(sdlFault));
1740 
1741 					sdl_deserialize_key(func->faults, fault, &in);
1742 					fault->name =sdl_deserialize_string(&in);
1743 					fault->details =sdl_deserialize_parameters(encoders, types, &in);
1744 					if (*in != 0) {
1745 						sdlSoapBindingFunctionFaultPtr binding = fault->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunctionFault));
1746 						memset(binding, 0, sizeof(sdlSoapBindingFunctionFault));
1747 						WSDL_CACHE_GET_1(binding->use,sdlEncodingUse,&in);
1748 						if (binding->use == SOAP_ENCODED) {
1749 							WSDL_CACHE_GET_1(binding->encodingStyle, sdlRpcEncodingStyle, &in);
1750 						} else {
1751 							binding->encodingStyle = SOAP_ENCODING_DEFAULT;
1752 						}
1753 						binding->ns = sdl_deserialize_string(&in);
1754 					} else {
1755 						WSDL_CACHE_SKIP(1, &in);
1756 						fault->bindingAttributes = NULL;
1757 					}
1758 				}
1759 			} else {
1760 				func->faults = NULL;
1761 			}
1762 			functions[i] = func;
1763 		}
1764 	}
1765 
1766 	/* deserialize requests */
1767 	WSDL_CACHE_GET_INT(i, &in);
1768 	if (i > 0) {
1769 		sdl->requests = emalloc(sizeof(HashTable));
1770 		zend_hash_init(sdl->requests, i, NULL, NULL, 0);
1771 		while (i > 0) {
1772 			int function_num;
1773 
1774 			WSDL_CACHE_GET_INT(function_num, &in);
1775 			sdl_deserialize_key(sdl->requests, functions[function_num-1], &in);
1776 			i--;
1777 		}
1778 	}
1779 
1780 	if (functions) {
1781 		efree(functions);
1782 	}
1783 	efree(bindings);
1784 	efree(encoders);
1785 	efree(types);
1786 	efree(buf);
1787 	return sdl;
1788 }
1789 
sdl_serialize_string(const char *str, smart_str *out)1790 static void sdl_serialize_string(const char *str, smart_str *out)
1791 {
1792 	if (str) {
1793 		int i = strlen(str);
1794 		WSDL_CACHE_PUT_INT(i, out);
1795 		if (i > 0) {
1796 			WSDL_CACHE_PUT_N(str, i, out);
1797 		}
1798 	} else {
1799 		WSDL_CACHE_PUT_INT(WSDL_NO_STRING_MARKER, out);
1800 	}
1801 }
1802 
1803 // TODO: refactor it
sdl_serialize_key(zend_string *key, smart_str *out)1804 static void sdl_serialize_key(zend_string *key, smart_str *out)
1805 {
1806 	if (key) {
1807 		WSDL_CACHE_PUT_INT(ZSTR_LEN(key), out);
1808 		WSDL_CACHE_PUT_N(ZSTR_VAL(key), ZSTR_LEN(key), out);
1809 	} else {
1810 		WSDL_CACHE_PUT_INT(WSDL_NO_STRING_MARKER, out);
1811 	}
1812 }
1813 
sdl_serialize_encoder_ref(encodePtr enc, HashTable *tmp_encoders, smart_str *out)1814 static void sdl_serialize_encoder_ref(encodePtr enc, HashTable *tmp_encoders, smart_str *out) {
1815 	if (enc) {
1816 		zval *encoder_num;
1817 		if ((encoder_num = zend_hash_str_find(tmp_encoders, (char*)&enc, sizeof(enc))) != 0) {
1818 			WSDL_CACHE_PUT_INT(Z_LVAL_P(encoder_num), out);
1819 		} else {
1820 			WSDL_CACHE_PUT_INT(0, out);
1821 		}
1822 	} else {
1823 		WSDL_CACHE_PUT_INT(0, out);
1824 	}
1825 }
1826 
sdl_serialize_type_ref(sdlTypePtr type, HashTable *tmp_types, smart_str *out)1827 static void sdl_serialize_type_ref(sdlTypePtr type, HashTable *tmp_types, smart_str *out) {
1828 	if (type) {
1829 		zval *type_num;
1830 		if ((type_num = zend_hash_str_find(tmp_types, (char*)&type, sizeof(type))) != NULL) {
1831 			WSDL_CACHE_PUT_INT(Z_LVAL_P(type_num), out);
1832 		} else {
1833 			WSDL_CACHE_PUT_INT(0, out);
1834 		}
1835 	} else {
1836 		WSDL_CACHE_PUT_INT(0,out);
1837 	}
1838 }
1839 
sdl_serialize_attribute(sdlAttributePtr attr, HashTable *tmp_encoders, smart_str *out)1840 static void sdl_serialize_attribute(sdlAttributePtr attr, HashTable *tmp_encoders, smart_str *out)
1841 {
1842 	int i;
1843 
1844 	sdl_serialize_string(attr->name, out);
1845 	sdl_serialize_string(attr->namens, out);
1846 	sdl_serialize_string(attr->ref, out);
1847 	sdl_serialize_string(attr->def, out);
1848 	sdl_serialize_string(attr->fixed, out);
1849 	WSDL_CACHE_PUT_1(attr->form, out);
1850 	WSDL_CACHE_PUT_1(attr->use, out);
1851 	sdl_serialize_encoder_ref(attr->encode, tmp_encoders, out);
1852 	if (attr->extraAttributes) {
1853 		i = zend_hash_num_elements(attr->extraAttributes);
1854 	} else {
1855 		i = 0;
1856 	}
1857 	WSDL_CACHE_PUT_INT(i, out);
1858 	if (i > 0) {
1859 		sdlExtraAttributePtr tmp;
1860 		zend_string *key;
1861 
1862 		ZEND_HASH_FOREACH_STR_KEY_PTR(attr->extraAttributes, key, tmp) {
1863 			sdl_serialize_key(key, out);
1864 			sdl_serialize_string(tmp->ns, out);
1865 			sdl_serialize_string(tmp->val, out);
1866 		} ZEND_HASH_FOREACH_END();
1867 	}
1868 }
1869 
sdl_serialize_model(sdlContentModelPtr model, HashTable *tmp_types, HashTable *tmp_elements, smart_str *out)1870 static void sdl_serialize_model(sdlContentModelPtr model, HashTable *tmp_types, HashTable *tmp_elements, smart_str *out)
1871 {
1872 	WSDL_CACHE_PUT_1(model->kind, out);
1873 	WSDL_CACHE_PUT_INT(model->min_occurs, out);
1874 	WSDL_CACHE_PUT_INT(model->max_occurs, out);
1875 	switch (model->kind) {
1876 		case XSD_CONTENT_ELEMENT:
1877 			sdl_serialize_type_ref(model->u.element, tmp_elements, out);
1878 			break;
1879 		case XSD_CONTENT_SEQUENCE:
1880 		case XSD_CONTENT_ALL:
1881 		case XSD_CONTENT_CHOICE: {
1882 				sdlContentModelPtr tmp;
1883 				int i = zend_hash_num_elements(model->u.content);
1884 
1885 				WSDL_CACHE_PUT_INT(i, out);
1886 				ZEND_HASH_FOREACH_PTR(model->u.content, tmp) {
1887 					sdl_serialize_model(tmp, tmp_types, tmp_elements, out);
1888 				} ZEND_HASH_FOREACH_END();
1889 			}
1890 			break;
1891 		case XSD_CONTENT_GROUP_REF:
1892 			sdl_serialize_string(model->u.group_ref,out);
1893 			break;
1894 		case XSD_CONTENT_GROUP:
1895 			sdl_serialize_type_ref(model->u.group, tmp_types, out);
1896 			break;
1897 		default:
1898 			break;
1899 	}
1900 }
1901 
sdl_serialize_resriction_int(sdlRestrictionIntPtr x, smart_str *out)1902 static void sdl_serialize_resriction_int(sdlRestrictionIntPtr x, smart_str *out)
1903 {
1904 	if (x) {
1905 		WSDL_CACHE_PUT_1(1, out);
1906 		WSDL_CACHE_PUT_INT(x->value, out);
1907 		WSDL_CACHE_PUT_1(x->fixed, out);
1908 	} else {
1909 		WSDL_CACHE_PUT_1(0, out);
1910 	}
1911 }
1912 
sdl_serialize_resriction_char(sdlRestrictionCharPtr x, smart_str *out)1913 static void sdl_serialize_resriction_char(sdlRestrictionCharPtr x, smart_str *out)
1914 {
1915 	if (x) {
1916 		WSDL_CACHE_PUT_1(1, out);
1917 		sdl_serialize_string(x->value, out);
1918 		WSDL_CACHE_PUT_1(x->fixed, out);
1919 	} else {
1920 		WSDL_CACHE_PUT_1(0, out);
1921 	}
1922 }
1923 
sdl_serialize_type(sdlTypePtr type, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)1924 static void sdl_serialize_type(sdlTypePtr type, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
1925 {
1926 	int i;
1927 	HashTable *tmp_elements = NULL;
1928 
1929 	WSDL_CACHE_PUT_1(type->kind, out);
1930 	sdl_serialize_string(type->name, out);
1931 	sdl_serialize_string(type->namens, out);
1932 	sdl_serialize_string(type->def, out);
1933 	sdl_serialize_string(type->fixed, out);
1934 	sdl_serialize_string(type->ref, out);
1935 	WSDL_CACHE_PUT_1(type->nillable, out);
1936 	WSDL_CACHE_PUT_1(type->form, out);
1937 	sdl_serialize_encoder_ref(type->encode, tmp_encoders, out);
1938 
1939 	if (type->restrictions) {
1940 		WSDL_CACHE_PUT_1(1, out);
1941 		sdl_serialize_resriction_int(type->restrictions->minExclusive,out);
1942 		sdl_serialize_resriction_int(type->restrictions->minInclusive,out);
1943 		sdl_serialize_resriction_int(type->restrictions->maxExclusive,out);
1944 		sdl_serialize_resriction_int(type->restrictions->maxInclusive,out);
1945 		sdl_serialize_resriction_int(type->restrictions->totalDigits,out);
1946 		sdl_serialize_resriction_int(type->restrictions->fractionDigits,out);
1947 		sdl_serialize_resriction_int(type->restrictions->length,out);
1948 		sdl_serialize_resriction_int(type->restrictions->minLength,out);
1949 		sdl_serialize_resriction_int(type->restrictions->maxLength,out);
1950 		sdl_serialize_resriction_char(type->restrictions->whiteSpace,out);
1951 		sdl_serialize_resriction_char(type->restrictions->pattern,out);
1952 		if (type->restrictions->enumeration) {
1953 			i = zend_hash_num_elements(type->restrictions->enumeration);
1954 		} else {
1955 			i = 0;
1956 		}
1957 		WSDL_CACHE_PUT_INT(i, out);
1958 		if (i > 0) {
1959 			sdlRestrictionCharPtr tmp;
1960 			zend_string *key;
1961 
1962 			ZEND_HASH_FOREACH_STR_KEY_PTR(type->restrictions->enumeration, key, tmp) {
1963 				sdl_serialize_resriction_char(tmp, out);
1964 				sdl_serialize_key(key, out);
1965 			} ZEND_HASH_FOREACH_END();
1966 		}
1967 	} else {
1968 		WSDL_CACHE_PUT_1(0, out);
1969 	}
1970 	if (type->elements) {
1971 		i = zend_hash_num_elements(type->elements);
1972 	} else {
1973 		i = 0;
1974 	}
1975 	WSDL_CACHE_PUT_INT(i, out);
1976 	if (i > 0) {
1977 		sdlTypePtr tmp;
1978 		zend_string *key;
1979 		zval zv;
1980 
1981 		tmp_elements = emalloc(sizeof(HashTable));
1982 		zend_hash_init(tmp_elements, i, NULL, NULL, 0);
1983 
1984 		ZEND_HASH_FOREACH_STR_KEY_PTR(type->elements, key, tmp) {
1985 			sdl_serialize_key(key, out);
1986 			sdl_serialize_type(tmp, tmp_encoders, tmp_types, out);
1987 			ZVAL_LONG(&zv, i);
1988 			zend_hash_str_add(tmp_elements, (char*)&tmp, sizeof(tmp), &zv);
1989 			i--;
1990 		} ZEND_HASH_FOREACH_END();
1991 	}
1992 
1993 	if (type->attributes) {
1994 		i = zend_hash_num_elements(type->attributes);
1995 	} else {
1996 		i = 0;
1997 	}
1998 	WSDL_CACHE_PUT_INT(i, out);
1999 	if (i > 0) {
2000 		sdlAttributePtr tmp;
2001 		zend_string *key;
2002 
2003 		ZEND_HASH_FOREACH_STR_KEY_PTR(type->attributes, key, tmp) {
2004 			sdl_serialize_key(key, out);
2005 			sdl_serialize_attribute(tmp, tmp_encoders, out);
2006 		} ZEND_HASH_FOREACH_END();
2007 	}
2008 	if (type->model) {
2009 		WSDL_CACHE_PUT_1(1, out);
2010 		sdl_serialize_model(type->model, tmp_types, tmp_elements, out);
2011 	} else {
2012 		WSDL_CACHE_PUT_1(0, out);
2013 	}
2014 	if (tmp_elements != NULL) {
2015 		zend_hash_destroy(tmp_elements);
2016 		efree(tmp_elements);
2017 	}
2018 }
2019 
sdl_serialize_encoder(encodePtr enc, HashTable *tmp_types, smart_str *out)2020 static void sdl_serialize_encoder(encodePtr enc, HashTable *tmp_types, smart_str *out)
2021 {
2022 	WSDL_CACHE_PUT_INT(enc->details.type, out);
2023 	sdl_serialize_string(enc->details.type_str, out);
2024 	sdl_serialize_string(enc->details.ns, out);
2025 	sdl_serialize_type_ref(enc->details.sdl_type, tmp_types, out);
2026 }
2027 
sdl_serialize_parameters(HashTable *ht, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)2028 static void sdl_serialize_parameters(HashTable *ht, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
2029 {
2030 	int i;
2031 
2032 	if (ht) {
2033 		i = zend_hash_num_elements(ht);
2034 	} else {
2035 		i = 0;
2036 	}
2037 	WSDL_CACHE_PUT_INT(i, out);
2038 	if (i > 0) {
2039 		sdlParamPtr tmp;
2040 		zend_string *key;
2041 
2042 		ZEND_HASH_FOREACH_STR_KEY_PTR(ht, key, tmp) {
2043 			sdl_serialize_key(key, out);
2044 			sdl_serialize_string(tmp->paramName, out);
2045 			WSDL_CACHE_PUT_INT(tmp->order, out);
2046 			sdl_serialize_encoder_ref(tmp->encode, tmp_encoders, out);
2047 			sdl_serialize_type_ref(tmp->element, tmp_types, out);
2048 		} ZEND_HASH_FOREACH_END();
2049 	}
2050 }
2051 
sdl_serialize_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)2052 static void sdl_serialize_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
2053 {
2054 	int i, j;
2055 
2056 	WSDL_CACHE_PUT_1(body->use, out);
2057 	if (body->use == SOAP_ENCODED) {
2058 		WSDL_CACHE_PUT_1(body->encodingStyle, out);
2059 	}
2060 	sdl_serialize_string(body->ns, out);
2061 	if (body->headers) {
2062 		i = zend_hash_num_elements(body->headers);
2063 	} else {
2064 		i = 0;
2065 	}
2066 	WSDL_CACHE_PUT_INT(i, out);
2067 	if (i > 0) {
2068 		sdlSoapBindingFunctionHeaderPtr tmp;
2069 		zend_string *key;
2070 
2071 		ZEND_HASH_FOREACH_STR_KEY_PTR(body->headers, key, tmp) {
2072 			sdl_serialize_key(key, out);
2073 			WSDL_CACHE_PUT_1(tmp->use, out);
2074 			if (tmp->use == SOAP_ENCODED) {
2075 				WSDL_CACHE_PUT_1(tmp->encodingStyle, out);
2076 			}
2077 			sdl_serialize_string(tmp->name, out);
2078 			sdl_serialize_string(tmp->ns, out);
2079 			sdl_serialize_encoder_ref(tmp->encode, tmp_encoders, out);
2080 			sdl_serialize_type_ref(tmp->element, tmp_types, out);
2081 			if (tmp->headerfaults) {
2082 				j = zend_hash_num_elements(tmp->headerfaults);
2083 			} else {
2084 				j = 0;
2085 			}
2086 			WSDL_CACHE_PUT_INT(j, out);
2087 			if (j > 0) {
2088 				sdlSoapBindingFunctionHeaderPtr tmp2;
2089 				zend_string *key;
2090 
2091 				ZEND_HASH_FOREACH_STR_KEY_PTR(body->headers, key, tmp2) {
2092 					sdl_serialize_key(key, out);
2093 					WSDL_CACHE_PUT_1(tmp2->use, out);
2094 					if (tmp2->use == SOAP_ENCODED) {
2095 						WSDL_CACHE_PUT_1(tmp2->encodingStyle, out);
2096 					}
2097 					sdl_serialize_string(tmp2->name, out);
2098 					sdl_serialize_string(tmp2->ns, out);
2099 					sdl_serialize_encoder_ref(tmp2->encode, tmp_encoders, out);
2100 					sdl_serialize_type_ref(tmp2->element, tmp_types, out);
2101 				} ZEND_HASH_FOREACH_END();
2102 			}
2103 		} ZEND_HASH_FOREACH_END();
2104 	}
2105 }
2106 
add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr sdl)2107 static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr sdl)
2108 {
2109 	smart_str buf = {0};
2110 	smart_str *out = &buf;
2111 	int i;
2112 	int type_num = 1;
2113 	int encoder_num = 1;
2114 	int f;
2115 	const encode *enc;
2116 	HashTable tmp_types;
2117 	HashTable tmp_encoders;
2118 	HashTable tmp_bindings;
2119 	HashTable tmp_functions;
2120 
2121 #ifdef ZEND_WIN32
2122 	f = open(fn,O_CREAT|O_WRONLY|O_EXCL|O_BINARY,S_IREAD|S_IWRITE);
2123 #else
2124 	f = open(fn,O_CREAT|O_WRONLY|O_EXCL|O_BINARY,S_IREAD|S_IWRITE);
2125 #endif
2126 	if (f < 0) {return;}
2127 
2128 	zend_hash_init(&tmp_types, 0, NULL, NULL, 0);
2129 	zend_hash_init(&tmp_encoders, 0, NULL, NULL, 0);
2130 	zend_hash_init(&tmp_bindings, 0, NULL, NULL, 0);
2131 	zend_hash_init(&tmp_functions, 0, NULL, NULL, 0);
2132 
2133 	WSDL_CACHE_PUT_N("wsdl", 4, out);
2134 	WSDL_CACHE_PUT_1(WSDL_CACHE_VERSION,out);
2135 	WSDL_CACHE_PUT_1(0,out);
2136 	WSDL_CACHE_PUT_N(&t, sizeof(t), out);
2137 
2138 	sdl_serialize_string(uri, out);
2139 	sdl_serialize_string(sdl->source, out);
2140 	sdl_serialize_string(sdl->target_ns, out);
2141 
2142 	if (sdl->groups) {
2143 		i = zend_hash_num_elements(sdl->groups);
2144 	} else {
2145 		i = 0;
2146 	}
2147 	WSDL_CACHE_PUT_INT(i, out);
2148 	if (i > 0) {
2149 		sdlTypePtr tmp;
2150 		zval zv;
2151 
2152 		ZEND_HASH_FOREACH_PTR(sdl->groups, tmp) {
2153 			ZVAL_LONG(&zv, type_num);
2154 			zend_hash_str_add(&tmp_types, (char*)&tmp, sizeof(tmp), &zv);
2155 			++type_num;
2156 		} ZEND_HASH_FOREACH_END();
2157 	}
2158 
2159 	if (sdl->types) {
2160 		i = zend_hash_num_elements(sdl->types);
2161 	} else {
2162 		i = 0;
2163 	}
2164 	WSDL_CACHE_PUT_INT(i, out);
2165 	if (i > 0) {
2166 		sdlTypePtr tmp;
2167 		zval zv;
2168 
2169 		ZEND_HASH_FOREACH_PTR(sdl->types, tmp) {
2170 			ZVAL_LONG(&zv,  type_num);
2171 			zend_hash_str_add(&tmp_types, (char*)&tmp, sizeof(tmp), &zv);
2172 			++type_num;
2173 		} ZEND_HASH_FOREACH_END();
2174 	}
2175 
2176 	if (sdl->elements) {
2177 		i = zend_hash_num_elements(sdl->elements);
2178 	} else {
2179 		i = 0;
2180 	}
2181 	WSDL_CACHE_PUT_INT(i, out);
2182 	if (i > 0) {
2183 		sdlTypePtr tmp;
2184 		zval zv;
2185 
2186 		ZEND_HASH_FOREACH_PTR(sdl->elements, tmp) {
2187 			ZVAL_LONG(&zv, type_num);
2188 			zend_hash_str_add(&tmp_types, (char*)&tmp, sizeof(tmp), &zv);
2189 			++type_num;
2190 		} ZEND_HASH_FOREACH_END();
2191 	}
2192 
2193 	if (sdl->encoders) {
2194 		i = zend_hash_num_elements(sdl->encoders);
2195 	} else {
2196 		i = 0;
2197 	}
2198 	WSDL_CACHE_PUT_INT(i, out);
2199 	if (i > 0) {
2200 		encodePtr tmp;
2201 		zval zv;
2202 
2203 		ZEND_HASH_FOREACH_PTR(sdl->encoders, tmp) {
2204 			ZVAL_LONG(&zv, encoder_num);
2205 			zend_hash_str_add(&tmp_encoders, (char*)&tmp, sizeof(tmp), &zv);
2206 			++encoder_num;
2207 		} ZEND_HASH_FOREACH_END();
2208 	}
2209 	enc = defaultEncoding;
2210 	while (enc->details.type != END_KNOWN_TYPES) {
2211 		zval zv;
2212 
2213 		ZVAL_LONG(&zv, encoder_num);
2214 		zend_hash_str_add(&tmp_encoders, (char*)&enc, sizeof(encodePtr), &zv);
2215 		enc++;
2216 		++encoder_num;
2217 	}
2218 
2219 	if (sdl->groups) {
2220 		sdlTypePtr tmp;
2221 		zend_string *key;
2222 
2223 		ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->groups, key, tmp) {
2224 			sdl_serialize_key(key, out);
2225 			sdl_serialize_type(tmp, &tmp_encoders, &tmp_types, out);
2226 		} ZEND_HASH_FOREACH_END();
2227 	}
2228 
2229 	if (sdl->types) {
2230 		sdlTypePtr tmp;
2231 		zend_string *key;
2232 
2233 		ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->types, key, tmp) {
2234 			sdl_serialize_key(key, out);
2235 			sdl_serialize_type(tmp, &tmp_encoders, &tmp_types, out);
2236 		} ZEND_HASH_FOREACH_END();
2237 	}
2238 
2239 	if (sdl->elements) {
2240 		sdlTypePtr tmp;
2241 		zend_string *key;
2242 
2243 		ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->elements, key, tmp) {
2244 			sdl_serialize_key(key, out);
2245 			sdl_serialize_type(tmp, &tmp_encoders, &tmp_types, out);
2246 		} ZEND_HASH_FOREACH_END();
2247 	}
2248 
2249 	if (sdl->encoders) {
2250 		encodePtr tmp;
2251 		zend_string *key;
2252 
2253 		ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->encoders, key, tmp) {
2254 			sdl_serialize_key(key, out);
2255 			sdl_serialize_encoder(tmp, &tmp_types, out);
2256 		} ZEND_HASH_FOREACH_END();
2257 	}
2258 
2259 	/* serialize bindings */
2260 	if (sdl->bindings) {
2261 		i = zend_hash_num_elements(sdl->bindings);
2262 	} else {
2263 		i = 0;
2264 	}
2265 	WSDL_CACHE_PUT_INT(i, out);
2266 	if (i > 0) {
2267 		sdlBindingPtr tmp;
2268 		int binding_num = 1;
2269 		zval zv;
2270 		zend_string *key;
2271 
2272 		ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->bindings, key, tmp) {
2273 			sdl_serialize_key(key, out);
2274 			sdl_serialize_string(tmp->name, out);
2275 			sdl_serialize_string(tmp->location, out);
2276 			WSDL_CACHE_PUT_1(tmp->bindingType,out);
2277 			if (tmp->bindingType == BINDING_SOAP && tmp->bindingAttributes != NULL) {
2278 				sdlSoapBindingPtr binding = (sdlSoapBindingPtr)tmp->bindingAttributes;
2279 				WSDL_CACHE_PUT_1(binding->style, out);
2280 				WSDL_CACHE_PUT_1(binding->transport, out);
2281 			} else {
2282 				WSDL_CACHE_PUT_1(0,out);
2283 			}
2284 
2285 			ZVAL_LONG(&zv, binding_num);
2286 			zend_hash_str_add(&tmp_bindings, (char*)&tmp, sizeof(tmp), &zv);
2287 			binding_num++;
2288 		} ZEND_HASH_FOREACH_END();
2289 	}
2290 
2291 	/* serialize functions */
2292 	i = zend_hash_num_elements(&sdl->functions);
2293 	WSDL_CACHE_PUT_INT(i, out);
2294 	if (i > 0) {
2295 		sdlFunctionPtr tmp;
2296 		zval *binding_num, zv;
2297 		int function_num = 1;
2298 		zend_string *key;
2299 
2300 		ZEND_HASH_FOREACH_STR_KEY_PTR(&sdl->functions, key, tmp) {
2301 			sdl_serialize_key(key, out);
2302 			sdl_serialize_string(tmp->functionName, out);
2303 			sdl_serialize_string(tmp->requestName, out);
2304 			sdl_serialize_string(tmp->responseName, out);
2305 
2306 			if (tmp->binding) {
2307 				binding_num = zend_hash_str_find(&tmp_bindings,(char*)&tmp->binding, sizeof(tmp->binding));
2308 				if (binding_num) {
2309 					WSDL_CACHE_PUT_INT(Z_LVAL_P(binding_num), out);
2310 					if (Z_LVAL_P(binding_num) >= 0) {
2311 						if (tmp->binding->bindingType == BINDING_SOAP && tmp->bindingAttributes != NULL) {
2312 							sdlSoapBindingFunctionPtr binding = (sdlSoapBindingFunctionPtr)tmp->bindingAttributes;
2313 							WSDL_CACHE_PUT_1(binding->style, out);
2314 							sdl_serialize_string(binding->soapAction, out);
2315 							sdl_serialize_soap_body(&binding->input, &tmp_encoders, &tmp_types, out);
2316 							sdl_serialize_soap_body(&binding->output, &tmp_encoders, &tmp_types, out);
2317 						} else {
2318 							WSDL_CACHE_PUT_1(0,out);
2319 						}
2320 					}
2321 				}
2322 			}
2323 			sdl_serialize_parameters(tmp->requestParameters, &tmp_encoders, &tmp_types, out);
2324 			sdl_serialize_parameters(tmp->responseParameters, &tmp_encoders, &tmp_types, out);
2325 
2326 			if (tmp->faults) {
2327 				sdlFaultPtr fault;
2328 				zend_string *key;
2329 
2330 				WSDL_CACHE_PUT_INT(zend_hash_num_elements(tmp->faults), out);
2331 
2332 				ZEND_HASH_FOREACH_STR_KEY_PTR(tmp->faults, key, fault) {
2333 					sdl_serialize_key(key, out);
2334 					sdl_serialize_string(fault->name, out);
2335 					sdl_serialize_parameters(fault->details, &tmp_encoders, &tmp_types, out);
2336 					if (tmp->binding->bindingType == BINDING_SOAP && fault->bindingAttributes != NULL) {
2337 						sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
2338 						WSDL_CACHE_PUT_1(binding->use, out);
2339 						if (binding->use == SOAP_ENCODED) {
2340 							WSDL_CACHE_PUT_1(binding->encodingStyle, out);
2341 						}
2342 						sdl_serialize_string(binding->ns, out);
2343 					} else {
2344 						WSDL_CACHE_PUT_1(0, out);
2345 					}
2346 				} ZEND_HASH_FOREACH_END();
2347 			} else {
2348 				WSDL_CACHE_PUT_INT(0, out);
2349 			}
2350 
2351 			ZVAL_LONG(&zv, function_num);
2352 			zend_hash_str_add(&tmp_functions, (char*)&tmp, sizeof(tmp), &zv);
2353 			function_num++;
2354 		} ZEND_HASH_FOREACH_END();
2355 	}
2356 
2357 	/* serialize requests */
2358 	if (sdl->requests) {
2359 		i = zend_hash_num_elements(sdl->requests);
2360 	} else {
2361 		i = 0;
2362 	}
2363 	WSDL_CACHE_PUT_INT(i, out);
2364 	if (i > 0) {
2365 		sdlFunctionPtr tmp;
2366 		zval *function_num;
2367 		zend_string *key;
2368 
2369 		ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->requests, key, tmp) {
2370 			function_num = zend_hash_str_find(&tmp_functions, (char*)&tmp, sizeof(tmp));
2371 			WSDL_CACHE_PUT_INT(Z_LVAL_P(function_num), out);
2372 			sdl_serialize_key(key, out);
2373 		} ZEND_HASH_FOREACH_END();
2374 	}
2375 
2376 	php_ignore_value(write(f, ZSTR_VAL(buf.s), ZSTR_LEN(buf.s)));
2377 	close(f);
2378 	smart_str_free(&buf);
2379 	zend_hash_destroy(&tmp_functions);
2380 	zend_hash_destroy(&tmp_bindings);
2381 	zend_hash_destroy(&tmp_encoders);
2382 	zend_hash_destroy(&tmp_types);
2383 }
2384 
2385 
make_persistent_restriction_int(void *data)2386 static void make_persistent_restriction_int(void *data)
2387 {
2388 	sdlRestrictionIntPtr *rest = (sdlRestrictionIntPtr *)data;
2389 	sdlRestrictionIntPtr prest = NULL;
2390 
2391 	prest = malloc(sizeof(sdlRestrictionInt));
2392 	*prest = **rest;
2393 	*rest = prest;
2394 }
2395 
2396 
make_persistent_restriction_char_int(sdlRestrictionCharPtr *rest)2397 static void make_persistent_restriction_char_int(sdlRestrictionCharPtr *rest)
2398 {
2399 	sdlRestrictionCharPtr prest = NULL;
2400 
2401 	prest = malloc(sizeof(sdlRestrictionChar));
2402 	memset(prest, 0, sizeof(sdlRestrictionChar));
2403 	prest->value = strdup((*rest)->value);
2404 	prest->fixed = (*rest)->fixed;
2405 	*rest = prest;
2406 }
2407 
2408 
make_persistent_sdl_type_ref(sdlTypePtr *type, HashTable *ptr_map, HashTable *bp_types)2409 static void make_persistent_sdl_type_ref(sdlTypePtr *type, HashTable *ptr_map, HashTable *bp_types)
2410 {
2411 	sdlTypePtr tmp;
2412 
2413 	if ((tmp = zend_hash_str_find_ptr(ptr_map, (char *)type, sizeof(sdlTypePtr))) != NULL) {
2414 		*type = tmp;
2415 	} else {
2416 		zend_hash_next_index_insert_ptr(bp_types, *type);
2417 	}
2418 }
2419 
2420 
make_persistent_sdl_encoder_ref(encodePtr *enc, HashTable *ptr_map, HashTable *bp_encoders)2421 static void make_persistent_sdl_encoder_ref(encodePtr *enc, HashTable *ptr_map, HashTable *bp_encoders)
2422 {
2423 	encodePtr tmp;
2424 
2425 	/* do not process defaultEncoding's here */
2426 	if ((*enc) >= defaultEncoding && (*enc) < defaultEncoding + numDefaultEncodings) {
2427 		return;
2428 	}
2429 
2430 	if ((tmp = zend_hash_str_find_ptr(ptr_map, (char *)enc, sizeof(encodePtr))) != NULL) {
2431 		*enc = tmp;
2432 	} else {
2433 		zend_hash_next_index_insert_ptr(bp_encoders, enc);
2434 	}
2435 }
2436 
2437 
make_persistent_sdl_function_headers(HashTable *headers, HashTable *ptr_map)2438 static HashTable* make_persistent_sdl_function_headers(HashTable *headers, HashTable *ptr_map)
2439 {
2440 	HashTable *pheaders;
2441 	sdlSoapBindingFunctionHeaderPtr tmp, pheader;
2442 	encodePtr penc;
2443 	sdlTypePtr ptype;
2444 	zend_string *key;
2445 
2446 	pheaders = malloc(sizeof(HashTable));
2447 	zend_hash_init(pheaders, zend_hash_num_elements(headers), NULL, delete_header_persistent, 1);
2448 
2449 	ZEND_HASH_FOREACH_STR_KEY_PTR(headers, key, tmp) {
2450 		pheader = malloc(sizeof(sdlSoapBindingFunctionHeader));
2451 		memset(pheader, 0, sizeof(sdlSoapBindingFunctionHeader));
2452 		*pheader = *tmp;
2453 
2454 		if (pheader->name) {
2455 			pheader->name = strdup(pheader->name);
2456 		}
2457 		if (pheader->ns) {
2458 			pheader->ns = strdup(pheader->ns);
2459 		}
2460 
2461 		if (pheader->encode && pheader->encode->details.sdl_type) {
2462 			if ((penc = zend_hash_str_find_ptr(ptr_map, (char*)&pheader->encode, sizeof(encodePtr))) == NULL) {
2463 				assert(0);
2464 			}
2465 			pheader->encode = penc;
2466 		}
2467 		if (pheader->element) {
2468 			if ((ptype = zend_hash_str_find_ptr(ptr_map, (char*)&pheader->element, sizeof(sdlTypePtr))) == NULL) {
2469 				assert(0);
2470 			}
2471 			pheader->element = ptype;
2472 		}
2473 
2474 		if (pheader->headerfaults) {
2475 			pheader->headerfaults = make_persistent_sdl_function_headers(pheader->headerfaults, ptr_map);
2476 		}
2477 
2478 		if (key) {
2479 			/* We have to duplicate key emalloc->malloc */
2480 			zend_hash_str_add_ptr(pheaders, ZSTR_VAL(key), ZSTR_LEN(key), pheader);
2481 		} else {
2482 			zend_hash_next_index_insert_ptr(pheaders, pheader);
2483 		}
2484 	} ZEND_HASH_FOREACH_END();
2485 
2486 	return pheaders;
2487 }
2488 
2489 
make_persistent_sdl_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTable *ptr_map)2490 static void make_persistent_sdl_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTable *ptr_map)
2491 {
2492 	if (body->ns) {
2493 		body->ns = strdup(body->ns);
2494 	}
2495 
2496 	if (body->headers) {
2497 		body->headers = make_persistent_sdl_function_headers(body->headers, ptr_map);
2498 	}
2499 }
2500 
2501 
make_persistent_sdl_parameters(HashTable *params, HashTable *ptr_map)2502 static HashTable* make_persistent_sdl_parameters(HashTable *params, HashTable *ptr_map)
2503 {
2504 	HashTable *pparams;
2505 	sdlParamPtr tmp, pparam;
2506 	sdlTypePtr ptype;
2507 	encodePtr penc;
2508 	zend_string *key;
2509 
2510 	pparams = malloc(sizeof(HashTable));
2511 	zend_hash_init(pparams, zend_hash_num_elements(params), NULL, delete_parameter_persistent, 1);
2512 
2513 	ZEND_HASH_FOREACH_STR_KEY_PTR(params, key, tmp) {
2514 		pparam = malloc(sizeof(sdlParam));
2515 		memset(pparam, 0, sizeof(sdlParam));
2516 		*pparam = *tmp;
2517 
2518 		if (pparam->paramName) {
2519 			pparam->paramName = strdup(pparam->paramName);
2520 		}
2521 
2522 		if (pparam->encode && pparam->encode->details.sdl_type) {
2523 			if ((penc = zend_hash_str_find_ptr(ptr_map, (char*)&pparam->encode, sizeof(encodePtr))) == NULL) {
2524 				assert(0);
2525 			}
2526 			pparam->encode = penc;
2527 		}
2528 		if (pparam->element) {
2529 			if ((ptype = zend_hash_str_find_ptr(ptr_map, (char*)&pparam->element, sizeof(sdlTypePtr))) == NULL) {
2530 				assert(0);
2531 			}
2532 			pparam->element = ptype;
2533 		}
2534 
2535 		if (key) {
2536 			/* We have to duplicate key emalloc->malloc */
2537 			zend_hash_str_add_ptr(pparams, ZSTR_VAL(key), ZSTR_LEN(key), pparam);
2538 		} else {
2539 			zend_hash_next_index_insert_ptr(pparams, pparam);
2540 		}
2541 	} ZEND_HASH_FOREACH_END();
2542 
2543 	return pparams;
2544 }
2545 
make_persistent_sdl_function_faults(sdlFunctionPtr func, HashTable *faults, HashTable *ptr_map)2546 static HashTable* make_persistent_sdl_function_faults(sdlFunctionPtr func, HashTable *faults, HashTable *ptr_map)
2547 {
2548 	HashTable *pfaults;
2549 	sdlFaultPtr tmp, pfault;
2550 	zend_string *key;
2551 
2552 	pfaults = malloc(sizeof(HashTable));
2553 	zend_hash_init(pfaults, zend_hash_num_elements(faults), NULL, delete_fault_persistent, 1);
2554 
2555 	ZEND_HASH_FOREACH_STR_KEY_PTR(faults, key, tmp) {
2556 		pfault = malloc(sizeof(sdlFault));
2557 		memset(pfault, 0, sizeof(sdlFault));
2558 		*pfault = *tmp;
2559 
2560 		if (pfault->name) {
2561 			pfault->name = strdup(pfault->name);
2562 		}
2563 		if (pfault->details) {
2564 			pfault->details = make_persistent_sdl_parameters(pfault->details, ptr_map);
2565 		}
2566 
2567 		if (func->binding->bindingType == BINDING_SOAP && pfault->bindingAttributes) {
2568 			sdlSoapBindingFunctionFaultPtr soap_binding;
2569 
2570 		   	soap_binding = malloc(sizeof(sdlSoapBindingFunctionFault));
2571 			memset(soap_binding, 0, sizeof(sdlSoapBindingFunctionFault));
2572 			*soap_binding = *(sdlSoapBindingFunctionFaultPtr)pfault->bindingAttributes;
2573 			if (soap_binding->ns) {
2574 				soap_binding->ns = strdup(soap_binding->ns);
2575 			}
2576 			pfault->bindingAttributes = soap_binding;
2577 		}
2578 
2579 		if (key) {
2580 			/* We have to duplicate key emalloc->malloc */
2581 			zend_hash_str_add_ptr(pfaults, ZSTR_VAL(key), ZSTR_LEN(key), pfault);
2582 		} else {
2583 			zend_hash_next_index_insert_ptr(pfaults, pfault);
2584 		}
2585 
2586 	} ZEND_HASH_FOREACH_END();
2587 
2588 	return pfaults;
2589 }
2590 
2591 
make_persistent_sdl_attribute(sdlAttributePtr attr, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)2592 static sdlAttributePtr make_persistent_sdl_attribute(sdlAttributePtr attr, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2593 {
2594 	sdlAttributePtr pattr;
2595 	zend_string *key;
2596 
2597 	pattr = malloc(sizeof(sdlAttribute));
2598 	memset(pattr, 0, sizeof(sdlAttribute));
2599 
2600 	*pattr = *attr;
2601 
2602 	if (pattr->name) {
2603 		pattr->name = strdup(pattr->name);
2604 	}
2605 	if (pattr->namens) {
2606 		pattr->namens = strdup(pattr->namens);
2607 	}
2608 	if (pattr->ref) {
2609 		pattr->ref = strdup(pattr->ref);
2610 	}
2611 	if (pattr->def) {
2612 		pattr->def = strdup(pattr->def);
2613 	}
2614 	if (pattr->fixed) {
2615 		pattr->fixed = strdup(pattr->fixed);
2616 	}
2617 
2618 	/* we do not want to process defaultEncoding's here */
2619 	if (pattr->encode) {
2620 		make_persistent_sdl_encoder_ref(&pattr->encode, ptr_map, bp_encoders);
2621 	}
2622 
2623 	if (pattr->extraAttributes) {
2624 		sdlExtraAttributePtr tmp, pextra;
2625 
2626 		pattr->extraAttributes = malloc(sizeof(HashTable));
2627 		zend_hash_init(pattr->extraAttributes, zend_hash_num_elements(attr->extraAttributes), NULL, delete_extra_attribute_persistent, 1);
2628 
2629 		ZEND_HASH_FOREACH_STR_KEY_PTR(attr->extraAttributes, key, tmp) {
2630 			if (key) {
2631 				pextra = malloc(sizeof(sdlExtraAttribute));
2632 				memset(pextra, 0, sizeof(sdlExtraAttribute));
2633 
2634 				if (tmp->ns) {
2635 					pextra->ns = strdup(tmp->ns);
2636 				}
2637 				if (tmp->val) {
2638 					pextra->val = strdup(tmp->val);
2639 				}
2640 
2641 				/* We have to duplicate key emalloc->malloc */
2642 				zend_hash_str_add_ptr(pattr->extraAttributes, ZSTR_VAL(key), ZSTR_LEN(key), pextra);
2643 			}
2644 		} ZEND_HASH_FOREACH_END();
2645 	}
2646 
2647 	return pattr;
2648 }
2649 
2650 
make_persistent_sdl_model(sdlContentModelPtr model, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)2651 static sdlContentModelPtr make_persistent_sdl_model(sdlContentModelPtr model, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2652 {
2653 	sdlContentModelPtr pmodel;
2654 	sdlContentModelPtr tmp, pcontent;
2655 
2