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