PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/soap - php_schema.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 1149 1424 80.7 %
Date: 2014-07-13 Functions: 39 43 90.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 13 Jul 2014 23:57:56 +0000 (8 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.