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