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