Back to index

php5  5.3.10
php_sdl.c
Go to the documentation of this file.
00001 /*
00002   +----------------------------------------------------------------------+
00003   | PHP Version 5                                                        |
00004   +----------------------------------------------------------------------+
00005   | Copyright (c) 1997-2012 The PHP Group                                |
00006   +----------------------------------------------------------------------+
00007   | This source file is subject to version 3.01 of the PHP license,      |
00008   | that is bundled with this package in the file LICENSE, and is        |
00009   | available through the world-wide-web at the following url:           |
00010   | http://www.php.net/license/3_01.txt                                  |
00011   | If you did not receive a copy of the PHP license and are unable to   |
00012   | obtain it through the world-wide-web, please send a note to          |
00013   | license@php.net so we can mail you a copy immediately.               |
00014   +----------------------------------------------------------------------+
00015   | Authors: Brad Lafountain <rodif_bl@yahoo.com>                        |
00016   |          Shane Caraveo <shane@caraveo.com>                           |
00017   |          Dmitry Stogov <dmitry@zend.com>                             |
00018   +----------------------------------------------------------------------+
00019 */
00020 /* $Id: php_sdl.c 321634 2012-01-01 13:15:04Z felipe $ */
00021 
00022 #include "php_soap.h"
00023 #include "ext/libxml/php_libxml.h"
00024 #include "libxml/uri.h"
00025 
00026 #include "ext/standard/md5.h"
00027 #include "tsrm_virtual_cwd.h"
00028 
00029 #include <sys/types.h>
00030 #include <sys/stat.h>
00031 #include <fcntl.h>
00032 
00033 #ifndef O_BINARY
00034 # define O_BINARY 0
00035 #endif
00036 
00037 static void delete_fault(void *fault);
00038 static void delete_fault_persistent(void *fault);
00039 static void delete_binding(void *binding);
00040 static void delete_binding_persistent(void *binding);
00041 static void delete_function(void *function);
00042 static void delete_function_persistent(void *function);
00043 static void delete_parameter(void *paramater);
00044 static void delete_parameter_persistent(void *paramater);
00045 static void delete_header(void *header);
00046 static void delete_header_persistent(void *header);
00047 static void delete_document(void *doc_ptr);
00048 
00049 encodePtr get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr node, const xmlChar *type)
00050 {
00051        encodePtr enc = NULL;
00052        xmlNsPtr nsptr;
00053        char *ns, *cptype;
00054 
00055        parse_namespace(type, &cptype, &ns);
00056        nsptr = xmlSearchNs(node->doc, node, BAD_CAST(ns));
00057        if (nsptr != NULL) {
00058               enc = get_encoder(sdl, (char*)nsptr->href, cptype);
00059               if (enc == NULL) {
00060                      enc = get_encoder_ex(sdl, cptype, strlen(cptype));
00061               }
00062        } else {
00063               enc = get_encoder_ex(sdl, (char*)type, xmlStrlen(type));
00064        }
00065        efree(cptype);
00066        if (ns) {efree(ns);}
00067        return enc;
00068 }
00069 
00070 static sdlTypePtr get_element(sdlPtr sdl, xmlNodePtr node, const xmlChar *type)
00071 {
00072        sdlTypePtr ret = NULL;
00073 
00074        if (sdl->elements) {
00075               xmlNsPtr nsptr;
00076               char *ns, *cptype;
00077               sdlTypePtr *sdl_type;
00078 
00079               parse_namespace(type, &cptype, &ns);
00080               nsptr = xmlSearchNs(node->doc, node, BAD_CAST(ns));
00081               if (nsptr != NULL) {
00082                      int ns_len = xmlStrlen(nsptr->href);
00083                      int type_len = strlen(cptype);
00084                      int len = ns_len + type_len + 1;
00085                      char *nscat = emalloc(len + 1);
00086 
00087                      memcpy(nscat, nsptr->href, ns_len);
00088                      nscat[ns_len] = ':';
00089                      memcpy(nscat+ns_len+1, cptype, type_len);
00090                      nscat[len] = '\0';
00091 
00092                      if (zend_hash_find(sdl->elements, nscat, len + 1, (void **)&sdl_type) == SUCCESS) {
00093                             ret = *sdl_type;
00094                      } else if (zend_hash_find(sdl->elements, (char*)type, type_len + 1, (void **)&sdl_type) == SUCCESS) {
00095                             ret = *sdl_type;
00096                      }
00097                      efree(nscat);
00098               } else {
00099                      if (zend_hash_find(sdl->elements, (char*)type, xmlStrlen(type) + 1, (void **)&sdl_type) == SUCCESS) {
00100                             ret = *sdl_type;
00101                      }
00102               }
00103 
00104               efree(cptype);
00105               if (ns) {efree(ns);}
00106        }
00107        return ret;
00108 }
00109 
00110 encodePtr get_encoder(sdlPtr sdl, const char *ns, const char *type)
00111 {
00112        encodePtr enc = NULL;
00113        char *nscat;
00114        int ns_len = strlen(ns);
00115        int type_len = strlen(type);
00116        int len = ns_len + type_len + 1;
00117 
00118        nscat = emalloc(len + 1);
00119        memcpy(nscat, ns, ns_len);
00120        nscat[ns_len] = ':';
00121        memcpy(nscat+ns_len+1, type, type_len);
00122        nscat[len] = '\0';
00123 
00124        enc = get_encoder_ex(sdl, nscat, len);
00125 
00126        if (enc == NULL &&
00127            ((ns_len == sizeof(SOAP_1_1_ENC_NAMESPACE)-1 &&
00128              memcmp(ns, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)-1) == 0) ||
00129             (ns_len == sizeof(SOAP_1_2_ENC_NAMESPACE)-1 &&
00130              memcmp(ns, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)-1) == 0))) {
00131               char *enc_nscat;
00132               int enc_ns_len;
00133               int enc_len;
00134 
00135               enc_ns_len = sizeof(XSD_NAMESPACE)-1;
00136               enc_len = enc_ns_len + type_len + 1;
00137               enc_nscat = emalloc(enc_len + 1);
00138               memcpy(enc_nscat, XSD_NAMESPACE, sizeof(XSD_NAMESPACE)-1);
00139               enc_nscat[enc_ns_len] = ':';
00140               memcpy(enc_nscat+enc_ns_len+1, type, type_len);
00141               enc_nscat[enc_len] = '\0';
00142 
00143               enc = get_encoder_ex(NULL, enc_nscat, enc_len);
00144               efree(enc_nscat);
00145               if (enc && sdl) {
00146                      encodePtr new_enc    = pemalloc(sizeof(encode), sdl->is_persistent);
00147                      memcpy(new_enc, enc, sizeof(encode));
00148                      if (sdl->is_persistent) {
00149                             new_enc->details.ns = zend_strndup(ns, ns_len);
00150                             new_enc->details.type_str = strdup(new_enc->details.type_str);
00151                      } else {
00152                             new_enc->details.ns = estrndup(ns, ns_len);
00153                             new_enc->details.type_str = estrdup(new_enc->details.type_str);
00154                      }
00155                      if (sdl->encoders == NULL) {
00156                             sdl->encoders = pemalloc(sizeof(HashTable), sdl->is_persistent);
00157                             zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, sdl->is_persistent);
00158                      }
00159                      zend_hash_update(sdl->encoders, nscat, len + 1, &new_enc, sizeof(encodePtr), NULL);
00160                      enc = new_enc;
00161               }
00162        }
00163        efree(nscat);
00164        return enc;
00165 }
00166 
00167 encodePtr get_encoder_ex(sdlPtr sdl, const char *nscat, int len)
00168 {
00169        encodePtr *enc;
00170        TSRMLS_FETCH();
00171 
00172        if (zend_hash_find(&SOAP_GLOBAL(defEnc), (char*)nscat, len + 1, (void **)&enc) == SUCCESS) {
00173               return (*enc);
00174        } else if (sdl && sdl->encoders && zend_hash_find(sdl->encoders, (char*)nscat, len + 1, (void **)&enc) == SUCCESS) {
00175               return (*enc);
00176        }
00177        return NULL;
00178 }
00179 
00180 sdlBindingPtr get_binding_from_type(sdlPtr sdl, int type)
00181 {
00182        sdlBindingPtr *binding;
00183 
00184        if (sdl == NULL) {
00185               return NULL;
00186        }
00187 
00188        for (zend_hash_internal_pointer_reset(sdl->bindings);
00189               zend_hash_get_current_data(sdl->bindings, (void **) &binding) == SUCCESS;
00190               zend_hash_move_forward(sdl->bindings)) {
00191               if ((*binding)->bindingType == type) {
00192                      return *binding;
00193               }
00194        }
00195        return NULL;
00196 }
00197 
00198 sdlBindingPtr get_binding_from_name(sdlPtr sdl, char *name, char *ns)
00199 {
00200        sdlBindingPtr binding = NULL;
00201        smart_str key = {0};
00202 
00203        smart_str_appends(&key, ns);
00204        smart_str_appendc(&key, ':');
00205        smart_str_appends(&key, name);
00206        smart_str_0(&key);
00207 
00208        zend_hash_find(sdl->bindings, key.c, key.len, (void **)&binding);
00209 
00210        smart_str_free(&key);
00211        return binding;
00212 }
00213 
00214 static int is_wsdl_element(xmlNodePtr node)
00215 {
00216        if (node->ns && strcmp((char*)node->ns->href, WSDL_NAMESPACE) != 0) {
00217               xmlAttrPtr attr;
00218               if ((attr = get_attribute_ex(node->properties, "required", WSDL_NAMESPACE)) != NULL &&
00219                    attr->children && attr->children->content &&
00220                    (strcmp((char*)attr->children->content, "1") == 0 ||
00221                     strcmp((char*)attr->children->content, "true") == 0)) {
00222                      soap_error1(E_ERROR, "Parsing WSDL: Unknown required WSDL extension '%s'", node->ns->href);
00223               }
00224               return 0;
00225        }
00226        return 1;
00227 }
00228 
00229 void sdl_set_uri_credentials(sdlCtx *ctx, char *uri TSRMLS_DC)
00230 {
00231        char *s;
00232        int l1, l2;
00233        zval *context = NULL;
00234        zval **header = NULL;
00235 
00236        /* check if we load xsd from the same server */
00237        s = strstr(ctx->sdl->source, "://");
00238        if (!s) return;
00239        s = strchr(s+3, '/');
00240        l1 = s - ctx->sdl->source;
00241        s = strstr((char*)uri, "://");
00242        if (!s) return;
00243        s = strchr(s+3, '/');
00244        l2 = s - (char*)uri;
00245        if (l1 != l2 || memcmp(ctx->sdl->source, uri, l1) != 0) {
00246               /* another server. clear authentication credentals */
00247               context = php_libxml_switch_context(NULL TSRMLS_CC);
00248               php_libxml_switch_context(context TSRMLS_CC);
00249               if (context) {
00250                      ctx->context = php_stream_context_from_zval(context, 1);
00251 
00252                      if (ctx->context &&
00253                          php_stream_context_get_option(ctx->context, "http", "header", &header) == SUCCESS) {
00254                             s = strstr(Z_STRVAL_PP(header), "Authorization: Basic");
00255                             if (s && (s == Z_STRVAL_PP(header) || *(s-1) == '\n' || *(s-1) == '\r')) {
00256                                    char *rest = strstr(s, "\r\n");
00257                                    if (rest) {
00258                                           zval new_header;
00259                                    
00260                                           rest += 2;
00261                                           Z_TYPE(new_header) = IS_STRING;
00262                                           Z_STRLEN(new_header) = Z_STRLEN_PP(header) - (rest - s);
00263                                           Z_STRVAL(new_header) = emalloc(Z_STRLEN_PP(header) + 1);
00264                                           memcpy(Z_STRVAL(new_header), Z_STRVAL_PP(header), s - Z_STRVAL_PP(header));
00265                                           memcpy(Z_STRVAL(new_header) + (s - Z_STRVAL_PP(header)), rest, Z_STRLEN_PP(header) - (rest - Z_STRVAL_PP(header)) + 1);
00266                                           ctx->old_header = *header;
00267                                           Z_ADDREF_P(ctx->old_header);
00268                                           php_stream_context_set_option(ctx->context, "http", "header", &new_header);
00269                                           zval_dtor(&new_header);
00270                                    }
00271                             }
00272                      }
00273               }
00274        }
00275 }
00276 
00277 void sdl_restore_uri_credentials(sdlCtx *ctx TSRMLS_DC)
00278 {
00279        if (ctx->old_header) {
00280            php_stream_context_set_option(ctx->context, "http", "header", ctx->old_header);
00281            zval_ptr_dtor(&ctx->old_header);
00282               ctx->old_header = NULL;
00283        }
00284        ctx->context = NULL;
00285 }
00286 
00287 static void load_wsdl_ex(zval *this_ptr, char *struri, sdlCtx *ctx, int include TSRMLS_DC)
00288 {
00289        sdlPtr tmpsdl = ctx->sdl;
00290        xmlDocPtr wsdl;
00291        xmlNodePtr root, definitions, trav;
00292        xmlAttrPtr targetNamespace;
00293 
00294        if (zend_hash_exists(&ctx->docs, struri, strlen(struri)+1)) {
00295               return;
00296        }
00297        
00298        sdl_set_uri_credentials(ctx, struri TSRMLS_CC);
00299        wsdl = soap_xmlParseFile(struri TSRMLS_CC);
00300        sdl_restore_uri_credentials(ctx TSRMLS_CC);
00301        
00302        if (!wsdl) {
00303               xmlErrorPtr xmlErrorPtr = xmlGetLastError();
00304 
00305               if (xmlErrorPtr) {
00306                      soap_error2(E_ERROR, "Parsing WSDL: Couldn't load from '%s' : %s", struri, xmlErrorPtr->message);
00307               } else {
00308                      soap_error1(E_ERROR, "Parsing WSDL: Couldn't load from '%s'", struri);
00309               }
00310        }
00311 
00312        zend_hash_add(&ctx->docs, struri, strlen(struri)+1, (void**)&wsdl, sizeof(xmlDocPtr), NULL);
00313 
00314        root = wsdl->children;
00315        definitions = get_node_ex(root, "definitions", WSDL_NAMESPACE);
00316        if (!definitions) {
00317               if (include) {
00318                      xmlNodePtr schema = get_node_ex(root, "schema", XSD_NAMESPACE);
00319                      if (schema) {
00320                             load_schema(ctx, schema TSRMLS_CC);
00321                             return;
00322                      }
00323               }
00324               soap_error1(E_ERROR, "Parsing WSDL: Couldn't find <definitions> in '%s'", struri);
00325        }
00326 
00327        if (!include) {
00328               targetNamespace = get_attribute(definitions->properties, "targetNamespace");
00329               if (targetNamespace) {
00330                      tmpsdl->target_ns = estrdup((char*)targetNamespace->children->content);
00331               }
00332        }
00333 
00334        trav = definitions->children;
00335        while (trav != NULL) {
00336               if (!is_wsdl_element(trav)) {
00337                      trav = trav->next;
00338                      continue;
00339               }
00340               if (node_is_equal(trav,"types")) {
00341                      /* TODO: Only one "types" is allowed */
00342                      xmlNodePtr trav2 = trav->children;
00343 
00344                      while (trav2 != NULL) {
00345                             if (node_is_equal_ex(trav2, "schema", XSD_NAMESPACE)) {
00346                                    load_schema(ctx, trav2 TSRMLS_CC);
00347                             } else if (is_wsdl_element(trav2) && !node_is_equal(trav2,"documentation")) {
00348                                    soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
00349                             }
00350                             trav2 = trav2->next;
00351                      }
00352               } else if (node_is_equal(trav,"import")) {
00353                      /* TODO: namespace ??? */
00354                      xmlAttrPtr tmp = get_attribute(trav->properties, "location");
00355                      if (tmp) {
00356                             xmlChar *uri;
00357                             xmlChar *base = xmlNodeGetBase(trav->doc, trav);
00358 
00359                             if (base == NULL) {
00360                                    uri = xmlBuildURI(tmp->children->content, trav->doc->URL);
00361                             } else {
00362                                    uri = xmlBuildURI(tmp->children->content, base);
00363                                    xmlFree(base);
00364                             }
00365                             load_wsdl_ex(this_ptr, (char*)uri, ctx, 1 TSRMLS_CC);
00366                             xmlFree(uri);
00367                      }
00368 
00369               } else if (node_is_equal(trav,"message")) {
00370                      xmlAttrPtr name = get_attribute(trav->properties, "name");
00371                      if (name && name->children && name->children->content) {
00372                             if (zend_hash_add(&ctx->messages, (char*)name->children->content, xmlStrlen(name->children->content)+1,&trav, sizeof(xmlNodePtr), NULL) != SUCCESS) {
00373                                    soap_error1(E_ERROR, "Parsing WSDL: <message> '%s' already defined", name->children->content);
00374                             }
00375                      } else {
00376                             soap_error0(E_ERROR, "Parsing WSDL: <message> has no name attribute");
00377                      }
00378 
00379               } else if (node_is_equal(trav,"portType")) {
00380                      xmlAttrPtr name = get_attribute(trav->properties, "name");
00381                      if (name && name->children && name->children->content) {
00382                             if (zend_hash_add(&ctx->portTypes, (char*)name->children->content, xmlStrlen(name->children->content)+1,&trav, sizeof(xmlNodePtr), NULL) != SUCCESS) {
00383                                    soap_error1(E_ERROR, "Parsing WSDL: <portType> '%s' already defined", name->children->content);
00384                             }
00385                      } else {
00386                             soap_error0(E_ERROR, "Parsing WSDL: <portType> has no name attribute");
00387                      }
00388 
00389               } else if (node_is_equal(trav,"binding")) {
00390                      xmlAttrPtr name = get_attribute(trav->properties, "name");
00391                      if (name && name->children && name->children->content) {
00392                             if (zend_hash_add(&ctx->bindings, (char*)name->children->content, xmlStrlen(name->children->content)+1,&trav, sizeof(xmlNodePtr), NULL) != SUCCESS) {
00393                                    soap_error1(E_ERROR, "Parsing WSDL: <binding> '%s' already defined", name->children->content);
00394                             }
00395                      } else {
00396                             soap_error0(E_ERROR, "Parsing WSDL: <binding> has no name attribute");
00397                      }
00398 
00399               } else if (node_is_equal(trav,"service")) {
00400                      xmlAttrPtr name = get_attribute(trav->properties, "name");
00401                      if (name && name->children && name->children->content) {
00402                             if (zend_hash_add(&ctx->services, (char*)name->children->content, xmlStrlen(name->children->content)+1,&trav, sizeof(xmlNodePtr), NULL) != SUCCESS) {
00403                                    soap_error1(E_ERROR, "Parsing WSDL: <service> '%s' already defined", name->children->content);
00404                             }
00405                      } else {
00406                             soap_error0(E_ERROR, "Parsing WSDL: <service> has no name attribute");
00407                      }
00408               } else if (!node_is_equal(trav,"documentation")) {
00409                      soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
00410               }
00411               trav = trav->next;
00412        }
00413 }
00414 
00415 static sdlSoapBindingFunctionHeaderPtr wsdl_soap_binding_header(sdlCtx* ctx, xmlNodePtr header, char* wsdl_soap_namespace, int fault)
00416 {
00417        xmlAttrPtr tmp;
00418        xmlNodePtr *message, part;
00419        char *ctype;
00420        sdlSoapBindingFunctionHeaderPtr h;
00421 
00422        tmp = get_attribute(header->properties, "message");
00423        if (!tmp) {
00424               soap_error0(E_ERROR, "Parsing WSDL: Missing message attribute for <header>");
00425        }
00426 
00427        ctype = strrchr((char*)tmp->children->content,':');
00428        if (ctype == NULL) {
00429               ctype = (char*)tmp->children->content;
00430        } else {
00431               ++ctype;
00432        }
00433        if (zend_hash_find(&ctx->messages, ctype, strlen(ctype)+1, (void**)&message) != SUCCESS) {
00434               soap_error1(E_ERROR, "Parsing WSDL: Missing <message> with name '%s'", tmp->children->content);
00435        }
00436 
00437        tmp = get_attribute(header->properties, "part");
00438        if (!tmp) {
00439               soap_error0(E_ERROR, "Parsing WSDL: Missing part attribute for <header>");
00440        }
00441        part = get_node_with_attribute_ex((*message)->children, "part", WSDL_NAMESPACE, "name", (char*)tmp->children->content, NULL);
00442        if (!part) {
00443               soap_error1(E_ERROR, "Parsing WSDL: Missing part '%s' in <message>", tmp->children->content);
00444        }
00445 
00446        h = emalloc(sizeof(sdlSoapBindingFunctionHeader));
00447        memset(h, 0, sizeof(sdlSoapBindingFunctionHeader));
00448        h->name = estrdup((char*)tmp->children->content);
00449 
00450        tmp = get_attribute(header->properties, "use");
00451        if (tmp && !strncmp((char*)tmp->children->content, "encoded", sizeof("encoded"))) {
00452               h->use = SOAP_ENCODED;
00453        } else {
00454               h->use = SOAP_LITERAL;
00455        }
00456 
00457        tmp = get_attribute(header->properties, "namespace");
00458        if (tmp) {
00459               h->ns = estrdup((char*)tmp->children->content);
00460        }
00461 
00462        if (h->use == SOAP_ENCODED) {
00463               tmp = get_attribute(header->properties, "encodingStyle");
00464               if (tmp) {
00465                      if (strncmp((char*)tmp->children->content, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) {
00466                             h->encodingStyle = SOAP_ENCODING_1_1;
00467                      } else if (strncmp((char*)tmp->children->content, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) {
00468                             h->encodingStyle = SOAP_ENCODING_1_2;
00469                      } else {
00470                             soap_error1(E_ERROR, "Parsing WSDL: Unknown encodingStyle '%s'", tmp->children->content);
00471                      }
00472               } else {
00473                      soap_error0(E_ERROR, "Parsing WSDL: Unspecified encodingStyle");
00474               }
00475        }
00476 
00477        tmp = get_attribute(part->properties, "type");
00478        if (tmp != NULL) {
00479               h->encode = get_encoder_from_prefix(ctx->sdl, part, tmp->children->content);
00480        } else {
00481               tmp = get_attribute(part->properties, "element");
00482               if (tmp != NULL) {
00483                      h->element = get_element(ctx->sdl, part, tmp->children->content);
00484                      if (h->element) {
00485                             h->encode = h->element->encode;
00486                             if (!h->ns && h->element->namens) {
00487                                    h->ns = estrdup(h->element->namens);
00488                             }
00489                             if (h->element->name) {
00490                                    efree(h->name);
00491                                    h->name = estrdup(h->element->name);
00492                             }
00493                      }
00494               }
00495        }
00496        if (!fault) {
00497               xmlNodePtr trav = header->children;
00498               while (trav != NULL) {
00499                      if (node_is_equal_ex(trav, "headerfault", wsdl_soap_namespace)) {
00500                             sdlSoapBindingFunctionHeaderPtr hf = wsdl_soap_binding_header(ctx, trav, wsdl_soap_namespace, 1);
00501                             smart_str key = {0};
00502 
00503                             if (h->headerfaults == NULL) {
00504                                    h->headerfaults = emalloc(sizeof(HashTable));
00505                                    zend_hash_init(h->headerfaults, 0, NULL, delete_header, 0);
00506                             }
00507 
00508                             if (hf->ns) {
00509                                    smart_str_appends(&key,hf->ns);
00510                                    smart_str_appendc(&key,':');
00511                             }
00512                             smart_str_appends(&key,hf->name);
00513                             smart_str_0(&key);
00514                             if (zend_hash_add(h->headerfaults, key.c, key.len+1, (void**)&hf, sizeof(sdlSoapBindingFunctionHeaderPtr), NULL) != SUCCESS) {
00515                                    delete_header((void**)&hf);
00516                             }
00517                             smart_str_free(&key);
00518                      } else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
00519                             soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
00520                      }
00521                      trav = trav->next;
00522               }
00523        }
00524        return h;
00525 }
00526 
00527 static void wsdl_soap_binding_body(sdlCtx* ctx, xmlNodePtr node, char* wsdl_soap_namespace, sdlSoapBindingFunctionBody *binding, HashTable* params)
00528 {
00529        xmlNodePtr body, trav;
00530        xmlAttrPtr tmp;
00531 
00532        trav = node->children;
00533        while (trav != NULL) {
00534               if (node_is_equal_ex(trav, "body", wsdl_soap_namespace)) {
00535                      body = trav;
00536 
00537                      tmp = get_attribute(body->properties, "use");
00538                      if (tmp && !strncmp((char*)tmp->children->content, "literal", sizeof("literal"))) {
00539                             binding->use = SOAP_LITERAL;
00540                      } else {
00541                             binding->use = SOAP_ENCODED;
00542                      }
00543 
00544                      tmp = get_attribute(body->properties, "namespace");
00545                      if (tmp) {
00546                             binding->ns = estrdup((char*)tmp->children->content);
00547                      }
00548 
00549                      tmp = get_attribute(body->properties, "parts");
00550                      if (tmp) {
00551                             HashTable    ht;
00552                             char *parts = (char*)tmp->children->content;
00553 
00554                             /* Delete all parts those are not in the "parts" attribute */
00555                             zend_hash_init(&ht, 0, NULL, delete_parameter, 0);
00556                             while (*parts) {
00557                                    HashPosition pos;
00558                                    sdlParamPtr *param;
00559                                    int found = 0;
00560                                    char *end;
00561 
00562                                    while (*parts == ' ') ++parts;
00563                                    if (*parts == '\0') break;
00564                                    end = strchr(parts, ' ');
00565                                    if (end) *end = '\0';
00566                                    zend_hash_internal_pointer_reset_ex(params, &pos);
00567                                    while (zend_hash_get_current_data_ex(params, (void **)&param, &pos) != FAILURE) {
00568                                           if ((*param)->paramName &&
00569                                               strcmp(parts, (*param)->paramName) == 0) {
00570                                           sdlParamPtr x_param;
00571                                           x_param = emalloc(sizeof(sdlParam));
00572                                           *x_param = **param;
00573                                           (*param)->paramName = NULL;
00574                                           zend_hash_next_index_insert(&ht, &x_param, sizeof(sdlParamPtr), NULL);
00575                                           found = 1;
00576                                           break;
00577                                           }
00578                                           zend_hash_move_forward_ex(params, &pos);
00579                                    }
00580                                    if (!found) {
00581                                           soap_error1(E_ERROR, "Parsing WSDL: Missing part '%s' in <message>", parts);
00582                                    }
00583                                    parts += strlen(parts);
00584                                    if (end) *end = ' ';
00585                             }
00586                             zend_hash_destroy(params);
00587                             *params = ht;
00588                      }
00589 
00590                      if (binding->use == SOAP_ENCODED) {
00591                             tmp = get_attribute(body->properties, "encodingStyle");
00592                             if (tmp) {
00593                                    if (strncmp((char*)tmp->children->content, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) {
00594                                           binding->encodingStyle = SOAP_ENCODING_1_1;
00595                                    } else if (strncmp((char*)tmp->children->content, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) {
00596                                           binding->encodingStyle = SOAP_ENCODING_1_2;
00597                                    } else {
00598                                           soap_error1(E_ERROR, "Parsing WSDL: Unknown encodingStyle '%s'", tmp->children->content);
00599                                    }
00600                             } else {
00601                                    soap_error0(E_ERROR, "Parsing WSDL: Unspecified encodingStyle");
00602                             }
00603                      }
00604               } else if (node_is_equal_ex(trav, "header", wsdl_soap_namespace)) {
00605                      sdlSoapBindingFunctionHeaderPtr h = wsdl_soap_binding_header(ctx, trav, wsdl_soap_namespace, 0);
00606                      smart_str key = {0};
00607 
00608                      if (binding->headers == NULL) {
00609                             binding->headers = emalloc(sizeof(HashTable));
00610                             zend_hash_init(binding->headers, 0, NULL, delete_header, 0);
00611                      }
00612 
00613                      if (h->ns) {
00614                             smart_str_appends(&key,h->ns);
00615                             smart_str_appendc(&key,':');
00616                      }
00617                      smart_str_appends(&key,h->name);
00618                      smart_str_0(&key);
00619                      if (zend_hash_add(binding->headers, key.c, key.len+1, (void**)&h, sizeof(sdlSoapBindingFunctionHeaderPtr), NULL) != SUCCESS) {
00620                             delete_header((void**)&h);
00621                      }
00622                      smart_str_free(&key);
00623               } else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
00624                      soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
00625               }
00626               trav = trav->next;
00627        }
00628 }
00629 
00630 static HashTable* wsdl_message(sdlCtx *ctx, xmlChar* message_name)
00631 {
00632        xmlNodePtr trav, part, message = NULL, *tmp;
00633        HashTable* parameters = NULL;
00634        char *ctype;
00635 
00636        ctype = strrchr((char*)message_name,':');
00637        if (ctype == NULL) {
00638               ctype = (char*)message_name;
00639        } else {
00640               ++ctype;
00641        }
00642        if (zend_hash_find(&ctx->messages, ctype, strlen(ctype)+1, (void**)&tmp) != SUCCESS) {
00643               soap_error1(E_ERROR, "Parsing WSDL: Missing <message> with name '%s'", message_name);
00644        }
00645        message = *tmp;
00646 
00647        parameters = emalloc(sizeof(HashTable));
00648        zend_hash_init(parameters, 0, NULL, delete_parameter, 0);
00649 
00650        trav = message->children;
00651        while (trav != NULL) {
00652               xmlAttrPtr element, type, name;
00653               sdlParamPtr param;
00654 
00655               if (trav->ns != NULL && strcmp((char*)trav->ns->href, WSDL_NAMESPACE) != 0) {
00656                      soap_error1(E_ERROR, "Parsing WSDL: Unexpected extensibility element <%s>", trav->name);
00657               }
00658               if (node_is_equal(trav,"documentation")) {
00659                      trav = trav->next;
00660                      continue;
00661               }
00662               if (!node_is_equal(trav,"part")) {
00663                      soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
00664               }
00665               part = trav;
00666               param = emalloc(sizeof(sdlParam));
00667               memset(param,0,sizeof(sdlParam));
00668               param->order = 0;
00669 
00670               name = get_attribute(part->properties, "name");
00671               if (name == NULL) {
00672                      soap_error1(E_ERROR, "Parsing WSDL: No name associated with <part> '%s'", message->name);
00673               }
00674 
00675               param->paramName = estrdup((char*)name->children->content);
00676 
00677               type = get_attribute(part->properties, "type");
00678               if (type != NULL) {
00679                      param->encode = get_encoder_from_prefix(ctx->sdl, part, type->children->content);
00680               } else {
00681                      element = get_attribute(part->properties, "element");
00682                      if (element != NULL) {
00683                             param->element = get_element(ctx->sdl, part, element->children->content);
00684                             if (param->element) {
00685                                    param->encode = param->element->encode;
00686                             }
00687                      }
00688               }
00689 
00690               zend_hash_next_index_insert(parameters, &param, sizeof(sdlParamPtr), NULL);
00691 
00692               trav = trav->next;
00693        }
00694        return parameters;
00695 }
00696 
00697 static sdlPtr load_wsdl(zval *this_ptr, char *struri TSRMLS_DC)
00698 {
00699        sdlCtx ctx;
00700        int i,n;
00701 
00702        memset(&ctx,0,sizeof(ctx));
00703        ctx.sdl = emalloc(sizeof(sdl));
00704        memset(ctx.sdl, 0, sizeof(sdl));
00705        ctx.sdl->source = estrdup(struri);
00706        zend_hash_init(&ctx.sdl->functions, 0, NULL, delete_function, 0);
00707 
00708        zend_hash_init(&ctx.docs, 0, NULL, delete_document, 0);
00709        zend_hash_init(&ctx.messages, 0, NULL, NULL, 0);
00710        zend_hash_init(&ctx.bindings, 0, NULL, NULL, 0);
00711        zend_hash_init(&ctx.portTypes, 0, NULL, NULL, 0);
00712        zend_hash_init(&ctx.services,  0, NULL, NULL, 0);
00713 
00714        load_wsdl_ex(this_ptr, struri,&ctx, 0 TSRMLS_CC);
00715        schema_pass2(&ctx);
00716 
00717        n = zend_hash_num_elements(&ctx.services);
00718        if (n > 0) {
00719               zend_hash_internal_pointer_reset(&ctx.services);
00720               for (i = 0; i < n; i++) {
00721                      xmlNodePtr *tmp, service;
00722                      xmlNodePtr trav, port;
00723                      int has_soap_port = 0;
00724 
00725                      zend_hash_get_current_data(&ctx.services, (void **)&tmp);
00726                      service = *tmp;
00727 
00728                      trav = service->children;
00729                      while (trav != NULL) {
00730                             xmlAttrPtr type, name, bindingAttr, location;
00731                             xmlNodePtr portType, operation;
00732                             xmlNodePtr address, binding, trav2;
00733                             char *ctype;
00734                             sdlBindingPtr tmpbinding;
00735                             char *wsdl_soap_namespace = NULL;
00736 
00737                             if (!is_wsdl_element(trav) || node_is_equal(trav,"documentation")) {
00738                                    trav = trav->next;
00739                                    continue;
00740                             }
00741                             if (!node_is_equal(trav,"port")) {
00742                                    soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
00743                             }
00744 
00745                             port = trav;
00746 
00747                             tmpbinding = emalloc(sizeof(sdlBinding));
00748                             memset(tmpbinding, 0, sizeof(sdlBinding));
00749 
00750                             bindingAttr = get_attribute(port->properties, "binding");
00751                             if (bindingAttr == NULL) {
00752                                    soap_error0(E_ERROR, "Parsing WSDL: No binding associated with <port>");
00753                             }
00754 
00755                             /* find address and figure out binding type */
00756                             address = NULL;
00757                             trav2 = port->children;
00758                             while (trav2 != NULL) {
00759                                    if (node_is_equal(trav2,"address") && trav2->ns) {
00760                                           if (!strncmp((char*)trav2->ns->href, WSDL_SOAP11_NAMESPACE, sizeof(WSDL_SOAP11_NAMESPACE))) {
00761                                                  address = trav2;
00762                                                  wsdl_soap_namespace = WSDL_SOAP11_NAMESPACE;
00763                                                  tmpbinding->bindingType = BINDING_SOAP;
00764                                           } else if (!strncmp((char*)trav2->ns->href, WSDL_SOAP12_NAMESPACE, sizeof(WSDL_SOAP12_NAMESPACE))) {
00765                                                  address = trav2;
00766                                                  wsdl_soap_namespace = WSDL_SOAP12_NAMESPACE;
00767                                                  tmpbinding->bindingType = BINDING_SOAP;
00768                                           } else if (!strncmp((char*)trav2->ns->href, RPC_SOAP12_NAMESPACE, sizeof(RPC_SOAP12_NAMESPACE))) {
00769                                                  address = trav2;
00770                                                  wsdl_soap_namespace = RPC_SOAP12_NAMESPACE;
00771                                                  tmpbinding->bindingType = BINDING_SOAP;
00772                                           } else if (!strncmp((char*)trav2->ns->href, WSDL_HTTP11_NAMESPACE, sizeof(WSDL_HTTP11_NAMESPACE))) {
00773                                                  address = trav2;
00774                                                  tmpbinding->bindingType = BINDING_HTTP;
00775                                           } else if (!strncmp((char*)trav2->ns->href, WSDL_HTTP12_NAMESPACE, sizeof(WSDL_HTTP12_NAMESPACE))) {
00776                                                  address = trav2;
00777                                                  tmpbinding->bindingType = BINDING_HTTP;
00778                                           }
00779                                    }
00780                                    if (trav2 != address && is_wsdl_element(trav2) && !node_is_equal(trav2,"documentation")) {
00781                                           soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
00782                                    }
00783                               trav2 = trav2->next;
00784                             }
00785                             if (!address || tmpbinding->bindingType == BINDING_HTTP) {
00786                                    if (has_soap_port || trav->next || i < n-1) {
00787                                           efree(tmpbinding);
00788                                           trav = trav->next;
00789                                           continue;
00790                                    } else if (!address) {
00791                                           soap_error0(E_ERROR, "Parsing WSDL: No address associated with <port>");
00792                                    }
00793                             }
00794                             has_soap_port = 1;
00795 
00796                             location = get_attribute(address->properties, "location");
00797                             if (!location) {
00798                                    soap_error0(E_ERROR, "Parsing WSDL: No location associated with <port>");
00799                             }
00800 
00801                             tmpbinding->location = estrdup((char*)location->children->content);
00802 
00803                             ctype = strrchr((char*)bindingAttr->children->content,':');
00804                             if (ctype == NULL) {
00805                                    ctype = (char*)bindingAttr->children->content;
00806                             } else {
00807                                    ++ctype;
00808                             }
00809                             if (zend_hash_find(&ctx.bindings, ctype, strlen(ctype)+1, (void*)&tmp) != SUCCESS) {
00810                                    soap_error1(E_ERROR, "Parsing WSDL: No <binding> element with name '%s'", ctype);
00811                             }
00812                             binding = *tmp;
00813 
00814                             if (tmpbinding->bindingType == BINDING_SOAP) {
00815                                    sdlSoapBindingPtr soapBinding;
00816                                    xmlNodePtr soapBindingNode;
00817                                    xmlAttrPtr tmp;
00818 
00819                                    soapBinding = emalloc(sizeof(sdlSoapBinding));
00820                                    memset(soapBinding, 0, sizeof(sdlSoapBinding));
00821                                    soapBinding->style = SOAP_DOCUMENT;
00822 
00823                                    soapBindingNode = get_node_ex(binding->children, "binding", wsdl_soap_namespace);
00824                                    if (soapBindingNode) {
00825                                           tmp = get_attribute(soapBindingNode->properties, "style");
00826                                           if (tmp && !strncmp((char*)tmp->children->content, "rpc", sizeof("rpc"))) {
00827                                                  soapBinding->style = SOAP_RPC;
00828                                           }
00829 
00830                                           tmp = get_attribute(soapBindingNode->properties, "transport");
00831                                           if (tmp) {
00832                                                  if (strncmp((char*)tmp->children->content, WSDL_HTTP_TRANSPORT, sizeof(WSDL_HTTP_TRANSPORT)) == 0) {
00833                                                         soapBinding->transport = SOAP_TRANSPORT_HTTP;
00834                                                  } else {
00835                                                         /* try the next binding */
00836                                                         efree(soapBinding);
00837                                                         efree(tmpbinding->location);
00838                                                         efree(tmpbinding);
00839                                                         trav = trav->next;
00840                                                         continue;
00841                                                  }
00842                                           }
00843                                    }
00844                                    tmpbinding->bindingAttributes = (void *)soapBinding;
00845                             }
00846 
00847                             name = get_attribute(binding->properties, "name");
00848                             if (name == NULL) {
00849                                    soap_error0(E_ERROR, "Parsing WSDL: Missing 'name' attribute for <binding>");
00850                             }
00851                             tmpbinding->name = estrdup((char*)name->children->content);
00852 
00853                             type = get_attribute(binding->properties, "type");
00854                             if (type == NULL) {
00855                                    soap_error0(E_ERROR, "Parsing WSDL: Missing 'type' attribute for <binding>");
00856                             }
00857 
00858                             ctype = strrchr((char*)type->children->content,':');
00859                             if (ctype == NULL) {
00860                                    ctype = (char*)type->children->content;
00861                             } else {
00862                                    ++ctype;
00863                             }
00864                             if (zend_hash_find(&ctx.portTypes, ctype, strlen(ctype)+1, (void**)&tmp) != SUCCESS) {
00865                                    soap_error1(E_ERROR, "Parsing WSDL: Missing <portType> with name '%s'", name->children->content);
00866                             }
00867                             portType = *tmp;
00868 
00869                             trav2 = binding->children;
00870                             while (trav2 != NULL) {
00871                                    sdlFunctionPtr function;
00872                                    xmlNodePtr input, output, fault, portTypeOperation, trav3;
00873                                    xmlAttrPtr op_name, paramOrder;
00874 
00875                                    if ((tmpbinding->bindingType == BINDING_SOAP &&
00876                                        node_is_equal_ex(trav2, "binding", wsdl_soap_namespace)) ||
00877                                        !is_wsdl_element(trav2) ||
00878                                        node_is_equal(trav2,"documentation")) {
00879                                           trav2 = trav2->next;
00880                                           continue;
00881                                    }
00882                                    if (!node_is_equal(trav2,"operation")) {
00883                                           soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
00884                                    }
00885 
00886                                    operation = trav2;
00887 
00888                                    op_name = get_attribute(operation->properties, "name");
00889                                    if (op_name == NULL) {
00890                                           soap_error0(E_ERROR, "Parsing WSDL: Missing 'name' attribute for <operation>");
00891                                    }
00892 
00893                                    trav3 = operation->children;
00894                                    while  (trav3 != NULL) {
00895                                           if (tmpbinding->bindingType == BINDING_SOAP &&
00896                                               node_is_equal_ex(trav3, "operation", wsdl_soap_namespace)) {
00897                                           } else if (is_wsdl_element(trav3) &&
00898                                                      !node_is_equal(trav3,"input") &&
00899                                                      !node_is_equal(trav3,"output") &&
00900                                                      !node_is_equal(trav3,"fault") &&
00901                                                      !node_is_equal(trav3,"documentation")) {
00902                                                  soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav3->name);
00903                                           }
00904                                           trav3 = trav3->next;
00905                                    }
00906 
00907                                    portTypeOperation = get_node_with_attribute_ex(portType->children, "operation", WSDL_NAMESPACE, "name", (char*)op_name->children->content, NULL);
00908                                    if (portTypeOperation == NULL) {
00909                                           soap_error1(E_ERROR, "Parsing WSDL: Missing <portType>/<operation> with name '%s'", op_name->children->content);
00910                                    }
00911 
00912                                    function = emalloc(sizeof(sdlFunction));
00913                                    memset(function, 0, sizeof(sdlFunction));
00914                                    function->functionName = estrdup((char*)op_name->children->content);
00915 
00916                                    if (tmpbinding->bindingType == BINDING_SOAP) {
00917                                           sdlSoapBindingFunctionPtr soapFunctionBinding;
00918                                           sdlSoapBindingPtr soapBinding;
00919                                           xmlNodePtr soapOperation;
00920                                           xmlAttrPtr tmp;
00921 
00922                                           soapFunctionBinding = emalloc(sizeof(sdlSoapBindingFunction));
00923                                           memset(soapFunctionBinding, 0, sizeof(sdlSoapBindingFunction));
00924                                           soapBinding = (sdlSoapBindingPtr)tmpbinding->bindingAttributes;
00925                                           soapFunctionBinding->style = soapBinding->style;
00926 
00927                                           soapOperation = get_node_ex(operation->children, "operation", wsdl_soap_namespace);
00928                                           if (soapOperation) {
00929                                                  tmp = get_attribute(soapOperation->properties, "soapAction");
00930                                                  if (tmp) {
00931                                                         soapFunctionBinding->soapAction = estrdup((char*)tmp->children->content);
00932                                                  }
00933 
00934                                                  tmp = get_attribute(soapOperation->properties, "style");
00935                                                  if (tmp) {
00936                                                         if (!strncmp((char*)tmp->children->content, "rpc", sizeof("rpc"))) {
00937                                                                soapFunctionBinding->style = SOAP_RPC;
00938                                                         } else {
00939                                                                soapFunctionBinding->style = SOAP_DOCUMENT;
00940                                                         }
00941                                                  } else {
00942                                                         soapFunctionBinding->style = soapBinding->style;
00943                                                  }
00944                                           }
00945 
00946                                           function->bindingAttributes = (void *)soapFunctionBinding;
00947                                    }
00948 
00949                                    input = get_node_ex(portTypeOperation->children, "input", WSDL_NAMESPACE);
00950                                    if (input != NULL) {
00951                                           xmlAttrPtr message, name;
00952 
00953                                           message = get_attribute(input->properties, "message");
00954                                           if (message == NULL) {
00955                                                  soap_error1(E_ERROR, "Parsing WSDL: Missing name for <input> of '%s'", op_name->children->content);
00956                                           }
00957                                           function->requestParameters = wsdl_message(&ctx, message->children->content);
00958 
00959                                           name = get_attribute(input->properties, "name");
00960 /* FIXME
00961                                           if (name != NULL) {
00962                                                  function->requestName = estrdup(name->children->content);
00963                                           } else {
00964 */
00965                                           {
00966                                                  function->requestName = estrdup(function->functionName);
00967                                           }
00968 
00969                                           if (tmpbinding->bindingType == BINDING_SOAP) {
00970                                                  input = get_node_ex(operation->children, "input", WSDL_NAMESPACE);
00971                                                  if (input != NULL) {
00972                                                         sdlSoapBindingFunctionPtr soapFunctionBinding = function->bindingAttributes;
00973                                                         wsdl_soap_binding_body(&ctx, input, wsdl_soap_namespace, &soapFunctionBinding->input, function->requestParameters);
00974                                                  }
00975                                           }
00976                                    }
00977 
00978                                    output = get_node_ex(portTypeOperation->children, "output", WSDL_NAMESPACE);
00979                                    if (output != NULL) {
00980                                           xmlAttrPtr message, name;
00981 
00982                                           message = get_attribute(output->properties, "message");
00983                                           if (message == NULL) {
00984                                                  soap_error1(E_ERROR, "Parsing WSDL: Missing name for <output> of '%s'", op_name->children->content);
00985                                           }
00986                                           function->responseParameters = wsdl_message(&ctx, message->children->content);
00987 
00988                                           name = get_attribute(output->properties, "name");
00989 /* FIXME
00990                                           if (name != NULL) {
00991                                                  function->responseName = estrdup(name->children->content);
00992                                           } else if (input == NULL) {
00993                                                  function->responseName = estrdup(function->functionName);
00994                                           } else {
00995 */
00996                                           {
00997                                                  int len = strlen(function->functionName);
00998                                                  function->responseName = emalloc(len + sizeof("Response"));
00999                                                  memcpy(function->responseName, function->functionName, len);
01000                                                  memcpy(function->responseName+len, "Response", sizeof("Response"));
01001                                           }
01002 
01003                                           if (tmpbinding->bindingType == BINDING_SOAP) {
01004                                                  output = get_node_ex(operation->children, "output", WSDL_NAMESPACE);
01005                                                  if (output != NULL) {
01006                                                         sdlSoapBindingFunctionPtr soapFunctionBinding = function->bindingAttributes;
01007                                                         wsdl_soap_binding_body(&ctx, output, wsdl_soap_namespace, &soapFunctionBinding->output, function->responseParameters);
01008                                                  }
01009                                           }
01010                                    }
01011 
01012                                    paramOrder = get_attribute(portTypeOperation->properties, "parameterOrder");
01013                                    if (paramOrder) {
01014                                           /* FIXME: */
01015                                    }
01016 
01017                                    fault = portTypeOperation->children;
01018                                    while (fault != NULL) {
01019                                           if (node_is_equal_ex(fault, "fault", WSDL_NAMESPACE)) {
01020                                                  xmlAttrPtr message, name;
01021                                                  sdlFaultPtr f;
01022 
01023                                                  name = get_attribute(fault->properties, "name");
01024                                                  if (name == NULL) {
01025                                                         soap_error1(E_ERROR, "Parsing WSDL: Missing name for <fault> of '%s'", op_name->children->content);
01026                                                  }
01027                                                  message = get_attribute(fault->properties, "message");
01028                                                  if (message == NULL) {
01029                                                         soap_error1(E_ERROR, "Parsing WSDL: Missing name for <output> of '%s'", op_name->children->content);
01030                                                  }
01031 
01032                                                  f = emalloc(sizeof(sdlFault));
01033                                                  memset(f, 0, sizeof(sdlFault));
01034 
01035                                                  f->name = estrdup((char*)name->children->content);
01036                                                  f->details = wsdl_message(&ctx, message->children->content);
01037                                                  if (f->details == NULL || zend_hash_num_elements(f->details) > 1) {
01038                                                         soap_error1(E_ERROR, "Parsing WSDL: The fault message '%s' must have a single part", message->children->content);
01039                                                  }
01040 
01041                                                  if (tmpbinding->bindingType == BINDING_SOAP) {
01042                                                         xmlNodePtr soap_fault = get_node_with_attribute_ex(operation->children, "fault", WSDL_NAMESPACE, "name", f->name, NULL);
01043                                                         if (soap_fault != NULL) {
01044                                                                xmlNodePtr trav = soap_fault->children;
01045                                                                while (trav != NULL) {
01046                                                                       if (node_is_equal_ex(trav, "fault", wsdl_soap_namespace)) {
01047                                                                              xmlAttrPtr tmp;
01048                                                                         sdlSoapBindingFunctionFaultPtr binding;
01049 
01050                                                                              binding = f->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunctionFault));
01051                                                                              memset(f->bindingAttributes, 0, sizeof(sdlSoapBindingFunctionFault));
01052 
01053                                                                              tmp = get_attribute(trav->properties, "use");
01054                                                                              if (tmp && !strncmp((char*)tmp->children->content, "encoded", sizeof("encoded"))) {
01055                                                                                     binding->use = SOAP_ENCODED;
01056                                                                              } else {
01057                                                                                     binding->use = SOAP_LITERAL;
01058                                                                              }
01059 
01060                                                                              tmp = get_attribute(trav->properties, "namespace");
01061                                                                              if (tmp) {
01062                                                                                     binding->ns = estrdup((char*)tmp->children->content);
01063                                                                              }
01064 
01065                                                                              if (binding->use == SOAP_ENCODED) {
01066                                                                                     tmp = get_attribute(trav->properties, "encodingStyle");
01067                                                                                     if (tmp) {
01068                                                                                            if (strncmp((char*)tmp->children->content, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) {
01069                                                                                                   binding->encodingStyle = SOAP_ENCODING_1_1;
01070                                                                                            } else if (strncmp((char*)tmp->children->content, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) {
01071                                                                                                   binding->encodingStyle = SOAP_ENCODING_1_2;
01072                                                                                            } else {
01073                                                                                                   soap_error1(E_ERROR, "Parsing WSDL: Unknown encodingStyle '%s'", tmp->children->content);
01074                                                                                            }
01075                                                                                     } else {
01076                                                                                            soap_error0(E_ERROR, "Parsing WSDL: Unspecified encodingStyle");
01077                                                                                     }
01078                                                                              }
01079                                                                       } else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
01080                                                                              soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
01081                                                                       }
01082                                                                       trav = trav->next;
01083                                                                }
01084                                                         }
01085                                                  }
01086                                                  if (function->faults == NULL) {
01087                                                         function->faults = emalloc(sizeof(HashTable));
01088                                                         zend_hash_init(function->faults, 0, NULL, delete_fault, 0);
01089                                                  }
01090                                                  if (zend_hash_add(function->faults, f->name, strlen(f->name)+1, (void**)&f, sizeof(sdlFaultPtr), NULL) != SUCCESS) {
01091                                                         soap_error2(E_ERROR, "Parsing WSDL: <fault> with name '%s' already defined in '%s'", f->name, op_name->children->content);
01092                                                  }
01093                                           }
01094                                           fault = fault->next;
01095                                    }
01096 
01097                                    function->binding = tmpbinding;
01098 
01099                                    {
01100                                           char *tmp = estrdup(function->functionName);
01101                                           int  len = strlen(tmp);
01102 
01103                                           if (zend_hash_add(&ctx.sdl->functions, php_strtolower(tmp, len), len+1, &function, sizeof(sdlFunctionPtr), NULL) != SUCCESS) {
01104                                                  zend_hash_next_index_insert(&ctx.sdl->functions, &function, sizeof(sdlFunctionPtr), NULL);
01105                                           }
01106                                           efree(tmp);
01107                                           if (function->requestName != NULL && strcmp(function->requestName,function->functionName) != 0) {
01108                                                  if (ctx.sdl->requests == NULL) {
01109                                                         ctx.sdl->requests = emalloc(sizeof(HashTable));
01110                                                         zend_hash_init(ctx.sdl->requests, 0, NULL, NULL, 0);
01111                                                  }
01112                                                  tmp = estrdup(function->requestName);
01113                                                  len = strlen(tmp);
01114                                                  zend_hash_add(ctx.sdl->requests, php_strtolower(tmp, len), len+1, &function, sizeof(sdlFunctionPtr), NULL);
01115                                                  efree(tmp);
01116                                           }
01117                                    }
01118                                    trav2 = trav2->next;
01119                             }
01120 
01121                             if (!ctx.sdl->bindings) {
01122                                    ctx.sdl->bindings = emalloc(sizeof(HashTable));
01123                                    zend_hash_init(ctx.sdl->bindings, 0, NULL, delete_binding, 0);
01124                             }
01125 
01126                             zend_hash_add(ctx.sdl->bindings, tmpbinding->name, strlen(tmpbinding->name), &tmpbinding, sizeof(sdlBindingPtr), NULL);
01127                             trav= trav->next;
01128                      }
01129 
01130                      zend_hash_move_forward(&ctx.services);
01131               }
01132        } else {
01133               soap_error0(E_ERROR, "Parsing WSDL: Couldn't bind to service");
01134        }
01135 
01136        if (ctx.sdl->bindings == NULL || ctx.sdl->bindings->nNumOfElements == 0) {
01137               soap_error0(E_ERROR, "Parsing WSDL: Could not find any usable binding services in WSDL.");
01138        }
01139 
01140        zend_hash_destroy(&ctx.messages);
01141        zend_hash_destroy(&ctx.bindings);
01142        zend_hash_destroy(&ctx.portTypes);
01143        zend_hash_destroy(&ctx.services);
01144        zend_hash_destroy(&ctx.docs);
01145 
01146        return ctx.sdl;
01147 }
01148 
01149 #define WSDL_CACHE_VERSION 0x0e
01150 
01151 #define WSDL_CACHE_GET(ret,type,buf)   memcpy(&ret,*buf,sizeof(type)); *buf += sizeof(type);
01152 #define WSDL_CACHE_GET_INT(ret,buf)    ret = ((unsigned char)(*buf)[0])|((unsigned char)(*buf)[1]<<8)|((unsigned char)(*buf)[2]<<16)|((int)(*buf)[3]<<24); *buf += 4;
01153 #define WSDL_CACHE_GET_1(ret,type,buf) ret = (type)(**buf); (*buf)++;
01154 #define WSDL_CACHE_GET_N(ret,n,buf)    memcpy(ret,*buf,n); *buf += n;
01155 #define WSDL_CACHE_SKIP(n,buf)         *buf += n;
01156 
01157 #define WSDL_CACHE_PUT_INT(val,buf)    smart_str_appendc(buf,val & 0xff); \
01158                                        smart_str_appendc(buf,(val >> 8) & 0xff); \
01159                                        smart_str_appendc(buf,(val >> 16) & 0xff); \
01160                                        smart_str_appendc(buf,(val >> 24) & 0xff);
01161 #define WSDL_CACHE_PUT_1(val,buf)      smart_str_appendc(buf,val);
01162 #define WSDL_CACHE_PUT_N(val,n,buf)    smart_str_appendl(buf,(char*)val,n);
01163 
01164 static char* sdl_deserialize_string(char **in)
01165 {
01166        char *s;
01167        int len;
01168 
01169        WSDL_CACHE_GET_INT(len, in);
01170        if (len == 0x7fffffff) {
01171               return NULL;
01172        } else {
01173               s = emalloc(len+1);
01174               WSDL_CACHE_GET_N(s, len, in);
01175               s[len] = '\0';
01176               return s;
01177        }
01178 }
01179 
01180 static void sdl_deserialize_key(HashTable* ht, void* data, char **in)
01181 {
01182        int len;
01183 
01184        WSDL_CACHE_GET_INT(len, in);
01185        if (len == 0) {
01186               zend_hash_next_index_insert(ht, &data, sizeof(void*), NULL);
01187        } else {
01188               zend_hash_add(ht, *in, len, &data, sizeof(void*), NULL);
01189               WSDL_CACHE_SKIP(len, in);
01190        }
01191 }
01192 
01193 static void sdl_deserialize_attribute(sdlAttributePtr attr, encodePtr *encoders, char **in)
01194 {
01195        int i;
01196 
01197        attr->name = sdl_deserialize_string(in);
01198        attr->namens = sdl_deserialize_string(in);
01199        attr->ref = sdl_deserialize_string(in);
01200        attr->def = sdl_deserialize_string(in);
01201        attr->fixed = sdl_deserialize_string(in);
01202        WSDL_CACHE_GET_1(attr->form, sdlForm, in);
01203        WSDL_CACHE_GET_1(attr->use, sdlUse, in);
01204        WSDL_CACHE_GET_INT(i, in);
01205        attr->encode = encoders[i];
01206        WSDL_CACHE_GET_INT(i, in);
01207        if (i > 0) {
01208               attr->extraAttributes = emalloc(sizeof(HashTable));
01209               zend_hash_init(attr->extraAttributes, i, NULL, delete_extra_attribute, 0);
01210               while (i > 0) {
01211                      sdlExtraAttributePtr x = emalloc(sizeof(sdlExtraAttribute));
01212                      sdl_deserialize_key(attr->extraAttributes, x, in);
01213                      x->ns = sdl_deserialize_string(in);
01214                      x->val = sdl_deserialize_string(in);
01215                      --i;
01216               }
01217        }
01218 }
01219 
01220 static sdlRestrictionIntPtr sdl_deserialize_resriction_int(char **in)
01221 {
01222        if (**in == 1) {
01223               sdlRestrictionIntPtr x = emalloc(sizeof(sdlRestrictionInt));
01224               WSDL_CACHE_SKIP(1, in);
01225               WSDL_CACHE_GET_INT(x->value, in);
01226               WSDL_CACHE_GET_1(x->fixed, char, in);
01227               return x;
01228        } else {
01229               WSDL_CACHE_SKIP(1, in);
01230               return NULL;
01231        }
01232 }
01233 
01234 static sdlRestrictionCharPtr sdl_deserialize_resriction_char(char **in)
01235 {
01236        if (**in == 1) {
01237               sdlRestrictionCharPtr x = emalloc(sizeof(sdlRestrictionChar));
01238               WSDL_CACHE_SKIP(1, in);
01239               x->value = sdl_deserialize_string(in);
01240               WSDL_CACHE_GET_1(x->fixed, char, in);
01241               return x;
01242        } else {
01243               WSDL_CACHE_SKIP(1, in);
01244               return NULL;
01245        }
01246 }
01247 
01248 static sdlContentModelPtr sdl_deserialize_model(sdlTypePtr *types, sdlTypePtr *elements, char **in)
01249 {
01250        int i;
01251        sdlContentModelPtr model = emalloc(sizeof(sdlContentModel));
01252 
01253        WSDL_CACHE_GET_1(model->kind, sdlContentKind, in);
01254        WSDL_CACHE_GET_INT(model->min_occurs, in);
01255        WSDL_CACHE_GET_INT(model->max_occurs, in);
01256        switch (model->kind) {
01257               case XSD_CONTENT_ELEMENT:
01258                      WSDL_CACHE_GET_INT(i, in);
01259                      model->u.element = elements[i];
01260                      break;
01261               case XSD_CONTENT_SEQUENCE:
01262               case XSD_CONTENT_ALL:
01263               case XSD_CONTENT_CHOICE:
01264                      WSDL_CACHE_GET_INT(i, in);
01265                      model->u.content = emalloc(sizeof(HashTable));
01266                      zend_hash_init(model->u.content, i, NULL, delete_model, 0);
01267                      while (i > 0) {
01268                             sdlContentModelPtr x = sdl_deserialize_model(types, elements, in);
01269                             zend_hash_next_index_insert(model->u.content,&x,sizeof(sdlContentModelPtr),NULL);
01270                             i--;
01271                      }
01272                      break;
01273               case XSD_CONTENT_GROUP_REF:
01274                      model->u.group_ref = sdl_deserialize_string(in);
01275                      break;
01276               case XSD_CONTENT_GROUP:
01277                      WSDL_CACHE_GET_INT(i, in);
01278                      model->u.group = types[i];
01279                      break;
01280               default:
01281                      break;
01282        }
01283        return model;
01284 }
01285 
01286 static void sdl_deserialize_type(sdlTypePtr type, sdlTypePtr *types, encodePtr *encoders, char **in)
01287 {
01288        int i;
01289        sdlTypePtr *elements = NULL;
01290 
01291        WSDL_CACHE_GET_1(type->kind, sdlTypeKind, in);
01292        type->name = sdl_deserialize_string(in);
01293        type->namens = sdl_deserialize_string(in);
01294        type->def = sdl_deserialize_string(in);
01295        type->fixed = sdl_deserialize_string(in);
01296        type->ref = sdl_deserialize_string(in);
01297        WSDL_CACHE_GET_1(type->nillable, char, in);
01298        WSDL_CACHE_GET_1(type->form, sdlForm, in);
01299 
01300        WSDL_CACHE_GET_INT(i, in);
01301        type->encode = encoders[i];
01302 
01303        if (**in == 1) {
01304               WSDL_CACHE_SKIP(1, in);
01305               type->restrictions = emalloc(sizeof(sdlRestrictions));
01306               /*memset(type->restrictions, 0, sizeof(sdlRestrictions));*/
01307               type->restrictions->minExclusive = sdl_deserialize_resriction_int(in);
01308               type->restrictions->minInclusive = sdl_deserialize_resriction_int(in);
01309               type->restrictions->maxExclusive = sdl_deserialize_resriction_int(in);
01310               type->restrictions->maxInclusive = sdl_deserialize_resriction_int(in);
01311               type->restrictions->totalDigits = sdl_deserialize_resriction_int(in);
01312               type->restrictions->fractionDigits = sdl_deserialize_resriction_int(in);
01313               type->restrictions->length = sdl_deserialize_resriction_int(in);
01314               type->restrictions->minLength = sdl_deserialize_resriction_int(in);
01315               type->restrictions->maxLength = sdl_deserialize_resriction_int(in);
01316               type->restrictions->whiteSpace = sdl_deserialize_resriction_char(in);
01317               type->restrictions->pattern = sdl_deserialize_resriction_char(in);
01318               WSDL_CACHE_GET_INT(i, in);
01319               if (i > 0) {
01320                      type->restrictions->enumeration = emalloc(sizeof(HashTable));
01321                      zend_hash_init(type->restrictions->enumeration, i, NULL, delete_restriction_var_char, 0);
01322                      while (i > 0) {
01323                             sdlRestrictionCharPtr x = sdl_deserialize_resriction_char(in);
01324                             sdl_deserialize_key(type->restrictions->enumeration, x, in);
01325                             --i;
01326                      }
01327               } else {
01328                      type->restrictions->enumeration = NULL;
01329               }
01330        } else {
01331               WSDL_CACHE_SKIP(1, in);
01332        }
01333 
01334        WSDL_CACHE_GET_INT(i, in);
01335        if (i > 0) {
01336               elements = safe_emalloc((i+1), sizeof(sdlTypePtr), 0);
01337               elements[0] = NULL;
01338               type->elements = emalloc(sizeof(HashTable));
01339               zend_hash_init(type->elements, i, NULL, delete_type, 0);
01340               while (i > 0) {
01341                      sdlTypePtr t = emalloc(sizeof(sdlType));
01342                      memset(t, 0, sizeof(sdlType));
01343                      sdl_deserialize_key(type->elements, t, in);
01344                      sdl_deserialize_type(t, types, encoders, in);
01345                      elements[i] = t;
01346                      --i;
01347               }
01348        }
01349 
01350        WSDL_CACHE_GET_INT(i, in);
01351        if (i > 0) {
01352               type->attributes = emalloc(sizeof(HashTable));
01353               zend_hash_init(type->attributes, i, NULL, delete_attribute, 0);
01354               while (i > 0) {
01355                      sdlAttributePtr attr = emalloc(sizeof(sdlAttribute));
01356                      memset(attr, 0, sizeof(sdlAttribute));
01357                      sdl_deserialize_key(type->attributes, attr, in);
01358                      sdl_deserialize_attribute(attr, encoders, in);
01359                      --i;
01360               }
01361        }
01362 
01363        if (**in != 0) {
01364               WSDL_CACHE_SKIP(1, in);
01365               type->model = sdl_deserialize_model(types, elements, in);
01366        } else {
01367               WSDL_CACHE_SKIP(1, in);
01368        }
01369        if (elements != NULL) {
01370               efree(elements);
01371        }
01372 }
01373 
01374 static void sdl_deserialize_encoder(encodePtr enc, sdlTypePtr *types, char **in)
01375 {
01376        int i;
01377 
01378        WSDL_CACHE_GET_INT(enc->details.type, in);
01379        enc->details.type_str = sdl_deserialize_string(in);
01380        enc->details.ns = sdl_deserialize_string(in);
01381        WSDL_CACHE_GET_INT(i, in);
01382        enc->details.sdl_type = types[i];
01383        enc->to_xml = sdl_guess_convert_xml;
01384        enc->to_zval = sdl_guess_convert_zval;
01385 
01386        if (enc->details.sdl_type == NULL) {
01387               int ns_len = strlen(enc->details.ns);
01388               int type_len = strlen(enc->details.type_str);
01389 
01390               if (((ns_len == sizeof(SOAP_1_1_ENC_NAMESPACE)-1 &&
01391                     memcmp(enc->details.ns, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)-1) == 0) ||
01392                    (ns_len == sizeof(SOAP_1_2_ENC_NAMESPACE)-1 &&
01393                     memcmp(enc->details.ns, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)-1) == 0))) {
01394                      char *enc_nscat;
01395                      int enc_ns_len;
01396                      int enc_len;
01397                      encodePtr real_enc;
01398 
01399                      enc_ns_len = sizeof(XSD_NAMESPACE)-1;
01400                      enc_len = enc_ns_len + type_len + 1;
01401                      enc_nscat = emalloc(enc_len + 1);
01402                      memcpy(enc_nscat, XSD_NAMESPACE, sizeof(XSD_NAMESPACE)-1);
01403                      enc_nscat[enc_ns_len] = ':';
01404                      memcpy(enc_nscat+enc_ns_len+1, enc->details.type_str, type_len);
01405                      enc_nscat[enc_len] = '\0';
01406 
01407                      real_enc = get_encoder_ex(NULL, enc_nscat, enc_len);
01408                      efree(enc_nscat);
01409                      if (real_enc) {
01410                             enc->to_zval = real_enc->to_zval;
01411                             enc->to_xml = real_enc->to_xml;
01412                      }
01413               }
01414        }      
01415 }
01416 
01417 static void sdl_deserialize_soap_body(sdlSoapBindingFunctionBodyPtr body, encodePtr *encoders, sdlTypePtr *types, char **in)
01418 {
01419        int i, j, n;
01420 
01421        WSDL_CACHE_GET_1(body->use, sdlEncodingUse, in);
01422        if (body->use == SOAP_ENCODED) {
01423               WSDL_CACHE_GET_1(body->encodingStyle, sdlRpcEncodingStyle, in);
01424        } else {
01425               body->encodingStyle = SOAP_ENCODING_DEFAULT;
01426        }
01427        body->ns = sdl_deserialize_string(in);
01428        WSDL_CACHE_GET_INT(i, in);
01429        if (i > 0) {
01430               body->headers = emalloc(sizeof(HashTable));
01431               zend_hash_init(body->headers, i, NULL, delete_header, 0);
01432               while (i > 0) {
01433                      sdlSoapBindingFunctionHeaderPtr tmp = emalloc(sizeof(sdlSoapBindingFunctionHeader));
01434                      memset(tmp, 0, sizeof(sdlSoapBindingFunctionHeader));
01435                      sdl_deserialize_key(body->headers, tmp, in);
01436                      WSDL_CACHE_GET_1(tmp->use, sdlEncodingUse, in);
01437                      if (tmp->use == SOAP_ENCODED) {
01438                             WSDL_CACHE_GET_1(tmp->encodingStyle, sdlRpcEncodingStyle, in);
01439                      } else {
01440                             tmp->encodingStyle = SOAP_ENCODING_DEFAULT;
01441                      }
01442                      tmp->name = sdl_deserialize_string(in);
01443                      tmp->ns = sdl_deserialize_string(in);
01444                      WSDL_CACHE_GET_INT(n, in);
01445                      tmp->encode = encoders[n];
01446                      WSDL_CACHE_GET_INT(n, in);
01447                      tmp->element = types[n];
01448                      --i;
01449                      WSDL_CACHE_GET_INT(j, in);
01450                      if (j > 0) {
01451                             tmp->headerfaults = emalloc(sizeof(HashTable));
01452                             zend_hash_init(tmp->headerfaults, i, NULL, delete_header, 0);
01453                             while (j > 0) {
01454                                    sdlSoapBindingFunctionHeaderPtr tmp2 = emalloc(sizeof(sdlSoapBindingFunctionHeader));
01455                                    memset(tmp2, 0, sizeof(sdlSoapBindingFunctionHeader));
01456                                    sdl_deserialize_key(tmp->headerfaults, tmp2, in);
01457                                    WSDL_CACHE_GET_1(tmp2->use, sdlEncodingUse, in);
01458                                    if (tmp2->use == SOAP_ENCODED) {
01459                                           WSDL_CACHE_GET_1(tmp2->encodingStyle, sdlRpcEncodingStyle, in);
01460                                    } else {
01461                                           tmp2->encodingStyle = SOAP_ENCODING_DEFAULT;
01462                                    }
01463                                    tmp2->name = sdl_deserialize_string(in);
01464                                    tmp2->ns = sdl_deserialize_string(in);
01465                                    WSDL_CACHE_GET_INT(n, in);
01466                                    tmp2->encode = encoders[n];
01467                                    WSDL_CACHE_GET_INT(n, in);
01468                                    tmp2->element = types[n];
01469                                    --j;
01470                             }
01471                      }
01472               }
01473        }
01474 }
01475 
01476 static HashTable* sdl_deserialize_parameters(encodePtr *encoders, sdlTypePtr *types, char **in)
01477 {
01478        int i, n;
01479        HashTable *ht;
01480 
01481        WSDL_CACHE_GET_INT(i, in);
01482        if (i == 0) {return NULL;}
01483        ht = emalloc(sizeof(HashTable));
01484        zend_hash_init(ht, i, NULL, delete_parameter, 0);
01485        while (i > 0) {
01486               sdlParamPtr param = emalloc(sizeof(sdlParam));
01487               sdl_deserialize_key(ht, param, in);
01488               param->paramName = sdl_deserialize_string(in);
01489               WSDL_CACHE_GET_INT(param->order, in);
01490               WSDL_CACHE_GET_INT(n, in);
01491               param->encode = encoders[n];
01492               WSDL_CACHE_GET_INT(n, in);
01493               param->element = types[n];
01494               --i;
01495        }
01496        return ht;
01497 }
01498 
01499 static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t, time_t *cached TSRMLS_DC)
01500 {
01501        sdlPtr sdl;
01502        time_t old_t;
01503        int  i, num_groups, num_types, num_elements, num_encoders, num_bindings, num_func;
01504        sdlFunctionPtr *functions = NULL;
01505        sdlBindingPtr *bindings;
01506        sdlTypePtr *types;
01507        encodePtr *encoders;
01508        encodePtr enc;
01509 
01510        int f;
01511        struct stat st;
01512        char *in, *buf;
01513 
01514        f = open(fn, O_RDONLY|O_BINARY);
01515        if (f < 0) {
01516               return NULL;
01517        }
01518        if (fstat(f, &st) != 0) {
01519               close(f);
01520               return NULL;
01521        }
01522        buf = in = emalloc(st.st_size);
01523        if (read(f, in, st.st_size) != st.st_size) {
01524               close(f);
01525               efree(in);
01526               return NULL;
01527        }
01528        close(f);
01529 
01530        if (strncmp(in,"wsdl",4) != 0 || in[4] != WSDL_CACHE_VERSION || in[5] != '\0') {
01531               unlink(fn);
01532               efree(buf);
01533               return NULL;
01534        }
01535        in += 6;
01536 
01537        WSDL_CACHE_GET(old_t, time_t, &in);
01538        if (old_t < t) {
01539               unlink(fn);
01540               efree(buf);
01541               return NULL;
01542        }
01543        *cached = old_t;
01544 
01545        WSDL_CACHE_GET_INT(i, &in);
01546        if (i == 0 && strncmp(in, uri, i) != 0) {
01547               unlink(fn);
01548               efree(buf);
01549               return NULL;
01550        }
01551        WSDL_CACHE_SKIP(i, &in);
01552 
01553        sdl = emalloc(sizeof(*sdl));
01554        memset(sdl, 0, sizeof(*sdl));
01555 
01556        sdl->source = sdl_deserialize_string(&in);
01557        sdl->target_ns = sdl_deserialize_string(&in);
01558 
01559        WSDL_CACHE_GET_INT(num_groups, &in);
01560        WSDL_CACHE_GET_INT(num_types, &in);
01561        WSDL_CACHE_GET_INT(num_elements, &in);
01562        WSDL_CACHE_GET_INT(num_encoders, &in);
01563 
01564        i = num_groups+num_types+num_elements;
01565        types = safe_emalloc((i+1), sizeof(sdlTypePtr), 0);
01566        types[0] = NULL;
01567        while (i > 0) {
01568               types[i] = emalloc(sizeof(sdlType));
01569               memset(types[i], 0, sizeof(sdlType));
01570               i--;
01571        }
01572 
01573        i = num_encoders;
01574        enc = defaultEncoding;
01575        while (enc->details.type != END_KNOWN_TYPES) {
01576               i++; enc++;
01577        }
01578        encoders = safe_emalloc((i+1), sizeof(encodePtr), 0);
01579        i = num_encoders;
01580        encoders[0] = NULL;
01581        while (i > 0) {
01582               encoders[i] = emalloc(sizeof(encode));
01583               memset(encoders[i], 0, sizeof(encode));
01584               i--;
01585        }
01586        i = num_encoders;
01587        enc = defaultEncoding;
01588        while (enc->details.type != END_KNOWN_TYPES) {
01589               encoders[++i] = enc++;
01590        }
01591 
01592        i = 1;
01593        if (num_groups > 0) {
01594               sdl->groups = emalloc(sizeof(HashTable));
01595               zend_hash_init(sdl->groups, num_groups, NULL, delete_type, 0);
01596               while (i < num_groups+1) {
01597                      sdl_deserialize_key(sdl->groups, types[i], &in);
01598                      sdl_deserialize_type(types[i], types, encoders, &in);
01599                      i++;
01600               }
01601        }
01602 
01603        if (num_types > 0) {
01604               sdl->types = emalloc(sizeof(HashTable));
01605               zend_hash_init(sdl->types, num_types, NULL, delete_type, 0);
01606               while (i < num_groups+num_types+1) {
01607                      sdl_deserialize_key(sdl->types, types[i], &in);
01608                      sdl_deserialize_type(types[i], types, encoders, &in);
01609                      i++;
01610               }
01611        }
01612 
01613        if (num_elements > 0) {
01614               sdl->elements = emalloc(sizeof(HashTable));
01615               zend_hash_init(sdl->elements, num_elements, NULL, delete_type, 0);
01616               while (i < num_groups+num_types+num_elements+1) {
01617                      sdl_deserialize_key(sdl->elements, types[i], &in);
01618                      sdl_deserialize_type(types[i], types, encoders, &in);
01619                      i++;
01620               }
01621        }
01622 
01623        i = 1;
01624        if (num_encoders > 0) {
01625               sdl->encoders = emalloc(sizeof(HashTable));
01626               zend_hash_init(sdl->encoders, num_encoders, NULL, delete_encoder, 0);
01627               while (i < num_encoders+1) {
01628                      sdl_deserialize_key(sdl->encoders, encoders[i], &in);
01629                      sdl_deserialize_encoder(encoders[i], types, &in);
01630                      i++;
01631               }
01632        }
01633 
01634        /* deserialize bindings */
01635        WSDL_CACHE_GET_INT(num_bindings, &in);
01636        bindings = safe_emalloc(num_bindings, sizeof(sdlBindingPtr), 0);
01637        if (num_bindings > 0) {
01638               sdl->bindings = emalloc(sizeof(HashTable));
01639               zend_hash_init(sdl->bindings, num_bindings, NULL, delete_binding, 0);
01640               for (i = 0; i < num_bindings; i++) {
01641                      sdlBindingPtr binding = emalloc(sizeof(sdlBinding));
01642                      memset(binding, 0, sizeof(sdlBinding));
01643                      sdl_deserialize_key(sdl->bindings, binding, &in);
01644                      binding->name = sdl_deserialize_string(&in);
01645                      binding->location = sdl_deserialize_string(&in);
01646                      WSDL_CACHE_GET_1(binding->bindingType,sdlBindingType,&in);
01647                      if (binding->bindingType == BINDING_SOAP && *in != 0) {
01648                        sdlSoapBindingPtr soap_binding = binding->bindingAttributes = emalloc(sizeof(sdlSoapBinding));
01649                             WSDL_CACHE_GET_1(soap_binding->style,sdlEncodingStyle,&in);
01650                             WSDL_CACHE_GET_1(soap_binding->transport,sdlTransport,&in);
01651                      } else {
01652                             WSDL_CACHE_SKIP(1,&in);
01653                      }
01654                      bindings[i] = binding;
01655               }
01656        }
01657 
01658        /* deserialize functions */
01659        WSDL_CACHE_GET_INT(num_func, &in);
01660        zend_hash_init(&sdl->functions, num_func, NULL, delete_function, 0);
01661        if (num_func > 0) {
01662               functions = safe_emalloc(num_func, sizeof(sdlFunctionPtr), 0);
01663               for (i = 0; i < num_func; i++) {
01664                      int binding_num, num_faults;
01665                      sdlFunctionPtr func = emalloc(sizeof(sdlFunction));
01666                      sdl_deserialize_key(&sdl->functions, func, &in);
01667                      func->functionName = sdl_deserialize_string(&in);
01668                      func->requestName = sdl_deserialize_string(&in);
01669                      func->responseName = sdl_deserialize_string(&in);
01670 
01671                      WSDL_CACHE_GET_INT(binding_num, &in);
01672                      if (binding_num == 0) {
01673                             func->binding = NULL;
01674                      } else {
01675                             func->binding = bindings[binding_num-1];
01676                      }
01677                      if (func->binding && func->binding->bindingType == BINDING_SOAP && *in != 0) {
01678                             sdlSoapBindingFunctionPtr binding = func->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunction));
01679                             memset(binding, 0, sizeof(sdlSoapBindingFunction));
01680                             WSDL_CACHE_GET_1(binding->style,sdlEncodingStyle,&in);
01681                             binding->soapAction = sdl_deserialize_string(&in);
01682                             sdl_deserialize_soap_body(&binding->input, encoders, types, &in);
01683                             sdl_deserialize_soap_body(&binding->output, encoders, types, &in);
01684                      } else {
01685                             WSDL_CACHE_SKIP(1, &in);
01686                             func->bindingAttributes = NULL;
01687                      }
01688 
01689                      func->requestParameters = sdl_deserialize_parameters(encoders, types, &in);
01690                      func->responseParameters = sdl_deserialize_parameters(encoders, types, &in);
01691 
01692                      WSDL_CACHE_GET_INT(num_faults, &in);
01693                      if (num_faults > 0) {
01694                        int j;
01695 
01696                             func->faults = emalloc(sizeof(HashTable));
01697                             zend_hash_init(func->faults, num_faults, NULL, delete_fault, 0);
01698 
01699                             for (j = 0; j < num_faults; j++) {
01700                                    sdlFaultPtr fault = emalloc(sizeof(sdlFault));
01701 
01702                                    sdl_deserialize_key(func->faults, fault, &in);
01703                                    fault->name =sdl_deserialize_string(&in);
01704                                    fault->details =sdl_deserialize_parameters(encoders, types, &in);
01705                                    if (*in != 0) {
01706                                           sdlSoapBindingFunctionFaultPtr binding = fault->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunctionFault));
01707                                           memset(binding, 0, sizeof(sdlSoapBindingFunctionFault));
01708                                           WSDL_CACHE_GET_1(binding->use,sdlEncodingUse,&in);
01709                                           if (binding->use == SOAP_ENCODED) {
01710                                                  WSDL_CACHE_GET_1(binding->encodingStyle, sdlRpcEncodingStyle, &in);
01711                                           } else {
01712                                                  binding->encodingStyle = SOAP_ENCODING_DEFAULT;
01713                                           }
01714                                           binding->ns = sdl_deserialize_string(&in);
01715                                    } else {
01716                                           WSDL_CACHE_SKIP(1, &in);
01717                                           fault->bindingAttributes = NULL;
01718                                    }
01719                             }
01720                      } else {
01721                             func->faults = NULL;
01722                      }
01723                      functions[i] = func;
01724               }
01725        }
01726 
01727        /* deserialize requests */
01728        WSDL_CACHE_GET_INT(i, &in);
01729        if (i > 0) {
01730               sdl->requests = emalloc(sizeof(HashTable));
01731               zend_hash_init(sdl->requests, i, NULL, NULL, 0);
01732               while (i > 0) {
01733                      int function_num;
01734 
01735                      WSDL_CACHE_GET_INT(function_num, &in);
01736                      sdl_deserialize_key(sdl->requests, functions[function_num-1], &in);
01737                      i--;
01738               }
01739        }
01740 
01741        if (functions) {
01742               efree(functions);
01743        }
01744        efree(bindings);
01745        efree(encoders);
01746        efree(types);
01747        efree(buf);
01748        return sdl;
01749 }
01750 
01751 static void sdl_serialize_string(const char *str, smart_str *out)
01752 {
01753        int i;
01754 
01755        if (str) {
01756               i = strlen(str);
01757               WSDL_CACHE_PUT_INT(i, out);
01758               if (i > 0) {
01759                      WSDL_CACHE_PUT_N(str, i, out);
01760               }
01761        } else {
01762               WSDL_CACHE_PUT_INT(0x7fffffff, out);
01763        }
01764 }
01765 
01766 static void sdl_serialize_key(HashTable *ht, smart_str *out)
01767 {
01768        char *key;
01769        uint  key_len;
01770        ulong index;
01771 
01772        if (zend_hash_get_current_key_ex(ht, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
01773               WSDL_CACHE_PUT_INT(key_len, out);
01774               WSDL_CACHE_PUT_N(key, key_len, out);
01775        } else {
01776               WSDL_CACHE_PUT_INT(0, out);
01777        }
01778 }
01779 
01780 static void sdl_serialize_encoder_ref(encodePtr enc, HashTable *tmp_encoders, smart_str *out) {
01781        if (enc) {
01782               int *encoder_num;
01783               if (zend_hash_find(tmp_encoders, (char*)&enc, sizeof(enc), (void**)&encoder_num) == SUCCESS) {
01784                      WSDL_CACHE_PUT_INT(*encoder_num, out);
01785               } else {
01786                      WSDL_CACHE_PUT_INT(0, out);
01787               }
01788        } else {
01789               WSDL_CACHE_PUT_INT(0, out);
01790        }
01791 }
01792 
01793 static void sdl_serialize_type_ref(sdlTypePtr type, HashTable *tmp_types, smart_str *out) {
01794        if (type) {
01795               int *type_num;
01796               if (zend_hash_find(tmp_types, (char*)&type, sizeof(type), (void**)&type_num) == SUCCESS) {
01797                      WSDL_CACHE_PUT_INT(*type_num, out);
01798               } else {
01799                      WSDL_CACHE_PUT_INT(0, out);
01800               }
01801        } else {
01802               WSDL_CACHE_PUT_INT(0,out);
01803        }
01804 }
01805 
01806 static void sdl_serialize_attribute(sdlAttributePtr attr, HashTable *tmp_encoders, smart_str *out)
01807 {
01808        int i;
01809 
01810        sdl_serialize_string(attr->name, out);
01811        sdl_serialize_string(attr->namens, out);
01812        sdl_serialize_string(attr->ref, out);
01813        sdl_serialize_string(attr->def, out);
01814        sdl_serialize_string(attr->fixed, out);
01815        WSDL_CACHE_PUT_1(attr->form, out);
01816        WSDL_CACHE_PUT_1(attr->use, out);
01817        sdl_serialize_encoder_ref(attr->encode, tmp_encoders, out);
01818        if (attr->extraAttributes) {
01819               i = zend_hash_num_elements(attr->extraAttributes);
01820        } else {
01821               i = 0;
01822        }
01823        WSDL_CACHE_PUT_INT(i, out);
01824        if (i > 0) {
01825               sdlExtraAttributePtr *tmp;
01826               zend_hash_internal_pointer_reset(attr->extraAttributes);
01827               while (zend_hash_get_current_data(attr->extraAttributes, (void**)&tmp) == SUCCESS) {
01828                      sdl_serialize_key(attr->extraAttributes, out);
01829                      sdl_serialize_string((*tmp)->ns, out);
01830                      sdl_serialize_string((*tmp)->val, out);
01831                      zend_hash_move_forward(attr->extraAttributes);
01832               }
01833        }
01834 }
01835 
01836 static void sdl_serialize_model(sdlContentModelPtr model, HashTable *tmp_types, HashTable *tmp_elements, smart_str *out)
01837 {
01838        WSDL_CACHE_PUT_1(model->kind, out);
01839        WSDL_CACHE_PUT_INT(model->min_occurs, out);
01840        WSDL_CACHE_PUT_INT(model->max_occurs, out);
01841        switch (model->kind) {
01842               case XSD_CONTENT_ELEMENT:
01843                      sdl_serialize_type_ref(model->u.element, tmp_elements, out);
01844                      break;
01845               case XSD_CONTENT_SEQUENCE:
01846               case XSD_CONTENT_ALL:
01847               case XSD_CONTENT_CHOICE: {
01848                             sdlContentModelPtr *tmp;
01849                             int i = zend_hash_num_elements(model->u.content);
01850 
01851                             WSDL_CACHE_PUT_INT(i, out);
01852                             zend_hash_internal_pointer_reset(model->u.content);
01853                             while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
01854                                    sdl_serialize_model(*tmp, tmp_types, tmp_elements, out);
01855                                    zend_hash_move_forward(model->u.content);
01856                             }
01857                      }
01858                      break;
01859               case XSD_CONTENT_GROUP_REF:
01860                      sdl_serialize_string(model->u.group_ref,out);
01861                      break;
01862               case XSD_CONTENT_GROUP:
01863                      sdl_serialize_type_ref(model->u.group, tmp_types, out);
01864                      break;
01865               default:
01866                      break;
01867        }
01868 }
01869 
01870 static void sdl_serialize_resriction_int(sdlRestrictionIntPtr x, smart_str *out)
01871 {
01872        if (x) {
01873               WSDL_CACHE_PUT_1(1, out);
01874               WSDL_CACHE_PUT_INT(x->value, out);
01875               WSDL_CACHE_PUT_1(x->fixed, out);
01876        } else {
01877               WSDL_CACHE_PUT_1(0, out);
01878        }
01879 }
01880 
01881 static void sdl_serialize_resriction_char(sdlRestrictionCharPtr x, smart_str *out)
01882 {
01883        if (x) {
01884               WSDL_CACHE_PUT_1(1, out);
01885               sdl_serialize_string(x->value, out);
01886               WSDL_CACHE_PUT_1(x->fixed, out);
01887        } else {
01888               WSDL_CACHE_PUT_1(0, out);
01889        }
01890 }
01891 
01892 static void sdl_serialize_type(sdlTypePtr type, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
01893 {
01894        int i;
01895        HashTable *tmp_elements = NULL;
01896 
01897        WSDL_CACHE_PUT_1(type->kind, out);
01898        sdl_serialize_string(type->name, out);
01899        sdl_serialize_string(type->namens, out);
01900        sdl_serialize_string(type->def, out);
01901        sdl_serialize_string(type->fixed, out);
01902        sdl_serialize_string(type->ref, out);
01903        WSDL_CACHE_PUT_1(type->nillable, out);
01904        WSDL_CACHE_PUT_1(type->form, out);
01905        sdl_serialize_encoder_ref(type->encode, tmp_encoders, out);
01906 
01907        if (type->restrictions) {
01908               WSDL_CACHE_PUT_1(1, out);
01909               sdl_serialize_resriction_int(type->restrictions->minExclusive,out);
01910               sdl_serialize_resriction_int(type->restrictions->minInclusive,out);
01911               sdl_serialize_resriction_int(type->restrictions->maxExclusive,out);
01912               sdl_serialize_resriction_int(type->restrictions->maxInclusive,out);
01913               sdl_serialize_resriction_int(type->restrictions->totalDigits,out);
01914               sdl_serialize_resriction_int(type->restrictions->fractionDigits,out);
01915               sdl_serialize_resriction_int(type->restrictions->length,out);
01916               sdl_serialize_resriction_int(type->restrictions->minLength,out);
01917               sdl_serialize_resriction_int(type->restrictions->maxLength,out);
01918               sdl_serialize_resriction_char(type->restrictions->whiteSpace,out);
01919               sdl_serialize_resriction_char(type->restrictions->pattern,out);
01920               if (type->restrictions->enumeration) {
01921                      i = zend_hash_num_elements(type->restrictions->enumeration);
01922               } else {
01923                      i = 0;
01924               }
01925               WSDL_CACHE_PUT_INT(i, out);
01926               if (i > 0) {
01927                      sdlRestrictionCharPtr *tmp;
01928 
01929                      zend_hash_internal_pointer_reset(type->restrictions->enumeration);
01930                      while (zend_hash_get_current_data(type->restrictions->enumeration, (void**)&tmp) == SUCCESS) {
01931                             sdl_serialize_resriction_char(*tmp, out);
01932                             sdl_serialize_key(type->restrictions->enumeration, out);
01933                             zend_hash_move_forward(type->restrictions->enumeration);
01934                      }
01935               }
01936        } else {
01937               WSDL_CACHE_PUT_1(0, out);
01938        }
01939        if (type->elements) {
01940               i = zend_hash_num_elements(type->elements);
01941        } else {
01942               i = 0;
01943        }
01944        WSDL_CACHE_PUT_INT(i, out);
01945        if (i > 0) {
01946               sdlTypePtr *tmp;
01947 
01948               tmp_elements = emalloc(sizeof(HashTable));
01949               zend_hash_init(tmp_elements, i, NULL, NULL, 0);
01950 
01951               zend_hash_internal_pointer_reset(type->elements);
01952               while (zend_hash_get_current_data(type->elements, (void**)&tmp) == SUCCESS) {
01953                      sdl_serialize_key(type->elements, out);
01954                      sdl_serialize_type(*tmp, tmp_encoders, tmp_types, out);
01955                      zend_hash_add(tmp_elements, (char*)tmp, sizeof(*tmp), &i, sizeof(int), NULL);
01956                      i--;
01957                      zend_hash_move_forward(type->elements);
01958               }
01959        }
01960 
01961        if (type->attributes) {
01962               i = zend_hash_num_elements(type->attributes);
01963        } else {
01964               i = 0;
01965        }
01966        WSDL_CACHE_PUT_INT(i, out);
01967        if (i > 0) {
01968               sdlAttributePtr *tmp;
01969               zend_hash_internal_pointer_reset(type->attributes);
01970               while (zend_hash_get_current_data(type->attributes, (void**)&tmp) == SUCCESS) {
01971                      sdl_serialize_key(type->attributes, out);
01972                      sdl_serialize_attribute(*tmp, tmp_encoders, out);
01973                      zend_hash_move_forward(type->attributes);
01974               }
01975        }
01976        if (type->model) {
01977               WSDL_CACHE_PUT_1(1, out);
01978               sdl_serialize_model(type->model, tmp_types, tmp_elements, out);
01979        } else {
01980               WSDL_CACHE_PUT_1(0, out);
01981        }
01982        if (tmp_elements != NULL) {
01983               zend_hash_destroy(tmp_elements);
01984               efree(tmp_elements);
01985        }
01986 }
01987 
01988 static void sdl_serialize_encoder(encodePtr enc, HashTable *tmp_types, smart_str *out)
01989 {
01990        WSDL_CACHE_PUT_INT(enc->details.type, out);
01991        sdl_serialize_string(enc->details.type_str, out);
01992        sdl_serialize_string(enc->details.ns, out);
01993        sdl_serialize_type_ref(enc->details.sdl_type, tmp_types, out);
01994 }
01995 
01996 static void sdl_serialize_parameters(HashTable *ht, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
01997 {
01998        int i;
01999 
02000        if (ht) {
02001               i = zend_hash_num_elements(ht);
02002        } else {
02003               i = 0;
02004        }
02005        WSDL_CACHE_PUT_INT(i, out);
02006        if (i > 0) {
02007               sdlParamPtr *tmp;
02008 
02009               zend_hash_internal_pointer_reset(ht);
02010               while (zend_hash_get_current_data(ht, (void**)&tmp) == SUCCESS) {
02011                      sdl_serialize_key(ht, out);
02012                      sdl_serialize_string((*tmp)->paramName, out);
02013                      WSDL_CACHE_PUT_INT((*tmp)->order, out);
02014                      sdl_serialize_encoder_ref((*tmp)->encode, tmp_encoders, out);
02015                      sdl_serialize_type_ref((*tmp)->element, tmp_types, out);
02016                      zend_hash_move_forward(ht);
02017               }
02018        }
02019 }
02020 
02021 static void sdl_serialize_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
02022 {
02023        int i, j;
02024 
02025        WSDL_CACHE_PUT_1(body->use, out);
02026        if (body->use == SOAP_ENCODED) {
02027               WSDL_CACHE_PUT_1(body->encodingStyle, out);
02028        }
02029        sdl_serialize_string(body->ns, out);
02030        if (body->headers) {
02031               i = zend_hash_num_elements(body->headers);
02032        } else {
02033               i = 0;
02034        }
02035        WSDL_CACHE_PUT_INT(i, out);
02036        if (i > 0) {
02037               sdlSoapBindingFunctionHeaderPtr *tmp;
02038               zend_hash_internal_pointer_reset(body->headers);
02039               while (zend_hash_get_current_data(body->headers, (void**)&tmp) == SUCCESS) {
02040                      sdl_serialize_key(body->headers, out);
02041                      WSDL_CACHE_PUT_1((*tmp)->use, out);
02042                      if ((*tmp)->use == SOAP_ENCODED) {
02043                             WSDL_CACHE_PUT_1((*tmp)->encodingStyle, out);
02044                      }
02045                      sdl_serialize_string((*tmp)->name, out);
02046                      sdl_serialize_string((*tmp)->ns, out);
02047                      sdl_serialize_encoder_ref((*tmp)->encode, tmp_encoders, out);
02048                      sdl_serialize_type_ref((*tmp)->element, tmp_types, out);
02049                      if ((*tmp)->headerfaults) {
02050                             j = zend_hash_num_elements((*tmp)->headerfaults);
02051                      } else {
02052                             j = 0;
02053                      }
02054                      WSDL_CACHE_PUT_INT(j, out);
02055                      if (j > 0) {
02056                             sdlSoapBindingFunctionHeaderPtr *tmp2;
02057                             zend_hash_internal_pointer_reset((*tmp)->headerfaults);
02058                             while (zend_hash_get_current_data((*tmp)->headerfaults, (void**)&tmp2) == SUCCESS) {
02059                                    sdl_serialize_key((*tmp)->headerfaults, out);
02060                                    WSDL_CACHE_PUT_1((*tmp2)->use, out);
02061                                    if ((*tmp2)->use == SOAP_ENCODED) {
02062                                           WSDL_CACHE_PUT_1((*tmp2)->encodingStyle, out);
02063                                    }
02064                                    sdl_serialize_string((*tmp2)->name, out);
02065                                    sdl_serialize_string((*tmp2)->ns, out);
02066                                    sdl_serialize_encoder_ref((*tmp2)->encode, tmp_encoders, out);
02067                                    sdl_serialize_type_ref((*tmp2)->element, tmp_types, out);
02068                                    zend_hash_move_forward((*tmp)->headerfaults);
02069                             }
02070                      }
02071                      zend_hash_move_forward(body->headers);
02072               }
02073        }
02074 }
02075 
02076 static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr sdl TSRMLS_DC)
02077 {
02078        smart_str buf = {0};
02079        smart_str *out = &buf;
02080        int i;
02081        int type_num = 1;
02082        int encoder_num = 1;
02083        int f;
02084        encodePtr enc;
02085        HashTable tmp_types;
02086        HashTable tmp_encoders;
02087        HashTable tmp_bindings;
02088        HashTable tmp_functions;
02089 
02090 #ifdef ZEND_WIN32
02091        f = open(fn,O_CREAT|O_WRONLY|O_EXCL|O_BINARY,S_IREAD|S_IWRITE);
02092 #else
02093        f = open(fn,O_CREAT|O_WRONLY|O_EXCL|O_BINARY,S_IREAD|S_IWRITE);
02094 #endif
02095        if (f < 0) {return;}
02096 
02097        zend_hash_init(&tmp_types, 0, NULL, NULL, 0);
02098        zend_hash_init(&tmp_encoders, 0, NULL, NULL, 0);
02099        zend_hash_init(&tmp_bindings, 0, NULL, NULL, 0);
02100        zend_hash_init(&tmp_functions, 0, NULL, NULL, 0);
02101 
02102        WSDL_CACHE_PUT_N("wsdl", 4, out);
02103        WSDL_CACHE_PUT_1(WSDL_CACHE_VERSION,out);
02104        WSDL_CACHE_PUT_1(0,out);
02105        WSDL_CACHE_PUT_N(&t, sizeof(t), out);
02106 
02107        sdl_serialize_string(uri, out);
02108        sdl_serialize_string(sdl->source, out);
02109        sdl_serialize_string(sdl->target_ns, out);
02110 
02111        if (sdl->groups) {
02112               i = zend_hash_num_elements(sdl->groups);
02113        } else {
02114               i = 0;
02115        }
02116        WSDL_CACHE_PUT_INT(i, out);
02117        if (i > 0) {
02118               sdlTypePtr *tmp;
02119 
02120               zend_hash_internal_pointer_reset(sdl->groups);
02121               while (zend_hash_get_current_data(sdl->groups, (void**)&tmp) == SUCCESS) {
02122                      zend_hash_add(&tmp_types, (char*)tmp, sizeof(*tmp), (void**)&type_num, sizeof(type_num), NULL);
02123                      ++type_num;
02124                      zend_hash_move_forward(sdl->groups);
02125               }
02126        }
02127 
02128        if (sdl->types) {
02129               i = zend_hash_num_elements(sdl->types);
02130        } else {
02131               i = 0;
02132        }
02133        WSDL_CACHE_PUT_INT(i, out);
02134        if (i > 0) {
02135               sdlTypePtr *tmp;
02136 
02137               zend_hash_internal_pointer_reset(sdl->types);
02138               while (zend_hash_get_current_data(sdl->types, (void**)&tmp) == SUCCESS) {
02139                      zend_hash_add(&tmp_types, (char*)tmp, sizeof(*tmp), (void**)&type_num, sizeof(type_num), NULL);
02140                      ++type_num;
02141                      zend_hash_move_forward(sdl->types);
02142               }
02143        }
02144 
02145        if (sdl->elements) {
02146               i = zend_hash_num_elements(sdl->elements);
02147        } else {
02148               i = 0;
02149        }
02150        WSDL_CACHE_PUT_INT(i, out);
02151        if (i > 0) {
02152               sdlTypePtr *tmp;
02153 
02154               zend_hash_internal_pointer_reset(sdl->elements);
02155               while (zend_hash_get_current_data(sdl->elements, (void**)&tmp) == SUCCESS) {
02156                      zend_hash_add(&tmp_types, (char*)tmp, sizeof(*tmp), (void**)&type_num, sizeof(type_num), NULL);
02157                      ++type_num;
02158                      zend_hash_move_forward(sdl->elements);
02159               }
02160        }
02161 
02162        if (sdl->encoders) {
02163               i = zend_hash_num_elements(sdl->encoders);
02164        } else {
02165               i = 0;
02166        }
02167        WSDL_CACHE_PUT_INT(i, out);
02168        if (i > 0) {
02169               encodePtr *tmp;
02170 
02171               zend_hash_internal_pointer_reset(sdl->encoders);
02172               while (zend_hash_get_current_data(sdl->encoders, (void**)&tmp) == SUCCESS) {
02173                      zend_hash_add(&tmp_encoders, (char*)tmp, sizeof(*tmp), (void**)&encoder_num, sizeof(encoder_num), NULL);
02174                      ++encoder_num;
02175                      zend_hash_move_forward(sdl->encoders);
02176               }
02177        }
02178        enc = defaultEncoding;
02179        while (enc->details.type != END_KNOWN_TYPES) {
02180               zend_hash_add(&tmp_encoders, (char*)&enc, sizeof(encodePtr), (void**)&encoder_num, sizeof(encoder_num), NULL);
02181               enc++;
02182               ++encoder_num;
02183        }
02184 
02185        if (sdl->groups) {
02186               sdlTypePtr *tmp;
02187               zend_hash_internal_pointer_reset(sdl->groups);
02188               while (zend_hash_get_current_data(sdl->groups, (void**)&tmp) == SUCCESS) {
02189                      sdl_serialize_key(sdl->groups, out);
02190                      sdl_serialize_type(*tmp, &tmp_encoders, &tmp_types, out);
02191                      zend_hash_move_forward(sdl->groups);
02192               }
02193        }
02194 
02195        if (sdl->types) {
02196               sdlTypePtr *tmp;
02197               zend_hash_internal_pointer_reset(sdl->types);
02198               while (zend_hash_get_current_data(sdl->types, (void**)&tmp) == SUCCESS) {
02199                      sdl_serialize_key(sdl->types, out);
02200                      sdl_serialize_type(*tmp, &tmp_encoders, &tmp_types, out);
02201                      zend_hash_move_forward(sdl->types);
02202               }
02203        }
02204 
02205        if (sdl->elements) {
02206               sdlTypePtr *tmp;
02207               zend_hash_internal_pointer_reset(sdl->elements);
02208               while (zend_hash_get_current_data(sdl->elements, (void**)&tmp) == SUCCESS) {
02209                      sdl_serialize_key(sdl->elements, out);
02210                      sdl_serialize_type(*tmp, &tmp_encoders, &tmp_types, out);
02211                      zend_hash_move_forward(sdl->elements);
02212               }
02213        }
02214 
02215        if (sdl->encoders) {
02216               encodePtr *tmp;
02217               zend_hash_internal_pointer_reset(sdl->encoders);
02218               while (zend_hash_get_current_data(sdl->encoders, (void**)&tmp) == SUCCESS) {
02219                      sdl_serialize_key(sdl->encoders, out);
02220                      sdl_serialize_encoder(*tmp, &tmp_types, out);
02221                      zend_hash_move_forward(sdl->encoders);
02222               }
02223        }
02224 
02225        /* serialize bindings */
02226        if (sdl->bindings) {
02227               i = zend_hash_num_elements(sdl->bindings);
02228        } else {
02229               i = 0;
02230        }
02231        WSDL_CACHE_PUT_INT(i, out);
02232        if (i > 0) {
02233               sdlBindingPtr *tmp;
02234               int binding_num = 1;
02235 
02236               zend_hash_internal_pointer_reset(sdl->bindings);
02237               while (zend_hash_get_current_data(sdl->bindings, (void**)&tmp) == SUCCESS) {
02238                      sdl_serialize_key(sdl->bindings, out);
02239                      sdl_serialize_string((*tmp)->name, out);
02240                      sdl_serialize_string((*tmp)->location, out);
02241                      WSDL_CACHE_PUT_1((*tmp)->bindingType,out);
02242                      if ((*tmp)->bindingType == BINDING_SOAP && (*tmp)->bindingAttributes != NULL) {
02243                             sdlSoapBindingPtr binding = (sdlSoapBindingPtr)(*tmp)->bindingAttributes;
02244                             WSDL_CACHE_PUT_1(binding->style, out);
02245                             WSDL_CACHE_PUT_1(binding->transport, out);
02246                      } else {
02247                             WSDL_CACHE_PUT_1(0,out);
02248                      }
02249 
02250                      zend_hash_add(&tmp_bindings, (char*)tmp, sizeof(*tmp), (void**)&binding_num, sizeof(binding_num), NULL);
02251                      binding_num++;
02252                      zend_hash_move_forward(sdl->bindings);
02253               }
02254        }
02255 
02256        /* serialize functions */
02257        i = zend_hash_num_elements(&sdl->functions);
02258        WSDL_CACHE_PUT_INT(i, out);
02259        if (i > 0) {
02260               sdlFunctionPtr *tmp;
02261               int *binding_num;
02262               int function_num = 1;
02263 
02264               zend_hash_internal_pointer_reset(&sdl->functions);
02265               while (zend_hash_get_current_data(&sdl->functions, (void**)&tmp) == SUCCESS) {
02266                      sdl_serialize_key(&sdl->functions, out);
02267                      sdl_serialize_string((*tmp)->functionName, out);
02268                      sdl_serialize_string((*tmp)->requestName, out);
02269                      sdl_serialize_string((*tmp)->responseName, out);
02270 
02271                      if ((*tmp)->binding == NULL ||
02272                          zend_hash_find(&tmp_bindings,(char*)&(*tmp)->binding,sizeof((*tmp)->binding), (void**)&binding_num) != SUCCESS) {
02273                      }
02274                      WSDL_CACHE_PUT_INT(*binding_num, out);
02275                      if (*binding_num >= 0) {
02276                             if ((*tmp)->binding->bindingType == BINDING_SOAP && (*tmp)->bindingAttributes != NULL) {
02277                                    sdlSoapBindingFunctionPtr binding = (sdlSoapBindingFunctionPtr)(*tmp)->bindingAttributes;
02278                                    WSDL_CACHE_PUT_1(binding->style, out);
02279                                    sdl_serialize_string(binding->soapAction, out);
02280                                    sdl_serialize_soap_body(&binding->input, &tmp_encoders, &tmp_types, out);
02281                                    sdl_serialize_soap_body(&binding->output, &tmp_encoders, &tmp_types, out);
02282                             } else {
02283                                    WSDL_CACHE_PUT_1(0,out);
02284                             }
02285                      }
02286                      sdl_serialize_parameters((*tmp)->requestParameters, &tmp_encoders, &tmp_types, out);
02287                      sdl_serialize_parameters((*tmp)->responseParameters, &tmp_encoders, &tmp_types, out);
02288 
02289                      if ((*tmp)->faults) {
02290                             sdlFaultPtr *fault;
02291 
02292                             WSDL_CACHE_PUT_INT(zend_hash_num_elements((*tmp)->faults), out);
02293 
02294                             zend_hash_internal_pointer_reset((*tmp)->faults);
02295                             while (zend_hash_get_current_data((*tmp)->faults, (void**)&fault) == SUCCESS) {
02296                                    sdl_serialize_key((*tmp)->faults, out);
02297                                    sdl_serialize_string((*fault)->name, out);
02298                                    sdl_serialize_parameters((*fault)->details, &tmp_encoders, &tmp_types, out);
02299                                    if ((*tmp)->binding->bindingType == BINDING_SOAP && (*fault)->bindingAttributes != NULL) {
02300                                           sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)(*fault)->bindingAttributes;
02301                                           WSDL_CACHE_PUT_1(binding->use, out);
02302                                           if (binding->use == SOAP_ENCODED) {
02303                                                  WSDL_CACHE_PUT_1(binding->encodingStyle, out);
02304                                           }
02305                                           sdl_serialize_string(binding->ns, out);
02306                                    } else {
02307                                           WSDL_CACHE_PUT_1(0, out);
02308                                    }
02309                                    zend_hash_move_forward((*tmp)->faults);
02310                             }
02311                      } else {
02312                             WSDL_CACHE_PUT_INT(0, out);
02313                      }
02314 
02315                      zend_hash_add(&tmp_functions, (char*)tmp, sizeof(*tmp), (void**)&function_num, sizeof(function_num), NULL);
02316                      function_num++;
02317                      zend_hash_move_forward(&sdl->functions);
02318               }
02319        }
02320 
02321        /* serialize requests */
02322        if (sdl->requests) {
02323               i = zend_hash_num_elements(sdl->requests);
02324        } else {
02325               i = 0;
02326        }
02327        WSDL_CACHE_PUT_INT(i, out);
02328        if (i > 0) {
02329               sdlFunctionPtr *tmp;
02330               int *function_num;
02331 
02332               zend_hash_internal_pointer_reset(sdl->requests);
02333               while (zend_hash_get_current_data(sdl->requests, (void**)&tmp) == SUCCESS) {
02334                      if (zend_hash_find(&tmp_functions, (char*)tmp, sizeof(*tmp), (void**)&function_num) != SUCCESS) {
02335                      }
02336                      WSDL_CACHE_PUT_INT(*function_num, out);
02337                      sdl_serialize_key(sdl->requests, out);
02338                      zend_hash_move_forward(sdl->requests);
02339               }
02340        }
02341 
02342        write(f, buf.c, buf.len);
02343        close(f);
02344        smart_str_free(&buf);
02345        zend_hash_destroy(&tmp_functions);
02346        zend_hash_destroy(&tmp_bindings);
02347        zend_hash_destroy(&tmp_encoders);
02348        zend_hash_destroy(&tmp_types);
02349 }
02350 
02351 
02352 static void make_persistent_restriction_int(void *data)
02353 {
02354        sdlRestrictionIntPtr *rest = (sdlRestrictionIntPtr *)data;
02355        sdlRestrictionIntPtr prest = NULL;
02356 
02357        prest = malloc(sizeof(sdlRestrictionInt));
02358        *prest = **rest;
02359        *rest = prest;
02360 }
02361 
02362 
02363 static void make_persistent_restriction_char(void *data)
02364 {
02365        sdlRestrictionCharPtr *rest = (sdlRestrictionCharPtr *)data;
02366        sdlRestrictionCharPtr prest = NULL;
02367 
02368        prest = malloc(sizeof(sdlRestrictionChar));
02369        memset(prest, 0, sizeof(sdlRestrictionChar));
02370        prest->value = strdup((*rest)->value);
02371        prest->fixed = (*rest)->fixed;
02372        *rest = prest;
02373 }
02374 
02375 
02376 static void make_persistent_sdl_type_ref(sdlTypePtr *type, HashTable *ptr_map, HashTable *bp_types)
02377 {
02378        sdlTypePtr *tmp;
02379 
02380        if (zend_hash_find(ptr_map, (char *)type, sizeof(sdlTypePtr), (void**)&tmp) == SUCCESS) {
02381               *type = *tmp;
02382        } else {
02383               zend_hash_next_index_insert(bp_types, (void*)&type, sizeof(sdlTypePtr*), NULL);
02384        }
02385 }
02386 
02387 
02388 static void make_persistent_sdl_encoder_ref(encodePtr *enc, HashTable *ptr_map, HashTable *bp_encoders)
02389 {
02390        encodePtr *tmp;
02391 
02392        /* do not process defaultEncoding's here */
02393        if ((*enc) >= defaultEncoding && (*enc) < defaultEncoding + numDefaultEncodings) {
02394               return;
02395        }
02396 
02397        if (zend_hash_find(ptr_map, (char *)enc, sizeof(encodePtr), (void**)&tmp) == SUCCESS) {
02398               *enc = *tmp;
02399        } else {
02400               zend_hash_next_index_insert(bp_encoders, (void*)&enc, sizeof(encodePtr*), NULL);
02401        }
02402 }
02403 
02404 
02405 static HashTable* make_persistent_sdl_function_headers(HashTable *headers, HashTable *ptr_map)
02406 {
02407        HashTable *pheaders;
02408        sdlSoapBindingFunctionHeaderPtr *tmp, pheader;
02409        encodePtr *penc;
02410        sdlTypePtr *ptype;
02411        ulong index;
02412        char *key;
02413        uint key_len;
02414 
02415        pheaders = malloc(sizeof(HashTable));
02416        zend_hash_init(pheaders, zend_hash_num_elements(headers), NULL, delete_header_persistent, 1);
02417 
02418        zend_hash_internal_pointer_reset(headers);
02419        while (zend_hash_get_current_data(headers, (void**)&tmp) == SUCCESS) {
02420               pheader = malloc(sizeof(sdlSoapBindingFunctionHeader));
02421               memset(pheader, 0, sizeof(sdlSoapBindingFunctionHeader));
02422               *pheader = **tmp;
02423 
02424               if (pheader->name) {
02425                      pheader->name = strdup(pheader->name);
02426               }
02427               if (pheader->ns) {
02428                      pheader->ns = strdup(pheader->ns);
02429               }
02430 
02431               if (pheader->encode->details.sdl_type) {
02432                      if (zend_hash_find(ptr_map, (char*)&pheader->encode, sizeof(encodePtr), (void**)&penc) == FAILURE) {
02433                             assert(0);
02434                      }
02435                      pheader->encode = *penc;
02436               }
02437               if (pheader->element) {
02438                      if (zend_hash_find(ptr_map, (char*)&pheader->element, sizeof(sdlTypePtr), (void**)&ptype) == FAILURE) {
02439                             assert(0);
02440                      }
02441                      pheader->element = *ptype;
02442               }
02443 
02444               if (pheader->headerfaults) {
02445                      pheader->headerfaults = make_persistent_sdl_function_headers(pheader->headerfaults, ptr_map);
02446               }
02447 
02448               if (zend_hash_get_current_key_ex(headers, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
02449                      zend_hash_add(pheaders, key, key_len, (void*)&pheader, sizeof(sdlSoapBindingFunctionHeaderPtr), NULL);
02450               } else {
02451                      zend_hash_next_index_insert(pheaders, (void*)&pheader, sizeof(sdlSoapBindingFunctionHeaderPtr), NULL);
02452               }
02453 
02454               zend_hash_move_forward(headers);
02455        }
02456 
02457        return pheaders;
02458 }
02459 
02460 
02461 static void make_persistent_sdl_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTable *ptr_map)
02462 {
02463        if (body->ns) {
02464               body->ns = strdup(body->ns);
02465        }
02466 
02467        if (body->headers) {
02468               body->headers = make_persistent_sdl_function_headers(body->headers, ptr_map);
02469        }
02470 }
02471 
02472 
02473 static HashTable* make_persistent_sdl_parameters(HashTable *params, HashTable *ptr_map)
02474 {
02475        HashTable *pparams;
02476        sdlParamPtr *tmp, pparam;
02477        sdlTypePtr *ptype;
02478        encodePtr *penc;
02479        ulong index;
02480        char *key;
02481        uint key_len;
02482 
02483        pparams = malloc(sizeof(HashTable));
02484        zend_hash_init(pparams, zend_hash_num_elements(params), NULL, delete_parameter_persistent, 1);
02485 
02486        zend_hash_internal_pointer_reset(params);
02487        while (zend_hash_get_current_data(params, (void**)&tmp) == SUCCESS) {
02488               pparam = malloc(sizeof(sdlParam));
02489               memset(pparam, 0, sizeof(sdlParam));
02490               *pparam = **tmp;
02491 
02492               if (pparam->paramName) {
02493                      pparam->paramName = strdup(pparam->paramName);
02494               }
02495 
02496               if (pparam->encode && pparam->encode->details.sdl_type) {
02497                      if (zend_hash_find(ptr_map, (char*)&pparam->encode, sizeof(encodePtr), (void**)&penc) == FAILURE) {
02498                             assert(0);
02499                      }
02500                      pparam->encode = *penc;
02501               }
02502               if (pparam->element) {
02503                      if (zend_hash_find(ptr_map, (char*)&pparam->element, sizeof(sdlTypePtr), (void**)&ptype) == FAILURE) {
02504                             assert(0);
02505                      }
02506                      pparam->element = *ptype;
02507               }
02508 
02509               if (zend_hash_get_current_key_ex(params, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
02510                      zend_hash_add(pparams, key, key_len, (void*)&pparam, sizeof(sdlParamPtr), NULL);
02511               } else {
02512                      zend_hash_next_index_insert(pparams, (void*)&pparam, sizeof(sdlParamPtr), NULL);
02513               }
02514 
02515               zend_hash_move_forward(params);
02516        }
02517 
02518 
02519        return pparams;
02520 }
02521 
02522 static HashTable* make_persistent_sdl_function_faults(sdlFunctionPtr func, HashTable *faults, HashTable *ptr_map)
02523 {
02524        HashTable *pfaults;
02525        sdlFaultPtr  *tmp, pfault;
02526        ulong index;
02527        char *key;
02528        uint key_len;
02529 
02530        pfaults = malloc(sizeof(HashTable));
02531        zend_hash_init(pfaults, zend_hash_num_elements(faults), NULL, delete_fault_persistent, 1);
02532 
02533        zend_hash_internal_pointer_reset(faults);
02534        while (zend_hash_get_current_data(faults, (void**)&tmp) == SUCCESS) {
02535               pfault = malloc(sizeof(sdlFault));
02536               memset(pfault, 0, sizeof(sdlFault));
02537               *pfault = **tmp;
02538 
02539               if (pfault->name) {
02540                      pfault->name = strdup(pfault->name);
02541               }
02542               if (pfault->details) {
02543                      pfault->details = make_persistent_sdl_parameters(pfault->details, ptr_map);
02544               }
02545 
02546               if (func->binding->bindingType == BINDING_SOAP && pfault->bindingAttributes) {
02547                      sdlSoapBindingFunctionFaultPtr soap_binding;
02548 
02549                      soap_binding = malloc(sizeof(sdlSoapBindingFunctionFault));
02550                      memset(soap_binding, 0, sizeof(sdlSoapBindingFunctionFault));
02551                      *soap_binding = *(sdlSoapBindingFunctionFaultPtr)pfault->bindingAttributes;
02552                      if (soap_binding->ns) {
02553                             soap_binding->ns = strdup(soap_binding->ns);
02554                      }
02555                      pfault->bindingAttributes = soap_binding;
02556               }
02557 
02558               if (zend_hash_get_current_key_ex(faults, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
02559                      zend_hash_add(pfaults, key, key_len, (void*)&pfault, sizeof(sdlParamPtr), NULL);
02560               } else {
02561                      zend_hash_next_index_insert(pfaults, (void*)&pfault, sizeof(sdlParamPtr), NULL);
02562               }
02563 
02564               zend_hash_move_forward(faults);
02565        }
02566 
02567 
02568        return pfaults;
02569 }
02570 
02571 
02572 static sdlAttributePtr make_persistent_sdl_attribute(sdlAttributePtr attr, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
02573 {
02574        sdlAttributePtr pattr;
02575        ulong index;
02576        char *key;
02577        uint key_len;
02578 
02579        pattr = malloc(sizeof(sdlAttribute));
02580        memset(pattr, 0, sizeof(sdlAttribute));
02581 
02582        *pattr = *attr;
02583 
02584        if (pattr->name) {
02585               pattr->name = strdup(pattr->name);
02586        }
02587        if (pattr->namens) {
02588               pattr->namens = strdup(pattr->namens);
02589        }
02590        if (pattr->ref) {
02591               pattr->ref = strdup(pattr->ref);
02592        }
02593        if (pattr->def) {
02594               pattr->def = strdup(pattr->def);
02595        }
02596        if (pattr->fixed) {
02597               pattr->fixed = strdup(pattr->fixed);
02598        }
02599 
02600        /* we do not want to process defaultEncoding's here */
02601        if (pattr->encode) {
02602               make_persistent_sdl_encoder_ref(&pattr->encode, ptr_map, bp_encoders);
02603        }
02604 
02605        if (pattr->extraAttributes) {
02606               sdlExtraAttributePtr *tmp, pextra;
02607 
02608               pattr->extraAttributes = malloc(sizeof(HashTable));
02609               zend_hash_init(pattr->extraAttributes, zend_hash_num_elements(attr->extraAttributes), NULL, delete_extra_attribute_persistent, 1);
02610 
02611               zend_hash_internal_pointer_reset(pattr->extraAttributes);
02612               while (zend_hash_get_current_data(attr->extraAttributes, (void**)&tmp) == SUCCESS) {
02613                      pextra = malloc(sizeof(sdlExtraAttribute));
02614                      memset(pextra, 0, sizeof(sdlExtraAttribute));
02615                      if ((*tmp)->ns) {
02616                             pextra->ns = strdup((*tmp)->ns);
02617                      }
02618                      if ((*tmp)->val) {
02619                             pextra->val = strdup((*tmp)->val);
02620                      }
02621 
02622                      if (zend_hash_get_current_key_ex(attr->extraAttributes, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
02623                             zend_hash_add(pattr->extraAttributes, key, key_len, (void*)&pextra, sizeof(sdlExtraAttributePtr), NULL);
02624                      }
02625 
02626                      zend_hash_move_forward(attr->extraAttributes);
02627               }
02628        }
02629 
02630        return pattr;
02631 }
02632 
02633 
02634 static sdlContentModelPtr make_persistent_sdl_model(sdlContentModelPtr model, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
02635 {
02636        sdlContentModelPtr pmodel;
02637        sdlContentModelPtr *tmp, pcontent;
02638 
02639        pmodel = malloc(sizeof(sdlContentModel));
02640        memset(pmodel, 0, sizeof(sdlContentModel));
02641        *pmodel = *model;
02642 
02643        switch (pmodel->kind) {
02644               case XSD_CONTENT_ELEMENT:
02645                      if (pmodel->u.element) {
02646                             make_persistent_sdl_type_ref(&pmodel->u.element, ptr_map, bp_types);
02647                      }
02648                      break;
02649 
02650               case XSD_CONTENT_SEQUENCE:
02651               case XSD_CONTENT_ALL:
02652               case XSD_CONTENT_CHOICE:
02653                      pmodel->u.content = malloc(sizeof(HashTable));
02654                      zend_hash_init(pmodel->u.content, zend_hash_num_elements(model->u.content), NULL, delete_model_persistent, 1);
02655 
02656                      zend_hash_internal_pointer_reset(model->u.content);
02657                      while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
02658                             pcontent = make_persistent_sdl_model(*tmp, ptr_map, bp_types, bp_encoders);
02659                             zend_hash_next_index_insert(pmodel->u.content, (void*)&pcontent, sizeof(sdlContentModelPtr), NULL);
02660                             zend_hash_move_forward(model->u.content);
02661                      }
02662                      break;
02663 
02664               case XSD_CONTENT_GROUP_REF:
02665                      if (pmodel->u.group_ref) {
02666                             pmodel->u.group_ref = strdup(pmodel->u.group_ref);
02667                      }
02668                      break;
02669 
02670               case XSD_CONTENT_GROUP:
02671                      if (pmodel->u.group) {
02672                             make_persistent_sdl_type_ref(&pmodel->u.group, ptr_map, bp_types);
02673                      }
02674                      break;
02675 
02676               default:
02677                      break;
02678        }
02679 
02680        return pmodel;
02681 }
02682 
02683 
02684 static sdlTypePtr make_persistent_sdl_type(sdlTypePtr type, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
02685 {
02686        ulong index;
02687        char *key;
02688        uint key_len;
02689        sdlTypePtr ptype = NULL;
02690 
02691        ptype = malloc(sizeof(sdlType));
02692        memset(ptype, 0, sizeof(sdlType));
02693 
02694        *ptype = *type;
02695 
02696        if (ptype->name) {
02697               ptype->name = strdup(ptype->name);
02698        }
02699        if (ptype->namens) {
02700               ptype->namens = strdup(ptype->namens);
02701        }
02702        if (ptype->def) {
02703               ptype->def = strdup(ptype->def);
02704        }
02705        if (ptype->fixed) {
02706               ptype->fixed = strdup(ptype->fixed);
02707        }
02708        if (ptype->ref) {
02709               ptype->ref = strdup(ptype->ref);
02710        }
02711 
02712        /* we do not want to process defaultEncoding's here */
02713        if (ptype->encode) {
02714               make_persistent_sdl_encoder_ref(&ptype->encode, ptr_map, bp_encoders);
02715        }
02716 
02717        if (ptype->restrictions) {
02718               ptype->restrictions = malloc(sizeof(sdlRestrictions));
02719               memset(ptype->restrictions, 0, sizeof(sdlRestrictions));
02720               *ptype->restrictions = *type->restrictions;
02721 
02722               if (ptype->restrictions->minExclusive) {
02723                      make_persistent_restriction_int(&ptype->restrictions->minExclusive);
02724               }
02725               if (ptype->restrictions->maxExclusive) {
02726                      make_persistent_restriction_int(&ptype->restrictions->maxExclusive);
02727               }
02728               if (ptype->restrictions->minInclusive) {
02729                      make_persistent_restriction_int(&ptype->restrictions->minInclusive);
02730               }
02731               if (ptype->restrictions->maxInclusive) {
02732                      make_persistent_restriction_int(&ptype->restrictions->maxInclusive);
02733               }
02734               if (ptype->restrictions->totalDigits) {
02735                      make_persistent_restriction_int(&ptype->restrictions->totalDigits);
02736               }
02737               if (ptype->restrictions->fractionDigits) {
02738                      make_persistent_restriction_int(&ptype->restrictions->fractionDigits);
02739               }
02740               if (ptype->restrictions->length) {
02741                      make_persistent_restriction_int(&ptype->restrictions->length);
02742               }
02743               if (ptype->restrictions->minLength) {
02744                      make_persistent_restriction_int(&ptype->restrictions->minLength);
02745               }
02746               if (ptype->restrictions->maxLength) {
02747                      make_persistent_restriction_int(&ptype->restrictions->maxLength);
02748               }
02749               if (ptype->restrictions->whiteSpace) {
02750                      make_persistent_restriction_char(&ptype->restrictions->whiteSpace);
02751               }
02752               if (ptype->restrictions->pattern) {
02753                      make_persistent_restriction_char(&ptype->restrictions->pattern);
02754               }
02755 
02756               if (type->restrictions->enumeration) {
02757                      sdlRestrictionCharPtr tmp;
02758 
02759                      ptype->restrictions->enumeration = malloc(sizeof(HashTable));
02760                      zend_hash_init(ptype->restrictions->enumeration, zend_hash_num_elements(type->restrictions->enumeration), NULL, delete_restriction_var_char_persistent, 1);
02761                      zend_hash_copy(ptype->restrictions->enumeration, type->restrictions->enumeration, make_persistent_restriction_char, (void*)&tmp, sizeof(sdlRestrictionCharPtr));
02762               }
02763        }
02764 
02765        if (ptype->elements) {
02766               sdlTypePtr *tmp, pelem;
02767 
02768               ptype->elements = malloc(sizeof(HashTable));
02769               zend_hash_init(ptype->elements, zend_hash_num_elements(type->elements), NULL, delete_type_persistent, 1);
02770 
02771               zend_hash_internal_pointer_reset(type->elements);
02772               while (zend_hash_get_current_data(type->elements, (void **)&tmp) == SUCCESS) {
02773                      pelem = make_persistent_sdl_type(*tmp, ptr_map, bp_types, bp_encoders);
02774                      if (zend_hash_get_current_key_ex(type->elements, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
02775                             zend_hash_add(ptype->elements, key, key_len, (void*)&pelem, sizeof(sdlTypePtr), NULL);
02776                      } else {
02777                             zend_hash_next_index_insert(ptype->elements, (void*)&pelem, sizeof(sdlTypePtr), NULL);
02778                      }
02779                      zend_hash_add(ptr_map, (char*)tmp, sizeof(*tmp), (void*)&pelem, sizeof(sdlTypePtr), NULL);
02780                      zend_hash_move_forward(type->elements);
02781               }
02782        }
02783 
02784        if (ptype->attributes) {
02785               sdlAttributePtr *tmp, pattr;
02786 
02787               ptype->attributes = malloc(sizeof(HashTable));
02788               zend_hash_init(ptype->attributes, zend_hash_num_elements(type->attributes), NULL, delete_attribute_persistent, 1);
02789 
02790               zend_hash_internal_pointer_reset(type->attributes);
02791               while (zend_hash_get_current_data(type->attributes, (void **)&tmp) == SUCCESS) {
02792                      pattr = make_persistent_sdl_attribute(*tmp, ptr_map, bp_types, bp_encoders);
02793                      if (zend_hash_get_current_key_ex(type->attributes, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
02794                             zend_hash_add(ptype->attributes, key, key_len, (void*)&pattr, sizeof(sdlAttributePtr), NULL);
02795                      } else {
02796                             zend_hash_next_index_insert(ptype->attributes, (void*)&pattr, sizeof(sdlAttributePtr), NULL);
02797                      }
02798                      zend_hash_move_forward(type->attributes);
02799               }
02800        }
02801 
02802        if (type->model) {
02803               ptype->model = make_persistent_sdl_model(ptype->model, ptr_map, bp_types, bp_encoders);
02804        }
02805 
02806        return ptype;
02807 }
02808 
02809 static encodePtr make_persistent_sdl_encoder(encodePtr enc, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
02810 {
02811        encodePtr penc = NULL;
02812 
02813        penc = malloc(sizeof(encode));
02814        memset(penc, 0, sizeof(encode));
02815 
02816        *penc = *enc;
02817 
02818        if (penc->details.type_str) {
02819               penc->details.type_str = strdup(penc->details.type_str);
02820        }
02821        if (penc->details.ns) {
02822               penc->details.ns = strdup(penc->details.ns);
02823        }
02824 
02825        if (penc->details.sdl_type) {
02826               make_persistent_sdl_type_ref(&penc->details.sdl_type, ptr_map, bp_types);
02827        }
02828 
02829        return penc;
02830 }
02831 
02832 static sdlBindingPtr make_persistent_sdl_binding(sdlBindingPtr bind, HashTable *ptr_map)
02833 {
02834        sdlBindingPtr pbind = NULL;
02835 
02836        pbind = malloc(sizeof(sdlBinding));
02837        memset(pbind, 0, sizeof(sdlBinding));
02838 
02839        *pbind = *bind;
02840 
02841        if (pbind->name) {
02842               pbind->name = strdup(pbind->name);
02843        }
02844        if (pbind->location) {
02845               pbind->location = strdup(pbind->location);
02846        }
02847 
02848        if (pbind->bindingType == BINDING_SOAP && pbind->bindingAttributes) {
02849               sdlSoapBindingPtr soap_binding;
02850           
02851               soap_binding = malloc(sizeof(sdlSoapBinding));
02852               memset(soap_binding, 0, sizeof(sdlSoapBinding));
02853               *soap_binding = *(sdlSoapBindingPtr)pbind->bindingAttributes;
02854               pbind->bindingAttributes = soap_binding;
02855        }
02856 
02857        return pbind;
02858 }
02859 
02860 static sdlFunctionPtr make_persistent_sdl_function(sdlFunctionPtr func, HashTable *ptr_map)
02861 {
02862        sdlFunctionPtr pfunc = NULL;
02863 
02864        pfunc = malloc(sizeof(sdlFunction));
02865        memset(pfunc, 0, sizeof(sdlFunction));
02866 
02867        *pfunc = *func;
02868 
02869        if (pfunc->functionName) {
02870               pfunc->functionName = strdup(pfunc->functionName);
02871        }
02872        if (pfunc->requestName) {
02873               pfunc->requestName = strdup(pfunc->requestName);
02874        }
02875        if (pfunc->responseName) {
02876               pfunc->responseName = strdup(pfunc->responseName);
02877        }
02878 
02879        if (pfunc->binding) {
02880               sdlBindingPtr *tmp;
02881 
02882               if (zend_hash_find(ptr_map, (char*)&pfunc->binding, sizeof(pfunc->binding), (void**)&tmp) == FAILURE) {
02883                      assert(0);
02884               }
02885               pfunc->binding = *tmp;
02886               
02887               if (pfunc->binding->bindingType == BINDING_SOAP && pfunc->bindingAttributes) {
02888                      sdlSoapBindingFunctionPtr soap_binding;
02889 
02890                      soap_binding = malloc(sizeof(sdlSoapBindingFunction));
02891                      memset(soap_binding, 0, sizeof(sdlSoapBindingFunction));
02892                      *soap_binding = *(sdlSoapBindingFunctionPtr)pfunc->bindingAttributes;
02893                      if (soap_binding->soapAction) {
02894                             soap_binding->soapAction = strdup(soap_binding->soapAction);
02895                      }
02896                      make_persistent_sdl_soap_body(&soap_binding->input, ptr_map);
02897                      make_persistent_sdl_soap_body(&soap_binding->output, ptr_map);
02898                      pfunc->bindingAttributes = soap_binding;
02899               }
02900 
02901               if (pfunc->requestParameters) {
02902                      pfunc->requestParameters = make_persistent_sdl_parameters(pfunc->requestParameters, ptr_map);
02903               }
02904               if (pfunc->responseParameters) {
02905                      pfunc->responseParameters = make_persistent_sdl_parameters(pfunc->responseParameters, ptr_map);
02906               }
02907               if (pfunc->faults) {
02908                      pfunc->faults = make_persistent_sdl_function_faults(pfunc, pfunc->faults, ptr_map);
02909               }
02910        }
02911 
02912        return pfunc;
02913 }
02914 
02915 static sdlPtr make_persistent_sdl(sdlPtr sdl TSRMLS_DC)
02916 {
02917        sdlPtr psdl = NULL;
02918        HashTable ptr_map;
02919        HashTable bp_types, bp_encoders;
02920        ulong index;
02921        char *key;
02922        uint key_len;
02923 
02924        zend_hash_init(&bp_types, 0, NULL, NULL, 0);
02925        zend_hash_init(&bp_encoders, 0, NULL, NULL, 0);
02926        zend_hash_init(&ptr_map, 0, NULL, NULL, 0);
02927 
02928        psdl = malloc(sizeof(*sdl));
02929        memset(psdl, 0, sizeof(*sdl));
02930 
02931        if (sdl->source) {
02932               psdl->source = strdup(sdl->source);
02933        }
02934        if (sdl->target_ns) {
02935               psdl->target_ns = strdup(sdl->target_ns);
02936        }
02937 
02938        if (sdl->groups) {
02939               sdlTypePtr *tmp;
02940               sdlTypePtr ptype;
02941 
02942               psdl->groups = malloc(sizeof(HashTable));
02943               zend_hash_init(psdl->groups, zend_hash_num_elements(sdl->groups), NULL, delete_type_persistent, 1);
02944 
02945               zend_hash_internal_pointer_reset(sdl->groups);
02946               while (zend_hash_get_current_data(sdl->groups, (void **)&tmp) == SUCCESS) {
02947                      ptype = make_persistent_sdl_type(*tmp, &ptr_map, &bp_types, &bp_encoders);
02948                      if (zend_hash_get_current_key_ex(sdl->groups, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
02949                             zend_hash_add(psdl->groups, key, key_len, (void*)&ptype, sizeof(sdlTypePtr), NULL);
02950                      } else {
02951                             zend_hash_next_index_insert(psdl->groups, (void*)&ptype, sizeof(sdlTypePtr), NULL);
02952                      }
02953                      zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&ptype, sizeof(sdlTypePtr), NULL);
02954                      zend_hash_move_forward(sdl->groups);
02955               }
02956        }
02957 
02958        if (sdl->types) {
02959               sdlTypePtr *tmp;
02960               sdlTypePtr ptype;
02961 
02962               psdl->types = malloc(sizeof(HashTable));
02963               zend_hash_init(psdl->types, zend_hash_num_elements(sdl->types), NULL, delete_type_persistent, 1);
02964 
02965               zend_hash_internal_pointer_reset(sdl->types);
02966               while (zend_hash_get_current_data(sdl->types, (void **)&tmp) == SUCCESS) {
02967                      ptype = make_persistent_sdl_type(*tmp, &ptr_map, &bp_types, &bp_encoders);
02968                      if (zend_hash_get_current_key_ex(sdl->types, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
02969                             zend_hash_add(psdl->types, key, key_len, (void*)&ptype, sizeof(sdlTypePtr), NULL);
02970                      } else {
02971                             zend_hash_next_index_insert(psdl->types, (void*)&ptype, sizeof(sdlTypePtr), NULL);
02972                      }
02973                      zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&ptype, sizeof(sdlTypePtr), NULL);
02974                      zend_hash_move_forward(sdl->types);
02975               }
02976        }
02977 
02978        if (sdl->elements) {
02979               sdlTypePtr *tmp;
02980               sdlTypePtr ptype;
02981 
02982               psdl->elements = malloc(sizeof(HashTable));
02983               zend_hash_init(psdl->elements, zend_hash_num_elements(sdl->elements), NULL, delete_type_persistent, 1);
02984 
02985               zend_hash_internal_pointer_reset(sdl->elements);
02986               while (zend_hash_get_current_data(sdl->elements, (void **)&tmp) == SUCCESS) {
02987                      ptype = make_persistent_sdl_type(*tmp, &ptr_map, &bp_types, &bp_encoders);
02988                      if (zend_hash_get_current_key_ex(sdl->elements, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
02989                             zend_hash_add(psdl->elements, key, key_len, (void*)&ptype, sizeof(sdlTypePtr), NULL);
02990                      } else {
02991                             zend_hash_next_index_insert(psdl->elements, (void*)&ptype, sizeof(sdlTypePtr), NULL);
02992                      }
02993                      zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&ptype, sizeof(sdlTypePtr), NULL);
02994                      zend_hash_move_forward(sdl->elements);
02995               }
02996        }
02997 
02998        if (sdl->encoders) {
02999               encodePtr *tmp;
03000               encodePtr penc;
03001 
03002               psdl->encoders = malloc(sizeof(HashTable));
03003               zend_hash_init(psdl->encoders, zend_hash_num_elements(sdl->encoders), NULL, delete_encoder_persistent, 1);
03004 
03005               zend_hash_internal_pointer_reset(sdl->encoders);
03006               while (zend_hash_get_current_data(sdl->encoders, (void **)&tmp) == SUCCESS) {
03007                      penc = make_persistent_sdl_encoder(*tmp, &ptr_map, &bp_types, &bp_encoders);
03008                      if (zend_hash_get_current_key_ex(sdl->encoders, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
03009                             zend_hash_add(psdl->encoders, key, key_len, (void*)&penc, sizeof(encodePtr), NULL);
03010                      } else {
03011                             zend_hash_next_index_insert(psdl->encoders, (void*)&penc, sizeof(encodePtr), NULL);
03012                      }
03013                      zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&penc, sizeof(encodePtr), NULL);
03014                      zend_hash_move_forward(sdl->encoders);
03015               }
03016        }
03017 
03018        /* do backpatching here */
03019        if (zend_hash_num_elements(&bp_types)) {
03020               sdlTypePtr **tmp, *ptype = NULL;
03021 
03022               zend_hash_internal_pointer_reset(&bp_types);
03023               while (zend_hash_get_current_data(&bp_types, (void**)&tmp) == SUCCESS) {
03024                      if (zend_hash_find(&ptr_map, (char*)(*tmp), sizeof(**tmp), (void**)&ptype) == FAILURE) {
03025                             assert(0);
03026                      }
03027                      **tmp = *ptype;
03028                      zend_hash_move_forward(&bp_types);
03029               }
03030        }
03031        if (zend_hash_num_elements(&bp_encoders)) {
03032               encodePtr **tmp, *penc = NULL;
03033 
03034               zend_hash_internal_pointer_reset(&bp_encoders);
03035               while (zend_hash_get_current_data(&bp_encoders, (void**)&tmp) == SUCCESS) {
03036                      if (zend_hash_find(&ptr_map, (char*)(*tmp), sizeof(**tmp), (void**)&penc) == FAILURE) {
03037                             assert(0);
03038                      }
03039                      **tmp = *penc;
03040                      zend_hash_move_forward(&bp_encoders);
03041               }
03042        }
03043 
03044 
03045        if (sdl->bindings) {
03046               sdlBindingPtr *tmp;
03047               sdlBindingPtr pbind;
03048 
03049               psdl->bindings = malloc(sizeof(HashTable));
03050               zend_hash_init(psdl->bindings, zend_hash_num_elements(sdl->bindings), NULL, delete_binding_persistent, 1);
03051 
03052               zend_hash_internal_pointer_reset(sdl->bindings);
03053               while (zend_hash_get_current_data(sdl->bindings, (void **)&tmp) == SUCCESS) {
03054                      pbind = make_persistent_sdl_binding(*tmp, &ptr_map);
03055                      if (zend_hash_get_current_key_ex(sdl->bindings, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
03056                             zend_hash_add(psdl->bindings, key, key_len, (void*)&pbind, sizeof(sdlBindingPtr), NULL);
03057                      } else {
03058                             zend_hash_next_index_insert(psdl->bindings, (void*)&pbind, sizeof(sdlBindingPtr), NULL);
03059                      }
03060                      zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&pbind, sizeof(sdlBindingPtr), NULL);
03061                      zend_hash_move_forward(sdl->bindings);
03062               }
03063        }
03064 
03065        zend_hash_init(&psdl->functions, zend_hash_num_elements(&sdl->functions), NULL, delete_function_persistent, 1);
03066        if (zend_hash_num_elements(&sdl->functions)) {
03067               sdlFunctionPtr *tmp;
03068               sdlFunctionPtr pfunc;
03069 
03070               zend_hash_internal_pointer_reset(&sdl->functions);
03071               while (zend_hash_get_current_data(&sdl->functions, (void **)&tmp) == SUCCESS) {
03072                      pfunc = make_persistent_sdl_function(*tmp, &ptr_map);
03073                      if (zend_hash_get_current_key_ex(&sdl->functions, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
03074                             zend_hash_add(&psdl->functions, key, key_len, (void*)&pfunc, sizeof(sdlFunctionPtr), NULL);
03075                      } else {
03076                             zend_hash_next_index_insert(&psdl->functions, (void*)&pfunc, sizeof(sdlFunctionPtr), NULL);
03077                      }
03078                      zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&pfunc, sizeof(sdlFunctionPtr), NULL);
03079                      zend_hash_move_forward(&sdl->functions);
03080               }
03081        }
03082 
03083        if (sdl->requests) {
03084               sdlFunctionPtr *tmp;
03085               sdlFunctionPtr *preq;
03086 
03087               psdl->requests = malloc(sizeof(HashTable));
03088               zend_hash_init(psdl->requests, zend_hash_num_elements(sdl->requests), NULL, NULL, 1);
03089 
03090               zend_hash_internal_pointer_reset(sdl->requests);
03091               while (zend_hash_get_current_data(sdl->requests, (void **)&tmp) == SUCCESS) {
03092                      if (zend_hash_find(&ptr_map, (char*)tmp, sizeof(*tmp), (void**)&preq) == FAILURE) {
03093                             assert(0);
03094                      }
03095                      *tmp = *preq;
03096                      if (zend_hash_get_current_key_ex(sdl->requests, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
03097                             zend_hash_add(psdl->requests, key, key_len, (void*)&preq, sizeof(sdlFunctionPtr), NULL);
03098                      }
03099                      zend_hash_move_forward(sdl->requests);
03100               }
03101        }
03102 
03103        zend_hash_destroy(&ptr_map);
03104        zend_hash_destroy(&bp_encoders);
03105        zend_hash_destroy(&bp_types);
03106 
03107        return psdl;
03108 }
03109 
03110 typedef struct _sdl_cache_bucket {
03111        sdlPtr sdl;
03112        time_t time;
03113 } sdl_cache_bucket;
03114 
03115 static void delete_psdl(void *data)
03116 {
03117        sdl_cache_bucket *p = (sdl_cache_bucket*)data;
03118        sdlPtr tmp = p->sdl;
03119 
03120        zend_hash_destroy(&tmp->functions);
03121        if (tmp->source) {
03122               free(tmp->source);
03123        }
03124        if (tmp->target_ns) {
03125               free(tmp->target_ns);
03126        }
03127        if (tmp->elements) {
03128               zend_hash_destroy(tmp->elements);
03129               free(tmp->elements);
03130        }
03131        if (tmp->encoders) {
03132               zend_hash_destroy(tmp->encoders);
03133               free(tmp->encoders);
03134        }
03135        if (tmp->types) {
03136               zend_hash_destroy(tmp->types);
03137               free(tmp->types);
03138        }
03139        if (tmp->groups) {
03140               zend_hash_destroy(tmp->groups);
03141               free(tmp->groups);
03142        }
03143        if (tmp->bindings) {
03144               zend_hash_destroy(tmp->bindings);
03145               free(tmp->bindings);
03146        }
03147        if (tmp->requests) {
03148               zend_hash_destroy(tmp->requests);
03149               free(tmp->requests);
03150        }
03151        free(tmp);
03152 }
03153 
03154 sdlPtr get_sdl(zval *this_ptr, char *uri, long cache_wsdl TSRMLS_DC)
03155 {
03156        char  fn[MAXPATHLEN];
03157        sdlPtr sdl = NULL;
03158        char* old_error_code = SOAP_GLOBAL(error_code);
03159        int uri_len = 0;
03160        php_stream_context *context=NULL;
03161        zval **tmp, **proxy_host, **proxy_port, *orig_context = NULL, *new_context = NULL;
03162        smart_str headers = {0};
03163        char* key = NULL;
03164        time_t t = time(0);
03165 
03166        if (strchr(uri,':') != NULL || IS_ABSOLUTE_PATH(uri, uri_len)) {
03167               uri_len = strlen(uri);
03168        } else if (VCWD_REALPATH(uri, fn) == NULL) {
03169               cache_wsdl = WSDL_CACHE_NONE;
03170        } else {
03171               uri = fn;
03172               uri_len = strlen(uri);
03173        }
03174 
03175        if ((cache_wsdl & WSDL_CACHE_MEMORY) && SOAP_GLOBAL(mem_cache)) {
03176               sdl_cache_bucket *p;
03177 
03178               if (SUCCESS == zend_hash_find(SOAP_GLOBAL(mem_cache), uri, uri_len+1, (void*)&p)) {
03179                      if (p->time < t - SOAP_GLOBAL(cache_ttl)) {
03180                             /* in-memory cache entry is expired */
03181                             zend_hash_del(&EG(persistent_list), uri, uri_len+1);
03182                      } else {
03183                             return p->sdl;
03184                      }
03185               }
03186        }
03187 
03188        if ((cache_wsdl & WSDL_CACHE_DISK) && (uri_len < MAXPATHLEN)) {
03189               time_t t = time(0);
03190               char md5str[33];
03191               PHP_MD5_CTX context;
03192               unsigned char digest[16];
03193               int len = strlen(SOAP_GLOBAL(cache_dir));
03194               time_t cached;
03195               char *user = php_get_current_user();
03196               int user_len = user ? strlen(user) + 1 : 0;
03197 
03198               md5str[0] = '\0';
03199               PHP_MD5Init(&context);
03200               PHP_MD5Update(&context, (unsigned char*)uri, uri_len);
03201               PHP_MD5Final(digest, &context);
03202               make_digest(md5str, digest);
03203               key = emalloc(len+sizeof("/wsdl-")-1+user_len+sizeof(md5str));
03204               memcpy(key,SOAP_GLOBAL(cache_dir),len);
03205               memcpy(key+len,"/wsdl-",sizeof("/wsdl-")-1);
03206               len += sizeof("/wsdl-")-1;
03207               if (user_len) {
03208                      memcpy(key+len, user, user_len-1);
03209                      len += user_len-1;
03210                      key[len++] = '-';
03211               }
03212               memcpy(key+len,md5str,sizeof(md5str));
03213 
03214               if ((sdl = get_sdl_from_cache(key, uri, t-SOAP_GLOBAL(cache_ttl), &cached TSRMLS_CC)) != NULL) {
03215                      t = cached;
03216                      efree(key);
03217                      goto cache_in_memory;
03218               }
03219        }
03220 
03221        if (SUCCESS == zend_hash_find(Z_OBJPROP_P(this_ptr),
03222                      "_stream_context", sizeof("_stream_context"), (void**)&tmp)) {
03223               context = php_stream_context_from_zval(*tmp, 0);
03224        } else {
03225               context = php_stream_context_alloc();
03226        }
03227 
03228        if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_host", sizeof("_proxy_host"), (void **) &proxy_host) == SUCCESS &&
03229            Z_TYPE_PP(proxy_host) == IS_STRING &&
03230            zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_port", sizeof("_proxy_port"), (void **) &proxy_port) == SUCCESS &&
03231            Z_TYPE_PP(proxy_port) == IS_LONG) {
03232               zval str_port, *str_proxy;
03233               smart_str proxy = {0};
03234               str_port = **proxy_port;
03235               zval_copy_ctor(&str_port);
03236               convert_to_string(&str_port);
03237               smart_str_appends(&proxy,"tcp://");
03238               smart_str_appends(&proxy,Z_STRVAL_PP(proxy_host));
03239               smart_str_appends(&proxy,":");
03240               smart_str_appends(&proxy,Z_STRVAL(str_port));
03241               smart_str_0(&proxy);
03242               zval_dtor(&str_port);
03243               MAKE_STD_ZVAL(str_proxy);
03244               ZVAL_STRING(str_proxy, proxy.c, 1);
03245               smart_str_free(&proxy);
03246               
03247               if (!context) {
03248                      context = php_stream_context_alloc();
03249               }
03250               php_stream_context_set_option(context, "http", "proxy", str_proxy);
03251               zval_ptr_dtor(&str_proxy);
03252 
03253               if (uri_len < sizeof("https://")-1 ||
03254                   strncasecmp(uri, "https://", sizeof("https://")-1) != 0) {
03255                      MAKE_STD_ZVAL(str_proxy);
03256                      ZVAL_BOOL(str_proxy, 1);
03257                      php_stream_context_set_option(context, "http", "request_fulluri", str_proxy);
03258                      zval_ptr_dtor(&str_proxy);
03259               }
03260 
03261               proxy_authentication(this_ptr, &headers TSRMLS_CC);
03262        }
03263 
03264        basic_authentication(this_ptr, &headers TSRMLS_CC);
03265 
03266        /* Use HTTP/1.1 with "Connection: close" by default */
03267        if (php_stream_context_get_option(context, "http", "protocol_version", &tmp) == FAILURE) {
03268        zval *http_version;
03269               MAKE_STD_ZVAL(http_version);
03270               ZVAL_DOUBLE(http_version, 1.1);
03271               php_stream_context_set_option(context, "http", "protocol_version", http_version);
03272               zval_ptr_dtor(&http_version);
03273               smart_str_appendl(&headers, "Connection: close", sizeof("Connection: close")-1);
03274        }
03275 
03276        if (headers.len > 0) {
03277               zval *str_headers;
03278 
03279               if (!context) {
03280                      context = php_stream_context_alloc();
03281               }
03282 
03283               smart_str_0(&headers);
03284               MAKE_STD_ZVAL(str_headers);
03285               ZVAL_STRING(str_headers, headers.c, 1);
03286               php_stream_context_set_option(context, "http", "header", str_headers);
03287               smart_str_free(&headers);
03288               zval_ptr_dtor(&str_headers);
03289        }
03290 
03291        if (context) {
03292               MAKE_STD_ZVAL(new_context);
03293               php_stream_context_to_zval(context, new_context);
03294               orig_context = php_libxml_switch_context(new_context TSRMLS_CC);
03295        }
03296 
03297        SOAP_GLOBAL(error_code) = "WSDL";
03298 
03299        sdl = load_wsdl(this_ptr, uri TSRMLS_CC);
03300        if (sdl) {
03301               sdl->is_persistent = 0;
03302        }
03303 
03304        SOAP_GLOBAL(error_code) = old_error_code;
03305 
03306        if (context) {
03307               php_libxml_switch_context(orig_context TSRMLS_CC);
03308               zval_ptr_dtor(&new_context);
03309        }
03310 
03311        if ((cache_wsdl & WSDL_CACHE_DISK) && key) {
03312               if (sdl) {
03313                      add_sdl_to_cache(key, uri, t, sdl TSRMLS_CC);
03314               }
03315               efree(key);
03316        }
03317 
03318 cache_in_memory:
03319        if (cache_wsdl & WSDL_CACHE_MEMORY) {
03320               if (sdl) {
03321                      sdlPtr psdl;
03322                      sdl_cache_bucket p;
03323 
03324                      if (SOAP_GLOBAL(mem_cache) == NULL) {
03325                             SOAP_GLOBAL(mem_cache) = malloc(sizeof(HashTable));
03326                             zend_hash_init(SOAP_GLOBAL(mem_cache), 0, NULL, delete_psdl, 1);
03327                      } else if (SOAP_GLOBAL(cache_limit) > 0 &&
03328                                 SOAP_GLOBAL(cache_limit) <= zend_hash_num_elements(SOAP_GLOBAL(mem_cache))) {
03329                             /* in-memory cache overflow */
03330                             sdl_cache_bucket *q;
03331                             HashPosition pos;
03332                             time_t latest = t;
03333                             char *key = NULL;
03334                             uint key_len;
03335                             ulong idx;
03336 
03337                             for (zend_hash_internal_pointer_reset_ex(SOAP_GLOBAL(mem_cache), &pos);
03338                                     zend_hash_get_current_data_ex(SOAP_GLOBAL(mem_cache), (void **) &q, &pos) == SUCCESS;
03339                                     zend_hash_move_forward_ex(SOAP_GLOBAL(mem_cache), &pos)) {
03340                                    if (q->time < latest) {
03341                                           latest = q->time;
03342                                           zend_hash_get_current_key_ex(SOAP_GLOBAL(mem_cache), &key, &key_len, &idx, 0, &pos);
03343                                    }
03344                             }
03345                             if (key) {
03346                                    zend_hash_del(SOAP_GLOBAL(mem_cache), key, key_len);
03347                             } else {
03348                                    return sdl;
03349                             }
03350                      }
03351 
03352                      psdl = make_persistent_sdl(sdl TSRMLS_CC);
03353                      psdl->is_persistent = 1;
03354                      p.time = t;
03355                      p.sdl = psdl;
03356 
03357                      if (SUCCESS == zend_hash_update(SOAP_GLOBAL(mem_cache), uri,
03358                                                                              uri_len+1, (void*)&p, sizeof(sdl_cache_bucket), NULL)) {
03359                             /* remove non-persitent sdl structure */
03360                             delete_sdl_impl(sdl);
03361                             /* and replace it with persistent one */
03362                             sdl = psdl;
03363                      } else {
03364                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to register persistent entry");
03365                             /* clean up persistent sdl */
03366                             delete_psdl(&p);
03367                             /* keep non-persistent sdl and return it */
03368                      }
03369               }
03370        }
03371 
03372        return sdl;
03373 }
03374 
03375 /* Deletes */
03376 void delete_sdl_impl(void *handle)
03377 {
03378        sdlPtr tmp = (sdlPtr)handle;
03379 
03380        zend_hash_destroy(&tmp->functions);
03381        if (tmp->source) {
03382               efree(tmp->source);
03383        }
03384        if (tmp->target_ns) {
03385               efree(tmp->target_ns);
03386        }
03387        if (tmp->elements) {
03388               zend_hash_destroy(tmp->elements);
03389               efree(tmp->elements);
03390        }
03391        if (tmp->encoders) {
03392               zend_hash_destroy(tmp->encoders);
03393               efree(tmp->encoders);
03394        }
03395        if (tmp->types) {
03396               zend_hash_destroy(tmp->types);
03397               efree(tmp->types);
03398        }
03399        if (tmp->groups) {
03400               zend_hash_destroy(tmp->groups);
03401               efree(tmp->groups);
03402        }
03403        if (tmp->bindings) {
03404               zend_hash_destroy(tmp->bindings);
03405               efree(tmp->bindings);
03406        }
03407        if (tmp->requests) {
03408               zend_hash_destroy(tmp->requests);
03409               efree(tmp->requests);
03410        }
03411        efree(tmp);
03412 }
03413 
03414 void delete_sdl(void *handle)
03415 {
03416        sdlPtr tmp = (sdlPtr)handle;
03417 
03418        if (!tmp->is_persistent) {
03419               delete_sdl_impl(tmp);
03420        }
03421 }
03422 
03423 static void delete_binding(void *data)
03424 {
03425        sdlBindingPtr binding = *((sdlBindingPtr*)data);
03426 
03427        if (binding->location) {
03428               efree(binding->location);
03429        }
03430        if (binding->name) {
03431               efree(binding->name);
03432        }
03433 
03434        if (binding->bindingType == BINDING_SOAP) {
03435               sdlSoapBindingPtr soapBind = binding->bindingAttributes;
03436               if (soapBind) {
03437                      efree(soapBind);
03438               }
03439        }
03440        efree(binding);
03441 }
03442 
03443 static void delete_binding_persistent(void *data)
03444 {
03445        sdlBindingPtr binding = *((sdlBindingPtr*)data);
03446 
03447        if (binding->location) {
03448               free(binding->location);
03449        }
03450        if (binding->name) {
03451               free(binding->name);
03452        }
03453 
03454        if (binding->bindingType == BINDING_SOAP) {
03455               sdlSoapBindingPtr soapBind = binding->bindingAttributes;
03456               if (soapBind) {
03457                      free(soapBind);
03458               }
03459        }
03460        free(binding);
03461 }
03462 
03463 static void delete_sdl_soap_binding_function_body(sdlSoapBindingFunctionBody body)
03464 {
03465        if (body.ns) {
03466               efree(body.ns);
03467        }
03468        if (body.headers) {
03469               zend_hash_destroy(body.headers);
03470               efree(body.headers);
03471        }
03472 }
03473 
03474 static void delete_sdl_soap_binding_function_body_persistent(sdlSoapBindingFunctionBody body)
03475 {
03476        if (body.ns) {
03477               free(body.ns);
03478        }
03479        if (body.headers) {
03480               zend_hash_destroy(body.headers);
03481               free(body.headers);
03482        }
03483 }
03484 
03485 static void delete_function(void *data)
03486 {
03487        sdlFunctionPtr function = *((sdlFunctionPtr*)data);
03488 
03489        if (function->functionName) {
03490               efree(function->functionName);
03491        }
03492        if (function->requestName) {
03493               efree(function->requestName);
03494        }
03495        if (function->responseName) {
03496               efree(function->responseName);
03497        }
03498        if (function->requestParameters) {
03499               zend_hash_destroy(function->requestParameters);
03500               efree(function->requestParameters);
03501        }
03502        if (function->responseParameters) {
03503               zend_hash_destroy(function->responseParameters);
03504               efree(function->responseParameters);
03505        }
03506        if (function->faults) {
03507               zend_hash_destroy(function->faults);
03508               efree(function->faults);
03509        }
03510 
03511        if (function->bindingAttributes &&
03512            function->binding && function->binding->bindingType == BINDING_SOAP) {
03513               sdlSoapBindingFunctionPtr soapFunction = function->bindingAttributes;
03514               if (soapFunction->soapAction) {
03515                      efree(soapFunction->soapAction);
03516               }
03517               delete_sdl_soap_binding_function_body(soapFunction->input);
03518               delete_sdl_soap_binding_function_body(soapFunction->output);
03519               efree(soapFunction);
03520        }
03521        efree(function);
03522 }
03523 
03524 static void delete_function_persistent(void *data)
03525 {
03526        sdlFunctionPtr function = *((sdlFunctionPtr*)data);
03527 
03528        if (function->functionName) {
03529               free(function->functionName);
03530        }
03531        if (function->requestName) {
03532               free(function->requestName);
03533        }
03534        if (function->responseName) {
03535               free(function->responseName);
03536        }
03537        if (function->requestParameters) {
03538               zend_hash_destroy(function->requestParameters);
03539               free(function->requestParameters);
03540        }
03541        if (function->responseParameters) {
03542               zend_hash_destroy(function->responseParameters);
03543               free(function->responseParameters);
03544        }
03545        if (function->faults) {
03546               zend_hash_destroy(function->faults);
03547               free(function->faults);
03548        }
03549 
03550        if (function->bindingAttributes &&
03551            function->binding && function->binding->bindingType == BINDING_SOAP) {
03552               sdlSoapBindingFunctionPtr soapFunction = function->bindingAttributes;
03553               if (soapFunction->soapAction) {
03554                      free(soapFunction->soapAction);
03555               }
03556               delete_sdl_soap_binding_function_body_persistent(soapFunction->input);
03557               delete_sdl_soap_binding_function_body_persistent(soapFunction->output);
03558               free(soapFunction);
03559        }
03560        free(function);
03561 }
03562 
03563 static void delete_parameter(void *data)
03564 {
03565        sdlParamPtr param = *((sdlParamPtr*)data);
03566        if (param->paramName) {
03567               efree(param->paramName);
03568        }
03569        efree(param);
03570 }
03571 
03572 static void delete_parameter_persistent(void *data)
03573 {
03574        sdlParamPtr param = *((sdlParamPtr*)data);
03575        if (param->paramName) {
03576               free(param->paramName);
03577        }
03578        free(param);
03579 }
03580 
03581 static void delete_header(void *data)
03582 {
03583        sdlSoapBindingFunctionHeaderPtr hdr = *((sdlSoapBindingFunctionHeaderPtr*)data);
03584        if (hdr->name) {
03585               efree(hdr->name);
03586        }
03587        if (hdr->ns) {
03588               efree(hdr->ns);
03589        }
03590        if (hdr->headerfaults) {
03591               zend_hash_destroy(hdr->headerfaults);
03592               efree(hdr->headerfaults);
03593        }
03594        efree(hdr);
03595 }
03596 
03597 static void delete_header_persistent(void *data)
03598 {
03599        sdlSoapBindingFunctionHeaderPtr hdr = *((sdlSoapBindingFunctionHeaderPtr*)data);
03600        if (hdr->name) {
03601               free(hdr->name);
03602        }
03603        if (hdr->ns) {
03604               free(hdr->ns);
03605        }
03606        if (hdr->headerfaults) {
03607               zend_hash_destroy(hdr->headerfaults);
03608               free(hdr->headerfaults);
03609        }
03610        free(hdr);
03611 }
03612 
03613 static void delete_fault(void *data)
03614 {
03615        sdlFaultPtr fault = *((sdlFaultPtr*)data);
03616        if (fault->name) {
03617               efree(fault->name);
03618        }
03619        if (fault->details) {
03620               zend_hash_destroy(fault->details);
03621               efree(fault->details);
03622        }
03623        if (fault->bindingAttributes) {
03624               sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
03625 
03626               if (binding->ns) {
03627                      efree(binding->ns);
03628               }
03629               efree(fault->bindingAttributes);
03630        }
03631        efree(fault);
03632 }
03633 
03634 static void delete_fault_persistent(void *data)
03635 {
03636        sdlFaultPtr fault = *((sdlFaultPtr*)data);
03637        if (fault->name) {
03638               free(fault->name);
03639        }
03640        if (fault->details) {
03641               zend_hash_destroy(fault->details);
03642               free(fault->details);
03643        }
03644        if (fault->bindingAttributes) {
03645               sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
03646 
03647               if (binding->ns) {
03648                      free(binding->ns);
03649               }
03650               free(fault->bindingAttributes);
03651        }
03652        free(fault);
03653 }
03654 
03655 static void delete_document(void *doc_ptr)
03656 {
03657        xmlDocPtr doc = *((xmlDocPtr*)doc_ptr);
03658        xmlFreeDoc(doc);
03659 }
03660