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