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_int
  35. delete_model_persistent
  36. delete_type
  37. delete_type_persistent
  38. delete_extra_attribute
  39. delete_extra_attribute_persistent
  40. delete_attribute
  41. delete_attribute_persistent
  42. delete_restriction_var_int
  43. delete_restriction_var_int_persistent
  44. delete_restriction_var_char_int
  45. delete_restriction_var_char
  46. delete_restriction_var_char_persistent_int
  47. delete_restriction_var_char_persistent

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

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