xref: /PHP-5.3/ext/soap/php_schema.c (revision a2045ff3)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2013 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 (zend_hash_find(sdl->encoders, nscat.c, nscat.len + 1, (void**)&enc_ptr) == SUCCESS) {
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(sdl->encoders, nscat.c, nscat.len + 1, &enc, sizeof(encodePtr), NULL);
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 TSRMLS_DC)98 static void schema_load_file(sdlCtx *ctx, xmlAttrPtr ns, xmlChar *location, xmlAttrPtr tns, int import TSRMLS_DC) {
99 	if (location != NULL &&
100 	    !zend_hash_exists(&ctx->docs, (char*)location, xmlStrlen(location)+1)) {
101 		xmlDocPtr doc;
102 		xmlNodePtr schema;
103 		xmlAttrPtr new_tns;
104 
105 		sdl_set_uri_credentials(ctx, (char*)location TSRMLS_CC);
106 		doc = soap_xmlParseFile((char*)location TSRMLS_CC);
107 		sdl_restore_uri_credentials(ctx TSRMLS_CC);
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_add(&ctx->docs, (char*)location, xmlStrlen(location)+1, (void**)&doc, sizeof(xmlDocPtr), NULL);
139 		load_schema(ctx, schema TSRMLS_CC);
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 TSRMLS_DC)163 int load_schema(sdlCtx *ctx, xmlNodePtr schema TSRMLS_DC)
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 TSRMLS_CC);
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 TSRMLS_CC);
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 TSRMLS_CC);
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 		zend_hash_next_index_insert(sdl->types,  &newType, sizeof(sdlTypePtr), (void **)&ptr);
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(sdl->encoders,  &cur_type->encode, sizeof(encodePtr), NULL);
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 			zend_hash_next_index_insert(sdl->types,  &newType, sizeof(sdlTypePtr), (void **)&ptr);
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 			zend_hash_update(cur_type->elements, newType->name, strlen(newType->name)+1, &newType, sizeof(sdlTypePtr), (void **)&ptr);
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, *tmp;
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(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);
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, *tmp;
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 			smart_str anonymous = {0};
461 
462 			smart_str_appendl(&anonymous, "anonymous", sizeof("anonymous")-1);
463 			smart_str_append_long(&anonymous, zend_hash_num_elements(sdl->types));
464 			smart_str_0(&anonymous);
465 			newType->name = anonymous.c;
466 		}
467 		newType->namens = estrdup((char*)tns->children->content);
468 
469 		if (cur_type->elements == NULL) {
470 			cur_type->elements = emalloc(sizeof(HashTable));
471 			zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
472 		}
473 		zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);
474 
475 		schema_simpleType(sdl, tns, trav, newType);
476 
477 		trav = trav->next;
478 	}
479 	if (trav != NULL) {
480 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in list", trav->name);
481 	}
482 	return TRUE;
483 }
484 
485 /*
486 <union
487   id = ID
488   memberTypes = List of QName
489   {any attributes with non-schema namespace . . .}>
490   Content: (annotation?, (simpleType*))
491 </union>
492 */
schema_union(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr unionType,sdlTypePtr cur_type)493 static int schema_union(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr unionType, sdlTypePtr cur_type)
494 {
495 	xmlNodePtr trav;
496 	xmlAttrPtr memberTypes;
497 
498 	memberTypes = get_attribute(unionType->properties, "memberTypes");
499 	if (memberTypes != NULL) {
500 		char *str, *start, *end, *next;
501 		char *type, *ns;
502 		xmlNsPtr nsptr;
503 
504 		str = estrdup((char*)memberTypes->children->content);
505 		whiteSpace_collapse(BAD_CAST(str));
506 		start = str;
507 		while (start != NULL && *start != '\0') {
508 			end = strchr(start,' ');
509 			if (end == NULL) {
510 				next = NULL;
511 			} else {
512 				*end = '\0';
513 				next = end+1;
514 			}
515 
516 			parse_namespace(BAD_CAST(start), &type, &ns);
517 			nsptr = xmlSearchNs(unionType->doc, unionType, BAD_CAST(ns));
518 			if (nsptr != NULL) {
519 				sdlTypePtr newType, *tmp;
520 
521 				newType = emalloc(sizeof(sdlType));
522 				memset(newType, 0, sizeof(sdlType));
523 
524 				newType->name = estrdup(type);
525 				newType->namens = estrdup((char*)nsptr->href);
526 
527 				newType->encode = get_create_encoder(sdl, newType, nsptr->href, BAD_CAST(type));
528 
529 				if (cur_type->elements == NULL) {
530 					cur_type->elements = emalloc(sizeof(HashTable));
531 					zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
532 				}
533 				zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);
534 			}
535 			if (type) {efree(type);}
536 			if (ns) {efree(ns);}
537 
538 			start = next;
539 		}
540 		efree(str);
541 	}
542 
543 	trav = unionType->children;
544 	if (trav != NULL && node_is_equal(trav,"annotation")) {
545 		/* TODO: <annotation> support */
546 		trav = trav->next;
547 	}
548 	while (trav != NULL) {
549 		if (node_is_equal(trav,"simpleType")) {
550 			sdlTypePtr newType, *tmp;
551 
552 			newType = emalloc(sizeof(sdlType));
553 			memset(newType, 0, sizeof(sdlType));
554 
555 			{
556 				smart_str anonymous = {0};
557 
558 				smart_str_appendl(&anonymous, "anonymous", sizeof("anonymous")-1);
559 				smart_str_append_long(&anonymous, zend_hash_num_elements(sdl->types));
560 				smart_str_0(&anonymous);
561 				newType->name = anonymous.c;
562 			}
563 			newType->namens = estrdup((char*)tns->children->content);
564 
565 			if (cur_type->elements == NULL) {
566 				cur_type->elements = emalloc(sizeof(HashTable));
567 				zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
568 			}
569 			zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);
570 
571 			schema_simpleType(sdl, tns, trav, newType);
572 
573 		} else {
574 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in union", trav->name);
575 		}
576 		trav = trav->next;
577 	}
578 	if (trav != NULL) {
579 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in union", trav->name);
580 	}
581 	return TRUE;
582 }
583 
584 /*
585 <simpleContent
586   id = ID
587   {any attributes with non-schema namespace . . .}>
588   Content: (annotation?, (restriction | extension))
589 </simpleContent>
590 */
schema_simpleContent(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr simpCompType,sdlTypePtr cur_type)591 static int schema_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr simpCompType, sdlTypePtr cur_type)
592 {
593 	xmlNodePtr trav;
594 
595 	trav = simpCompType->children;
596 	if (trav != NULL && node_is_equal(trav,"annotation")) {
597 		/* TODO: <annotation> support */
598 		trav = trav->next;
599 	}
600 	if (trav != NULL) {
601 		if (node_is_equal(trav, "restriction")) {
602 			cur_type->kind = XSD_TYPEKIND_RESTRICTION;
603 			schema_restriction_simpleContent(sdl, tns, trav, cur_type, 0);
604 			trav = trav->next;
605 		} else if (node_is_equal(trav, "extension")) {
606 			cur_type->kind = XSD_TYPEKIND_EXTENSION;
607 			schema_extension_simpleContent(sdl, tns, trav, cur_type);
608 			trav = trav->next;
609 		} else {
610 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in simpleContent", trav->name);
611 		}
612 	} else {
613 		soap_error0(E_ERROR, "Parsing Schema: expected <restriction> or <extension> in simpleContent");
614 	}
615 	if (trav != NULL) {
616 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in simpleContent", trav->name);
617 	}
618 
619 	return TRUE;
620 }
621 
622 /*
623 simpleType:<restriction
624   base = QName
625   id = ID
626   {any attributes with non-schema namespace . . .}>
627   Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)?)
628 </restriction>
629 simpleContent:<restriction
630   base = QName
631   id = ID
632   {any attributes with non-schema namespace . . .}>
633   Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))
634 </restriction>
635 */
schema_restriction_simpleContent(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr restType,sdlTypePtr cur_type,int simpleType)636 static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr restType, sdlTypePtr cur_type, int simpleType)
637 {
638 	xmlNodePtr trav;
639 	xmlAttrPtr base;
640 
641 	base = get_attribute(restType->properties, "base");
642 	if (base != NULL) {
643 		char *type, *ns;
644 		xmlNsPtr nsptr;
645 
646 		parse_namespace(base->children->content, &type, &ns);
647 		nsptr = xmlSearchNs(restType->doc, restType, BAD_CAST(ns));
648 		if (nsptr != NULL) {
649 			cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(type));
650 		}
651 		if (type) {efree(type);}
652 		if (ns) {efree(ns);}
653 	} else if (!simpleType) {
654 		soap_error0(E_ERROR, "Parsing Schema: restriction has no 'base' attribute");
655 	}
656 
657 	if (cur_type->restrictions == NULL) {
658 		cur_type->restrictions = emalloc(sizeof(sdlRestrictions));
659 		memset(cur_type->restrictions, 0, sizeof(sdlRestrictions));
660 	}
661 
662 	trav = restType->children;
663 	if (trav != NULL && node_is_equal(trav, "annotation")) {
664 		/* TODO: <annotation> support */
665 		trav = trav->next;
666 	}
667 	if (trav != NULL && node_is_equal(trav, "simpleType")) {
668 		schema_simpleType(sdl, tns, trav, cur_type);
669 		trav = trav->next;
670 	}
671 	while (trav != NULL) {
672 		if (node_is_equal(trav, "minExclusive")) {
673 			schema_restriction_var_int(trav, &cur_type->restrictions->minExclusive);
674 		} else if (node_is_equal(trav, "minInclusive")) {
675 			schema_restriction_var_int(trav, &cur_type->restrictions->minInclusive);
676 		} else if (node_is_equal(trav, "maxExclusive")) {
677 			schema_restriction_var_int(trav, &cur_type->restrictions->maxExclusive);
678 		} else if (node_is_equal(trav, "maxInclusive")) {
679 			schema_restriction_var_int(trav, &cur_type->restrictions->maxInclusive);
680 		} else if (node_is_equal(trav, "totalDigits")) {
681 			schema_restriction_var_int(trav, &cur_type->restrictions->totalDigits);
682 		} else if (node_is_equal(trav, "fractionDigits")) {
683 			schema_restriction_var_int(trav, &cur_type->restrictions->fractionDigits);
684 		} else if (node_is_equal(trav, "length")) {
685 			schema_restriction_var_int(trav, &cur_type->restrictions->length);
686 		} else if (node_is_equal(trav, "minLength")) {
687 			schema_restriction_var_int(trav, &cur_type->restrictions->minLength);
688 		} else if (node_is_equal(trav, "maxLength")) {
689 			schema_restriction_var_int(trav, &cur_type->restrictions->maxLength);
690 		} else if (node_is_equal(trav, "whiteSpace")) {
691 			schema_restriction_var_char(trav, &cur_type->restrictions->whiteSpace);
692 		} else if (node_is_equal(trav, "pattern")) {
693 			schema_restriction_var_char(trav, &cur_type->restrictions->pattern);
694 		} else if (node_is_equal(trav, "enumeration")) {
695 			sdlRestrictionCharPtr enumval = NULL;
696 
697 			schema_restriction_var_char(trav, &enumval);
698 			if (cur_type->restrictions->enumeration == NULL) {
699 				cur_type->restrictions->enumeration = emalloc(sizeof(HashTable));
700 				zend_hash_init(cur_type->restrictions->enumeration, 0, NULL, delete_restriction_var_char, 0);
701 			}
702 			if (zend_hash_add(cur_type->restrictions->enumeration, enumval->value, strlen(enumval->value)+1, &enumval, sizeof(sdlRestrictionCharPtr), NULL) == FAILURE) {
703 				delete_restriction_var_char(&enumval);
704 			}
705 		} else {
706 			break;
707 		}
708 		trav = trav->next;
709 	}
710 	if (!simpleType) {
711 		while (trav != NULL) {
712 			if (node_is_equal(trav,"attribute")) {
713 				schema_attribute(sdl, tns, trav, cur_type, NULL);
714 			} else if (node_is_equal(trav,"attributeGroup")) {
715 				schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
716 			} else if (node_is_equal(trav,"anyAttribute")) {
717 				/* TODO: <anyAttribute> support */
718 				trav = trav->next;
719 				break;
720 			} else {
721 				soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in restriction", trav->name);
722 			}
723 			trav = trav->next;
724 		}
725 	}
726 	if (trav != NULL) {
727 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in restriction", trav->name);
728 	}
729 
730 	return TRUE;
731 }
732 
733 /*
734 <restriction
735   base = QName
736   id = ID
737   {any attributes with non-schema namespace . . .}>
738   Content: (annotation?, (group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?))
739 </restriction>
740 */
schema_restriction_complexContent(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr restType,sdlTypePtr cur_type)741 static int schema_restriction_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr restType, sdlTypePtr cur_type)
742 {
743 	xmlAttrPtr base;
744 	xmlNodePtr trav;
745 
746 	base = get_attribute(restType->properties, "base");
747 	if (base != NULL) {
748 		char *type, *ns;
749 		xmlNsPtr nsptr;
750 
751 		parse_namespace(base->children->content, &type, &ns);
752 		nsptr = xmlSearchNs(restType->doc, restType, BAD_CAST(ns));
753 		if (nsptr != NULL) {
754 			cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(type));
755 		}
756 		if (type) {efree(type);}
757 		if (ns) {efree(ns);}
758 	} else {
759 		soap_error0(E_ERROR, "Parsing Schema: restriction has no 'base' attribute");
760 	}
761 
762 	trav = restType->children;
763 	if (trav != NULL && node_is_equal(trav,"annotation")) {
764 		/* TODO: <annotation> support */
765 		trav = trav->next;
766 	}
767 	if (trav != NULL) {
768 		if (node_is_equal(trav,"group")) {
769 			schema_group(sdl, tns, trav, cur_type, NULL);
770 			trav = trav->next;
771 		} else if (node_is_equal(trav,"all")) {
772 			schema_all(sdl, tns, trav, cur_type, NULL);
773 			trav = trav->next;
774 		} else if (node_is_equal(trav,"choice")) {
775 			schema_choice(sdl, tns, trav, cur_type, NULL);
776 			trav = trav->next;
777 		} else if (node_is_equal(trav,"sequence")) {
778 			schema_sequence(sdl, tns, trav, cur_type, NULL);
779 			trav = trav->next;
780 		}
781 	}
782 	while (trav != NULL) {
783 		if (node_is_equal(trav,"attribute")) {
784 			schema_attribute(sdl, tns, trav, cur_type, NULL);
785 		} else if (node_is_equal(trav,"attributeGroup")) {
786 			schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
787 		} else if (node_is_equal(trav,"anyAttribute")) {
788 			/* TODO: <anyAttribute> support */
789 			trav = trav->next;
790 			break;
791 		} else {
792 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in restriction", trav->name);
793 		}
794 		trav = trav->next;
795 	}
796 	if (trav != NULL) {
797 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in restriction", trav->name);
798 	}
799 
800 	return TRUE;
801 }
802 
schema_restriction_var_int(xmlNodePtr val,sdlRestrictionIntPtr * valptr)803 static int schema_restriction_var_int(xmlNodePtr val, sdlRestrictionIntPtr *valptr)
804 {
805 	xmlAttrPtr fixed, value;
806 
807 	if ((*valptr) == NULL) {
808 		(*valptr) = emalloc(sizeof(sdlRestrictionInt));
809 	}
810 	memset((*valptr), 0, sizeof(sdlRestrictionInt));
811 
812 	fixed = get_attribute(val->properties, "fixed");
813 	(*valptr)->fixed = FALSE;
814 	if (fixed != NULL) {
815 		if (!strncmp((char*)fixed->children->content, "true", sizeof("true")) ||
816 			!strncmp((char*)fixed->children->content, "1", sizeof("1")))
817 			(*valptr)->fixed = TRUE;
818 	}
819 
820 	value = get_attribute(val->properties, "value");
821 	if (value == NULL) {
822 		soap_error0(E_ERROR, "Parsing Schema: missing restriction value");
823 	}
824 
825 	(*valptr)->value = atoi((char*)value->children->content);
826 
827 	return TRUE;
828 }
829 
schema_restriction_var_char(xmlNodePtr val,sdlRestrictionCharPtr * valptr)830 static int schema_restriction_var_char(xmlNodePtr val, sdlRestrictionCharPtr *valptr)
831 {
832 	xmlAttrPtr fixed, value;
833 
834 	if ((*valptr) == NULL) {
835 		(*valptr) = emalloc(sizeof(sdlRestrictionChar));
836 	}
837 	memset((*valptr), 0, sizeof(sdlRestrictionChar));
838 
839 	fixed = get_attribute(val->properties, "fixed");
840 	(*valptr)->fixed = FALSE;
841 	if (fixed != NULL) {
842 		if (!strncmp((char*)fixed->children->content, "true", sizeof("true")) ||
843 		    !strncmp((char*)fixed->children->content, "1", sizeof("1"))) {
844 			(*valptr)->fixed = TRUE;
845 		}
846 	}
847 
848 	value = get_attribute(val->properties, "value");
849 	if (value == NULL) {
850 		soap_error0(E_ERROR, "Parsing Schema: missing restriction value");
851 	}
852 
853 	(*valptr)->value = estrdup((char*)value->children->content);
854 	return TRUE;
855 }
856 
857 /*
858 From simpleContent (not supported):
859 <extension
860   base = QName
861   id = ID
862   {any attributes with non-schema namespace . . .}>
863   Content: (annotation?, ((attribute | attributeGroup)*, anyAttribute?))
864 </extension>
865 */
schema_extension_simpleContent(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr extType,sdlTypePtr cur_type)866 static int schema_extension_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type)
867 {
868 	xmlNodePtr trav;
869 	xmlAttrPtr base;
870 
871 	base = get_attribute(extType->properties, "base");
872 	if (base != NULL) {
873 		char *type, *ns;
874 		xmlNsPtr nsptr;
875 
876 		parse_namespace(base->children->content, &type, &ns);
877 		nsptr = xmlSearchNs(extType->doc, extType, BAD_CAST(ns));
878 		if (nsptr != NULL) {
879 			cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(type));
880 		}
881 		if (type) {efree(type);}
882 		if (ns) {efree(ns);}
883 	} else {
884 		soap_error0(E_ERROR, "Parsing Schema: extension has no 'base' attribute");
885 	}
886 
887 	trav = extType->children;
888 	if (trav != NULL && node_is_equal(trav,"annotation")) {
889 		/* TODO: <annotation> support */
890 		trav = trav->next;
891 	}
892 	while (trav != NULL) {
893 		if (node_is_equal(trav,"attribute")) {
894 			schema_attribute(sdl, tns, trav, cur_type, NULL);
895 		} else if (node_is_equal(trav,"attributeGroup")) {
896 			schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
897 		} else if (node_is_equal(trav,"anyAttribute")) {
898 			/* TODO: <anyAttribute> support */
899 			trav = trav->next;
900 			break;
901 		} else {
902 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in extension", trav->name);
903 		}
904 		trav = trav->next;
905 	}
906 	if (trav != NULL) {
907 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in extension", trav->name);
908 	}
909 	return TRUE;
910 }
911 
912 /*
913 From complexContent:
914 <extension
915   base = QName
916   id = ID
917   {any attributes with non-schema namespace . . .}>
918   Content: (annotation?, ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?)))
919 </extension>
920 */
schema_extension_complexContent(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr extType,sdlTypePtr cur_type)921 static int schema_extension_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type)
922 {
923 	xmlNodePtr trav;
924 	xmlAttrPtr base;
925 
926 	base = get_attribute(extType->properties, "base");
927 	if (base != NULL) {
928 		char *type, *ns;
929 		xmlNsPtr nsptr;
930 
931 		parse_namespace(base->children->content, &type, &ns);
932 		nsptr = xmlSearchNs(extType->doc, extType, BAD_CAST(ns));
933 		if (nsptr != NULL) {
934 			cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(type));
935 		}
936 		if (type) {efree(type);}
937 		if (ns) {efree(ns);}
938 	} else {
939 		soap_error0(E_ERROR, "Parsing Schema: extension has no 'base' attribute");
940 	}
941 
942 	trav = extType->children;
943 	if (trav != NULL && node_is_equal(trav,"annotation")) {
944 		/* TODO: <annotation> support */
945 		trav = trav->next;
946 	}
947 	if (trav != NULL) {
948 		if (node_is_equal(trav,"group")) {
949 			schema_group(sdl, tns, trav, cur_type, NULL);
950 			trav = trav->next;
951 		} else if (node_is_equal(trav,"all")) {
952 			schema_all(sdl, tns, trav, cur_type, NULL);
953 			trav = trav->next;
954 		} else if (node_is_equal(trav,"choice")) {
955 			schema_choice(sdl, tns, trav, cur_type, NULL);
956 			trav = trav->next;
957 		} else if (node_is_equal(trav,"sequence")) {
958 			schema_sequence(sdl, tns, trav, cur_type, NULL);
959 			trav = trav->next;
960 		}
961 	}
962 	while (trav != NULL) {
963 		if (node_is_equal(trav,"attribute")) {
964 			schema_attribute(sdl, tns, trav, cur_type, NULL);
965 		} else if (node_is_equal(trav,"attributeGroup")) {
966 			schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
967 		} else if (node_is_equal(trav,"anyAttribute")) {
968 			/* TODO: <anyAttribute> support */
969 			trav = trav->next;
970 			break;
971 		} else {
972 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in extension", trav->name);
973 		}
974 		trav = trav->next;
975 	}
976 	if (trav != NULL) {
977 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in extension", trav->name);
978 	}
979 	return TRUE;
980 }
981 
schema_min_max(xmlNodePtr node,sdlContentModelPtr model)982 void schema_min_max(xmlNodePtr node, sdlContentModelPtr model)
983 {
984 	xmlAttrPtr attr = get_attribute(node->properties, "minOccurs");
985 
986 	if (attr) {
987 		model->min_occurs = atoi((char*)attr->children->content);
988 	} else {
989 		model->min_occurs = 1;
990 	}
991 
992 	attr = get_attribute(node->properties, "maxOccurs");
993 	if (attr) {
994 		if (!strncmp((char*)attr->children->content, "unbounded", sizeof("unbounded"))) {
995 			model->max_occurs = -1;
996 		} else {
997 			model->max_occurs = atoi((char*)attr->children->content);
998 		}
999 	} else {
1000 		model->max_occurs = 1;
1001 	}
1002 }
1003 
1004 /*
1005 <all
1006   id = ID
1007   maxOccurs = 1 : 1
1008   minOccurs = (0 | 1) : 1
1009   {any attributes with non-schema namespace . . .}>
1010   Content: (annotation?, element*)
1011 </all>
1012 */
schema_all(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr all,sdlTypePtr cur_type,sdlContentModelPtr model)1013 static int schema_all(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr all, sdlTypePtr cur_type, sdlContentModelPtr model)
1014 {
1015 	xmlNodePtr trav;
1016 	sdlContentModelPtr newModel;
1017 
1018 	newModel = emalloc(sizeof(sdlContentModel));
1019 	newModel->kind = XSD_CONTENT_ALL;
1020 	newModel->u.content = emalloc(sizeof(HashTable));
1021 	zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
1022 	if (model == NULL) {
1023 		cur_type->model = newModel;
1024 	} else {
1025 		zend_hash_next_index_insert(model->u.content,&newModel,sizeof(sdlContentModelPtr), NULL);
1026 	}
1027 
1028 	schema_min_max(all, newModel);
1029 
1030 	trav = all->children;
1031 	if (trav != NULL && node_is_equal(trav,"annotation")) {
1032 		/* TODO: <annotation> support */
1033 		trav = trav->next;
1034 	}
1035 	while (trav != NULL) {
1036 		if (node_is_equal(trav,"element")) {
1037 			schema_element(sdl, tns, trav, cur_type, newModel);
1038 		} else {
1039 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in all", trav->name);
1040 		}
1041 		trav = trav->next;
1042 	}
1043 	return TRUE;
1044 }
1045 
1046 /*
1047 <group
1048   name = NCName
1049   Content: (annotation?, (all | choice | sequence))
1050 </group>
1051 <group
1052   name = NCName
1053   ref = QName>
1054   Content: (annotation?)
1055 </group>
1056 */
schema_group(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr groupType,sdlTypePtr cur_type,sdlContentModelPtr model)1057 static int schema_group(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr groupType, sdlTypePtr cur_type, sdlContentModelPtr model)
1058 {
1059 	xmlNodePtr trav;
1060 	xmlAttrPtr ns, name, ref = NULL;
1061 	sdlContentModelPtr newModel;
1062 
1063 	ns = get_attribute(groupType->properties, "targetNamespace");
1064 	if (ns == NULL) {
1065 		ns = tns;
1066 	}
1067 
1068 	name = get_attribute(groupType->properties, "name");
1069 	if (name == NULL) {
1070 		name = ref = get_attribute(groupType->properties, "ref");
1071 	}
1072 
1073 	if (name) {
1074 		smart_str key = {0};
1075 
1076 		if (ref) {
1077 			char *type, *ns;
1078 			xmlNsPtr nsptr;
1079 
1080 			parse_namespace(ref->children->content, &type, &ns);
1081 			nsptr = xmlSearchNs(groupType->doc, groupType, BAD_CAST(ns));
1082 			if (nsptr != NULL) {
1083 				smart_str_appends(&key, (char*)nsptr->href);
1084 			}
1085 			smart_str_appendc(&key, ':');
1086 			smart_str_appends(&key, type);
1087 			smart_str_0(&key);
1088 
1089 			newModel = emalloc(sizeof(sdlContentModel));
1090 			newModel->kind = XSD_CONTENT_GROUP_REF;
1091 			newModel->u.group_ref = estrdup(key.c);
1092 
1093 			if (type) {efree(type);}
1094 			if (ns) {efree(ns);}
1095 		} else {
1096 			newModel = emalloc(sizeof(sdlContentModel));
1097 			newModel->kind = XSD_CONTENT_SEQUENCE; /* will be redefined */
1098 			newModel->u.content = emalloc(sizeof(HashTable));
1099 			zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
1100 
1101 			smart_str_appends(&key, (char*)ns->children->content);
1102 			smart_str_appendc(&key, ':');
1103 			smart_str_appends(&key, (char*)name->children->content);
1104 			smart_str_0(&key);
1105 		}
1106 
1107 		if (cur_type == NULL) {
1108 			sdlTypePtr newType;
1109 
1110 			newType = emalloc(sizeof(sdlType));
1111 			memset(newType, 0, sizeof(sdlType));
1112 
1113 			if (sdl->groups == NULL) {
1114 				sdl->groups = emalloc(sizeof(HashTable));
1115 				zend_hash_init(sdl->groups, 0, NULL, delete_type, 0);
1116 			}
1117 			if (zend_hash_add(sdl->groups, key.c, key.len+1, (void**)&newType, sizeof(sdlTypePtr), NULL) != SUCCESS) {
1118 				soap_error1(E_ERROR, "Parsing Schema: group '%s' already defined", key.c);
1119 			}
1120 
1121 			cur_type = newType;
1122 		}
1123 		smart_str_free(&key);
1124 
1125 		if (model == NULL) {
1126 			cur_type->model = newModel;
1127 		} else {
1128 			zend_hash_next_index_insert(model->u.content, &newModel, sizeof(sdlContentModelPtr), NULL);
1129 		}
1130 	} else {
1131 		soap_error0(E_ERROR, "Parsing Schema: group has no 'name' nor 'ref' attributes");
1132 	}
1133 
1134 	schema_min_max(groupType, newModel);
1135 
1136 	trav = groupType->children;
1137 	if (trav != NULL && node_is_equal(trav,"annotation")) {
1138 		/* TODO: <annotation> support */
1139 		trav = trav->next;
1140 	}
1141 	if (trav != NULL) {
1142 		if (node_is_equal(trav,"choice")) {
1143 			if (ref != NULL) {
1144 				soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent");
1145 			}
1146 			newModel->kind = XSD_CONTENT_CHOICE;
1147 			schema_choice(sdl, tns, trav, cur_type, newModel);
1148 			trav = trav->next;
1149 		} else if (node_is_equal(trav,"sequence")) {
1150 			if (ref != NULL) {
1151 				soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent");
1152 			}
1153 			newModel->kind = XSD_CONTENT_SEQUENCE;
1154 			schema_sequence(sdl, tns, trav, cur_type, newModel);
1155 			trav = trav->next;
1156 		} else if (node_is_equal(trav,"all")) {
1157 			if (ref != NULL) {
1158 				soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent");
1159 			}
1160 			newModel->kind = XSD_CONTENT_ALL;
1161 			schema_all(sdl, tns, trav, cur_type, newModel);
1162 			trav = trav->next;
1163 		} else {
1164 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in group", trav->name);
1165 		}
1166 	}
1167 	if (trav != NULL) {
1168 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in group", trav->name);
1169 	}
1170 	return TRUE;
1171 }
1172 /*
1173 <choice
1174   id = ID
1175   maxOccurs = (nonNegativeInteger | unbounded)  : 1
1176   minOccurs = nonNegativeInteger : 1
1177   {any attributes with non-schema namespace . . .}>
1178   Content: (annotation?, (element | group | choice | sequence | any)*)
1179 </choice>
1180 */
schema_choice(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr choiceType,sdlTypePtr cur_type,sdlContentModelPtr model)1181 static int schema_choice(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr choiceType, sdlTypePtr cur_type, sdlContentModelPtr model)
1182 {
1183 	xmlNodePtr trav;
1184 	sdlContentModelPtr newModel;
1185 
1186 	newModel = emalloc(sizeof(sdlContentModel));
1187 	newModel->kind = XSD_CONTENT_CHOICE;
1188 	newModel->u.content = emalloc(sizeof(HashTable));
1189 	zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
1190 	if (model == NULL) {
1191 		cur_type->model = newModel;
1192 	} else {
1193 		zend_hash_next_index_insert(model->u.content,&newModel,sizeof(sdlContentModelPtr), NULL);
1194 	}
1195 
1196 	schema_min_max(choiceType, newModel);
1197 
1198 	trav = choiceType->children;
1199 	if (trav != NULL && node_is_equal(trav,"annotation")) {
1200 		/* TODO: <annotation> support */
1201 		trav = trav->next;
1202 	}
1203 	while (trav != NULL) {
1204 		if (node_is_equal(trav,"element")) {
1205 			schema_element(sdl, tns, trav, cur_type, newModel);
1206 		} else if (node_is_equal(trav,"group")) {
1207 			schema_group(sdl, tns, trav, cur_type, newModel);
1208 		} else if (node_is_equal(trav,"choice")) {
1209 			schema_choice(sdl, tns, trav, cur_type, newModel);
1210 		} else if (node_is_equal(trav,"sequence")) {
1211 			schema_sequence(sdl, tns, trav, cur_type, newModel);
1212 		} else if (node_is_equal(trav,"any")) {
1213 			schema_any(sdl, tns, trav, cur_type, newModel);
1214 		} else {
1215 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in choice", trav->name);
1216 		}
1217 		trav = trav->next;
1218 	}
1219 	return TRUE;
1220 }
1221 
1222 /*
1223 <sequence
1224   id = ID
1225   maxOccurs = (nonNegativeInteger | unbounded)  : 1
1226   minOccurs = nonNegativeInteger : 1
1227   {any attributes with non-schema namespace . . .}>
1228   Content: (annotation?, (element | group | choice | sequence | any)*)
1229 </sequence>
1230 */
schema_sequence(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr seqType,sdlTypePtr cur_type,sdlContentModelPtr model)1231 static int schema_sequence(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr seqType, sdlTypePtr cur_type, sdlContentModelPtr model)
1232 {
1233 	xmlNodePtr trav;
1234 	sdlContentModelPtr newModel;
1235 
1236 	newModel = emalloc(sizeof(sdlContentModel));
1237 	newModel->kind = XSD_CONTENT_SEQUENCE;
1238 	newModel->u.content = emalloc(sizeof(HashTable));
1239 	zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
1240 	if (model == NULL) {
1241 		cur_type->model = newModel;
1242 	} else {
1243 		zend_hash_next_index_insert(model->u.content,&newModel,sizeof(sdlContentModelPtr), NULL);
1244 	}
1245 
1246 	schema_min_max(seqType, newModel);
1247 
1248 	trav = seqType->children;
1249 	if (trav != NULL && node_is_equal(trav,"annotation")) {
1250 		/* TODO: <annotation> support */
1251 		trav = trav->next;
1252 	}
1253 	while (trav != NULL) {
1254 		if (node_is_equal(trav,"element")) {
1255 			schema_element(sdl, tns, trav, cur_type, newModel);
1256 		} else if (node_is_equal(trav,"group")) {
1257 			schema_group(sdl, tns, trav, cur_type, newModel);
1258 		} else if (node_is_equal(trav,"choice")) {
1259 			schema_choice(sdl, tns, trav, cur_type, newModel);
1260 		} else if (node_is_equal(trav,"sequence")) {
1261 			schema_sequence(sdl, tns, trav, cur_type, newModel);
1262 		} else if (node_is_equal(trav,"any")) {
1263 			schema_any(sdl, tns, trav, cur_type, newModel);
1264 		} else {
1265 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in sequence", trav->name);
1266 		}
1267 		trav = trav->next;
1268 	}
1269 	return TRUE;
1270 }
1271 
1272 /*
1273 <any
1274   id = ID
1275   maxOccurs = (nonNegativeInteger | unbounded)  : 1
1276   minOccurs = nonNegativeInteger : 1
1277   namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) )  : ##any
1278   processContents = (lax | skip | strict) : strict
1279   {any attributes with non-schema namespace . . .}>
1280   Content: (annotation?)
1281 </any>
1282 */
schema_any(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr anyType,sdlTypePtr cur_type,sdlContentModelPtr model)1283 static int schema_any(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr anyType, sdlTypePtr cur_type, sdlContentModelPtr model)
1284 {
1285 	if (model != NULL) {
1286 		sdlContentModelPtr newModel;
1287 
1288 		newModel = emalloc(sizeof(sdlContentModel));
1289 		newModel->kind = XSD_CONTENT_ANY;
1290 
1291 		schema_min_max(anyType, newModel);
1292 
1293 		zend_hash_next_index_insert(model->u.content, &newModel, sizeof(sdlContentModelPtr), NULL);
1294 	}
1295 	return TRUE;
1296 }
1297 
1298 /*
1299 <complexContent
1300   id = ID
1301   mixed = boolean
1302   {any attributes with non-schema namespace . . .}>
1303   Content: (annotation?, (restriction | extension))
1304 </complexContent>
1305 */
schema_complexContent(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr compCont,sdlTypePtr cur_type)1306 static int schema_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr compCont, sdlTypePtr cur_type)
1307 {
1308 	xmlNodePtr trav;
1309 
1310 	trav = compCont->children;
1311 	if (trav != NULL && node_is_equal(trav,"annotation")) {
1312 		/* TODO: <annotation> support */
1313 		trav = trav->next;
1314 	}
1315 	if (trav != NULL) {
1316 		if (node_is_equal(trav, "restriction")) {
1317 			cur_type->kind = XSD_TYPEKIND_RESTRICTION;
1318 			schema_restriction_complexContent(sdl, tns, trav, cur_type);
1319 			trav = trav->next;
1320 		} else if (node_is_equal(trav, "extension")) {
1321 			cur_type->kind = XSD_TYPEKIND_EXTENSION;
1322 			schema_extension_complexContent(sdl, tns, trav, cur_type);
1323 			trav = trav->next;
1324 		} else {
1325 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexContent", trav->name);
1326 		}
1327 	} else {
1328 		soap_error0(E_ERROR, "Parsing Schema: <restriction> or <extension> expected in complexContent");
1329 	}
1330 	if (trav != NULL) {
1331 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexContent", trav->name);
1332 	}
1333 
1334 	return TRUE;
1335 }
1336 
1337 /*
1338 <complexType
1339   abstract = boolean : false
1340   block = (#all | List of (extension | restriction))
1341   final = (#all | List of (extension | restriction))
1342   id = ID
1343   mixed = boolean : false
1344   name = NCName
1345   {any attributes with non-schema namespace . . .}>
1346   Content: (annotation?, (simpleContent | complexContent | ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?))))
1347 </complexType>
1348 */
schema_complexType(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr compType,sdlTypePtr cur_type)1349 static int schema_complexType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr compType, sdlTypePtr cur_type)
1350 {
1351 	xmlNodePtr trav;
1352 	xmlAttrPtr attrs, name, ns;
1353 
1354 	attrs = compType->properties;
1355 	ns = get_attribute(attrs, "targetNamespace");
1356 	if (ns == NULL) {
1357 		ns = tns;
1358 	}
1359 
1360 	name = get_attribute(attrs, "name");
1361 	if (cur_type != NULL) {
1362 		/* Anonymous type inside <element> */
1363 		sdlTypePtr newType, *ptr;
1364 
1365 		newType = emalloc(sizeof(sdlType));
1366 		memset(newType, 0, sizeof(sdlType));
1367 		newType->kind = XSD_TYPEKIND_COMPLEX;
1368 		if (name != NULL) {
1369 			newType->name = estrdup((char*)name->children->content);
1370 			newType->namens = estrdup((char*)ns->children->content);
1371 		} else {
1372 			newType->name = estrdup(cur_type->name);
1373 			newType->namens = estrdup(cur_type->namens);
1374 		}
1375 
1376 		zend_hash_next_index_insert(sdl->types,  &newType, sizeof(sdlTypePtr), (void **)&ptr);
1377 
1378 		if (sdl->encoders == NULL) {
1379 			sdl->encoders = emalloc(sizeof(HashTable));
1380 			zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, 0);
1381 		}
1382 		cur_type->encode = emalloc(sizeof(encode));
1383 		memset(cur_type->encode, 0, sizeof(encode));
1384 		cur_type->encode->details.ns = estrdup(newType->namens);
1385 		cur_type->encode->details.type_str = estrdup(newType->name);
1386 		cur_type->encode->details.sdl_type = *ptr;
1387 		cur_type->encode->to_xml = sdl_guess_convert_xml;
1388 		cur_type->encode->to_zval = sdl_guess_convert_zval;
1389 		zend_hash_next_index_insert(sdl->encoders,  &cur_type->encode, sizeof(encodePtr), NULL);
1390 
1391 		cur_type =*ptr;
1392 
1393 	} else if (name) {
1394 		sdlTypePtr newType, *ptr;
1395 
1396 		newType = emalloc(sizeof(sdlType));
1397 		memset(newType, 0, sizeof(sdlType));
1398 		newType->kind = XSD_TYPEKIND_COMPLEX;
1399 		newType->name = estrdup((char*)name->children->content);
1400 		newType->namens = estrdup((char*)ns->children->content);
1401 
1402 		zend_hash_next_index_insert(sdl->types,  &newType, sizeof(sdlTypePtr), (void **)&ptr);
1403 
1404 		cur_type = (*ptr);
1405 		create_encoder(sdl, cur_type, ns->children->content, name->children->content);
1406 	} else {
1407 		soap_error0(E_ERROR, "Parsing Schema: complexType has no 'name' attribute");
1408 		return FALSE;
1409 	}
1410 
1411 	trav = compType->children;
1412 	if (trav != NULL && node_is_equal(trav, "annotation")) {
1413 		/* TODO: <annotation> support */
1414 		trav = trav->next;
1415 	}
1416 	if (trav != NULL) {
1417 		if (node_is_equal(trav,"simpleContent")) {
1418 			schema_simpleContent(sdl, tns, trav, cur_type);
1419 			trav = trav->next;
1420 		} else if (node_is_equal(trav,"complexContent")) {
1421 			schema_complexContent(sdl, tns, trav, cur_type);
1422 			trav = trav->next;
1423 		} else {
1424 			if (node_is_equal(trav,"group")) {
1425 				schema_group(sdl, tns, trav, cur_type, NULL);
1426 				trav = trav->next;
1427 			} else if (node_is_equal(trav,"all")) {
1428 				schema_all(sdl, tns, trav, cur_type, NULL);
1429 				trav = trav->next;
1430 			} else if (node_is_equal(trav,"choice")) {
1431 				schema_choice(sdl, tns, trav, cur_type, NULL);
1432 				trav = trav->next;
1433 			} else if (node_is_equal(trav,"sequence")) {
1434 				schema_sequence(sdl, tns, trav, cur_type, NULL);
1435 				trav = trav->next;
1436 			}
1437 			while (trav != NULL) {
1438 				if (node_is_equal(trav,"attribute")) {
1439 					schema_attribute(sdl, tns, trav, cur_type, NULL);
1440 				} else if (node_is_equal(trav,"attributeGroup")) {
1441 					schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
1442 				} else if (node_is_equal(trav,"anyAttribute")) {
1443 					/* TODO: <anyAttribute> support */
1444 					trav = trav->next;
1445 					break;
1446 				} else {
1447 					soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexType", trav->name);
1448 				}
1449 				trav = trav->next;
1450 			}
1451 		}
1452 	}
1453 	if (trav != NULL) {
1454 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexType", trav->name);
1455 	}
1456 	return TRUE;
1457 }
1458 /*
1459 <element
1460   abstract = boolean : false
1461   block = (#all | List of (extension | restriction | substitution))
1462   default = string
1463   final = (#all | List of (extension | restriction))
1464   fixed = string
1465   form = (qualified | unqualified)
1466   id = ID
1467   maxOccurs = (nonNegativeInteger | unbounded)  : 1
1468   minOccurs = nonNegativeInteger : 1
1469   name = NCName
1470   nillable = boolean : false
1471   ref = QName
1472   substitutionGroup = QName
1473   type = QName
1474   {any attributes with non-schema namespace . . .}>
1475   Content: (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*))
1476 </element>
1477 */
schema_element(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr element,sdlTypePtr cur_type,sdlContentModelPtr model)1478 static int schema_element(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr element, sdlTypePtr cur_type, sdlContentModelPtr model)
1479 {
1480 	xmlNodePtr trav;
1481 	xmlAttrPtr attrs, attr, ns, name, type, ref = NULL;
1482 
1483 	attrs = element->properties;
1484 	ns = get_attribute(attrs, "targetNamespace");
1485 	if (ns == NULL) {
1486 		ns = tns;
1487 	}
1488 
1489 	name = get_attribute(attrs, "name");
1490 	if (name == NULL) {
1491 		name = ref = get_attribute(attrs, "ref");
1492 	}
1493 
1494 	if (name) {
1495 		HashTable *addHash;
1496 		sdlTypePtr newType;
1497 		smart_str key = {0};
1498 
1499 		newType = emalloc(sizeof(sdlType));
1500 		memset(newType, 0, sizeof(sdlType));
1501 
1502 		if (ref) {
1503 			smart_str nscat = {0};
1504 			char *type, *ns;
1505 			xmlNsPtr nsptr;
1506 
1507 			parse_namespace(ref->children->content, &type, &ns);
1508 			nsptr = xmlSearchNs(element->doc, element, BAD_CAST(ns));
1509 			if (nsptr != NULL) {
1510 				smart_str_appends(&nscat, (char*)nsptr->href);
1511 				newType->namens = estrdup((char*)nsptr->href);
1512 			}
1513 			smart_str_appendc(&nscat, ':');
1514 			smart_str_appends(&nscat, type);
1515 			newType->name = estrdup(type);
1516 			smart_str_0(&nscat);
1517 			if (type) {efree(type);}
1518 			if (ns) {efree(ns);}
1519 			newType->ref = estrdup(nscat.c);
1520 			smart_str_free(&nscat);
1521 		} else {
1522 			newType->name = estrdup((char*)name->children->content);
1523 			newType->namens = estrdup((char*)ns->children->content);
1524 		}
1525 
1526 		newType->nillable = FALSE;
1527 
1528 		if (cur_type == NULL) {
1529 			if (sdl->elements == NULL) {
1530 				sdl->elements = emalloc(sizeof(HashTable));
1531 				zend_hash_init(sdl->elements, 0, NULL, delete_type, 0);
1532 			}
1533 			addHash = sdl->elements;
1534 			smart_str_appends(&key, newType->namens);
1535 			smart_str_appendc(&key, ':');
1536 			smart_str_appends(&key, newType->name);
1537 		} else {
1538 			if (cur_type->elements == NULL) {
1539 				cur_type->elements = emalloc(sizeof(HashTable));
1540 				zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
1541 			}
1542 			addHash = cur_type->elements;
1543 			smart_str_appends(&key, newType->name);
1544 		}
1545 
1546 		smart_str_0(&key);
1547 		if (zend_hash_add(addHash, key.c, key.len + 1, &newType, sizeof(sdlTypePtr), NULL) != SUCCESS) {
1548 			if (cur_type == NULL) {
1549 				soap_error1(E_ERROR, "Parsing Schema: element '%s' already defined", key.c);
1550 			} else {
1551 				zend_hash_next_index_insert(addHash, &newType, sizeof(sdlTypePtr), NULL);
1552 			}
1553 		}
1554 		smart_str_free(&key);
1555 
1556 		if (model != NULL) {
1557 			sdlContentModelPtr newModel = emalloc(sizeof(sdlContentModel));
1558 
1559 			newModel->kind = XSD_CONTENT_ELEMENT;
1560 			newModel->u.element = newType;
1561 
1562 			schema_min_max(element, newModel);
1563 
1564 
1565 			zend_hash_next_index_insert(model->u.content, &newModel, sizeof(sdlContentModelPtr), NULL);
1566 		}
1567 		cur_type = newType;
1568 	} else {
1569 		soap_error0(E_ERROR, "Parsing Schema: element has no 'name' nor 'ref' attributes");
1570 	}
1571 
1572 	/* nillable = boolean : false */
1573 	attrs = element->properties;
1574 	attr = get_attribute(attrs, "nillable");
1575 	if (attr) {
1576 		if (ref != NULL) {
1577 			soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'nillable' attributes");
1578 		}
1579 		if (!stricmp((char*)attr->children->content, "true") ||
1580 			!stricmp((char*)attr->children->content, "1")) {
1581 			cur_type->nillable = TRUE;
1582 		} else {
1583 			cur_type->nillable = FALSE;
1584 		}
1585 	} else {
1586 		cur_type->nillable = FALSE;
1587 	}
1588 
1589 	attr = get_attribute(attrs, "fixed");
1590 	if (attr) {
1591 		if (ref != NULL) {
1592 			soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'fixed' attributes");
1593 		}
1594 		cur_type->fixed = estrdup((char*)attr->children->content);
1595 	}
1596 
1597 	attr = get_attribute(attrs, "default");
1598 	if (attr) {
1599 		if (ref != NULL) {
1600 			soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'fixed' attributes");
1601 		} else if (ref != NULL) {
1602 			soap_error0(E_ERROR, "Parsing Schema: element has both 'default' and 'fixed' attributes");
1603 		}
1604 		cur_type->def = estrdup((char*)attr->children->content);
1605 	}
1606 
1607 	/* form */
1608 	attr = get_attribute(attrs, "form");
1609 	if (attr) {
1610 		if (strncmp((char*)attr->children->content, "qualified", sizeof("qualified")) == 0) {
1611 		  cur_type->form = XSD_FORM_QUALIFIED;
1612 		} else if (strncmp((char*)attr->children->content, "unqualified", sizeof("unqualified")) == 0) {
1613 		  cur_type->form = XSD_FORM_UNQUALIFIED;
1614 		} else {
1615 		  cur_type->form = XSD_FORM_DEFAULT;
1616 		}
1617 	} else {
1618 	  cur_type->form = XSD_FORM_DEFAULT;
1619 	}
1620 	if (cur_type->form == XSD_FORM_DEFAULT) {
1621  		xmlNodePtr parent = element->parent;
1622  		while (parent) {
1623 			if (node_is_equal_ex(parent, "schema", SCHEMA_NAMESPACE)) {
1624 				xmlAttrPtr def;
1625 				def = get_attribute(parent->properties, "elementFormDefault");
1626 				if(def == NULL || strncmp((char*)def->children->content, "qualified", sizeof("qualified"))) {
1627 					cur_type->form = XSD_FORM_UNQUALIFIED;
1628 				} else {
1629 					cur_type->form = XSD_FORM_QUALIFIED;
1630 				}
1631 				break;
1632 			}
1633 			parent = parent->parent;
1634   	}
1635 		if (parent == NULL) {
1636 			cur_type->form = XSD_FORM_UNQUALIFIED;
1637 		}
1638 	}
1639 
1640 	/* type = QName */
1641 	type = get_attribute(attrs, "type");
1642 	if (type) {
1643 		char *cptype, *str_ns;
1644 		xmlNsPtr nsptr;
1645 
1646 		if (ref != NULL) {
1647 			soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'type' attributes");
1648 		}
1649 		parse_namespace(type->children->content, &cptype, &str_ns);
1650 		nsptr = xmlSearchNs(element->doc, element, BAD_CAST(str_ns));
1651 		if (nsptr != NULL) {
1652 			cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(cptype));
1653 		}
1654 		if (str_ns) {efree(str_ns);}
1655 		if (cptype) {efree(cptype);}
1656 	}
1657 
1658 	trav = element->children;
1659 	if (trav != NULL && node_is_equal(trav, "annotation")) {
1660 		/* TODO: <annotation> support */
1661 		trav = trav->next;
1662 	}
1663 	if (trav != NULL) {
1664 		if (node_is_equal(trav,"simpleType")) {
1665 			if (ref != NULL) {
1666 				soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' attribute and subtype");
1667 			} else if (type != NULL) {
1668 				soap_error0(E_ERROR, "Parsing Schema: element has both 'type' attribute and subtype");
1669 			}
1670 			schema_simpleType(sdl, tns, trav, cur_type);
1671 			trav = trav->next;
1672 		} else if (node_is_equal(trav,"complexType")) {
1673 			if (ref != NULL) {
1674 				soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' attribute and subtype");
1675 			} else if (type != NULL) {
1676 				soap_error0(E_ERROR, "Parsing Schema: element has both 'type' attribute and subtype");
1677 			}
1678 			schema_complexType(sdl, tns, trav, cur_type);
1679 			trav = trav->next;
1680 		}
1681 	}
1682 	while (trav != NULL) {
1683 		if (node_is_equal(trav,"unique")) {
1684 			/* TODO: <unique> support */
1685 		} else if (node_is_equal(trav,"key")) {
1686 			/* TODO: <key> support */
1687 		} else if (node_is_equal(trav,"keyref")) {
1688 			/* TODO: <keyref> support */
1689 		} else {
1690 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in element", trav->name);
1691 		}
1692 		trav = trav->next;
1693 	}
1694 
1695 	return TRUE;
1696 }
1697 
1698 /*
1699 <attribute
1700   default = string
1701   fixed = string
1702   form = (qualified | unqualified)
1703   id = ID
1704   name = NCName
1705   ref = QName
1706   type = QName
1707   use = (optional | prohibited | required) : optional
1708   {any attributes with non-schema namespace . . .}>
1709   Content: (annotation?, (simpleType?))
1710 </attribute>
1711 */
schema_attribute(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr attrType,sdlTypePtr cur_type,sdlCtx * ctx)1712 static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdlTypePtr cur_type, sdlCtx *ctx)
1713 {
1714 	sdlAttributePtr newAttr;
1715 	xmlAttrPtr attr, name, ref = NULL, type = NULL;
1716 	xmlNodePtr trav;
1717 
1718 	name = get_attribute(attrType->properties, "name");
1719 	if (name == NULL) {
1720 		name = ref = get_attribute(attrType->properties, "ref");
1721 	}
1722 	if (name) {
1723 		HashTable *addHash;
1724 		smart_str key = {0};
1725 
1726 		newAttr = emalloc(sizeof(sdlAttribute));
1727 		memset(newAttr, 0, sizeof(sdlAttribute));
1728 
1729 		if (ref) {
1730 			char *attr_name, *ns;
1731 			xmlNsPtr nsptr;
1732 
1733 			parse_namespace(ref->children->content, &attr_name, &ns);
1734 			nsptr = xmlSearchNs(attrType->doc, attrType, BAD_CAST(ns));
1735 			if (nsptr != NULL) {
1736 				smart_str_appends(&key, (char*)nsptr->href);
1737 				newAttr->namens = estrdup((char*)nsptr->href);
1738 			}
1739 			smart_str_appendc(&key, ':');
1740 			smart_str_appends(&key, attr_name);
1741 			smart_str_0(&key);
1742 			newAttr->ref = estrdup(key.c);
1743 			if (attr_name) {efree(attr_name);}
1744 			if (ns) {efree(ns);}
1745 		} else {
1746 			xmlAttrPtr ns;
1747 
1748 			ns = get_attribute(attrType->properties, "targetNamespace");
1749 			if (ns == NULL) {
1750 				ns = tns;
1751 			}
1752 			if (ns != NULL) {
1753 				smart_str_appends(&key, (char*)ns->children->content);
1754 				smart_str_appendc(&key, ':');
1755 				newAttr->namens = estrdup((char*)ns->children->content);
1756 			}
1757 			smart_str_appends(&key, (char*)name->children->content);
1758 			smart_str_0(&key);
1759 		}
1760 
1761 		if (cur_type == NULL) {
1762 			addHash = ctx->attributes;
1763 		} else {
1764 			if (cur_type->attributes == NULL) {
1765 				cur_type->attributes = emalloc(sizeof(HashTable));
1766 				zend_hash_init(cur_type->attributes, 0, NULL, delete_attribute, 0);
1767 			}
1768 			addHash = cur_type->attributes;
1769 		}
1770 
1771 		if (zend_hash_add(addHash, key.c, key.len + 1, &newAttr, sizeof(sdlAttributePtr), NULL) != SUCCESS) {
1772 			soap_error1(E_ERROR, "Parsing Schema: attribute '%s' already defined", key.c);
1773 		}
1774 		smart_str_free(&key);
1775 	} else{
1776 		soap_error0(E_ERROR, "Parsing Schema: attribute has no 'name' nor 'ref' attributes");
1777 	}
1778 
1779 	/* type = QName */
1780 	type = get_attribute(attrType->properties, "type");
1781 	if (type) {
1782 		char *cptype, *str_ns;
1783 		xmlNsPtr nsptr;
1784 
1785 		if (ref != NULL) {
1786 			soap_error0(E_ERROR, "Parsing Schema: attribute has both 'ref' and 'type' attributes");
1787 		}
1788 		parse_namespace(type->children->content, &cptype, &str_ns);
1789 		nsptr = xmlSearchNs(attrType->doc, attrType, BAD_CAST(str_ns));
1790 		if (nsptr != NULL) {
1791 			newAttr->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(cptype));
1792 		}
1793 		if (str_ns) {efree(str_ns);}
1794 		if (cptype) {efree(cptype);}
1795 	}
1796 
1797 	attr = attrType->properties;
1798 	while (attr != NULL) {
1799 		if (attr_is_equal_ex(attr, "default", SCHEMA_NAMESPACE)) {
1800 			newAttr->def = estrdup((char*)attr->children->content);
1801 		} else if (attr_is_equal_ex(attr, "fixed", SCHEMA_NAMESPACE)) {
1802 			newAttr->fixed = estrdup((char*)attr->children->content);
1803 		} else if (attr_is_equal_ex(attr, "form", SCHEMA_NAMESPACE)) {
1804 			if (strncmp((char*)attr->children->content, "qualified", sizeof("qualified")) == 0) {
1805 			  newAttr->form = XSD_FORM_QUALIFIED;
1806 			} else if (strncmp((char*)attr->children->content, "unqualified", sizeof("unqualified")) == 0) {
1807 			  newAttr->form = XSD_FORM_UNQUALIFIED;
1808 			} else {
1809 			  newAttr->form = XSD_FORM_DEFAULT;
1810 			}
1811 		} else if (attr_is_equal_ex(attr, "id", SCHEMA_NAMESPACE)) {
1812 			/* skip */
1813 		} else if (attr_is_equal_ex(attr, "name", SCHEMA_NAMESPACE)) {
1814 			newAttr->name = estrdup((char*)attr->children->content);
1815 		} else if (attr_is_equal_ex(attr, "ref", SCHEMA_NAMESPACE)) {
1816 			/* already processed */
1817 		} else if (attr_is_equal_ex(attr, "type", SCHEMA_NAMESPACE)) {
1818 			/* already processed */
1819 		} else if (attr_is_equal_ex(attr, "use", SCHEMA_NAMESPACE)) {
1820 			if (strncmp((char*)attr->children->content, "prohibited", sizeof("prohibited")) == 0) {
1821 			  newAttr->use = XSD_USE_PROHIBITED;
1822 			} else if (strncmp((char*)attr->children->content, "required", sizeof("required")) == 0) {
1823 			  newAttr->use = XSD_USE_REQUIRED;
1824 			} else if (strncmp((char*)attr->children->content, "optional", sizeof("optional")) == 0) {
1825 			  newAttr->use = XSD_USE_OPTIONAL;
1826 			} else {
1827 			  newAttr->use = XSD_USE_DEFAULT;
1828 			}
1829 		} else {
1830 			xmlNsPtr nsPtr = attr_find_ns(attr);
1831 
1832 			if (strncmp((char*)nsPtr->href, SCHEMA_NAMESPACE, sizeof(SCHEMA_NAMESPACE))) {
1833 				smart_str key2 = {0};
1834 				sdlExtraAttributePtr ext;
1835 				xmlNsPtr nsptr;
1836 				char *value, *ns;
1837 
1838 				ext = emalloc(sizeof(sdlExtraAttribute));
1839 				memset(ext, 0, sizeof(sdlExtraAttribute));
1840 				parse_namespace(attr->children->content, &value, &ns);
1841 				nsptr = xmlSearchNs(attr->doc, attr->parent, BAD_CAST(ns));
1842 				if (nsptr) {
1843 					ext->ns = estrdup((char*)nsptr->href);
1844 					ext->val = estrdup(value);
1845 				} else {
1846 					ext->val = estrdup((char*)attr->children->content);
1847 				}
1848 				if (ns) {efree(ns);}
1849 				efree(value);
1850 
1851 				if (!newAttr->extraAttributes) {
1852 					newAttr->extraAttributes = emalloc(sizeof(HashTable));
1853 					zend_hash_init(newAttr->extraAttributes, 0, NULL, delete_extra_attribute, 0);
1854 				}
1855 
1856 				smart_str_appends(&key2, (char*)nsPtr->href);
1857 				smart_str_appendc(&key2, ':');
1858 				smart_str_appends(&key2, (char*)attr->name);
1859 				smart_str_0(&key2);
1860 				zend_hash_add(newAttr->extraAttributes, key2.c, key2.len + 1, &ext, sizeof(sdlExtraAttributePtr), NULL);
1861 				smart_str_free(&key2);
1862 			}
1863 		}
1864 		attr = attr->next;
1865 	}
1866 	if (newAttr->form == XSD_FORM_DEFAULT) {
1867  		xmlNodePtr parent = attrType->parent;
1868  		while (parent) {
1869 			if (node_is_equal_ex(parent, "schema", SCHEMA_NAMESPACE)) {
1870 				xmlAttrPtr def;
1871 				def = get_attribute(parent->properties, "attributeFormDefault");
1872 				if(def == NULL || strncmp((char*)def->children->content, "qualified", sizeof("qualified"))) {
1873 					newAttr->form = XSD_FORM_UNQUALIFIED;
1874 				} else {
1875 					newAttr->form = XSD_FORM_QUALIFIED;
1876 				}
1877 				break;
1878 			}
1879 			parent = parent->parent;
1880   	}
1881 		if (parent == NULL) {
1882 			newAttr->form = XSD_FORM_UNQUALIFIED;
1883 		}
1884 	}
1885 	trav = attrType->children;
1886 	if (trav != NULL && node_is_equal(trav, "annotation")) {
1887 		/* TODO: <annotation> support */
1888 		trav = trav->next;
1889 	}
1890 	if (trav != NULL) {
1891 		if (node_is_equal(trav,"simpleType")) {
1892 			sdlTypePtr dummy_type;
1893 			if (ref != NULL) {
1894 				soap_error0(E_ERROR, "Parsing Schema: attribute has both 'ref' attribute and subtype");
1895 			} else if (type != NULL) {
1896 				soap_error0(E_ERROR, "Parsing Schema: attribute has both 'type' attribute and subtype");
1897 			}
1898 			dummy_type = emalloc(sizeof(sdlType));
1899 			memset(dummy_type, 0, sizeof(sdlType));
1900 			{
1901 				smart_str anonymous = {0};
1902 
1903 				smart_str_appendl(&anonymous, "anonymous", sizeof("anonymous")-1);
1904 				smart_str_append_long(&anonymous, zend_hash_num_elements(sdl->types));
1905 				smart_str_0(&anonymous);
1906 				dummy_type->name = anonymous.c;
1907 			}
1908 			dummy_type->namens = estrdup((char*)tns->children->content);
1909 			schema_simpleType(sdl, tns, trav, dummy_type);
1910 			newAttr->encode = dummy_type->encode;
1911 			delete_type(&dummy_type);
1912 			trav = trav->next;
1913 		}
1914 	}
1915 	if (trav != NULL) {
1916 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attribute", trav->name);
1917 	}
1918 	return TRUE;
1919 }
1920 
schema_attributeGroup(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr attrGroup,sdlTypePtr cur_type,sdlCtx * ctx)1921 static int schema_attributeGroup(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrGroup, sdlTypePtr cur_type, sdlCtx *ctx)
1922 {
1923 	xmlNodePtr trav;
1924 	xmlAttrPtr name, ref = NULL;
1925 
1926 
1927 	name = get_attribute(attrGroup->properties, "name");
1928 	if (name == NULL) {
1929 		name = ref = get_attribute(attrGroup->properties, "ref");
1930 	}
1931 	if (name) {
1932 		if (cur_type == NULL) {
1933 			xmlAttrPtr ns;
1934 			sdlTypePtr newType;
1935 			smart_str key = {0};
1936 
1937 			ns = get_attribute(attrGroup->properties, "targetNamespace");
1938 			if (ns == NULL) {
1939 				ns = tns;
1940 			}
1941 			newType = emalloc(sizeof(sdlType));
1942 			memset(newType, 0, sizeof(sdlType));
1943 			newType->name = estrdup((char*)name->children->content);
1944 			newType->namens = estrdup((char*)ns->children->content);
1945 
1946 			smart_str_appends(&key, newType->namens);
1947 			smart_str_appendc(&key, ':');
1948 			smart_str_appends(&key, newType->name);
1949 			smart_str_0(&key);
1950 
1951 			if (zend_hash_add(ctx->attributeGroups, key.c, key.len + 1, &newType, sizeof(sdlTypePtr), NULL) != SUCCESS) {
1952 				soap_error1(E_ERROR, "Parsing Schema: attributeGroup '%s' already defined", key.c);
1953 			}
1954 			cur_type = newType;
1955 			smart_str_free(&key);
1956 		} else if (ref) {
1957 			sdlAttributePtr newAttr;
1958 			char *group_name, *ns;
1959 			smart_str key = {0};
1960 			xmlNsPtr nsptr;
1961 
1962 			if (cur_type->attributes == NULL) {
1963 				cur_type->attributes = emalloc(sizeof(HashTable));
1964 				zend_hash_init(cur_type->attributes, 0, NULL, delete_attribute, 0);
1965 			}
1966 			newAttr = emalloc(sizeof(sdlAttribute));
1967 			memset(newAttr, 0, sizeof(sdlAttribute));
1968 
1969 			parse_namespace(ref->children->content, &group_name, &ns);
1970 			nsptr = xmlSearchNs(attrGroup->doc, attrGroup, BAD_CAST(ns));
1971 			if (nsptr != NULL) {
1972 				smart_str_appends(&key, (char*)nsptr->href);
1973 			}
1974 			smart_str_appendc(&key, ':');
1975 			smart_str_appends(&key, group_name);
1976 			smart_str_0(&key);
1977 			newAttr->ref = estrdup(key.c);
1978 			if (group_name) {efree(group_name);}
1979 			if (ns) {efree(ns);}
1980 			smart_str_free(&key);
1981 
1982 			zend_hash_next_index_insert(cur_type->attributes, &newAttr, sizeof(sdlAttributePtr), NULL);
1983 			cur_type = NULL;
1984 		}
1985 	} else{
1986 		soap_error0(E_ERROR, "Parsing Schema: attributeGroup has no 'name' nor 'ref' attributes");
1987 	}
1988 
1989 	trav = attrGroup->children;
1990 	if (trav != NULL && node_is_equal(trav, "annotation")) {
1991 		/* TODO: <annotation> support */
1992 		trav = trav->next;
1993 	}
1994 	while (trav != NULL) {
1995 		if (node_is_equal(trav,"attribute")) {
1996 			if (ref != NULL) {
1997 				soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
1998 			}
1999 			schema_attribute(sdl, tns, trav, cur_type, NULL);
2000 		} else if (node_is_equal(trav,"attributeGroup")) {
2001 			if (ref != NULL) {
2002 				soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
2003 			}
2004 			schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
2005 		} else if (node_is_equal(trav,"anyAttribute")) {
2006 			if (ref != NULL) {
2007 				soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
2008 			}
2009 			/* TODO: <anyAttribute> support */
2010 			trav = trav->next;
2011 			break;
2012 		} else {
2013 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attributeGroup", trav->name);
2014 		}
2015 		trav = trav->next;
2016 	}
2017 	if (trav != NULL) {
2018 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attributeGroup", trav->name);
2019 	}
2020 	return TRUE;
2021 }
2022 
copy_extra_attribute(void * attribute)2023 static void copy_extra_attribute(void *attribute)
2024 {
2025 	sdlExtraAttributePtr *attr = (sdlExtraAttributePtr*)attribute;
2026 	sdlExtraAttributePtr new_attr;
2027 
2028 	new_attr = emalloc(sizeof(sdlExtraAttribute));
2029 	memcpy(new_attr, *attr, sizeof(sdlExtraAttribute));
2030 	*attr = new_attr;
2031 	if (new_attr->ns) {
2032 		new_attr->ns = estrdup(new_attr->ns);
2033 	}
2034 	if (new_attr->val) {
2035 		new_attr->val = estrdup(new_attr->val);
2036 	}
2037 }
2038 
schema_attribute_fixup(sdlCtx * ctx,sdlAttributePtr attr)2039 static void schema_attribute_fixup(sdlCtx *ctx, sdlAttributePtr attr)
2040 {
2041 	sdlAttributePtr *tmp;
2042 
2043 	if (attr->ref != NULL) {
2044 		if (ctx->attributes != NULL) {
2045 			if (zend_hash_find(ctx->attributes, attr->ref, strlen(attr->ref)+1, (void**)&tmp) == SUCCESS) {
2046 				schema_attribute_fixup(ctx, *tmp);
2047 				if ((*tmp)->name != NULL && attr->name == NULL) {
2048 					attr->name = estrdup((*tmp)->name);
2049 				}
2050 				if ((*tmp)->namens != NULL && attr->namens == NULL) {
2051 					attr->namens = estrdup((*tmp)->namens);
2052 				}
2053 				if ((*tmp)->def != NULL && attr->def == NULL) {
2054 					attr->def = estrdup((*tmp)->def);
2055 				}
2056 				if ((*tmp)->fixed != NULL && attr->fixed == NULL) {
2057 					attr->fixed = estrdup((*tmp)->fixed);
2058 				}
2059 				if (attr->form == XSD_FORM_DEFAULT) {
2060 					attr->form = (*tmp)->form;
2061 				}
2062 				if (attr->use == XSD_USE_DEFAULT) {
2063 					attr->use  = (*tmp)->use;
2064 				}
2065 				if ((*tmp)->extraAttributes != NULL) {
2066 				  xmlNodePtr node;
2067 
2068 					attr->extraAttributes = emalloc(sizeof(HashTable));
2069 					zend_hash_init(attr->extraAttributes, zend_hash_num_elements((*tmp)->extraAttributes), NULL, delete_extra_attribute, 0);
2070 					zend_hash_copy(attr->extraAttributes, (*tmp)->extraAttributes, copy_extra_attribute, &node, sizeof(xmlNodePtr));
2071 				}
2072 				attr->encode = (*tmp)->encode;
2073 			}
2074 		}
2075 		if (attr->name == NULL && attr->ref != NULL) {
2076 			char *name = strrchr(attr->ref, ':');
2077 			if (name) {
2078 				attr->name = estrdup(name+1);
2079 			} else{
2080 				attr->name = estrdup(attr->ref);
2081 			}
2082 		}
2083 		efree(attr->ref);
2084 		attr->ref = NULL;
2085 	}
2086 }
2087 
schema_attributegroup_fixup(sdlCtx * ctx,sdlAttributePtr attr,HashTable * ht)2088 static void schema_attributegroup_fixup(sdlCtx *ctx, sdlAttributePtr attr, HashTable *ht)
2089 {
2090 	sdlTypePtr *tmp;
2091 	sdlAttributePtr *tmp_attr;
2092 
2093 	if (attr->ref != NULL) {
2094 		if (ctx->attributeGroups != NULL) {
2095 			if (zend_hash_find(ctx->attributeGroups, attr->ref, strlen(attr->ref)+1, (void**)&tmp) == SUCCESS) {
2096 				if ((*tmp)->attributes) {
2097 					zend_hash_internal_pointer_reset((*tmp)->attributes);
2098 					while (zend_hash_get_current_data((*tmp)->attributes,(void**)&tmp_attr) == SUCCESS) {
2099 						if (zend_hash_get_current_key_type((*tmp)->attributes) == HASH_KEY_IS_STRING) {
2100 							char* key;
2101 							uint key_len;
2102 							sdlAttributePtr newAttr;
2103 
2104 							schema_attribute_fixup(ctx,*tmp_attr);
2105 
2106 							newAttr = emalloc(sizeof(sdlAttribute));
2107 							memcpy(newAttr, *tmp_attr, sizeof(sdlAttribute));
2108 							if (newAttr->def) {newAttr->def = estrdup(newAttr->def);}
2109 							if (newAttr->fixed) {newAttr->fixed = estrdup(newAttr->fixed);}
2110 							if (newAttr->namens) {newAttr->namens = estrdup(newAttr->namens);}
2111 							if (newAttr->name) {newAttr->name = estrdup(newAttr->name);}
2112 							if (newAttr->extraAttributes) {
2113 							  xmlNodePtr node;
2114 								HashTable *ht = emalloc(sizeof(HashTable));
2115 								zend_hash_init(ht, zend_hash_num_elements(newAttr->extraAttributes), NULL, delete_extra_attribute, 0);
2116 								zend_hash_copy(ht, newAttr->extraAttributes, copy_extra_attribute, &node, sizeof(xmlNodePtr));
2117 								newAttr->extraAttributes = ht;
2118 							}
2119 
2120 							zend_hash_get_current_key_ex((*tmp)->attributes, &key, &key_len, NULL, 0, NULL);
2121 							zend_hash_add(ht, key, key_len, &newAttr, sizeof(sdlAttributePtr), NULL);
2122 
2123 							zend_hash_move_forward((*tmp)->attributes);
2124 						} else {
2125 							ulong index;
2126 
2127 							schema_attributegroup_fixup(ctx,*tmp_attr, ht);
2128 							zend_hash_get_current_key((*tmp)->attributes, NULL, &index, 0);
2129 							zend_hash_index_del((*tmp)->attributes, index);
2130 						}
2131 					}
2132 				}
2133 			}
2134 		}
2135 		efree(attr->ref);
2136 		attr->ref = NULL;
2137 	}
2138 }
2139 
schema_content_model_fixup(sdlCtx * ctx,sdlContentModelPtr model)2140 static void schema_content_model_fixup(sdlCtx *ctx, sdlContentModelPtr model)
2141 {
2142 	switch (model->kind) {
2143 		case XSD_CONTENT_GROUP_REF: {
2144 			sdlTypePtr *tmp;
2145 
2146 			if (ctx->sdl->groups && zend_hash_find(ctx->sdl->groups, model->u.group_ref, strlen(model->u.group_ref)+1, (void**)&tmp) == SUCCESS) {
2147 				schema_type_fixup(ctx,*tmp);
2148 				efree(model->u.group_ref);
2149 				model->kind = XSD_CONTENT_GROUP;
2150 				model->u.group = (*tmp);
2151 			} else {
2152 				soap_error0(E_ERROR, "Parsing Schema: unresolved group 'ref' attribute");
2153 			}
2154 			break;
2155 		}
2156 		case XSD_CONTENT_CHOICE: {
2157 			if (model->max_occurs != 1) {
2158 				HashPosition pos;
2159 				sdlContentModelPtr *tmp;
2160 
2161 				zend_hash_internal_pointer_reset_ex(model->u.content, &pos);
2162 				while (zend_hash_get_current_data_ex(model->u.content, (void**)&tmp, &pos) == SUCCESS) {
2163 					(*tmp)->min_occurs = 0;
2164 					(*tmp)->max_occurs = model->max_occurs;
2165 					zend_hash_move_forward_ex(model->u.content, &pos);
2166 				}
2167 
2168 				model->kind = XSD_CONTENT_ALL;
2169 				model->min_occurs = 1;
2170 				model->max_occurs = 1;
2171 			}
2172 		}
2173 		case XSD_CONTENT_SEQUENCE:
2174 		case XSD_CONTENT_ALL: {
2175 			sdlContentModelPtr *tmp;
2176 
2177 			zend_hash_internal_pointer_reset(model->u.content);
2178 			while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
2179 				schema_content_model_fixup(ctx, *tmp);
2180 				zend_hash_move_forward(model->u.content);
2181 			}
2182 			break;
2183 		}
2184 		default:
2185 			break;
2186 	}
2187 }
2188 
schema_type_fixup(sdlCtx * ctx,sdlTypePtr type)2189 static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type)
2190 {
2191 	sdlTypePtr *tmp;
2192 	sdlAttributePtr *attr;
2193 
2194 	if (type->ref != NULL) {
2195 		if (ctx->sdl->elements != NULL) {
2196 			if (zend_hash_find(ctx->sdl->elements, type->ref, strlen(type->ref)+1, (void**)&tmp) == SUCCESS) {
2197 				type->kind = (*tmp)->kind;
2198 				type->encode = (*tmp)->encode;
2199 				if ((*tmp)->nillable) {
2200 				  type->nillable = 1;
2201 				}
2202 				if ((*tmp)->fixed) {
2203 				  type->fixed = estrdup((*tmp)->fixed);
2204 				}
2205 				if ((*tmp)->def) {
2206 				  type->def = estrdup((*tmp)->def);
2207 				}
2208 				type->form = (*tmp)->form;
2209 			} else if (strcmp(type->ref, SCHEMA_NAMESPACE ":schema") == 0) {
2210 				type->encode = get_conversion(XSD_ANYXML);
2211 			} else {
2212 				soap_error0(E_ERROR, "Parsing Schema: unresolved element 'ref' attribute");
2213 			}
2214 		}
2215 		efree(type->ref);
2216 		type->ref = NULL;
2217 	}
2218 	if (type->elements) {
2219 		zend_hash_internal_pointer_reset(type->elements);
2220 		while (zend_hash_get_current_data(type->elements,(void**)&tmp) == SUCCESS) {
2221 			schema_type_fixup(ctx,*tmp);
2222 			zend_hash_move_forward(type->elements);
2223 		}
2224 	}
2225 	if (type->model) {
2226 		schema_content_model_fixup(ctx, type->model);
2227 	}
2228 	if (type->attributes) {
2229 		zend_hash_internal_pointer_reset(type->attributes);
2230 		while (zend_hash_get_current_data(type->attributes,(void**)&attr) == SUCCESS) {
2231 			if (zend_hash_get_current_key_type(type->attributes) == HASH_KEY_IS_STRING) {
2232 				schema_attribute_fixup(ctx,*attr);
2233 				zend_hash_move_forward(type->attributes);
2234 			} else {
2235 				ulong index;
2236 
2237 				schema_attributegroup_fixup(ctx,*attr,type->attributes);
2238 				zend_hash_get_current_key(type->attributes, NULL, &index, 0);
2239 				zend_hash_index_del(type->attributes, index);
2240 			}
2241 		}
2242 	}
2243 }
2244 
schema_pass2(sdlCtx * ctx)2245 void schema_pass2(sdlCtx *ctx)
2246 {
2247 	sdlPtr sdl = ctx->sdl;
2248 	sdlAttributePtr *attr;
2249 	sdlTypePtr *type;
2250 
2251 	if (ctx->attributes) {
2252 		zend_hash_internal_pointer_reset(ctx->attributes);
2253 		while (zend_hash_get_current_data(ctx->attributes,(void**)&attr) == SUCCESS) {
2254 			schema_attribute_fixup(ctx,*attr);
2255 			zend_hash_move_forward(ctx->attributes);
2256 		}
2257 	}
2258 	if (ctx->attributeGroups) {
2259 		zend_hash_internal_pointer_reset(ctx->attributeGroups);
2260 		while (zend_hash_get_current_data(ctx->attributeGroups,(void**)&type) == SUCCESS) {
2261 			schema_type_fixup(ctx,*type);
2262 			zend_hash_move_forward(ctx->attributeGroups);
2263 		}
2264 	}
2265 	if (sdl->elements) {
2266 		zend_hash_internal_pointer_reset(sdl->elements);
2267 		while (zend_hash_get_current_data(sdl->elements,(void**)&type) == SUCCESS) {
2268 			schema_type_fixup(ctx,*type);
2269 			zend_hash_move_forward(sdl->elements);
2270 		}
2271 	}
2272 	if (sdl->groups) {
2273 		zend_hash_internal_pointer_reset(sdl->groups);
2274 		while (zend_hash_get_current_data(sdl->groups,(void**)&type) == SUCCESS) {
2275 			schema_type_fixup(ctx,*type);
2276 			zend_hash_move_forward(sdl->groups);
2277 		}
2278 	}
2279 	if (sdl->types) {
2280 		zend_hash_internal_pointer_reset(sdl->types);
2281 		while (zend_hash_get_current_data(sdl->types,(void**)&type) == SUCCESS) {
2282 			schema_type_fixup(ctx,*type);
2283 			zend_hash_move_forward(sdl->types);
2284 		}
2285 	}
2286 	if (ctx->attributes) {
2287 		zend_hash_destroy(ctx->attributes);
2288 		efree(ctx->attributes);
2289 	}
2290 	if (ctx->attributeGroups) {
2291 		zend_hash_destroy(ctx->attributeGroups);
2292 		efree(ctx->attributeGroups);
2293 	}
2294 }
2295 
delete_model(void * handle)2296 void delete_model(void *handle)
2297 {
2298 	sdlContentModelPtr tmp = *((sdlContentModelPtr*)handle);
2299 	switch (tmp->kind) {
2300 		case XSD_CONTENT_ELEMENT:
2301 		case XSD_CONTENT_GROUP:
2302 			break;
2303 		case XSD_CONTENT_SEQUENCE:
2304 		case XSD_CONTENT_ALL:
2305 		case XSD_CONTENT_CHOICE:
2306 			zend_hash_destroy(tmp->u.content);
2307 			efree(tmp->u.content);
2308 			break;
2309 		case XSD_CONTENT_GROUP_REF:
2310 			efree(tmp->u.group_ref);
2311 			break;
2312 		default:
2313 			break;
2314 	}
2315 	efree(tmp);
2316 }
2317 
delete_model_persistent(void * handle)2318 void delete_model_persistent(void *handle)
2319 {
2320 	sdlContentModelPtr tmp = *((sdlContentModelPtr*)handle);
2321 	switch (tmp->kind) {
2322 		case XSD_CONTENT_ELEMENT:
2323 		case XSD_CONTENT_GROUP:
2324 			break;
2325 		case XSD_CONTENT_SEQUENCE:
2326 		case XSD_CONTENT_ALL:
2327 		case XSD_CONTENT_CHOICE:
2328 			zend_hash_destroy(tmp->u.content);
2329 			free(tmp->u.content);
2330 			break;
2331 		case XSD_CONTENT_GROUP_REF:
2332 			free(tmp->u.group_ref);
2333 			break;
2334 		default:
2335 			break;
2336 	}
2337 	free(tmp);
2338 }
2339 
delete_type(void * data)2340 void delete_type(void *data)
2341 {
2342 	sdlTypePtr type = *((sdlTypePtr*)data);
2343 
2344 	if (type->name) {
2345 		efree(type->name);
2346 	}
2347 	if (type->namens) {
2348 		efree(type->namens);
2349 	}
2350 	if (type->def) {
2351 		efree(type->def);
2352 	}
2353 	if (type->fixed) {
2354 		efree(type->fixed);
2355 	}
2356 	if (type->elements) {
2357 		zend_hash_destroy(type->elements);
2358 		efree(type->elements);
2359 	}
2360 	if (type->attributes) {
2361 		zend_hash_destroy(type->attributes);
2362 		efree(type->attributes);
2363 	}
2364 	if (type->model) {
2365 		delete_model((void**)&type->model);
2366 	}
2367 	if (type->restrictions) {
2368 		delete_restriction_var_int(&type->restrictions->minExclusive);
2369 		delete_restriction_var_int(&type->restrictions->minInclusive);
2370 		delete_restriction_var_int(&type->restrictions->maxExclusive);
2371 		delete_restriction_var_int(&type->restrictions->maxInclusive);
2372 		delete_restriction_var_int(&type->restrictions->totalDigits);
2373 		delete_restriction_var_int(&type->restrictions->fractionDigits);
2374 		delete_restriction_var_int(&type->restrictions->length);
2375 		delete_restriction_var_int(&type->restrictions->minLength);
2376 		delete_restriction_var_int(&type->restrictions->maxLength);
2377 		delete_restriction_var_char(&type->restrictions->whiteSpace);
2378 		delete_restriction_var_char(&type->restrictions->pattern);
2379 		if (type->restrictions->enumeration) {
2380 			zend_hash_destroy(type->restrictions->enumeration);
2381 			efree(type->restrictions->enumeration);
2382 		}
2383 		efree(type->restrictions);
2384 	}
2385 	efree(type);
2386 }
2387 
delete_type_persistent(void * data)2388 void delete_type_persistent(void *data)
2389 {
2390 	sdlTypePtr type = *((sdlTypePtr*)data);
2391 	if (type->name) {
2392 		free(type->name);
2393 	}
2394 	if (type->namens) {
2395 		free(type->namens);
2396 	}
2397 	if (type->def) {
2398 		free(type->def);
2399 	}
2400 	if (type->fixed) {
2401 		free(type->fixed);
2402 	}
2403 	if (type->elements) {
2404 		zend_hash_destroy(type->elements);
2405 		free(type->elements);
2406 	}
2407 	if (type->attributes) {
2408 		zend_hash_destroy(type->attributes);
2409 		free(type->attributes);
2410 	}
2411 	if (type->model) {
2412 		delete_model_persistent((void**)&type->model);
2413 	}
2414 	if (type->restrictions) {
2415 		delete_restriction_var_int_persistent(&type->restrictions->minExclusive);
2416 		delete_restriction_var_int_persistent(&type->restrictions->minInclusive);
2417 		delete_restriction_var_int_persistent(&type->restrictions->maxExclusive);
2418 		delete_restriction_var_int_persistent(&type->restrictions->maxInclusive);
2419 		delete_restriction_var_int_persistent(&type->restrictions->totalDigits);
2420 		delete_restriction_var_int_persistent(&type->restrictions->fractionDigits);
2421 		delete_restriction_var_int_persistent(&type->restrictions->length);
2422 		delete_restriction_var_int_persistent(&type->restrictions->minLength);
2423 		delete_restriction_var_int_persistent(&type->restrictions->maxLength);
2424 		delete_restriction_var_char_persistent(&type->restrictions->whiteSpace);
2425 		delete_restriction_var_char_persistent(&type->restrictions->pattern);
2426 		if (type->restrictions->enumeration) {
2427 			zend_hash_destroy(type->restrictions->enumeration);
2428 			free(type->restrictions->enumeration);
2429 		}
2430 		free(type->restrictions);
2431 	}
2432 	free(type);
2433 }
2434 
delete_extra_attribute(void * attribute)2435 void delete_extra_attribute(void *attribute)
2436 {
2437 	sdlExtraAttributePtr attr = *((sdlExtraAttributePtr*)attribute);
2438 
2439 	if (attr->ns) {
2440 		efree(attr->ns);
2441 	}
2442 	if (attr->val) {
2443 		efree(attr->val);
2444 	}
2445 	efree(attr);
2446 }
2447 
delete_extra_attribute_persistent(void * attribute)2448 void delete_extra_attribute_persistent(void *attribute)
2449 {
2450 	sdlExtraAttributePtr attr = *((sdlExtraAttributePtr*)attribute);
2451 
2452 	if (attr->ns) {
2453 		free(attr->ns);
2454 	}
2455 	if (attr->val) {
2456 		free(attr->val);
2457 	}
2458 	free(attr);
2459 }
2460 
delete_attribute(void * attribute)2461 void delete_attribute(void *attribute)
2462 {
2463 	sdlAttributePtr attr = *((sdlAttributePtr*)attribute);
2464 
2465 	if (attr->def) {
2466 		efree(attr->def);
2467 	}
2468 	if (attr->fixed) {
2469 		efree(attr->fixed);
2470 	}
2471 	if (attr->name) {
2472 		efree(attr->name);
2473 	}
2474 	if (attr->namens) {
2475 		efree(attr->namens);
2476 	}
2477 	if (attr->ref) {
2478 		efree(attr->ref);
2479 	}
2480 	if (attr->extraAttributes) {
2481 		zend_hash_destroy(attr->extraAttributes);
2482 		efree(attr->extraAttributes);
2483 	}
2484 	efree(attr);
2485 }
2486 
delete_attribute_persistent(void * attribute)2487 void delete_attribute_persistent(void *attribute)
2488 {
2489 	sdlAttributePtr attr = *((sdlAttributePtr*)attribute);
2490 
2491 	if (attr->def) {
2492 		free(attr->def);
2493 	}
2494 	if (attr->fixed) {
2495 		free(attr->fixed);
2496 	}
2497 	if (attr->name) {
2498 		free(attr->name);
2499 	}
2500 	if (attr->namens) {
2501 		free(attr->namens);
2502 	}
2503 	if (attr->ref) {
2504 		free(attr->ref);
2505 	}
2506 	if (attr->extraAttributes) {
2507 		zend_hash_destroy(attr->extraAttributes);
2508 		free(attr->extraAttributes);
2509 	}
2510 	free(attr);
2511 }
2512 
delete_restriction_var_int(void * rvi)2513 void delete_restriction_var_int(void *rvi)
2514 {
2515 	sdlRestrictionIntPtr ptr = *((sdlRestrictionIntPtr*)rvi);
2516 	if (ptr) {
2517 		efree(ptr);
2518 	}
2519 }
2520 
delete_restriction_var_int_persistent(void * rvi)2521 void delete_restriction_var_int_persistent(void *rvi)
2522 {
2523 	sdlRestrictionIntPtr ptr = *((sdlRestrictionIntPtr*)rvi);
2524 	if (ptr) {
2525 		free(ptr);
2526 	}
2527 }
2528 
delete_restriction_var_char(void * srvc)2529 void delete_restriction_var_char(void *srvc)
2530 {
2531 	sdlRestrictionCharPtr ptr = *((sdlRestrictionCharPtr*)srvc);
2532 	if (ptr) {
2533 		if (ptr->value) {
2534 			efree(ptr->value);
2535 		}
2536 		efree(ptr);
2537 	}
2538 }
2539 
delete_restriction_var_char_persistent(void * srvc)2540 void delete_restriction_var_char_persistent(void *srvc)
2541 {
2542 	sdlRestrictionCharPtr ptr = *((sdlRestrictionCharPtr*)srvc);
2543 	if (ptr) {
2544 		if (ptr->value) {
2545 			free(ptr->value);
2546 		}
2547 		free(ptr);
2548 	}
2549 }
2550