xref: /PHP-7.0/ext/soap/php_schema.c (revision 478f119a)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 7                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2017 The PHP Group                                |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.txt                                  |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Authors: Brad Lafountain <rodif_bl@yahoo.com>                        |
16   |          Shane Caraveo <shane@caraveo.com>                           |
17   |          Dmitry Stogov <dmitry@zend.com>                             |
18   +----------------------------------------------------------------------+
19 */
20 /* $Id$ */
21 
22 #include "php_soap.h"
23 #include "libxml/uri.h"
24 
25 static int schema_simpleType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr simpleType, sdlTypePtr cur_type);
26 static int schema_complexType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr compType, sdlTypePtr cur_type);
27 static int schema_list(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr listType, sdlTypePtr cur_type);
28 static int schema_union(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr unionType, sdlTypePtr cur_type);
29 static int schema_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr simpCompType, sdlTypePtr cur_type);
30 static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr restType, sdlTypePtr cur_type, int simpleType);
31 static int schema_restriction_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr restType, sdlTypePtr cur_type);
32 static int schema_extension_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type);
33 static int schema_extension_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type);
34 static int schema_sequence(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr seqType, sdlTypePtr cur_type, sdlContentModelPtr model);
35 static int schema_all(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type, sdlContentModelPtr model);
36 static int schema_choice(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr choiceType, sdlTypePtr cur_type, sdlContentModelPtr model);
37 static int schema_group(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr groupType, sdlTypePtr cur_type, sdlContentModelPtr model);
38 static int schema_any(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type, sdlContentModelPtr model);
39 static int schema_element(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr element, sdlTypePtr cur_type, sdlContentModelPtr model);
40 static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdlTypePtr cur_type, sdlCtx *ctx);
41 static int schema_attributeGroup(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdlTypePtr cur_type, sdlCtx *ctx);
42 
43 static int schema_restriction_var_int(xmlNodePtr val, sdlRestrictionIntPtr *valptr);
44 
45 static int schema_restriction_var_char(xmlNodePtr val, sdlRestrictionCharPtr *valptr);
46 
47 static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type);
48 
create_encoder(sdlPtr sdl,sdlTypePtr cur_type,const xmlChar * ns,const xmlChar * type)49 static encodePtr create_encoder(sdlPtr sdl, sdlTypePtr cur_type, const xmlChar *ns, const xmlChar *type)
50 {
51 	smart_str nscat = {0};
52 	encodePtr enc, enc_ptr;
53 
54 	if (sdl->encoders == NULL) {
55 		sdl->encoders = emalloc(sizeof(HashTable));
56 		zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, 0);
57 	}
58 	smart_str_appends(&nscat, (char*)ns);
59 	smart_str_appendc(&nscat, ':');
60 	smart_str_appends(&nscat, (char*)type);
61 	smart_str_0(&nscat);
62 	if ((enc_ptr = zend_hash_find_ptr(sdl->encoders, nscat.s)) != NULL) {
63 		enc = enc_ptr;
64 		if (enc->details.ns) {
65 			efree(enc->details.ns);
66 		}
67 		if (enc->details.type_str) {
68 			efree(enc->details.type_str);
69 		}
70 	} else {
71 		enc_ptr = NULL;
72 		enc = emalloc(sizeof(encode));
73 	}
74 	memset(enc, 0, sizeof(encode));
75 
76 	enc->details.ns = estrdup((char*)ns);
77 	enc->details.type_str = estrdup((char*)type);
78 	enc->details.sdl_type = cur_type;
79 	enc->to_xml = sdl_guess_convert_xml;
80 	enc->to_zval = sdl_guess_convert_zval;
81 
82 	if (enc_ptr == NULL) {
83 		zend_hash_update_ptr(sdl->encoders, nscat.s, enc);
84 	}
85 	smart_str_free(&nscat);
86 	return enc;
87 }
88 
get_create_encoder(sdlPtr sdl,sdlTypePtr cur_type,const xmlChar * ns,const xmlChar * type)89 static encodePtr get_create_encoder(sdlPtr sdl, sdlTypePtr cur_type, const xmlChar *ns, const xmlChar *type)
90 {
91 	encodePtr enc = get_encoder(sdl, (char*)ns, (char*)type);
92 	if (enc == NULL) {
93 		enc = create_encoder(sdl, cur_type, ns, type);
94 	}
95 	return enc;
96 }
97 
schema_load_file(sdlCtx * ctx,xmlAttrPtr ns,xmlChar * location,xmlAttrPtr tns,int import)98 static void schema_load_file(sdlCtx *ctx, xmlAttrPtr ns, xmlChar *location, xmlAttrPtr tns, int import) {
99 	if (location != NULL &&
100 	    !zend_hash_str_exists(&ctx->docs, (char*)location, xmlStrlen(location))) {
101 		xmlDocPtr doc;
102 		xmlNodePtr schema;
103 		xmlAttrPtr new_tns;
104 
105 		sdl_set_uri_credentials(ctx, (char*)location);
106 		doc = soap_xmlParseFile((char*)location);
107 		sdl_restore_uri_credentials(ctx);
108 
109 		if (doc == NULL) {
110 			soap_error1(E_ERROR, "Parsing Schema: can't import schema from '%s'", location);
111 		}
112 		schema = get_node(doc->children, "schema");
113 		if (schema == NULL) {
114 			xmlFreeDoc(doc);
115 			soap_error1(E_ERROR, "Parsing Schema: can't import schema from '%s'", location);
116 		}
117 		new_tns = get_attribute(schema->properties, "targetNamespace");
118 		if (import) {
119 			if (ns != NULL && (new_tns == NULL || xmlStrcmp(ns->children->content, new_tns->children->content) != 0)) {
120 				xmlFreeDoc(doc);
121 				soap_error2(E_ERROR, "Parsing Schema: can't import schema from '%s', unexpected 'targetNamespace'='%s'", location, ns->children->content);
122 			}
123 			if (ns == NULL && new_tns != NULL) {
124 				xmlFreeDoc(doc);
125 				soap_error2(E_ERROR, "Parsing Schema: can't import schema from '%s', unexpected 'targetNamespace'='%s'", location, new_tns->children->content);
126 			}
127 		} else {
128 			new_tns = get_attribute(schema->properties, "targetNamespace");
129 			if (new_tns == NULL) {
130 				if (tns != NULL) {
131 					xmlSetProp(schema, BAD_CAST("targetNamespace"), tns->children->content);
132 				}
133 			} else if (tns != NULL && xmlStrcmp(tns->children->content, new_tns->children->content) != 0) {
134 				xmlFreeDoc(doc);
135 				soap_error1(E_ERROR, "Parsing Schema: can't include schema from '%s', different 'targetNamespace'", location);
136 			}
137 		}
138 		zend_hash_str_add_ptr(&ctx->docs, (char*)location, xmlStrlen(location), doc);
139 		load_schema(ctx, schema);
140 	}
141 }
142 
143 /*
144 2.6.1 xsi:type
145 2.6.2 xsi:nil
146 2.6.3 xsi:schemaLocation, xsi:noNamespaceSchemaLocation
147 */
148 
149 /*
150 <schema
151   attributeFormDefault = (qualified | unqualified) : unqualified
152   blockDefault = (#all | List of (extension | restriction | substitution))  : ''
153   elementFormDefault = (qualified | unqualified) : unqualified
154   finalDefault = (#all | List of (extension | restriction))  : ''
155   id = ID
156   targetNamespace = anyURI
157   version = token
158   xml:lang = language
159   {any attributes with non-schema namespace . . .}>
160   Content: ((include | import | redefine | annotation)*, (((simpleType | complexType | group | attributeGroup) | element | attribute | notation), annotation*)*)
161 </schema>
162 */
load_schema(sdlCtx * ctx,xmlNodePtr schema)163 int load_schema(sdlCtx *ctx, xmlNodePtr schema)
164 {
165 	xmlNodePtr trav;
166 	xmlAttrPtr tns;
167 
168 	if (!ctx->sdl->types) {
169 		ctx->sdl->types = emalloc(sizeof(HashTable));
170 		zend_hash_init(ctx->sdl->types, 0, NULL, delete_type, 0);
171 	}
172 	if (!ctx->attributes) {
173 		ctx->attributes = emalloc(sizeof(HashTable));
174 		zend_hash_init(ctx->attributes, 0, NULL, delete_attribute, 0);
175 	}
176 	if (!ctx->attributeGroups) {
177 		ctx->attributeGroups = emalloc(sizeof(HashTable));
178 		zend_hash_init(ctx->attributeGroups, 0, NULL, delete_type, 0);
179 	}
180 
181 	tns = get_attribute(schema->properties, "targetNamespace");
182 	if (tns == NULL) {
183 		tns = xmlSetProp(schema, BAD_CAST("targetNamespace"), BAD_CAST(""));
184 		xmlNewNs(schema, BAD_CAST(""), NULL);
185 	}
186 
187 	trav = schema->children;
188 	while (trav != NULL) {
189 		if (node_is_equal(trav,"include")) {
190 			xmlAttrPtr location;
191 
192 			location = get_attribute(trav->properties, "schemaLocation");
193 			if (location == NULL) {
194 				soap_error0(E_ERROR, "Parsing Schema: include has no 'schemaLocation' attribute");
195 			} else {
196 				xmlChar *uri;
197 				xmlChar *base = xmlNodeGetBase(trav->doc, trav);
198 
199 				if (base == NULL) {
200 			    uri = xmlBuildURI(location->children->content, trav->doc->URL);
201 				} else {
202 	    		uri = xmlBuildURI(location->children->content, base);
203 			    xmlFree(base);
204 				}
205 				schema_load_file(ctx, NULL, uri, tns, 0);
206 				xmlFree(uri);
207 			}
208 
209 		} else if (node_is_equal(trav,"redefine")) {
210 			xmlAttrPtr location;
211 
212 			location = get_attribute(trav->properties, "schemaLocation");
213 			if (location == NULL) {
214 				soap_error0(E_ERROR, "Parsing Schema: redefine has no 'schemaLocation' attribute");
215 			} else {
216 			  xmlChar *uri;
217 				xmlChar *base = xmlNodeGetBase(trav->doc, trav);
218 
219 				if (base == NULL) {
220 			    uri = xmlBuildURI(location->children->content, trav->doc->URL);
221 				} else {
222 	    		uri = xmlBuildURI(location->children->content, base);
223 			    xmlFree(base);
224 				}
225 				schema_load_file(ctx, NULL, uri, tns, 0);
226 				xmlFree(uri);
227 				/* TODO: <redefine> support */
228 			}
229 
230 		} else if (node_is_equal(trav,"import")) {
231 			xmlAttrPtr ns, location;
232 			xmlChar *uri = NULL;
233 
234 			ns = get_attribute(trav->properties, "namespace");
235 			location = get_attribute(trav->properties, "schemaLocation");
236 
237 			if (ns != NULL && tns != NULL && xmlStrcmp(ns->children->content, tns->children->content) == 0) {
238 				if (location) {
239 					soap_error1(E_ERROR, "Parsing Schema: can't import schema from '%s', namespace must not match the enclosing schema 'targetNamespace'", location->children->content);
240 				} else {
241 					soap_error0(E_ERROR, "Parsing Schema: can't import schema. Namespace must not match the enclosing schema 'targetNamespace'");
242 				}
243 			}
244 			if (location) {
245 				xmlChar *base = xmlNodeGetBase(trav->doc, trav);
246 
247 				if (base == NULL) {
248 			    uri = xmlBuildURI(location->children->content, trav->doc->URL);
249 				} else {
250 	    		uri = xmlBuildURI(location->children->content, base);
251 			    xmlFree(base);
252 				}
253 			}
254 			schema_load_file(ctx, ns, uri, tns, 1);
255 			if (uri != NULL) {xmlFree(uri);}
256 		} else if (node_is_equal(trav,"annotation")) {
257 			/* TODO: <annotation> support */
258 /* annotation cleanup
259 			xmlNodePtr tmp = trav;
260 			trav = trav->next;
261 			xmlUnlinkNode(tmp);
262 			xmlFreeNode(tmp);
263 			continue;
264 */
265 		} else {
266 			break;
267 		}
268 		trav = trav->next;
269 	}
270 
271 	while (trav != NULL) {
272 		if (node_is_equal(trav,"simpleType")) {
273 			schema_simpleType(ctx->sdl, tns, trav, NULL);
274 		} else if (node_is_equal(trav,"complexType")) {
275 			schema_complexType(ctx->sdl, tns, trav, NULL);
276 		} else if (node_is_equal(trav,"group")) {
277 			schema_group(ctx->sdl, tns, trav, NULL, NULL);
278 		} else if (node_is_equal(trav,"attributeGroup")) {
279 			schema_attributeGroup(ctx->sdl, tns, trav, NULL, ctx);
280 		} else if (node_is_equal(trav,"element")) {
281 			schema_element(ctx->sdl, tns, trav, NULL, NULL);
282 		} else if (node_is_equal(trav,"attribute")) {
283 			schema_attribute(ctx->sdl, tns, trav, NULL, ctx);
284 		} else if (node_is_equal(trav,"notation")) {
285 			/* TODO: <notation> support */
286 		} else if (node_is_equal(trav,"annotation")) {
287 			/* TODO: <annotation> support */
288 		} else {
289 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in schema", trav->name);
290 		}
291 		trav = trav->next;
292 	}
293 	return TRUE;
294 }
295 
296 /*
297 <simpleType
298   final = (#all | (list | union | restriction))
299   id = ID
300   name = NCName
301   {any attributes with non-schema namespace . . .}>
302   Content: (annotation?, (restriction | list | union))
303 </simpleType>
304 */
schema_simpleType(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr simpleType,sdlTypePtr cur_type)305 static int schema_simpleType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr simpleType, sdlTypePtr cur_type)
306 {
307 	xmlNodePtr trav;
308 	xmlAttrPtr name, ns;
309 
310 	ns = get_attribute(simpleType->properties, "targetNamespace");
311 	if (ns == NULL) {
312 		ns = tns;
313 	}
314 
315 	name = get_attribute(simpleType->properties, "name");
316 	if (cur_type != NULL) {
317 		/* Anonymous type inside <element> or <restriction> */
318 		sdlTypePtr newType, ptr;
319 
320 		newType = emalloc(sizeof(sdlType));
321 		memset(newType, 0, sizeof(sdlType));
322 		newType->kind = XSD_TYPEKIND_SIMPLE;
323 		if (name != NULL) {
324 			newType->name = estrdup((char*)name->children->content);
325 			newType->namens = estrdup((char*)ns->children->content);
326 		} else {
327 			newType->name = estrdup(cur_type->name);
328 			newType->namens = estrdup(cur_type->namens);
329 		}
330 
331 		ptr = zend_hash_next_index_insert_ptr(sdl->types,  newType);
332 
333 		if (sdl->encoders == NULL) {
334 			sdl->encoders = emalloc(sizeof(HashTable));
335 			zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, 0);
336 		}
337 		cur_type->encode = emalloc(sizeof(encode));
338 		memset(cur_type->encode, 0, sizeof(encode));
339 		cur_type->encode->details.ns = estrdup(newType->namens);
340 		cur_type->encode->details.type_str = estrdup(newType->name);
341 		cur_type->encode->details.sdl_type = ptr;
342 		cur_type->encode->to_xml = sdl_guess_convert_xml;
343 		cur_type->encode->to_zval = sdl_guess_convert_zval;
344 		zend_hash_next_index_insert_ptr(sdl->encoders,  cur_type->encode);
345 
346 		cur_type =ptr;
347 
348 	} else if (name != NULL) {
349 		sdlTypePtr newType, ptr;
350 
351 		newType = emalloc(sizeof(sdlType));
352 		memset(newType, 0, sizeof(sdlType));
353 		newType->kind = XSD_TYPEKIND_SIMPLE;
354 		newType->name = estrdup((char*)name->children->content);
355 		newType->namens = estrdup((char*)ns->children->content);
356 
357 		if (cur_type == NULL) {
358 			ptr = zend_hash_next_index_insert_ptr(sdl->types, newType);
359 		} else {
360 			if (cur_type->elements == NULL) {
361 				cur_type->elements = emalloc(sizeof(HashTable));
362 				zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
363 			}
364 			ptr = zend_hash_str_update_ptr(cur_type->elements, newType->name, strlen(newType->name), newType);
365 		}
366 		cur_type = ptr;
367 
368 		create_encoder(sdl, cur_type, ns->children->content, name->children->content);
369 	} else {
370 		soap_error0(E_ERROR, "Parsing Schema: simpleType has no 'name' attribute");
371 	}
372 
373 	trav = simpleType->children;
374 	if (trav != NULL && node_is_equal(trav,"annotation")) {
375 		/* TODO: <annotation> support */
376 		trav = trav->next;
377 	}
378 	if (trav != NULL) {
379 		if (node_is_equal(trav,"restriction")) {
380 			schema_restriction_simpleContent(sdl, tns, trav, cur_type, 1);
381 			trav = trav->next;
382 		} else if (node_is_equal(trav,"list")) {
383 			cur_type->kind = XSD_TYPEKIND_LIST;
384 			schema_list(sdl, tns, trav, cur_type);
385 			trav = trav->next;
386 		} else if (node_is_equal(trav,"union")) {
387 			cur_type->kind = XSD_TYPEKIND_UNION;
388 			schema_union(sdl, tns, trav, cur_type);
389 			trav = trav->next;
390 		} else {
391 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in simpleType", trav->name);
392 		}
393 	} else {
394 		soap_error0(E_ERROR, "Parsing Schema: expected <restriction>, <list> or <union> in simpleType");
395 	}
396 	if (trav != NULL) {
397 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in simpleType", trav->name);
398 	}
399 
400 	return TRUE;
401 }
402 
403 /*
404 <list
405   id = ID
406   itemType = QName
407   {any attributes with non-schema namespace . . .}>
408   Content: (annotation?, (simpleType?))
409 </list>
410 */
schema_list(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr listType,sdlTypePtr cur_type)411 static int schema_list(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr listType, sdlTypePtr cur_type)
412 {
413 	xmlNodePtr trav;
414 	xmlAttrPtr itemType;
415 
416 	itemType = get_attribute(listType->properties, "itemType");
417 	if (itemType != NULL) {
418 		char *type, *ns;
419 		xmlNsPtr nsptr;
420 
421 		parse_namespace(itemType->children->content, &type, &ns);
422 		nsptr = xmlSearchNs(listType->doc, listType, BAD_CAST(ns));
423 		if (nsptr != NULL) {
424 			sdlTypePtr newType;
425 
426 			newType = emalloc(sizeof(sdlType));
427 			memset(newType, 0, sizeof(sdlType));
428 
429 			newType->name = estrdup(type);
430 			newType->namens = estrdup((char*)nsptr->href);
431 
432 			newType->encode = get_create_encoder(sdl, newType, nsptr->href, BAD_CAST(type));
433 
434 			if (cur_type->elements == NULL) {
435 				cur_type->elements = emalloc(sizeof(HashTable));
436 				zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
437 			}
438 			zend_hash_next_index_insert_ptr(cur_type->elements, newType);
439 		}
440 		if (type) {efree(type);}
441 		if (ns) {efree(ns);}
442 	}
443 
444 	trav = listType->children;
445 	if (trav != NULL && node_is_equal(trav,"annotation")) {
446 		/* TODO: <annotation> support */
447 		trav = trav->next;
448 	}
449 	if (trav != NULL && node_is_equal(trav,"simpleType")) {
450 		sdlTypePtr newType;
451 
452 		if (itemType != NULL) {
453 			soap_error0(E_ERROR, "Parsing Schema: element has both 'itemType' attribute and subtype");
454 		}
455 
456 		newType = emalloc(sizeof(sdlType));
457 		memset(newType, 0, sizeof(sdlType));
458 
459 		{
460 			char buf[MAX_LENGTH_OF_LONG + 1];
461 			char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, zend_hash_num_elements(sdl->types));
462 			char *str = emalloc(sizeof("anonymous") + buf + sizeof(buf) - 1 - res);
463 
464 			memcpy(str, "anonymous", sizeof("anonymous")-1);
465 			memcpy(str + sizeof("anonymous")-1, res, buf + sizeof(buf) - res);
466 			newType->name = str;
467 		}
468 		newType->namens = estrdup((char*)tns->children->content);
469 
470 		if (cur_type->elements == NULL) {
471 			cur_type->elements = emalloc(sizeof(HashTable));
472 			zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
473 		}
474 		zend_hash_next_index_insert_ptr(cur_type->elements, newType);
475 
476 		schema_simpleType(sdl, tns, trav, newType);
477 
478 		trav = trav->next;
479 	}
480 	if (trav != NULL) {
481 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in list", trav->name);
482 	}
483 	return TRUE;
484 }
485 
486 /*
487 <union
488   id = ID
489   memberTypes = List of QName
490   {any attributes with non-schema namespace . . .}>
491   Content: (annotation?, (simpleType*))
492 </union>
493 */
schema_union(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr unionType,sdlTypePtr cur_type)494 static int schema_union(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr unionType, sdlTypePtr cur_type)
495 {
496 	xmlNodePtr trav;
497 	xmlAttrPtr memberTypes;
498 
499 	memberTypes = get_attribute(unionType->properties, "memberTypes");
500 	if (memberTypes != NULL) {
501 		char *str, *start, *end, *next;
502 		char *type, *ns;
503 		xmlNsPtr nsptr;
504 
505 		str = estrdup((char*)memberTypes->children->content);
506 		whiteSpace_collapse(BAD_CAST(str));
507 		start = str;
508 		while (start != NULL && *start != '\0') {
509 			end = strchr(start,' ');
510 			if (end == NULL) {
511 				next = NULL;
512 			} else {
513 				*end = '\0';
514 				next = end+1;
515 			}
516 
517 			parse_namespace(BAD_CAST(start), &type, &ns);
518 			nsptr = xmlSearchNs(unionType->doc, unionType, BAD_CAST(ns));
519 			if (nsptr != NULL) {
520 				sdlTypePtr newType;
521 
522 				newType = emalloc(sizeof(sdlType));
523 				memset(newType, 0, sizeof(sdlType));
524 
525 				newType->name = estrdup(type);
526 				newType->namens = estrdup((char*)nsptr->href);
527 
528 				newType->encode = get_create_encoder(sdl, newType, nsptr->href, BAD_CAST(type));
529 
530 				if (cur_type->elements == NULL) {
531 					cur_type->elements = emalloc(sizeof(HashTable));
532 					zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
533 				}
534 				zend_hash_next_index_insert_ptr(cur_type->elements, newType);
535 			}
536 			if (type) {efree(type);}
537 			if (ns) {efree(ns);}
538 
539 			start = next;
540 		}
541 		efree(str);
542 	}
543 
544 	trav = unionType->children;
545 	if (trav != NULL && node_is_equal(trav,"annotation")) {
546 		/* TODO: <annotation> support */
547 		trav = trav->next;
548 	}
549 	while (trav != NULL) {
550 		if (node_is_equal(trav,"simpleType")) {
551 			sdlTypePtr newType;
552 
553 			newType = emalloc(sizeof(sdlType));
554 			memset(newType, 0, sizeof(sdlType));
555 
556 			{
557 				char buf[MAX_LENGTH_OF_LONG + 1];
558 				char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, zend_hash_num_elements(sdl->types));
559 				char *str = emalloc(sizeof("anonymous") + buf + sizeof(buf) - 1 - res);
560 
561 				memcpy(str, "anonymous", sizeof("anonymous")-1);
562 				memcpy(str + sizeof("anonymous")-1, res, buf + sizeof(buf) - res);
563 				newType->name = str;
564 			}
565 			newType->namens = estrdup((char*)tns->children->content);
566 
567 			if (cur_type->elements == NULL) {
568 				cur_type->elements = emalloc(sizeof(HashTable));
569 				zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
570 			}
571 			zend_hash_next_index_insert_ptr(cur_type->elements, newType);
572 
573 			schema_simpleType(sdl, tns, trav, newType);
574 
575 		} else {
576 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in union", trav->name);
577 		}
578 		trav = trav->next;
579 	}
580 	if (trav != NULL) {
581 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in union", trav->name);
582 	}
583 	return TRUE;
584 }
585 
586 /*
587 <simpleContent
588   id = ID
589   {any attributes with non-schema namespace . . .}>
590   Content: (annotation?, (restriction | extension))
591 </simpleContent>
592 */
schema_simpleContent(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr simpCompType,sdlTypePtr cur_type)593 static int schema_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr simpCompType, sdlTypePtr cur_type)
594 {
595 	xmlNodePtr trav;
596 
597 	trav = simpCompType->children;
598 	if (trav != NULL && node_is_equal(trav,"annotation")) {
599 		/* TODO: <annotation> support */
600 		trav = trav->next;
601 	}
602 	if (trav != NULL) {
603 		if (node_is_equal(trav, "restriction")) {
604 			cur_type->kind = XSD_TYPEKIND_RESTRICTION;
605 			schema_restriction_simpleContent(sdl, tns, trav, cur_type, 0);
606 			trav = trav->next;
607 		} else if (node_is_equal(trav, "extension")) {
608 			cur_type->kind = XSD_TYPEKIND_EXTENSION;
609 			schema_extension_simpleContent(sdl, tns, trav, cur_type);
610 			trav = trav->next;
611 		} else {
612 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in simpleContent", trav->name);
613 		}
614 	} else {
615 		soap_error0(E_ERROR, "Parsing Schema: expected <restriction> or <extension> in simpleContent");
616 	}
617 	if (trav != NULL) {
618 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in simpleContent", trav->name);
619 	}
620 
621 	return TRUE;
622 }
623 
624 /*
625 simpleType:<restriction
626   base = QName
627   id = ID
628   {any attributes with non-schema namespace . . .}>
629   Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)?)
630 </restriction>
631 simpleContent:<restriction
632   base = QName
633   id = ID
634   {any attributes with non-schema namespace . . .}>
635   Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))
636 </restriction>
637 */
schema_restriction_simpleContent(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr restType,sdlTypePtr cur_type,int simpleType)638 static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr restType, sdlTypePtr cur_type, int simpleType)
639 {
640 	xmlNodePtr trav;
641 	xmlAttrPtr base;
642 
643 	base = get_attribute(restType->properties, "base");
644 	if (base != NULL) {
645 		char *type, *ns;
646 		xmlNsPtr nsptr;
647 
648 		parse_namespace(base->children->content, &type, &ns);
649 		nsptr = xmlSearchNs(restType->doc, restType, BAD_CAST(ns));
650 		if (nsptr != NULL) {
651 			cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(type));
652 		}
653 		if (type) {efree(type);}
654 		if (ns) {efree(ns);}
655 	} else if (!simpleType) {
656 		soap_error0(E_ERROR, "Parsing Schema: restriction has no 'base' attribute");
657 	}
658 
659 	if (cur_type->restrictions == NULL) {
660 		cur_type->restrictions = emalloc(sizeof(sdlRestrictions));
661 		memset(cur_type->restrictions, 0, sizeof(sdlRestrictions));
662 	}
663 
664 	trav = restType->children;
665 	if (trav != NULL && node_is_equal(trav, "annotation")) {
666 		/* TODO: <annotation> support */
667 		trav = trav->next;
668 	}
669 	if (trav != NULL && node_is_equal(trav, "simpleType")) {
670 		schema_simpleType(sdl, tns, trav, cur_type);
671 		trav = trav->next;
672 	}
673 	while (trav != NULL) {
674 		if (node_is_equal(trav, "minExclusive")) {
675 			schema_restriction_var_int(trav, &cur_type->restrictions->minExclusive);
676 		} else if (node_is_equal(trav, "minInclusive")) {
677 			schema_restriction_var_int(trav, &cur_type->restrictions->minInclusive);
678 		} else if (node_is_equal(trav, "maxExclusive")) {
679 			schema_restriction_var_int(trav, &cur_type->restrictions->maxExclusive);
680 		} else if (node_is_equal(trav, "maxInclusive")) {
681 			schema_restriction_var_int(trav, &cur_type->restrictions->maxInclusive);
682 		} else if (node_is_equal(trav, "totalDigits")) {
683 			schema_restriction_var_int(trav, &cur_type->restrictions->totalDigits);
684 		} else if (node_is_equal(trav, "fractionDigits")) {
685 			schema_restriction_var_int(trav, &cur_type->restrictions->fractionDigits);
686 		} else if (node_is_equal(trav, "length")) {
687 			schema_restriction_var_int(trav, &cur_type->restrictions->length);
688 		} else if (node_is_equal(trav, "minLength")) {
689 			schema_restriction_var_int(trav, &cur_type->restrictions->minLength);
690 		} else if (node_is_equal(trav, "maxLength")) {
691 			schema_restriction_var_int(trav, &cur_type->restrictions->maxLength);
692 		} else if (node_is_equal(trav, "whiteSpace")) {
693 			schema_restriction_var_char(trav, &cur_type->restrictions->whiteSpace);
694 		} else if (node_is_equal(trav, "pattern")) {
695 			schema_restriction_var_char(trav, &cur_type->restrictions->pattern);
696 		} else if (node_is_equal(trav, "enumeration")) {
697 			sdlRestrictionCharPtr enumval = NULL;
698 
699 			schema_restriction_var_char(trav, &enumval);
700 			if (cur_type->restrictions->enumeration == NULL) {
701 				cur_type->restrictions->enumeration = emalloc(sizeof(HashTable));
702 				zend_hash_init(cur_type->restrictions->enumeration, 0, NULL, delete_restriction_var_char, 0);
703 			}
704 			if (zend_hash_str_add_ptr(cur_type->restrictions->enumeration, enumval->value, strlen(enumval->value), enumval) == NULL) {
705 				delete_restriction_var_char_int(enumval);
706 			}
707 		} else {
708 			break;
709 		}
710 		trav = trav->next;
711 	}
712 	if (!simpleType) {
713 		while (trav != NULL) {
714 			if (node_is_equal(trav,"attribute")) {
715 				schema_attribute(sdl, tns, trav, cur_type, NULL);
716 			} else if (node_is_equal(trav,"attributeGroup")) {
717 				schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
718 			} else if (node_is_equal(trav,"anyAttribute")) {
719 				/* TODO: <anyAttribute> support */
720 				trav = trav->next;
721 				break;
722 			} else {
723 				soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in restriction", trav->name);
724 			}
725 			trav = trav->next;
726 		}
727 	}
728 	if (trav != NULL) {
729 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in restriction", trav->name);
730 	}
731 
732 	return TRUE;
733 }
734 
735 /*
736 <restriction
737   base = QName
738   id = ID
739   {any attributes with non-schema namespace . . .}>
740   Content: (annotation?, (group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?))
741 </restriction>
742 */
schema_restriction_complexContent(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr restType,sdlTypePtr cur_type)743 static int schema_restriction_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr restType, sdlTypePtr cur_type)
744 {
745 	xmlAttrPtr base;
746 	xmlNodePtr trav;
747 
748 	base = get_attribute(restType->properties, "base");
749 	if (base != NULL) {
750 		char *type, *ns;
751 		xmlNsPtr nsptr;
752 
753 		parse_namespace(base->children->content, &type, &ns);
754 		nsptr = xmlSearchNs(restType->doc, restType, BAD_CAST(ns));
755 		if (nsptr != NULL) {
756 			cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(type));
757 		}
758 		if (type) {efree(type);}
759 		if (ns) {efree(ns);}
760 	} else {
761 		soap_error0(E_ERROR, "Parsing Schema: restriction has no 'base' attribute");
762 	}
763 
764 	trav = restType->children;
765 	if (trav != NULL && node_is_equal(trav,"annotation")) {
766 		/* TODO: <annotation> support */
767 		trav = trav->next;
768 	}
769 	if (trav != NULL) {
770 		if (node_is_equal(trav,"group")) {
771 			schema_group(sdl, tns, trav, cur_type, NULL);
772 			trav = trav->next;
773 		} else if (node_is_equal(trav,"all")) {
774 			schema_all(sdl, tns, trav, cur_type, NULL);
775 			trav = trav->next;
776 		} else if (node_is_equal(trav,"choice")) {
777 			schema_choice(sdl, tns, trav, cur_type, NULL);
778 			trav = trav->next;
779 		} else if (node_is_equal(trav,"sequence")) {
780 			schema_sequence(sdl, tns, trav, cur_type, NULL);
781 			trav = trav->next;
782 		}
783 	}
784 	while (trav != NULL) {
785 		if (node_is_equal(trav,"attribute")) {
786 			schema_attribute(sdl, tns, trav, cur_type, NULL);
787 		} else if (node_is_equal(trav,"attributeGroup")) {
788 			schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
789 		} else if (node_is_equal(trav,"anyAttribute")) {
790 			/* TODO: <anyAttribute> support */
791 			trav = trav->next;
792 			break;
793 		} else {
794 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in restriction", trav->name);
795 		}
796 		trav = trav->next;
797 	}
798 	if (trav != NULL) {
799 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in restriction", trav->name);
800 	}
801 
802 	return TRUE;
803 }
804 
schema_restriction_var_int(xmlNodePtr val,sdlRestrictionIntPtr * valptr)805 static int schema_restriction_var_int(xmlNodePtr val, sdlRestrictionIntPtr *valptr)
806 {
807 	xmlAttrPtr fixed, value;
808 
809 	if ((*valptr) == NULL) {
810 		(*valptr) = emalloc(sizeof(sdlRestrictionInt));
811 	}
812 	memset((*valptr), 0, sizeof(sdlRestrictionInt));
813 
814 	fixed = get_attribute(val->properties, "fixed");
815 	(*valptr)->fixed = FALSE;
816 	if (fixed != NULL) {
817 		if (!strncmp((char*)fixed->children->content, "true", sizeof("true")) ||
818 			!strncmp((char*)fixed->children->content, "1", sizeof("1")))
819 			(*valptr)->fixed = TRUE;
820 	}
821 
822 	value = get_attribute(val->properties, "value");
823 	if (value == NULL) {
824 		soap_error0(E_ERROR, "Parsing Schema: missing restriction value");
825 	}
826 
827 	(*valptr)->value = atoi((char*)value->children->content);
828 
829 	return TRUE;
830 }
831 
schema_restriction_var_char(xmlNodePtr val,sdlRestrictionCharPtr * valptr)832 static int schema_restriction_var_char(xmlNodePtr val, sdlRestrictionCharPtr *valptr)
833 {
834 	xmlAttrPtr fixed, value;
835 
836 	if ((*valptr) == NULL) {
837 		(*valptr) = emalloc(sizeof(sdlRestrictionChar));
838 	}
839 	memset((*valptr), 0, sizeof(sdlRestrictionChar));
840 
841 	fixed = get_attribute(val->properties, "fixed");
842 	(*valptr)->fixed = FALSE;
843 	if (fixed != NULL) {
844 		if (!strncmp((char*)fixed->children->content, "true", sizeof("true")) ||
845 		    !strncmp((char*)fixed->children->content, "1", sizeof("1"))) {
846 			(*valptr)->fixed = TRUE;
847 		}
848 	}
849 
850 	value = get_attribute(val->properties, "value");
851 	if (value == NULL) {
852 		soap_error0(E_ERROR, "Parsing Schema: missing restriction value");
853 	}
854 
855 	(*valptr)->value = estrdup((char*)value->children->content);
856 	return TRUE;
857 }
858 
859 /*
860 From simpleContent (not supported):
861 <extension
862   base = QName
863   id = ID
864   {any attributes with non-schema namespace . . .}>
865   Content: (annotation?, ((attribute | attributeGroup)*, anyAttribute?))
866 </extension>
867 */
schema_extension_simpleContent(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr extType,sdlTypePtr cur_type)868 static int schema_extension_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type)
869 {
870 	xmlNodePtr trav;
871 	xmlAttrPtr base;
872 
873 	base = get_attribute(extType->properties, "base");
874 	if (base != NULL) {
875 		char *type, *ns;
876 		xmlNsPtr nsptr;
877 
878 		parse_namespace(base->children->content, &type, &ns);
879 		nsptr = xmlSearchNs(extType->doc, extType, BAD_CAST(ns));
880 		if (nsptr != NULL) {
881 			cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(type));
882 		}
883 		if (type) {efree(type);}
884 		if (ns) {efree(ns);}
885 	} else {
886 		soap_error0(E_ERROR, "Parsing Schema: extension has no 'base' attribute");
887 	}
888 
889 	trav = extType->children;
890 	if (trav != NULL && node_is_equal(trav,"annotation")) {
891 		/* TODO: <annotation> support */
892 		trav = trav->next;
893 	}
894 	while (trav != NULL) {
895 		if (node_is_equal(trav,"attribute")) {
896 			schema_attribute(sdl, tns, trav, cur_type, NULL);
897 		} else if (node_is_equal(trav,"attributeGroup")) {
898 			schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
899 		} else if (node_is_equal(trav,"anyAttribute")) {
900 			/* TODO: <anyAttribute> support */
901 			trav = trav->next;
902 			break;
903 		} else {
904 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in extension", trav->name);
905 		}
906 		trav = trav->next;
907 	}
908 	if (trav != NULL) {
909 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in extension", trav->name);
910 	}
911 	return TRUE;
912 }
913 
914 /*
915 From complexContent:
916 <extension
917   base = QName
918   id = ID
919   {any attributes with non-schema namespace . . .}>
920   Content: (annotation?, ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?)))
921 </extension>
922 */
schema_extension_complexContent(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr extType,sdlTypePtr cur_type)923 static int schema_extension_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type)
924 {
925 	xmlNodePtr trav;
926 	xmlAttrPtr base;
927 
928 	base = get_attribute(extType->properties, "base");
929 	if (base != NULL) {
930 		char *type, *ns;
931 		xmlNsPtr nsptr;
932 
933 		parse_namespace(base->children->content, &type, &ns);
934 		nsptr = xmlSearchNs(extType->doc, extType, BAD_CAST(ns));
935 		if (nsptr != NULL) {
936 			cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(type));
937 		}
938 		if (type) {efree(type);}
939 		if (ns) {efree(ns);}
940 	} else {
941 		soap_error0(E_ERROR, "Parsing Schema: extension has no 'base' attribute");
942 	}
943 
944 	trav = extType->children;
945 	if (trav != NULL && node_is_equal(trav,"annotation")) {
946 		/* TODO: <annotation> support */
947 		trav = trav->next;
948 	}
949 	if (trav != NULL) {
950 		if (node_is_equal(trav,"group")) {
951 			schema_group(sdl, tns, trav, cur_type, NULL);
952 			trav = trav->next;
953 		} else if (node_is_equal(trav,"all")) {
954 			schema_all(sdl, tns, trav, cur_type, NULL);
955 			trav = trav->next;
956 		} else if (node_is_equal(trav,"choice")) {
957 			schema_choice(sdl, tns, trav, cur_type, NULL);
958 			trav = trav->next;
959 		} else if (node_is_equal(trav,"sequence")) {
960 			schema_sequence(sdl, tns, trav, cur_type, NULL);
961 			trav = trav->next;
962 		}
963 	}
964 	while (trav != NULL) {
965 		if (node_is_equal(trav,"attribute")) {
966 			schema_attribute(sdl, tns, trav, cur_type, NULL);
967 		} else if (node_is_equal(trav,"attributeGroup")) {
968 			schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
969 		} else if (node_is_equal(trav,"anyAttribute")) {
970 			/* TODO: <anyAttribute> support */
971 			trav = trav->next;
972 			break;
973 		} else {
974 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in extension", trav->name);
975 		}
976 		trav = trav->next;
977 	}
978 	if (trav != NULL) {
979 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in extension", trav->name);
980 	}
981 	return TRUE;
982 }
983 
schema_min_max(xmlNodePtr node,sdlContentModelPtr model)984 void schema_min_max(xmlNodePtr node, sdlContentModelPtr model)
985 {
986 	xmlAttrPtr attr = get_attribute(node->properties, "minOccurs");
987 
988 	if (attr) {
989 		model->min_occurs = atoi((char*)attr->children->content);
990 	} else {
991 		model->min_occurs = 1;
992 	}
993 
994 	attr = get_attribute(node->properties, "maxOccurs");
995 	if (attr) {
996 		if (!strncmp((char*)attr->children->content, "unbounded", sizeof("unbounded"))) {
997 			model->max_occurs = -1;
998 		} else {
999 			model->max_occurs = atoi((char*)attr->children->content);
1000 		}
1001 	} else {
1002 		model->max_occurs = 1;
1003 	}
1004 }
1005 
1006 /*
1007 <all
1008   id = ID
1009   maxOccurs = 1 : 1
1010   minOccurs = (0 | 1) : 1
1011   {any attributes with non-schema namespace . . .}>
1012   Content: (annotation?, element*)
1013 </all>
1014 */
schema_all(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr all,sdlTypePtr cur_type,sdlContentModelPtr model)1015 static int schema_all(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr all, sdlTypePtr cur_type, sdlContentModelPtr model)
1016 {
1017 	xmlNodePtr trav;
1018 	sdlContentModelPtr newModel;
1019 
1020 	newModel = emalloc(sizeof(sdlContentModel));
1021 	newModel->kind = XSD_CONTENT_ALL;
1022 	newModel->u.content = emalloc(sizeof(HashTable));
1023 	zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
1024 	if (model == NULL) {
1025 		cur_type->model = newModel;
1026 	} else {
1027 		zend_hash_next_index_insert_ptr(model->u.content, newModel);
1028 	}
1029 
1030 	schema_min_max(all, newModel);
1031 
1032 	trav = all->children;
1033 	if (trav != NULL && node_is_equal(trav,"annotation")) {
1034 		/* TODO: <annotation> support */
1035 		trav = trav->next;
1036 	}
1037 	while (trav != NULL) {
1038 		if (node_is_equal(trav,"element")) {
1039 			schema_element(sdl, tns, trav, cur_type, newModel);
1040 		} else {
1041 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in all", trav->name);
1042 		}
1043 		trav = trav->next;
1044 	}
1045 	return TRUE;
1046 }
1047 
1048 /*
1049 <group
1050   name = NCName
1051   Content: (annotation?, (all | choice | sequence))
1052 </group>
1053 <group
1054   name = NCName
1055   ref = QName>
1056   Content: (annotation?)
1057 </group>
1058 */
schema_group(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr groupType,sdlTypePtr cur_type,sdlContentModelPtr model)1059 static int schema_group(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr groupType, sdlTypePtr cur_type, sdlContentModelPtr model)
1060 {
1061 	xmlNodePtr trav;
1062 	xmlAttrPtr ns, name, ref = NULL;
1063 	sdlContentModelPtr newModel = NULL;
1064 
1065 	ns = get_attribute(groupType->properties, "targetNamespace");
1066 	if (ns == NULL) {
1067 		ns = tns;
1068 	}
1069 
1070 	name = get_attribute(groupType->properties, "name");
1071 	if (name == NULL) {
1072 		name = ref = get_attribute(groupType->properties, "ref");
1073 	}
1074 
1075 	if (name) {
1076 		smart_str key = {0};
1077 
1078 		if (ref) {
1079 			char *type, *ns;
1080 			xmlNsPtr nsptr;
1081 
1082 			parse_namespace(ref->children->content, &type, &ns);
1083 			nsptr = xmlSearchNs(groupType->doc, groupType, BAD_CAST(ns));
1084 			if (nsptr != NULL) {
1085 				smart_str_appends(&key, (char*)nsptr->href);
1086 			} else {
1087 				xmlAttrPtr ns = get_attribute(groupType->properties, "targetNamespace");
1088 				if (ns == NULL) {
1089 					ns = tns;
1090 				}
1091 				if (ns) {
1092 					smart_str_appends(&key, (char*)ns->children->content);
1093 				}
1094 			}
1095 			smart_str_appendc(&key, ':');
1096 			smart_str_appends(&key, type);
1097 			smart_str_0(&key);
1098 
1099 			newModel = emalloc(sizeof(sdlContentModel));
1100 			newModel->kind = XSD_CONTENT_GROUP_REF;
1101 			newModel->u.group_ref = estrndup(ZSTR_VAL(key.s), ZSTR_LEN(key.s));
1102 
1103 			if (type) {efree(type);}
1104 			if (ns) {efree(ns);}
1105 		} else {
1106 			newModel = emalloc(sizeof(sdlContentModel));
1107 			newModel->kind = XSD_CONTENT_SEQUENCE; /* will be redefined */
1108 			newModel->u.content = emalloc(sizeof(HashTable));
1109 			zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
1110 
1111 			smart_str_appends(&key, (char*)ns->children->content);
1112 			smart_str_appendc(&key, ':');
1113 			smart_str_appends(&key, (char*)name->children->content);
1114 			smart_str_0(&key);
1115 		}
1116 
1117 		if (cur_type == NULL) {
1118 			sdlTypePtr newType;
1119 
1120 			newType = emalloc(sizeof(sdlType));
1121 			memset(newType, 0, sizeof(sdlType));
1122 
1123 			if (sdl->groups == NULL) {
1124 				sdl->groups = emalloc(sizeof(HashTable));
1125 				zend_hash_init(sdl->groups, 0, NULL, delete_type, 0);
1126 			}
1127 			if (zend_hash_add_ptr(sdl->groups, key.s, newType) == NULL) {
1128 				soap_error1(E_ERROR, "Parsing Schema: group '%s' already defined", ZSTR_VAL(key.s));
1129 			}
1130 
1131 			cur_type = newType;
1132 		}
1133 		smart_str_free(&key);
1134 
1135 		if (model == NULL) {
1136 			cur_type->model = newModel;
1137 		} else {
1138 			zend_hash_next_index_insert_ptr(model->u.content, newModel);
1139 		}
1140 	} else {
1141 		soap_error0(E_ERROR, "Parsing Schema: group has no 'name' nor 'ref' attributes");
1142 	}
1143 
1144 	schema_min_max(groupType, newModel);
1145 
1146 	trav = groupType->children;
1147 	if (trav != NULL && node_is_equal(trav,"annotation")) {
1148 		/* TODO: <annotation> support */
1149 		trav = trav->next;
1150 	}
1151 	if (trav != NULL) {
1152 		if (node_is_equal(trav,"choice")) {
1153 			if (ref != NULL) {
1154 				soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent");
1155 			}
1156 			newModel->kind = XSD_CONTENT_CHOICE;
1157 			schema_choice(sdl, tns, trav, cur_type, newModel);
1158 			trav = trav->next;
1159 		} else if (node_is_equal(trav,"sequence")) {
1160 			if (ref != NULL) {
1161 				soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent");
1162 			}
1163 			newModel->kind = XSD_CONTENT_SEQUENCE;
1164 			schema_sequence(sdl, tns, trav, cur_type, newModel);
1165 			trav = trav->next;
1166 		} else if (node_is_equal(trav,"all")) {
1167 			if (ref != NULL) {
1168 				soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent");
1169 			}
1170 			newModel->kind = XSD_CONTENT_ALL;
1171 			schema_all(sdl, tns, trav, cur_type, newModel);
1172 			trav = trav->next;
1173 		} else {
1174 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in group", trav->name);
1175 		}
1176 	}
1177 	if (trav != NULL) {
1178 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in group", trav->name);
1179 	}
1180 	return TRUE;
1181 }
1182 /*
1183 <choice
1184   id = ID
1185   maxOccurs = (nonNegativeInteger | unbounded)  : 1
1186   minOccurs = nonNegativeInteger : 1
1187   {any attributes with non-schema namespace . . .}>
1188   Content: (annotation?, (element | group | choice | sequence | any)*)
1189 </choice>
1190 */
schema_choice(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr choiceType,sdlTypePtr cur_type,sdlContentModelPtr model)1191 static int schema_choice(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr choiceType, sdlTypePtr cur_type, sdlContentModelPtr model)
1192 {
1193 	xmlNodePtr trav;
1194 	sdlContentModelPtr newModel;
1195 
1196 	newModel = emalloc(sizeof(sdlContentModel));
1197 	newModel->kind = XSD_CONTENT_CHOICE;
1198 	newModel->u.content = emalloc(sizeof(HashTable));
1199 	zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
1200 	if (model == NULL) {
1201 		cur_type->model = newModel;
1202 	} else {
1203 		zend_hash_next_index_insert_ptr(model->u.content, newModel);
1204 	}
1205 
1206 	schema_min_max(choiceType, newModel);
1207 
1208 	trav = choiceType->children;
1209 	if (trav != NULL && node_is_equal(trav,"annotation")) {
1210 		/* TODO: <annotation> support */
1211 		trav = trav->next;
1212 	}
1213 	while (trav != NULL) {
1214 		if (node_is_equal(trav,"element")) {
1215 			schema_element(sdl, tns, trav, cur_type, newModel);
1216 		} else if (node_is_equal(trav,"group")) {
1217 			schema_group(sdl, tns, trav, cur_type, newModel);
1218 		} else if (node_is_equal(trav,"choice")) {
1219 			schema_choice(sdl, tns, trav, cur_type, newModel);
1220 		} else if (node_is_equal(trav,"sequence")) {
1221 			schema_sequence(sdl, tns, trav, cur_type, newModel);
1222 		} else if (node_is_equal(trav,"any")) {
1223 			schema_any(sdl, tns, trav, cur_type, newModel);
1224 		} else {
1225 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in choice", trav->name);
1226 		}
1227 		trav = trav->next;
1228 	}
1229 	return TRUE;
1230 }
1231 
1232 /*
1233 <sequence
1234   id = ID
1235   maxOccurs = (nonNegativeInteger | unbounded)  : 1
1236   minOccurs = nonNegativeInteger : 1
1237   {any attributes with non-schema namespace . . .}>
1238   Content: (annotation?, (element | group | choice | sequence | any)*)
1239 </sequence>
1240 */
schema_sequence(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr seqType,sdlTypePtr cur_type,sdlContentModelPtr model)1241 static int schema_sequence(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr seqType, sdlTypePtr cur_type, sdlContentModelPtr model)
1242 {
1243 	xmlNodePtr trav;
1244 	sdlContentModelPtr newModel;
1245 
1246 	newModel = emalloc(sizeof(sdlContentModel));
1247 	newModel->kind = XSD_CONTENT_SEQUENCE;
1248 	newModel->u.content = emalloc(sizeof(HashTable));
1249 	zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
1250 	if (model == NULL) {
1251 		cur_type->model = newModel;
1252 	} else {
1253 		zend_hash_next_index_insert_ptr(model->u.content, newModel);
1254 	}
1255 
1256 	schema_min_max(seqType, newModel);
1257 
1258 	trav = seqType->children;
1259 	if (trav != NULL && node_is_equal(trav,"annotation")) {
1260 		/* TODO: <annotation> support */
1261 		trav = trav->next;
1262 	}
1263 	while (trav != NULL) {
1264 		if (node_is_equal(trav,"element")) {
1265 			schema_element(sdl, tns, trav, cur_type, newModel);
1266 		} else if (node_is_equal(trav,"group")) {
1267 			schema_group(sdl, tns, trav, cur_type, newModel);
1268 		} else if (node_is_equal(trav,"choice")) {
1269 			schema_choice(sdl, tns, trav, cur_type, newModel);
1270 		} else if (node_is_equal(trav,"sequence")) {
1271 			schema_sequence(sdl, tns, trav, cur_type, newModel);
1272 		} else if (node_is_equal(trav,"any")) {
1273 			schema_any(sdl, tns, trav, cur_type, newModel);
1274 		} else {
1275 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in sequence", trav->name);
1276 		}
1277 		trav = trav->next;
1278 	}
1279 	return TRUE;
1280 }
1281 
1282 /*
1283 <any
1284   id = ID
1285   maxOccurs = (nonNegativeInteger | unbounded)  : 1
1286   minOccurs = nonNegativeInteger : 1
1287   namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) )  : ##any
1288   processContents = (lax | skip | strict) : strict
1289   {any attributes with non-schema namespace . . .}>
1290   Content: (annotation?)
1291 </any>
1292 */
schema_any(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr anyType,sdlTypePtr cur_type,sdlContentModelPtr model)1293 static int schema_any(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr anyType, sdlTypePtr cur_type, sdlContentModelPtr model)
1294 {
1295 	if (model != NULL) {
1296 		sdlContentModelPtr newModel;
1297 
1298 		newModel = emalloc(sizeof(sdlContentModel));
1299 		newModel->kind = XSD_CONTENT_ANY;
1300 
1301 		schema_min_max(anyType, newModel);
1302 
1303 		zend_hash_next_index_insert_ptr(model->u.content, newModel);
1304 	}
1305 	return TRUE;
1306 }
1307 
1308 /*
1309 <complexContent
1310   id = ID
1311   mixed = boolean
1312   {any attributes with non-schema namespace . . .}>
1313   Content: (annotation?, (restriction | extension))
1314 </complexContent>
1315 */
schema_complexContent(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr compCont,sdlTypePtr cur_type)1316 static int schema_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr compCont, sdlTypePtr cur_type)
1317 {
1318 	xmlNodePtr trav;
1319 
1320 	trav = compCont->children;
1321 	if (trav != NULL && node_is_equal(trav,"annotation")) {
1322 		/* TODO: <annotation> support */
1323 		trav = trav->next;
1324 	}
1325 	if (trav != NULL) {
1326 		if (node_is_equal(trav, "restriction")) {
1327 			cur_type->kind = XSD_TYPEKIND_RESTRICTION;
1328 			schema_restriction_complexContent(sdl, tns, trav, cur_type);
1329 			trav = trav->next;
1330 		} else if (node_is_equal(trav, "extension")) {
1331 			cur_type->kind = XSD_TYPEKIND_EXTENSION;
1332 			schema_extension_complexContent(sdl, tns, trav, cur_type);
1333 			trav = trav->next;
1334 		} else {
1335 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexContent", trav->name);
1336 		}
1337 	} else {
1338 		soap_error0(E_ERROR, "Parsing Schema: <restriction> or <extension> expected in complexContent");
1339 	}
1340 	if (trav != NULL) {
1341 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexContent", trav->name);
1342 	}
1343 
1344 	return TRUE;
1345 }
1346 
1347 /*
1348 <complexType
1349   abstract = boolean : false
1350   block = (#all | List of (extension | restriction))
1351   final = (#all | List of (extension | restriction))
1352   id = ID
1353   mixed = boolean : false
1354   name = NCName
1355   {any attributes with non-schema namespace . . .}>
1356   Content: (annotation?, (simpleContent | complexContent | ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?))))
1357 </complexType>
1358 */
schema_complexType(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr compType,sdlTypePtr cur_type)1359 static int schema_complexType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr compType, sdlTypePtr cur_type)
1360 {
1361 	xmlNodePtr trav;
1362 	xmlAttrPtr attrs, name, ns;
1363 
1364 	attrs = compType->properties;
1365 	ns = get_attribute(attrs, "targetNamespace");
1366 	if (ns == NULL) {
1367 		ns = tns;
1368 	}
1369 
1370 	name = get_attribute(attrs, "name");
1371 	if (cur_type != NULL) {
1372 		/* Anonymous type inside <element> */
1373 		sdlTypePtr newType, ptr;
1374 
1375 		newType = emalloc(sizeof(sdlType));
1376 		memset(newType, 0, sizeof(sdlType));
1377 		newType->kind = XSD_TYPEKIND_COMPLEX;
1378 		if (name != NULL) {
1379 			newType->name = estrdup((char*)name->children->content);
1380 			newType->namens = estrdup((char*)ns->children->content);
1381 		} else {
1382 			newType->name = estrdup(cur_type->name);
1383 			newType->namens = estrdup(cur_type->namens);
1384 		}
1385 
1386 		ptr = zend_hash_next_index_insert_ptr(sdl->types, newType);
1387 
1388 		if (sdl->encoders == NULL) {
1389 			sdl->encoders = emalloc(sizeof(HashTable));
1390 			zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, 0);
1391 		}
1392 		cur_type->encode = emalloc(sizeof(encode));
1393 		memset(cur_type->encode, 0, sizeof(encode));
1394 		cur_type->encode->details.ns = estrdup(newType->namens);
1395 		cur_type->encode->details.type_str = estrdup(newType->name);
1396 		cur_type->encode->details.sdl_type = ptr;
1397 		cur_type->encode->to_xml = sdl_guess_convert_xml;
1398 		cur_type->encode->to_zval = sdl_guess_convert_zval;
1399 		zend_hash_next_index_insert_ptr(sdl->encoders, cur_type->encode);
1400 
1401 		cur_type = ptr;
1402 
1403 	} else if (name) {
1404 		sdlTypePtr newType, ptr;
1405 
1406 		newType = emalloc(sizeof(sdlType));
1407 		memset(newType, 0, sizeof(sdlType));
1408 		newType->kind = XSD_TYPEKIND_COMPLEX;
1409 		newType->name = estrdup((char*)name->children->content);
1410 		newType->namens = estrdup((char*)ns->children->content);
1411 
1412 		ptr = zend_hash_next_index_insert_ptr(sdl->types, newType);
1413 
1414 		cur_type = ptr;
1415 		create_encoder(sdl, cur_type, ns->children->content, name->children->content);
1416 	} else {
1417 		soap_error0(E_ERROR, "Parsing Schema: complexType has no 'name' attribute");
1418 		return FALSE;
1419 	}
1420 
1421 	trav = compType->children;
1422 	if (trav != NULL && node_is_equal(trav, "annotation")) {
1423 		/* TODO: <annotation> support */
1424 		trav = trav->next;
1425 	}
1426 	if (trav != NULL) {
1427 		if (node_is_equal(trav,"simpleContent")) {
1428 			schema_simpleContent(sdl, tns, trav, cur_type);
1429 			trav = trav->next;
1430 		} else if (node_is_equal(trav,"complexContent")) {
1431 			schema_complexContent(sdl, tns, trav, cur_type);
1432 			trav = trav->next;
1433 		} else {
1434 			if (node_is_equal(trav,"group")) {
1435 				schema_group(sdl, tns, trav, cur_type, NULL);
1436 				trav = trav->next;
1437 			} else if (node_is_equal(trav,"all")) {
1438 				schema_all(sdl, tns, trav, cur_type, NULL);
1439 				trav = trav->next;
1440 			} else if (node_is_equal(trav,"choice")) {
1441 				schema_choice(sdl, tns, trav, cur_type, NULL);
1442 				trav = trav->next;
1443 			} else if (node_is_equal(trav,"sequence")) {
1444 				schema_sequence(sdl, tns, trav, cur_type, NULL);
1445 				trav = trav->next;
1446 			}
1447 			while (trav != NULL) {
1448 				if (node_is_equal(trav,"attribute")) {
1449 					schema_attribute(sdl, tns, trav, cur_type, NULL);
1450 				} else if (node_is_equal(trav,"attributeGroup")) {
1451 					schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
1452 				} else if (node_is_equal(trav,"anyAttribute")) {
1453 					/* TODO: <anyAttribute> support */
1454 					trav = trav->next;
1455 					break;
1456 				} else {
1457 					soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexType", trav->name);
1458 				}
1459 				trav = trav->next;
1460 			}
1461 		}
1462 	}
1463 	if (trav != NULL) {
1464 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexType", trav->name);
1465 	}
1466 	return TRUE;
1467 }
1468 /*
1469 <element
1470   abstract = boolean : false
1471   block = (#all | List of (extension | restriction | substitution))
1472   default = string
1473   final = (#all | List of (extension | restriction))
1474   fixed = string
1475   form = (qualified | unqualified)
1476   id = ID
1477   maxOccurs = (nonNegativeInteger | unbounded)  : 1
1478   minOccurs = nonNegativeInteger : 1
1479   name = NCName
1480   nillable = boolean : false
1481   ref = QName
1482   substitutionGroup = QName
1483   type = QName
1484   {any attributes with non-schema namespace . . .}>
1485   Content: (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*))
1486 </element>
1487 */
schema_element(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr element,sdlTypePtr cur_type,sdlContentModelPtr model)1488 static int schema_element(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr element, sdlTypePtr cur_type, sdlContentModelPtr model)
1489 {
1490 	xmlNodePtr trav;
1491 	xmlAttrPtr attrs, attr, ns, name, type, ref = NULL;
1492 
1493 	attrs = element->properties;
1494 	ns = get_attribute(attrs, "targetNamespace");
1495 	if (ns == NULL) {
1496 		ns = tns;
1497 	}
1498 
1499 	name = get_attribute(attrs, "name");
1500 	if (name == NULL) {
1501 		name = ref = get_attribute(attrs, "ref");
1502 	}
1503 
1504 	if (name) {
1505 		HashTable *addHash;
1506 		sdlTypePtr newType;
1507 		smart_str key = {0};
1508 
1509 		newType = emalloc(sizeof(sdlType));
1510 		memset(newType, 0, sizeof(sdlType));
1511 
1512 		if (ref) {
1513 			smart_str nscat = {0};
1514 			char *type, *ns;
1515 			xmlNsPtr nsptr;
1516 
1517 			parse_namespace(ref->children->content, &type, &ns);
1518 			nsptr = xmlSearchNs(element->doc, element, BAD_CAST(ns));
1519 			if (nsptr != NULL) {
1520 				smart_str_appends(&nscat, (char*)nsptr->href);
1521 				newType->namens = estrdup((char*)nsptr->href);
1522 			} else {
1523 				xmlAttrPtr ns = get_attribute(attrs, "targetNamespace");
1524 				if (ns == NULL) {
1525 					ns = tns;
1526 				}
1527 				if (ns) {
1528 					smart_str_appends(&nscat, (char*)ns->children->content);
1529 				}
1530 			}
1531 			smart_str_appendc(&nscat, ':');
1532 			smart_str_appends(&nscat, type);
1533 			newType->name = estrdup(type);
1534 			smart_str_0(&nscat);
1535 			if (type) {efree(type);}
1536 			if (ns) {efree(ns);}
1537 			newType->ref = estrndup(ZSTR_VAL(nscat.s), ZSTR_LEN(nscat.s));
1538 			smart_str_free(&nscat);
1539 		} else {
1540 			newType->name = estrdup((char*)name->children->content);
1541 			newType->namens = estrdup((char*)ns->children->content);
1542 		}
1543 
1544 		newType->nillable = FALSE;
1545 
1546 		if (cur_type == NULL) {
1547 			if (sdl->elements == NULL) {
1548 				sdl->elements = emalloc(sizeof(HashTable));
1549 				zend_hash_init(sdl->elements, 0, NULL, delete_type, 0);
1550 			}
1551 			addHash = sdl->elements;
1552 			smart_str_appends(&key, newType->namens);
1553 			smart_str_appendc(&key, ':');
1554 			smart_str_appends(&key, newType->name);
1555 		} else {
1556 			if (cur_type->elements == NULL) {
1557 				cur_type->elements = emalloc(sizeof(HashTable));
1558 				zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
1559 			}
1560 			addHash = cur_type->elements;
1561 			smart_str_appends(&key, newType->name);
1562 		}
1563 
1564 		smart_str_0(&key);
1565 		if (zend_hash_add_ptr(addHash, key.s, newType) == NULL) {
1566 			if (cur_type == NULL) {
1567 				soap_error1(E_ERROR, "Parsing Schema: element '%s' already defined", ZSTR_VAL(key.s));
1568 			} else {
1569 				zend_hash_next_index_insert_ptr(addHash, newType);
1570 			}
1571 		}
1572 		smart_str_free(&key);
1573 
1574 		if (model != NULL) {
1575 			sdlContentModelPtr newModel = emalloc(sizeof(sdlContentModel));
1576 
1577 			newModel->kind = XSD_CONTENT_ELEMENT;
1578 			newModel->u.element = newType;
1579 
1580 			schema_min_max(element, newModel);
1581 
1582 
1583 			zend_hash_next_index_insert_ptr(model->u.content, newModel);
1584 		}
1585 		cur_type = newType;
1586 	} else {
1587 		soap_error0(E_ERROR, "Parsing Schema: element has no 'name' nor 'ref' attributes");
1588 	}
1589 
1590 	/* nillable = boolean : false */
1591 	attrs = element->properties;
1592 	attr = get_attribute(attrs, "nillable");
1593 	if (attr) {
1594 		if (ref != NULL) {
1595 			soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'nillable' attributes");
1596 		}
1597 		if (!stricmp((char*)attr->children->content, "true") ||
1598 			!stricmp((char*)attr->children->content, "1")) {
1599 			cur_type->nillable = TRUE;
1600 		} else {
1601 			cur_type->nillable = FALSE;
1602 		}
1603 	} else {
1604 		cur_type->nillable = FALSE;
1605 	}
1606 
1607 	attr = get_attribute(attrs, "fixed");
1608 	if (attr) {
1609 		if (ref != NULL) {
1610 			soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'fixed' attributes");
1611 		}
1612 		cur_type->fixed = estrdup((char*)attr->children->content);
1613 	}
1614 
1615 	attr = get_attribute(attrs, "default");
1616 	if (attr) {
1617 		if (ref != NULL) {
1618 			soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'fixed' attributes");
1619 		} else if (ref != NULL) {
1620 			soap_error0(E_ERROR, "Parsing Schema: element has both 'default' and 'fixed' attributes");
1621 		}
1622 		cur_type->def = estrdup((char*)attr->children->content);
1623 	}
1624 
1625 	/* form */
1626 	attr = get_attribute(attrs, "form");
1627 	if (attr) {
1628 		if (strncmp((char*)attr->children->content, "qualified", sizeof("qualified")) == 0) {
1629 		  cur_type->form = XSD_FORM_QUALIFIED;
1630 		} else if (strncmp((char*)attr->children->content, "unqualified", sizeof("unqualified")) == 0) {
1631 		  cur_type->form = XSD_FORM_UNQUALIFIED;
1632 		} else {
1633 		  cur_type->form = XSD_FORM_DEFAULT;
1634 		}
1635 	} else {
1636 	  cur_type->form = XSD_FORM_DEFAULT;
1637 	}
1638 	if (cur_type->form == XSD_FORM_DEFAULT) {
1639  		xmlNodePtr parent = element->parent;
1640  		while (parent) {
1641 			if (node_is_equal_ex(parent, "schema", SCHEMA_NAMESPACE)) {
1642 				xmlAttrPtr def;
1643 				def = get_attribute(parent->properties, "elementFormDefault");
1644 				if(def == NULL || strncmp((char*)def->children->content, "qualified", sizeof("qualified"))) {
1645 					cur_type->form = XSD_FORM_UNQUALIFIED;
1646 				} else {
1647 					cur_type->form = XSD_FORM_QUALIFIED;
1648 				}
1649 				break;
1650 			}
1651 			parent = parent->parent;
1652   	}
1653 		if (parent == NULL) {
1654 			cur_type->form = XSD_FORM_UNQUALIFIED;
1655 		}
1656 	}
1657 
1658 	/* type = QName */
1659 	type = get_attribute(attrs, "type");
1660 	if (type) {
1661 		char *cptype, *str_ns;
1662 		xmlNsPtr nsptr;
1663 
1664 		if (ref != NULL) {
1665 			soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'type' attributes");
1666 		}
1667 		parse_namespace(type->children->content, &cptype, &str_ns);
1668 		nsptr = xmlSearchNs(element->doc, element, BAD_CAST(str_ns));
1669 		if (nsptr != NULL) {
1670 			cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(cptype));
1671 		}
1672 		if (str_ns) {efree(str_ns);}
1673 		if (cptype) {efree(cptype);}
1674 	}
1675 
1676 	trav = element->children;
1677 	if (trav != NULL && node_is_equal(trav, "annotation")) {
1678 		/* TODO: <annotation> support */
1679 		trav = trav->next;
1680 	}
1681 	if (trav != NULL) {
1682 		if (node_is_equal(trav,"simpleType")) {
1683 			if (ref != NULL) {
1684 				soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' attribute and subtype");
1685 			} else if (type != NULL) {
1686 				soap_error0(E_ERROR, "Parsing Schema: element has both 'type' attribute and subtype");
1687 			}
1688 			schema_simpleType(sdl, tns, trav, cur_type);
1689 			trav = trav->next;
1690 		} else if (node_is_equal(trav,"complexType")) {
1691 			if (ref != NULL) {
1692 				soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' attribute and subtype");
1693 			} else if (type != NULL) {
1694 				soap_error0(E_ERROR, "Parsing Schema: element has both 'type' attribute and subtype");
1695 			}
1696 			schema_complexType(sdl, tns, trav, cur_type);
1697 			trav = trav->next;
1698 		}
1699 	}
1700 	while (trav != NULL) {
1701 		if (node_is_equal(trav,"unique")) {
1702 			/* TODO: <unique> support */
1703 		} else if (node_is_equal(trav,"key")) {
1704 			/* TODO: <key> support */
1705 		} else if (node_is_equal(trav,"keyref")) {
1706 			/* TODO: <keyref> support */
1707 		} else {
1708 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in element", trav->name);
1709 		}
1710 		trav = trav->next;
1711 	}
1712 
1713 	return TRUE;
1714 }
1715 
1716 /*
1717 <attribute
1718   default = string
1719   fixed = string
1720   form = (qualified | unqualified)
1721   id = ID
1722   name = NCName
1723   ref = QName
1724   type = QName
1725   use = (optional | prohibited | required) : optional
1726   {any attributes with non-schema namespace . . .}>
1727   Content: (annotation?, (simpleType?))
1728 </attribute>
1729 */
schema_attribute(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr attrType,sdlTypePtr cur_type,sdlCtx * ctx)1730 static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdlTypePtr cur_type, sdlCtx *ctx)
1731 {
1732 	sdlAttributePtr newAttr;
1733 	xmlAttrPtr attr, name, ref = NULL, type = NULL;
1734 	xmlNodePtr trav;
1735 
1736 	name = get_attribute(attrType->properties, "name");
1737 	if (name == NULL) {
1738 		name = ref = get_attribute(attrType->properties, "ref");
1739 	}
1740 	if (name) {
1741 		HashTable *addHash;
1742 		smart_str key = {0};
1743 
1744 		newAttr = emalloc(sizeof(sdlAttribute));
1745 		memset(newAttr, 0, sizeof(sdlAttribute));
1746 
1747 		if (ref) {
1748 			char *attr_name, *ns;
1749 			xmlNsPtr nsptr;
1750 
1751 			parse_namespace(ref->children->content, &attr_name, &ns);
1752 			nsptr = xmlSearchNs(attrType->doc, attrType, BAD_CAST(ns));
1753 			if (nsptr != NULL) {
1754 				smart_str_appends(&key, (char*)nsptr->href);
1755 				newAttr->namens = estrdup((char*)nsptr->href);
1756 			} else {
1757 				xmlAttrPtr ns = get_attribute(attrType->properties, "targetNamespace");
1758 				if (ns == NULL) {
1759 					ns = tns;
1760 				}
1761 				if (ns) {
1762 					smart_str_appends(&key, (char*)ns->children->content);
1763 				}
1764 			}
1765 			smart_str_appendc(&key, ':');
1766 			smart_str_appends(&key, attr_name);
1767 			smart_str_0(&key);
1768 			newAttr->ref = estrndup(ZSTR_VAL(key.s), ZSTR_LEN(key.s));
1769 			if (attr_name) {efree(attr_name);}
1770 			if (ns) {efree(ns);}
1771 		} else {
1772 			xmlAttrPtr ns;
1773 
1774 			ns = get_attribute(attrType->properties, "targetNamespace");
1775 			if (ns == NULL) {
1776 				ns = tns;
1777 			}
1778 			if (ns != NULL) {
1779 				smart_str_appends(&key, (char*)ns->children->content);
1780 				smart_str_appendc(&key, ':');
1781 				newAttr->namens = estrdup((char*)ns->children->content);
1782 			}
1783 			smart_str_appends(&key, (char*)name->children->content);
1784 			smart_str_0(&key);
1785 		}
1786 
1787 		if (cur_type == NULL) {
1788 			addHash = ctx->attributes;
1789 		} else {
1790 			if (cur_type->attributes == NULL) {
1791 				cur_type->attributes = emalloc(sizeof(HashTable));
1792 				zend_hash_init(cur_type->attributes, 0, NULL, delete_attribute, 0);
1793 			}
1794 			addHash = cur_type->attributes;
1795 		}
1796 
1797 		if (zend_hash_add_ptr(addHash, key.s, newAttr) == NULL) {
1798 			soap_error1(E_ERROR, "Parsing Schema: attribute '%s' already defined", ZSTR_VAL(key.s));
1799 		}
1800 		smart_str_free(&key);
1801 	} else{
1802 		soap_error0(E_ERROR, "Parsing Schema: attribute has no 'name' nor 'ref' attributes");
1803 	}
1804 
1805 	/* type = QName */
1806 	type = get_attribute(attrType->properties, "type");
1807 	if (type) {
1808 		char *cptype, *str_ns;
1809 		xmlNsPtr nsptr;
1810 
1811 		if (ref != NULL) {
1812 			soap_error0(E_ERROR, "Parsing Schema: attribute has both 'ref' and 'type' attributes");
1813 		}
1814 		parse_namespace(type->children->content, &cptype, &str_ns);
1815 		nsptr = xmlSearchNs(attrType->doc, attrType, BAD_CAST(str_ns));
1816 		if (nsptr != NULL) {
1817 			newAttr->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(cptype));
1818 		}
1819 		if (str_ns) {efree(str_ns);}
1820 		if (cptype) {efree(cptype);}
1821 	}
1822 
1823 	attr = attrType->properties;
1824 	while (attr != NULL) {
1825 		if (attr_is_equal_ex(attr, "default", SCHEMA_NAMESPACE)) {
1826 			newAttr->def = estrdup((char*)attr->children->content);
1827 		} else if (attr_is_equal_ex(attr, "fixed", SCHEMA_NAMESPACE)) {
1828 			newAttr->fixed = estrdup((char*)attr->children->content);
1829 		} else if (attr_is_equal_ex(attr, "form", SCHEMA_NAMESPACE)) {
1830 			if (strncmp((char*)attr->children->content, "qualified", sizeof("qualified")) == 0) {
1831 			  newAttr->form = XSD_FORM_QUALIFIED;
1832 			} else if (strncmp((char*)attr->children->content, "unqualified", sizeof("unqualified")) == 0) {
1833 			  newAttr->form = XSD_FORM_UNQUALIFIED;
1834 			} else {
1835 			  newAttr->form = XSD_FORM_DEFAULT;
1836 			}
1837 		} else if (attr_is_equal_ex(attr, "id", SCHEMA_NAMESPACE)) {
1838 			/* skip */
1839 		} else if (attr_is_equal_ex(attr, "name", SCHEMA_NAMESPACE)) {
1840 			newAttr->name = estrdup((char*)attr->children->content);
1841 		} else if (attr_is_equal_ex(attr, "ref", SCHEMA_NAMESPACE)) {
1842 			/* already processed */
1843 		} else if (attr_is_equal_ex(attr, "type", SCHEMA_NAMESPACE)) {
1844 			/* already processed */
1845 		} else if (attr_is_equal_ex(attr, "use", SCHEMA_NAMESPACE)) {
1846 			if (strncmp((char*)attr->children->content, "prohibited", sizeof("prohibited")) == 0) {
1847 			  newAttr->use = XSD_USE_PROHIBITED;
1848 			} else if (strncmp((char*)attr->children->content, "required", sizeof("required")) == 0) {
1849 			  newAttr->use = XSD_USE_REQUIRED;
1850 			} else if (strncmp((char*)attr->children->content, "optional", sizeof("optional")) == 0) {
1851 			  newAttr->use = XSD_USE_OPTIONAL;
1852 			} else {
1853 			  newAttr->use = XSD_USE_DEFAULT;
1854 			}
1855 		} else {
1856 			xmlNsPtr nsPtr = attr_find_ns(attr);
1857 
1858 			if (strncmp((char*)nsPtr->href, SCHEMA_NAMESPACE, sizeof(SCHEMA_NAMESPACE))) {
1859 				smart_str key2 = {0};
1860 				sdlExtraAttributePtr ext;
1861 				xmlNsPtr nsptr;
1862 				char *value, *ns;
1863 
1864 				ext = emalloc(sizeof(sdlExtraAttribute));
1865 				memset(ext, 0, sizeof(sdlExtraAttribute));
1866 				parse_namespace(attr->children->content, &value, &ns);
1867 				nsptr = xmlSearchNs(attr->doc, attr->parent, BAD_CAST(ns));
1868 				if (nsptr) {
1869 					ext->ns = estrdup((char*)nsptr->href);
1870 					ext->val = estrdup(value);
1871 				} else {
1872 					ext->val = estrdup((char*)attr->children->content);
1873 				}
1874 				if (ns) {efree(ns);}
1875 				efree(value);
1876 
1877 				if (!newAttr->extraAttributes) {
1878 					newAttr->extraAttributes = emalloc(sizeof(HashTable));
1879 					zend_hash_init(newAttr->extraAttributes, 0, NULL, delete_extra_attribute, 0);
1880 				}
1881 
1882 				smart_str_appends(&key2, (char*)nsPtr->href);
1883 				smart_str_appendc(&key2, ':');
1884 				smart_str_appends(&key2, (char*)attr->name);
1885 				smart_str_0(&key2);
1886 				zend_hash_add_ptr(newAttr->extraAttributes, key2.s, ext);
1887 				smart_str_free(&key2);
1888 			}
1889 		}
1890 		attr = attr->next;
1891 	}
1892 	if (newAttr->form == XSD_FORM_DEFAULT) {
1893  		xmlNodePtr parent = attrType->parent;
1894  		while (parent) {
1895 			if (node_is_equal_ex(parent, "schema", SCHEMA_NAMESPACE)) {
1896 				xmlAttrPtr def;
1897 				def = get_attribute(parent->properties, "attributeFormDefault");
1898 				if(def == NULL || strncmp((char*)def->children->content, "qualified", sizeof("qualified"))) {
1899 					newAttr->form = XSD_FORM_UNQUALIFIED;
1900 				} else {
1901 					newAttr->form = XSD_FORM_QUALIFIED;
1902 				}
1903 				break;
1904 			}
1905 			parent = parent->parent;
1906   	}
1907 		if (parent == NULL) {
1908 			newAttr->form = XSD_FORM_UNQUALIFIED;
1909 		}
1910 	}
1911 	trav = attrType->children;
1912 	if (trav != NULL && node_is_equal(trav, "annotation")) {
1913 		/* TODO: <annotation> support */
1914 		trav = trav->next;
1915 	}
1916 	if (trav != NULL) {
1917 		if (node_is_equal(trav,"simpleType")) {
1918 			sdlTypePtr dummy_type;
1919 			zval zv;
1920 
1921 			if (ref != NULL) {
1922 				soap_error0(E_ERROR, "Parsing Schema: attribute has both 'ref' attribute and subtype");
1923 			} else if (type != NULL) {
1924 				soap_error0(E_ERROR, "Parsing Schema: attribute has both 'type' attribute and subtype");
1925 			}
1926 			dummy_type = emalloc(sizeof(sdlType));
1927 			memset(dummy_type, 0, sizeof(sdlType));
1928 			{
1929 				char buf[MAX_LENGTH_OF_LONG + 1];
1930 				char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, zend_hash_num_elements(sdl->types));
1931 				char *str = emalloc(sizeof("anonymous") + buf + sizeof(buf) - 1 - res);
1932 
1933 				memcpy(str, "anonymous", sizeof("anonymous")-1);
1934 				memcpy(str + sizeof("anonymous")-1, res, buf + sizeof(buf) - res);
1935 				dummy_type->name = str;
1936 			}
1937 			dummy_type->namens = estrdup((char*)tns->children->content);
1938 			schema_simpleType(sdl, tns, trav, dummy_type);
1939 			newAttr->encode = dummy_type->encode;
1940 			ZVAL_PTR(&zv, dummy_type);
1941 			delete_type(&zv);
1942 			trav = trav->next;
1943 		}
1944 	}
1945 	if (trav != NULL) {
1946 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attribute", trav->name);
1947 	}
1948 	return TRUE;
1949 }
1950 
schema_attributeGroup(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr attrGroup,sdlTypePtr cur_type,sdlCtx * ctx)1951 static int schema_attributeGroup(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrGroup, sdlTypePtr cur_type, sdlCtx *ctx)
1952 {
1953 	xmlNodePtr trav;
1954 	xmlAttrPtr name, ref = NULL;
1955 
1956 
1957 	name = get_attribute(attrGroup->properties, "name");
1958 	if (name == NULL) {
1959 		name = ref = get_attribute(attrGroup->properties, "ref");
1960 	}
1961 	if (name) {
1962 		if (cur_type == NULL) {
1963 			xmlAttrPtr ns;
1964 			sdlTypePtr newType;
1965 			smart_str key = {0};
1966 
1967 			ns = get_attribute(attrGroup->properties, "targetNamespace");
1968 			if (ns == NULL) {
1969 				ns = tns;
1970 			}
1971 			newType = emalloc(sizeof(sdlType));
1972 			memset(newType, 0, sizeof(sdlType));
1973 			newType->name = estrdup((char*)name->children->content);
1974 			newType->namens = estrdup((char*)ns->children->content);
1975 
1976 			smart_str_appends(&key, newType->namens);
1977 			smart_str_appendc(&key, ':');
1978 			smart_str_appends(&key, newType->name);
1979 			smart_str_0(&key);
1980 
1981 			if (zend_hash_add_ptr(ctx->attributeGroups, key.s, newType) == NULL) {
1982 				soap_error1(E_ERROR, "Parsing Schema: attributeGroup '%s' already defined", ZSTR_VAL(key.s));
1983 			}
1984 			cur_type = newType;
1985 			smart_str_free(&key);
1986 		} else if (ref) {
1987 			sdlAttributePtr newAttr;
1988 			char *group_name, *ns;
1989 			smart_str key = {0};
1990 			xmlNsPtr nsptr;
1991 
1992 			if (cur_type->attributes == NULL) {
1993 				cur_type->attributes = emalloc(sizeof(HashTable));
1994 				zend_hash_init(cur_type->attributes, 0, NULL, delete_attribute, 0);
1995 			}
1996 			newAttr = emalloc(sizeof(sdlAttribute));
1997 			memset(newAttr, 0, sizeof(sdlAttribute));
1998 
1999 			parse_namespace(ref->children->content, &group_name, &ns);
2000 			nsptr = xmlSearchNs(attrGroup->doc, attrGroup, BAD_CAST(ns));
2001 			if (nsptr != NULL) {
2002 				smart_str_appends(&key, (char*)nsptr->href);
2003 			}
2004 			smart_str_appendc(&key, ':');
2005 			smart_str_appends(&key, group_name);
2006 			smart_str_0(&key);
2007 			newAttr->ref = estrndup(ZSTR_VAL(key.s), ZSTR_LEN(key.s));
2008 			if (group_name) {efree(group_name);}
2009 			if (ns) {efree(ns);}
2010 			smart_str_free(&key);
2011 
2012 			zend_hash_next_index_insert_ptr(cur_type->attributes, newAttr);
2013 			cur_type = NULL;
2014 		}
2015 	} else{
2016 		soap_error0(E_ERROR, "Parsing Schema: attributeGroup has no 'name' nor 'ref' attributes");
2017 	}
2018 
2019 	trav = attrGroup->children;
2020 	if (trav != NULL && node_is_equal(trav, "annotation")) {
2021 		/* TODO: <annotation> support */
2022 		trav = trav->next;
2023 	}
2024 	while (trav != NULL) {
2025 		if (node_is_equal(trav,"attribute")) {
2026 			if (ref != NULL) {
2027 				soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
2028 			}
2029 			schema_attribute(sdl, tns, trav, cur_type, NULL);
2030 		} else if (node_is_equal(trav,"attributeGroup")) {
2031 			if (ref != NULL) {
2032 				soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
2033 			}
2034 			schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
2035 		} else if (node_is_equal(trav,"anyAttribute")) {
2036 			if (ref != NULL) {
2037 				soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
2038 			}
2039 			/* TODO: <anyAttribute> support */
2040 			trav = trav->next;
2041 			break;
2042 		} else {
2043 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attributeGroup", trav->name);
2044 		}
2045 		trav = trav->next;
2046 	}
2047 	if (trav != NULL) {
2048 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attributeGroup", trav->name);
2049 	}
2050 	return TRUE;
2051 }
2052 
copy_extra_attribute(zval * zv)2053 static void copy_extra_attribute(zval *zv)
2054 {
2055 	sdlExtraAttributePtr new_attr;
2056 
2057 	new_attr = emalloc(sizeof(sdlExtraAttribute));
2058 	memcpy(new_attr, Z_PTR_P(zv), sizeof(sdlExtraAttribute));
2059 	Z_PTR_P(zv) = new_attr;
2060 	if (new_attr->ns) {
2061 		new_attr->ns = estrdup(new_attr->ns);
2062 	}
2063 	if (new_attr->val) {
2064 		new_attr->val = estrdup(new_attr->val);
2065 	}
2066 }
2067 
schema_find_by_ref(HashTable * ht,char * ref)2068 static void* schema_find_by_ref(HashTable *ht, char *ref)
2069 {
2070 	void *tmp;
2071 
2072 	if ((tmp = zend_hash_str_find_ptr(ht, ref, strlen(ref))) != NULL) {
2073 		return tmp;
2074 	} else {
2075 		ref = strrchr(ref, ':');
2076 		if (ref) {
2077 			if ((tmp = zend_hash_str_find_ptr(ht, ref, strlen(ref))) != NULL) {
2078 				return tmp;
2079 			}
2080 		}
2081 	}
2082 	return NULL;
2083 }
2084 
schema_attribute_fixup(sdlCtx * ctx,sdlAttributePtr attr)2085 static void schema_attribute_fixup(sdlCtx *ctx, sdlAttributePtr attr)
2086 {
2087 	sdlAttributePtr tmp;
2088 
2089 	if (attr->ref != NULL) {
2090 		if (ctx->attributes != NULL) {
2091 			tmp = (sdlAttributePtr)schema_find_by_ref(ctx->attributes, attr->ref);
2092 			if (tmp) {
2093 				schema_attribute_fixup(ctx, tmp);
2094 				if (tmp->name != NULL && attr->name == NULL) {
2095 					attr->name = estrdup(tmp->name);
2096 				}
2097 				if (tmp->namens != NULL && attr->namens == NULL) {
2098 					attr->namens = estrdup(tmp->namens);
2099 				}
2100 				if (tmp->def != NULL && attr->def == NULL) {
2101 					attr->def = estrdup(tmp->def);
2102 				}
2103 				if (tmp->fixed != NULL && attr->fixed == NULL) {
2104 					attr->fixed = estrdup(tmp->fixed);
2105 				}
2106 				if (attr->form == XSD_FORM_DEFAULT) {
2107 					attr->form = tmp->form;
2108 				}
2109 				if (attr->use == XSD_USE_DEFAULT) {
2110 					attr->use  = tmp->use;
2111 				}
2112 				if (tmp->extraAttributes != NULL) {
2113 					attr->extraAttributes = emalloc(sizeof(HashTable));
2114 					zend_hash_init(attr->extraAttributes, zend_hash_num_elements(tmp->extraAttributes), NULL, delete_extra_attribute, 0);
2115 					zend_hash_copy(attr->extraAttributes, tmp->extraAttributes, copy_extra_attribute);
2116 				}
2117 				attr->encode = tmp->encode;
2118 			}
2119 		}
2120 		if (attr->name == NULL && attr->ref != NULL) {
2121 			char *name = strrchr(attr->ref, ':');
2122 			if (name) {
2123 				attr->name = estrdup(name+1);
2124 			} else{
2125 				attr->name = estrdup(attr->ref);
2126 			}
2127 		}
2128 		efree(attr->ref);
2129 		attr->ref = NULL;
2130 	}
2131 }
2132 
schema_attributegroup_fixup(sdlCtx * ctx,sdlAttributePtr attr,HashTable * ht)2133 static void schema_attributegroup_fixup(sdlCtx *ctx, sdlAttributePtr attr, HashTable *ht)
2134 {
2135 	sdlTypePtr tmp;
2136 	sdlAttributePtr tmp_attr;
2137 
2138 	if (attr->ref != NULL) {
2139 		if (ctx->attributeGroups != NULL) {
2140 			tmp = (sdlTypePtr)schema_find_by_ref(ctx->attributeGroups, attr->ref);
2141 			if (tmp) {
2142 				if (tmp->attributes) {
2143 					zend_hash_internal_pointer_reset(tmp->attributes);
2144 					while ((tmp_attr = zend_hash_get_current_data_ptr(tmp->attributes)) != NULL) {
2145 						if (zend_hash_get_current_key_type(tmp->attributes) == HASH_KEY_IS_STRING) {
2146 							zend_string* _key;
2147 							sdlAttributePtr newAttr;
2148 
2149 							schema_attribute_fixup(ctx, tmp_attr);
2150 
2151 							newAttr = emalloc(sizeof(sdlAttribute));
2152 							memcpy(newAttr, tmp_attr, sizeof(sdlAttribute));
2153 							if (newAttr->def) {newAttr->def = estrdup(newAttr->def);}
2154 							if (newAttr->fixed) {newAttr->fixed = estrdup(newAttr->fixed);}
2155 							if (newAttr->namens) {newAttr->namens = estrdup(newAttr->namens);}
2156 							if (newAttr->name) {newAttr->name = estrdup(newAttr->name);}
2157 							if (newAttr->extraAttributes) {
2158 								HashTable *ht = emalloc(sizeof(HashTable));
2159 								zend_hash_init(ht, zend_hash_num_elements(newAttr->extraAttributes), NULL, delete_extra_attribute, 0);
2160 								zend_hash_copy(ht, newAttr->extraAttributes, copy_extra_attribute);
2161 								newAttr->extraAttributes = ht;
2162 							}
2163 
2164 							zend_hash_get_current_key(tmp->attributes, &_key, NULL);
2165 							zend_hash_add_ptr(ht, _key, newAttr);
2166 
2167 							zend_hash_move_forward(tmp->attributes);
2168 						} else {
2169 							zend_ulong index;
2170 
2171 							schema_attributegroup_fixup(ctx, tmp_attr, ht);
2172 							zend_hash_get_current_key(tmp->attributes, NULL, &index);
2173 							zend_hash_index_del(tmp->attributes, index);
2174 						}
2175 					}
2176 				}
2177 			}
2178 		}
2179 		efree(attr->ref);
2180 		attr->ref = NULL;
2181 	}
2182 }
2183 
schema_content_model_fixup(sdlCtx * ctx,sdlContentModelPtr model)2184 static void schema_content_model_fixup(sdlCtx *ctx, sdlContentModelPtr model)
2185 {
2186 	switch (model->kind) {
2187 		case XSD_CONTENT_GROUP_REF: {
2188 			sdlTypePtr tmp;
2189 
2190 			if (ctx->sdl->groups && (tmp = zend_hash_str_find_ptr(ctx->sdl->groups, model->u.group_ref, strlen(model->u.group_ref))) != NULL) {
2191 				schema_type_fixup(ctx, tmp);
2192 				efree(model->u.group_ref);
2193 				model->kind = XSD_CONTENT_GROUP;
2194 				model->u.group = tmp;
2195 			} else {
2196 				soap_error1(E_ERROR, "Parsing Schema: unresolved group 'ref' attribute '%s'", model->u.group_ref);
2197 			}
2198 			break;
2199 		}
2200 		case XSD_CONTENT_CHOICE: {
2201 			if (model->max_occurs != 1) {
2202 				sdlContentModelPtr tmp;
2203 
2204 				ZEND_HASH_FOREACH_PTR(model->u.content, tmp) {
2205 					tmp->min_occurs = 0;
2206 					tmp->max_occurs = model->max_occurs;
2207 				} ZEND_HASH_FOREACH_END();
2208 
2209 				model->kind = XSD_CONTENT_ALL;
2210 				model->min_occurs = 1;
2211 				model->max_occurs = 1;
2212 			}
2213 		}
2214 		case XSD_CONTENT_SEQUENCE:
2215 		case XSD_CONTENT_ALL: {
2216 			sdlContentModelPtr tmp;
2217 
2218 			ZEND_HASH_FOREACH_PTR(model->u.content, tmp) {
2219 				schema_content_model_fixup(ctx, tmp);
2220 			} ZEND_HASH_FOREACH_END();
2221 			break;
2222 		}
2223 		default:
2224 			break;
2225 	}
2226 }
2227 
schema_type_fixup(sdlCtx * ctx,sdlTypePtr type)2228 static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type)
2229 {
2230 	sdlTypePtr tmp;
2231 	sdlAttributePtr attr;
2232 
2233 	if (type->ref != NULL) {
2234 		if (ctx->sdl->elements != NULL) {
2235 			tmp = (sdlTypePtr)schema_find_by_ref(ctx->sdl->elements, type->ref);
2236 			if (tmp) {
2237 				type->kind = tmp->kind;
2238 				type->encode = tmp->encode;
2239 				if (tmp->nillable) {
2240 				  type->nillable = 1;
2241 				}
2242 				if (tmp->fixed) {
2243 				  type->fixed = estrdup(tmp->fixed);
2244 				}
2245 				if (tmp->def) {
2246 				  type->def = estrdup(tmp->def);
2247 				}
2248 				type->form = tmp->form;
2249 			} else if (strcmp(type->ref, SCHEMA_NAMESPACE ":schema") == 0) {
2250 				type->encode = get_conversion(XSD_ANYXML);
2251 			} else {
2252 				soap_error1(E_ERROR, "Parsing Schema: unresolved element 'ref' attribute '%s'", type->ref);
2253 			}
2254 		}
2255 		efree(type->ref);
2256 		type->ref = NULL;
2257 	}
2258 	if (type->elements) {
2259 		ZEND_HASH_FOREACH_PTR(type->elements, tmp) {
2260 			schema_type_fixup(ctx, tmp);
2261 		} ZEND_HASH_FOREACH_END();
2262 	}
2263 	if (type->model) {
2264 		schema_content_model_fixup(ctx, type->model);
2265 	}
2266 	if (type->attributes) {
2267 		zend_string *str_key;
2268 		zend_ulong index;
2269 
2270 		ZEND_HASH_FOREACH_KEY_PTR(type->attributes, index, str_key, attr) {
2271 			if (str_key) {
2272 				schema_attribute_fixup(ctx, attr);
2273 			} else {
2274 				schema_attributegroup_fixup(ctx, attr, type->attributes);
2275 				zend_hash_index_del(type->attributes, index);
2276 			}
2277 		} ZEND_HASH_FOREACH_END();
2278 	}
2279 }
2280 
schema_pass2(sdlCtx * ctx)2281 void schema_pass2(sdlCtx *ctx)
2282 {
2283 	sdlPtr sdl = ctx->sdl;
2284 	sdlAttributePtr attr;
2285 	sdlTypePtr type;
2286 
2287 	if (ctx->attributes) {
2288 		ZEND_HASH_FOREACH_PTR(ctx->attributes, attr) {
2289 			schema_attribute_fixup(ctx, attr);
2290 		} ZEND_HASH_FOREACH_END();
2291 	}
2292 	if (ctx->attributeGroups) {
2293 		ZEND_HASH_FOREACH_PTR(ctx->attributeGroups, type) {
2294 			schema_type_fixup(ctx, type);
2295 		} ZEND_HASH_FOREACH_END();
2296 	}
2297 	if (sdl->elements) {
2298 		ZEND_HASH_FOREACH_PTR(sdl->elements, type) {
2299 			schema_type_fixup(ctx, type);
2300 		} ZEND_HASH_FOREACH_END();
2301 	}
2302 	if (sdl->groups) {
2303 		ZEND_HASH_FOREACH_PTR(sdl->groups, type) {
2304 			schema_type_fixup(ctx, type);
2305 		} ZEND_HASH_FOREACH_END();
2306 	}
2307 	if (sdl->types) {
2308 		ZEND_HASH_FOREACH_PTR(sdl->types, type) {
2309 			schema_type_fixup(ctx, type);
2310 		} ZEND_HASH_FOREACH_END();
2311 	}
2312 	if (ctx->attributes) {
2313 		zend_hash_destroy(ctx->attributes);
2314 		efree(ctx->attributes);
2315 	}
2316 	if (ctx->attributeGroups) {
2317 		zend_hash_destroy(ctx->attributeGroups);
2318 		efree(ctx->attributeGroups);
2319 	}
2320 }
2321 
delete_model(zval * zv)2322 void delete_model(zval *zv)
2323 {
2324 	sdlContentModelPtr tmp = Z_PTR_P(zv);
2325 	switch (tmp->kind) {
2326 		case XSD_CONTENT_ELEMENT:
2327 		case XSD_CONTENT_GROUP:
2328 			break;
2329 		case XSD_CONTENT_SEQUENCE:
2330 		case XSD_CONTENT_ALL:
2331 		case XSD_CONTENT_CHOICE:
2332 			zend_hash_destroy(tmp->u.content);
2333 			efree(tmp->u.content);
2334 			break;
2335 		case XSD_CONTENT_GROUP_REF:
2336 			efree(tmp->u.group_ref);
2337 			break;
2338 		default:
2339 			break;
2340 	}
2341 	efree(tmp);
2342 }
2343 
delete_model_persistent_int(sdlContentModelPtr tmp)2344 static void delete_model_persistent_int(sdlContentModelPtr tmp)
2345 {
2346 	switch (tmp->kind) {
2347 		case XSD_CONTENT_ELEMENT:
2348 		case XSD_CONTENT_GROUP:
2349 			break;
2350 		case XSD_CONTENT_SEQUENCE:
2351 		case XSD_CONTENT_ALL:
2352 		case XSD_CONTENT_CHOICE:
2353 			zend_hash_destroy(tmp->u.content);
2354 			free(tmp->u.content);
2355 			break;
2356 		case XSD_CONTENT_GROUP_REF:
2357 			free(tmp->u.group_ref);
2358 			break;
2359 		default:
2360 			break;
2361 	}
2362 	free(tmp);
2363 }
2364 
delete_model_persistent(zval * zv)2365 void delete_model_persistent(zval *zv)
2366 {
2367 	delete_model_persistent_int(Z_PTR_P(zv));
2368 }
2369 
delete_type(zval * zv)2370 void delete_type(zval *zv)
2371 {
2372 	sdlTypePtr type = Z_PTR_P(zv);
2373 
2374 	if (type->name) {
2375 		efree(type->name);
2376 	}
2377 	if (type->namens) {
2378 		efree(type->namens);
2379 	}
2380 	if (type->def) {
2381 		efree(type->def);
2382 	}
2383 	if (type->fixed) {
2384 		efree(type->fixed);
2385 	}
2386 	if (type->elements) {
2387 		zend_hash_destroy(type->elements);
2388 		efree(type->elements);
2389 	}
2390 	if (type->attributes) {
2391 		zend_hash_destroy(type->attributes);
2392 		efree(type->attributes);
2393 	}
2394 	if (type->model) {
2395 		zval zv;
2396 		ZVAL_PTR(&zv, type->model);
2397 		delete_model(&zv);
2398 	}
2399 	if (type->restrictions) {
2400 		delete_restriction_var_int(type->restrictions->minExclusive);
2401 		delete_restriction_var_int(type->restrictions->minInclusive);
2402 		delete_restriction_var_int(type->restrictions->maxExclusive);
2403 		delete_restriction_var_int(type->restrictions->maxInclusive);
2404 		delete_restriction_var_int(type->restrictions->totalDigits);
2405 		delete_restriction_var_int(type->restrictions->fractionDigits);
2406 		delete_restriction_var_int(type->restrictions->length);
2407 		delete_restriction_var_int(type->restrictions->minLength);
2408 		delete_restriction_var_int(type->restrictions->maxLength);
2409 		delete_restriction_var_char_int(type->restrictions->whiteSpace);
2410 		delete_restriction_var_char_int(type->restrictions->pattern);
2411 		if (type->restrictions->enumeration) {
2412 			zend_hash_destroy(type->restrictions->enumeration);
2413 			efree(type->restrictions->enumeration);
2414 		}
2415 		efree(type->restrictions);
2416 	}
2417 	efree(type);
2418 }
2419 
delete_type_persistent(zval * zv)2420 void delete_type_persistent(zval *zv)
2421 {
2422 	sdlTypePtr type = Z_PTR_P(zv);
2423 	if (type->name) {
2424 		free(type->name);
2425 	}
2426 	if (type->namens) {
2427 		free(type->namens);
2428 	}
2429 	if (type->def) {
2430 		free(type->def);
2431 	}
2432 	if (type->fixed) {
2433 		free(type->fixed);
2434 	}
2435 	if (type->elements) {
2436 		zend_hash_destroy(type->elements);
2437 		free(type->elements);
2438 	}
2439 	if (type->attributes) {
2440 		zend_hash_destroy(type->attributes);
2441 		free(type->attributes);
2442 	}
2443 	if (type->model) {
2444 		delete_model_persistent_int(type->model);
2445 	}
2446 	if (type->restrictions) {
2447 		delete_restriction_var_int_persistent(type->restrictions->minExclusive);
2448 		delete_restriction_var_int_persistent(type->restrictions->minInclusive);
2449 		delete_restriction_var_int_persistent(type->restrictions->maxExclusive);
2450 		delete_restriction_var_int_persistent(type->restrictions->maxInclusive);
2451 		delete_restriction_var_int_persistent(type->restrictions->totalDigits);
2452 		delete_restriction_var_int_persistent(type->restrictions->fractionDigits);
2453 		delete_restriction_var_int_persistent(type->restrictions->length);
2454 		delete_restriction_var_int_persistent(type->restrictions->minLength);
2455 		delete_restriction_var_int_persistent(type->restrictions->maxLength);
2456 		delete_restriction_var_char_persistent_int(type->restrictions->whiteSpace);
2457 		delete_restriction_var_char_persistent_int(type->restrictions->pattern);
2458 		if (type->restrictions->enumeration) {
2459 			zend_hash_destroy(type->restrictions->enumeration);
2460 			free(type->restrictions->enumeration);
2461 		}
2462 		free(type->restrictions);
2463 	}
2464 	free(type);
2465 }
2466 
delete_extra_attribute(zval * zv)2467 void delete_extra_attribute(zval *zv)
2468 {
2469 	sdlExtraAttributePtr attr = Z_PTR_P(zv);
2470 
2471 	if (attr->ns) {
2472 		efree(attr->ns);
2473 	}
2474 	if (attr->val) {
2475 		efree(attr->val);
2476 	}
2477 	efree(attr);
2478 }
2479 
delete_extra_attribute_persistent(zval * zv)2480 void delete_extra_attribute_persistent(zval *zv)
2481 {
2482 	sdlExtraAttributePtr attr = Z_PTR_P(zv);
2483 
2484 	if (attr->ns) {
2485 		free(attr->ns);
2486 	}
2487 	if (attr->val) {
2488 		free(attr->val);
2489 	}
2490 	free(attr);
2491 }
2492 
delete_attribute(zval * zv)2493 void delete_attribute(zval *zv)
2494 {
2495 	sdlAttributePtr attr = Z_PTR_P(zv);
2496 
2497 	if (attr->def) {
2498 		efree(attr->def);
2499 	}
2500 	if (attr->fixed) {
2501 		efree(attr->fixed);
2502 	}
2503 	if (attr->name) {
2504 		efree(attr->name);
2505 	}
2506 	if (attr->namens) {
2507 		efree(attr->namens);
2508 	}
2509 	if (attr->ref) {
2510 		efree(attr->ref);
2511 	}
2512 	if (attr->extraAttributes) {
2513 		zend_hash_destroy(attr->extraAttributes);
2514 		efree(attr->extraAttributes);
2515 	}
2516 	efree(attr);
2517 }
2518 
delete_attribute_persistent(zval * zv)2519 void delete_attribute_persistent(zval *zv)
2520 {
2521 	sdlAttributePtr attr = Z_PTR_P(zv);
2522 
2523 	if (attr->def) {
2524 		free(attr->def);
2525 	}
2526 	if (attr->fixed) {
2527 		free(attr->fixed);
2528 	}
2529 	if (attr->name) {
2530 		free(attr->name);
2531 	}
2532 	if (attr->namens) {
2533 		free(attr->namens);
2534 	}
2535 	if (attr->ref) {
2536 		free(attr->ref);
2537 	}
2538 	if (attr->extraAttributes) {
2539 		zend_hash_destroy(attr->extraAttributes);
2540 		free(attr->extraAttributes);
2541 	}
2542 	free(attr);
2543 }
2544 
delete_restriction_var_int(sdlRestrictionIntPtr ptr)2545 void delete_restriction_var_int(sdlRestrictionIntPtr ptr)
2546 {
2547 	if (ptr) {
2548 		efree(ptr);
2549 	}
2550 }
2551 
delete_restriction_var_int_persistent(sdlRestrictionIntPtr ptr)2552 void delete_restriction_var_int_persistent(sdlRestrictionIntPtr ptr)
2553 {
2554 	if (ptr) {
2555 		free(ptr);
2556 	}
2557 }
2558 
delete_restriction_var_char_int(sdlRestrictionCharPtr ptr)2559 void delete_restriction_var_char_int(sdlRestrictionCharPtr ptr)
2560 {
2561 	if (ptr) {
2562 		if (ptr->value) {
2563 			efree(ptr->value);
2564 		}
2565 		efree(ptr);
2566 	}
2567 }
2568 
delete_restriction_var_char(zval * zv)2569 void delete_restriction_var_char(zval *zv)
2570 {
2571 	delete_restriction_var_char_int(Z_PTR_P(zv));
2572 }
2573 
delete_restriction_var_char_persistent_int(sdlRestrictionCharPtr ptr)2574 void delete_restriction_var_char_persistent_int(sdlRestrictionCharPtr ptr)
2575 {
2576 	if (ptr) {
2577 		if (ptr->value) {
2578 			free(ptr->value);
2579 		}
2580 		free(ptr);
2581 	}
2582 }
2583 
delete_restriction_var_char_persistent(zval * zv)2584 void delete_restriction_var_char_persistent(zval *zv)
2585 {
2586 	delete_restriction_var_char_persistent_int(Z_PTR_P(zv));
2587 }
2588