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