1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2018 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") + buf + sizeof(buf) - 1 - 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") + buf + sizeof(buf) - 1 - 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 }
1801
1802 /* type = QName */
1803 type = get_attribute(attrType->properties, "type");
1804 if (type) {
1805 char *cptype, *str_ns;
1806 xmlNsPtr nsptr;
1807
1808 if (ref != NULL) {
1809 soap_error0(E_ERROR, "Parsing Schema: attribute has both 'ref' and 'type' attributes");
1810 }
1811 parse_namespace(type->children->content, &cptype, &str_ns);
1812 nsptr = xmlSearchNs(attrType->doc, attrType, BAD_CAST(str_ns));
1813 if (nsptr != NULL) {
1814 newAttr->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(cptype));
1815 }
1816 if (str_ns) {efree(str_ns);}
1817 if (cptype) {efree(cptype);}
1818 }
1819
1820 attr = attrType->properties;
1821 while (attr != NULL) {
1822 if (attr_is_equal_ex(attr, "default", SCHEMA_NAMESPACE)) {
1823 newAttr->def = estrdup((char*)attr->children->content);
1824 } else if (attr_is_equal_ex(attr, "fixed", SCHEMA_NAMESPACE)) {
1825 newAttr->fixed = estrdup((char*)attr->children->content);
1826 } else if (attr_is_equal_ex(attr, "form", SCHEMA_NAMESPACE)) {
1827 if (strncmp((char*)attr->children->content, "qualified", sizeof("qualified")) == 0) {
1828 newAttr->form = XSD_FORM_QUALIFIED;
1829 } else if (strncmp((char*)attr->children->content, "unqualified", sizeof("unqualified")) == 0) {
1830 newAttr->form = XSD_FORM_UNQUALIFIED;
1831 } else {
1832 newAttr->form = XSD_FORM_DEFAULT;
1833 }
1834 } else if (attr_is_equal_ex(attr, "id", SCHEMA_NAMESPACE)) {
1835 /* skip */
1836 } else if (attr_is_equal_ex(attr, "name", SCHEMA_NAMESPACE)) {
1837 newAttr->name = estrdup((char*)attr->children->content);
1838 } else if (attr_is_equal_ex(attr, "ref", SCHEMA_NAMESPACE)) {
1839 /* already processed */
1840 } else if (attr_is_equal_ex(attr, "type", SCHEMA_NAMESPACE)) {
1841 /* already processed */
1842 } else if (attr_is_equal_ex(attr, "use", SCHEMA_NAMESPACE)) {
1843 if (strncmp((char*)attr->children->content, "prohibited", sizeof("prohibited")) == 0) {
1844 newAttr->use = XSD_USE_PROHIBITED;
1845 } else if (strncmp((char*)attr->children->content, "required", sizeof("required")) == 0) {
1846 newAttr->use = XSD_USE_REQUIRED;
1847 } else if (strncmp((char*)attr->children->content, "optional", sizeof("optional")) == 0) {
1848 newAttr->use = XSD_USE_OPTIONAL;
1849 } else {
1850 newAttr->use = XSD_USE_DEFAULT;
1851 }
1852 } else {
1853 xmlNsPtr nsPtr = attr_find_ns(attr);
1854
1855 if (strncmp((char*)nsPtr->href, SCHEMA_NAMESPACE, sizeof(SCHEMA_NAMESPACE))) {
1856 smart_str key2 = {0};
1857 sdlExtraAttributePtr ext;
1858 xmlNsPtr nsptr;
1859 char *value, *ns;
1860
1861 ext = emalloc(sizeof(sdlExtraAttribute));
1862 memset(ext, 0, sizeof(sdlExtraAttribute));
1863 parse_namespace(attr->children->content, &value, &ns);
1864 nsptr = xmlSearchNs(attr->doc, attr->parent, BAD_CAST(ns));
1865 if (nsptr) {
1866 ext->ns = estrdup((char*)nsptr->href);
1867 ext->val = estrdup(value);
1868 } else {
1869 ext->val = estrdup((char*)attr->children->content);
1870 }
1871 if (ns) {efree(ns);}
1872 efree(value);
1873
1874 if (!newAttr->extraAttributes) {
1875 newAttr->extraAttributes = emalloc(sizeof(HashTable));
1876 zend_hash_init(newAttr->extraAttributes, 0, NULL, delete_extra_attribute, 0);
1877 }
1878
1879 smart_str_appends(&key2, (char*)nsPtr->href);
1880 smart_str_appendc(&key2, ':');
1881 smart_str_appends(&key2, (char*)attr->name);
1882 smart_str_0(&key2);
1883 zend_hash_add_ptr(newAttr->extraAttributes, key2.s, ext);
1884 smart_str_free(&key2);
1885 }
1886 }
1887 attr = attr->next;
1888 }
1889 if (newAttr->form == XSD_FORM_DEFAULT) {
1890 xmlNodePtr parent = attrType->parent;
1891 while (parent) {
1892 if (node_is_equal_ex(parent, "schema", SCHEMA_NAMESPACE)) {
1893 xmlAttrPtr def;
1894 def = get_attribute(parent->properties, "attributeFormDefault");
1895 if(def == NULL || strncmp((char*)def->children->content, "qualified", sizeof("qualified"))) {
1896 newAttr->form = XSD_FORM_UNQUALIFIED;
1897 } else {
1898 newAttr->form = XSD_FORM_QUALIFIED;
1899 }
1900 break;
1901 }
1902 parent = parent->parent;
1903 }
1904 if (parent == NULL) {
1905 newAttr->form = XSD_FORM_UNQUALIFIED;
1906 }
1907 }
1908 trav = attrType->children;
1909 if (trav != NULL && node_is_equal(trav, "annotation")) {
1910 /* TODO: <annotation> support */
1911 trav = trav->next;
1912 }
1913 if (trav != NULL) {
1914 if (node_is_equal(trav,"simpleType")) {
1915 sdlTypePtr dummy_type;
1916 zval zv;
1917
1918 if (ref != NULL) {
1919 soap_error0(E_ERROR, "Parsing Schema: attribute has both 'ref' attribute and subtype");
1920 } else if (type != NULL) {
1921 soap_error0(E_ERROR, "Parsing Schema: attribute has both 'type' attribute and subtype");
1922 }
1923 dummy_type = emalloc(sizeof(sdlType));
1924 memset(dummy_type, 0, sizeof(sdlType));
1925 {
1926 char buf[MAX_LENGTH_OF_LONG + 1];
1927 char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, zend_hash_num_elements(sdl->types));
1928 char *str = emalloc(sizeof("anonymous") + buf + sizeof(buf) - 1 - res);
1929
1930 memcpy(str, "anonymous", sizeof("anonymous")-1);
1931 memcpy(str + sizeof("anonymous")-1, res, buf + sizeof(buf) - res);
1932 dummy_type->name = str;
1933 }
1934 dummy_type->namens = estrdup((char*)tns->children->content);
1935 schema_simpleType(sdl, tns, trav, dummy_type);
1936 newAttr->encode = dummy_type->encode;
1937 ZVAL_PTR(&zv, dummy_type);
1938 delete_type(&zv);
1939 trav = trav->next;
1940 }
1941 }
1942 if (trav != NULL) {
1943 soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attribute", trav->name);
1944 }
1945 return TRUE;
1946 }
1947
schema_attributeGroup(sdlPtr sdl,xmlAttrPtr tns,xmlNodePtr attrGroup,sdlTypePtr cur_type,sdlCtx * ctx)1948 static int schema_attributeGroup(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrGroup, sdlTypePtr cur_type, sdlCtx *ctx)
1949 {
1950 xmlNodePtr trav;
1951 xmlAttrPtr name, ref = NULL;
1952
1953
1954 name = get_attribute(attrGroup->properties, "name");
1955 if (name == NULL) {
1956 name = ref = get_attribute(attrGroup->properties, "ref");
1957 }
1958 if (name) {
1959 if (cur_type == NULL) {
1960 xmlAttrPtr ns;
1961 sdlTypePtr newType;
1962 smart_str key = {0};
1963
1964 ns = get_attribute(attrGroup->properties, "targetNamespace");
1965 if (ns == NULL) {
1966 ns = tns;
1967 }
1968 newType = emalloc(sizeof(sdlType));
1969 memset(newType, 0, sizeof(sdlType));
1970 newType->name = estrdup((char*)name->children->content);
1971 newType->namens = estrdup((char*)ns->children->content);
1972
1973 smart_str_appends(&key, newType->namens);
1974 smart_str_appendc(&key, ':');
1975 smart_str_appends(&key, newType->name);
1976 smart_str_0(&key);
1977
1978 if (zend_hash_add_ptr(ctx->attributeGroups, key.s, newType) == NULL) {
1979 soap_error1(E_ERROR, "Parsing Schema: attributeGroup '%s' already defined", ZSTR_VAL(key.s));
1980 }
1981 cur_type = newType;
1982 smart_str_free(&key);
1983 } else if (ref) {
1984 sdlAttributePtr newAttr;
1985 char *group_name, *ns;
1986 smart_str key = {0};
1987 xmlNsPtr nsptr;
1988
1989 if (cur_type->attributes == NULL) {
1990 cur_type->attributes = emalloc(sizeof(HashTable));
1991 zend_hash_init(cur_type->attributes, 0, NULL, delete_attribute, 0);
1992 }
1993 newAttr = emalloc(sizeof(sdlAttribute));
1994 memset(newAttr, 0, sizeof(sdlAttribute));
1995
1996 parse_namespace(ref->children->content, &group_name, &ns);
1997 nsptr = xmlSearchNs(attrGroup->doc, attrGroup, BAD_CAST(ns));
1998 if (nsptr != NULL) {
1999 smart_str_appends(&key, (char*)nsptr->href);
2000 }
2001 smart_str_appendc(&key, ':');
2002 smart_str_appends(&key, group_name);
2003 smart_str_0(&key);
2004 newAttr->ref = estrndup(ZSTR_VAL(key.s), ZSTR_LEN(key.s));
2005 if (group_name) {efree(group_name);}
2006 if (ns) {efree(ns);}
2007 smart_str_free(&key);
2008
2009 zend_hash_next_index_insert_ptr(cur_type->attributes, newAttr);
2010 cur_type = NULL;
2011 }
2012 } else{
2013 soap_error0(E_ERROR, "Parsing Schema: attributeGroup has no 'name' nor 'ref' attributes");
2014 }
2015
2016 trav = attrGroup->children;
2017 if (trav != NULL && node_is_equal(trav, "annotation")) {
2018 /* TODO: <annotation> support */
2019 trav = trav->next;
2020 }
2021 while (trav != NULL) {
2022 if (node_is_equal(trav,"attribute")) {
2023 if (ref != NULL) {
2024 soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
2025 }
2026 schema_attribute(sdl, tns, trav, cur_type, NULL);
2027 } else if (node_is_equal(trav,"attributeGroup")) {
2028 if (ref != NULL) {
2029 soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
2030 }
2031 schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
2032 } else if (node_is_equal(trav,"anyAttribute")) {
2033 if (ref != NULL) {
2034 soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
2035 }
2036 /* TODO: <anyAttribute> support */
2037 trav = trav->next;
2038 break;
2039 } else {
2040 soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attributeGroup", trav->name);
2041 }
2042 trav = trav->next;
2043 }
2044 if (trav != NULL) {
2045 soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attributeGroup", trav->name);
2046 }
2047 return TRUE;
2048 }
2049
copy_extra_attribute(zval * zv)2050 static void copy_extra_attribute(zval *zv)
2051 {
2052 sdlExtraAttributePtr new_attr;
2053
2054 new_attr = emalloc(sizeof(sdlExtraAttribute));
2055 memcpy(new_attr, Z_PTR_P(zv), sizeof(sdlExtraAttribute));
2056 Z_PTR_P(zv) = new_attr;
2057 if (new_attr->ns) {
2058 new_attr->ns = estrdup(new_attr->ns);
2059 }
2060 if (new_attr->val) {
2061 new_attr->val = estrdup(new_attr->val);
2062 }
2063 }
2064
schema_find_by_ref(HashTable * ht,char * ref)2065 static void* schema_find_by_ref(HashTable *ht, char *ref)
2066 {
2067 void *tmp;
2068
2069 if ((tmp = zend_hash_str_find_ptr(ht, ref, strlen(ref))) != NULL) {
2070 return tmp;
2071 } else {
2072 ref = strrchr(ref, ':');
2073 if (ref) {
2074 if ((tmp = zend_hash_str_find_ptr(ht, ref, strlen(ref))) != NULL) {
2075 return tmp;
2076 }
2077 }
2078 }
2079 return NULL;
2080 }
2081
schema_attribute_fixup(sdlCtx * ctx,sdlAttributePtr attr)2082 static void schema_attribute_fixup(sdlCtx *ctx, sdlAttributePtr attr)
2083 {
2084 sdlAttributePtr tmp;
2085
2086 if (attr->ref != NULL) {
2087 if (ctx->attributes != NULL) {
2088 tmp = (sdlAttributePtr)schema_find_by_ref(ctx->attributes, attr->ref);
2089 if (tmp) {
2090 schema_attribute_fixup(ctx, tmp);
2091 if (tmp->name != NULL && attr->name == NULL) {
2092 attr->name = estrdup(tmp->name);
2093 }
2094 if (tmp->namens != NULL && attr->namens == NULL) {
2095 attr->namens = estrdup(tmp->namens);
2096 }
2097 if (tmp->def != NULL && attr->def == NULL) {
2098 attr->def = estrdup(tmp->def);
2099 }
2100 if (tmp->fixed != NULL && attr->fixed == NULL) {
2101 attr->fixed = estrdup(tmp->fixed);
2102 }
2103 if (attr->form == XSD_FORM_DEFAULT) {
2104 attr->form = tmp->form;
2105 }
2106 if (attr->use == XSD_USE_DEFAULT) {
2107 attr->use = tmp->use;
2108 }
2109 if (tmp->extraAttributes != NULL) {
2110 attr->extraAttributes = emalloc(sizeof(HashTable));
2111 zend_hash_init(attr->extraAttributes, zend_hash_num_elements(tmp->extraAttributes), NULL, delete_extra_attribute, 0);
2112 zend_hash_copy(attr->extraAttributes, tmp->extraAttributes, copy_extra_attribute);
2113 }
2114 attr->encode = tmp->encode;
2115 }
2116 }
2117 if (attr->name == NULL && attr->ref != NULL) {
2118 char *name = strrchr(attr->ref, ':');
2119 if (name) {
2120 attr->name = estrdup(name+1);
2121 } else{
2122 attr->name = estrdup(attr->ref);
2123 }
2124 }
2125 efree(attr->ref);
2126 attr->ref = NULL;
2127 }
2128 }
2129
schema_attributegroup_fixup(sdlCtx * ctx,sdlAttributePtr attr,HashTable * ht)2130 static void schema_attributegroup_fixup(sdlCtx *ctx, sdlAttributePtr attr, HashTable *ht)
2131 {
2132 sdlTypePtr tmp;
2133 sdlAttributePtr tmp_attr;
2134
2135 if (attr->ref != NULL) {
2136 if (ctx->attributeGroups != NULL) {
2137 tmp = (sdlTypePtr)schema_find_by_ref(ctx->attributeGroups, attr->ref);
2138 if (tmp) {
2139 if (tmp->attributes) {
2140 zend_hash_internal_pointer_reset(tmp->attributes);
2141 while ((tmp_attr = zend_hash_get_current_data_ptr(tmp->attributes)) != NULL) {
2142 if (zend_hash_get_current_key_type(tmp->attributes) == HASH_KEY_IS_STRING) {
2143 zend_string* _key;
2144 sdlAttributePtr newAttr;
2145
2146 schema_attribute_fixup(ctx, tmp_attr);
2147
2148 newAttr = emalloc(sizeof(sdlAttribute));
2149 memcpy(newAttr, tmp_attr, sizeof(sdlAttribute));
2150 if (newAttr->def) {newAttr->def = estrdup(newAttr->def);}
2151 if (newAttr->fixed) {newAttr->fixed = estrdup(newAttr->fixed);}
2152 if (newAttr->namens) {newAttr->namens = estrdup(newAttr->namens);}
2153 if (newAttr->name) {newAttr->name = estrdup(newAttr->name);}
2154 if (newAttr->extraAttributes) {
2155 HashTable *ht = emalloc(sizeof(HashTable));
2156 zend_hash_init(ht, zend_hash_num_elements(newAttr->extraAttributes), NULL, delete_extra_attribute, 0);
2157 zend_hash_copy(ht, newAttr->extraAttributes, copy_extra_attribute);
2158 newAttr->extraAttributes = ht;
2159 }
2160
2161 zend_hash_get_current_key(tmp->attributes, &_key, NULL);
2162 zend_hash_add_ptr(ht, _key, newAttr);
2163
2164 zend_hash_move_forward(tmp->attributes);
2165 } else {
2166 zend_ulong index;
2167
2168 schema_attributegroup_fixup(ctx, tmp_attr, ht);
2169 zend_hash_get_current_key(tmp->attributes, NULL, &index);
2170 zend_hash_index_del(tmp->attributes, index);
2171 }
2172 }
2173 }
2174 }
2175 }
2176 efree(attr->ref);
2177 attr->ref = NULL;
2178 }
2179 }
2180
schema_content_model_fixup(sdlCtx * ctx,sdlContentModelPtr model)2181 static void schema_content_model_fixup(sdlCtx *ctx, sdlContentModelPtr model)
2182 {
2183 switch (model->kind) {
2184 case XSD_CONTENT_GROUP_REF: {
2185 sdlTypePtr tmp;
2186
2187 if (ctx->sdl->groups && (tmp = zend_hash_str_find_ptr(ctx->sdl->groups, model->u.group_ref, strlen(model->u.group_ref))) != NULL) {
2188 schema_type_fixup(ctx, tmp);
2189 efree(model->u.group_ref);
2190 model->kind = XSD_CONTENT_GROUP;
2191 model->u.group = tmp;
2192 } else {
2193 soap_error1(E_ERROR, "Parsing Schema: unresolved group 'ref' attribute '%s'", model->u.group_ref);
2194 }
2195 break;
2196 }
2197 case XSD_CONTENT_CHOICE: {
2198 if (model->max_occurs != 1) {
2199 sdlContentModelPtr tmp;
2200
2201 ZEND_HASH_FOREACH_PTR(model->u.content, tmp) {
2202 tmp->min_occurs = 0;
2203 tmp->max_occurs = model->max_occurs;
2204 } ZEND_HASH_FOREACH_END();
2205
2206 model->kind = XSD_CONTENT_ALL;
2207 model->min_occurs = 1;
2208 model->max_occurs = 1;
2209 }
2210 }
2211 case XSD_CONTENT_SEQUENCE:
2212 case XSD_CONTENT_ALL: {
2213 sdlContentModelPtr tmp;
2214
2215 ZEND_HASH_FOREACH_PTR(model->u.content, tmp) {
2216 schema_content_model_fixup(ctx, tmp);
2217 } ZEND_HASH_FOREACH_END();
2218 break;
2219 }
2220 default:
2221 break;
2222 }
2223 }
2224
schema_type_fixup(sdlCtx * ctx,sdlTypePtr type)2225 static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type)
2226 {
2227 sdlTypePtr tmp;
2228 sdlAttributePtr attr;
2229
2230 if (type->ref != NULL) {
2231 if (ctx->sdl->elements != NULL) {
2232 tmp = (sdlTypePtr)schema_find_by_ref(ctx->sdl->elements, type->ref);
2233 if (tmp) {
2234 type->kind = tmp->kind;
2235 type->encode = tmp->encode;
2236 if (tmp->nillable) {
2237 type->nillable = 1;
2238 }
2239 if (tmp->fixed) {
2240 type->fixed = estrdup(tmp->fixed);
2241 }
2242 if (tmp->def) {
2243 type->def = estrdup(tmp->def);
2244 }
2245 type->form = tmp->form;
2246 } else if (strcmp(type->ref, SCHEMA_NAMESPACE ":schema") == 0) {
2247 type->encode = get_conversion(XSD_ANYXML);
2248 } else {
2249 soap_error1(E_ERROR, "Parsing Schema: unresolved element 'ref' attribute '%s'", type->ref);
2250 }
2251 }
2252 efree(type->ref);
2253 type->ref = NULL;
2254 }
2255 if (type->elements) {
2256 ZEND_HASH_FOREACH_PTR(type->elements, tmp) {
2257 schema_type_fixup(ctx, tmp);
2258 } ZEND_HASH_FOREACH_END();
2259 }
2260 if (type->model) {
2261 schema_content_model_fixup(ctx, type->model);
2262 }
2263 if (type->attributes) {
2264 zend_string *str_key;
2265 zend_ulong index;
2266
2267 ZEND_HASH_FOREACH_KEY_PTR(type->attributes, index, str_key, attr) {
2268 if (str_key) {
2269 schema_attribute_fixup(ctx, attr);
2270 } else {
2271 schema_attributegroup_fixup(ctx, attr, type->attributes);
2272 zend_hash_index_del(type->attributes, index);
2273 }
2274 } ZEND_HASH_FOREACH_END();
2275 }
2276 }
2277
schema_pass2(sdlCtx * ctx)2278 void schema_pass2(sdlCtx *ctx)
2279 {
2280 sdlPtr sdl = ctx->sdl;
2281 sdlAttributePtr attr;
2282 sdlTypePtr type;
2283
2284 if (ctx->attributes) {
2285 ZEND_HASH_FOREACH_PTR(ctx->attributes, attr) {
2286 schema_attribute_fixup(ctx, attr);
2287 } ZEND_HASH_FOREACH_END();
2288 }
2289 if (ctx->attributeGroups) {
2290 ZEND_HASH_FOREACH_PTR(ctx->attributeGroups, type) {
2291 schema_type_fixup(ctx, type);
2292 } ZEND_HASH_FOREACH_END();
2293 }
2294 if (sdl->elements) {
2295 ZEND_HASH_FOREACH_PTR(sdl->elements, type) {
2296 schema_type_fixup(ctx, type);
2297 } ZEND_HASH_FOREACH_END();
2298 }
2299 if (sdl->groups) {
2300 ZEND_HASH_FOREACH_PTR(sdl->groups, type) {
2301 schema_type_fixup(ctx, type);
2302 } ZEND_HASH_FOREACH_END();
2303 }
2304 if (sdl->types) {
2305 ZEND_HASH_FOREACH_PTR(sdl->types, type) {
2306 schema_type_fixup(ctx, type);
2307 } ZEND_HASH_FOREACH_END();
2308 }
2309 if (ctx->attributes) {
2310 zend_hash_destroy(ctx->attributes);
2311 efree(ctx->attributes);
2312 }
2313 if (ctx->attributeGroups) {
2314 zend_hash_destroy(ctx->attributeGroups);
2315 efree(ctx->attributeGroups);
2316 }
2317 }
2318
delete_model(zval * zv)2319 void delete_model(zval *zv)
2320 {
2321 sdlContentModelPtr tmp = Z_PTR_P(zv);
2322 switch (tmp->kind) {
2323 case XSD_CONTENT_ELEMENT:
2324 case XSD_CONTENT_GROUP:
2325 break;
2326 case XSD_CONTENT_SEQUENCE:
2327 case XSD_CONTENT_ALL:
2328 case XSD_CONTENT_CHOICE:
2329 zend_hash_destroy(tmp->u.content);
2330 efree(tmp->u.content);
2331 break;
2332 case XSD_CONTENT_GROUP_REF:
2333 efree(tmp->u.group_ref);
2334 break;
2335 default:
2336 break;
2337 }
2338 efree(tmp);
2339 }
2340
delete_model_persistent_int(sdlContentModelPtr tmp)2341 static void delete_model_persistent_int(sdlContentModelPtr tmp)
2342 {
2343 switch (tmp->kind) {
2344 case XSD_CONTENT_ELEMENT:
2345 case XSD_CONTENT_GROUP:
2346 break;
2347 case XSD_CONTENT_SEQUENCE:
2348 case XSD_CONTENT_ALL:
2349 case XSD_CONTENT_CHOICE:
2350 zend_hash_destroy(tmp->u.content);
2351 free(tmp->u.content);
2352 break;
2353 case XSD_CONTENT_GROUP_REF:
2354 free(tmp->u.group_ref);
2355 break;
2356 default:
2357 break;
2358 }
2359 free(tmp);
2360 }
2361
delete_model_persistent(zval * zv)2362 void delete_model_persistent(zval *zv)
2363 {
2364 delete_model_persistent_int(Z_PTR_P(zv));
2365 }
2366
delete_type(zval * zv)2367 void delete_type(zval *zv)
2368 {
2369 sdlTypePtr type = Z_PTR_P(zv);
2370
2371 if (type->name) {
2372 efree(type->name);
2373 }
2374 if (type->namens) {
2375 efree(type->namens);
2376 }
2377 if (type->def) {
2378 efree(type->def);
2379 }
2380 if (type->fixed) {
2381 efree(type->fixed);
2382 }
2383 if (type->elements) {
2384 zend_hash_destroy(type->elements);
2385 efree(type->elements);
2386 }
2387 if (type->attributes) {
2388 zend_hash_destroy(type->attributes);
2389 efree(type->attributes);
2390 }
2391 if (type->model) {
2392 zval zv;
2393 ZVAL_PTR(&zv, type->model);
2394 delete_model(&zv);
2395 }
2396 if (type->restrictions) {
2397 delete_restriction_var_int(type->restrictions->minExclusive);
2398 delete_restriction_var_int(type->restrictions->minInclusive);
2399 delete_restriction_var_int(type->restrictions->maxExclusive);
2400 delete_restriction_var_int(type->restrictions->maxInclusive);
2401 delete_restriction_var_int(type->restrictions->totalDigits);
2402 delete_restriction_var_int(type->restrictions->fractionDigits);
2403 delete_restriction_var_int(type->restrictions->length);
2404 delete_restriction_var_int(type->restrictions->minLength);
2405 delete_restriction_var_int(type->restrictions->maxLength);
2406 delete_restriction_var_char_int(type->restrictions->whiteSpace);
2407 delete_restriction_var_char_int(type->restrictions->pattern);
2408 if (type->restrictions->enumeration) {
2409 zend_hash_destroy(type->restrictions->enumeration);
2410 efree(type->restrictions->enumeration);
2411 }
2412 efree(type->restrictions);
2413 }
2414 efree(type);
2415 }
2416
delete_type_persistent(zval * zv)2417 void delete_type_persistent(zval *zv)
2418 {
2419 sdlTypePtr type = Z_PTR_P(zv);
2420 if (type->name) {
2421 free(type->name);
2422 }
2423 if (type->namens) {
2424 free(type->namens);
2425 }
2426 if (type->def) {
2427 free(type->def);
2428 }
2429 if (type->fixed) {
2430 free(type->fixed);
2431 }
2432 if (type->elements) {
2433 zend_hash_destroy(type->elements);
2434 free(type->elements);
2435 }
2436 if (type->attributes) {
2437 zend_hash_destroy(type->attributes);
2438 free(type->attributes);
2439 }
2440 if (type->model) {
2441 delete_model_persistent_int(type->model);
2442 }
2443 if (type->restrictions) {
2444 delete_restriction_var_int_persistent(type->restrictions->minExclusive);
2445 delete_restriction_var_int_persistent(type->restrictions->minInclusive);
2446 delete_restriction_var_int_persistent(type->restrictions->maxExclusive);
2447 delete_restriction_var_int_persistent(type->restrictions->maxInclusive);
2448 delete_restriction_var_int_persistent(type->restrictions->totalDigits);
2449 delete_restriction_var_int_persistent(type->restrictions->fractionDigits);
2450 delete_restriction_var_int_persistent(type->restrictions->length);
2451 delete_restriction_var_int_persistent(type->restrictions->minLength);
2452 delete_restriction_var_int_persistent(type->restrictions->maxLength);
2453 delete_restriction_var_char_persistent_int(type->restrictions->whiteSpace);
2454 delete_restriction_var_char_persistent_int(type->restrictions->pattern);
2455 if (type->restrictions->enumeration) {
2456 zend_hash_destroy(type->restrictions->enumeration);
2457 free(type->restrictions->enumeration);
2458 }
2459 free(type->restrictions);
2460 }
2461 free(type);
2462 }
2463
delete_extra_attribute(zval * zv)2464 void delete_extra_attribute(zval *zv)
2465 {
2466 sdlExtraAttributePtr attr = Z_PTR_P(zv);
2467
2468 if (attr->ns) {
2469 efree(attr->ns);
2470 }
2471 if (attr->val) {
2472 efree(attr->val);
2473 }
2474 efree(attr);
2475 }
2476
delete_extra_attribute_persistent(zval * zv)2477 void delete_extra_attribute_persistent(zval *zv)
2478 {
2479 sdlExtraAttributePtr attr = Z_PTR_P(zv);
2480
2481 if (attr->ns) {
2482 free(attr->ns);
2483 }
2484 if (attr->val) {
2485 free(attr->val);
2486 }
2487 free(attr);
2488 }
2489
delete_attribute(zval * zv)2490 void delete_attribute(zval *zv)
2491 {
2492 sdlAttributePtr attr = Z_PTR_P(zv);
2493
2494 if (attr->def) {
2495 efree(attr->def);
2496 }
2497 if (attr->fixed) {
2498 efree(attr->fixed);
2499 }
2500 if (attr->name) {
2501 efree(attr->name);
2502 }
2503 if (attr->namens) {
2504 efree(attr->namens);
2505 }
2506 if (attr->ref) {
2507 efree(attr->ref);
2508 }
2509 if (attr->extraAttributes) {
2510 zend_hash_destroy(attr->extraAttributes);
2511 efree(attr->extraAttributes);
2512 }
2513 efree(attr);
2514 }
2515
delete_attribute_persistent(zval * zv)2516 void delete_attribute_persistent(zval *zv)
2517 {
2518 sdlAttributePtr attr = Z_PTR_P(zv);
2519
2520 if (attr->def) {
2521 free(attr->def);
2522 }
2523 if (attr->fixed) {
2524 free(attr->fixed);
2525 }
2526 if (attr->name) {
2527 free(attr->name);
2528 }
2529 if (attr->namens) {
2530 free(attr->namens);
2531 }
2532 if (attr->ref) {
2533 free(attr->ref);
2534 }
2535 if (attr->extraAttributes) {
2536 zend_hash_destroy(attr->extraAttributes);
2537 free(attr->extraAttributes);
2538 }
2539 free(attr);
2540 }
2541
delete_restriction_var_int(sdlRestrictionIntPtr ptr)2542 void delete_restriction_var_int(sdlRestrictionIntPtr ptr)
2543 {
2544 if (ptr) {
2545 efree(ptr);
2546 }
2547 }
2548
delete_restriction_var_int_persistent(sdlRestrictionIntPtr ptr)2549 void delete_restriction_var_int_persistent(sdlRestrictionIntPtr ptr)
2550 {
2551 if (ptr) {
2552 free(ptr);
2553 }
2554 }
2555
delete_restriction_var_char_int(sdlRestrictionCharPtr ptr)2556 void delete_restriction_var_char_int(sdlRestrictionCharPtr ptr)
2557 {
2558 if (ptr) {
2559 if (ptr->value) {
2560 efree(ptr->value);
2561 }
2562 efree(ptr);
2563 }
2564 }
2565
delete_restriction_var_char(zval * zv)2566 void delete_restriction_var_char(zval *zv)
2567 {
2568 delete_restriction_var_char_int(Z_PTR_P(zv));
2569 }
2570
delete_restriction_var_char_persistent_int(sdlRestrictionCharPtr ptr)2571 void delete_restriction_var_char_persistent_int(sdlRestrictionCharPtr ptr)
2572 {
2573 if (ptr) {
2574 if (ptr->value) {
2575 free(ptr->value);
2576 }
2577 free(ptr);
2578 }
2579 }
2580
delete_restriction_var_char_persistent(zval * zv)2581 void delete_restriction_var_char_persistent(zval *zv)
2582 {
2583 delete_restriction_var_char_persistent_int(Z_PTR_P(zv));
2584 }
2585