root/ext/soap/php_schema.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. create_encoder
  2. get_create_encoder
  3. schema_load_file
  4. load_schema
  5. schema_simpleType
  6. schema_list
  7. schema_union
  8. schema_simpleContent
  9. schema_restriction_simpleContent
  10. schema_restriction_complexContent
  11. schema_restriction_var_int
  12. schema_restriction_var_char
  13. schema_extension_simpleContent
  14. schema_extension_complexContent
  15. schema_min_max
  16. schema_all
  17. schema_group
  18. schema_choice
  19. schema_sequence
  20. schema_any
  21. schema_complexContent
  22. schema_complexType
  23. schema_element
  24. schema_attribute
  25. schema_attributeGroup
  26. copy_extra_attribute
  27. schema_find_by_ref
  28. schema_attribute_fixup
  29. schema_attributegroup_fixup
  30. schema_content_model_fixup
  31. schema_type_fixup
  32. schema_pass2
  33. delete_model
  34. delete_model_persistent
  35. delete_type
  36. delete_type_persistent
  37. delete_extra_attribute
  38. delete_extra_attribute_persistent
  39. delete_attribute
  40. delete_attribute_persistent
  41. delete_restriction_var_int
  42. delete_restriction_var_int_persistent
  43. delete_restriction_var_char
  44. delete_restriction_var_char_persistent

   1 /*
   2   +----------------------------------------------------------------------+
   3   | PHP Version 5                                                        |
   4   +----------------------------------------------------------------------+
   5   | Copyright (c) 1997-2016 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 
  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 
  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 
  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 */
 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 */
 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 */
 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 */
 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 */
 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 */
 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 */
 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 
 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 
 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 */
 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 */
 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 
 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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
2557 void delete_restriction_var_int(void *rvi)
2558 {
2559         sdlRestrictionIntPtr ptr = *((sdlRestrictionIntPtr*)rvi);
2560         if (ptr) {
2561                 efree(ptr);
2562         }
2563 }
2564 
2565 void delete_restriction_var_int_persistent(void *rvi)
2566 {
2567         sdlRestrictionIntPtr ptr = *((sdlRestrictionIntPtr*)rvi);
2568         if (ptr) {
2569                 free(ptr);
2570         }
2571 }
2572 
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 
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 }

/* [<][>][^][v][top][bottom][index][help] */