root/ext/soap/php_sdl.c

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

DEFINITIONS

This source file includes following definitions.
  1. get_encoder_from_prefix
  2. get_element
  3. get_encoder
  4. get_encoder_ex
  5. get_binding_from_type
  6. get_binding_from_name
  7. is_wsdl_element
  8. sdl_set_uri_credentials
  9. sdl_restore_uri_credentials
  10. load_wsdl_ex
  11. wsdl_soap_binding_header
  12. wsdl_soap_binding_body
  13. wsdl_message
  14. load_wsdl
  15. sdl_deserialize_string
  16. sdl_deserialize_key
  17. sdl_deserialize_attribute
  18. sdl_deserialize_resriction_int
  19. sdl_deserialize_resriction_char
  20. sdl_deserialize_model
  21. sdl_deserialize_type
  22. sdl_deserialize_encoder
  23. sdl_deserialize_soap_body
  24. sdl_deserialize_parameters
  25. get_sdl_from_cache
  26. sdl_serialize_string
  27. sdl_serialize_key
  28. sdl_serialize_encoder_ref
  29. sdl_serialize_type_ref
  30. sdl_serialize_attribute
  31. sdl_serialize_model
  32. sdl_serialize_resriction_int
  33. sdl_serialize_resriction_char
  34. sdl_serialize_type
  35. sdl_serialize_encoder
  36. sdl_serialize_parameters
  37. sdl_serialize_soap_body
  38. add_sdl_to_cache
  39. make_persistent_restriction_int
  40. make_persistent_restriction_char
  41. make_persistent_sdl_type_ref
  42. make_persistent_sdl_encoder_ref
  43. make_persistent_sdl_function_headers
  44. make_persistent_sdl_soap_body
  45. make_persistent_sdl_parameters
  46. make_persistent_sdl_function_faults
  47. make_persistent_sdl_attribute
  48. make_persistent_sdl_model
  49. make_persistent_sdl_type
  50. make_persistent_sdl_encoder
  51. make_persistent_sdl_binding
  52. make_persistent_sdl_function
  53. make_persistent_sdl
  54. delete_psdl
  55. get_sdl
  56. delete_sdl_impl
  57. delete_sdl
  58. delete_binding
  59. delete_binding_persistent
  60. delete_sdl_soap_binding_function_body
  61. delete_sdl_soap_binding_function_body_persistent
  62. delete_function
  63. delete_function_persistent
  64. delete_parameter
  65. delete_parameter_persistent
  66. delete_header
  67. delete_header_persistent
  68. delete_fault
  69. delete_fault_persistent
  70. delete_document

   1 /*
   2   +----------------------------------------------------------------------+
   3   | PHP Version 5                                                        |
   4   +----------------------------------------------------------------------+
   5   | Copyright (c) 1997-2016 The PHP Group                                |
   6   +----------------------------------------------------------------------+
   7   | This source file is subject to version 3.01 of the PHP license,      |
   8   | that is bundled with this package in the file LICENSE, and is        |
   9   | available through the world-wide-web at the following url:           |
  10   | http://www.php.net/license/3_01.txt                                  |
  11   | If you did not receive a copy of the PHP license and are unable to   |
  12   | obtain it through the world-wide-web, please send a note to          |
  13   | license@php.net so we can mail you a copy immediately.               |
  14   +----------------------------------------------------------------------+
  15   | Authors: Brad Lafountain <rodif_bl@yahoo.com>                        |
  16   |          Shane Caraveo <shane@caraveo.com>                           |
  17   |          Dmitry Stogov <dmitry@zend.com>                             |
  18   +----------------------------------------------------------------------+
  19 */
  20 /* $Id$ */
  21 
  22 #include "php_soap.h"
  23 #include "ext/libxml/php_libxml.h"
  24 #include "libxml/uri.h"
  25 
  26 #include "ext/standard/md5.h"
  27 #include "zend_virtual_cwd.h"
  28 
  29 #include <sys/types.h>
  30 #include <sys/stat.h>
  31 #include <fcntl.h>
  32 
  33 #ifndef O_BINARY
  34 # define O_BINARY 0
  35 #endif
  36 
  37 static void delete_fault(void *fault);
  38 static void delete_fault_persistent(void *fault);
  39 static void delete_binding(void *binding);
  40 static void delete_binding_persistent(void *binding);
  41 static void delete_function(void *function);
  42 static void delete_function_persistent(void *function);
  43 static void delete_parameter(void *parameter);
  44 static void delete_parameter_persistent(void *parameter);
  45 static void delete_header(void *header);
  46 static void delete_header_persistent(void *header);
  47 static void delete_document(void *doc_ptr);
  48 
  49 encodePtr get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr node, const xmlChar *type)
  50 {
  51         encodePtr enc = NULL;
  52         xmlNsPtr nsptr;
  53         char *ns, *cptype;
  54 
  55         parse_namespace(type, &cptype, &ns);
  56         nsptr = xmlSearchNs(node->doc, node, BAD_CAST(ns));
  57         if (nsptr != NULL) {
  58                 enc = get_encoder(sdl, (char*)nsptr->href, cptype);
  59                 if (enc == NULL) {
  60                         enc = get_encoder_ex(sdl, cptype, strlen(cptype));
  61                 }
  62         } else {
  63                 enc = get_encoder_ex(sdl, (char*)type, xmlStrlen(type));
  64         }
  65         efree(cptype);
  66         if (ns) {efree(ns);}
  67         return enc;
  68 }
  69 
  70 static sdlTypePtr get_element(sdlPtr sdl, xmlNodePtr node, const xmlChar *type)
  71 {
  72         sdlTypePtr ret = NULL;
  73 
  74         if (sdl->elements) {
  75                 xmlNsPtr nsptr;
  76                 char *ns, *cptype;
  77                 sdlTypePtr *sdl_type;
  78 
  79                 parse_namespace(type, &cptype, &ns);
  80                 nsptr = xmlSearchNs(node->doc, node, BAD_CAST(ns));
  81                 if (nsptr != NULL) {
  82                         int ns_len = xmlStrlen(nsptr->href);
  83                         int type_len = strlen(cptype);
  84                         int len = ns_len + type_len + 1;
  85                         char *nscat = emalloc(len + 1);
  86 
  87                         memcpy(nscat, nsptr->href, ns_len);
  88                         nscat[ns_len] = ':';
  89                         memcpy(nscat+ns_len+1, cptype, type_len);
  90                         nscat[len] = '\0';
  91 
  92                         if (zend_hash_find(sdl->elements, nscat, len + 1, (void **)&sdl_type) == SUCCESS) {
  93                                 ret = *sdl_type;
  94                         } else if (zend_hash_find(sdl->elements, (char*)type, type_len + 1, (void **)&sdl_type) == SUCCESS) {
  95                                 ret = *sdl_type;
  96                         }
  97                         efree(nscat);
  98                 } else {
  99                         if (zend_hash_find(sdl->elements, (char*)type, xmlStrlen(type) + 1, (void **)&sdl_type) == SUCCESS) {
 100                                 ret = *sdl_type;
 101                         }
 102                 }
 103 
 104                 efree(cptype);
 105                 if (ns) {efree(ns);}
 106         }
 107         return ret;
 108 }
 109 
 110 encodePtr get_encoder(sdlPtr sdl, const char *ns, const char *type)
 111 {
 112         encodePtr enc = NULL;
 113         char *nscat;
 114         int ns_len = ns ? strlen(ns) : 0;
 115         int type_len = strlen(type);
 116         int len = ns_len + type_len + 1;
 117 
 118         nscat = emalloc(len + 1);
 119         memcpy(nscat, ns, ns_len);
 120         nscat[ns_len] = ':';
 121         memcpy(nscat+ns_len+1, type, type_len);
 122         nscat[len] = '\0';
 123 
 124         enc = get_encoder_ex(sdl, nscat, len);
 125 
 126         if (enc == NULL &&
 127             ((ns_len == sizeof(SOAP_1_1_ENC_NAMESPACE)-1 &&
 128               memcmp(ns, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)-1) == 0) ||
 129              (ns_len == sizeof(SOAP_1_2_ENC_NAMESPACE)-1 &&
 130               memcmp(ns, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)-1) == 0))) {
 131                 char *enc_nscat;
 132                 int enc_ns_len;
 133                 int enc_len;
 134 
 135                 enc_ns_len = sizeof(XSD_NAMESPACE)-1;
 136                 enc_len = enc_ns_len + type_len + 1;
 137                 enc_nscat = emalloc(enc_len + 1);
 138                 memcpy(enc_nscat, XSD_NAMESPACE, sizeof(XSD_NAMESPACE)-1);
 139                 enc_nscat[enc_ns_len] = ':';
 140                 memcpy(enc_nscat+enc_ns_len+1, type, type_len);
 141                 enc_nscat[enc_len] = '\0';
 142 
 143                 enc = get_encoder_ex(NULL, enc_nscat, enc_len);
 144                 efree(enc_nscat);
 145                 if (enc && sdl) {
 146                         encodePtr new_enc       = pemalloc(sizeof(encode), sdl->is_persistent);
 147                         memcpy(new_enc, enc, sizeof(encode));
 148                         if (sdl->is_persistent) {
 149                                 new_enc->details.ns = zend_strndup(ns, ns_len);
 150                                 new_enc->details.type_str = strdup(new_enc->details.type_str);
 151                         } else {
 152                                 new_enc->details.ns = estrndup(ns, ns_len);
 153                                 new_enc->details.type_str = estrdup(new_enc->details.type_str);
 154                         }
 155                         if (sdl->encoders == NULL) {
 156                                 sdl->encoders = pemalloc(sizeof(HashTable), sdl->is_persistent);
 157                                 zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, sdl->is_persistent);
 158                         }
 159                         zend_hash_update(sdl->encoders, nscat, len + 1, &new_enc, sizeof(encodePtr), NULL);
 160                         enc = new_enc;
 161                 }
 162         }
 163         efree(nscat);
 164         return enc;
 165 }
 166 
 167 encodePtr get_encoder_ex(sdlPtr sdl, const char *nscat, int len)
 168 {
 169         encodePtr *enc;
 170         TSRMLS_FETCH();
 171 
 172         if (zend_hash_find(&SOAP_GLOBAL(defEnc), (char*)nscat, len + 1, (void **)&enc) == SUCCESS) {
 173                 return (*enc);
 174         } else if (sdl && sdl->encoders && zend_hash_find(sdl->encoders, (char*)nscat, len + 1, (void **)&enc) == SUCCESS) {
 175                 return (*enc);
 176         }
 177         return NULL;
 178 }
 179 
 180 sdlBindingPtr get_binding_from_type(sdlPtr sdl, int type)
 181 {
 182         sdlBindingPtr *binding;
 183 
 184         if (sdl == NULL) {
 185                 return NULL;
 186         }
 187 
 188         for (zend_hash_internal_pointer_reset(sdl->bindings);
 189                 zend_hash_get_current_data(sdl->bindings, (void **) &binding) == SUCCESS;
 190                 zend_hash_move_forward(sdl->bindings)) {
 191                 if ((*binding)->bindingType == type) {
 192                         return *binding;
 193                 }
 194         }
 195         return NULL;
 196 }
 197 
 198 sdlBindingPtr get_binding_from_name(sdlPtr sdl, char *name, char *ns)
 199 {
 200         sdlBindingPtr binding = NULL;
 201         smart_str key = {0};
 202 
 203         smart_str_appends(&key, ns);
 204         smart_str_appendc(&key, ':');
 205         smart_str_appends(&key, name);
 206         smart_str_0(&key);
 207 
 208         zend_hash_find(sdl->bindings, key.c, key.len, (void **)&binding);
 209 
 210         smart_str_free(&key);
 211         return binding;
 212 }
 213 
 214 static int is_wsdl_element(xmlNodePtr node)
 215 {
 216         if (node->ns && strcmp((char*)node->ns->href, WSDL_NAMESPACE) != 0) {
 217                 xmlAttrPtr attr;
 218                 if ((attr = get_attribute_ex(node->properties, "required", WSDL_NAMESPACE)) != NULL &&
 219                      attr->children && attr->children->content &&
 220                      (strcmp((char*)attr->children->content, "1") == 0 ||
 221                       strcmp((char*)attr->children->content, "true") == 0)) {
 222                         soap_error1(E_ERROR, "Parsing WSDL: Unknown required WSDL extension '%s'", node->ns->href);
 223                 }
 224                 return 0;
 225         }
 226         return 1;
 227 }
 228 
 229 void sdl_set_uri_credentials(sdlCtx *ctx, char *uri TSRMLS_DC)
 230 {
 231         char *s;
 232         int l1, l2;
 233         zval *context = NULL;
 234         zval **header = NULL;
 235 
 236         /* check if we load xsd from the same server */
 237         s = strstr(ctx->sdl->source, "://");
 238         if (!s) return;
 239         s = strchr(s+3, '/');
 240         l1 = s ? (s - ctx->sdl->source) : strlen(ctx->sdl->source);
 241         s = strstr((char*)uri, "://");
 242         if (!s) return;
 243         s = strchr(s+3, '/');
 244         l2 = s ? (s - (char*)uri) : strlen((char*)uri);
 245         if (l1 != l2) {
 246                 /* check for http://...:80/ */
 247                 if (l1 > 11 &&
 248                     ctx->sdl->source[4] == ':' &&
 249                     ctx->sdl->source[l1-3] == ':' &&
 250                     ctx->sdl->source[l1-2] == '8' &&
 251                     ctx->sdl->source[l1-1] == '0') {
 252                         l1 -= 3;
 253                 }
 254                 if (l2 > 11 &&
 255                     uri[4] == ':' &&
 256                     uri[l2-3] == ':' &&
 257                     uri[l2-2] == '8' &&
 258                     uri[l2-1] == '0') {
 259                         l2 -= 3;
 260                 }
 261                 /* check for https://...:443/ */
 262                 if (l1 > 13 &&
 263                     ctx->sdl->source[4] == 's' &&
 264                     ctx->sdl->source[l1-4] == ':' &&
 265                     ctx->sdl->source[l1-3] == '4' &&
 266                     ctx->sdl->source[l1-2] == '4' &&
 267                     ctx->sdl->source[l1-1] == '3') {
 268                         l1 -= 4;
 269                 }
 270                 if (l2 > 13 &&
 271                     uri[4] == 's' &&
 272                     uri[l2-4] == ':' &&
 273                     uri[l2-3] == '4' &&
 274                     uri[l2-2] == '4' &&
 275                     uri[l2-1] == '3') {
 276                         l2 -= 4;
 277                 }
 278         }
 279         if (l1 != l2 || memcmp(ctx->sdl->source, uri, l1) != 0) {
 280                 /* another server. clear authentication credentals */
 281                 context = php_libxml_switch_context(NULL TSRMLS_CC);
 282                 php_libxml_switch_context(context TSRMLS_CC);
 283                 if (context) {
 284                         ctx->context = php_stream_context_from_zval(context, 1);
 285 
 286                         if (ctx->context &&
 287                             php_stream_context_get_option(ctx->context, "http", "header", &header) == SUCCESS) {
 288                                 s = strstr(Z_STRVAL_PP(header), "Authorization: Basic");
 289                                 if (s && (s == Z_STRVAL_PP(header) || *(s-1) == '\n' || *(s-1) == '\r')) {
 290                                         char *rest = strstr(s, "\r\n");
 291                                         if (rest) {
 292                                                 zval new_header;
 293                                         
 294                                                 rest += 2;
 295                                                 Z_TYPE(new_header) = IS_STRING;
 296                                                 Z_STRLEN(new_header) = Z_STRLEN_PP(header) - (rest - s);
 297                                                 Z_STRVAL(new_header) = emalloc(Z_STRLEN_PP(header) + 1);
 298                                                 memcpy(Z_STRVAL(new_header), Z_STRVAL_PP(header), s - Z_STRVAL_PP(header));
 299                                                 memcpy(Z_STRVAL(new_header) + (s - Z_STRVAL_PP(header)), rest, Z_STRLEN_PP(header) - (rest - Z_STRVAL_PP(header)) + 1);
 300                                                 ctx->old_header = *header;
 301                                                 Z_ADDREF_P(ctx->old_header);
 302                                                 php_stream_context_set_option(ctx->context, "http", "header", &new_header);
 303                                                 zval_dtor(&new_header);
 304                                         }
 305                                 }
 306                         }
 307                 }
 308         }
 309 }
 310 
 311 void sdl_restore_uri_credentials(sdlCtx *ctx TSRMLS_DC)
 312 {
 313         if (ctx->old_header) {
 314             php_stream_context_set_option(ctx->context, "http", "header", ctx->old_header);
 315             zval_ptr_dtor(&ctx->old_header);
 316                 ctx->old_header = NULL;
 317         }
 318         ctx->context = NULL;
 319 }
 320 
 321 static void load_wsdl_ex(zval *this_ptr, char *struri, sdlCtx *ctx, int include TSRMLS_DC)
 322 {
 323         sdlPtr tmpsdl = ctx->sdl;
 324         xmlDocPtr wsdl;
 325         xmlNodePtr root, definitions, trav;
 326         xmlAttrPtr targetNamespace;
 327 
 328         if (zend_hash_exists(&ctx->docs, struri, strlen(struri)+1)) {
 329                 return;
 330         }
 331         
 332         sdl_set_uri_credentials(ctx, struri TSRMLS_CC);
 333         wsdl = soap_xmlParseFile(struri TSRMLS_CC);
 334         sdl_restore_uri_credentials(ctx TSRMLS_CC);
 335         
 336         if (!wsdl) {
 337                 xmlErrorPtr xmlErrorPtr = xmlGetLastError();
 338 
 339                 if (xmlErrorPtr) {
 340                         soap_error2(E_ERROR, "Parsing WSDL: Couldn't load from '%s' : %s", struri, xmlErrorPtr->message);
 341                 } else {
 342                         soap_error1(E_ERROR, "Parsing WSDL: Couldn't load from '%s'", struri);
 343                 }
 344         }
 345 
 346         zend_hash_add(&ctx->docs, struri, strlen(struri)+1, (void**)&wsdl, sizeof(xmlDocPtr), NULL);
 347 
 348         root = wsdl->children;
 349         definitions = get_node_ex(root, "definitions", WSDL_NAMESPACE);
 350         if (!definitions) {
 351                 if (include) {
 352                         xmlNodePtr schema = get_node_ex(root, "schema", XSD_NAMESPACE);
 353                         if (schema) {
 354                                 load_schema(ctx, schema TSRMLS_CC);
 355                                 return;
 356                         }
 357                 }
 358                 soap_error1(E_ERROR, "Parsing WSDL: Couldn't find <definitions> in '%s'", struri);
 359         }
 360 
 361         if (!include) {
 362                 targetNamespace = get_attribute(definitions->properties, "targetNamespace");
 363                 if (targetNamespace) {
 364                         tmpsdl->target_ns = estrdup((char*)targetNamespace->children->content);
 365                 }
 366         }
 367 
 368         trav = definitions->children;
 369         while (trav != NULL) {
 370                 if (!is_wsdl_element(trav)) {
 371                         trav = trav->next;
 372                         continue;
 373                 }
 374                 if (node_is_equal(trav,"types")) {
 375                         /* TODO: Only one "types" is allowed */
 376                         xmlNodePtr trav2 = trav->children;
 377 
 378                         while (trav2 != NULL) {
 379                                 if (node_is_equal_ex(trav2, "schema", XSD_NAMESPACE)) {
 380                                         load_schema(ctx, trav2 TSRMLS_CC);
 381                                 } else if (is_wsdl_element(trav2) && !node_is_equal(trav2,"documentation")) {
 382                                         soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
 383                                 }
 384                                 trav2 = trav2->next;
 385                         }
 386                 } else if (node_is_equal(trav,"import")) {
 387                         /* TODO: namespace ??? */
 388                         xmlAttrPtr tmp = get_attribute(trav->properties, "location");
 389                         if (tmp) {
 390                                 xmlChar *uri;
 391                                 xmlChar *base = xmlNodeGetBase(trav->doc, trav);
 392 
 393                                 if (base == NULL) {
 394                                         uri = xmlBuildURI(tmp->children->content, trav->doc->URL);
 395                                 } else {
 396                                         uri = xmlBuildURI(tmp->children->content, base);
 397                                         xmlFree(base);
 398                                 }
 399                                 load_wsdl_ex(this_ptr, (char*)uri, ctx, 1 TSRMLS_CC);
 400                                 xmlFree(uri);
 401                         }
 402 
 403                 } else if (node_is_equal(trav,"message")) {
 404                         xmlAttrPtr name = get_attribute(trav->properties, "name");
 405                         if (name && name->children && name->children->content) {
 406                                 if (zend_hash_add(&ctx->messages, (char*)name->children->content, xmlStrlen(name->children->content)+1,&trav, sizeof(xmlNodePtr), NULL) != SUCCESS) {
 407                                         soap_error1(E_ERROR, "Parsing WSDL: <message> '%s' already defined", name->children->content);
 408                                 }
 409                         } else {
 410                                 soap_error0(E_ERROR, "Parsing WSDL: <message> has no name attribute");
 411                         }
 412 
 413                 } else if (node_is_equal(trav,"portType")) {
 414                         xmlAttrPtr name = get_attribute(trav->properties, "name");
 415                         if (name && name->children && name->children->content) {
 416                                 if (zend_hash_add(&ctx->portTypes, (char*)name->children->content, xmlStrlen(name->children->content)+1,&trav, sizeof(xmlNodePtr), NULL) != SUCCESS) {
 417                                         soap_error1(E_ERROR, "Parsing WSDL: <portType> '%s' already defined", name->children->content);
 418                                 }
 419                         } else {
 420                                 soap_error0(E_ERROR, "Parsing WSDL: <portType> has no name attribute");
 421                         }
 422 
 423                 } else if (node_is_equal(trav,"binding")) {
 424                         xmlAttrPtr name = get_attribute(trav->properties, "name");
 425                         if (name && name->children && name->children->content) {
 426                                 if (zend_hash_add(&ctx->bindings, (char*)name->children->content, xmlStrlen(name->children->content)+1,&trav, sizeof(xmlNodePtr), NULL) != SUCCESS) {
 427                                         soap_error1(E_ERROR, "Parsing WSDL: <binding> '%s' already defined", name->children->content);
 428                                 }
 429                         } else {
 430                                 soap_error0(E_ERROR, "Parsing WSDL: <binding> has no name attribute");
 431                         }
 432 
 433                 } else if (node_is_equal(trav,"service")) {
 434                         xmlAttrPtr name = get_attribute(trav->properties, "name");
 435                         if (name && name->children && name->children->content) {
 436                                 if (zend_hash_add(&ctx->services, (char*)name->children->content, xmlStrlen(name->children->content)+1,&trav, sizeof(xmlNodePtr), NULL) != SUCCESS) {
 437                                         soap_error1(E_ERROR, "Parsing WSDL: <service> '%s' already defined", name->children->content);
 438                                 }
 439                         } else {
 440                                 soap_error0(E_ERROR, "Parsing WSDL: <service> has no name attribute");
 441                         }
 442                 } else if (!node_is_equal(trav,"documentation")) {
 443                         soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
 444                 }
 445                 trav = trav->next;
 446         }
 447 }
 448 
 449 static sdlSoapBindingFunctionHeaderPtr wsdl_soap_binding_header(sdlCtx* ctx, xmlNodePtr header, char* wsdl_soap_namespace, int fault)
 450 {
 451         xmlAttrPtr tmp;
 452         xmlNodePtr *message, part;
 453         char *ctype;
 454         sdlSoapBindingFunctionHeaderPtr h;
 455 
 456         tmp = get_attribute(header->properties, "message");
 457         if (!tmp) {
 458                 soap_error0(E_ERROR, "Parsing WSDL: Missing message attribute for <header>");
 459         }
 460 
 461         ctype = strrchr((char*)tmp->children->content,':');
 462         if (ctype == NULL) {
 463                 ctype = (char*)tmp->children->content;
 464         } else {
 465                 ++ctype;
 466         }
 467         if (zend_hash_find(&ctx->messages, ctype, strlen(ctype)+1, (void**)&message) != SUCCESS) {
 468                 soap_error1(E_ERROR, "Parsing WSDL: Missing <message> with name '%s'", tmp->children->content);
 469         }
 470 
 471         tmp = get_attribute(header->properties, "part");
 472         if (!tmp) {
 473                 soap_error0(E_ERROR, "Parsing WSDL: Missing part attribute for <header>");
 474         }
 475         part = get_node_with_attribute_ex((*message)->children, "part", WSDL_NAMESPACE, "name", (char*)tmp->children->content, NULL);
 476         if (!part) {
 477                 soap_error1(E_ERROR, "Parsing WSDL: Missing part '%s' in <message>", tmp->children->content);
 478         }
 479 
 480         h = emalloc(sizeof(sdlSoapBindingFunctionHeader));
 481         memset(h, 0, sizeof(sdlSoapBindingFunctionHeader));
 482         h->name = estrdup((char*)tmp->children->content);
 483 
 484         tmp = get_attribute(header->properties, "use");
 485         if (tmp && !strncmp((char*)tmp->children->content, "encoded", sizeof("encoded"))) {
 486                 h->use = SOAP_ENCODED;
 487         } else {
 488                 h->use = SOAP_LITERAL;
 489         }
 490 
 491         tmp = get_attribute(header->properties, "namespace");
 492         if (tmp) {
 493                 h->ns = estrdup((char*)tmp->children->content);
 494         }
 495 
 496         if (h->use == SOAP_ENCODED) {
 497                 tmp = get_attribute(header->properties, "encodingStyle");
 498                 if (tmp) {
 499                         if (strncmp((char*)tmp->children->content, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) {
 500                                 h->encodingStyle = SOAP_ENCODING_1_1;
 501                         } else if (strncmp((char*)tmp->children->content, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) {
 502                                 h->encodingStyle = SOAP_ENCODING_1_2;
 503                         } else {
 504                                 soap_error1(E_ERROR, "Parsing WSDL: Unknown encodingStyle '%s'", tmp->children->content);
 505                         }
 506                 } else {
 507                         soap_error0(E_ERROR, "Parsing WSDL: Unspecified encodingStyle");
 508                 }
 509         }
 510 
 511         tmp = get_attribute(part->properties, "type");
 512         if (tmp != NULL) {
 513                 h->encode = get_encoder_from_prefix(ctx->sdl, part, tmp->children->content);
 514         } else {
 515                 tmp = get_attribute(part->properties, "element");
 516                 if (tmp != NULL) {
 517                         h->element = get_element(ctx->sdl, part, tmp->children->content);
 518                         if (h->element) {
 519                                 h->encode = h->element->encode;
 520                                 if (!h->ns && h->element->namens) {
 521                                         h->ns = estrdup(h->element->namens);
 522                                 }
 523                                 if (h->element->name) {
 524                                         efree(h->name);
 525                                         h->name = estrdup(h->element->name);
 526                                 }
 527                         }
 528                 }
 529         }
 530         if (!fault) {
 531                 xmlNodePtr trav = header->children;
 532                 while (trav != NULL) {
 533                         if (node_is_equal_ex(trav, "headerfault", wsdl_soap_namespace)) {
 534                                 sdlSoapBindingFunctionHeaderPtr hf = wsdl_soap_binding_header(ctx, trav, wsdl_soap_namespace, 1);
 535                                 smart_str key = {0};
 536 
 537                                 if (h->headerfaults == NULL) {
 538                                         h->headerfaults = emalloc(sizeof(HashTable));
 539                                         zend_hash_init(h->headerfaults, 0, NULL, delete_header, 0);
 540                                 }
 541 
 542                                 if (hf->ns) {
 543                                         smart_str_appends(&key,hf->ns);
 544                                         smart_str_appendc(&key,':');
 545                                 }
 546                                 smart_str_appends(&key,hf->name);
 547                                 smart_str_0(&key);
 548                                 if (zend_hash_add(h->headerfaults, key.c, key.len+1, (void**)&hf, sizeof(sdlSoapBindingFunctionHeaderPtr), NULL) != SUCCESS) {
 549                                         delete_header((void**)&hf);
 550                                 }
 551                                 smart_str_free(&key);
 552                         } else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
 553                                 soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
 554                         }
 555                         trav = trav->next;
 556                 }
 557         }
 558         return h;
 559 }
 560 
 561 static void wsdl_soap_binding_body(sdlCtx* ctx, xmlNodePtr node, char* wsdl_soap_namespace, sdlSoapBindingFunctionBody *binding, HashTable* params)
 562 {
 563         xmlNodePtr body, trav;
 564         xmlAttrPtr tmp;
 565 
 566         trav = node->children;
 567         while (trav != NULL) {
 568                 if (node_is_equal_ex(trav, "body", wsdl_soap_namespace)) {
 569                         body = trav;
 570 
 571                         tmp = get_attribute(body->properties, "use");
 572                         if (tmp && !strncmp((char*)tmp->children->content, "literal", sizeof("literal"))) {
 573                                 binding->use = SOAP_LITERAL;
 574                         } else {
 575                                 binding->use = SOAP_ENCODED;
 576                         }
 577 
 578                         tmp = get_attribute(body->properties, "namespace");
 579                         if (tmp) {
 580                                 binding->ns = estrdup((char*)tmp->children->content);
 581                         }
 582 
 583                         tmp = get_attribute(body->properties, "parts");
 584                         if (tmp) {
 585                                 HashTable    ht;
 586                                 char *parts = (char*)tmp->children->content;
 587 
 588                                 /* Delete all parts those are not in the "parts" attribute */
 589                                 zend_hash_init(&ht, 0, NULL, delete_parameter, 0);
 590                                 while (*parts) {
 591                                         HashPosition pos;
 592                                         sdlParamPtr *param;
 593                                         int found = 0;
 594                                         char *end;
 595 
 596                                         while (*parts == ' ') ++parts;
 597                                         if (*parts == '\0') break;
 598                                         end = strchr(parts, ' ');
 599                                         if (end) *end = '\0';
 600                                         zend_hash_internal_pointer_reset_ex(params, &pos);
 601                                         while (zend_hash_get_current_data_ex(params, (void **)&param, &pos) != FAILURE) {
 602                                                 if ((*param)->paramName &&
 603                                                     strcmp(parts, (*param)->paramName) == 0) {
 604                                                 sdlParamPtr x_param;
 605                                                 x_param = emalloc(sizeof(sdlParam));
 606                                                 *x_param = **param;
 607                                                 (*param)->paramName = NULL;
 608                                                 zend_hash_next_index_insert(&ht, &x_param, sizeof(sdlParamPtr), NULL);
 609                                                 found = 1;
 610                                                 break;
 611                                                 }
 612                                                 zend_hash_move_forward_ex(params, &pos);
 613                                         }
 614                                         if (!found) {
 615                                                 soap_error1(E_ERROR, "Parsing WSDL: Missing part '%s' in <message>", parts);
 616                                         }
 617                                         parts += strlen(parts);
 618                                         if (end) *end = ' ';
 619                                 }
 620                                 zend_hash_destroy(params);
 621                                 *params = ht;
 622                         }
 623 
 624                         if (binding->use == SOAP_ENCODED) {
 625                                 tmp = get_attribute(body->properties, "encodingStyle");
 626                                 if (tmp) {
 627                                         if (strncmp((char*)tmp->children->content, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) {
 628                                                 binding->encodingStyle = SOAP_ENCODING_1_1;
 629                                         } else if (strncmp((char*)tmp->children->content, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) {
 630                                                 binding->encodingStyle = SOAP_ENCODING_1_2;
 631                                         } else {
 632                                                 soap_error1(E_ERROR, "Parsing WSDL: Unknown encodingStyle '%s'", tmp->children->content);
 633                                         }
 634                                 } else {
 635                                         soap_error0(E_ERROR, "Parsing WSDL: Unspecified encodingStyle");
 636                                 }
 637                         }
 638                 } else if (node_is_equal_ex(trav, "header", wsdl_soap_namespace)) {
 639                         sdlSoapBindingFunctionHeaderPtr h = wsdl_soap_binding_header(ctx, trav, wsdl_soap_namespace, 0);
 640                         smart_str key = {0};
 641 
 642                         if (binding->headers == NULL) {
 643                                 binding->headers = emalloc(sizeof(HashTable));
 644                                 zend_hash_init(binding->headers, 0, NULL, delete_header, 0);
 645                         }
 646 
 647                         if (h->ns) {
 648                                 smart_str_appends(&key,h->ns);
 649                                 smart_str_appendc(&key,':');
 650                         }
 651                         smart_str_appends(&key,h->name);
 652                         smart_str_0(&key);
 653                         if (zend_hash_add(binding->headers, key.c, key.len+1, (void**)&h, sizeof(sdlSoapBindingFunctionHeaderPtr), NULL) != SUCCESS) {
 654                                 delete_header((void**)&h);
 655                         }
 656                         smart_str_free(&key);
 657                 } else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
 658                         soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
 659                 }
 660                 trav = trav->next;
 661         }
 662 }
 663 
 664 static HashTable* wsdl_message(sdlCtx *ctx, xmlChar* message_name)
 665 {
 666         xmlNodePtr trav, part, message = NULL, *tmp;
 667         HashTable* parameters = NULL;
 668         char *ctype;
 669 
 670         ctype = strrchr((char*)message_name,':');
 671         if (ctype == NULL) {
 672                 ctype = (char*)message_name;
 673         } else {
 674                 ++ctype;
 675         }
 676         if (zend_hash_find(&ctx->messages, ctype, strlen(ctype)+1, (void**)&tmp) != SUCCESS) {
 677                 soap_error1(E_ERROR, "Parsing WSDL: Missing <message> with name '%s'", message_name);
 678         }
 679         message = *tmp;
 680 
 681         parameters = emalloc(sizeof(HashTable));
 682         zend_hash_init(parameters, 0, NULL, delete_parameter, 0);
 683 
 684         trav = message->children;
 685         while (trav != NULL) {
 686                 xmlAttrPtr element, type, name;
 687                 sdlParamPtr param;
 688 
 689                 if (trav->ns != NULL && strcmp((char*)trav->ns->href, WSDL_NAMESPACE) != 0) {
 690                         soap_error1(E_ERROR, "Parsing WSDL: Unexpected extensibility element <%s>", trav->name);
 691                 }
 692                 if (node_is_equal(trav,"documentation")) {
 693                         trav = trav->next;
 694                         continue;
 695                 }
 696                 if (!node_is_equal(trav,"part")) {
 697                         soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
 698                 }
 699                 part = trav;
 700                 param = emalloc(sizeof(sdlParam));
 701                 memset(param,0,sizeof(sdlParam));
 702                 param->order = 0;
 703 
 704                 name = get_attribute(part->properties, "name");
 705                 if (name == NULL) {
 706                         soap_error1(E_ERROR, "Parsing WSDL: No name associated with <part> '%s'", message->name);
 707                 }
 708 
 709                 param->paramName = estrdup((char*)name->children->content);
 710 
 711                 type = get_attribute(part->properties, "type");
 712                 if (type != NULL) {
 713                         param->encode = get_encoder_from_prefix(ctx->sdl, part, type->children->content);
 714                 } else {
 715                         element = get_attribute(part->properties, "element");
 716                         if (element != NULL) {
 717                                 param->element = get_element(ctx->sdl, part, element->children->content);
 718                                 if (param->element) {
 719                                         param->encode = param->element->encode;
 720                                 }
 721                         }
 722                 }
 723 
 724                 zend_hash_next_index_insert(parameters, &param, sizeof(sdlParamPtr), NULL);
 725 
 726                 trav = trav->next;
 727         }
 728         return parameters;
 729 }
 730 
 731 static sdlPtr load_wsdl(zval *this_ptr, char *struri TSRMLS_DC)
 732 {
 733         sdlCtx ctx;
 734         int i,n;
 735 
 736         memset(&ctx,0,sizeof(ctx));
 737         ctx.sdl = emalloc(sizeof(sdl));
 738         memset(ctx.sdl, 0, sizeof(sdl));
 739         ctx.sdl->source = estrdup(struri);
 740         zend_hash_init(&ctx.sdl->functions, 0, NULL, delete_function, 0);
 741 
 742         zend_hash_init(&ctx.docs, 0, NULL, delete_document, 0);
 743         zend_hash_init(&ctx.messages, 0, NULL, NULL, 0);
 744         zend_hash_init(&ctx.bindings, 0, NULL, NULL, 0);
 745         zend_hash_init(&ctx.portTypes, 0, NULL, NULL, 0);
 746         zend_hash_init(&ctx.services,  0, NULL, NULL, 0);
 747 
 748         load_wsdl_ex(this_ptr, struri,&ctx, 0 TSRMLS_CC);
 749         schema_pass2(&ctx);
 750 
 751         n = zend_hash_num_elements(&ctx.services);
 752         if (n > 0) {
 753                 zend_hash_internal_pointer_reset(&ctx.services);
 754                 for (i = 0; i < n; i++) {
 755                         xmlNodePtr *tmp, service;
 756                         xmlNodePtr trav, port;
 757                         int has_soap_port = 0;
 758 
 759                         zend_hash_get_current_data(&ctx.services, (void **)&tmp);
 760                         service = *tmp;
 761 
 762                         trav = service->children;
 763                         while (trav != NULL) {
 764                                 xmlAttrPtr type, name, bindingAttr, location;
 765                                 xmlNodePtr portType, operation;
 766                                 xmlNodePtr address, binding, trav2;
 767                                 char *ctype;
 768                                 sdlBindingPtr tmpbinding;
 769                                 char *wsdl_soap_namespace = NULL;
 770 
 771                                 if (!is_wsdl_element(trav) || node_is_equal(trav,"documentation")) {
 772                                         trav = trav->next;
 773                                         continue;
 774                                 }
 775                                 if (!node_is_equal(trav,"port")) {
 776                                         soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
 777                                 }
 778 
 779                                 port = trav;
 780 
 781                                 tmpbinding = emalloc(sizeof(sdlBinding));
 782                                 memset(tmpbinding, 0, sizeof(sdlBinding));
 783 
 784                                 bindingAttr = get_attribute(port->properties, "binding");
 785                                 if (bindingAttr == NULL) {
 786                                         soap_error0(E_ERROR, "Parsing WSDL: No binding associated with <port>");
 787                                 }
 788 
 789                                 /* find address and figure out binding type */
 790                                 address = NULL;
 791                                 trav2 = port->children;
 792                                 while (trav2 != NULL) {
 793                                         if (node_is_equal(trav2,"address") && trav2->ns) {
 794                                                 if (!strncmp((char*)trav2->ns->href, WSDL_SOAP11_NAMESPACE, sizeof(WSDL_SOAP11_NAMESPACE))) {
 795                                                         address = trav2;
 796                                                         wsdl_soap_namespace = WSDL_SOAP11_NAMESPACE;
 797                                                         tmpbinding->bindingType = BINDING_SOAP;
 798                                                 } else if (!strncmp((char*)trav2->ns->href, WSDL_SOAP12_NAMESPACE, sizeof(WSDL_SOAP12_NAMESPACE))) {
 799                                                         address = trav2;
 800                                                         wsdl_soap_namespace = WSDL_SOAP12_NAMESPACE;
 801                                                         tmpbinding->bindingType = BINDING_SOAP;
 802                                                 } else if (!strncmp((char*)trav2->ns->href, RPC_SOAP12_NAMESPACE, sizeof(RPC_SOAP12_NAMESPACE))) {
 803                                                         address = trav2;
 804                                                         wsdl_soap_namespace = RPC_SOAP12_NAMESPACE;
 805                                                         tmpbinding->bindingType = BINDING_SOAP;
 806                                                 } else if (!strncmp((char*)trav2->ns->href, WSDL_HTTP11_NAMESPACE, sizeof(WSDL_HTTP11_NAMESPACE))) {
 807                                                         address = trav2;
 808                                                         tmpbinding->bindingType = BINDING_HTTP;
 809                                                 } else if (!strncmp((char*)trav2->ns->href, WSDL_HTTP12_NAMESPACE, sizeof(WSDL_HTTP12_NAMESPACE))) {
 810                                                         address = trav2;
 811                                                         tmpbinding->bindingType = BINDING_HTTP;
 812                                                 }
 813                                         }
 814                                         if (trav2 != address && is_wsdl_element(trav2) && !node_is_equal(trav2,"documentation")) {
 815                                                 soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
 816                                         }
 817                                   trav2 = trav2->next;
 818                                 }
 819                                 if (!address || tmpbinding->bindingType == BINDING_HTTP) {
 820                                         if (has_soap_port || trav->next || i < n-1) {
 821                                                 efree(tmpbinding);
 822                                                 trav = trav->next;
 823                                                 continue;
 824                                         } else if (!address) {
 825                                                 soap_error0(E_ERROR, "Parsing WSDL: No address associated with <port>");
 826                                         }
 827                                 }
 828                                 has_soap_port = 1;
 829 
 830                                 location = get_attribute(address->properties, "location");
 831                                 if (!location) {
 832                                         soap_error0(E_ERROR, "Parsing WSDL: No location associated with <port>");
 833                                 }
 834 
 835                                 tmpbinding->location = estrdup((char*)location->children->content);
 836 
 837                                 ctype = strrchr((char*)bindingAttr->children->content,':');
 838                                 if (ctype == NULL) {
 839                                         ctype = (char*)bindingAttr->children->content;
 840                                 } else {
 841                                         ++ctype;
 842                                 }
 843                                 if (zend_hash_find(&ctx.bindings, ctype, strlen(ctype)+1, (void*)&tmp) != SUCCESS) {
 844                                         soap_error1(E_ERROR, "Parsing WSDL: No <binding> element with name '%s'", ctype);
 845                                 }
 846                                 binding = *tmp;
 847 
 848                                 if (tmpbinding->bindingType == BINDING_SOAP) {
 849                                         sdlSoapBindingPtr soapBinding;
 850                                         xmlNodePtr soapBindingNode;
 851                                         xmlAttrPtr tmp;
 852 
 853                                         soapBinding = emalloc(sizeof(sdlSoapBinding));
 854                                         memset(soapBinding, 0, sizeof(sdlSoapBinding));
 855                                         soapBinding->style = SOAP_DOCUMENT;
 856 
 857                                         soapBindingNode = get_node_ex(binding->children, "binding", wsdl_soap_namespace);
 858                                         if (soapBindingNode) {
 859                                                 tmp = get_attribute(soapBindingNode->properties, "style");
 860                                                 if (tmp && !strncmp((char*)tmp->children->content, "rpc", sizeof("rpc"))) {
 861                                                         soapBinding->style = SOAP_RPC;
 862                                                 }
 863 
 864                                                 tmp = get_attribute(soapBindingNode->properties, "transport");
 865                                                 if (tmp) {
 866                                                         if (strncmp((char*)tmp->children->content, WSDL_HTTP_TRANSPORT, sizeof(WSDL_HTTP_TRANSPORT)) == 0) {
 867                                                                 soapBinding->transport = SOAP_TRANSPORT_HTTP;
 868                                                         } else {
 869                                                                 /* try the next binding */
 870                                                                 efree(soapBinding);
 871                                                                 efree(tmpbinding->location);
 872                                                                 efree(tmpbinding);
 873                                                                 trav = trav->next;
 874                                                                 continue;
 875                                                         }
 876                                                 }
 877                                         }
 878                                         tmpbinding->bindingAttributes = (void *)soapBinding;
 879                                 }
 880 
 881                                 name = get_attribute(binding->properties, "name");
 882                                 if (name == NULL) {
 883                                         soap_error0(E_ERROR, "Parsing WSDL: Missing 'name' attribute for <binding>");
 884                                 }
 885                                 tmpbinding->name = estrdup((char*)name->children->content);
 886 
 887                                 type = get_attribute(binding->properties, "type");
 888                                 if (type == NULL) {
 889                                         soap_error0(E_ERROR, "Parsing WSDL: Missing 'type' attribute for <binding>");
 890                                 }
 891 
 892                                 ctype = strrchr((char*)type->children->content,':');
 893                                 if (ctype == NULL) {
 894                                         ctype = (char*)type->children->content;
 895                                 } else {
 896                                         ++ctype;
 897                                 }
 898                                 if (zend_hash_find(&ctx.portTypes, ctype, strlen(ctype)+1, (void**)&tmp) != SUCCESS) {
 899                                         soap_error1(E_ERROR, "Parsing WSDL: Missing <portType> with name '%s'", name->children->content);
 900                                 }
 901                                 portType = *tmp;
 902 
 903                                 trav2 = binding->children;
 904                                 while (trav2 != NULL) {
 905                                         sdlFunctionPtr function;
 906                                         xmlNodePtr input, output, fault, portTypeOperation, trav3;
 907                                         xmlAttrPtr op_name, paramOrder;
 908 
 909                                         if ((tmpbinding->bindingType == BINDING_SOAP &&
 910                                             node_is_equal_ex(trav2, "binding", wsdl_soap_namespace)) ||
 911                                             !is_wsdl_element(trav2) ||
 912                                             node_is_equal(trav2,"documentation")) {
 913                                                 trav2 = trav2->next;
 914                                                 continue;
 915                                         }
 916                                         if (!node_is_equal(trav2,"operation")) {
 917                                                 soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
 918                                         }
 919 
 920                                         operation = trav2;
 921 
 922                                         op_name = get_attribute(operation->properties, "name");
 923                                         if (op_name == NULL) {
 924                                                 soap_error0(E_ERROR, "Parsing WSDL: Missing 'name' attribute for <operation>");
 925                                         }
 926 
 927                                         trav3 = operation->children;
 928                                         while  (trav3 != NULL) {
 929                                                 if (tmpbinding->bindingType == BINDING_SOAP &&
 930                                                     node_is_equal_ex(trav3, "operation", wsdl_soap_namespace)) {
 931                                                 } else if (is_wsdl_element(trav3) &&
 932                                                            !node_is_equal(trav3,"input") &&
 933                                                            !node_is_equal(trav3,"output") &&
 934                                                            !node_is_equal(trav3,"fault") &&
 935                                                            !node_is_equal(trav3,"documentation")) {
 936                                                         soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav3->name);
 937                                                 }
 938                                                 trav3 = trav3->next;
 939                                         }
 940 
 941                                         portTypeOperation = get_node_with_attribute_ex(portType->children, "operation", WSDL_NAMESPACE, "name", (char*)op_name->children->content, NULL);
 942                                         if (portTypeOperation == NULL) {
 943                                                 soap_error1(E_ERROR, "Parsing WSDL: Missing <portType>/<operation> with name '%s'", op_name->children->content);
 944                                         }
 945 
 946                                         function = emalloc(sizeof(sdlFunction));
 947                                         memset(function, 0, sizeof(sdlFunction));
 948                                         function->functionName = estrdup((char*)op_name->children->content);
 949 
 950                                         if (tmpbinding->bindingType == BINDING_SOAP) {
 951                                                 sdlSoapBindingFunctionPtr soapFunctionBinding;
 952                                                 sdlSoapBindingPtr soapBinding;
 953                                                 xmlNodePtr soapOperation;
 954                                                 xmlAttrPtr tmp;
 955 
 956                                                 soapFunctionBinding = emalloc(sizeof(sdlSoapBindingFunction));
 957                                                 memset(soapFunctionBinding, 0, sizeof(sdlSoapBindingFunction));
 958                                                 soapBinding = (sdlSoapBindingPtr)tmpbinding->bindingAttributes;
 959                                                 soapFunctionBinding->style = soapBinding->style;
 960 
 961                                                 soapOperation = get_node_ex(operation->children, "operation", wsdl_soap_namespace);
 962                                                 if (soapOperation) {
 963                                                         tmp = get_attribute(soapOperation->properties, "soapAction");
 964                                                         if (tmp) {
 965                                                                 soapFunctionBinding->soapAction = estrdup((char*)tmp->children->content);
 966                                                         }
 967 
 968                                                         tmp = get_attribute(soapOperation->properties, "style");
 969                                                         if (tmp) {
 970                                                                 if (!strncmp((char*)tmp->children->content, "rpc", sizeof("rpc"))) {
 971                                                                         soapFunctionBinding->style = SOAP_RPC;
 972                                                                 } else {
 973                                                                         soapFunctionBinding->style = SOAP_DOCUMENT;
 974                                                                 }
 975                                                         } else {
 976                                                                 soapFunctionBinding->style = soapBinding->style;
 977                                                         }
 978                                                 }
 979 
 980                                                 function->bindingAttributes = (void *)soapFunctionBinding;
 981                                         }
 982 
 983                                         input = get_node_ex(portTypeOperation->children, "input", WSDL_NAMESPACE);
 984                                         if (input != NULL) {
 985                                                 xmlAttrPtr message, name;
 986 
 987                                                 message = get_attribute(input->properties, "message");
 988                                                 if (message == NULL) {
 989                                                         soap_error1(E_ERROR, "Parsing WSDL: Missing name for <input> of '%s'", op_name->children->content);
 990                                                 }
 991                                                 function->requestParameters = wsdl_message(&ctx, message->children->content);
 992 
 993                                                 name = get_attribute(input->properties, "name");
 994 /* FIXME
 995                                                 if (name != NULL) {
 996                                                         function->requestName = estrdup(name->children->content);
 997                                                 } else {
 998 */
 999                                                 {
1000                                                         function->requestName = estrdup(function->functionName);
1001                                                 }
1002 
1003                                                 if (tmpbinding->bindingType == BINDING_SOAP) {
1004                                                         input = get_node_ex(operation->children, "input", WSDL_NAMESPACE);
1005                                                         if (input != NULL) {
1006                                                                 sdlSoapBindingFunctionPtr soapFunctionBinding = function->bindingAttributes;
1007                                                                 wsdl_soap_binding_body(&ctx, input, wsdl_soap_namespace, &soapFunctionBinding->input, function->requestParameters);
1008                                                         }
1009                                                 }
1010                                         }
1011 
1012                                         output = get_node_ex(portTypeOperation->children, "output", WSDL_NAMESPACE);
1013                                         if (output != NULL) {
1014                                                 xmlAttrPtr message, name;
1015 
1016                                                 message = get_attribute(output->properties, "message");
1017                                                 if (message == NULL) {
1018                                                         soap_error1(E_ERROR, "Parsing WSDL: Missing name for <output> of '%s'", op_name->children->content);
1019                                                 }
1020                                                 function->responseParameters = wsdl_message(&ctx, message->children->content);
1021 
1022                                                 name = get_attribute(output->properties, "name");
1023 /* FIXME
1024                                                 if (name != NULL) {
1025                                                         function->responseName = estrdup(name->children->content);
1026                                                 } else if (input == NULL) {
1027                                                         function->responseName = estrdup(function->functionName);
1028                                                 } else {
1029 */
1030                                                 {
1031                                                         int len = strlen(function->functionName);
1032                                                         function->responseName = emalloc(len + sizeof("Response"));
1033                                                         memcpy(function->responseName, function->functionName, len);
1034                                                         memcpy(function->responseName+len, "Response", sizeof("Response"));
1035                                                 }
1036 
1037                                                 if (tmpbinding->bindingType == BINDING_SOAP) {
1038                                                         output = get_node_ex(operation->children, "output", WSDL_NAMESPACE);
1039                                                         if (output != NULL) {
1040                                                                 sdlSoapBindingFunctionPtr soapFunctionBinding = function->bindingAttributes;
1041                                                                 wsdl_soap_binding_body(&ctx, output, wsdl_soap_namespace, &soapFunctionBinding->output, function->responseParameters);
1042                                                         }
1043                                                 }
1044                                         }
1045 
1046                                         paramOrder = get_attribute(portTypeOperation->properties, "parameterOrder");
1047                                         if (paramOrder) {
1048                                                 /* FIXME: */
1049                                         }
1050 
1051                                         fault = portTypeOperation->children;
1052                                         while (fault != NULL) {
1053                                                 if (node_is_equal_ex(fault, "fault", WSDL_NAMESPACE)) {
1054                                                         xmlAttrPtr message, name;
1055                                                         sdlFaultPtr f;
1056 
1057                                                         name = get_attribute(fault->properties, "name");
1058                                                         if (name == NULL) {
1059                                                                 soap_error1(E_ERROR, "Parsing WSDL: Missing name for <fault> of '%s'", op_name->children->content);
1060                                                         }
1061                                                         message = get_attribute(fault->properties, "message");
1062                                                         if (message == NULL) {
1063                                                                 soap_error1(E_ERROR, "Parsing WSDL: Missing name for <output> of '%s'", op_name->children->content);
1064                                                         }
1065 
1066                                                         f = emalloc(sizeof(sdlFault));
1067                                                         memset(f, 0, sizeof(sdlFault));
1068 
1069                                                         f->name = estrdup((char*)name->children->content);
1070                                                         f->details = wsdl_message(&ctx, message->children->content);
1071                                                         if (f->details == NULL || zend_hash_num_elements(f->details) > 1) {
1072                                                                 soap_error1(E_ERROR, "Parsing WSDL: The fault message '%s' must have a single part", message->children->content);
1073                                                         }
1074 
1075                                                         if (tmpbinding->bindingType == BINDING_SOAP) {
1076                                                                 xmlNodePtr soap_fault = get_node_with_attribute_ex(operation->children, "fault", WSDL_NAMESPACE, "name", f->name, NULL);
1077                                                                 if (soap_fault != NULL) {
1078                                                                         xmlNodePtr trav = soap_fault->children;
1079                                                                         while (trav != NULL) {
1080                                                                                 if (node_is_equal_ex(trav, "fault", wsdl_soap_namespace)) {
1081                                                                                         xmlAttrPtr tmp;
1082                                                                                   sdlSoapBindingFunctionFaultPtr binding;
1083 
1084                                                                                         binding = f->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunctionFault));
1085                                                                                         memset(f->bindingAttributes, 0, sizeof(sdlSoapBindingFunctionFault));
1086 
1087                                                                                         tmp = get_attribute(trav->properties, "use");
1088                                                                                         if (tmp && !strncmp((char*)tmp->children->content, "encoded", sizeof("encoded"))) {
1089                                                                                                 binding->use = SOAP_ENCODED;
1090                                                                                         } else {
1091                                                                                                 binding->use = SOAP_LITERAL;
1092                                                                                         }
1093 
1094                                                                                         tmp = get_attribute(trav->properties, "namespace");
1095                                                                                         if (tmp) {
1096                                                                                                 binding->ns = estrdup((char*)tmp->children->content);
1097                                                                                         }
1098 
1099                                                                                         if (binding->use == SOAP_ENCODED) {
1100                                                                                                 tmp = get_attribute(trav->properties, "encodingStyle");
1101                                                                                                 if (tmp) {
1102                                                                                                         if (strncmp((char*)tmp->children->content, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) {
1103                                                                                                                 binding->encodingStyle = SOAP_ENCODING_1_1;
1104                                                                                                         } else if (strncmp((char*)tmp->children->content, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) {
1105                                                                                                                 binding->encodingStyle = SOAP_ENCODING_1_2;
1106                                                                                                         } else {
1107                                                                                                                 soap_error1(E_ERROR, "Parsing WSDL: Unknown encodingStyle '%s'", tmp->children->content);
1108                                                                                                         }
1109                                                                                                 } else {
1110                                                                                                         soap_error0(E_ERROR, "Parsing WSDL: Unspecified encodingStyle");
1111                                                                                                 }
1112                                                                                         }
1113                                                                                 } else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
1114                                                                                         soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
1115                                                                                 }
1116                                                                                 trav = trav->next;
1117                                                                         }
1118                                                                 }
1119                                                         }
1120                                                         if (function->faults == NULL) {
1121                                                                 function->faults = emalloc(sizeof(HashTable));
1122                                                                 zend_hash_init(function->faults, 0, NULL, delete_fault, 0);
1123                                                         }
1124                                                         if (zend_hash_add(function->faults, f->name, strlen(f->name)+1, (void**)&f, sizeof(sdlFaultPtr), NULL) != SUCCESS) {
1125                                                                 soap_error2(E_ERROR, "Parsing WSDL: <fault> with name '%s' already defined in '%s'", f->name, op_name->children->content);
1126                                                         }
1127                                                 }
1128                                                 fault = fault->next;
1129                                         }
1130 
1131                                         function->binding = tmpbinding;
1132 
1133                                         {
1134                                                 char *tmp = estrdup(function->functionName);
1135                                                 int  len = strlen(tmp);
1136 
1137                                                 if (zend_hash_add(&ctx.sdl->functions, php_strtolower(tmp, len), len+1, &function, sizeof(sdlFunctionPtr), NULL) != SUCCESS) {
1138                                                         zend_hash_next_index_insert(&ctx.sdl->functions, &function, sizeof(sdlFunctionPtr), NULL);
1139                                                 }
1140                                                 efree(tmp);
1141                                                 if (function->requestName != NULL && strcmp(function->requestName,function->functionName) != 0) {
1142                                                         if (ctx.sdl->requests == NULL) {
1143                                                                 ctx.sdl->requests = emalloc(sizeof(HashTable));
1144                                                                 zend_hash_init(ctx.sdl->requests, 0, NULL, NULL, 0);
1145                                                         }
1146                                                         tmp = estrdup(function->requestName);
1147                                                         len = strlen(tmp);
1148                                                         zend_hash_add(ctx.sdl->requests, php_strtolower(tmp, len), len+1, &function, sizeof(sdlFunctionPtr), NULL);
1149                                                         efree(tmp);
1150                                                 }
1151                                         }
1152                                         trav2 = trav2->next;
1153                                 }
1154 
1155                                 if (!ctx.sdl->bindings) {
1156                                         ctx.sdl->bindings = emalloc(sizeof(HashTable));
1157                                         zend_hash_init(ctx.sdl->bindings, 0, NULL, delete_binding, 0);
1158                                 }
1159 
1160                                 if (zend_hash_add(ctx.sdl->bindings, tmpbinding->name, strlen(tmpbinding->name), &tmpbinding, sizeof(sdlBindingPtr), NULL) != SUCCESS) {
1161                                         zend_hash_next_index_insert(ctx.sdl->bindings, &tmpbinding, sizeof(sdlBindingPtr), NULL);
1162                                 }
1163                                 trav= trav->next;
1164                         }
1165 
1166                         zend_hash_move_forward(&ctx.services);
1167                 }
1168         } else {
1169                 soap_error0(E_ERROR, "Parsing WSDL: Couldn't bind to service");
1170         }
1171 
1172         if (ctx.sdl->bindings == NULL || ctx.sdl->bindings->nNumOfElements == 0) {
1173                 soap_error0(E_ERROR, "Parsing WSDL: Could not find any usable binding services in WSDL.");
1174         }
1175 
1176         zend_hash_destroy(&ctx.messages);
1177         zend_hash_destroy(&ctx.bindings);
1178         zend_hash_destroy(&ctx.portTypes);
1179         zend_hash_destroy(&ctx.services);
1180         zend_hash_destroy(&ctx.docs);
1181 
1182         return ctx.sdl;
1183 }
1184 
1185 #define WSDL_CACHE_VERSION 0x0e
1186 
1187 #define WSDL_CACHE_GET(ret,type,buf)   memcpy(&ret,*buf,sizeof(type)); *buf += sizeof(type);
1188 #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;
1189 #define WSDL_CACHE_GET_1(ret,type,buf) ret = (type)(**buf); (*buf)++;
1190 #define WSDL_CACHE_GET_N(ret,n,buf)    memcpy(ret,*buf,n); *buf += n;
1191 #define WSDL_CACHE_SKIP(n,buf)         *buf += n;
1192 
1193 #define WSDL_CACHE_PUT_INT(val,buf)    smart_str_appendc(buf,val & 0xff); \
1194                                        smart_str_appendc(buf,(val >> 8) & 0xff); \
1195                                        smart_str_appendc(buf,(val >> 16) & 0xff); \
1196                                        smart_str_appendc(buf,(val >> 24) & 0xff);
1197 #define WSDL_CACHE_PUT_1(val,buf)      smart_str_appendc(buf,val);
1198 #define WSDL_CACHE_PUT_N(val,n,buf)    smart_str_appendl(buf,(char*)val,n);
1199 
1200 static char* sdl_deserialize_string(char **in)
1201 {
1202         char *s;
1203         int len;
1204 
1205         WSDL_CACHE_GET_INT(len, in);
1206         if (len == 0x7fffffff) {
1207                 return NULL;
1208         } else {
1209                 s = emalloc(len+1);
1210                 WSDL_CACHE_GET_N(s, len, in);
1211                 s[len] = '\0';
1212                 return s;
1213         }
1214 }
1215 
1216 static void sdl_deserialize_key(HashTable* ht, void* data, char **in)
1217 {
1218         int len;
1219 
1220         WSDL_CACHE_GET_INT(len, in);
1221         if (len == 0) {
1222                 zend_hash_next_index_insert(ht, &data, sizeof(void*), NULL);
1223         } else {
1224                 zend_hash_add(ht, *in, len, &data, sizeof(void*), NULL);
1225                 WSDL_CACHE_SKIP(len, in);
1226         }
1227 }
1228 
1229 static void sdl_deserialize_attribute(sdlAttributePtr attr, encodePtr *encoders, char **in)
1230 {
1231         int i;
1232 
1233         attr->name = sdl_deserialize_string(in);
1234         attr->namens = sdl_deserialize_string(in);
1235         attr->ref = sdl_deserialize_string(in);
1236         attr->def = sdl_deserialize_string(in);
1237         attr->fixed = sdl_deserialize_string(in);
1238         WSDL_CACHE_GET_1(attr->form, sdlForm, in);
1239         WSDL_CACHE_GET_1(attr->use, sdlUse, in);
1240         WSDL_CACHE_GET_INT(i, in);
1241         attr->encode = encoders[i];
1242         WSDL_CACHE_GET_INT(i, in);
1243         if (i > 0) {
1244                 attr->extraAttributes = emalloc(sizeof(HashTable));
1245                 zend_hash_init(attr->extraAttributes, i, NULL, delete_extra_attribute, 0);
1246                 while (i > 0) {
1247                         sdlExtraAttributePtr x = emalloc(sizeof(sdlExtraAttribute));
1248                         sdl_deserialize_key(attr->extraAttributes, x, in);
1249                         x->ns = sdl_deserialize_string(in);
1250                         x->val = sdl_deserialize_string(in);
1251                         --i;
1252                 }
1253         }
1254 }
1255 
1256 static sdlRestrictionIntPtr sdl_deserialize_resriction_int(char **in)
1257 {
1258         if (**in == 1) {
1259                 sdlRestrictionIntPtr x = emalloc(sizeof(sdlRestrictionInt));
1260                 WSDL_CACHE_SKIP(1, in);
1261                 WSDL_CACHE_GET_INT(x->value, in);
1262                 WSDL_CACHE_GET_1(x->fixed, char, in);
1263                 return x;
1264         } else {
1265                 WSDL_CACHE_SKIP(1, in);
1266                 return NULL;
1267         }
1268 }
1269 
1270 static sdlRestrictionCharPtr sdl_deserialize_resriction_char(char **in)
1271 {
1272         if (**in == 1) {
1273                 sdlRestrictionCharPtr x = emalloc(sizeof(sdlRestrictionChar));
1274                 WSDL_CACHE_SKIP(1, in);
1275                 x->value = sdl_deserialize_string(in);
1276                 WSDL_CACHE_GET_1(x->fixed, char, in);
1277                 return x;
1278         } else {
1279                 WSDL_CACHE_SKIP(1, in);
1280                 return NULL;
1281         }
1282 }
1283 
1284 static sdlContentModelPtr sdl_deserialize_model(sdlTypePtr *types, sdlTypePtr *elements, char **in)
1285 {
1286         int i;
1287         sdlContentModelPtr model = emalloc(sizeof(sdlContentModel));
1288 
1289         WSDL_CACHE_GET_1(model->kind, sdlContentKind, in);
1290         WSDL_CACHE_GET_INT(model->min_occurs, in);
1291         WSDL_CACHE_GET_INT(model->max_occurs, in);
1292         switch (model->kind) {
1293                 case XSD_CONTENT_ELEMENT:
1294                         WSDL_CACHE_GET_INT(i, in);
1295                         model->u.element = elements[i];
1296                         break;
1297                 case XSD_CONTENT_SEQUENCE:
1298                 case XSD_CONTENT_ALL:
1299                 case XSD_CONTENT_CHOICE:
1300                         WSDL_CACHE_GET_INT(i, in);
1301                         model->u.content = emalloc(sizeof(HashTable));
1302                         zend_hash_init(model->u.content, i, NULL, delete_model, 0);
1303                         while (i > 0) {
1304                                 sdlContentModelPtr x = sdl_deserialize_model(types, elements, in);
1305                                 zend_hash_next_index_insert(model->u.content,&x,sizeof(sdlContentModelPtr),NULL);
1306                                 i--;
1307                         }
1308                         break;
1309                 case XSD_CONTENT_GROUP_REF:
1310                         model->u.group_ref = sdl_deserialize_string(in);
1311                         break;
1312                 case XSD_CONTENT_GROUP:
1313                         WSDL_CACHE_GET_INT(i, in);
1314                         model->u.group = types[i];
1315                         break;
1316                 default:
1317                         break;
1318         }
1319         return model;
1320 }
1321 
1322 static void sdl_deserialize_type(sdlTypePtr type, sdlTypePtr *types, encodePtr *encoders, char **in)
1323 {
1324         int i;
1325         sdlTypePtr *elements = NULL;
1326 
1327         WSDL_CACHE_GET_1(type->kind, sdlTypeKind, in);
1328         type->name = sdl_deserialize_string(in);
1329         type->namens = sdl_deserialize_string(in);
1330         type->def = sdl_deserialize_string(in);
1331         type->fixed = sdl_deserialize_string(in);
1332         type->ref = sdl_deserialize_string(in);
1333         WSDL_CACHE_GET_1(type->nillable, char, in);
1334         WSDL_CACHE_GET_1(type->form, sdlForm, in);
1335 
1336         WSDL_CACHE_GET_INT(i, in);
1337         type->encode = encoders[i];
1338 
1339         if (**in == 1) {
1340                 WSDL_CACHE_SKIP(1, in);
1341                 type->restrictions = emalloc(sizeof(sdlRestrictions));
1342                 /*memset(type->restrictions, 0, sizeof(sdlRestrictions));*/
1343                 type->restrictions->minExclusive = sdl_deserialize_resriction_int(in);
1344                 type->restrictions->minInclusive = sdl_deserialize_resriction_int(in);
1345                 type->restrictions->maxExclusive = sdl_deserialize_resriction_int(in);
1346                 type->restrictions->maxInclusive = sdl_deserialize_resriction_int(in);
1347                 type->restrictions->totalDigits = sdl_deserialize_resriction_int(in);
1348                 type->restrictions->fractionDigits = sdl_deserialize_resriction_int(in);
1349                 type->restrictions->length = sdl_deserialize_resriction_int(in);
1350                 type->restrictions->minLength = sdl_deserialize_resriction_int(in);
1351                 type->restrictions->maxLength = sdl_deserialize_resriction_int(in);
1352                 type->restrictions->whiteSpace = sdl_deserialize_resriction_char(in);
1353                 type->restrictions->pattern = sdl_deserialize_resriction_char(in);
1354                 WSDL_CACHE_GET_INT(i, in);
1355                 if (i > 0) {
1356                         type->restrictions->enumeration = emalloc(sizeof(HashTable));
1357                         zend_hash_init(type->restrictions->enumeration, i, NULL, delete_restriction_var_char, 0);
1358                         while (i > 0) {
1359                                 sdlRestrictionCharPtr x = sdl_deserialize_resriction_char(in);
1360                                 sdl_deserialize_key(type->restrictions->enumeration, x, in);
1361                                 --i;
1362                         }
1363                 } else {
1364                         type->restrictions->enumeration = NULL;
1365                 }
1366         } else {
1367                 WSDL_CACHE_SKIP(1, in);
1368         }
1369 
1370         WSDL_CACHE_GET_INT(i, in);
1371         if (i > 0) {
1372                 elements = safe_emalloc((i+1), sizeof(sdlTypePtr), 0);
1373                 elements[0] = NULL;
1374                 type->elements = emalloc(sizeof(HashTable));
1375                 zend_hash_init(type->elements, i, NULL, delete_type, 0);
1376                 while (i > 0) {
1377                         sdlTypePtr t = emalloc(sizeof(sdlType));
1378                         memset(t, 0, sizeof(sdlType));
1379                         sdl_deserialize_key(type->elements, t, in);
1380                         sdl_deserialize_type(t, types, encoders, in);
1381                         elements[i] = t;
1382                         --i;
1383                 }
1384         }
1385 
1386         WSDL_CACHE_GET_INT(i, in);
1387         if (i > 0) {
1388                 type->attributes = emalloc(sizeof(HashTable));
1389                 zend_hash_init(type->attributes, i, NULL, delete_attribute, 0);
1390                 while (i > 0) {
1391                         sdlAttributePtr attr = emalloc(sizeof(sdlAttribute));
1392                         memset(attr, 0, sizeof(sdlAttribute));
1393                         sdl_deserialize_key(type->attributes, attr, in);
1394                         sdl_deserialize_attribute(attr, encoders, in);
1395                         --i;
1396                 }
1397         }
1398 
1399         if (**in != 0) {
1400                 WSDL_CACHE_SKIP(1, in);
1401                 type->model = sdl_deserialize_model(types, elements, in);
1402         } else {
1403                 WSDL_CACHE_SKIP(1, in);
1404         }
1405         if (elements != NULL) {
1406                 efree(elements);
1407         }
1408 }
1409 
1410 static void sdl_deserialize_encoder(encodePtr enc, sdlTypePtr *types, char **in)
1411 {
1412         int i;
1413 
1414         WSDL_CACHE_GET_INT(enc->details.type, in);
1415         enc->details.type_str = sdl_deserialize_string(in);
1416         enc->details.ns = sdl_deserialize_string(in);
1417         WSDL_CACHE_GET_INT(i, in);
1418         enc->details.sdl_type = types[i];
1419         enc->to_xml = sdl_guess_convert_xml;
1420         enc->to_zval = sdl_guess_convert_zval;
1421 
1422         if (enc->details.sdl_type == NULL) {
1423                 int ns_len = strlen(enc->details.ns);
1424                 int type_len = strlen(enc->details.type_str);
1425 
1426                 if (((ns_len == sizeof(SOAP_1_1_ENC_NAMESPACE)-1 &&
1427                       memcmp(enc->details.ns, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)-1) == 0) ||
1428                      (ns_len == sizeof(SOAP_1_2_ENC_NAMESPACE)-1 &&
1429                       memcmp(enc->details.ns, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)-1) == 0))) {
1430                         char *enc_nscat;
1431                         int enc_ns_len;
1432                         int enc_len;
1433                         encodePtr real_enc;
1434 
1435                         enc_ns_len = sizeof(XSD_NAMESPACE)-1;
1436                         enc_len = enc_ns_len + type_len + 1;
1437                         enc_nscat = emalloc(enc_len + 1);
1438                         memcpy(enc_nscat, XSD_NAMESPACE, sizeof(XSD_NAMESPACE)-1);
1439                         enc_nscat[enc_ns_len] = ':';
1440                         memcpy(enc_nscat+enc_ns_len+1, enc->details.type_str, type_len);
1441                         enc_nscat[enc_len] = '\0';
1442 
1443                         real_enc = get_encoder_ex(NULL, enc_nscat, enc_len);
1444                         efree(enc_nscat);
1445                         if (real_enc) {
1446                                 enc->to_zval = real_enc->to_zval;
1447                                 enc->to_xml = real_enc->to_xml;
1448                         }
1449                 }
1450         }       
1451 }
1452 
1453 static void sdl_deserialize_soap_body(sdlSoapBindingFunctionBodyPtr body, encodePtr *encoders, sdlTypePtr *types, char **in)
1454 {
1455         int i, j, n;
1456 
1457         WSDL_CACHE_GET_1(body->use, sdlEncodingUse, in);
1458         if (body->use == SOAP_ENCODED) {
1459                 WSDL_CACHE_GET_1(body->encodingStyle, sdlRpcEncodingStyle, in);
1460         } else {
1461                 body->encodingStyle = SOAP_ENCODING_DEFAULT;
1462         }
1463         body->ns = sdl_deserialize_string(in);
1464         WSDL_CACHE_GET_INT(i, in);
1465         if (i > 0) {
1466                 body->headers = emalloc(sizeof(HashTable));
1467                 zend_hash_init(body->headers, i, NULL, delete_header, 0);
1468                 while (i > 0) {
1469                         sdlSoapBindingFunctionHeaderPtr tmp = emalloc(sizeof(sdlSoapBindingFunctionHeader));
1470                         memset(tmp, 0, sizeof(sdlSoapBindingFunctionHeader));
1471                         sdl_deserialize_key(body->headers, tmp, in);
1472                         WSDL_CACHE_GET_1(tmp->use, sdlEncodingUse, in);
1473                         if (tmp->use == SOAP_ENCODED) {
1474                                 WSDL_CACHE_GET_1(tmp->encodingStyle, sdlRpcEncodingStyle, in);
1475                         } else {
1476                                 tmp->encodingStyle = SOAP_ENCODING_DEFAULT;
1477                         }
1478                         tmp->name = sdl_deserialize_string(in);
1479                         tmp->ns = sdl_deserialize_string(in);
1480                         WSDL_CACHE_GET_INT(n, in);
1481                         tmp->encode = encoders[n];
1482                         WSDL_CACHE_GET_INT(n, in);
1483                         tmp->element = types[n];
1484                         --i;
1485                         WSDL_CACHE_GET_INT(j, in);
1486                         if (j > 0) {
1487                                 tmp->headerfaults = emalloc(sizeof(HashTable));
1488                                 zend_hash_init(tmp->headerfaults, i, NULL, delete_header, 0);
1489                                 while (j > 0) {
1490                                         sdlSoapBindingFunctionHeaderPtr tmp2 = emalloc(sizeof(sdlSoapBindingFunctionHeader));
1491                                         memset(tmp2, 0, sizeof(sdlSoapBindingFunctionHeader));
1492                                         sdl_deserialize_key(tmp->headerfaults, tmp2, in);
1493                                         WSDL_CACHE_GET_1(tmp2->use, sdlEncodingUse, in);
1494                                         if (tmp2->use == SOAP_ENCODED) {
1495                                                 WSDL_CACHE_GET_1(tmp2->encodingStyle, sdlRpcEncodingStyle, in);
1496                                         } else {
1497                                                 tmp2->encodingStyle = SOAP_ENCODING_DEFAULT;
1498                                         }
1499                                         tmp2->name = sdl_deserialize_string(in);
1500                                         tmp2->ns = sdl_deserialize_string(in);
1501                                         WSDL_CACHE_GET_INT(n, in);
1502                                         tmp2->encode = encoders[n];
1503                                         WSDL_CACHE_GET_INT(n, in);
1504                                         tmp2->element = types[n];
1505                                         --j;
1506                                 }
1507                         }
1508                 }
1509         }
1510 }
1511 
1512 static HashTable* sdl_deserialize_parameters(encodePtr *encoders, sdlTypePtr *types, char **in)
1513 {
1514         int i, n;
1515         HashTable *ht;
1516 
1517         WSDL_CACHE_GET_INT(i, in);
1518         if (i == 0) {return NULL;}
1519         ht = emalloc(sizeof(HashTable));
1520         zend_hash_init(ht, i, NULL, delete_parameter, 0);
1521         while (i > 0) {
1522                 sdlParamPtr param = emalloc(sizeof(sdlParam));
1523                 sdl_deserialize_key(ht, param, in);
1524                 param->paramName = sdl_deserialize_string(in);
1525                 WSDL_CACHE_GET_INT(param->order, in);
1526                 WSDL_CACHE_GET_INT(n, in);
1527                 param->encode = encoders[n];
1528                 WSDL_CACHE_GET_INT(n, in);
1529                 param->element = types[n];
1530                 --i;
1531         }
1532         return ht;
1533 }
1534 
1535 static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t, time_t *cached TSRMLS_DC)
1536 {
1537         sdlPtr sdl;
1538         time_t old_t;
1539         int  i, num_groups, num_types, num_elements, num_encoders, num_bindings, num_func;
1540         sdlFunctionPtr *functions = NULL;
1541         sdlBindingPtr *bindings;
1542         sdlTypePtr *types;
1543         encodePtr *encoders;
1544         encodePtr enc;
1545 
1546         int f;
1547         struct stat st;
1548         char *in, *buf;
1549 
1550         f = open(fn, O_RDONLY|O_BINARY);
1551         if (f < 0) {
1552                 return NULL;
1553         }
1554         if (fstat(f, &st) != 0) {
1555                 close(f);
1556                 return NULL;
1557         }
1558         buf = in = emalloc(st.st_size);
1559         if (read(f, in, st.st_size) != st.st_size) {
1560                 close(f);
1561                 efree(in);
1562                 return NULL;
1563         }
1564         close(f);
1565 
1566         if (strncmp(in,"wsdl",4) != 0 || in[4] != WSDL_CACHE_VERSION || in[5] != '\0') {
1567                 unlink(fn);
1568                 efree(buf);
1569                 return NULL;
1570         }
1571         in += 6;
1572 
1573         WSDL_CACHE_GET(old_t, time_t, &in);
1574         if (old_t < t) {
1575                 unlink(fn);
1576                 efree(buf);
1577                 return NULL;
1578         }
1579         *cached = old_t;
1580 
1581         WSDL_CACHE_GET_INT(i, &in);
1582         if (i == 0 && strncmp(in, uri, i) != 0) {
1583                 unlink(fn);
1584                 efree(buf);
1585                 return NULL;
1586         }
1587         WSDL_CACHE_SKIP(i, &in);
1588 
1589         sdl = emalloc(sizeof(*sdl));
1590         memset(sdl, 0, sizeof(*sdl));
1591 
1592         sdl->source = sdl_deserialize_string(&in);
1593         sdl->target_ns = sdl_deserialize_string(&in);
1594 
1595         WSDL_CACHE_GET_INT(num_groups, &in);
1596         WSDL_CACHE_GET_INT(num_types, &in);
1597         WSDL_CACHE_GET_INT(num_elements, &in);
1598         WSDL_CACHE_GET_INT(num_encoders, &in);
1599 
1600         i = num_groups+num_types+num_elements;
1601         types = safe_emalloc((i+1), sizeof(sdlTypePtr), 0);
1602         types[0] = NULL;
1603         while (i > 0) {
1604                 types[i] = emalloc(sizeof(sdlType));
1605                 memset(types[i], 0, sizeof(sdlType));
1606                 i--;
1607         }
1608 
1609         i = num_encoders;
1610         enc = defaultEncoding;
1611         while (enc->details.type != END_KNOWN_TYPES) {
1612                 i++; enc++;
1613         }
1614         encoders = safe_emalloc((i+1), sizeof(encodePtr), 0);
1615         i = num_encoders;
1616         encoders[0] = NULL;
1617         while (i > 0) {
1618                 encoders[i] = emalloc(sizeof(encode));
1619                 memset(encoders[i], 0, sizeof(encode));
1620                 i--;
1621         }
1622         i = num_encoders;
1623         enc = defaultEncoding;
1624         while (enc->details.type != END_KNOWN_TYPES) {
1625                 encoders[++i] = enc++;
1626         }
1627 
1628         i = 1;
1629         if (num_groups > 0) {
1630                 sdl->groups = emalloc(sizeof(HashTable));
1631                 zend_hash_init(sdl->groups, num_groups, NULL, delete_type, 0);
1632                 while (i < num_groups+1) {
1633                         sdl_deserialize_key(sdl->groups, types[i], &in);
1634                         sdl_deserialize_type(types[i], types, encoders, &in);
1635                         i++;
1636                 }
1637         }
1638 
1639         if (num_types > 0) {
1640                 sdl->types = emalloc(sizeof(HashTable));
1641                 zend_hash_init(sdl->types, num_types, NULL, delete_type, 0);
1642                 while (i < num_groups+num_types+1) {
1643                         sdl_deserialize_key(sdl->types, types[i], &in);
1644                         sdl_deserialize_type(types[i], types, encoders, &in);
1645                         i++;
1646                 }
1647         }
1648 
1649         if (num_elements > 0) {
1650                 sdl->elements = emalloc(sizeof(HashTable));
1651                 zend_hash_init(sdl->elements, num_elements, NULL, delete_type, 0);
1652                 while (i < num_groups+num_types+num_elements+1) {
1653                         sdl_deserialize_key(sdl->elements, types[i], &in);
1654                         sdl_deserialize_type(types[i], types, encoders, &in);
1655                         i++;
1656                 }
1657         }
1658 
1659         i = 1;
1660         if (num_encoders > 0) {
1661                 sdl->encoders = emalloc(sizeof(HashTable));
1662                 zend_hash_init(sdl->encoders, num_encoders, NULL, delete_encoder, 0);
1663                 while (i < num_encoders+1) {
1664                         sdl_deserialize_key(sdl->encoders, encoders[i], &in);
1665                         sdl_deserialize_encoder(encoders[i], types, &in);
1666                         i++;
1667                 }
1668         }
1669 
1670         /* deserialize bindings */
1671         WSDL_CACHE_GET_INT(num_bindings, &in);
1672         bindings = safe_emalloc(num_bindings, sizeof(sdlBindingPtr), 0);
1673         if (num_bindings > 0) {
1674                 sdl->bindings = emalloc(sizeof(HashTable));
1675                 zend_hash_init(sdl->bindings, num_bindings, NULL, delete_binding, 0);
1676                 for (i = 0; i < num_bindings; i++) {
1677                         sdlBindingPtr binding = emalloc(sizeof(sdlBinding));
1678                         memset(binding, 0, sizeof(sdlBinding));
1679                         sdl_deserialize_key(sdl->bindings, binding, &in);
1680                         binding->name = sdl_deserialize_string(&in);
1681                         binding->location = sdl_deserialize_string(&in);
1682                         WSDL_CACHE_GET_1(binding->bindingType,sdlBindingType,&in);
1683                         if (binding->bindingType == BINDING_SOAP && *in != 0) {
1684                           sdlSoapBindingPtr soap_binding = binding->bindingAttributes = emalloc(sizeof(sdlSoapBinding));
1685                                 WSDL_CACHE_GET_1(soap_binding->style,sdlEncodingStyle,&in);
1686                                 WSDL_CACHE_GET_1(soap_binding->transport,sdlTransport,&in);
1687                         } else {
1688                                 WSDL_CACHE_SKIP(1,&in);
1689                         }
1690                         bindings[i] = binding;
1691                 }
1692         }
1693 
1694         /* deserialize functions */
1695         WSDL_CACHE_GET_INT(num_func, &in);
1696         zend_hash_init(&sdl->functions, num_func, NULL, delete_function, 0);
1697         if (num_func > 0) {
1698                 functions = safe_emalloc(num_func, sizeof(sdlFunctionPtr), 0);
1699                 for (i = 0; i < num_func; i++) {
1700                         int binding_num, num_faults;
1701                         sdlFunctionPtr func = emalloc(sizeof(sdlFunction));
1702                         sdl_deserialize_key(&sdl->functions, func, &in);
1703                         func->functionName = sdl_deserialize_string(&in);
1704                         func->requestName = sdl_deserialize_string(&in);
1705                         func->responseName = sdl_deserialize_string(&in);
1706 
1707                         WSDL_CACHE_GET_INT(binding_num, &in);
1708                         if (binding_num == 0) {
1709                                 func->binding = NULL;
1710                         } else {
1711                                 func->binding = bindings[binding_num-1];
1712                         }
1713                         if (func->binding && func->binding->bindingType == BINDING_SOAP && *in != 0) {
1714                                 sdlSoapBindingFunctionPtr binding = func->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunction));
1715                                 memset(binding, 0, sizeof(sdlSoapBindingFunction));
1716                                 WSDL_CACHE_GET_1(binding->style,sdlEncodingStyle,&in);
1717                                 binding->soapAction = sdl_deserialize_string(&in);
1718                                 sdl_deserialize_soap_body(&binding->input, encoders, types, &in);
1719                                 sdl_deserialize_soap_body(&binding->output, encoders, types, &in);
1720                         } else {
1721                                 WSDL_CACHE_SKIP(1, &in);
1722                                 func->bindingAttributes = NULL;
1723                         }
1724 
1725                         func->requestParameters = sdl_deserialize_parameters(encoders, types, &in);
1726                         func->responseParameters = sdl_deserialize_parameters(encoders, types, &in);
1727 
1728                         WSDL_CACHE_GET_INT(num_faults, &in);
1729                         if (num_faults > 0) {
1730                           int j;
1731 
1732                                 func->faults = emalloc(sizeof(HashTable));
1733                                 zend_hash_init(func->faults, num_faults, NULL, delete_fault, 0);
1734 
1735                                 for (j = 0; j < num_faults; j++) {
1736                                         sdlFaultPtr fault = emalloc(sizeof(sdlFault));
1737 
1738                                         sdl_deserialize_key(func->faults, fault, &in);
1739                                         fault->name =sdl_deserialize_string(&in);
1740                                         fault->details =sdl_deserialize_parameters(encoders, types, &in);
1741                                         if (*in != 0) {
1742                                                 sdlSoapBindingFunctionFaultPtr binding = fault->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunctionFault));
1743                                                 memset(binding, 0, sizeof(sdlSoapBindingFunctionFault));
1744                                                 WSDL_CACHE_GET_1(binding->use,sdlEncodingUse,&in);
1745                                                 if (binding->use == SOAP_ENCODED) {
1746                                                         WSDL_CACHE_GET_1(binding->encodingStyle, sdlRpcEncodingStyle, &in);
1747                                                 } else {
1748                                                         binding->encodingStyle = SOAP_ENCODING_DEFAULT;
1749                                                 }
1750                                                 binding->ns = sdl_deserialize_string(&in);
1751                                         } else {
1752                                                 WSDL_CACHE_SKIP(1, &in);
1753                                                 fault->bindingAttributes = NULL;
1754                                         }
1755                                 }
1756                         } else {
1757                                 func->faults = NULL;
1758                         }
1759                         functions[i] = func;
1760                 }
1761         }
1762 
1763         /* deserialize requests */
1764         WSDL_CACHE_GET_INT(i, &in);
1765         if (i > 0) {
1766                 sdl->requests = emalloc(sizeof(HashTable));
1767                 zend_hash_init(sdl->requests, i, NULL, NULL, 0);
1768                 while (i > 0) {
1769                         int function_num;
1770 
1771                         WSDL_CACHE_GET_INT(function_num, &in);
1772                         sdl_deserialize_key(sdl->requests, functions[function_num-1], &in);
1773                         i--;
1774                 }
1775         }
1776 
1777         if (functions) {
1778                 efree(functions);
1779         }
1780         efree(bindings);
1781         efree(encoders);
1782         efree(types);
1783         efree(buf);
1784         return sdl;
1785 }
1786 
1787 static void sdl_serialize_string(const char *str, smart_str *out)
1788 {
1789         int i;
1790 
1791         if (str) {
1792                 i = strlen(str);
1793                 WSDL_CACHE_PUT_INT(i, out);
1794                 if (i > 0) {
1795                         WSDL_CACHE_PUT_N(str, i, out);
1796                 }
1797         } else {
1798                 WSDL_CACHE_PUT_INT(0x7fffffff, out);
1799         }
1800 }
1801 
1802 static void sdl_serialize_key(HashTable *ht, smart_str *out)
1803 {
1804         char *key;
1805         uint  key_len;
1806         ulong index;
1807 
1808         if (zend_hash_get_current_key_ex(ht, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
1809                 WSDL_CACHE_PUT_INT(key_len, out);
1810                 WSDL_CACHE_PUT_N(key, key_len, out);
1811         } else {
1812                 WSDL_CACHE_PUT_INT(0, out);
1813         }
1814 }
1815 
1816 static void sdl_serialize_encoder_ref(encodePtr enc, HashTable *tmp_encoders, smart_str *out) {
1817         if (enc) {
1818                 int *encoder_num;
1819                 if (zend_hash_find(tmp_encoders, (char*)&enc, sizeof(enc), (void**)&encoder_num) == SUCCESS) {
1820                         WSDL_CACHE_PUT_INT(*encoder_num, out);
1821                 } else {
1822                         WSDL_CACHE_PUT_INT(0, out);
1823                 }
1824         } else {
1825                 WSDL_CACHE_PUT_INT(0, out);
1826         }
1827 }
1828 
1829 static void sdl_serialize_type_ref(sdlTypePtr type, HashTable *tmp_types, smart_str *out) {
1830         if (type) {
1831                 int *type_num;
1832                 if (zend_hash_find(tmp_types, (char*)&type, sizeof(type), (void**)&type_num) == SUCCESS) {
1833                         WSDL_CACHE_PUT_INT(*type_num, out);
1834                 } else {
1835                         WSDL_CACHE_PUT_INT(0, out);
1836                 }
1837         } else {
1838                 WSDL_CACHE_PUT_INT(0,out);
1839         }
1840 }
1841 
1842 static void sdl_serialize_attribute(sdlAttributePtr attr, HashTable *tmp_encoders, smart_str *out)
1843 {
1844         int i;
1845 
1846         sdl_serialize_string(attr->name, out);
1847         sdl_serialize_string(attr->namens, out);
1848         sdl_serialize_string(attr->ref, out);
1849         sdl_serialize_string(attr->def, out);
1850         sdl_serialize_string(attr->fixed, out);
1851         WSDL_CACHE_PUT_1(attr->form, out);
1852         WSDL_CACHE_PUT_1(attr->use, out);
1853         sdl_serialize_encoder_ref(attr->encode, tmp_encoders, out);
1854         if (attr->extraAttributes) {
1855                 i = zend_hash_num_elements(attr->extraAttributes);
1856         } else {
1857                 i = 0;
1858         }
1859         WSDL_CACHE_PUT_INT(i, out);
1860         if (i > 0) {
1861                 sdlExtraAttributePtr *tmp;
1862                 zend_hash_internal_pointer_reset(attr->extraAttributes);
1863                 while (zend_hash_get_current_data(attr->extraAttributes, (void**)&tmp) == SUCCESS) {
1864                         sdl_serialize_key(attr->extraAttributes, out);
1865                         sdl_serialize_string((*tmp)->ns, out);
1866                         sdl_serialize_string((*tmp)->val, out);
1867                         zend_hash_move_forward(attr->extraAttributes);
1868                 }
1869         }
1870 }
1871 
1872 static void sdl_serialize_model(sdlContentModelPtr model, HashTable *tmp_types, HashTable *tmp_elements, smart_str *out)
1873 {
1874         WSDL_CACHE_PUT_1(model->kind, out);
1875         WSDL_CACHE_PUT_INT(model->min_occurs, out);
1876         WSDL_CACHE_PUT_INT(model->max_occurs, out);
1877         switch (model->kind) {
1878                 case XSD_CONTENT_ELEMENT:
1879                         sdl_serialize_type_ref(model->u.element, tmp_elements, out);
1880                         break;
1881                 case XSD_CONTENT_SEQUENCE:
1882                 case XSD_CONTENT_ALL:
1883                 case XSD_CONTENT_CHOICE: {
1884                                 sdlContentModelPtr *tmp;
1885                                 int i = zend_hash_num_elements(model->u.content);
1886 
1887                                 WSDL_CACHE_PUT_INT(i, out);
1888                                 zend_hash_internal_pointer_reset(model->u.content);
1889                                 while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
1890                                         sdl_serialize_model(*tmp, tmp_types, tmp_elements, out);
1891                                         zend_hash_move_forward(model->u.content);
1892                                 }
1893                         }
1894                         break;
1895                 case XSD_CONTENT_GROUP_REF:
1896                         sdl_serialize_string(model->u.group_ref,out);
1897                         break;
1898                 case XSD_CONTENT_GROUP:
1899                         sdl_serialize_type_ref(model->u.group, tmp_types, out);
1900                         break;
1901                 default:
1902                         break;
1903         }
1904 }
1905 
1906 static void sdl_serialize_resriction_int(sdlRestrictionIntPtr x, smart_str *out)
1907 {
1908         if (x) {
1909                 WSDL_CACHE_PUT_1(1, out);
1910                 WSDL_CACHE_PUT_INT(x->value, out);
1911                 WSDL_CACHE_PUT_1(x->fixed, out);
1912         } else {
1913                 WSDL_CACHE_PUT_1(0, out);
1914         }
1915 }
1916 
1917 static void sdl_serialize_resriction_char(sdlRestrictionCharPtr x, smart_str *out)
1918 {
1919         if (x) {
1920                 WSDL_CACHE_PUT_1(1, out);
1921                 sdl_serialize_string(x->value, out);
1922                 WSDL_CACHE_PUT_1(x->fixed, out);
1923         } else {
1924                 WSDL_CACHE_PUT_1(0, out);
1925         }
1926 }
1927 
1928 static void sdl_serialize_type(sdlTypePtr type, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
1929 {
1930         int i;
1931         HashTable *tmp_elements = NULL;
1932 
1933         WSDL_CACHE_PUT_1(type->kind, out);
1934         sdl_serialize_string(type->name, out);
1935         sdl_serialize_string(type->namens, out);
1936         sdl_serialize_string(type->def, out);
1937         sdl_serialize_string(type->fixed, out);
1938         sdl_serialize_string(type->ref, out);
1939         WSDL_CACHE_PUT_1(type->nillable, out);
1940         WSDL_CACHE_PUT_1(type->form, out);
1941         sdl_serialize_encoder_ref(type->encode, tmp_encoders, out);
1942 
1943         if (type->restrictions) {
1944                 WSDL_CACHE_PUT_1(1, out);
1945                 sdl_serialize_resriction_int(type->restrictions->minExclusive,out);
1946                 sdl_serialize_resriction_int(type->restrictions->minInclusive,out);
1947                 sdl_serialize_resriction_int(type->restrictions->maxExclusive,out);
1948                 sdl_serialize_resriction_int(type->restrictions->maxInclusive,out);
1949                 sdl_serialize_resriction_int(type->restrictions->totalDigits,out);
1950                 sdl_serialize_resriction_int(type->restrictions->fractionDigits,out);
1951                 sdl_serialize_resriction_int(type->restrictions->length,out);
1952                 sdl_serialize_resriction_int(type->restrictions->minLength,out);
1953                 sdl_serialize_resriction_int(type->restrictions->maxLength,out);
1954                 sdl_serialize_resriction_char(type->restrictions->whiteSpace,out);
1955                 sdl_serialize_resriction_char(type->restrictions->pattern,out);
1956                 if (type->restrictions->enumeration) {
1957                         i = zend_hash_num_elements(type->restrictions->enumeration);
1958                 } else {
1959                         i = 0;
1960                 }
1961                 WSDL_CACHE_PUT_INT(i, out);
1962                 if (i > 0) {
1963                         sdlRestrictionCharPtr *tmp;
1964 
1965                         zend_hash_internal_pointer_reset(type->restrictions->enumeration);
1966                         while (zend_hash_get_current_data(type->restrictions->enumeration, (void**)&tmp) == SUCCESS) {
1967                                 sdl_serialize_resriction_char(*tmp, out);
1968                                 sdl_serialize_key(type->restrictions->enumeration, out);
1969                                 zend_hash_move_forward(type->restrictions->enumeration);
1970                         }
1971                 }
1972         } else {
1973                 WSDL_CACHE_PUT_1(0, out);
1974         }
1975         if (type->elements) {
1976                 i = zend_hash_num_elements(type->elements);
1977         } else {
1978                 i = 0;
1979         }
1980         WSDL_CACHE_PUT_INT(i, out);
1981         if (i > 0) {
1982                 sdlTypePtr *tmp;
1983 
1984                 tmp_elements = emalloc(sizeof(HashTable));
1985                 zend_hash_init(tmp_elements, i, NULL, NULL, 0);
1986 
1987                 zend_hash_internal_pointer_reset(type->elements);
1988                 while (zend_hash_get_current_data(type->elements, (void**)&tmp) == SUCCESS) {
1989                         sdl_serialize_key(type->elements, out);
1990                         sdl_serialize_type(*tmp, tmp_encoders, tmp_types, out);
1991                         zend_hash_add(tmp_elements, (char*)tmp, sizeof(*tmp), &i, sizeof(int), NULL);
1992                         i--;
1993                         zend_hash_move_forward(type->elements);
1994                 }
1995         }
1996 
1997         if (type->attributes) {
1998                 i = zend_hash_num_elements(type->attributes);
1999         } else {
2000                 i = 0;
2001         }
2002         WSDL_CACHE_PUT_INT(i, out);
2003         if (i > 0) {
2004                 sdlAttributePtr *tmp;
2005                 zend_hash_internal_pointer_reset(type->attributes);
2006                 while (zend_hash_get_current_data(type->attributes, (void**)&tmp) == SUCCESS) {
2007                         sdl_serialize_key(type->attributes, out);
2008                         sdl_serialize_attribute(*tmp, tmp_encoders, out);
2009                         zend_hash_move_forward(type->attributes);
2010                 }
2011         }
2012         if (type->model) {
2013                 WSDL_CACHE_PUT_1(1, out);
2014                 sdl_serialize_model(type->model, tmp_types, tmp_elements, out);
2015         } else {
2016                 WSDL_CACHE_PUT_1(0, out);
2017         }
2018         if (tmp_elements != NULL) {
2019                 zend_hash_destroy(tmp_elements);
2020                 efree(tmp_elements);
2021         }
2022 }
2023 
2024 static void sdl_serialize_encoder(encodePtr enc, HashTable *tmp_types, smart_str *out)
2025 {
2026         WSDL_CACHE_PUT_INT(enc->details.type, out);
2027         sdl_serialize_string(enc->details.type_str, out);
2028         sdl_serialize_string(enc->details.ns, out);
2029         sdl_serialize_type_ref(enc->details.sdl_type, tmp_types, out);
2030 }
2031 
2032 static void sdl_serialize_parameters(HashTable *ht, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
2033 {
2034         int i;
2035 
2036         if (ht) {
2037                 i = zend_hash_num_elements(ht);
2038         } else {
2039                 i = 0;
2040         }
2041         WSDL_CACHE_PUT_INT(i, out);
2042         if (i > 0) {
2043                 sdlParamPtr *tmp;
2044 
2045                 zend_hash_internal_pointer_reset(ht);
2046                 while (zend_hash_get_current_data(ht, (void**)&tmp) == SUCCESS) {
2047                         sdl_serialize_key(ht, out);
2048                         sdl_serialize_string((*tmp)->paramName, out);
2049                         WSDL_CACHE_PUT_INT((*tmp)->order, out);
2050                         sdl_serialize_encoder_ref((*tmp)->encode, tmp_encoders, out);
2051                         sdl_serialize_type_ref((*tmp)->element, tmp_types, out);
2052                         zend_hash_move_forward(ht);
2053                 }
2054         }
2055 }
2056 
2057 static void sdl_serialize_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
2058 {
2059         int i, j;
2060 
2061         WSDL_CACHE_PUT_1(body->use, out);
2062         if (body->use == SOAP_ENCODED) {
2063                 WSDL_CACHE_PUT_1(body->encodingStyle, out);
2064         }
2065         sdl_serialize_string(body->ns, out);
2066         if (body->headers) {
2067                 i = zend_hash_num_elements(body->headers);
2068         } else {
2069                 i = 0;
2070         }
2071         WSDL_CACHE_PUT_INT(i, out);
2072         if (i > 0) {
2073                 sdlSoapBindingFunctionHeaderPtr *tmp;
2074                 zend_hash_internal_pointer_reset(body->headers);
2075                 while (zend_hash_get_current_data(body->headers, (void**)&tmp) == SUCCESS) {
2076                         sdl_serialize_key(body->headers, out);
2077                         WSDL_CACHE_PUT_1((*tmp)->use, out);
2078                         if ((*tmp)->use == SOAP_ENCODED) {
2079                                 WSDL_CACHE_PUT_1((*tmp)->encodingStyle, out);
2080                         }
2081                         sdl_serialize_string((*tmp)->name, out);
2082                         sdl_serialize_string((*tmp)->ns, out);
2083                         sdl_serialize_encoder_ref((*tmp)->encode, tmp_encoders, out);
2084                         sdl_serialize_type_ref((*tmp)->element, tmp_types, out);
2085                         if ((*tmp)->headerfaults) {
2086                                 j = zend_hash_num_elements((*tmp)->headerfaults);
2087                         } else {
2088                                 j = 0;
2089                         }
2090                         WSDL_CACHE_PUT_INT(j, out);
2091                         if (j > 0) {
2092                                 sdlSoapBindingFunctionHeaderPtr *tmp2;
2093                                 zend_hash_internal_pointer_reset((*tmp)->headerfaults);
2094                                 while (zend_hash_get_current_data((*tmp)->headerfaults, (void**)&tmp2) == SUCCESS) {
2095                                         sdl_serialize_key((*tmp)->headerfaults, out);
2096                                         WSDL_CACHE_PUT_1((*tmp2)->use, out);
2097                                         if ((*tmp2)->use == SOAP_ENCODED) {
2098                                                 WSDL_CACHE_PUT_1((*tmp2)->encodingStyle, out);
2099                                         }
2100                                         sdl_serialize_string((*tmp2)->name, out);
2101                                         sdl_serialize_string((*tmp2)->ns, out);
2102                                         sdl_serialize_encoder_ref((*tmp2)->encode, tmp_encoders, out);
2103                                         sdl_serialize_type_ref((*tmp2)->element, tmp_types, out);
2104                                         zend_hash_move_forward((*tmp)->headerfaults);
2105                                 }
2106                         }
2107                         zend_hash_move_forward(body->headers);
2108                 }
2109         }
2110 }
2111 
2112 static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr sdl TSRMLS_DC)
2113 {
2114         smart_str buf = {0};
2115         smart_str *out = &buf;
2116         int i;
2117         int type_num = 1;
2118         int encoder_num = 1;
2119         int f;
2120         encodePtr enc;
2121         HashTable tmp_types;
2122         HashTable tmp_encoders;
2123         HashTable tmp_bindings;
2124         HashTable tmp_functions;
2125 
2126 #ifdef ZEND_WIN32
2127         f = open(fn,O_CREAT|O_WRONLY|O_EXCL|O_BINARY,S_IREAD|S_IWRITE);
2128 #else
2129         f = open(fn,O_CREAT|O_WRONLY|O_EXCL|O_BINARY,S_IREAD|S_IWRITE);
2130 #endif
2131         if (f < 0) {return;}
2132 
2133         zend_hash_init(&tmp_types, 0, NULL, NULL, 0);
2134         zend_hash_init(&tmp_encoders, 0, NULL, NULL, 0);
2135         zend_hash_init(&tmp_bindings, 0, NULL, NULL, 0);
2136         zend_hash_init(&tmp_functions, 0, NULL, NULL, 0);
2137 
2138         WSDL_CACHE_PUT_N("wsdl", 4, out);
2139         WSDL_CACHE_PUT_1(WSDL_CACHE_VERSION,out);
2140         WSDL_CACHE_PUT_1(0,out);
2141         WSDL_CACHE_PUT_N(&t, sizeof(t), out);
2142 
2143         sdl_serialize_string(uri, out);
2144         sdl_serialize_string(sdl->source, out);
2145         sdl_serialize_string(sdl->target_ns, out);
2146 
2147         if (sdl->groups) {
2148                 i = zend_hash_num_elements(sdl->groups);
2149         } else {
2150                 i = 0;
2151         }
2152         WSDL_CACHE_PUT_INT(i, out);
2153         if (i > 0) {
2154                 sdlTypePtr *tmp;
2155 
2156                 zend_hash_internal_pointer_reset(sdl->groups);
2157                 while (zend_hash_get_current_data(sdl->groups, (void**)&tmp) == SUCCESS) {
2158                         zend_hash_add(&tmp_types, (char*)tmp, sizeof(*tmp), (void**)&type_num, sizeof(type_num), NULL);
2159                         ++type_num;
2160                         zend_hash_move_forward(sdl->groups);
2161                 }
2162         }
2163 
2164         if (sdl->types) {
2165                 i = zend_hash_num_elements(sdl->types);
2166         } else {
2167                 i = 0;
2168         }
2169         WSDL_CACHE_PUT_INT(i, out);
2170         if (i > 0) {
2171                 sdlTypePtr *tmp;
2172 
2173                 zend_hash_internal_pointer_reset(sdl->types);
2174                 while (zend_hash_get_current_data(sdl->types, (void**)&tmp) == SUCCESS) {
2175                         zend_hash_add(&tmp_types, (char*)tmp, sizeof(*tmp), (void**)&type_num, sizeof(type_num), NULL);
2176                         ++type_num;
2177                         zend_hash_move_forward(sdl->types);
2178                 }
2179         }
2180 
2181         if (sdl->elements) {
2182                 i = zend_hash_num_elements(sdl->elements);
2183         } else {
2184                 i = 0;
2185         }
2186         WSDL_CACHE_PUT_INT(i, out);
2187         if (i > 0) {
2188                 sdlTypePtr *tmp;
2189 
2190                 zend_hash_internal_pointer_reset(sdl->elements);
2191                 while (zend_hash_get_current_data(sdl->elements, (void**)&tmp) == SUCCESS) {
2192                         zend_hash_add(&tmp_types, (char*)tmp, sizeof(*tmp), (void**)&type_num, sizeof(type_num), NULL);
2193                         ++type_num;
2194                         zend_hash_move_forward(sdl->elements);
2195                 }
2196         }
2197 
2198         if (sdl->encoders) {
2199                 i = zend_hash_num_elements(sdl->encoders);
2200         } else {
2201                 i = 0;
2202         }
2203         WSDL_CACHE_PUT_INT(i, out);
2204         if (i > 0) {
2205                 encodePtr *tmp;
2206 
2207                 zend_hash_internal_pointer_reset(sdl->encoders);
2208                 while (zend_hash_get_current_data(sdl->encoders, (void**)&tmp) == SUCCESS) {
2209                         zend_hash_add(&tmp_encoders, (char*)tmp, sizeof(*tmp), (void**)&encoder_num, sizeof(encoder_num), NULL);
2210                         ++encoder_num;
2211                         zend_hash_move_forward(sdl->encoders);
2212                 }
2213         }
2214         enc = defaultEncoding;
2215         while (enc->details.type != END_KNOWN_TYPES) {
2216                 zend_hash_add(&tmp_encoders, (char*)&enc, sizeof(encodePtr), (void**)&encoder_num, sizeof(encoder_num), NULL);
2217                 enc++;
2218                 ++encoder_num;
2219         }
2220 
2221         if (sdl->groups) {
2222                 sdlTypePtr *tmp;
2223                 zend_hash_internal_pointer_reset(sdl->groups);
2224                 while (zend_hash_get_current_data(sdl->groups, (void**)&tmp) == SUCCESS) {
2225                         sdl_serialize_key(sdl->groups, out);
2226                         sdl_serialize_type(*tmp, &tmp_encoders, &tmp_types, out);
2227                         zend_hash_move_forward(sdl->groups);
2228                 }
2229         }
2230 
2231         if (sdl->types) {
2232                 sdlTypePtr *tmp;
2233                 zend_hash_internal_pointer_reset(sdl->types);
2234                 while (zend_hash_get_current_data(sdl->types, (void**)&tmp) == SUCCESS) {
2235                         sdl_serialize_key(sdl->types, out);
2236                         sdl_serialize_type(*tmp, &tmp_encoders, &tmp_types, out);
2237                         zend_hash_move_forward(sdl->types);
2238                 }
2239         }
2240 
2241         if (sdl->elements) {
2242                 sdlTypePtr *tmp;
2243                 zend_hash_internal_pointer_reset(sdl->elements);
2244                 while (zend_hash_get_current_data(sdl->elements, (void**)&tmp) == SUCCESS) {
2245                         sdl_serialize_key(sdl->elements, out);
2246                         sdl_serialize_type(*tmp, &tmp_encoders, &tmp_types, out);
2247                         zend_hash_move_forward(sdl->elements);
2248                 }
2249         }
2250 
2251         if (sdl->encoders) {
2252                 encodePtr *tmp;
2253                 zend_hash_internal_pointer_reset(sdl->encoders);
2254                 while (zend_hash_get_current_data(sdl->encoders, (void**)&tmp) == SUCCESS) {
2255                         sdl_serialize_key(sdl->encoders, out);
2256                         sdl_serialize_encoder(*tmp, &tmp_types, out);
2257                         zend_hash_move_forward(sdl->encoders);
2258                 }
2259         }
2260 
2261         /* serialize bindings */
2262         if (sdl->bindings) {
2263                 i = zend_hash_num_elements(sdl->bindings);
2264         } else {
2265                 i = 0;
2266         }
2267         WSDL_CACHE_PUT_INT(i, out);
2268         if (i > 0) {
2269                 sdlBindingPtr *tmp;
2270                 int binding_num = 1;
2271 
2272                 zend_hash_internal_pointer_reset(sdl->bindings);
2273                 while (zend_hash_get_current_data(sdl->bindings, (void**)&tmp) == SUCCESS) {
2274                         sdl_serialize_key(sdl->bindings, out);
2275                         sdl_serialize_string((*tmp)->name, out);
2276                         sdl_serialize_string((*tmp)->location, out);
2277                         WSDL_CACHE_PUT_1((*tmp)->bindingType,out);
2278                         if ((*tmp)->bindingType == BINDING_SOAP && (*tmp)->bindingAttributes != NULL) {
2279                                 sdlSoapBindingPtr binding = (sdlSoapBindingPtr)(*tmp)->bindingAttributes;
2280                                 WSDL_CACHE_PUT_1(binding->style, out);
2281                                 WSDL_CACHE_PUT_1(binding->transport, out);
2282                         } else {
2283                                 WSDL_CACHE_PUT_1(0,out);
2284                         }
2285 
2286                         zend_hash_add(&tmp_bindings, (char*)tmp, sizeof(*tmp), (void**)&binding_num, sizeof(binding_num), NULL);
2287                         binding_num++;
2288                         zend_hash_move_forward(sdl->bindings);
2289                 }
2290         }
2291 
2292         /* serialize functions */
2293         i = zend_hash_num_elements(&sdl->functions);
2294         WSDL_CACHE_PUT_INT(i, out);
2295         if (i > 0) {
2296                 sdlFunctionPtr *tmp;
2297                 int *binding_num;
2298                 int function_num = 1;
2299 
2300                 zend_hash_internal_pointer_reset(&sdl->functions);
2301                 while (zend_hash_get_current_data(&sdl->functions, (void**)&tmp) == SUCCESS) {
2302                         sdl_serialize_key(&sdl->functions, out);
2303                         sdl_serialize_string((*tmp)->functionName, out);
2304                         sdl_serialize_string((*tmp)->requestName, out);
2305                         sdl_serialize_string((*tmp)->responseName, out);
2306 
2307                         if ((*tmp)->binding == NULL ||
2308                             zend_hash_find(&tmp_bindings,(char*)&(*tmp)->binding,sizeof((*tmp)->binding), (void**)&binding_num) != SUCCESS) {
2309                         }
2310                         WSDL_CACHE_PUT_INT(*binding_num, out);
2311                         if (*binding_num >= 0) {
2312                                 if ((*tmp)->binding->bindingType == BINDING_SOAP && (*tmp)->bindingAttributes != NULL) {
2313                                         sdlSoapBindingFunctionPtr binding = (sdlSoapBindingFunctionPtr)(*tmp)->bindingAttributes;
2314                                         WSDL_CACHE_PUT_1(binding->style, out);
2315                                         sdl_serialize_string(binding->soapAction, out);
2316                                         sdl_serialize_soap_body(&binding->input, &tmp_encoders, &tmp_types, out);
2317                                         sdl_serialize_soap_body(&binding->output, &tmp_encoders, &tmp_types, out);
2318                                 } else {
2319                                         WSDL_CACHE_PUT_1(0,out);
2320                                 }
2321                         }
2322                         sdl_serialize_parameters((*tmp)->requestParameters, &tmp_encoders, &tmp_types, out);
2323                         sdl_serialize_parameters((*tmp)->responseParameters, &tmp_encoders, &tmp_types, out);
2324 
2325                         if ((*tmp)->faults) {
2326                                 sdlFaultPtr *fault;
2327 
2328                                 WSDL_CACHE_PUT_INT(zend_hash_num_elements((*tmp)->faults), out);
2329 
2330                                 zend_hash_internal_pointer_reset((*tmp)->faults);
2331                                 while (zend_hash_get_current_data((*tmp)->faults, (void**)&fault) == SUCCESS) {
2332                                         sdl_serialize_key((*tmp)->faults, out);
2333                                         sdl_serialize_string((*fault)->name, out);
2334                                         sdl_serialize_parameters((*fault)->details, &tmp_encoders, &tmp_types, out);
2335                                         if ((*tmp)->binding->bindingType == BINDING_SOAP && (*fault)->bindingAttributes != NULL) {
2336                                                 sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)(*fault)->bindingAttributes;
2337                                                 WSDL_CACHE_PUT_1(binding->use, out);
2338                                                 if (binding->use == SOAP_ENCODED) {
2339                                                         WSDL_CACHE_PUT_1(binding->encodingStyle, out);
2340                                                 }
2341                                                 sdl_serialize_string(binding->ns, out);
2342                                         } else {
2343                                                 WSDL_CACHE_PUT_1(0, out);
2344                                         }
2345                                         zend_hash_move_forward((*tmp)->faults);
2346                                 }
2347                         } else {
2348                                 WSDL_CACHE_PUT_INT(0, out);
2349                         }
2350 
2351                         zend_hash_add(&tmp_functions, (char*)tmp, sizeof(*tmp), (void**)&function_num, sizeof(function_num), NULL);
2352                         function_num++;
2353                         zend_hash_move_forward(&sdl->functions);
2354                 }
2355         }
2356 
2357         /* serialize requests */
2358         if (sdl->requests) {
2359                 i = zend_hash_num_elements(sdl->requests);
2360         } else {
2361                 i = 0;
2362         }
2363         WSDL_CACHE_PUT_INT(i, out);
2364         if (i > 0) {
2365                 sdlFunctionPtr *tmp;
2366                 int *function_num;
2367 
2368                 zend_hash_internal_pointer_reset(sdl->requests);
2369                 while (zend_hash_get_current_data(sdl->requests, (void**)&tmp) == SUCCESS) {
2370                         if (zend_hash_find(&tmp_functions, (char*)tmp, sizeof(*tmp), (void**)&function_num) != SUCCESS) {
2371                         }
2372                         WSDL_CACHE_PUT_INT(*function_num, out);
2373                         sdl_serialize_key(sdl->requests, out);
2374                         zend_hash_move_forward(sdl->requests);
2375                 }
2376         }
2377 
2378         php_ignore_value(write(f, buf.c, buf.len));
2379         close(f);
2380         smart_str_free(&buf);
2381         zend_hash_destroy(&tmp_functions);
2382         zend_hash_destroy(&tmp_bindings);
2383         zend_hash_destroy(&tmp_encoders);
2384         zend_hash_destroy(&tmp_types);
2385 }
2386 
2387 
2388 static void make_persistent_restriction_int(void *data)
2389 {
2390         sdlRestrictionIntPtr *rest = (sdlRestrictionIntPtr *)data;
2391         sdlRestrictionIntPtr prest = NULL;
2392 
2393         prest = malloc(sizeof(sdlRestrictionInt));
2394         *prest = **rest;
2395         *rest = prest;
2396 }
2397 
2398 
2399 static void make_persistent_restriction_char(void *data)
2400 {
2401         sdlRestrictionCharPtr *rest = (sdlRestrictionCharPtr *)data;
2402         sdlRestrictionCharPtr prest = NULL;
2403 
2404         prest = malloc(sizeof(sdlRestrictionChar));
2405         memset(prest, 0, sizeof(sdlRestrictionChar));
2406         prest->value = strdup((*rest)->value);
2407         prest->fixed = (*rest)->fixed;
2408         *rest = prest;
2409 }
2410 
2411 
2412 static void make_persistent_sdl_type_ref(sdlTypePtr *type, HashTable *ptr_map, HashTable *bp_types)
2413 {
2414         sdlTypePtr *tmp;
2415 
2416         if (zend_hash_find(ptr_map, (char *)type, sizeof(sdlTypePtr), (void**)&tmp) == SUCCESS) {
2417                 *type = *tmp;
2418         } else {
2419                 zend_hash_next_index_insert(bp_types, (void*)&type, sizeof(sdlTypePtr*), NULL);
2420         }
2421 }
2422 
2423 
2424 static void make_persistent_sdl_encoder_ref(encodePtr *enc, HashTable *ptr_map, HashTable *bp_encoders)
2425 {
2426         encodePtr *tmp;
2427 
2428         /* do not process defaultEncoding's here */
2429         if ((*enc) >= defaultEncoding && (*enc) < defaultEncoding + numDefaultEncodings) {
2430                 return;
2431         }
2432 
2433         if (zend_hash_find(ptr_map, (char *)enc, sizeof(encodePtr), (void**)&tmp) == SUCCESS) {
2434                 *enc = *tmp;
2435         } else {
2436                 zend_hash_next_index_insert(bp_encoders, (void*)&enc, sizeof(encodePtr*), NULL);
2437         }
2438 }
2439 
2440 
2441 static HashTable* make_persistent_sdl_function_headers(HashTable *headers, HashTable *ptr_map)
2442 {
2443         HashTable *pheaders;
2444         sdlSoapBindingFunctionHeaderPtr *tmp, pheader;
2445         encodePtr *penc;
2446         sdlTypePtr *ptype;
2447         ulong index;
2448         char *key;
2449         uint key_len;
2450 
2451         pheaders = malloc(sizeof(HashTable));
2452         zend_hash_init(pheaders, zend_hash_num_elements(headers), NULL, delete_header_persistent, 1);
2453 
2454         zend_hash_internal_pointer_reset(headers);
2455         while (zend_hash_get_current_data(headers, (void**)&tmp) == SUCCESS) {
2456                 pheader = malloc(sizeof(sdlSoapBindingFunctionHeader));
2457                 memset(pheader, 0, sizeof(sdlSoapBindingFunctionHeader));
2458                 *pheader = **tmp;
2459 
2460                 if (pheader->name) {
2461                         pheader->name = strdup(pheader->name);
2462                 }
2463                 if (pheader->ns) {
2464                         pheader->ns = strdup(pheader->ns);
2465                 }
2466 
2467                 if (pheader->encode->details.sdl_type) {
2468                         if (zend_hash_find(ptr_map, (char*)&pheader->encode, sizeof(encodePtr), (void**)&penc) == FAILURE) {
2469                                 assert(0);
2470                         }
2471                         pheader->encode = *penc;
2472                 }
2473                 if (pheader->element) {
2474                         if (zend_hash_find(ptr_map, (char*)&pheader->element, sizeof(sdlTypePtr), (void**)&ptype) == FAILURE) {
2475                                 assert(0);
2476                         }
2477                         pheader->element = *ptype;
2478                 }
2479 
2480                 if (pheader->headerfaults) {
2481                         pheader->headerfaults = make_persistent_sdl_function_headers(pheader->headerfaults, ptr_map);
2482                 }
2483 
2484                 if (zend_hash_get_current_key_ex(headers, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2485                         zend_hash_add(pheaders, key, key_len, (void*)&pheader, sizeof(sdlSoapBindingFunctionHeaderPtr), NULL);
2486                 } else {
2487                         zend_hash_next_index_insert(pheaders, (void*)&pheader, sizeof(sdlSoapBindingFunctionHeaderPtr), NULL);
2488                 }
2489 
2490                 zend_hash_move_forward(headers);
2491         }
2492 
2493         return pheaders;
2494 }
2495 
2496 
2497 static void make_persistent_sdl_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTable *ptr_map)
2498 {
2499         if (body->ns) {
2500                 body->ns = strdup(body->ns);
2501         }
2502 
2503         if (body->headers) {
2504                 body->headers = make_persistent_sdl_function_headers(body->headers, ptr_map);
2505         }
2506 }
2507 
2508 
2509 static HashTable* make_persistent_sdl_parameters(HashTable *params, HashTable *ptr_map)
2510 {
2511         HashTable *pparams;
2512         sdlParamPtr *tmp, pparam;
2513         sdlTypePtr *ptype;
2514         encodePtr *penc;
2515         ulong index;
2516         char *key;
2517         uint key_len;
2518 
2519         pparams = malloc(sizeof(HashTable));
2520         zend_hash_init(pparams, zend_hash_num_elements(params), NULL, delete_parameter_persistent, 1);
2521 
2522         zend_hash_internal_pointer_reset(params);
2523         while (zend_hash_get_current_data(params, (void**)&tmp) == SUCCESS) {
2524                 pparam = malloc(sizeof(sdlParam));
2525                 memset(pparam, 0, sizeof(sdlParam));
2526                 *pparam = **tmp;
2527 
2528                 if (pparam->paramName) {
2529                         pparam->paramName = strdup(pparam->paramName);
2530                 }
2531 
2532                 if (pparam->encode && pparam->encode->details.sdl_type) {
2533                         if (zend_hash_find(ptr_map, (char*)&pparam->encode, sizeof(encodePtr), (void**)&penc) == FAILURE) {
2534                                 assert(0);
2535                         }
2536                         pparam->encode = *penc;
2537                 }
2538                 if (pparam->element) {
2539                         if (zend_hash_find(ptr_map, (char*)&pparam->element, sizeof(sdlTypePtr), (void**)&ptype) == FAILURE) {
2540                                 assert(0);
2541                         }
2542                         pparam->element = *ptype;
2543                 }
2544 
2545                 if (zend_hash_get_current_key_ex(params, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2546                         zend_hash_add(pparams, key, key_len, (void*)&pparam, sizeof(sdlParamPtr), NULL);
2547                 } else {
2548                         zend_hash_next_index_insert(pparams, (void*)&pparam, sizeof(sdlParamPtr), NULL);
2549                 }
2550 
2551                 zend_hash_move_forward(params);
2552         }
2553 
2554 
2555         return pparams;
2556 }
2557 
2558 static HashTable* make_persistent_sdl_function_faults(sdlFunctionPtr func, HashTable *faults, HashTable *ptr_map)
2559 {
2560         HashTable *pfaults;
2561         sdlFaultPtr  *tmp, pfault;
2562         ulong index;
2563         char *key;
2564         uint key_len;
2565 
2566         pfaults = malloc(sizeof(HashTable));
2567         zend_hash_init(pfaults, zend_hash_num_elements(faults), NULL, delete_fault_persistent, 1);
2568 
2569         zend_hash_internal_pointer_reset(faults);
2570         while (zend_hash_get_current_data(faults, (void**)&tmp) == SUCCESS) {
2571                 pfault = malloc(sizeof(sdlFault));
2572                 memset(pfault, 0, sizeof(sdlFault));
2573                 *pfault = **tmp;
2574 
2575                 if (pfault->name) {
2576                         pfault->name = strdup(pfault->name);
2577                 }
2578                 if (pfault->details) {
2579                         pfault->details = make_persistent_sdl_parameters(pfault->details, ptr_map);
2580                 }
2581 
2582                 if (func->binding->bindingType == BINDING_SOAP && pfault->bindingAttributes) {
2583                         sdlSoapBindingFunctionFaultPtr soap_binding;
2584 
2585                         soap_binding = malloc(sizeof(sdlSoapBindingFunctionFault));
2586                         memset(soap_binding, 0, sizeof(sdlSoapBindingFunctionFault));
2587                         *soap_binding = *(sdlSoapBindingFunctionFaultPtr)pfault->bindingAttributes;
2588                         if (soap_binding->ns) {
2589                                 soap_binding->ns = strdup(soap_binding->ns);
2590                         }
2591                         pfault->bindingAttributes = soap_binding;
2592                 }
2593 
2594                 if (zend_hash_get_current_key_ex(faults, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2595                         zend_hash_add(pfaults, key, key_len, (void*)&pfault, sizeof(sdlParamPtr), NULL);
2596                 } else {
2597                         zend_hash_next_index_insert(pfaults, (void*)&pfault, sizeof(sdlParamPtr), NULL);
2598                 }
2599 
2600                 zend_hash_move_forward(faults);
2601         }
2602 
2603 
2604         return pfaults;
2605 }
2606 
2607 
2608 static sdlAttributePtr make_persistent_sdl_attribute(sdlAttributePtr attr, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2609 {
2610         sdlAttributePtr pattr;
2611         ulong index;
2612         char *key;
2613         uint key_len;
2614 
2615         pattr = malloc(sizeof(sdlAttribute));
2616         memset(pattr, 0, sizeof(sdlAttribute));
2617 
2618         *pattr = *attr;
2619 
2620         if (pattr->name) {
2621                 pattr->name = strdup(pattr->name);
2622         }
2623         if (pattr->namens) {
2624                 pattr->namens = strdup(pattr->namens);
2625         }
2626         if (pattr->ref) {
2627                 pattr->ref = strdup(pattr->ref);
2628         }
2629         if (pattr->def) {
2630                 pattr->def = strdup(pattr->def);
2631         }
2632         if (pattr->fixed) {
2633                 pattr->fixed = strdup(pattr->fixed);
2634         }
2635 
2636         /* we do not want to process defaultEncoding's here */
2637         if (pattr->encode) {
2638                 make_persistent_sdl_encoder_ref(&pattr->encode, ptr_map, bp_encoders);
2639         }
2640 
2641         if (pattr->extraAttributes) {
2642                 sdlExtraAttributePtr *tmp, pextra;
2643 
2644                 pattr->extraAttributes = malloc(sizeof(HashTable));
2645                 zend_hash_init(pattr->extraAttributes, zend_hash_num_elements(attr->extraAttributes), NULL, delete_extra_attribute_persistent, 1);
2646 
2647                 zend_hash_internal_pointer_reset(pattr->extraAttributes);
2648                 while (zend_hash_get_current_data(attr->extraAttributes, (void**)&tmp) == SUCCESS) {
2649                         if (zend_hash_get_current_key_ex(attr->extraAttributes, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {                       
2650                                 pextra = malloc(sizeof(sdlExtraAttribute));
2651                                 memset(pextra, 0, sizeof(sdlExtraAttribute));
2652 
2653                                 if ((*tmp)->ns) {
2654                                         pextra->ns = strdup((*tmp)->ns);
2655                                 }
2656                                 if ((*tmp)->val) {
2657                                         pextra->val = strdup((*tmp)->val);
2658                                 }
2659                         
2660                                 zend_hash_add(pattr->extraAttributes, key, key_len, (void*)&pextra, sizeof(sdlExtraAttributePtr), NULL);
2661                         }
2662 
2663                         zend_hash_move_forward(attr->extraAttributes);
2664                 }
2665         }
2666 
2667         return pattr;
2668 }
2669 
2670 
2671 static sdlContentModelPtr make_persistent_sdl_model(sdlContentModelPtr model, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2672 {
2673         sdlContentModelPtr pmodel;
2674         sdlContentModelPtr *tmp, pcontent;
2675 
2676         pmodel = malloc(sizeof(sdlContentModel));
2677         memset(pmodel, 0, sizeof(sdlContentModel));
2678         *pmodel = *model;
2679 
2680         switch (pmodel->kind) {
2681                 case XSD_CONTENT_ELEMENT:
2682                         if (pmodel->u.element) {
2683                                 make_persistent_sdl_type_ref(&pmodel->u.element, ptr_map, bp_types);
2684                         }
2685                         break;
2686 
2687                 case XSD_CONTENT_SEQUENCE:
2688                 case XSD_CONTENT_ALL:
2689                 case XSD_CONTENT_CHOICE:
2690                         pmodel->u.content = malloc(sizeof(HashTable));
2691                         zend_hash_init(pmodel->u.content, zend_hash_num_elements(model->u.content), NULL, delete_model_persistent, 1);
2692 
2693                         zend_hash_internal_pointer_reset(model->u.content);
2694                         while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
2695                                 pcontent = make_persistent_sdl_model(*tmp, ptr_map, bp_types, bp_encoders);
2696                                 zend_hash_next_index_insert(pmodel->u.content, (void*)&pcontent, sizeof(sdlContentModelPtr), NULL);
2697                                 zend_hash_move_forward(model->u.content);
2698                         }
2699                         break;
2700 
2701                 case XSD_CONTENT_GROUP_REF:
2702                         if (pmodel->u.group_ref) {
2703                                 pmodel->u.group_ref = strdup(pmodel->u.group_ref);
2704                         }
2705                         break;
2706 
2707                 case XSD_CONTENT_GROUP:
2708                         if (pmodel->u.group) {
2709                                 make_persistent_sdl_type_ref(&pmodel->u.group, ptr_map, bp_types);
2710                         }
2711                         break;
2712 
2713                 default:
2714                         break;
2715         }
2716 
2717         return pmodel;
2718 }
2719 
2720 
2721 static sdlTypePtr make_persistent_sdl_type(sdlTypePtr type, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2722 {
2723         ulong index;
2724         char *key;
2725         uint key_len;
2726         sdlTypePtr ptype = NULL;
2727 
2728         ptype = malloc(sizeof(sdlType));
2729         memset(ptype, 0, sizeof(sdlType));
2730 
2731         *ptype = *type;
2732 
2733         if (ptype->name) {
2734                 ptype->name = strdup(ptype->name);
2735         }
2736         if (ptype->namens) {
2737                 ptype->namens = strdup(ptype->namens);
2738         }
2739         if (ptype->def) {
2740                 ptype->def = strdup(ptype->def);
2741         }
2742         if (ptype->fixed) {
2743                 ptype->fixed = strdup(ptype->fixed);
2744         }
2745         if (ptype->ref) {
2746                 ptype->ref = strdup(ptype->ref);
2747         }
2748 
2749         /* we do not want to process defaultEncoding's here */
2750         if (ptype->encode) {
2751                 make_persistent_sdl_encoder_ref(&ptype->encode, ptr_map, bp_encoders);
2752         }
2753 
2754         if (ptype->restrictions) {
2755                 ptype->restrictions = malloc(sizeof(sdlRestrictions));
2756                 memset(ptype->restrictions, 0, sizeof(sdlRestrictions));
2757                 *ptype->restrictions = *type->restrictions;
2758 
2759                 if (ptype->restrictions->minExclusive) {
2760                         make_persistent_restriction_int(&ptype->restrictions->minExclusive);
2761                 }
2762                 if (ptype->restrictions->maxExclusive) {
2763                         make_persistent_restriction_int(&ptype->restrictions->maxExclusive);
2764                 }
2765                 if (ptype->restrictions->minInclusive) {
2766                         make_persistent_restriction_int(&ptype->restrictions->minInclusive);
2767                 }
2768                 if (ptype->restrictions->maxInclusive) {
2769                         make_persistent_restriction_int(&ptype->restrictions->maxInclusive);
2770                 }
2771                 if (ptype->restrictions->totalDigits) {
2772                         make_persistent_restriction_int(&ptype->restrictions->totalDigits);
2773                 }
2774                 if (ptype->restrictions->fractionDigits) {
2775                         make_persistent_restriction_int(&ptype->restrictions->fractionDigits);
2776                 }
2777                 if (ptype->restrictions->length) {
2778                         make_persistent_restriction_int(&ptype->restrictions->length);
2779                 }
2780                 if (ptype->restrictions->minLength) {
2781                         make_persistent_restriction_int(&ptype->restrictions->minLength);
2782                 }
2783                 if (ptype->restrictions->maxLength) {
2784                         make_persistent_restriction_int(&ptype->restrictions->maxLength);
2785                 }
2786                 if (ptype->restrictions->whiteSpace) {
2787                         make_persistent_restriction_char(&ptype->restrictions->whiteSpace);
2788                 }
2789                 if (ptype->restrictions->pattern) {
2790                         make_persistent_restriction_char(&ptype->restrictions->pattern);
2791                 }
2792 
2793                 if (type->restrictions->enumeration) {
2794                         sdlRestrictionCharPtr tmp;
2795 
2796                         ptype->restrictions->enumeration = malloc(sizeof(HashTable));
2797                         zend_hash_init(ptype->restrictions->enumeration, zend_hash_num_elements(type->restrictions->enumeration), NULL, delete_restriction_var_char_persistent, 1);
2798                         zend_hash_copy(ptype->restrictions->enumeration, type->restrictions->enumeration, make_persistent_restriction_char, (void*)&tmp, sizeof(sdlRestrictionCharPtr));
2799                 }
2800         }
2801 
2802         if (ptype->elements) {
2803                 sdlTypePtr *tmp, pelem;
2804 
2805                 ptype->elements = malloc(sizeof(HashTable));
2806                 zend_hash_init(ptype->elements, zend_hash_num_elements(type->elements), NULL, delete_type_persistent, 1);
2807 
2808                 zend_hash_internal_pointer_reset(type->elements);
2809                 while (zend_hash_get_current_data(type->elements, (void **)&tmp) == SUCCESS) {
2810                         pelem = make_persistent_sdl_type(*tmp, ptr_map, bp_types, bp_encoders);
2811                         if (zend_hash_get_current_key_ex(type->elements, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2812                                 zend_hash_add(ptype->elements, key, key_len, (void*)&pelem, sizeof(sdlTypePtr), NULL);
2813                         } else {
2814                                 zend_hash_next_index_insert(ptype->elements, (void*)&pelem, sizeof(sdlTypePtr), NULL);
2815                         }
2816                         zend_hash_add(ptr_map, (char*)tmp, sizeof(*tmp), (void*)&pelem, sizeof(sdlTypePtr), NULL);
2817                         zend_hash_move_forward(type->elements);
2818                 }
2819         }
2820 
2821         if (ptype->attributes) {
2822                 sdlAttributePtr *tmp, pattr;
2823 
2824                 ptype->attributes = malloc(sizeof(HashTable));
2825                 zend_hash_init(ptype->attributes, zend_hash_num_elements(type->attributes), NULL, delete_attribute_persistent, 1);
2826 
2827                 zend_hash_internal_pointer_reset(type->attributes);
2828                 while (zend_hash_get_current_data(type->attributes, (void **)&tmp) == SUCCESS) {
2829                         pattr = make_persistent_sdl_attribute(*tmp, ptr_map, bp_types, bp_encoders);
2830                         if (zend_hash_get_current_key_ex(type->attributes, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2831                                 zend_hash_add(ptype->attributes, key, key_len, (void*)&pattr, sizeof(sdlAttributePtr), NULL);
2832                         } else {
2833                                 zend_hash_next_index_insert(ptype->attributes, (void*)&pattr, sizeof(sdlAttributePtr), NULL);
2834                         }
2835                         zend_hash_move_forward(type->attributes);
2836                 }
2837         }
2838 
2839         if (type->model) {
2840                 ptype->model = make_persistent_sdl_model(ptype->model, ptr_map, bp_types, bp_encoders);
2841         }
2842 
2843         return ptype;
2844 }
2845 
2846 static encodePtr make_persistent_sdl_encoder(encodePtr enc, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2847 {
2848         encodePtr penc = NULL;
2849 
2850         penc = malloc(sizeof(encode));
2851         memset(penc, 0, sizeof(encode));
2852 
2853         *penc = *enc;
2854 
2855         if (penc->details.type_str) {
2856                 penc->details.type_str = strdup(penc->details.type_str);
2857         }
2858         if (penc->details.ns) {
2859                 penc->details.ns = strdup(penc->details.ns);
2860         }
2861 
2862         if (penc->details.sdl_type) {
2863                 make_persistent_sdl_type_ref(&penc->details.sdl_type, ptr_map, bp_types);
2864         }
2865 
2866         return penc;
2867 }
2868 
2869 static sdlBindingPtr make_persistent_sdl_binding(sdlBindingPtr bind, HashTable *ptr_map)
2870 {
2871         sdlBindingPtr pbind = NULL;
2872 
2873         pbind = malloc(sizeof(sdlBinding));
2874         memset(pbind, 0, sizeof(sdlBinding));
2875 
2876         *pbind = *bind;
2877 
2878         if (pbind->name) {
2879                 pbind->name = strdup(pbind->name);
2880         }
2881         if (pbind->location) {
2882                 pbind->location = strdup(pbind->location);
2883         }
2884 
2885         if (pbind->bindingType == BINDING_SOAP && pbind->bindingAttributes) {
2886                 sdlSoapBindingPtr soap_binding;
2887            
2888                 soap_binding = malloc(sizeof(sdlSoapBinding));
2889                 memset(soap_binding, 0, sizeof(sdlSoapBinding));
2890                 *soap_binding = *(sdlSoapBindingPtr)pbind->bindingAttributes;
2891                 pbind->bindingAttributes = soap_binding;
2892         }
2893 
2894         return pbind;
2895 }
2896 
2897 static sdlFunctionPtr make_persistent_sdl_function(sdlFunctionPtr func, HashTable *ptr_map)
2898 {
2899         sdlFunctionPtr pfunc = NULL;
2900 
2901         pfunc = malloc(sizeof(sdlFunction));
2902         memset(pfunc, 0, sizeof(sdlFunction));
2903 
2904         *pfunc = *func;
2905 
2906         if (pfunc->functionName) {
2907                 pfunc->functionName = strdup(pfunc->functionName);
2908         }
2909         if (pfunc->requestName) {
2910                 pfunc->requestName = strdup(pfunc->requestName);
2911         }
2912         if (pfunc->responseName) {
2913                 pfunc->responseName = strdup(pfunc->responseName);
2914         }
2915 
2916         if (pfunc->binding) {
2917                 sdlBindingPtr *tmp;
2918 
2919                 if (zend_hash_find(ptr_map, (char*)&pfunc->binding, sizeof(pfunc->binding), (void**)&tmp) == FAILURE) {
2920                         assert(0);
2921                 }
2922                 pfunc->binding = *tmp;
2923                 
2924                 if (pfunc->binding->bindingType == BINDING_SOAP && pfunc->bindingAttributes) {
2925                         sdlSoapBindingFunctionPtr soap_binding;
2926 
2927                         soap_binding = malloc(sizeof(sdlSoapBindingFunction));
2928                         memset(soap_binding, 0, sizeof(sdlSoapBindingFunction));
2929                         *soap_binding = *(sdlSoapBindingFunctionPtr)pfunc->bindingAttributes;
2930                         if (soap_binding->soapAction) {
2931                                 soap_binding->soapAction = strdup(soap_binding->soapAction);
2932                         }
2933                         make_persistent_sdl_soap_body(&soap_binding->input, ptr_map);
2934                         make_persistent_sdl_soap_body(&soap_binding->output, ptr_map);
2935                         pfunc->bindingAttributes = soap_binding;
2936                 }
2937 
2938                 if (pfunc->requestParameters) {
2939                         pfunc->requestParameters = make_persistent_sdl_parameters(pfunc->requestParameters, ptr_map);
2940                 }
2941                 if (pfunc->responseParameters) {
2942                         pfunc->responseParameters = make_persistent_sdl_parameters(pfunc->responseParameters, ptr_map);
2943                 }
2944                 if (pfunc->faults) {
2945                         pfunc->faults = make_persistent_sdl_function_faults(pfunc, pfunc->faults, ptr_map);
2946                 }
2947         }
2948 
2949         return pfunc;
2950 }
2951 
2952 static sdlPtr make_persistent_sdl(sdlPtr sdl TSRMLS_DC)
2953 {
2954         sdlPtr psdl = NULL;
2955         HashTable ptr_map;
2956         HashTable bp_types, bp_encoders;
2957         ulong index;
2958         char *key;
2959         uint key_len;
2960 
2961         zend_hash_init(&bp_types, 0, NULL, NULL, 0);
2962         zend_hash_init(&bp_encoders, 0, NULL, NULL, 0);
2963         zend_hash_init(&ptr_map, 0, NULL, NULL, 0);
2964 
2965         psdl = malloc(sizeof(*sdl));
2966         memset(psdl, 0, sizeof(*sdl));
2967 
2968         if (sdl->source) {
2969                 psdl->source = strdup(sdl->source);
2970         }
2971         if (sdl->target_ns) {
2972                 psdl->target_ns = strdup(sdl->target_ns);
2973         }
2974 
2975         if (sdl->groups) {
2976                 sdlTypePtr *tmp;
2977                 sdlTypePtr ptype;
2978 
2979                 psdl->groups = malloc(sizeof(HashTable));
2980                 zend_hash_init(psdl->groups, zend_hash_num_elements(sdl->groups), NULL, delete_type_persistent, 1);
2981 
2982                 zend_hash_internal_pointer_reset(sdl->groups);
2983                 while (zend_hash_get_current_data(sdl->groups, (void **)&tmp) == SUCCESS) {
2984                         ptype = make_persistent_sdl_type(*tmp, &ptr_map, &bp_types, &bp_encoders);
2985                         if (zend_hash_get_current_key_ex(sdl->groups, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
2986                                 zend_hash_add(psdl->groups, key, key_len, (void*)&ptype, sizeof(sdlTypePtr), NULL);
2987                         } else {
2988                                 zend_hash_next_index_insert(psdl->groups, (void*)&ptype, sizeof(sdlTypePtr), NULL);
2989                         }
2990                         zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&ptype, sizeof(sdlTypePtr), NULL);
2991                         zend_hash_move_forward(sdl->groups);
2992                 }
2993         }
2994 
2995         if (sdl->types) {
2996                 sdlTypePtr *tmp;
2997                 sdlTypePtr ptype;
2998 
2999                 psdl->types = malloc(sizeof(HashTable));
3000                 zend_hash_init(psdl->types, zend_hash_num_elements(sdl->types), NULL, delete_type_persistent, 1);
3001 
3002                 zend_hash_internal_pointer_reset(sdl->types);
3003                 while (zend_hash_get_current_data(sdl->types, (void **)&tmp) == SUCCESS) {
3004                         ptype = make_persistent_sdl_type(*tmp, &ptr_map, &bp_types, &bp_encoders);
3005                         if (zend_hash_get_current_key_ex(sdl->types, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3006                                 zend_hash_add(psdl->types, key, key_len, (void*)&ptype, sizeof(sdlTypePtr), NULL);
3007                         } else {
3008                                 zend_hash_next_index_insert(psdl->types, (void*)&ptype, sizeof(sdlTypePtr), NULL);
3009                         }
3010                         zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&ptype, sizeof(sdlTypePtr), NULL);
3011                         zend_hash_move_forward(sdl->types);
3012                 }
3013         }
3014 
3015         if (sdl->elements) {
3016                 sdlTypePtr *tmp;
3017                 sdlTypePtr ptype;
3018 
3019                 psdl->elements = malloc(sizeof(HashTable));
3020                 zend_hash_init(psdl->elements, zend_hash_num_elements(sdl->elements), NULL, delete_type_persistent, 1);
3021 
3022                 zend_hash_internal_pointer_reset(sdl->elements);
3023                 while (zend_hash_get_current_data(sdl->elements, (void **)&tmp) == SUCCESS) {
3024                         ptype = make_persistent_sdl_type(*tmp, &ptr_map, &bp_types, &bp_encoders);
3025                         if (zend_hash_get_current_key_ex(sdl->elements, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3026                                 zend_hash_add(psdl->elements, key, key_len, (void*)&ptype, sizeof(sdlTypePtr), NULL);
3027                         } else {
3028                                 zend_hash_next_index_insert(psdl->elements, (void*)&ptype, sizeof(sdlTypePtr), NULL);
3029                         }
3030                         zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&ptype, sizeof(sdlTypePtr), NULL);
3031                         zend_hash_move_forward(sdl->elements);
3032                 }
3033         }
3034 
3035         if (sdl->encoders) {
3036                 encodePtr *tmp;
3037                 encodePtr penc;
3038 
3039                 psdl->encoders = malloc(sizeof(HashTable));
3040                 zend_hash_init(psdl->encoders, zend_hash_num_elements(sdl->encoders), NULL, delete_encoder_persistent, 1);
3041 
3042                 zend_hash_internal_pointer_reset(sdl->encoders);
3043                 while (zend_hash_get_current_data(sdl->encoders, (void **)&tmp) == SUCCESS) {
3044                         penc = make_persistent_sdl_encoder(*tmp, &ptr_map, &bp_types, &bp_encoders);
3045                         if (zend_hash_get_current_key_ex(sdl->encoders, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3046                                 zend_hash_add(psdl->encoders, key, key_len, (void*)&penc, sizeof(encodePtr), NULL);
3047                         } else {
3048                                 zend_hash_next_index_insert(psdl->encoders, (void*)&penc, sizeof(encodePtr), NULL);
3049                         }
3050                         zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&penc, sizeof(encodePtr), NULL);
3051                         zend_hash_move_forward(sdl->encoders);
3052                 }
3053         }
3054 
3055         /* do backpatching here */
3056         if (zend_hash_num_elements(&bp_types)) {
3057                 sdlTypePtr **tmp, *ptype = NULL;
3058 
3059                 zend_hash_internal_pointer_reset(&bp_types);
3060                 while (zend_hash_get_current_data(&bp_types, (void**)&tmp) == SUCCESS) {
3061                         if (zend_hash_find(&ptr_map, (char*)(*tmp), sizeof(**tmp), (void**)&ptype) == FAILURE) {
3062                                 assert(0);
3063                         }
3064                         **tmp = *ptype;
3065                         zend_hash_move_forward(&bp_types);
3066                 }
3067         }
3068         if (zend_hash_num_elements(&bp_encoders)) {
3069                 encodePtr **tmp, *penc = NULL;
3070 
3071                 zend_hash_internal_pointer_reset(&bp_encoders);
3072                 while (zend_hash_get_current_data(&bp_encoders, (void**)&tmp) == SUCCESS) {
3073                         if (zend_hash_find(&ptr_map, (char*)(*tmp), sizeof(**tmp), (void**)&penc) == FAILURE) {
3074                                 assert(0);
3075                         }
3076                         **tmp = *penc;
3077                         zend_hash_move_forward(&bp_encoders);
3078                 }
3079         }
3080 
3081 
3082         if (sdl->bindings) {
3083                 sdlBindingPtr *tmp;
3084                 sdlBindingPtr pbind;
3085 
3086                 psdl->bindings = malloc(sizeof(HashTable));
3087                 zend_hash_init(psdl->bindings, zend_hash_num_elements(sdl->bindings), NULL, delete_binding_persistent, 1);
3088 
3089                 zend_hash_internal_pointer_reset(sdl->bindings);
3090                 while (zend_hash_get_current_data(sdl->bindings, (void **)&tmp) == SUCCESS) {
3091                         pbind = make_persistent_sdl_binding(*tmp, &ptr_map);
3092                         if (zend_hash_get_current_key_ex(sdl->bindings, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3093                                 zend_hash_add(psdl->bindings, key, key_len, (void*)&pbind, sizeof(sdlBindingPtr), NULL);
3094                         } else {
3095                                 zend_hash_next_index_insert(psdl->bindings, (void*)&pbind, sizeof(sdlBindingPtr), NULL);
3096                         }
3097                         zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&pbind, sizeof(sdlBindingPtr), NULL);
3098                         zend_hash_move_forward(sdl->bindings);
3099                 }
3100         }
3101 
3102         zend_hash_init(&psdl->functions, zend_hash_num_elements(&sdl->functions), NULL, delete_function_persistent, 1);
3103         if (zend_hash_num_elements(&sdl->functions)) {
3104                 sdlFunctionPtr *tmp;
3105                 sdlFunctionPtr pfunc;
3106 
3107                 zend_hash_internal_pointer_reset(&sdl->functions);
3108                 while (zend_hash_get_current_data(&sdl->functions, (void **)&tmp) == SUCCESS) {
3109                         pfunc = make_persistent_sdl_function(*tmp, &ptr_map);
3110                         if (zend_hash_get_current_key_ex(&sdl->functions, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3111                                 zend_hash_add(&psdl->functions, key, key_len, (void*)&pfunc, sizeof(sdlFunctionPtr), NULL);
3112                         } else {
3113                                 zend_hash_next_index_insert(&psdl->functions, (void*)&pfunc, sizeof(sdlFunctionPtr), NULL);
3114                         }
3115                         zend_hash_add(&ptr_map, (char*)tmp, sizeof(*tmp), (void*)&pfunc, sizeof(sdlFunctionPtr), NULL);
3116                         zend_hash_move_forward(&sdl->functions);
3117                 }
3118         }
3119 
3120         if (sdl->requests) {
3121                 sdlFunctionPtr *tmp;
3122                 sdlFunctionPtr *preq;
3123 
3124                 psdl->requests = malloc(sizeof(HashTable));
3125                 zend_hash_init(psdl->requests, zend_hash_num_elements(sdl->requests), NULL, NULL, 1);
3126 
3127                 zend_hash_internal_pointer_reset(sdl->requests);
3128                 while (zend_hash_get_current_data(sdl->requests, (void **)&tmp) == SUCCESS) {
3129                         if (zend_hash_find(&ptr_map, (char*)tmp, sizeof(*tmp), (void**)&preq) == FAILURE) {
3130                                 assert(0);
3131                         }
3132                         *tmp = *preq;
3133                         if (zend_hash_get_current_key_ex(sdl->requests, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
3134                                 zend_hash_add(psdl->requests, key, key_len, (void*)&preq, sizeof(sdlFunctionPtr), NULL);
3135                         }
3136                         zend_hash_move_forward(sdl->requests);
3137                 }
3138         }
3139 
3140         zend_hash_destroy(&ptr_map);
3141         zend_hash_destroy(&bp_encoders);
3142         zend_hash_destroy(&bp_types);
3143 
3144         return psdl;
3145 }
3146 
3147 typedef struct _sdl_cache_bucket {
3148         sdlPtr sdl;
3149         time_t time;
3150 } sdl_cache_bucket;
3151 
3152 static void delete_psdl(void *data)
3153 {
3154         sdl_cache_bucket *p = (sdl_cache_bucket*)data;
3155         sdlPtr tmp = p->sdl;
3156 
3157         zend_hash_destroy(&tmp->functions);
3158         if (tmp->source) {
3159                 free(tmp->source);
3160         }
3161         if (tmp->target_ns) {
3162                 free(tmp->target_ns);
3163         }
3164         if (tmp->elements) {
3165                 zend_hash_destroy(tmp->elements);
3166                 free(tmp->elements);
3167         }
3168         if (tmp->encoders) {
3169                 zend_hash_destroy(tmp->encoders);
3170                 free(tmp->encoders);
3171         }
3172         if (tmp->types) {
3173                 zend_hash_destroy(tmp->types);
3174                 free(tmp->types);
3175         }
3176         if (tmp->groups) {
3177                 zend_hash_destroy(tmp->groups);
3178                 free(tmp->groups);
3179         }
3180         if (tmp->bindings) {
3181                 zend_hash_destroy(tmp->bindings);
3182                 free(tmp->bindings);
3183         }
3184         if (tmp->requests) {
3185                 zend_hash_destroy(tmp->requests);
3186                 free(tmp->requests);
3187         }
3188         free(tmp);
3189 }
3190 
3191 sdlPtr get_sdl(zval *this_ptr, char *uri, long cache_wsdl TSRMLS_DC)
3192 {
3193         char  fn[MAXPATHLEN];
3194         sdlPtr sdl = NULL;
3195         char* old_error_code = SOAP_GLOBAL(error_code);
3196         int uri_len = 0;
3197         php_stream_context *context=NULL;
3198         zval **tmp, **proxy_host, **proxy_port, *orig_context = NULL, *new_context = NULL;
3199         smart_str headers = {0};
3200         char* key = NULL;
3201         time_t t = time(0);
3202         zend_bool has_proxy_authorization = 0;
3203         zend_bool has_authorization = 0;
3204 
3205         if (strchr(uri,':') != NULL || IS_ABSOLUTE_PATH(uri, uri_len)) {
3206                 uri_len = strlen(uri);
3207         } else if (VCWD_REALPATH(uri, fn) == NULL) {
3208                 cache_wsdl = WSDL_CACHE_NONE;
3209         } else {
3210                 uri = fn;
3211                 uri_len = strlen(uri);
3212         }
3213 
3214         if ((cache_wsdl & WSDL_CACHE_MEMORY) && SOAP_GLOBAL(mem_cache)) {
3215                 sdl_cache_bucket *p;
3216 
3217                 if (SUCCESS == zend_hash_find(SOAP_GLOBAL(mem_cache), uri, uri_len+1, (void*)&p)) {
3218                         if (p->time < t - SOAP_GLOBAL(cache_ttl)) {
3219                                 /* in-memory cache entry is expired */
3220                                 zend_hash_del(&EG(persistent_list), uri, uri_len+1);
3221                         } else {
3222                                 return p->sdl;
3223                         }
3224                 }
3225         }
3226 
3227         if ((cache_wsdl & WSDL_CACHE_DISK) && (uri_len < MAXPATHLEN)) {
3228                 time_t t = time(0);
3229                 char md5str[33];
3230                 PHP_MD5_CTX context;
3231                 unsigned char digest[16];
3232                 int len = strlen(SOAP_GLOBAL(cache_dir));
3233                 time_t cached;
3234                 char *user = php_get_current_user(TSRMLS_C);
3235                 int user_len = user ? strlen(user) + 1 : 0;
3236 
3237                 md5str[0] = '\0';
3238                 PHP_MD5Init(&context);
3239                 PHP_MD5Update(&context, (unsigned char*)uri, uri_len);
3240                 PHP_MD5Final(digest, &context);
3241                 make_digest(md5str, digest);
3242                 key = emalloc(len+sizeof("/wsdl-")-1+user_len+sizeof(md5str));
3243                 memcpy(key,SOAP_GLOBAL(cache_dir),len);
3244                 memcpy(key+len,"/wsdl-",sizeof("/wsdl-")-1);
3245                 len += sizeof("/wsdl-")-1;
3246                 if (user_len) {
3247                         memcpy(key+len, user, user_len-1);
3248                         len += user_len-1;
3249                         key[len++] = '-';
3250                 }
3251                 memcpy(key+len,md5str,sizeof(md5str));
3252 
3253                 if ((sdl = get_sdl_from_cache(key, uri, t-SOAP_GLOBAL(cache_ttl), &cached TSRMLS_CC)) != NULL) {
3254                         t = cached;
3255                         efree(key);
3256                         goto cache_in_memory;
3257                 }
3258         }
3259 
3260         if (SUCCESS == zend_hash_find(Z_OBJPROP_P(this_ptr),
3261                         "_stream_context", sizeof("_stream_context"), (void**)&tmp)) {
3262                 context = php_stream_context_from_zval(*tmp, 0);
3263         } else {
3264                 context = php_stream_context_alloc(TSRMLS_C);
3265         }
3266 
3267         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_user_agent", sizeof("_user_agent"), (void **) &tmp) == SUCCESS &&
3268             Z_TYPE_PP(tmp) == IS_STRING && Z_STRLEN_PP(tmp) > 0) {      
3269                 smart_str_appends(&headers, "User-Agent: ");
3270                 smart_str_appends(&headers, Z_STRVAL_PP(tmp));
3271                 smart_str_appends(&headers, "\r\n");
3272         }
3273 
3274         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_host", sizeof("_proxy_host"), (void **) &proxy_host) == SUCCESS &&
3275             Z_TYPE_PP(proxy_host) == IS_STRING &&
3276             zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_port", sizeof("_proxy_port"), (void **) &proxy_port) == SUCCESS &&
3277             Z_TYPE_PP(proxy_port) == IS_LONG) {
3278                 zval str_port, *str_proxy;
3279                 smart_str proxy = {0};
3280                 str_port = **proxy_port;
3281                 zval_copy_ctor(&str_port);
3282                 convert_to_string(&str_port);
3283                 smart_str_appends(&proxy,"tcp://");
3284                 smart_str_appends(&proxy,Z_STRVAL_PP(proxy_host));
3285                 smart_str_appends(&proxy,":");
3286                 smart_str_appends(&proxy,Z_STRVAL(str_port));
3287                 smart_str_0(&proxy);
3288                 zval_dtor(&str_port);
3289                 MAKE_STD_ZVAL(str_proxy);
3290                 ZVAL_STRING(str_proxy, proxy.c, 1);
3291                 smart_str_free(&proxy);
3292                 
3293                 if (!context) {
3294                         context = php_stream_context_alloc(TSRMLS_C);
3295                 }
3296                 php_stream_context_set_option(context, "http", "proxy", str_proxy);
3297                 zval_ptr_dtor(&str_proxy);
3298 
3299                 if (uri_len < sizeof("https://")-1 ||
3300                     strncasecmp(uri, "https://", sizeof("https://")-1) != 0) {
3301                         MAKE_STD_ZVAL(str_proxy);
3302                         ZVAL_BOOL(str_proxy, 1);
3303                         php_stream_context_set_option(context, "http", "request_fulluri", str_proxy);
3304                         zval_ptr_dtor(&str_proxy);
3305                 }
3306 
3307                 has_proxy_authorization = proxy_authentication(this_ptr, &headers TSRMLS_CC);
3308         }
3309 
3310         has_authorization = basic_authentication(this_ptr, &headers TSRMLS_CC);
3311 
3312         /* Use HTTP/1.1 with "Connection: close" by default */
3313         if (php_stream_context_get_option(context, "http", "protocol_version", &tmp) == FAILURE) {
3314         zval *http_version;
3315                 MAKE_STD_ZVAL(http_version);
3316                 ZVAL_DOUBLE(http_version, 1.1);
3317                 php_stream_context_set_option(context, "http", "protocol_version", http_version);
3318                 zval_ptr_dtor(&http_version);
3319                 smart_str_appendl(&headers, "Connection: close\r\n", sizeof("Connection: close\r\n")-1);
3320         }
3321 
3322         if (headers.len > 0) {
3323                 zval *str_headers;
3324 
3325                 if (!context) {
3326                         context = php_stream_context_alloc(TSRMLS_C);
3327                 } else {
3328                         http_context_headers(context, has_authorization, has_proxy_authorization, 0, &headers TSRMLS_CC);
3329                 }
3330 
3331                 smart_str_0(&headers);
3332                 MAKE_STD_ZVAL(str_headers);
3333                 ZVAL_STRING(str_headers, headers.c, 1);
3334                 php_stream_context_set_option(context, "http", "header", str_headers);
3335                 smart_str_free(&headers);
3336                 zval_ptr_dtor(&str_headers);
3337         }
3338 
3339         if (context) {
3340                 MAKE_STD_ZVAL(new_context);
3341                 php_stream_context_to_zval(context, new_context);
3342                 orig_context = php_libxml_switch_context(new_context TSRMLS_CC);
3343         }
3344 
3345         SOAP_GLOBAL(error_code) = "WSDL";
3346 
3347         sdl = load_wsdl(this_ptr, uri TSRMLS_CC);
3348         if (sdl) {
3349                 sdl->is_persistent = 0;
3350         }
3351 
3352         SOAP_GLOBAL(error_code) = old_error_code;
3353 
3354         if (context) {
3355                 php_libxml_switch_context(orig_context TSRMLS_CC);
3356                 zval_ptr_dtor(&new_context);
3357         }
3358 
3359         if ((cache_wsdl & WSDL_CACHE_DISK) && key) {
3360                 if (sdl) {
3361                         add_sdl_to_cache(key, uri, t, sdl TSRMLS_CC);
3362                 }
3363                 efree(key);
3364         }
3365 
3366 cache_in_memory:
3367         if (cache_wsdl & WSDL_CACHE_MEMORY) {
3368                 if (sdl) {
3369                         sdlPtr psdl;
3370                         sdl_cache_bucket p;
3371 
3372                         if (SOAP_GLOBAL(mem_cache) == NULL) {
3373                                 SOAP_GLOBAL(mem_cache) = malloc(sizeof(HashTable));
3374                                 zend_hash_init(SOAP_GLOBAL(mem_cache), 0, NULL, delete_psdl, 1);
3375                         } else if (SOAP_GLOBAL(cache_limit) > 0 &&
3376                                    SOAP_GLOBAL(cache_limit) <= zend_hash_num_elements(SOAP_GLOBAL(mem_cache))) {
3377                                 /* in-memory cache overflow */
3378                                 sdl_cache_bucket *q;
3379                                 HashPosition pos;
3380                                 time_t latest = t;
3381                                 char *key = NULL;
3382                                 uint key_len;
3383                                 ulong idx;
3384 
3385                                 for (zend_hash_internal_pointer_reset_ex(SOAP_GLOBAL(mem_cache), &pos);
3386                                          zend_hash_get_current_data_ex(SOAP_GLOBAL(mem_cache), (void **) &q, &pos) == SUCCESS;
3387                                          zend_hash_move_forward_ex(SOAP_GLOBAL(mem_cache), &pos)) {
3388                                         if (q->time < latest) {
3389                                                 latest = q->time;
3390                                                 zend_hash_get_current_key_ex(SOAP_GLOBAL(mem_cache), &key, &key_len, &idx, 0, &pos);
3391                                         }
3392                                 }
3393                                 if (key) {
3394                                         zend_hash_del(SOAP_GLOBAL(mem_cache), key, key_len);
3395                                 } else {
3396                                         return sdl;
3397                                 }
3398                         }
3399 
3400                         psdl = make_persistent_sdl(sdl TSRMLS_CC);
3401                         psdl->is_persistent = 1;
3402                         p.time = t;
3403                         p.sdl = psdl;
3404 
3405                         if (SUCCESS == zend_hash_update(SOAP_GLOBAL(mem_cache), uri,
3406                                                                                         uri_len+1, (void*)&p, sizeof(sdl_cache_bucket), NULL)) {
3407                                 /* remove non-persitent sdl structure */
3408                                 delete_sdl_impl(sdl);
3409                                 /* and replace it with persistent one */
3410                                 sdl = psdl;
3411                         } else {
3412                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to register persistent entry");
3413                                 /* clean up persistent sdl */
3414                                 delete_psdl(&p);
3415                                 /* keep non-persistent sdl and return it */
3416                         }
3417                 }
3418         }
3419 
3420         return sdl;
3421 }
3422 
3423 /* Deletes */
3424 void delete_sdl_impl(void *handle)
3425 {
3426         sdlPtr tmp = (sdlPtr)handle;
3427 
3428         zend_hash_destroy(&tmp->functions);
3429         if (tmp->source) {
3430                 efree(tmp->source);
3431         }
3432         if (tmp->target_ns) {
3433                 efree(tmp->target_ns);
3434         }
3435         if (tmp->elements) {
3436                 zend_hash_destroy(tmp->elements);
3437                 efree(tmp->elements);
3438         }
3439         if (tmp->encoders) {
3440                 zend_hash_destroy(tmp->encoders);
3441                 efree(tmp->encoders);
3442         }
3443         if (tmp->types) {
3444                 zend_hash_destroy(tmp->types);
3445                 efree(tmp->types);
3446         }
3447         if (tmp->groups) {
3448                 zend_hash_destroy(tmp->groups);
3449                 efree(tmp->groups);
3450         }
3451         if (tmp->bindings) {
3452                 zend_hash_destroy(tmp->bindings);
3453                 efree(tmp->bindings);
3454         }
3455         if (tmp->requests) {
3456                 zend_hash_destroy(tmp->requests);
3457                 efree(tmp->requests);
3458         }
3459         efree(tmp);
3460 }
3461 
3462 void delete_sdl(void *handle)
3463 {
3464         sdlPtr tmp = (sdlPtr)handle;
3465 
3466         if (!tmp->is_persistent) {
3467                 delete_sdl_impl(tmp);
3468         }
3469 }
3470 
3471 static void delete_binding(void *data)
3472 {
3473         sdlBindingPtr binding = *((sdlBindingPtr*)data);
3474 
3475         if (binding->location) {
3476                 efree(binding->location);
3477         }
3478         if (binding->name) {
3479                 efree(binding->name);
3480         }
3481 
3482         if (binding->bindingType == BINDING_SOAP) {
3483                 sdlSoapBindingPtr soapBind = binding->bindingAttributes;
3484                 if (soapBind) {
3485                         efree(soapBind);
3486                 }
3487         }
3488         efree(binding);
3489 }
3490 
3491 static void delete_binding_persistent(void *data)
3492 {
3493         sdlBindingPtr binding = *((sdlBindingPtr*)data);
3494 
3495         if (binding->location) {
3496                 free(binding->location);
3497         }
3498         if (binding->name) {
3499                 free(binding->name);
3500         }
3501 
3502         if (binding->bindingType == BINDING_SOAP) {
3503                 sdlSoapBindingPtr soapBind = binding->bindingAttributes;
3504                 if (soapBind) {
3505                         free(soapBind);
3506                 }
3507         }
3508         free(binding);
3509 }
3510 
3511 static void delete_sdl_soap_binding_function_body(sdlSoapBindingFunctionBody body)
3512 {
3513         if (body.ns) {
3514                 efree(body.ns);
3515         }
3516         if (body.headers) {
3517                 zend_hash_destroy(body.headers);
3518                 efree(body.headers);
3519         }
3520 }
3521 
3522 static void delete_sdl_soap_binding_function_body_persistent(sdlSoapBindingFunctionBody body)
3523 {
3524         if (body.ns) {
3525                 free(body.ns);
3526         }
3527         if (body.headers) {
3528                 zend_hash_destroy(body.headers);
3529                 free(body.headers);
3530         }
3531 }
3532 
3533 static void delete_function(void *data)
3534 {
3535         sdlFunctionPtr function = *((sdlFunctionPtr*)data);
3536 
3537         if (function->functionName) {
3538                 efree(function->functionName);
3539         }
3540         if (function->requestName) {
3541                 efree(function->requestName);
3542         }
3543         if (function->responseName) {
3544                 efree(function->responseName);
3545         }
3546         if (function->requestParameters) {
3547                 zend_hash_destroy(function->requestParameters);
3548                 efree(function->requestParameters);
3549         }
3550         if (function->responseParameters) {
3551                 zend_hash_destroy(function->responseParameters);
3552                 efree(function->responseParameters);
3553         }
3554         if (function->faults) {
3555                 zend_hash_destroy(function->faults);
3556                 efree(function->faults);
3557         }
3558 
3559         if (function->bindingAttributes &&
3560             function->binding && function->binding->bindingType == BINDING_SOAP) {
3561                 sdlSoapBindingFunctionPtr soapFunction = function->bindingAttributes;
3562                 if (soapFunction->soapAction) {
3563                         efree(soapFunction->soapAction);
3564                 }
3565                 delete_sdl_soap_binding_function_body(soapFunction->input);
3566                 delete_sdl_soap_binding_function_body(soapFunction->output);
3567                 efree(soapFunction);
3568         }
3569         efree(function);
3570 }
3571 
3572 static void delete_function_persistent(void *data)
3573 {
3574         sdlFunctionPtr function = *((sdlFunctionPtr*)data);
3575 
3576         if (function->functionName) {
3577                 free(function->functionName);
3578         }
3579         if (function->requestName) {
3580                 free(function->requestName);
3581         }
3582         if (function->responseName) {
3583                 free(function->responseName);
3584         }
3585         if (function->requestParameters) {
3586                 zend_hash_destroy(function->requestParameters);
3587                 free(function->requestParameters);
3588         }
3589         if (function->responseParameters) {
3590                 zend_hash_destroy(function->responseParameters);
3591                 free(function->responseParameters);
3592         }
3593         if (function->faults) {
3594                 zend_hash_destroy(function->faults);
3595                 free(function->faults);
3596         }
3597 
3598         if (function->bindingAttributes &&
3599             function->binding && function->binding->bindingType == BINDING_SOAP) {
3600                 sdlSoapBindingFunctionPtr soapFunction = function->bindingAttributes;
3601                 if (soapFunction->soapAction) {
3602                         free(soapFunction->soapAction);
3603                 }
3604                 delete_sdl_soap_binding_function_body_persistent(soapFunction->input);
3605                 delete_sdl_soap_binding_function_body_persistent(soapFunction->output);
3606                 free(soapFunction);
3607         }
3608         free(function);
3609 }
3610 
3611 static void delete_parameter(void *data)
3612 {
3613         sdlParamPtr param = *((sdlParamPtr*)data);
3614         if (param->paramName) {
3615                 efree(param->paramName);
3616         }
3617         efree(param);
3618 }
3619 
3620 static void delete_parameter_persistent(void *data)
3621 {
3622         sdlParamPtr param = *((sdlParamPtr*)data);
3623         if (param->paramName) {
3624                 free(param->paramName);
3625         }
3626         free(param);
3627 }
3628 
3629 static void delete_header(void *data)
3630 {
3631         sdlSoapBindingFunctionHeaderPtr hdr = *((sdlSoapBindingFunctionHeaderPtr*)data);
3632         if (hdr->name) {
3633                 efree(hdr->name);
3634         }
3635         if (hdr->ns) {
3636                 efree(hdr->ns);
3637         }
3638         if (hdr->headerfaults) {
3639                 zend_hash_destroy(hdr->headerfaults);
3640                 efree(hdr->headerfaults);
3641         }
3642         efree(hdr);
3643 }
3644 
3645 static void delete_header_persistent(void *data)
3646 {
3647         sdlSoapBindingFunctionHeaderPtr hdr = *((sdlSoapBindingFunctionHeaderPtr*)data);
3648         if (hdr->name) {
3649                 free(hdr->name);
3650         }
3651         if (hdr->ns) {
3652                 free(hdr->ns);
3653         }
3654         if (hdr->headerfaults) {
3655                 zend_hash_destroy(hdr->headerfaults);
3656                 free(hdr->headerfaults);
3657         }
3658         free(hdr);
3659 }
3660 
3661 static void delete_fault(void *data)
3662 {
3663         sdlFaultPtr fault = *((sdlFaultPtr*)data);
3664         if (fault->name) {
3665                 efree(fault->name);
3666         }
3667         if (fault->details) {
3668                 zend_hash_destroy(fault->details);
3669                 efree(fault->details);
3670         }
3671         if (fault->bindingAttributes) {
3672                 sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
3673 
3674                 if (binding->ns) {
3675                         efree(binding->ns);
3676                 }
3677                 efree(fault->bindingAttributes);
3678         }
3679         efree(fault);
3680 }
3681 
3682 static void delete_fault_persistent(void *data)
3683 {
3684         sdlFaultPtr fault = *((sdlFaultPtr*)data);
3685         if (fault->name) {
3686                 free(fault->name);
3687         }
3688         if (fault->details) {
3689                 zend_hash_destroy(fault->details);
3690                 free(fault->details);
3691         }
3692         if (fault->bindingAttributes) {
3693                 sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
3694 
3695                 if (binding->ns) {
3696                         free(binding->ns);
3697                 }
3698                 free(fault->bindingAttributes);
3699         }
3700         free(fault);
3701 }
3702 
3703 static void delete_document(void *doc_ptr)
3704 {
3705         xmlDocPtr doc = *((xmlDocPtr*)doc_ptr);
3706         xmlFreeDoc(doc);
3707 }
3708 

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