]> granicus.if.org Git - php/commitdiff
WSDL caching was implemented
authorDmitry Stogov <dmitry@php.net>
Tue, 10 Feb 2004 13:41:21 +0000 (13:41 +0000)
committerDmitry Stogov <dmitry@php.net>
Tue, 10 Feb 2004 13:41:21 +0000 (13:41 +0000)
ext/soap/TODO
ext/soap/php_encoding.c
ext/soap/php_packet_soap.c
ext/soap/php_schema.c
ext/soap/php_schema.h
ext/soap/php_sdl.c
ext/soap/php_sdl.h
ext/soap/php_soap.h
ext/soap/soap.c

index bd4743bcce18110925c6cea3b07c5eb15f3d5e2f..b188e32e8693ef634eea82b108e1034c516628a2 100644 (file)
@@ -3,7 +3,7 @@ General
 - make sure soapserver.map(), soap_encode_to_xml() and soap_encode_to_zval() are really need
 - reimplement SoapObject::__getfunctions() and SoapObject::__gettypes()
   to return structures instead of strings
-- memory leaks (libxml and WSDL/Schema use malloc to cache WSDL)
+? memory leaks (libxml and WSDL/Schema use malloc to cache WSDL)
 - error handling???
 
 SOAP
@@ -57,7 +57,7 @@ WSDL
 - support for <opperation> <fault>
 ? server part support for "document" style encoding
 - function/method overloading/redeclaration (test(int); test(string))
-- wsdl caching
++ wsdl caching
 - wsdl auto generation
 ? SOAP binding
   - <soap:body> parts attribute
index 69768b67d5d314486ee4a4c79684cb99ccece2ea..9686048dbb99adc334d444ac3084fa43c9031a91 100644 (file)
@@ -826,7 +826,7 @@ static void model_to_zval_object(zval *ret, sdlContentModelPtr model, xmlNodePtr
                        }
                }
                case XSD_CONTENT_GROUP:
-                       model_to_zval_object(ret, model->u.group, data, sdl TSRMLS_CC);
+                       model_to_zval_object(ret, model->u.group->model, data, sdl TSRMLS_CC);
                default:
                  break;
        }
@@ -1023,7 +1023,7 @@ static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, HashTa
                        return 0;
                }
                case XSD_CONTENT_GROUP: {
-                       return model_to_xml_object(node, model->u.group, prop, style, model->min_occurs > 0);
+                       return model_to_xml_object(node, model->u.group->model, prop, style, model->min_occurs > 0);
                }
                default:
                  break;
@@ -1555,7 +1555,7 @@ static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data)
        int dimension = 1;
        int* dims = NULL;
        int* pos = NULL;
-       xmlAttrPtr attr;        
+       xmlAttrPtr attr;
        sdlPtr sdl;
        sdlAttributePtr *arrayType;
        sdlExtraAttributePtr *ext;
index c3efe0b9d42fa77cf6df9d6a5c2a3bac482d592c..f29193dbd1bd322e60ac655fead94799491180b2 100644 (file)
@@ -240,63 +240,66 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
                        char *name, *ns = NULL;
                        zval* tmp;
                        sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes;
-                       int res_count = zend_hash_num_elements(fn->responseParameters);
+                       int res_count;
 
                        hdrs = fnb->output.headers;
 
-                       zend_hash_internal_pointer_reset(fn->responseParameters);
-                       while (zend_hash_get_current_data(fn->responseParameters, (void **)&h_param) == SUCCESS) {
-                               param = (*h_param);
-                               if (fnb->style == SOAP_DOCUMENT) {
-                                       name = param->encode->details.type_str;
-                                       ns = param->encode->details.ns;
-                               } else {
-                                       name = fn->responseName;
-                                       /* ns = ? */
-                               }
-
-                               /* Get value of parameter */
-                               cur = get_node_ex(resp, name, ns);
-                               if (!cur) {
-                                       cur = get_node(resp, name);
-                                       /* TODO: produce warning invalid ns */
-                               }
-                               if (cur) {
+                       if (fn->responseParameters) {
+                         res_count = zend_hash_num_elements(fn->responseParameters);
+                               zend_hash_internal_pointer_reset(fn->responseParameters);
+                               while (zend_hash_get_current_data(fn->responseParameters, (void **)&h_param) == SUCCESS) {
+                                       param = (*h_param);
                                        if (fnb->style == SOAP_DOCUMENT) {
-                                               val = cur;
+                                               name = param->encode->details.type_str;
+                                               ns = param->encode->details.ns;
                                        } else {
-                                               val = get_node(cur->children, param->paramName);
-                                               if (val == NULL && res_count == 1) {
-                                                       val = get_node(cur->children, "return");
-                                               }
-                                               if (val == NULL && res_count == 1) {
-                                                       val = get_node(cur->children, "result");
+                                               name = fn->responseName;
+                                               /* ns = ? */
+                                       }
+
+                                       /* Get value of parameter */
+                                       cur = get_node_ex(resp, name, ns);
+                                       if (!cur) {
+                                               cur = get_node(resp, name);
+                                               /* TODO: produce warning invalid ns */
+                                       }
+                                       if (cur) {
+                                               if (fnb->style == SOAP_DOCUMENT) {
+                                                       val = cur;
+                                               } else {
+                                                       val = get_node(cur->children, param->paramName);
+                                                       if (val == NULL && res_count == 1) {
+                                                               val = get_node(cur->children, "return");
+                                                       }
+                                                       if (val == NULL && res_count == 1) {
+                                                               val = get_node(cur->children, "result");
+                                                       }
                                                }
                                        }
-                               }
 
-                               if (!val) {
-                                       /* TODO: may be "nil" is not OK? */
-                                       MAKE_STD_ZVAL(tmp);
-                                       ZVAL_NULL(tmp);
+                                       if (!val) {
+                                               /* TODO: may be "nil" is not OK? */
+                                               MAKE_STD_ZVAL(tmp);
+                                               ZVAL_NULL(tmp);
 /*
-                                       add_soap_fault(this_ptr, "Client", "Can't find response data", NULL, NULL TSRMLS_CC);
-                                       xmlFreeDoc(response);
-                                       return FALSE;
+                                               add_soap_fault(this_ptr, "Client", "Can't find response data", NULL, NULL TSRMLS_CC);
+                                               xmlFreeDoc(response);
+                                               return FALSE;
 */
-                               } else {
-                                       /* Decoding value of parameter */
-                                       if (param != NULL) {
-                                               tmp = master_to_zval(param->encode, val);
                                        } else {
-                                               tmp = master_to_zval(NULL, val);
+                                               /* Decoding value of parameter */
+                                               if (param != NULL) {
+                                                       tmp = master_to_zval(param->encode, val);
+                                               } else {
+                                                       tmp = master_to_zval(NULL, val);
+                                               }
                                        }
-                               }
-                               add_assoc_zval(return_value, param->paramName, tmp);
+                                       add_assoc_zval(return_value, param->paramName, tmp);
 
-                               param_count++;
+                                       param_count++;
 
-                               zend_hash_move_forward(fn->responseParameters);
+                                       zend_hash_move_forward(fn->responseParameters);
+                               }
                        }
                } else {
                  /* Function hasn't WSDL description */
index 9c219da0c69cf2e5e0c5af257fd6b515714185dd..db97fbfa3fac3bc395af0e89ed69cc898fefe1ca 100644 (file)
@@ -46,13 +46,6 @@ static int schema_restriction_var_char(xmlNodePtr val, sdlRestrictionCharPtr *va
 
 static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type);
 
-static void delete_model(void *handle);
-static void delete_type(void *data);
-static void delete_extra_attribute(void *attribute);
-static void delete_attribute(void *attribute);
-static void delete_restriction_var_int(void *rvi);
-static void delete_schema_restriction_var_char(void *srvc);
-
 static encodePtr create_encoder(sdlPtr sdl, sdlTypePtr cur_type, const char *ns, const char *type)
 {
        smart_str nscat = {0};
@@ -697,7 +690,7 @@ static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodeP
                        schema_restriction_var_char(trav, &enumval);
                        if (cur_type->restrictions->enumeration == NULL) {
                                cur_type->restrictions->enumeration = sdl_malloc(sizeof(HashTable));
-                               zend_hash_init(cur_type->restrictions->enumeration, 0, NULL, delete_schema_restriction_var_char, SDL_PERSISTENT);
+                               zend_hash_init(cur_type->restrictions->enumeration, 0, NULL, delete_restriction_var_char, SDL_PERSISTENT);
                        }
                        zend_hash_add(cur_type->restrictions->enumeration, enumval->value, strlen(enumval->value)+1, &enumval, sizeof(sdlRestrictionCharPtr), NULL);
                } else {
@@ -2113,7 +2106,7 @@ static void schema_content_model_fixup(sdlCtx *ctx, sdlContentModelPtr model)
                                schema_type_fixup(ctx,*tmp);
                                efree(model->u.group_ref);
                                model->kind = XSD_CONTENT_GROUP;
-                               model->u.group = (*tmp)->model;
+                               model->u.group = (*tmp);
                        } else {
                                php_error(E_ERROR, "SOAP-ERROR: Parsing Schema: unresolved group 'ref' attribute");
                        }
@@ -2231,7 +2224,7 @@ void schema_pass2(sdlCtx *ctx)
        }
 }
 
-static void delete_model(void *handle)
+void delete_model(void *handle)
 {
        sdlContentModelPtr tmp = *((sdlContentModelPtr*)handle);
        switch (tmp->kind) {
@@ -2251,7 +2244,7 @@ static void delete_model(void *handle)
        sdl_free(tmp);
 }
 
-static void delete_type(void *data)
+void delete_type(void *data)
 {
        sdlTypePtr type = *((sdlTypePtr*)data);
        if (type->name) {
@@ -2287,8 +2280,8 @@ static void delete_type(void *data)
                delete_restriction_var_int(&type->restrictions->length);
                delete_restriction_var_int(&type->restrictions->minLength);
                delete_restriction_var_int(&type->restrictions->maxLength);
-               delete_schema_restriction_var_char(&type->restrictions->whiteSpace);
-               delete_schema_restriction_var_char(&type->restrictions->pattern);
+               delete_restriction_var_char(&type->restrictions->whiteSpace);
+               delete_restriction_var_char(&type->restrictions->pattern);
                if (type->restrictions->enumeration) {
                        zend_hash_destroy(type->restrictions->enumeration);
                        sdl_free(type->restrictions->enumeration);
@@ -2298,7 +2291,7 @@ static void delete_type(void *data)
        sdl_free(type);
 }
 
-static void delete_extra_attribute(void *attribute)
+void delete_extra_attribute(void *attribute)
 {
        sdlExtraAttributePtr attr = *((sdlExtraAttributePtr*)attribute);
 
@@ -2311,7 +2304,7 @@ static void delete_extra_attribute(void *attribute)
        sdl_free(attr);
 }
 
-static void delete_attribute(void *attribute)
+void delete_attribute(void *attribute)
 {
        sdlAttributePtr attr = *((sdlAttributePtr*)attribute);
 
@@ -2334,7 +2327,7 @@ static void delete_attribute(void *attribute)
        sdl_free(attr);
 }
 
-static void delete_restriction_var_int(void *rvi)
+void delete_restriction_var_int(void *rvi)
 {
        sdlRestrictionIntPtr ptr = *((sdlRestrictionIntPtr*)rvi);
        if (ptr) {
@@ -2342,7 +2335,7 @@ static void delete_restriction_var_int(void *rvi)
        }
 }
 
-static void delete_schema_restriction_var_char(void *srvc)
+void delete_restriction_var_char(void *srvc)
 {
        sdlRestrictionCharPtr ptr = *((sdlRestrictionCharPtr*)srvc);
        if (ptr) {
index 7b121fae09059d30b4a7cfda7e6a06b80960da58..9101725df3013b682364cd63a1f6bc66f6f939ef 100644 (file)
 int load_schema(sdlCtx *ctx, xmlNodePtr schema);
 void schema_pass2(sdlCtx *ctx);
 
+void delete_model(void *handle);
+void delete_type(void *data);
+void delete_extra_attribute(void *attribute);
+void delete_attribute(void *attribute);
+void delete_restriction_var_int(void *rvi);
+void delete_restriction_var_char(void *srvc);
 #endif
index 0ad9b637892c348cb54212ab2a2fc95b5262d14a..586389f66ed242fd2b9da246d418f69a2ee2c09f 100644 (file)
 #include "php_soap.h"
 #include "libxml/uri.h"
 
+#include "ext/standard/md5.h"
+#include "tsrm_virtual_cwd.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
 static void delete_binding(void *binding);
 static void delete_function(void *function);
-static void delete_paramater(void *paramater);
+static void delete_parameter(void *paramater);
 static void delete_header(void *header);
 static void delete_document(void *doc_ptr);
 
@@ -149,8 +160,6 @@ static void load_wsdl_ex(char *struri, sdlCtx *ctx, int include)
          return;
        }
 
-       /* TODO: WSDL Caching */
-
        wsdl = soap_xmlParseFile(struri);
 
        if (!wsdl) {
@@ -403,7 +412,7 @@ static HashTable* wsdl_message(sdlCtx *ctx, char* message_name)
        message = *tmp;
 
        parameters = sdl_malloc(sizeof(HashTable));
-       zend_hash_init(parameters, 0, NULL, delete_paramater, SDL_PERSISTENT);
+       zend_hash_init(parameters, 0, NULL, delete_parameter, SDL_PERSISTENT);
 
        trav = message->children;
        FOREACHNODE(trav, "part", part) {
@@ -751,7 +760,1059 @@ static sdlPtr load_wsdl(char *struri)
        return ctx.sdl;
 }
 
-sdlPtr get_sdl(char *uri)
+#define WSDL_CACHE_VERSION 01
+
+#define WSDL_CACHE_GET(ret,type,buf)   memcpy(&ret,*buf,sizeof(type)); *buf += sizeof(type);
+#define WSDL_CACHE_GET_INT(ret,buf)    ret = ((int)(*buf)[0])+((int)(*buf)[1]<<8)+((int)(*buf)[2]<<16)+((int)(*buf)[3]<<24); *buf += 4;
+#define WSDL_CACHE_GET_1(ret,type,buf) ret = (type)(**buf); (*buf)++;
+#define WSDL_CACHE_GET_N(ret,n,buf)    memcpy(ret,*buf,n); *buf += n;
+#define WSDL_CACHE_SKIP(n,buf)         *buf += n;
+
+#define WSDL_CACHE_PUT_INT(val,buf)    smart_str_appendc(buf,val & 0xff); \
+                                       smart_str_appendc(buf,(val >> 8) & 0xff); \
+                                       smart_str_appendc(buf,(val >> 16) & 0xff); \
+                                       smart_str_appendc(buf,(val >> 24) & 0xff);
+#define WSDL_CACHE_PUT_1(val,buf)      smart_str_appendc(buf,val);
+#define WSDL_CACHE_PUT_N(val,n,buf)    smart_str_appendl(buf,(char*)val,n);
+
+static char* sdl_deserialize_string(char **in)
+{
+       char *s;
+       int len;
+
+       WSDL_CACHE_GET_INT(len, in);
+       if (len == 0) {
+               return NULL;
+       } else {
+               s = sdl_malloc(len+1);
+               WSDL_CACHE_GET_N(s, len, in);
+               s[len] = '\0';
+               return s;
+       }
+}
+
+static void sdl_deserialize_key(HashTable* ht, void* data, char **in)
+{
+       int len;
+
+       WSDL_CACHE_GET_INT(len, in);
+       if (len == 0) {
+               zend_hash_next_index_insert(ht, &data, sizeof(void*), NULL);
+       } else {
+               zend_hash_add(ht, *in, len, &data, sizeof(void*), NULL);
+               WSDL_CACHE_SKIP(len, in);
+       }
+}
+
+static void sdl_deserialize_attribute(sdlAttributePtr attr, encodePtr *encoders, char **in)
+{
+       int i;
+
+       attr->name = sdl_deserialize_string(in);
+       attr->ref = sdl_deserialize_string(in);
+       attr->def = sdl_deserialize_string(in);
+       attr->fixed = sdl_deserialize_string(in);
+       WSDL_CACHE_GET_1(attr->form, sdlForm, in);
+       WSDL_CACHE_GET_1(attr->use, sdlUse, in);
+       WSDL_CACHE_GET_INT(i, in);
+       attr->encode = encoders[i];
+       WSDL_CACHE_GET_INT(i, in);
+       if (i > 0) {
+               attr->extraAttributes = sdl_malloc(sizeof(HashTable));
+               zend_hash_init(attr->extraAttributes, i, NULL, delete_extra_attribute, SDL_PERSISTENT);
+               while (i > 0) {
+                       sdlExtraAttributePtr x = sdl_malloc(sizeof(sdlExtraAttribute));
+                       sdl_deserialize_key(attr->extraAttributes, x, in);
+                       x->ns = sdl_deserialize_string(in);
+                       x->val = sdl_deserialize_string(in);
+                       --i;
+               }
+       }
+}
+
+static sdlRestrictionIntPtr sdl_deserialize_resriction_int(char **in)
+{
+       if (**in == 1) {
+               sdlRestrictionIntPtr x = sdl_malloc(sizeof(sdlRestrictionInt));
+               WSDL_CACHE_SKIP(1, in);
+               WSDL_CACHE_GET_INT(x->value, in);
+               WSDL_CACHE_GET_1(x->fixed, char, in);
+               return x;
+       } else {
+               WSDL_CACHE_SKIP(1, in);
+               return NULL;
+       }
+}
+
+static sdlRestrictionCharPtr sdl_deserialize_resriction_char(char **in)
+{
+       if (**in == 1) {
+               sdlRestrictionCharPtr x = sdl_malloc(sizeof(sdlRestrictionChar));
+               WSDL_CACHE_SKIP(1, in);
+               x->value = sdl_deserialize_string(in);
+               WSDL_CACHE_GET_1(x->fixed, char, in);
+               return x;
+       } else {
+               WSDL_CACHE_SKIP(1, in);
+               return NULL;
+       }
+}
+
+static sdlContentModelPtr sdl_deserialize_model(sdlTypePtr *types, sdlTypePtr *elements, char **in)
+{
+       int i;
+       sdlContentModelPtr model = sdl_malloc(sizeof(sdlContentModel));
+
+       WSDL_CACHE_GET_1(model->kind, sdlContentKind, in);
+       WSDL_CACHE_GET_INT(model->min_occurs, in);
+       WSDL_CACHE_GET_INT(model->max_occurs, in);
+       switch (model->kind) {
+               case XSD_CONTENT_ELEMENT:
+                       WSDL_CACHE_GET_INT(i, in);
+                       model->u.element = elements[i];
+                       break;
+               case XSD_CONTENT_SEQUENCE:
+               case XSD_CONTENT_ALL:
+               case XSD_CONTENT_CHOICE:
+                       WSDL_CACHE_GET_INT(i, in);
+                       if (i > 0) {
+                               model->u.content = sdl_malloc(sizeof(HashTable));
+                               zend_hash_init(model->u.content, i, NULL, delete_model, SDL_PERSISTENT);
+                               while (i > 0) {
+                                       sdlContentModelPtr x = sdl_deserialize_model(types, elements, in);
+                                       zend_hash_next_index_insert(model->u.content,&x,sizeof(sdlContentModelPtr),NULL);
+                                       i--;
+                               }
+                       }
+                       break;
+               case XSD_CONTENT_GROUP_REF:
+                       model->u.group_ref = sdl_deserialize_string(in);
+                       break;
+               case XSD_CONTENT_GROUP:
+                       WSDL_CACHE_GET_INT(i, in);
+                       model->u.group = types[i];
+                       break;
+               default:
+                       break;
+       }
+       return model;
+}
+
+static void sdl_deserialize_type(sdlTypePtr type, sdlTypePtr *types, encodePtr *encoders, char **in)
+{
+       int i;
+       sdlTypePtr *elements = NULL;
+
+       WSDL_CACHE_GET_1(type->kind, sdlTypeKind, in);
+       type->name = sdl_deserialize_string(in);
+       type->namens = sdl_deserialize_string(in);
+       type->def = sdl_deserialize_string(in);
+       type->fixed = sdl_deserialize_string(in);
+       type->ref = sdl_deserialize_string(in);
+       WSDL_CACHE_GET_1(type->nillable, char, in);
+
+       WSDL_CACHE_GET_INT(i, in);
+       type->encode = encoders[i];
+
+       if (**in == 1) {
+               WSDL_CACHE_SKIP(1, in);
+               type->restrictions = sdl_malloc(sizeof(sdlRestrictions));
+               /*memset(type->restrictions, 0, sizeof(sdlRestrictions));*/
+               type->restrictions->minExclusive = sdl_deserialize_resriction_int(in);
+               type->restrictions->minInclusive = sdl_deserialize_resriction_int(in);
+               type->restrictions->maxExclusive = sdl_deserialize_resriction_int(in);
+               type->restrictions->maxInclusive = sdl_deserialize_resriction_int(in);
+               type->restrictions->totalDigits = sdl_deserialize_resriction_int(in);
+               type->restrictions->fractionDigits = sdl_deserialize_resriction_int(in);
+               type->restrictions->length = sdl_deserialize_resriction_int(in);
+               type->restrictions->minLength = sdl_deserialize_resriction_int(in);
+               type->restrictions->maxLength = sdl_deserialize_resriction_int(in);
+               type->restrictions->whiteSpace = sdl_deserialize_resriction_char(in);
+               type->restrictions->pattern = sdl_deserialize_resriction_char(in);
+               WSDL_CACHE_GET_INT(i, in);
+               if (i > 0) {
+                       type->restrictions->enumeration = sdl_malloc(sizeof(HashTable));
+                       zend_hash_init(type->restrictions->enumeration, i, NULL, delete_restriction_var_char, SDL_PERSISTENT);
+                       while (i > 0) {
+                               sdlRestrictionCharPtr x = sdl_deserialize_resriction_char(in);
+                               sdl_deserialize_key(type->restrictions->enumeration, x, in);
+                               --i;
+                       }
+               } else {
+                       type->restrictions->enumeration = NULL;
+               }
+       } else {
+               WSDL_CACHE_SKIP(1, in);
+       }
+
+       WSDL_CACHE_GET_INT(i, in);
+       if (i > 0) {
+               elements = do_alloca((i+1) * sizeof(sdlTypePtr));
+               elements[0] = NULL;
+               type->elements = sdl_malloc(sizeof(HashTable));
+               zend_hash_init(type->elements, i, NULL, delete_type, SDL_PERSISTENT);
+               while (i > 0) {
+                       sdlTypePtr t = sdl_malloc(sizeof(sdlType));
+                       memset(t, 0, sizeof(sdlType));
+                       sdl_deserialize_key(type->elements, t, in);
+                       sdl_deserialize_type(t, types, encoders, in);
+                       elements[i] = t;
+                       --i;
+               }
+       }
+
+       WSDL_CACHE_GET_INT(i, in);
+       if (i > 0) {
+               type->attributes = sdl_malloc(sizeof(HashTable));
+               zend_hash_init(type->attributes, i, NULL, delete_attribute, SDL_PERSISTENT);
+               while (i > 0) {
+                       sdlAttributePtr attr = sdl_malloc(sizeof(sdlAttribute));
+                       memset(attr, 0, sizeof(sdlAttribute));
+                       sdl_deserialize_key(type->attributes, attr, in);
+                       sdl_deserialize_attribute(attr, encoders, in);
+                       --i;
+               }
+       }
+
+       if (**in != 0) {
+               WSDL_CACHE_SKIP(1, in);
+               type->model = sdl_deserialize_model(types, elements, in);
+       } else {
+               WSDL_CACHE_SKIP(1, in);
+       }
+       if (elements != NULL) {
+               free_alloca(elements);
+       }
+}
+
+static void sdl_deserialize_encoder(encodePtr enc, sdlTypePtr *types, char **in)
+{
+       int i;
+
+       WSDL_CACHE_GET_INT(enc->details.type, in);
+       enc->details.type_str = sdl_deserialize_string(in);
+       enc->details.ns = sdl_deserialize_string(in);
+       WSDL_CACHE_GET_INT(i, in);
+       enc->details.sdl_type = types[i];
+       enc->to_xml = sdl_guess_convert_xml;
+       enc->to_zval = sdl_guess_convert_zval;
+}
+
+static void sdl_deserialize_soap_body(sdlSoapBindingFunctionBodyPtr body, encodePtr *encoders, sdlTypePtr *types, char **in)
+{
+       int i, n;
+
+       WSDL_CACHE_GET_1(body->use, sdlEncodingUse, in);
+       body->ns = sdl_deserialize_string(in);
+       body->parts = sdl_deserialize_string(in);
+       body->encodingStyle = sdl_deserialize_string(in);
+       WSDL_CACHE_GET_INT(i, in);
+       if (i > 0) {
+               body->headers = sdl_malloc(sizeof(HashTable));
+               zend_hash_init(body->headers, i, NULL, delete_header, SDL_PERSISTENT);
+               while (i > 0) {
+                       sdlSoapBindingFunctionHeaderPtr tmp = sdl_malloc(sizeof(sdlSoapBindingFunctionHeader));
+                       sdl_deserialize_key(body->headers, tmp, in);
+                       WSDL_CACHE_GET_1(tmp->use, sdlEncodingUse, in);
+                       tmp->name = sdl_deserialize_string(in);
+                       tmp->ns = sdl_deserialize_string(in);
+                       tmp->encodingStyle = sdl_deserialize_string(in);
+                       WSDL_CACHE_GET_INT(n, in);
+                       tmp->encode = encoders[n];
+                       WSDL_CACHE_GET_INT(n, in);
+                       tmp->element = types[n];
+                       --i;
+               }
+       }
+}
+
+static HashTable* sdl_deserialize_parameters(encodePtr *encoders, sdlTypePtr *types, char **in)
+{
+       int i, n;
+       HashTable *ht;
+
+       WSDL_CACHE_GET_INT(i, in);
+       if (i == 0) {return NULL;}
+       ht = sdl_malloc(sizeof(HashTable));
+       zend_hash_init(ht, i, NULL, delete_parameter, SDL_PERSISTENT);
+       while (i > 0) {
+               sdlParamPtr param = sdl_malloc(sizeof(sdlParam));
+               sdl_deserialize_key(ht, param, in);
+               param->paramName = sdl_deserialize_string(in);
+               WSDL_CACHE_GET_INT(param->order, in);
+               WSDL_CACHE_GET_INT(n, in);
+               param->encode = encoders[n];
+               WSDL_CACHE_GET_INT(n, in);
+               param->element = types[n];
+               --i;
+       }
+       return ht;
+}
+
+static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t)
+{
+       sdlPtr sdl;
+       time_t old_t;
+       int  i, num_groups, num_types, num_elements, num_encoders, num_bindings, num_func;
+       sdlFunctionPtr *functions;
+       sdlBindingPtr *bindings;
+       sdlTypePtr *types;
+       encodePtr *encoders;
+       encodePtr enc;
+
+       int f;
+       struct stat st;
+       char *in, *buf;
+
+       f = open(fn, O_RDONLY|O_BINARY);
+       if (f < 0) {
+               return NULL;
+       }
+       if (fstat(f, &st) != 0) {
+               close(f);
+               return NULL;
+       }
+       buf = in = do_alloca(st.st_size);
+       if (read(f, in, st.st_size) != st.st_size) {
+               close(f);
+               free_alloca(in);
+               return NULL;
+       }
+       close(f);
+
+       if (strncmp(in,"wsdl",4) != 0 || in[4] != WSDL_CACHE_VERSION || in[5] != '\0') {
+               unlink(fn);
+               free_alloca(buf);
+               return NULL;
+       }
+       in += 6;
+
+       WSDL_CACHE_GET(old_t, time_t, &in);
+       if (old_t < t) {
+               unlink(fn);
+               free_alloca(buf);
+               return NULL;
+       }
+
+       WSDL_CACHE_GET_INT(i, &in);
+       if (i == 0 && strncmp(in, uri, i) != 0) {
+               unlink(fn);
+               free_alloca(buf);
+               return NULL;
+       }
+       WSDL_CACHE_SKIP(i, &in);
+
+       sdl = sdl_malloc(sizeof(*sdl));
+       memset(sdl, 0, sizeof(*sdl));
+
+       sdl->source = sdl_deserialize_string(&in);
+       sdl->target_ns = sdl_deserialize_string(&in);
+
+       WSDL_CACHE_GET_INT(num_groups, &in);
+       WSDL_CACHE_GET_INT(num_types, &in);
+       WSDL_CACHE_GET_INT(num_elements, &in);
+       WSDL_CACHE_GET_INT(num_encoders, &in);
+
+       i = num_groups+num_types+num_elements;
+       types = do_alloca((i+1)*sizeof(sdlTypePtr));
+       types[0] = NULL;
+       while (i > 0) {
+               types[i] = sdl_malloc(sizeof(sdlType));
+               memset(types[i], 0, sizeof(sdlType));
+               i--;
+       }
+
+       i = num_encoders;
+       enc = defaultEncoding;
+       while (enc->details.type != END_KNOWN_TYPES) {
+               i++; enc++;
+       }
+       encoders = do_alloca((i+1)*sizeof(encodePtr));
+       i = num_encoders;
+       encoders[0] = NULL;
+       while (i > 0) {
+               encoders[i] = sdl_malloc(sizeof(encode));
+               memset(encoders[i], 0, sizeof(encode));
+               i--;
+       }
+       i = num_encoders;
+       enc = defaultEncoding;
+       while (enc->details.type != END_KNOWN_TYPES) {
+               encoders[++i] = enc++;
+       }
+
+       i = 1;
+       if (num_groups > 0) {
+               sdl->groups = sdl_malloc(sizeof(HashTable));
+               zend_hash_init(sdl->groups, num_groups, NULL, delete_type, SDL_PERSISTENT);
+               while (i < num_groups+1) {
+                       sdl_deserialize_key(sdl->groups, types[i], &in);
+                       sdl_deserialize_type(types[i], types, encoders, &in);
+                       i++;
+               }
+       }
+
+       if (num_types > 0) {
+               sdl->types = sdl_malloc(sizeof(HashTable));
+               zend_hash_init(sdl->types, num_types, NULL, delete_type, SDL_PERSISTENT);
+               while (i < num_groups+num_types+1) {
+                       sdl_deserialize_key(sdl->types, types[i], &in);
+                       sdl_deserialize_type(types[i], types, encoders, &in);
+                       i++;
+               }
+       }
+
+       if (num_elements > 0) {
+               sdl->elements = sdl_malloc(sizeof(HashTable));
+               zend_hash_init(sdl->elements, num_elements, NULL, delete_type, SDL_PERSISTENT);
+               while (i < num_groups+num_types+num_elements+1) {
+                       sdl_deserialize_key(sdl->elements, types[i], &in);
+                       sdl_deserialize_type(types[i], types, encoders, &in);
+                       i++;
+               }
+       }
+
+       i = 1;
+       if (num_encoders > 0) {
+               sdl->encoders = sdl_malloc(sizeof(HashTable));
+               zend_hash_init(sdl->encoders, num_encoders, NULL, delete_encoder, SDL_PERSISTENT);
+               while (i < num_encoders+1) {
+                       sdl_deserialize_key(sdl->encoders, encoders[i], &in);
+                       sdl_deserialize_encoder(encoders[i], types, &in);
+                       i++;
+               }
+       }
+
+       /* deserialize bindings */
+       WSDL_CACHE_GET_INT(num_bindings, &in);
+       bindings = do_alloca(num_bindings*sizeof(sdlBindingPtr));
+       if (num_bindings > 0) {
+               sdl->bindings = sdl_malloc(sizeof(HashTable));
+               zend_hash_init(sdl->bindings, num_bindings, NULL, delete_binding, SDL_PERSISTENT);
+               for (i = 0; i < num_bindings; i++) {
+                       sdlBindingPtr binding = sdl_malloc(sizeof(sdlBinding));
+                       memset(binding, 0, sizeof(sdlBinding));
+                       sdl_deserialize_key(sdl->bindings, binding, &in);
+                       binding->name = sdl_deserialize_string(&in);
+                       binding->location = sdl_deserialize_string(&in);
+                       WSDL_CACHE_GET_1(binding->bindingType,sdlBindingType,&in);
+                       if (binding->bindingType == BINDING_SOAP) {
+                               if (*in != 0) {
+                                 sdlSoapBindingPtr soap_binding = binding->bindingAttributes = sdl_malloc(sizeof(sdlSoapBinding));
+                                       WSDL_CACHE_GET_1(soap_binding->style,sdlEncodingStyle,&in);
+                                       soap_binding->transport = sdl_deserialize_string(&in);
+                               } else {
+                                       WSDL_CACHE_SKIP(1,&in);
+                               }
+                       }
+                       bindings[i] = binding;
+               }
+       }
+
+       /* deserialize functions */
+       WSDL_CACHE_GET_INT(num_func, &in);
+       zend_hash_init(&sdl->functions, num_func, NULL, delete_function, SDL_PERSISTENT);
+       functions = do_alloca(num_func*sizeof(sdlFunctionPtr));
+       for (i = 0; i < num_func; i++) {
+               int binding_num;
+               sdlFunctionPtr func = sdl_malloc(sizeof(sdlFunction));
+               sdl_deserialize_key(&sdl->functions, func, &in);
+               func->functionName = sdl_deserialize_string(&in);
+               func->requestName = sdl_deserialize_string(&in);
+               func->responseName = sdl_deserialize_string(&in);
+
+               WSDL_CACHE_GET_INT(binding_num, &in);
+               if (binding_num == 0) {
+                       func->binding = NULL;
+               } else {
+                       func->binding = bindings[binding_num-1];
+               }
+               if (func->binding && func->binding->bindingType == BINDING_SOAP) {
+                       if (*in != 0) {
+                               sdlSoapBindingFunctionPtr binding = func->bindingAttributes = sdl_malloc(sizeof(sdlSoapBindingFunction));
+                               memset(binding, 0, sizeof(sdlSoapBindingFunction));
+                               WSDL_CACHE_GET_1(binding->style,sdlEncodingStyle,&in);
+                               binding->soapAction = sdl_deserialize_string(&in);
+                               sdl_deserialize_soap_body(&binding->input, encoders, types, &in);
+                               sdl_deserialize_soap_body(&binding->output, encoders, types, &in);
+                               /*sdl_deserialize_soap_body(&binding->fault, encoders, types, &in);*/
+                       } else {
+                               WSDL_CACHE_SKIP(1, &in);
+                       }
+               }
+
+               func->requestParameters = sdl_deserialize_parameters(encoders, types, &in);
+               func->responseParameters = sdl_deserialize_parameters(encoders, types, &in);
+               functions[i] = func;
+       }
+
+       /* deserialize requests */
+       WSDL_CACHE_GET_INT(i, &in);
+       if (i > 0) {
+               sdl->requests = sdl_malloc(sizeof(HashTable));
+               zend_hash_init(sdl->requests, i, NULL, NULL, SDL_PERSISTENT);
+               while (i > 0) {
+                       int function_num;
+
+                       WSDL_CACHE_GET_INT(function_num, &in);
+                       sdl_deserialize_key(sdl->requests, functions[function_num], &in);
+                       i--;
+               }
+       }
+
+       free_alloca(functions);
+       free_alloca(bindings);
+       free_alloca(encoders);
+       free_alloca(types);
+       free_alloca(buf);
+       return sdl;
+}
+
+static void sdl_serialize_string(const char *str, smart_str *out)
+{
+       int i;
+
+       if (str) {
+               i = strlen(str);
+       } else {
+               i = 0;
+       }
+       WSDL_CACHE_PUT_INT(i, out);
+       if (i > 0) {
+               WSDL_CACHE_PUT_N(str, i, out);
+       }
+}
+
+static void sdl_serialize_key(HashTable *ht, smart_str *out)
+{
+       char *key;
+       uint  key_len;
+       ulong index;
+
+       if (zend_hash_get_current_key_ex(ht, &key, &key_len, &index, 0, NULL) == HASH_KEY_IS_STRING) {
+               WSDL_CACHE_PUT_INT(key_len, out);
+               WSDL_CACHE_PUT_N(key, key_len, out);
+       } else {
+               WSDL_CACHE_PUT_INT(0, out);
+       }
+}
+
+static void sdl_serialize_encoder_ref(encodePtr enc, HashTable *tmp_encoders, smart_str *out) {
+       if (enc) {
+               int *encoder_num;
+               if (zend_hash_find(tmp_encoders, (char*)&enc, sizeof(enc), (void**)&encoder_num) == SUCCESS) {
+                       WSDL_CACHE_PUT_INT(*encoder_num, out);
+               } else {
+                       WSDL_CACHE_PUT_INT(0, out);
+               }
+       } else {
+               WSDL_CACHE_PUT_INT(0, out);
+       }
+}
+
+static void sdl_serialize_type_ref(sdlTypePtr type, HashTable *tmp_types, smart_str *out) {
+       if (type) {
+               int *type_num;
+               if (zend_hash_find(tmp_types, (char*)&type, sizeof(type), (void**)&type_num) == SUCCESS) {
+                       WSDL_CACHE_PUT_INT(*type_num, out);
+               } else {
+                       WSDL_CACHE_PUT_INT(0, out);
+               }
+       } else {
+               WSDL_CACHE_PUT_INT(0,out);
+       }
+}
+
+static void sdl_serialize_attribute(sdlAttributePtr attr, HashTable *tmp_encoders, smart_str *out)
+{
+       int i;
+
+       sdl_serialize_string(attr->name, out);
+       sdl_serialize_string(attr->ref, out);
+       sdl_serialize_string(attr->def, out);
+       sdl_serialize_string(attr->fixed, out);
+       WSDL_CACHE_PUT_1(attr->form, out);
+       WSDL_CACHE_PUT_1(attr->use, out);
+       sdl_serialize_encoder_ref(attr->encode, tmp_encoders, out);
+       if (attr->extraAttributes) {
+               i = zend_hash_num_elements(attr->extraAttributes);
+       } else {
+               i = 0;
+       }
+       WSDL_CACHE_PUT_INT(i, out);
+       if (i > 0) {
+               sdlExtraAttributePtr *tmp;
+               zend_hash_internal_pointer_reset(attr->extraAttributes);
+               while (zend_hash_get_current_data(attr->extraAttributes, (void**)&tmp) == SUCCESS) {
+                       sdl_serialize_key(attr->extraAttributes, out);
+                       sdl_serialize_string((*tmp)->ns, out);
+                       sdl_serialize_string((*tmp)->val, out);
+                       zend_hash_move_forward(attr->extraAttributes);
+               }
+       }
+}
+
+static void sdl_serialize_model(sdlContentModelPtr model, HashTable *tmp_types, HashTable *tmp_elements, smart_str *out)
+{
+       WSDL_CACHE_PUT_1(model->kind, out);
+       WSDL_CACHE_PUT_INT(model->min_occurs, out);
+       WSDL_CACHE_PUT_INT(model->max_occurs, out);
+       switch (model->kind) {
+               case XSD_CONTENT_ELEMENT:
+                       sdl_serialize_type_ref(model->u.element, tmp_elements, out);
+                       break;
+               case XSD_CONTENT_SEQUENCE:
+               case XSD_CONTENT_ALL:
+               case XSD_CONTENT_CHOICE: {
+                               sdlContentModelPtr *tmp;
+                               int i = zend_hash_num_elements(model->u.content);
+
+                               WSDL_CACHE_PUT_INT(i, out);
+                               zend_hash_internal_pointer_reset(model->u.content);
+                               while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
+                                       sdl_serialize_model(*tmp, tmp_types, tmp_elements, out);
+                                       zend_hash_move_forward(model->u.content);
+                               }
+                       }
+                       break;
+               case XSD_CONTENT_GROUP_REF:
+                       sdl_serialize_string(model->u.group_ref,out);
+                       break;
+               case XSD_CONTENT_GROUP:
+                       sdl_serialize_type_ref(model->u.group, tmp_types, out);
+                       break;
+               default:
+                       break;
+       }
+}
+
+static void sdl_serialize_resriction_int(sdlRestrictionIntPtr x, smart_str *out)
+{
+       if (x) {
+               WSDL_CACHE_PUT_1(1, out);
+               WSDL_CACHE_PUT_INT(x->value, out);
+               WSDL_CACHE_PUT_1(x->fixed, out);
+       } else {
+               WSDL_CACHE_PUT_1(0, out);
+       }
+}
+
+static void sdl_serialize_resriction_char(sdlRestrictionCharPtr x, smart_str *out)
+{
+       if (x) {
+               WSDL_CACHE_PUT_1(1, out);
+               sdl_serialize_string(x->value, out);
+               WSDL_CACHE_PUT_1(x->fixed, out);
+       } else {
+               WSDL_CACHE_PUT_1(0, out);
+       }
+}
+
+static void sdl_serialize_type(sdlTypePtr type, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
+{
+       int i;
+       HashTable *tmp_elements = NULL;
+
+       WSDL_CACHE_PUT_1(type->kind, out);
+       sdl_serialize_string(type->name, out);
+       sdl_serialize_string(type->namens, out);
+       sdl_serialize_string(type->def, out);
+       sdl_serialize_string(type->fixed, out);
+       sdl_serialize_string(type->ref, out);
+       WSDL_CACHE_PUT_1(type->nillable, out);
+       sdl_serialize_encoder_ref(type->encode, tmp_encoders, out);
+
+       if (type->restrictions) {
+               WSDL_CACHE_PUT_1(1, out);
+               sdl_serialize_resriction_int(type->restrictions->minExclusive,out);
+               sdl_serialize_resriction_int(type->restrictions->minInclusive,out);
+               sdl_serialize_resriction_int(type->restrictions->maxExclusive,out);
+               sdl_serialize_resriction_int(type->restrictions->maxInclusive,out);
+               sdl_serialize_resriction_int(type->restrictions->totalDigits,out);
+               sdl_serialize_resriction_int(type->restrictions->fractionDigits,out);
+               sdl_serialize_resriction_int(type->restrictions->length,out);
+               sdl_serialize_resriction_int(type->restrictions->minLength,out);
+               sdl_serialize_resriction_int(type->restrictions->maxLength,out);
+               sdl_serialize_resriction_char(type->restrictions->whiteSpace,out);
+               sdl_serialize_resriction_char(type->restrictions->pattern,out);
+               if (type->restrictions->enumeration) {
+                       i = zend_hash_num_elements(type->restrictions->enumeration);
+               } else {
+                       i = 0;
+               }
+               WSDL_CACHE_PUT_INT(i, out);
+               if (i > 0) {
+                       sdlRestrictionCharPtr *tmp;
+
+                       zend_hash_internal_pointer_reset(type->restrictions->enumeration);
+                       while (zend_hash_get_current_data(type->restrictions->enumeration, (void**)&tmp) == SUCCESS) {
+                               sdl_serialize_resriction_char(*tmp, out);
+                               sdl_serialize_key(type->restrictions->enumeration, out);
+                               zend_hash_move_forward(type->restrictions->enumeration);
+                       }
+               }
+       } else {
+               WSDL_CACHE_PUT_1(0, out);
+       }
+       if (type->elements) {
+               i = zend_hash_num_elements(type->elements);
+       } else {
+               i = 0;
+       }
+       WSDL_CACHE_PUT_INT(i, out);
+       if (i > 0) {
+               sdlTypePtr *tmp;
+
+         tmp_elements = emalloc(sizeof(HashTable));
+         zend_hash_init(tmp_elements, 0, NULL, NULL, 0);
+
+               zend_hash_internal_pointer_reset(type->elements);
+               while (zend_hash_get_current_data(type->elements, (void**)&tmp) == SUCCESS) {
+                       sdl_serialize_key(type->elements, out);
+                       sdl_serialize_type(*tmp, tmp_encoders, tmp_types, out);
+                       zend_hash_add(tmp_elements, (char*)tmp, sizeof(*tmp), &i, sizeof(int), NULL);
+                       i--;
+                       zend_hash_move_forward(type->elements);
+               }
+       }
+
+       if (type->attributes) {
+               i = zend_hash_num_elements(type->attributes);
+       } else {
+               i = 0;
+       }
+       WSDL_CACHE_PUT_INT(i, out);
+       if (i > 0) {
+               sdlAttributePtr *tmp;
+               zend_hash_internal_pointer_reset(type->attributes);
+               while (zend_hash_get_current_data(type->attributes, (void**)&tmp) == SUCCESS) {
+                       sdl_serialize_key(type->attributes, out);
+                       sdl_serialize_attribute(*tmp, tmp_encoders, out);
+                       zend_hash_move_forward(type->attributes);
+               }
+       }
+       if (type->model) {
+               WSDL_CACHE_PUT_1(1, out);
+               sdl_serialize_model(type->model, tmp_types, tmp_elements, out);
+       } else {
+               WSDL_CACHE_PUT_1(0, out);
+       }
+       if (tmp_elements != NULL) {
+               zend_hash_destroy(tmp_elements);
+               efree(tmp_elements);
+       }
+}
+
+static void sdl_serialize_encoder(encodePtr enc, HashTable *tmp_types, smart_str *out)
+{
+       WSDL_CACHE_PUT_INT(enc->details.type, out);
+       sdl_serialize_string(enc->details.type_str, out);
+       sdl_serialize_string(enc->details.ns, out);
+       sdl_serialize_type_ref(enc->details.sdl_type, tmp_types, out);
+}
+
+static void sdl_serialize_parameters(HashTable *ht, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
+{
+       int i;
+
+       if (ht) {
+               i = zend_hash_num_elements(ht);
+       } else {
+               i = 0;
+       }
+       WSDL_CACHE_PUT_INT(i, out);
+       if (i > 0) {
+               sdlParamPtr *tmp;
+
+               zend_hash_internal_pointer_reset(ht);
+               while (zend_hash_get_current_data(ht, (void**)&tmp) == SUCCESS) {
+                       sdl_serialize_key(ht, out);
+                       sdl_serialize_string((*tmp)->paramName, out);
+                       WSDL_CACHE_PUT_INT((*tmp)->order, out);
+                       sdl_serialize_encoder_ref((*tmp)->encode, tmp_encoders, out);
+                       sdl_serialize_type_ref((*tmp)->element, tmp_types, out);
+                       zend_hash_move_forward(ht);
+               }
+       }
+}
+
+static void sdl_serialize_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTable *tmp_encoders, HashTable *tmp_types, smart_str *out)
+{
+       int i;
+
+       WSDL_CACHE_PUT_1(body->use, out);
+       sdl_serialize_string(body->ns, out);
+       sdl_serialize_string(body->parts, out);
+       sdl_serialize_string(body->encodingStyle, out);
+       if (body->headers) {
+               i = zend_hash_num_elements(body->headers);
+       } else {
+               i = 0;
+       }
+       WSDL_CACHE_PUT_INT(i, out);
+       if (i > 0) {
+               sdlSoapBindingFunctionHeaderPtr *tmp;
+               zend_hash_internal_pointer_reset(body->headers);
+               while (zend_hash_get_current_data(body->headers, (void**)&tmp) == SUCCESS) {
+                       sdl_serialize_key(body->headers, out);
+                       WSDL_CACHE_PUT_1((*tmp)->use, out);
+                       sdl_serialize_string((*tmp)->name, out);
+                       sdl_serialize_string((*tmp)->ns, out);
+                       sdl_serialize_string((*tmp)->encodingStyle, out);
+                       sdl_serialize_encoder_ref((*tmp)->encode, tmp_encoders, out);
+                       sdl_serialize_type_ref((*tmp)->element, tmp_types, out);
+                       zend_hash_move_forward(body->headers);
+               }
+       }
+}
+
+static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr sdl)
+{
+       smart_str buf = {0};
+       smart_str *out = &buf;
+       int i;
+       int type_num = 1;
+       int encoder_num = 1;
+       int f;
+       encodePtr enc;
+       HashTable tmp_types;
+       HashTable tmp_encoders;
+       HashTable tmp_bindings;
+       HashTable tmp_functions;
+
+       f = open(fn,O_CREAT|O_WRONLY|O_EXCL|O_BINARY,S_IREAD|S_IWRITE);
+       if (f < 0) {return;}
+
+       zend_hash_init(&tmp_types, 0, NULL, NULL, 0);
+       zend_hash_init(&tmp_encoders, 0, NULL, NULL, 0);
+       zend_hash_init(&tmp_bindings, 0, NULL, NULL, 0);
+       zend_hash_init(&tmp_functions, 0, NULL, NULL, 0);
+
+       WSDL_CACHE_PUT_N("wsdl", 4, out);
+       WSDL_CACHE_PUT_1(WSDL_CACHE_VERSION,out);
+       WSDL_CACHE_PUT_1(0,out);
+       WSDL_CACHE_PUT_N(&t, sizeof(t), out);
+
+       sdl_serialize_string(uri, out);
+       sdl_serialize_string(sdl->source, out);
+       sdl_serialize_string(sdl->target_ns, out);
+
+       if (sdl->groups) {
+               i = zend_hash_num_elements(sdl->groups);
+       } else {
+               i = 0;
+       }
+       WSDL_CACHE_PUT_INT(i, out);
+       if (i > 0) {
+               sdlTypePtr *tmp;
+
+               zend_hash_internal_pointer_reset(sdl->groups);
+               while (zend_hash_get_current_data(sdl->groups, (void**)&tmp) == SUCCESS) {
+                       zend_hash_add(&tmp_types, (char*)tmp, sizeof(*tmp), (void**)&type_num, sizeof(type_num), NULL);
+                       ++type_num;
+                       zend_hash_move_forward(sdl->groups);
+               }
+       }
+
+       if (sdl->types) {
+               i = zend_hash_num_elements(sdl->types);
+       } else {
+               i = 0;
+       }
+       WSDL_CACHE_PUT_INT(i, out);
+       if (i > 0) {
+               sdlTypePtr *tmp;
+
+               zend_hash_internal_pointer_reset(sdl->types);
+               while (zend_hash_get_current_data(sdl->types, (void**)&tmp) == SUCCESS) {
+                       zend_hash_add(&tmp_types, (char*)tmp, sizeof(*tmp), (void**)&type_num, sizeof(type_num), NULL);
+                       ++type_num;
+                       zend_hash_move_forward(sdl->types);
+               }
+       }
+
+       if (sdl->elements) {
+               i = zend_hash_num_elements(sdl->elements);
+       } else {
+               i = 0;
+       }
+       WSDL_CACHE_PUT_INT(i, out);
+       if (i > 0) {
+               sdlTypePtr *tmp;
+
+               zend_hash_internal_pointer_reset(sdl->elements);
+               while (zend_hash_get_current_data(sdl->elements, (void**)&tmp) == SUCCESS) {
+                       zend_hash_add(&tmp_types, (char*)tmp, sizeof(*tmp), (void**)&type_num, sizeof(type_num), NULL);
+                       ++type_num;
+                       zend_hash_move_forward(sdl->elements);
+               }
+       }
+
+       if (sdl->encoders) {
+               i = zend_hash_num_elements(sdl->encoders);
+       } else {
+               i = 0;
+       }
+       WSDL_CACHE_PUT_INT(i, out);
+       if (i > 0) {
+               encodePtr *tmp;
+
+               zend_hash_internal_pointer_reset(sdl->encoders);
+               while (zend_hash_get_current_data(sdl->encoders, (void**)&tmp) == SUCCESS) {
+                       zend_hash_add(&tmp_encoders, (char*)tmp, sizeof(*tmp), (void**)&encoder_num, sizeof(encoder_num), NULL);
+                       ++encoder_num;
+                       zend_hash_move_forward(sdl->encoders);
+               }
+       }
+       enc = defaultEncoding;
+       while (enc->details.type != END_KNOWN_TYPES) {
+               zend_hash_add(&tmp_encoders, (char*)&enc, sizeof(encodePtr), (void**)&encoder_num, sizeof(encoder_num), NULL);
+               enc++;
+               ++encoder_num;
+       }
+
+       if (sdl->groups) {
+               sdlTypePtr *tmp;
+               zend_hash_internal_pointer_reset(sdl->groups);
+               while (zend_hash_get_current_data(sdl->groups, (void**)&tmp) == SUCCESS) {
+                       sdl_serialize_key(sdl->groups, out);
+                       sdl_serialize_type(*tmp, &tmp_encoders, &tmp_types, out);
+                       zend_hash_move_forward(sdl->groups);
+               }
+       }
+
+       if (sdl->types) {
+               sdlTypePtr *tmp;
+               zend_hash_internal_pointer_reset(sdl->types);
+               while (zend_hash_get_current_data(sdl->types, (void**)&tmp) == SUCCESS) {
+                       sdl_serialize_key(sdl->types, out);
+                       sdl_serialize_type(*tmp, &tmp_encoders, &tmp_types, out);
+                       zend_hash_move_forward(sdl->types);
+               }
+       }
+
+       if (sdl->elements) {
+               sdlTypePtr *tmp;
+               zend_hash_internal_pointer_reset(sdl->elements);
+               while (zend_hash_get_current_data(sdl->elements, (void**)&tmp) == SUCCESS) {
+                       sdl_serialize_key(sdl->elements, out);
+                       sdl_serialize_type(*tmp, &tmp_encoders, &tmp_types, out);
+                       zend_hash_move_forward(sdl->elements);
+               }
+       }
+
+       if (sdl->encoders) {
+               encodePtr *tmp;
+               zend_hash_internal_pointer_reset(sdl->encoders);
+               while (zend_hash_get_current_data(sdl->encoders, (void**)&tmp) == SUCCESS) {
+                       sdl_serialize_key(sdl->encoders, out);
+                       sdl_serialize_encoder(*tmp, &tmp_types, out);
+                       zend_hash_move_forward(sdl->encoders);
+               }
+       }
+
+       /* serialize bindings */
+       if (sdl->bindings) {
+               i = zend_hash_num_elements(sdl->bindings);
+       } else {
+               i = 0;
+       }
+       WSDL_CACHE_PUT_INT(i, out);
+       if (i > 0) {
+               sdlBindingPtr *tmp;
+               int binding_num = 1;
+
+               zend_hash_internal_pointer_reset(sdl->bindings);
+               while (zend_hash_get_current_data(sdl->bindings, (void**)&tmp) == SUCCESS) {
+                       sdl_serialize_key(sdl->bindings, out);
+                       sdl_serialize_string((*tmp)->name, out);
+                       sdl_serialize_string((*tmp)->location, out);
+                       WSDL_CACHE_PUT_1((*tmp)->bindingType,out);
+                       if ((*tmp)->bindingType == BINDING_SOAP && (*tmp)->bindingAttributes != NULL) {
+                               sdlSoapBindingPtr binding = (sdlSoapBindingPtr)(*tmp)->bindingAttributes;
+                               WSDL_CACHE_PUT_1(binding->style, out);
+                               sdl_serialize_string(binding->transport, out);
+                       } else {
+                               WSDL_CACHE_PUT_1(0,out);
+                       }
+
+                       zend_hash_add(&tmp_bindings, (char*)tmp, sizeof(*tmp), (void**)&binding_num, sizeof(binding_num), NULL);
+                       binding_num++;
+                       zend_hash_move_forward(sdl->bindings);
+               }
+       }
+
+       /* serialize functions */
+       i = zend_hash_num_elements(&sdl->functions);
+       WSDL_CACHE_PUT_INT(i, out);
+       if (i > 0) {
+               sdlFunctionPtr *tmp;
+               int *binding_num;
+               int function_num = 1;
+
+               zend_hash_internal_pointer_reset(&sdl->functions);
+               while (zend_hash_get_current_data(&sdl->functions, (void**)&tmp) == SUCCESS) {
+                       sdl_serialize_key(&sdl->functions, out);
+                       sdl_serialize_string((*tmp)->functionName, out);
+                       sdl_serialize_string((*tmp)->requestName, out);
+                       sdl_serialize_string((*tmp)->responseName, out);
+
+                       if ((*tmp)->binding == NULL ||
+                           zend_hash_find(&tmp_bindings,(char*)&(*tmp)->binding,sizeof((*tmp)->binding), (void**)&binding_num) != SUCCESS) {
+                       }
+                       WSDL_CACHE_PUT_INT(*binding_num, out);
+                       if (binding_num >= 0) {
+                               if ((*tmp)->binding->bindingType == BINDING_SOAP && (*tmp)->bindingAttributes != NULL) {
+                                       sdlSoapBindingFunctionPtr binding = (sdlSoapBindingFunctionPtr)(*tmp)->bindingAttributes;
+                                       WSDL_CACHE_PUT_1(binding->style, out);
+                                       sdl_serialize_string(binding->soapAction, out);
+                                       sdl_serialize_soap_body(&binding->input, &tmp_encoders, &tmp_types, out);
+                                       sdl_serialize_soap_body(&binding->output, &tmp_encoders, &tmp_types, out);
+                                       /*sdl_serialize_soap_body(&binding->fault, &tmp_encoders, &tmp_types, out);*/
+                               } else {
+                                       WSDL_CACHE_PUT_1(0,out);
+                               }
+                       }
+                       sdl_serialize_parameters((*tmp)->requestParameters, &tmp_encoders, &tmp_types, out);
+                       sdl_serialize_parameters((*tmp)->responseParameters, &tmp_encoders, &tmp_types, out);
+
+                       zend_hash_add(&tmp_functions, (char*)tmp, sizeof(*tmp), (void**)&function_num, sizeof(function_num), NULL);
+                       function_num++;
+                       zend_hash_move_forward(&sdl->functions);
+               }
+       }
+
+       /* serialize requests */
+       if (sdl->requests) {
+               i = zend_hash_num_elements(sdl->requests);
+       } else {
+               i = 0;
+       }
+       WSDL_CACHE_PUT_INT(i, out);
+       if (i > 0) {
+               sdlFunctionPtr *tmp;
+               int *function_num;
+
+               zend_hash_internal_pointer_reset(sdl->requests);
+               while (zend_hash_get_current_data(sdl->requests, (void**)&tmp) == SUCCESS) {
+                       if (zend_hash_find(&tmp_functions, (char*)tmp, sizeof(*tmp), (void**)&function_num) != SUCCESS) {
+                       }
+                       WSDL_CACHE_PUT_INT(*function_num, out);
+                       sdl_serialize_key(sdl->requests, out);
+                       zend_hash_move_forward(sdl->requests);
+               }
+       }
+
+       write(f, buf.c, buf.len);
+       close(f);
+       smart_str_free(&buf);
+       zend_hash_destroy(&tmp_functions);
+       zend_hash_destroy(&tmp_bindings);
+       zend_hash_destroy(&tmp_encoders);
+       zend_hash_destroy(&tmp_types);
+}
+
+sdlPtr get_sdl(char *uri TSRMLS_DC)
 {
 #ifdef SDL_CACHE
        sdlPtr tmp, *hndl;
@@ -768,7 +1829,43 @@ sdlPtr get_sdl(char *uri)
 
        return tmp;
 #else
-       return load_wsdl(uri);
+       if (SOAP_GLOBAL(cache_enabled)) {
+               char  fn[MAXPATHLEN];
+               char* key;
+               sdlPtr sdl;
+               time_t t = time(0);
+
+         char md5str[33];
+       PHP_MD5_CTX context;
+         unsigned char digest[16];
+         int len = strlen(SOAP_GLOBAL(cache_dir));
+
+         if (strchr(uri,':') != NULL || IS_ABSOLUTE_PATH(uri,strlen(uri))) {
+                 strcpy(fn, uri);
+               } else if (VCWD_REALPATH(uri, fn) == NULL) {
+                       return load_wsdl(uri);
+               }
+         md5str[0] = '\0';
+         PHP_MD5Init(&context);
+         PHP_MD5Update(&context, fn, strlen(fn));
+         PHP_MD5Final(digest, &context);
+         make_digest(md5str, digest);
+         key = do_alloca(len+sizeof("/wsdl-")-1+sizeof(md5str));
+         memcpy(key,SOAP_GLOBAL(cache_dir),len);
+         memcpy(key+len,"/wsdl-",sizeof("/wsdl-")-1);
+         memcpy(key+len+sizeof("/wsdl-")-1,md5str,sizeof(md5str));
+
+               if ((sdl = get_sdl_from_cache(key, fn, t-SOAP_GLOBAL(cache_ttl))) == NULL) {
+                       sdl = load_wsdl(fn);
+                       if (sdl != NULL) {
+                               add_sdl_to_cache(key, fn, t, sdl);
+                       }
+               }
+               free_alloca(key);
+               return sdl;
+       } else {
+               return load_wsdl(uri);
+       }
 #endif
 }
 
@@ -884,13 +1981,13 @@ static void delete_function(void *data)
                }
                delete_sdl_soap_binding_function_body(soapFunction->input);
                delete_sdl_soap_binding_function_body(soapFunction->output);
-               delete_sdl_soap_binding_function_body(soapFunction->falut);
+               delete_sdl_soap_binding_function_body(soapFunction->fault);
                sdl_free(soapFunction);
        }
        sdl_free(function);
 }
 
-static void delete_paramater(void *data)
+static void delete_parameter(void *data)
 {
        sdlParamPtr param = *((sdlParamPtr*)data);
        if (param->paramName) {
index 2886f1200efc88ed13764e506f1b6ba74624eab3..3e7742386b9e083e364e93f9940c81df6228913a 100644 (file)
 #define XSD_WHITESPACE_PRESERVE 1
 #define XSD_WHITESPACE_REPLACE  1
 
-#define BINDING_SOAP 1
-#define BINDING_HTTP 2
+typedef enum _sdlBindingType {
+       BINDING_SOAP = 1,
+       BINDING_HTTP = 2
+} sdlBindingType;
 
-#define SOAP_RPC 1
-#define SOAP_DOCUMENT 2
+typedef enum _sdlEncodingStyle {
+       SOAP_RPC = 1,
+       SOAP_DOCUMENT = 2
+} sdlEncodingStyle;
 
-#define SOAP_ENCODED 1
-#define SOAP_LITERAL 2
+typedef enum _sdlEncodingUse {
+       SOAP_ENCODED = 1,
+       SOAP_LITERAL = 2
+} sdlEncodingUse;
 
 struct _sdl {
        HashTable  functions;        /* array of sdlFunction */
@@ -74,42 +80,42 @@ typedef struct sdlCtx {
 } sdlCtx;
 
 struct _sdlBinding {
-       char *name;
-       char *location;
-       int   bindingType;
-       void *bindingAttributes; /* sdlSoapBindingPtr */
+       char           *name;
+       char           *location;
+       sdlBindingType  bindingType;
+       void           *bindingAttributes; /* sdlSoapBindingPtr */
 };
 
 /* Soap Binding Specfic stuff */
 struct _sdlSoapBinding {
-       char *transport;
-       int   style;
+       char             *transport;
+       sdlEncodingStyle  style;
 };
 
 typedef struct _sdlSoapBindingFunctionHeader {
-       char       *name;
-       char       *ns;
-       int         use;
-       sdlTypePtr  element;
-       encodePtr   encode;
-       char       *encodingStyle; /* not implemented yet */
+       char           *name;
+       char           *ns;
+       sdlEncodingUse  use;
+       sdlTypePtr      element;
+       encodePtr       encode;
+       char           *encodingStyle; /* not implemented yet */
 } sdlSoapBindingFunctionHeader, *sdlSoapBindingFunctionHeaderPtr;
 
 struct _sdlSoapBindingFunctionBody {
-       char      *ns;
-       int        use;
-       char      *parts;          /* not implemented yet */
-       char      *encodingStyle;  /* not implemented yet */
-       HashTable *headers;        /* array of sdlSoapBindingFunctionHeaderPtr */
+       char           *ns;
+       sdlEncodingUse  use;
+       char           *parts;          /* not implemented yet */
+       char           *encodingStyle;  /* not implemented yet */
+       HashTable      *headers;        /* array of sdlSoapBindingFunctionHeaderPtr */
 };
 
 struct _sdlSoapBindingFunction {
-       char *soapAction;
-       int   style;
+       char                       *soapAction;
+       sdlEncodingStyle            style;
 
-       sdlSoapBindingFunctionBody input;
-       sdlSoapBindingFunctionBody output;
-       sdlSoapBindingFunctionBody falut;
+       sdlSoapBindingFunctionBody  input;
+       sdlSoapBindingFunctionBody  output;
+       sdlSoapBindingFunctionBody  fault;
 };
 
 struct _sdlRestrictionInt {
@@ -155,7 +161,7 @@ struct _sdlContentModel {
        int max_occurs;
        union {
                sdlTypePtr          element;      /* pointer to element */
-               sdlContentModelPtr  group;        /* pointer to group */
+               sdlTypePtr          group;        /* pointer to group */
                HashTable          *content;      /* array of sdlContentModel for sequnce,all,choice*/
                char               *group_ref;    /* reference to group */
        } u;
@@ -174,7 +180,7 @@ struct _sdlType {
        sdlTypeKind         kind;
        char               *name;
        char               *namens;
-       int                 nillable;
+       char                nillable;
        HashTable          *elements;             /* array of sdlTypePtr */
        HashTable          *attributes;           /* array of sdlAttributePtr */
        sdlRestrictionsPtr  restrictions;
@@ -231,7 +237,7 @@ struct _sdlAttribute {
        encodePtr  encode;
 };
 
-sdlPtr get_sdl(char *uri);
+sdlPtr get_sdl(char *uri TSRMLS_DC);
 
 encodePtr get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr data, const char *type);
 encodePtr get_encoder(sdlPtr sdl, const char *ns, const char *type);
index 3986cc064c725c7dea6223afade5fc478dd64b20..192289f377156ad1886224f741ef529cd2bdd904 100644 (file)
@@ -148,6 +148,9 @@ ZEND_BEGIN_MODULE_GLOBALS(soap)
        int        soap_version;
        sdlPtr     sdl;
        zend_bool  use_soap_error_handler;
+       zend_bool  cache_enabled;
+       char*      cache_dir;
+       long       cache_ttl;
 ZEND_END_MODULE_GLOBALS(soap)
 
 #ifdef PHP_WIN32
index 5f96b765794b61f24bd1384fa43248ceedec77b8..5e1e47a10b51a21db8be1463909994b1e03fe671 100644 (file)
@@ -278,6 +278,20 @@ zend_module_entry soap_module_entry = {
 ZEND_GET_MODULE(soap)
 #endif
 
+PHP_INI_BEGIN()
+STD_PHP_INI_ENTRY("soap.wsdl_cache_enabled",     "1", PHP_INI_ALL, OnUpdateBool,
+                  cache_enabled, zend_soap_globals, soap_globals)
+STD_PHP_INI_ENTRY("soap.wsdl_cache_dir",         "/tmp", PHP_INI_ALL, OnUpdateString,
+                  cache_dir, zend_soap_globals, soap_globals)
+#ifdef ZEND_ENGINE_2
+STD_PHP_INI_ENTRY("soap.wsdl_cache_ttl",         "86400", PHP_INI_ALL, OnUpdateLong,
+                  cache_ttl, zend_soap_globals, soap_globals)
+#else
+STD_PHP_INI_ENTRY("soap.wsdl_cache_ttl",         "86400", PHP_INI_ALL, OnUpdateInt,
+                  cache_ttl, zend_soap_globals, soap_globals)
+#endif
+PHP_INI_END()
+
 static void php_soap_init_globals(zend_soap_globals *soap_globals)
 {
        int i;
@@ -343,6 +357,7 @@ PHP_MINIT_FUNCTION(soap)
 
        /* TODO: add ini entry for always use soap errors */
        ZEND_INIT_MODULE_GLOBALS(soap, php_soap_init_globals, NULL);
+  REGISTER_INI_ENTRIES();
 
 #ifndef ZEND_ENGINE_2
        /* Enable php stream/wrapper support for libxml */
@@ -489,6 +504,7 @@ PHP_MINFO_FUNCTION(soap)
        php_info_print_table_row(2, "Soap Client", "enabled");
        php_info_print_table_row(2, "Soap Server", "enabled");
        php_info_print_table_end();
+       DISPLAY_INI_ENTRIES();
 }
 
 #ifdef HAVE_PHP_DOMXML
@@ -695,7 +711,7 @@ PHP_METHOD(soapserver,soapserver)
        zend_hash_init(service->soap_functions.ft, 0, NULL, ZVAL_PTR_DTOR, 0);
 
        if (wsdl) {
-               service->sdl = get_sdl(Z_STRVAL_P(wsdl));
+               service->sdl = get_sdl(Z_STRVAL_P(wsdl) TSRMLS_CC);
                if (service->uri == NULL) {
                        if (service->sdl->target_ns) {
                                service->uri = estrdup(service->sdl->target_ns);
@@ -1130,6 +1146,7 @@ PHP_METHOD(soapserver, handle)
                                php_error(E_ERROR, "PHP-SOAP requires 'always_populate_raw_post_data' to be on please check your php.ini file");
                        }
                        php_error(E_ERROR, "Can't find HTTP_RAW_POST_DATA");
+                       return;
                }
        } else {
                doc_request = soap_xmlParseMemory(arg,arg_len);
@@ -1577,7 +1594,7 @@ PHP_METHOD(soapclient, soapclient)
                old_soap_version = SOAP_GLOBAL(soap_version);
                SOAP_GLOBAL(soap_version) = soap_version;
 
-               sdl = get_sdl(Z_STRVAL_P(wsdl));
+               sdl = get_sdl(Z_STRVAL_P(wsdl) TSRMLS_CC);
                ret = zend_list_insert(sdl, le_sdl);
 
                add_property_resource(this_ptr, "sdl", ret);