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