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