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: 1129 1408 80.2 %
Date: 2016-02-13 Functions: 42 47 89.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 14 Feb 2016 01:46:45 +0000 (2 hours ago)

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