xref: /PHP-5.5/ext/soap/php_schema.c (revision 73c1be26)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2015 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 			} else {
1085 				xmlAttrPtr ns = get_attribute(groupType->properties, "targetNamespace");
1086 				if (ns == NULL) {
1087 					ns = tns;
1088 				}
1089 				if (ns) {
1090 					smart_str_appends(&key, (char*)ns->children->content);
1091 				}
1092 			}
1093 			smart_str_appendc(&key, ':');
1094 			smart_str_appends(&key, type);
1095 			smart_str_0(&key);
1096 
1097 			newModel = emalloc(sizeof(sdlContentModel));
1098 			newModel->kind = XSD_CONTENT_GROUP_REF;
1099 			newModel->u.group_ref = estrdup(key.c);
1100 
1101 			if (type) {efree(type);}
1102 			if (ns) {efree(ns);}
1103 		} else {
1104 			newModel = emalloc(sizeof(sdlContentModel));
1105 			newModel->kind = XSD_CONTENT_SEQUENCE; /* will be redefined */
1106 			newModel->u.content = emalloc(sizeof(HashTable));
1107 			zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
1108 
1109 			smart_str_appends(&key, (char*)ns->children->content);
1110 			smart_str_appendc(&key, ':');
1111 			smart_str_appends(&key, (char*)name->children->content);
1112 			smart_str_0(&key);
1113 		}
1114 
1115 		if (cur_type == NULL) {
1116 			sdlTypePtr newType;
1117 
1118 			newType = emalloc(sizeof(sdlType));
1119 			memset(newType, 0, sizeof(sdlType));
1120 
1121 			if (sdl->groups == NULL) {
1122 				sdl->groups = emalloc(sizeof(HashTable));
1123 				zend_hash_init(sdl->groups, 0, NULL, delete_type, 0);
1124 			}
1125 			if (zend_hash_add(sdl->groups, key.c, key.len+1, (void**)&newType, sizeof(sdlTypePtr), NULL) != SUCCESS) {
1126 				soap_error1(E_ERROR, "Parsing Schema: group '%s' already defined", key.c);
1127 			}
1128 
1129 			cur_type = newType;
1130 		}
1131 		smart_str_free(&key);
1132 
1133 		if (model == NULL) {
1134 			cur_type->model = newModel;
1135 		} else {
1136 			zend_hash_next_index_insert(model->u.content, &newModel, sizeof(sdlContentModelPtr), NULL);
1137 		}
1138 	} else {
1139 		soap_error0(E_ERROR, "Parsing Schema: group has no 'name' nor 'ref' attributes");
1140 	}
1141 
1142 	schema_min_max(groupType, newModel);
1143 
1144 	trav = groupType->children;
1145 	if (trav != NULL && node_is_equal(trav,"annotation")) {
1146 		/* TODO: <annotation> support */
1147 		trav = trav->next;
1148 	}
1149 	if (trav != NULL) {
1150 		if (node_is_equal(trav,"choice")) {
1151 			if (ref != NULL) {
1152 				soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent");
1153 			}
1154 			newModel->kind = XSD_CONTENT_CHOICE;
1155 			schema_choice(sdl, tns, trav, cur_type, newModel);
1156 			trav = trav->next;
1157 		} else if (node_is_equal(trav,"sequence")) {
1158 			if (ref != NULL) {
1159 				soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent");
1160 			}
1161 			newModel->kind = XSD_CONTENT_SEQUENCE;
1162 			schema_sequence(sdl, tns, trav, cur_type, newModel);
1163 			trav = trav->next;
1164 		} else if (node_is_equal(trav,"all")) {
1165 			if (ref != NULL) {
1166 				soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent");
1167 			}
1168 			newModel->kind = XSD_CONTENT_ALL;
1169 			schema_all(sdl, tns, trav, cur_type, newModel);
1170 			trav = trav->next;
1171 		} else {
1172 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in group", trav->name);
1173 		}
1174 	}
1175 	if (trav != NULL) {
1176 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in group", trav->name);
1177 	}
1178 	return TRUE;
1179 }
1180 /*
1181 <choice
1182   id = ID
1183   maxOccurs = (nonNegativeInteger | unbounded)  : 1
1184   minOccurs = nonNegativeInteger : 1
1185   {any attributes with non-schema namespace . . .}>
1186   Content: (annotation?, (element | group | choice | sequence | any)*)
1187 </choice>
1188 */
schema_choice(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr choiceType,sdlTypePtr cur_type,sdlContentModelPtr model)1189 static int schema_choice(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr choiceType, sdlTypePtr cur_type, sdlContentModelPtr model)
1190 {
1191 	xmlNodePtr trav;
1192 	sdlContentModelPtr newModel;
1193 
1194 	newModel = emalloc(sizeof(sdlContentModel));
1195 	newModel->kind = XSD_CONTENT_CHOICE;
1196 	newModel->u.content = emalloc(sizeof(HashTable));
1197 	zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
1198 	if (model == NULL) {
1199 		cur_type->model = newModel;
1200 	} else {
1201 		zend_hash_next_index_insert(model->u.content,&newModel,sizeof(sdlContentModelPtr), NULL);
1202 	}
1203 
1204 	schema_min_max(choiceType, newModel);
1205 
1206 	trav = choiceType->children;
1207 	if (trav != NULL && node_is_equal(trav,"annotation")) {
1208 		/* TODO: <annotation> support */
1209 		trav = trav->next;
1210 	}
1211 	while (trav != NULL) {
1212 		if (node_is_equal(trav,"element")) {
1213 			schema_element(sdl, tns, trav, cur_type, newModel);
1214 		} else if (node_is_equal(trav,"group")) {
1215 			schema_group(sdl, tns, trav, cur_type, newModel);
1216 		} else if (node_is_equal(trav,"choice")) {
1217 			schema_choice(sdl, tns, trav, cur_type, newModel);
1218 		} else if (node_is_equal(trav,"sequence")) {
1219 			schema_sequence(sdl, tns, trav, cur_type, newModel);
1220 		} else if (node_is_equal(trav,"any")) {
1221 			schema_any(sdl, tns, trav, cur_type, newModel);
1222 		} else {
1223 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in choice", trav->name);
1224 		}
1225 		trav = trav->next;
1226 	}
1227 	return TRUE;
1228 }
1229 
1230 /*
1231 <sequence
1232   id = ID
1233   maxOccurs = (nonNegativeInteger | unbounded)  : 1
1234   minOccurs = nonNegativeInteger : 1
1235   {any attributes with non-schema namespace . . .}>
1236   Content: (annotation?, (element | group | choice | sequence | any)*)
1237 </sequence>
1238 */
schema_sequence(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr seqType,sdlTypePtr cur_type,sdlContentModelPtr model)1239 static int schema_sequence(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr seqType, sdlTypePtr cur_type, sdlContentModelPtr model)
1240 {
1241 	xmlNodePtr trav;
1242 	sdlContentModelPtr newModel;
1243 
1244 	newModel = emalloc(sizeof(sdlContentModel));
1245 	newModel->kind = XSD_CONTENT_SEQUENCE;
1246 	newModel->u.content = emalloc(sizeof(HashTable));
1247 	zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
1248 	if (model == NULL) {
1249 		cur_type->model = newModel;
1250 	} else {
1251 		zend_hash_next_index_insert(model->u.content,&newModel,sizeof(sdlContentModelPtr), NULL);
1252 	}
1253 
1254 	schema_min_max(seqType, newModel);
1255 
1256 	trav = seqType->children;
1257 	if (trav != NULL && node_is_equal(trav,"annotation")) {
1258 		/* TODO: <annotation> support */
1259 		trav = trav->next;
1260 	}
1261 	while (trav != NULL) {
1262 		if (node_is_equal(trav,"element")) {
1263 			schema_element(sdl, tns, trav, cur_type, newModel);
1264 		} else if (node_is_equal(trav,"group")) {
1265 			schema_group(sdl, tns, trav, cur_type, newModel);
1266 		} else if (node_is_equal(trav,"choice")) {
1267 			schema_choice(sdl, tns, trav, cur_type, newModel);
1268 		} else if (node_is_equal(trav,"sequence")) {
1269 			schema_sequence(sdl, tns, trav, cur_type, newModel);
1270 		} else if (node_is_equal(trav,"any")) {
1271 			schema_any(sdl, tns, trav, cur_type, newModel);
1272 		} else {
1273 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in sequence", trav->name);
1274 		}
1275 		trav = trav->next;
1276 	}
1277 	return TRUE;
1278 }
1279 
1280 /*
1281 <any
1282   id = ID
1283   maxOccurs = (nonNegativeInteger | unbounded)  : 1
1284   minOccurs = nonNegativeInteger : 1
1285   namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) )  : ##any
1286   processContents = (lax | skip | strict) : strict
1287   {any attributes with non-schema namespace . . .}>
1288   Content: (annotation?)
1289 </any>
1290 */
schema_any(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr anyType,sdlTypePtr cur_type,sdlContentModelPtr model)1291 static int schema_any(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr anyType, sdlTypePtr cur_type, sdlContentModelPtr model)
1292 {
1293 	if (model != NULL) {
1294 		sdlContentModelPtr newModel;
1295 
1296 		newModel = emalloc(sizeof(sdlContentModel));
1297 		newModel->kind = XSD_CONTENT_ANY;
1298 
1299 		schema_min_max(anyType, newModel);
1300 
1301 		zend_hash_next_index_insert(model->u.content, &newModel, sizeof(sdlContentModelPtr), NULL);
1302 	}
1303 	return TRUE;
1304 }
1305 
1306 /*
1307 <complexContent
1308   id = ID
1309   mixed = boolean
1310   {any attributes with non-schema namespace . . .}>
1311   Content: (annotation?, (restriction | extension))
1312 </complexContent>
1313 */
schema_complexContent(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr compCont,sdlTypePtr cur_type)1314 static int schema_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr compCont, sdlTypePtr cur_type)
1315 {
1316 	xmlNodePtr trav;
1317 
1318 	trav = compCont->children;
1319 	if (trav != NULL && node_is_equal(trav,"annotation")) {
1320 		/* TODO: <annotation> support */
1321 		trav = trav->next;
1322 	}
1323 	if (trav != NULL) {
1324 		if (node_is_equal(trav, "restriction")) {
1325 			cur_type->kind = XSD_TYPEKIND_RESTRICTION;
1326 			schema_restriction_complexContent(sdl, tns, trav, cur_type);
1327 			trav = trav->next;
1328 		} else if (node_is_equal(trav, "extension")) {
1329 			cur_type->kind = XSD_TYPEKIND_EXTENSION;
1330 			schema_extension_complexContent(sdl, tns, trav, cur_type);
1331 			trav = trav->next;
1332 		} else {
1333 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexContent", trav->name);
1334 		}
1335 	} else {
1336 		soap_error0(E_ERROR, "Parsing Schema: <restriction> or <extension> expected in complexContent");
1337 	}
1338 	if (trav != NULL) {
1339 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexContent", trav->name);
1340 	}
1341 
1342 	return TRUE;
1343 }
1344 
1345 /*
1346 <complexType
1347   abstract = boolean : false
1348   block = (#all | List of (extension | restriction))
1349   final = (#all | List of (extension | restriction))
1350   id = ID
1351   mixed = boolean : false
1352   name = NCName
1353   {any attributes with non-schema namespace . . .}>
1354   Content: (annotation?, (simpleContent | complexContent | ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?))))
1355 </complexType>
1356 */
schema_complexType(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr compType,sdlTypePtr cur_type)1357 static int schema_complexType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr compType, sdlTypePtr cur_type)
1358 {
1359 	xmlNodePtr trav;
1360 	xmlAttrPtr attrs, name, ns;
1361 
1362 	attrs = compType->properties;
1363 	ns = get_attribute(attrs, "targetNamespace");
1364 	if (ns == NULL) {
1365 		ns = tns;
1366 	}
1367 
1368 	name = get_attribute(attrs, "name");
1369 	if (cur_type != NULL) {
1370 		/* Anonymous type inside <element> */
1371 		sdlTypePtr newType, *ptr;
1372 
1373 		newType = emalloc(sizeof(sdlType));
1374 		memset(newType, 0, sizeof(sdlType));
1375 		newType->kind = XSD_TYPEKIND_COMPLEX;
1376 		if (name != NULL) {
1377 			newType->name = estrdup((char*)name->children->content);
1378 			newType->namens = estrdup((char*)ns->children->content);
1379 		} else {
1380 			newType->name = estrdup(cur_type->name);
1381 			newType->namens = estrdup(cur_type->namens);
1382 		}
1383 
1384 		zend_hash_next_index_insert(sdl->types,  &newType, sizeof(sdlTypePtr), (void **)&ptr);
1385 
1386 		if (sdl->encoders == NULL) {
1387 			sdl->encoders = emalloc(sizeof(HashTable));
1388 			zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, 0);
1389 		}
1390 		cur_type->encode = emalloc(sizeof(encode));
1391 		memset(cur_type->encode, 0, sizeof(encode));
1392 		cur_type->encode->details.ns = estrdup(newType->namens);
1393 		cur_type->encode->details.type_str = estrdup(newType->name);
1394 		cur_type->encode->details.sdl_type = *ptr;
1395 		cur_type->encode->to_xml = sdl_guess_convert_xml;
1396 		cur_type->encode->to_zval = sdl_guess_convert_zval;
1397 		zend_hash_next_index_insert(sdl->encoders,  &cur_type->encode, sizeof(encodePtr), NULL);
1398 
1399 		cur_type =*ptr;
1400 
1401 	} else if (name) {
1402 		sdlTypePtr newType, *ptr;
1403 
1404 		newType = emalloc(sizeof(sdlType));
1405 		memset(newType, 0, sizeof(sdlType));
1406 		newType->kind = XSD_TYPEKIND_COMPLEX;
1407 		newType->name = estrdup((char*)name->children->content);
1408 		newType->namens = estrdup((char*)ns->children->content);
1409 
1410 		zend_hash_next_index_insert(sdl->types,  &newType, sizeof(sdlTypePtr), (void **)&ptr);
1411 
1412 		cur_type = (*ptr);
1413 		create_encoder(sdl, cur_type, ns->children->content, name->children->content);
1414 	} else {
1415 		soap_error0(E_ERROR, "Parsing Schema: complexType has no 'name' attribute");
1416 		return FALSE;
1417 	}
1418 
1419 	trav = compType->children;
1420 	if (trav != NULL && node_is_equal(trav, "annotation")) {
1421 		/* TODO: <annotation> support */
1422 		trav = trav->next;
1423 	}
1424 	if (trav != NULL) {
1425 		if (node_is_equal(trav,"simpleContent")) {
1426 			schema_simpleContent(sdl, tns, trav, cur_type);
1427 			trav = trav->next;
1428 		} else if (node_is_equal(trav,"complexContent")) {
1429 			schema_complexContent(sdl, tns, trav, cur_type);
1430 			trav = trav->next;
1431 		} else {
1432 			if (node_is_equal(trav,"group")) {
1433 				schema_group(sdl, tns, trav, cur_type, NULL);
1434 				trav = trav->next;
1435 			} else if (node_is_equal(trav,"all")) {
1436 				schema_all(sdl, tns, trav, cur_type, NULL);
1437 				trav = trav->next;
1438 			} else if (node_is_equal(trav,"choice")) {
1439 				schema_choice(sdl, tns, trav, cur_type, NULL);
1440 				trav = trav->next;
1441 			} else if (node_is_equal(trav,"sequence")) {
1442 				schema_sequence(sdl, tns, trav, cur_type, NULL);
1443 				trav = trav->next;
1444 			}
1445 			while (trav != NULL) {
1446 				if (node_is_equal(trav,"attribute")) {
1447 					schema_attribute(sdl, tns, trav, cur_type, NULL);
1448 				} else if (node_is_equal(trav,"attributeGroup")) {
1449 					schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
1450 				} else if (node_is_equal(trav,"anyAttribute")) {
1451 					/* TODO: <anyAttribute> support */
1452 					trav = trav->next;
1453 					break;
1454 				} else {
1455 					soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexType", trav->name);
1456 				}
1457 				trav = trav->next;
1458 			}
1459 		}
1460 	}
1461 	if (trav != NULL) {
1462 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexType", trav->name);
1463 	}
1464 	return TRUE;
1465 }
1466 /*
1467 <element
1468   abstract = boolean : false
1469   block = (#all | List of (extension | restriction | substitution))
1470   default = string
1471   final = (#all | List of (extension | restriction))
1472   fixed = string
1473   form = (qualified | unqualified)
1474   id = ID
1475   maxOccurs = (nonNegativeInteger | unbounded)  : 1
1476   minOccurs = nonNegativeInteger : 1
1477   name = NCName
1478   nillable = boolean : false
1479   ref = QName
1480   substitutionGroup = QName
1481   type = QName
1482   {any attributes with non-schema namespace . . .}>
1483   Content: (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*))
1484 </element>
1485 */
schema_element(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr element,sdlTypePtr cur_type,sdlContentModelPtr model)1486 static int schema_element(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr element, sdlTypePtr cur_type, sdlContentModelPtr model)
1487 {
1488 	xmlNodePtr trav;
1489 	xmlAttrPtr attrs, attr, ns, name, type, ref = NULL;
1490 
1491 	attrs = element->properties;
1492 	ns = get_attribute(attrs, "targetNamespace");
1493 	if (ns == NULL) {
1494 		ns = tns;
1495 	}
1496 
1497 	name = get_attribute(attrs, "name");
1498 	if (name == NULL) {
1499 		name = ref = get_attribute(attrs, "ref");
1500 	}
1501 
1502 	if (name) {
1503 		HashTable *addHash;
1504 		sdlTypePtr newType;
1505 		smart_str key = {0};
1506 
1507 		newType = emalloc(sizeof(sdlType));
1508 		memset(newType, 0, sizeof(sdlType));
1509 
1510 		if (ref) {
1511 			smart_str nscat = {0};
1512 			char *type, *ns;
1513 			xmlNsPtr nsptr;
1514 
1515 			parse_namespace(ref->children->content, &type, &ns);
1516 			nsptr = xmlSearchNs(element->doc, element, BAD_CAST(ns));
1517 			if (nsptr != NULL) {
1518 				smart_str_appends(&nscat, (char*)nsptr->href);
1519 				newType->namens = estrdup((char*)nsptr->href);
1520 			} else {
1521 				xmlAttrPtr ns = get_attribute(attrs, "targetNamespace");
1522 				if (ns == NULL) {
1523 					ns = tns;
1524 				}
1525 				if (ns) {
1526 					smart_str_appends(&nscat, (char*)ns->children->content);
1527 				}
1528 			}
1529 			smart_str_appendc(&nscat, ':');
1530 			smart_str_appends(&nscat, type);
1531 			newType->name = estrdup(type);
1532 			smart_str_0(&nscat);
1533 			if (type) {efree(type);}
1534 			if (ns) {efree(ns);}
1535 			newType->ref = estrdup(nscat.c);
1536 			smart_str_free(&nscat);
1537 		} else {
1538 			newType->name = estrdup((char*)name->children->content);
1539 			newType->namens = estrdup((char*)ns->children->content);
1540 		}
1541 
1542 		newType->nillable = FALSE;
1543 
1544 		if (cur_type == NULL) {
1545 			if (sdl->elements == NULL) {
1546 				sdl->elements = emalloc(sizeof(HashTable));
1547 				zend_hash_init(sdl->elements, 0, NULL, delete_type, 0);
1548 			}
1549 			addHash = sdl->elements;
1550 			smart_str_appends(&key, newType->namens);
1551 			smart_str_appendc(&key, ':');
1552 			smart_str_appends(&key, newType->name);
1553 		} else {
1554 			if (cur_type->elements == NULL) {
1555 				cur_type->elements = emalloc(sizeof(HashTable));
1556 				zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
1557 			}
1558 			addHash = cur_type->elements;
1559 			smart_str_appends(&key, newType->name);
1560 		}
1561 
1562 		smart_str_0(&key);
1563 		if (zend_hash_add(addHash, key.c, key.len + 1, &newType, sizeof(sdlTypePtr), NULL) != SUCCESS) {
1564 			if (cur_type == NULL) {
1565 				soap_error1(E_ERROR, "Parsing Schema: element '%s' already defined", key.c);
1566 			} else {
1567 				zend_hash_next_index_insert(addHash, &newType, sizeof(sdlTypePtr), NULL);
1568 			}
1569 		}
1570 		smart_str_free(&key);
1571 
1572 		if (model != NULL) {
1573 			sdlContentModelPtr newModel = emalloc(sizeof(sdlContentModel));
1574 
1575 			newModel->kind = XSD_CONTENT_ELEMENT;
1576 			newModel->u.element = newType;
1577 
1578 			schema_min_max(element, newModel);
1579 
1580 
1581 			zend_hash_next_index_insert(model->u.content, &newModel, sizeof(sdlContentModelPtr), NULL);
1582 		}
1583 		cur_type = newType;
1584 	} else {
1585 		soap_error0(E_ERROR, "Parsing Schema: element has no 'name' nor 'ref' attributes");
1586 	}
1587 
1588 	/* nillable = boolean : false */
1589 	attrs = element->properties;
1590 	attr = get_attribute(attrs, "nillable");
1591 	if (attr) {
1592 		if (ref != NULL) {
1593 			soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'nillable' attributes");
1594 		}
1595 		if (!stricmp((char*)attr->children->content, "true") ||
1596 			!stricmp((char*)attr->children->content, "1")) {
1597 			cur_type->nillable = TRUE;
1598 		} else {
1599 			cur_type->nillable = FALSE;
1600 		}
1601 	} else {
1602 		cur_type->nillable = FALSE;
1603 	}
1604 
1605 	attr = get_attribute(attrs, "fixed");
1606 	if (attr) {
1607 		if (ref != NULL) {
1608 			soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'fixed' attributes");
1609 		}
1610 		cur_type->fixed = estrdup((char*)attr->children->content);
1611 	}
1612 
1613 	attr = get_attribute(attrs, "default");
1614 	if (attr) {
1615 		if (ref != NULL) {
1616 			soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'fixed' attributes");
1617 		} else if (ref != NULL) {
1618 			soap_error0(E_ERROR, "Parsing Schema: element has both 'default' and 'fixed' attributes");
1619 		}
1620 		cur_type->def = estrdup((char*)attr->children->content);
1621 	}
1622 
1623 	/* form */
1624 	attr = get_attribute(attrs, "form");
1625 	if (attr) {
1626 		if (strncmp((char*)attr->children->content, "qualified", sizeof("qualified")) == 0) {
1627 		  cur_type->form = XSD_FORM_QUALIFIED;
1628 		} else if (strncmp((char*)attr->children->content, "unqualified", sizeof("unqualified")) == 0) {
1629 		  cur_type->form = XSD_FORM_UNQUALIFIED;
1630 		} else {
1631 		  cur_type->form = XSD_FORM_DEFAULT;
1632 		}
1633 	} else {
1634 	  cur_type->form = XSD_FORM_DEFAULT;
1635 	}
1636 	if (cur_type->form == XSD_FORM_DEFAULT) {
1637  		xmlNodePtr parent = element->parent;
1638  		while (parent) {
1639 			if (node_is_equal_ex(parent, "schema", SCHEMA_NAMESPACE)) {
1640 				xmlAttrPtr def;
1641 				def = get_attribute(parent->properties, "elementFormDefault");
1642 				if(def == NULL || strncmp((char*)def->children->content, "qualified", sizeof("qualified"))) {
1643 					cur_type->form = XSD_FORM_UNQUALIFIED;
1644 				} else {
1645 					cur_type->form = XSD_FORM_QUALIFIED;
1646 				}
1647 				break;
1648 			}
1649 			parent = parent->parent;
1650   	}
1651 		if (parent == NULL) {
1652 			cur_type->form = XSD_FORM_UNQUALIFIED;
1653 		}
1654 	}
1655 
1656 	/* type = QName */
1657 	type = get_attribute(attrs, "type");
1658 	if (type) {
1659 		char *cptype, *str_ns;
1660 		xmlNsPtr nsptr;
1661 
1662 		if (ref != NULL) {
1663 			soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'type' attributes");
1664 		}
1665 		parse_namespace(type->children->content, &cptype, &str_ns);
1666 		nsptr = xmlSearchNs(element->doc, element, BAD_CAST(str_ns));
1667 		if (nsptr != NULL) {
1668 			cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(cptype));
1669 		}
1670 		if (str_ns) {efree(str_ns);}
1671 		if (cptype) {efree(cptype);}
1672 	}
1673 
1674 	trav = element->children;
1675 	if (trav != NULL && node_is_equal(trav, "annotation")) {
1676 		/* TODO: <annotation> support */
1677 		trav = trav->next;
1678 	}
1679 	if (trav != NULL) {
1680 		if (node_is_equal(trav,"simpleType")) {
1681 			if (ref != NULL) {
1682 				soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' attribute and subtype");
1683 			} else if (type != NULL) {
1684 				soap_error0(E_ERROR, "Parsing Schema: element has both 'type' attribute and subtype");
1685 			}
1686 			schema_simpleType(sdl, tns, trav, cur_type);
1687 			trav = trav->next;
1688 		} else if (node_is_equal(trav,"complexType")) {
1689 			if (ref != NULL) {
1690 				soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' attribute and subtype");
1691 			} else if (type != NULL) {
1692 				soap_error0(E_ERROR, "Parsing Schema: element has both 'type' attribute and subtype");
1693 			}
1694 			schema_complexType(sdl, tns, trav, cur_type);
1695 			trav = trav->next;
1696 		}
1697 	}
1698 	while (trav != NULL) {
1699 		if (node_is_equal(trav,"unique")) {
1700 			/* TODO: <unique> support */
1701 		} else if (node_is_equal(trav,"key")) {
1702 			/* TODO: <key> support */
1703 		} else if (node_is_equal(trav,"keyref")) {
1704 			/* TODO: <keyref> support */
1705 		} else {
1706 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in element", trav->name);
1707 		}
1708 		trav = trav->next;
1709 	}
1710 
1711 	return TRUE;
1712 }
1713 
1714 /*
1715 <attribute
1716   default = string
1717   fixed = string
1718   form = (qualified | unqualified)
1719   id = ID
1720   name = NCName
1721   ref = QName
1722   type = QName
1723   use = (optional | prohibited | required) : optional
1724   {any attributes with non-schema namespace . . .}>
1725   Content: (annotation?, (simpleType?))
1726 </attribute>
1727 */
schema_attribute(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr attrType,sdlTypePtr cur_type,sdlCtx * ctx)1728 static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdlTypePtr cur_type, sdlCtx *ctx)
1729 {
1730 	sdlAttributePtr newAttr;
1731 	xmlAttrPtr attr, name, ref = NULL, type = NULL;
1732 	xmlNodePtr trav;
1733 
1734 	name = get_attribute(attrType->properties, "name");
1735 	if (name == NULL) {
1736 		name = ref = get_attribute(attrType->properties, "ref");
1737 	}
1738 	if (name) {
1739 		HashTable *addHash;
1740 		smart_str key = {0};
1741 
1742 		newAttr = emalloc(sizeof(sdlAttribute));
1743 		memset(newAttr, 0, sizeof(sdlAttribute));
1744 
1745 		if (ref) {
1746 			char *attr_name, *ns;
1747 			xmlNsPtr nsptr;
1748 
1749 			parse_namespace(ref->children->content, &attr_name, &ns);
1750 			nsptr = xmlSearchNs(attrType->doc, attrType, BAD_CAST(ns));
1751 			if (nsptr != NULL) {
1752 				smart_str_appends(&key, (char*)nsptr->href);
1753 				newAttr->namens = estrdup((char*)nsptr->href);
1754 			} else {
1755 				xmlAttrPtr ns = get_attribute(attrType->properties, "targetNamespace");
1756 				if (ns == NULL) {
1757 					ns = tns;
1758 				}
1759 				if (ns) {
1760 					smart_str_appends(&key, (char*)ns->children->content);
1761 				}
1762 			}
1763 			smart_str_appendc(&key, ':');
1764 			smart_str_appends(&key, attr_name);
1765 			smart_str_0(&key);
1766 			newAttr->ref = estrdup(key.c);
1767 			if (attr_name) {efree(attr_name);}
1768 			if (ns) {efree(ns);}
1769 		} else {
1770 			xmlAttrPtr ns;
1771 
1772 			ns = get_attribute(attrType->properties, "targetNamespace");
1773 			if (ns == NULL) {
1774 				ns = tns;
1775 			}
1776 			if (ns != NULL) {
1777 				smart_str_appends(&key, (char*)ns->children->content);
1778 				smart_str_appendc(&key, ':');
1779 				newAttr->namens = estrdup((char*)ns->children->content);
1780 			}
1781 			smart_str_appends(&key, (char*)name->children->content);
1782 			smart_str_0(&key);
1783 		}
1784 
1785 		if (cur_type == NULL) {
1786 			addHash = ctx->attributes;
1787 		} else {
1788 			if (cur_type->attributes == NULL) {
1789 				cur_type->attributes = emalloc(sizeof(HashTable));
1790 				zend_hash_init(cur_type->attributes, 0, NULL, delete_attribute, 0);
1791 			}
1792 			addHash = cur_type->attributes;
1793 		}
1794 
1795 		if (zend_hash_add(addHash, key.c, key.len + 1, &newAttr, sizeof(sdlAttributePtr), NULL) != SUCCESS) {
1796 			soap_error1(E_ERROR, "Parsing Schema: attribute '%s' already defined", key.c);
1797 		}
1798 		smart_str_free(&key);
1799 	} else{
1800 		soap_error0(E_ERROR, "Parsing Schema: attribute has no 'name' nor 'ref' attributes");
1801 	}
1802 
1803 	/* type = QName */
1804 	type = get_attribute(attrType->properties, "type");
1805 	if (type) {
1806 		char *cptype, *str_ns;
1807 		xmlNsPtr nsptr;
1808 
1809 		if (ref != NULL) {
1810 			soap_error0(E_ERROR, "Parsing Schema: attribute has both 'ref' and 'type' attributes");
1811 		}
1812 		parse_namespace(type->children->content, &cptype, &str_ns);
1813 		nsptr = xmlSearchNs(attrType->doc, attrType, BAD_CAST(str_ns));
1814 		if (nsptr != NULL) {
1815 			newAttr->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(cptype));
1816 		}
1817 		if (str_ns) {efree(str_ns);}
1818 		if (cptype) {efree(cptype);}
1819 	}
1820 
1821 	attr = attrType->properties;
1822 	while (attr != NULL) {
1823 		if (attr_is_equal_ex(attr, "default", SCHEMA_NAMESPACE)) {
1824 			newAttr->def = estrdup((char*)attr->children->content);
1825 		} else if (attr_is_equal_ex(attr, "fixed", SCHEMA_NAMESPACE)) {
1826 			newAttr->fixed = estrdup((char*)attr->children->content);
1827 		} else if (attr_is_equal_ex(attr, "form", SCHEMA_NAMESPACE)) {
1828 			if (strncmp((char*)attr->children->content, "qualified", sizeof("qualified")) == 0) {
1829 			  newAttr->form = XSD_FORM_QUALIFIED;
1830 			} else if (strncmp((char*)attr->children->content, "unqualified", sizeof("unqualified")) == 0) {
1831 			  newAttr->form = XSD_FORM_UNQUALIFIED;
1832 			} else {
1833 			  newAttr->form = XSD_FORM_DEFAULT;
1834 			}
1835 		} else if (attr_is_equal_ex(attr, "id", SCHEMA_NAMESPACE)) {
1836 			/* skip */
1837 		} else if (attr_is_equal_ex(attr, "name", SCHEMA_NAMESPACE)) {
1838 			newAttr->name = estrdup((char*)attr->children->content);
1839 		} else if (attr_is_equal_ex(attr, "ref", SCHEMA_NAMESPACE)) {
1840 			/* already processed */
1841 		} else if (attr_is_equal_ex(attr, "type", SCHEMA_NAMESPACE)) {
1842 			/* already processed */
1843 		} else if (attr_is_equal_ex(attr, "use", SCHEMA_NAMESPACE)) {
1844 			if (strncmp((char*)attr->children->content, "prohibited", sizeof("prohibited")) == 0) {
1845 			  newAttr->use = XSD_USE_PROHIBITED;
1846 			} else if (strncmp((char*)attr->children->content, "required", sizeof("required")) == 0) {
1847 			  newAttr->use = XSD_USE_REQUIRED;
1848 			} else if (strncmp((char*)attr->children->content, "optional", sizeof("optional")) == 0) {
1849 			  newAttr->use = XSD_USE_OPTIONAL;
1850 			} else {
1851 			  newAttr->use = XSD_USE_DEFAULT;
1852 			}
1853 		} else {
1854 			xmlNsPtr nsPtr = attr_find_ns(attr);
1855 
1856 			if (strncmp((char*)nsPtr->href, SCHEMA_NAMESPACE, sizeof(SCHEMA_NAMESPACE))) {
1857 				smart_str key2 = {0};
1858 				sdlExtraAttributePtr ext;
1859 				xmlNsPtr nsptr;
1860 				char *value, *ns;
1861 
1862 				ext = emalloc(sizeof(sdlExtraAttribute));
1863 				memset(ext, 0, sizeof(sdlExtraAttribute));
1864 				parse_namespace(attr->children->content, &value, &ns);
1865 				nsptr = xmlSearchNs(attr->doc, attr->parent, BAD_CAST(ns));
1866 				if (nsptr) {
1867 					ext->ns = estrdup((char*)nsptr->href);
1868 					ext->val = estrdup(value);
1869 				} else {
1870 					ext->val = estrdup((char*)attr->children->content);
1871 				}
1872 				if (ns) {efree(ns);}
1873 				efree(value);
1874 
1875 				if (!newAttr->extraAttributes) {
1876 					newAttr->extraAttributes = emalloc(sizeof(HashTable));
1877 					zend_hash_init(newAttr->extraAttributes, 0, NULL, delete_extra_attribute, 0);
1878 				}
1879 
1880 				smart_str_appends(&key2, (char*)nsPtr->href);
1881 				smart_str_appendc(&key2, ':');
1882 				smart_str_appends(&key2, (char*)attr->name);
1883 				smart_str_0(&key2);
1884 				zend_hash_add(newAttr->extraAttributes, key2.c, key2.len + 1, &ext, sizeof(sdlExtraAttributePtr), NULL);
1885 				smart_str_free(&key2);
1886 			}
1887 		}
1888 		attr = attr->next;
1889 	}
1890 	if (newAttr->form == XSD_FORM_DEFAULT) {
1891  		xmlNodePtr parent = attrType->parent;
1892  		while (parent) {
1893 			if (node_is_equal_ex(parent, "schema", SCHEMA_NAMESPACE)) {
1894 				xmlAttrPtr def;
1895 				def = get_attribute(parent->properties, "attributeFormDefault");
1896 				if(def == NULL || strncmp((char*)def->children->content, "qualified", sizeof("qualified"))) {
1897 					newAttr->form = XSD_FORM_UNQUALIFIED;
1898 				} else {
1899 					newAttr->form = XSD_FORM_QUALIFIED;
1900 				}
1901 				break;
1902 			}
1903 			parent = parent->parent;
1904   	}
1905 		if (parent == NULL) {
1906 			newAttr->form = XSD_FORM_UNQUALIFIED;
1907 		}
1908 	}
1909 	trav = attrType->children;
1910 	if (trav != NULL && node_is_equal(trav, "annotation")) {
1911 		/* TODO: <annotation> support */
1912 		trav = trav->next;
1913 	}
1914 	if (trav != NULL) {
1915 		if (node_is_equal(trav,"simpleType")) {
1916 			sdlTypePtr dummy_type;
1917 			if (ref != NULL) {
1918 				soap_error0(E_ERROR, "Parsing Schema: attribute has both 'ref' attribute and subtype");
1919 			} else if (type != NULL) {
1920 				soap_error0(E_ERROR, "Parsing Schema: attribute has both 'type' attribute and subtype");
1921 			}
1922 			dummy_type = emalloc(sizeof(sdlType));
1923 			memset(dummy_type, 0, sizeof(sdlType));
1924 			{
1925 				smart_str anonymous = {0};
1926 
1927 				smart_str_appendl(&anonymous, "anonymous", sizeof("anonymous")-1);
1928 				smart_str_append_long(&anonymous, zend_hash_num_elements(sdl->types));
1929 				smart_str_0(&anonymous);
1930 				dummy_type->name = anonymous.c;
1931 			}
1932 			dummy_type->namens = estrdup((char*)tns->children->content);
1933 			schema_simpleType(sdl, tns, trav, dummy_type);
1934 			newAttr->encode = dummy_type->encode;
1935 			delete_type(&dummy_type);
1936 			trav = trav->next;
1937 		}
1938 	}
1939 	if (trav != NULL) {
1940 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attribute", trav->name);
1941 	}
1942 	return TRUE;
1943 }
1944 
schema_attributeGroup(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr attrGroup,sdlTypePtr cur_type,sdlCtx * ctx)1945 static int schema_attributeGroup(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrGroup, sdlTypePtr cur_type, sdlCtx *ctx)
1946 {
1947 	xmlNodePtr trav;
1948 	xmlAttrPtr name, ref = NULL;
1949 
1950 
1951 	name = get_attribute(attrGroup->properties, "name");
1952 	if (name == NULL) {
1953 		name = ref = get_attribute(attrGroup->properties, "ref");
1954 	}
1955 	if (name) {
1956 		if (cur_type == NULL) {
1957 			xmlAttrPtr ns;
1958 			sdlTypePtr newType;
1959 			smart_str key = {0};
1960 
1961 			ns = get_attribute(attrGroup->properties, "targetNamespace");
1962 			if (ns == NULL) {
1963 				ns = tns;
1964 			}
1965 			newType = emalloc(sizeof(sdlType));
1966 			memset(newType, 0, sizeof(sdlType));
1967 			newType->name = estrdup((char*)name->children->content);
1968 			newType->namens = estrdup((char*)ns->children->content);
1969 
1970 			smart_str_appends(&key, newType->namens);
1971 			smart_str_appendc(&key, ':');
1972 			smart_str_appends(&key, newType->name);
1973 			smart_str_0(&key);
1974 
1975 			if (zend_hash_add(ctx->attributeGroups, key.c, key.len + 1, &newType, sizeof(sdlTypePtr), NULL) != SUCCESS) {
1976 				soap_error1(E_ERROR, "Parsing Schema: attributeGroup '%s' already defined", key.c);
1977 			}
1978 			cur_type = newType;
1979 			smart_str_free(&key);
1980 		} else if (ref) {
1981 			sdlAttributePtr newAttr;
1982 			char *group_name, *ns;
1983 			smart_str key = {0};
1984 			xmlNsPtr nsptr;
1985 
1986 			if (cur_type->attributes == NULL) {
1987 				cur_type->attributes = emalloc(sizeof(HashTable));
1988 				zend_hash_init(cur_type->attributes, 0, NULL, delete_attribute, 0);
1989 			}
1990 			newAttr = emalloc(sizeof(sdlAttribute));
1991 			memset(newAttr, 0, sizeof(sdlAttribute));
1992 
1993 			parse_namespace(ref->children->content, &group_name, &ns);
1994 			nsptr = xmlSearchNs(attrGroup->doc, attrGroup, BAD_CAST(ns));
1995 			if (nsptr != NULL) {
1996 				smart_str_appends(&key, (char*)nsptr->href);
1997 			}
1998 			smart_str_appendc(&key, ':');
1999 			smart_str_appends(&key, group_name);
2000 			smart_str_0(&key);
2001 			newAttr->ref = estrdup(key.c);
2002 			if (group_name) {efree(group_name);}
2003 			if (ns) {efree(ns);}
2004 			smart_str_free(&key);
2005 
2006 			zend_hash_next_index_insert(cur_type->attributes, &newAttr, sizeof(sdlAttributePtr), NULL);
2007 			cur_type = NULL;
2008 		}
2009 	} else{
2010 		soap_error0(E_ERROR, "Parsing Schema: attributeGroup has no 'name' nor 'ref' attributes");
2011 	}
2012 
2013 	trav = attrGroup->children;
2014 	if (trav != NULL && node_is_equal(trav, "annotation")) {
2015 		/* TODO: <annotation> support */
2016 		trav = trav->next;
2017 	}
2018 	while (trav != NULL) {
2019 		if (node_is_equal(trav,"attribute")) {
2020 			if (ref != NULL) {
2021 				soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
2022 			}
2023 			schema_attribute(sdl, tns, trav, cur_type, NULL);
2024 		} else if (node_is_equal(trav,"attributeGroup")) {
2025 			if (ref != NULL) {
2026 				soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
2027 			}
2028 			schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
2029 		} else if (node_is_equal(trav,"anyAttribute")) {
2030 			if (ref != NULL) {
2031 				soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
2032 			}
2033 			/* TODO: <anyAttribute> support */
2034 			trav = trav->next;
2035 			break;
2036 		} else {
2037 			soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attributeGroup", trav->name);
2038 		}
2039 		trav = trav->next;
2040 	}
2041 	if (trav != NULL) {
2042 		soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attributeGroup", trav->name);
2043 	}
2044 	return TRUE;
2045 }
2046 
copy_extra_attribute(void * attribute)2047 static void copy_extra_attribute(void *attribute)
2048 {
2049 	sdlExtraAttributePtr *attr = (sdlExtraAttributePtr*)attribute;
2050 	sdlExtraAttributePtr new_attr;
2051 
2052 	new_attr = emalloc(sizeof(sdlExtraAttribute));
2053 	memcpy(new_attr, *attr, sizeof(sdlExtraAttribute));
2054 	*attr = new_attr;
2055 	if (new_attr->ns) {
2056 		new_attr->ns = estrdup(new_attr->ns);
2057 	}
2058 	if (new_attr->val) {
2059 		new_attr->val = estrdup(new_attr->val);
2060 	}
2061 }
2062 
schema_find_by_ref(HashTable * ht,char * ref)2063 static void* schema_find_by_ref(HashTable *ht, char *ref)
2064 {
2065 	void **tmp;
2066 
2067 	if (zend_hash_find(ht, ref, strlen(ref)+1, (void**)&tmp) == SUCCESS) {
2068 		return tmp;
2069 	} else {
2070 		ref = strrchr(ref, ':');
2071 		if (ref) {
2072 			if (zend_hash_find(ht, ref, strlen(ref)+1, (void**)&tmp) == SUCCESS) {
2073 				return tmp;
2074 			}
2075 		}
2076 	}
2077 	return NULL;
2078 }
2079 
schema_attribute_fixup(sdlCtx * ctx,sdlAttributePtr attr)2080 static void schema_attribute_fixup(sdlCtx *ctx, sdlAttributePtr attr)
2081 {
2082 	sdlAttributePtr *tmp;
2083 
2084 	if (attr->ref != NULL) {
2085 		if (ctx->attributes != NULL) {
2086 			tmp = (sdlAttributePtr*)schema_find_by_ref(ctx->attributes, attr->ref);
2087 			if (tmp) {
2088 				schema_attribute_fixup(ctx, *tmp);
2089 				if ((*tmp)->name != NULL && attr->name == NULL) {
2090 					attr->name = estrdup((*tmp)->name);
2091 				}
2092 				if ((*tmp)->namens != NULL && attr->namens == NULL) {
2093 					attr->namens = estrdup((*tmp)->namens);
2094 				}
2095 				if ((*tmp)->def != NULL && attr->def == NULL) {
2096 					attr->def = estrdup((*tmp)->def);
2097 				}
2098 				if ((*tmp)->fixed != NULL && attr->fixed == NULL) {
2099 					attr->fixed = estrdup((*tmp)->fixed);
2100 				}
2101 				if (attr->form == XSD_FORM_DEFAULT) {
2102 					attr->form = (*tmp)->form;
2103 				}
2104 				if (attr->use == XSD_USE_DEFAULT) {
2105 					attr->use  = (*tmp)->use;
2106 				}
2107 				if ((*tmp)->extraAttributes != NULL) {
2108 				  xmlNodePtr node;
2109 
2110 					attr->extraAttributes = emalloc(sizeof(HashTable));
2111 					zend_hash_init(attr->extraAttributes, zend_hash_num_elements((*tmp)->extraAttributes), NULL, delete_extra_attribute, 0);
2112 					zend_hash_copy(attr->extraAttributes, (*tmp)->extraAttributes, copy_extra_attribute, &node, sizeof(xmlNodePtr));
2113 				}
2114 				attr->encode = (*tmp)->encode;
2115 			}
2116 		}
2117 		if (attr->name == NULL && attr->ref != NULL) {
2118 			char *name = strrchr(attr->ref, ':');
2119 			if (name) {
2120 				attr->name = estrdup(name+1);
2121 			} else{
2122 				attr->name = estrdup(attr->ref);
2123 			}
2124 		}
2125 		efree(attr->ref);
2126 		attr->ref = NULL;
2127 	}
2128 }
2129 
schema_attributegroup_fixup(sdlCtx * ctx,sdlAttributePtr attr,HashTable * ht)2130 static void schema_attributegroup_fixup(sdlCtx *ctx, sdlAttributePtr attr, HashTable *ht)
2131 {
2132 	sdlTypePtr *tmp;
2133 	sdlAttributePtr *tmp_attr;
2134 
2135 	if (attr->ref != NULL) {
2136 		if (ctx->attributeGroups != NULL) {
2137 			tmp = (sdlTypePtr*)schema_find_by_ref(ctx->attributeGroups, attr->ref);
2138 			if (tmp) {
2139 				if ((*tmp)->attributes) {
2140 					zend_hash_internal_pointer_reset((*tmp)->attributes);
2141 					while (zend_hash_get_current_data((*tmp)->attributes,(void**)&tmp_attr) == SUCCESS) {
2142 						if (zend_hash_get_current_key_type((*tmp)->attributes) == HASH_KEY_IS_STRING) {
2143 							char* key;
2144 							uint key_len;
2145 							sdlAttributePtr newAttr;
2146 
2147 							schema_attribute_fixup(ctx,*tmp_attr);
2148 
2149 							newAttr = emalloc(sizeof(sdlAttribute));
2150 							memcpy(newAttr, *tmp_attr, sizeof(sdlAttribute));
2151 							if (newAttr->def) {newAttr->def = estrdup(newAttr->def);}
2152 							if (newAttr->fixed) {newAttr->fixed = estrdup(newAttr->fixed);}
2153 							if (newAttr->namens) {newAttr->namens = estrdup(newAttr->namens);}
2154 							if (newAttr->name) {newAttr->name = estrdup(newAttr->name);}
2155 							if (newAttr->extraAttributes) {
2156 							  xmlNodePtr node;
2157 								HashTable *ht = emalloc(sizeof(HashTable));
2158 								zend_hash_init(ht, zend_hash_num_elements(newAttr->extraAttributes), NULL, delete_extra_attribute, 0);
2159 								zend_hash_copy(ht, newAttr->extraAttributes, copy_extra_attribute, &node, sizeof(xmlNodePtr));
2160 								newAttr->extraAttributes = ht;
2161 							}
2162 
2163 							zend_hash_get_current_key_ex((*tmp)->attributes, &key, &key_len, NULL, 0, NULL);
2164 							zend_hash_add(ht, key, key_len, &newAttr, sizeof(sdlAttributePtr), NULL);
2165 
2166 							zend_hash_move_forward((*tmp)->attributes);
2167 						} else {
2168 							ulong index;
2169 
2170 							schema_attributegroup_fixup(ctx,*tmp_attr, ht);
2171 							zend_hash_get_current_key((*tmp)->attributes, NULL, &index, 0);
2172 							zend_hash_index_del((*tmp)->attributes, index);
2173 						}
2174 					}
2175 				}
2176 			}
2177 		}
2178 		efree(attr->ref);
2179 		attr->ref = NULL;
2180 	}
2181 }
2182 
schema_content_model_fixup(sdlCtx * ctx,sdlContentModelPtr model)2183 static void schema_content_model_fixup(sdlCtx *ctx, sdlContentModelPtr model)
2184 {
2185 	switch (model->kind) {
2186 		case XSD_CONTENT_GROUP_REF: {
2187 			sdlTypePtr *tmp;
2188 
2189 			if (ctx->sdl->groups && zend_hash_find(ctx->sdl->groups, model->u.group_ref, strlen(model->u.group_ref)+1, (void**)&tmp) == SUCCESS) {
2190 				schema_type_fixup(ctx,*tmp);
2191 				efree(model->u.group_ref);
2192 				model->kind = XSD_CONTENT_GROUP;
2193 				model->u.group = (*tmp);
2194 			} else {
2195 				soap_error1(E_ERROR, "Parsing Schema: unresolved group 'ref' attribute '%s'", model->u.group_ref);
2196 			}
2197 			break;
2198 		}
2199 		case XSD_CONTENT_CHOICE: {
2200 			if (model->max_occurs != 1) {
2201 				HashPosition pos;
2202 				sdlContentModelPtr *tmp;
2203 
2204 				zend_hash_internal_pointer_reset_ex(model->u.content, &pos);
2205 				while (zend_hash_get_current_data_ex(model->u.content, (void**)&tmp, &pos) == SUCCESS) {
2206 					(*tmp)->min_occurs = 0;
2207 					(*tmp)->max_occurs = model->max_occurs;
2208 					zend_hash_move_forward_ex(model->u.content, &pos);
2209 				}
2210 
2211 				model->kind = XSD_CONTENT_ALL;
2212 				model->min_occurs = 1;
2213 				model->max_occurs = 1;
2214 			}
2215 		}
2216 		case XSD_CONTENT_SEQUENCE:
2217 		case XSD_CONTENT_ALL: {
2218 			sdlContentModelPtr *tmp;
2219 
2220 			zend_hash_internal_pointer_reset(model->u.content);
2221 			while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
2222 				schema_content_model_fixup(ctx, *tmp);
2223 				zend_hash_move_forward(model->u.content);
2224 			}
2225 			break;
2226 		}
2227 		default:
2228 			break;
2229 	}
2230 }
2231 
schema_type_fixup(sdlCtx * ctx,sdlTypePtr type)2232 static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type)
2233 {
2234 	sdlTypePtr *tmp;
2235 	sdlAttributePtr *attr;
2236 
2237 	if (type->ref != NULL) {
2238 		if (ctx->sdl->elements != NULL) {
2239 			tmp = (sdlTypePtr*)schema_find_by_ref(ctx->sdl->elements, type->ref);
2240 			if (tmp) {
2241 				type->kind = (*tmp)->kind;
2242 				type->encode = (*tmp)->encode;
2243 				if ((*tmp)->nillable) {
2244 				  type->nillable = 1;
2245 				}
2246 				if ((*tmp)->fixed) {
2247 				  type->fixed = estrdup((*tmp)->fixed);
2248 				}
2249 				if ((*tmp)->def) {
2250 				  type->def = estrdup((*tmp)->def);
2251 				}
2252 				type->form = (*tmp)->form;
2253 			} else if (strcmp(type->ref, SCHEMA_NAMESPACE ":schema") == 0) {
2254 				type->encode = get_conversion(XSD_ANYXML);
2255 			} else {
2256 				soap_error1(E_ERROR, "Parsing Schema: unresolved element 'ref' attribute '%s'", type->ref);
2257 			}
2258 		}
2259 		efree(type->ref);
2260 		type->ref = NULL;
2261 	}
2262 	if (type->elements) {
2263 		zend_hash_internal_pointer_reset(type->elements);
2264 		while (zend_hash_get_current_data(type->elements,(void**)&tmp) == SUCCESS) {
2265 			schema_type_fixup(ctx,*tmp);
2266 			zend_hash_move_forward(type->elements);
2267 		}
2268 	}
2269 	if (type->model) {
2270 		schema_content_model_fixup(ctx, type->model);
2271 	}
2272 	if (type->attributes) {
2273 		zend_hash_internal_pointer_reset(type->attributes);
2274 		while (zend_hash_get_current_data(type->attributes,(void**)&attr) == SUCCESS) {
2275 			if (zend_hash_get_current_key_type(type->attributes) == HASH_KEY_IS_STRING) {
2276 				schema_attribute_fixup(ctx,*attr);
2277 				zend_hash_move_forward(type->attributes);
2278 			} else {
2279 				ulong index;
2280 
2281 				schema_attributegroup_fixup(ctx,*attr,type->attributes);
2282 				zend_hash_get_current_key(type->attributes, NULL, &index, 0);
2283 				zend_hash_index_del(type->attributes, index);
2284 			}
2285 		}
2286 	}
2287 }
2288 
schema_pass2(sdlCtx * ctx)2289 void schema_pass2(sdlCtx *ctx)
2290 {
2291 	sdlPtr sdl = ctx->sdl;
2292 	sdlAttributePtr *attr;
2293 	sdlTypePtr *type;
2294 
2295 	if (ctx->attributes) {
2296 		zend_hash_internal_pointer_reset(ctx->attributes);
2297 		while (zend_hash_get_current_data(ctx->attributes,(void**)&attr) == SUCCESS) {
2298 			schema_attribute_fixup(ctx,*attr);
2299 			zend_hash_move_forward(ctx->attributes);
2300 		}
2301 	}
2302 	if (ctx->attributeGroups) {
2303 		zend_hash_internal_pointer_reset(ctx->attributeGroups);
2304 		while (zend_hash_get_current_data(ctx->attributeGroups,(void**)&type) == SUCCESS) {
2305 			schema_type_fixup(ctx,*type);
2306 			zend_hash_move_forward(ctx->attributeGroups);
2307 		}
2308 	}
2309 	if (sdl->elements) {
2310 		zend_hash_internal_pointer_reset(sdl->elements);
2311 		while (zend_hash_get_current_data(sdl->elements,(void**)&type) == SUCCESS) {
2312 			schema_type_fixup(ctx,*type);
2313 			zend_hash_move_forward(sdl->elements);
2314 		}
2315 	}
2316 	if (sdl->groups) {
2317 		zend_hash_internal_pointer_reset(sdl->groups);
2318 		while (zend_hash_get_current_data(sdl->groups,(void**)&type) == SUCCESS) {
2319 			schema_type_fixup(ctx,*type);
2320 			zend_hash_move_forward(sdl->groups);
2321 		}
2322 	}
2323 	if (sdl->types) {
2324 		zend_hash_internal_pointer_reset(sdl->types);
2325 		while (zend_hash_get_current_data(sdl->types,(void**)&type) == SUCCESS) {
2326 			schema_type_fixup(ctx,*type);
2327 			zend_hash_move_forward(sdl->types);
2328 		}
2329 	}
2330 	if (ctx->attributes) {
2331 		zend_hash_destroy(ctx->attributes);
2332 		efree(ctx->attributes);
2333 	}
2334 	if (ctx->attributeGroups) {
2335 		zend_hash_destroy(ctx->attributeGroups);
2336 		efree(ctx->attributeGroups);
2337 	}
2338 }
2339 
delete_model(void * handle)2340 void delete_model(void *handle)
2341 {
2342 	sdlContentModelPtr tmp = *((sdlContentModelPtr*)handle);
2343 	switch (tmp->kind) {
2344 		case XSD_CONTENT_ELEMENT:
2345 		case XSD_CONTENT_GROUP:
2346 			break;
2347 		case XSD_CONTENT_SEQUENCE:
2348 		case XSD_CONTENT_ALL:
2349 		case XSD_CONTENT_CHOICE:
2350 			zend_hash_destroy(tmp->u.content);
2351 			efree(tmp->u.content);
2352 			break;
2353 		case XSD_CONTENT_GROUP_REF:
2354 			efree(tmp->u.group_ref);
2355 			break;
2356 		default:
2357 			break;
2358 	}
2359 	efree(tmp);
2360 }
2361 
delete_model_persistent(void * handle)2362 void delete_model_persistent(void *handle)
2363 {
2364 	sdlContentModelPtr tmp = *((sdlContentModelPtr*)handle);
2365 	switch (tmp->kind) {
2366 		case XSD_CONTENT_ELEMENT:
2367 		case XSD_CONTENT_GROUP:
2368 			break;
2369 		case XSD_CONTENT_SEQUENCE:
2370 		case XSD_CONTENT_ALL:
2371 		case XSD_CONTENT_CHOICE:
2372 			zend_hash_destroy(tmp->u.content);
2373 			free(tmp->u.content);
2374 			break;
2375 		case XSD_CONTENT_GROUP_REF:
2376 			free(tmp->u.group_ref);
2377 			break;
2378 		default:
2379 			break;
2380 	}
2381 	free(tmp);
2382 }
2383 
delete_type(void * data)2384 void delete_type(void *data)
2385 {
2386 	sdlTypePtr type = *((sdlTypePtr*)data);
2387 
2388 	if (type->name) {
2389 		efree(type->name);
2390 	}
2391 	if (type->namens) {
2392 		efree(type->namens);
2393 	}
2394 	if (type->def) {
2395 		efree(type->def);
2396 	}
2397 	if (type->fixed) {
2398 		efree(type->fixed);
2399 	}
2400 	if (type->elements) {
2401 		zend_hash_destroy(type->elements);
2402 		efree(type->elements);
2403 	}
2404 	if (type->attributes) {
2405 		zend_hash_destroy(type->attributes);
2406 		efree(type->attributes);
2407 	}
2408 	if (type->model) {
2409 		delete_model((void**)&type->model);
2410 	}
2411 	if (type->restrictions) {
2412 		delete_restriction_var_int(&type->restrictions->minExclusive);
2413 		delete_restriction_var_int(&type->restrictions->minInclusive);
2414 		delete_restriction_var_int(&type->restrictions->maxExclusive);
2415 		delete_restriction_var_int(&type->restrictions->maxInclusive);
2416 		delete_restriction_var_int(&type->restrictions->totalDigits);
2417 		delete_restriction_var_int(&type->restrictions->fractionDigits);
2418 		delete_restriction_var_int(&type->restrictions->length);
2419 		delete_restriction_var_int(&type->restrictions->minLength);
2420 		delete_restriction_var_int(&type->restrictions->maxLength);
2421 		delete_restriction_var_char(&type->restrictions->whiteSpace);
2422 		delete_restriction_var_char(&type->restrictions->pattern);
2423 		if (type->restrictions->enumeration) {
2424 			zend_hash_destroy(type->restrictions->enumeration);
2425 			efree(type->restrictions->enumeration);
2426 		}
2427 		efree(type->restrictions);
2428 	}
2429 	efree(type);
2430 }
2431 
delete_type_persistent(void * data)2432 void delete_type_persistent(void *data)
2433 {
2434 	sdlTypePtr type = *((sdlTypePtr*)data);
2435 	if (type->name) {
2436 		free(type->name);
2437 	}
2438 	if (type->namens) {
2439 		free(type->namens);
2440 	}
2441 	if (type->def) {
2442 		free(type->def);
2443 	}
2444 	if (type->fixed) {
2445 		free(type->fixed);
2446 	}
2447 	if (type->elements) {
2448 		zend_hash_destroy(type->elements);
2449 		free(type->elements);
2450 	}
2451 	if (type->attributes) {
2452 		zend_hash_destroy(type->attributes);
2453 		free(type->attributes);
2454 	}
2455 	if (type->model) {
2456 		delete_model_persistent((void**)&type->model);
2457 	}
2458 	if (type->restrictions) {
2459 		delete_restriction_var_int_persistent(&type->restrictions->minExclusive);
2460 		delete_restriction_var_int_persistent(&type->restrictions->minInclusive);
2461 		delete_restriction_var_int_persistent(&type->restrictions->maxExclusive);
2462 		delete_restriction_var_int_persistent(&type->restrictions->maxInclusive);
2463 		delete_restriction_var_int_persistent(&type->restrictions->totalDigits);
2464 		delete_restriction_var_int_persistent(&type->restrictions->fractionDigits);
2465 		delete_restriction_var_int_persistent(&type->restrictions->length);
2466 		delete_restriction_var_int_persistent(&type->restrictions->minLength);
2467 		delete_restriction_var_int_persistent(&type->restrictions->maxLength);
2468 		delete_restriction_var_char_persistent(&type->restrictions->whiteSpace);
2469 		delete_restriction_var_char_persistent(&type->restrictions->pattern);
2470 		if (type->restrictions->enumeration) {
2471 			zend_hash_destroy(type->restrictions->enumeration);
2472 			free(type->restrictions->enumeration);
2473 		}
2474 		free(type->restrictions);
2475 	}
2476 	free(type);
2477 }
2478 
delete_extra_attribute(void * attribute)2479 void delete_extra_attribute(void *attribute)
2480 {
2481 	sdlExtraAttributePtr attr = *((sdlExtraAttributePtr*)attribute);
2482 
2483 	if (attr->ns) {
2484 		efree(attr->ns);
2485 	}
2486 	if (attr->val) {
2487 		efree(attr->val);
2488 	}
2489 	efree(attr);
2490 }
2491 
delete_extra_attribute_persistent(void * attribute)2492 void delete_extra_attribute_persistent(void *attribute)
2493 {
2494 	sdlExtraAttributePtr attr = *((sdlExtraAttributePtr*)attribute);
2495 
2496 	if (attr->ns) {
2497 		free(attr->ns);
2498 	}
2499 	if (attr->val) {
2500 		free(attr->val);
2501 	}
2502 	free(attr);
2503 }
2504 
delete_attribute(void * attribute)2505 void delete_attribute(void *attribute)
2506 {
2507 	sdlAttributePtr attr = *((sdlAttributePtr*)attribute);
2508 
2509 	if (attr->def) {
2510 		efree(attr->def);
2511 	}
2512 	if (attr->fixed) {
2513 		efree(attr->fixed);
2514 	}
2515 	if (attr->name) {
2516 		efree(attr->name);
2517 	}
2518 	if (attr->namens) {
2519 		efree(attr->namens);
2520 	}
2521 	if (attr->ref) {
2522 		efree(attr->ref);
2523 	}
2524 	if (attr->extraAttributes) {
2525 		zend_hash_destroy(attr->extraAttributes);
2526 		efree(attr->extraAttributes);
2527 	}
2528 	efree(attr);
2529 }
2530 
delete_attribute_persistent(void * attribute)2531 void delete_attribute_persistent(void *attribute)
2532 {
2533 	sdlAttributePtr attr = *((sdlAttributePtr*)attribute);
2534 
2535 	if (attr->def) {
2536 		free(attr->def);
2537 	}
2538 	if (attr->fixed) {
2539 		free(attr->fixed);
2540 	}
2541 	if (attr->name) {
2542 		free(attr->name);
2543 	}
2544 	if (attr->namens) {
2545 		free(attr->namens);
2546 	}
2547 	if (attr->ref) {
2548 		free(attr->ref);
2549 	}
2550 	if (attr->extraAttributes) {
2551 		zend_hash_destroy(attr->extraAttributes);
2552 		free(attr->extraAttributes);
2553 	}
2554 	free(attr);
2555 }
2556 
delete_restriction_var_int(void * rvi)2557 void delete_restriction_var_int(void *rvi)
2558 {
2559 	sdlRestrictionIntPtr ptr = *((sdlRestrictionIntPtr*)rvi);
2560 	if (ptr) {
2561 		efree(ptr);
2562 	}
2563 }
2564 
delete_restriction_var_int_persistent(void * rvi)2565 void delete_restriction_var_int_persistent(void *rvi)
2566 {
2567 	sdlRestrictionIntPtr ptr = *((sdlRestrictionIntPtr*)rvi);
2568 	if (ptr) {
2569 		free(ptr);
2570 	}
2571 }
2572 
delete_restriction_var_char(void * srvc)2573 void delete_restriction_var_char(void *srvc)
2574 {
2575 	sdlRestrictionCharPtr ptr = *((sdlRestrictionCharPtr*)srvc);
2576 	if (ptr) {
2577 		if (ptr->value) {
2578 			efree(ptr->value);
2579 		}
2580 		efree(ptr);
2581 	}
2582 }
2583 
delete_restriction_var_char_persistent(void * srvc)2584 void delete_restriction_var_char_persistent(void *srvc)
2585 {
2586 	sdlRestrictionCharPtr ptr = *((sdlRestrictionCharPtr*)srvc);
2587 	if (ptr) {
2588 		if (ptr->value) {
2589 			free(ptr->value);
2590 		}
2591 		free(ptr);
2592 	}
2593 }
2594