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

Generated by: LCOV version 1.10

Generated at Sat, 13 Dec 2014 06:16:20 +0000 (7 days ago)

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