]> granicus.if.org Git - php/commitdiff
import php-soap library from sourceforge
authorShane Caraveo <shane@php.net>
Sun, 7 Jul 2002 23:03:43 +0000 (23:03 +0000)
committerShane Caraveo <shane@php.net>
Sun, 7 Jul 2002 23:03:43 +0000 (23:03 +0000)
22 files changed:
ext/soap/EXPERIMENTAL [new file with mode: 0644]
ext/soap/Makefile [new file with mode: 0644]
ext/soap/Makefile.in [new file with mode: 0644]
ext/soap/TODO [new file with mode: 0644]
ext/soap/config.m4 [new file with mode: 0644]
ext/soap/libs.mk [new file with mode: 0644]
ext/soap/package.xml [new file with mode: 0644]
ext/soap/php_encoding.c [new file with mode: 0644]
ext/soap/php_encoding.h [new file with mode: 0644]
ext/soap/php_http.c [new file with mode: 0644]
ext/soap/php_http.h [new file with mode: 0644]
ext/soap/php_packet_soap.c [new file with mode: 0644]
ext/soap/php_packet_soap.h [new file with mode: 0644]
ext/soap/php_schema.c [new file with mode: 0644]
ext/soap/php_schema.h [new file with mode: 0644]
ext/soap/php_sdl.c [new file with mode: 0644]
ext/soap/php_sdl.h [new file with mode: 0644]
ext/soap/php_soap.dsp [new file with mode: 0644]
ext/soap/php_soap.h [new file with mode: 0644]
ext/soap/php_xml.c [new file with mode: 0644]
ext/soap/php_xml.h [new file with mode: 0644]
ext/soap/soap.c [new file with mode: 0644]

diff --git a/ext/soap/EXPERIMENTAL b/ext/soap/EXPERIMENTAL
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/ext/soap/Makefile b/ext/soap/Makefile
new file mode 100644 (file)
index 0000000..1107a70
--- /dev/null
@@ -0,0 +1,13 @@
+top_srcdir   = /usr/local/src/php-4.2.0
+top_builddir = /usr/local/src/php-4.2.0
+srcdir       = /usr/local/src/php-4.2.0/ext/soap
+builddir     = /usr/local/src/php-4.2.0/ext/soap
+VPATH        = /usr/local/src/php-4.2.0/ext/soap
+# $Id$
+
+LTLIBRARY_NAME        = libsoap.la
+LTLIBRARY_SOURCES     = soap.c php_sdl.c php_schema.c php_xml.c php_encoding.c php_http.c php_packet_soap.c
+LTLIBRARY_SHARED_NAME = soap.la
+LTLIBRARY_SHARED_LIBADD  = $(SOAP_SHARED_LIBADD)
+
+include $(top_srcdir)/build/dynlib.mk
diff --git a/ext/soap/Makefile.in b/ext/soap/Makefile.in
new file mode 100644 (file)
index 0000000..eb52167
--- /dev/null
@@ -0,0 +1,8 @@
+# $Id$
+
+LTLIBRARY_NAME        = libsoap.la
+LTLIBRARY_SOURCES     = soap.c php_sdl.c php_schema.c php_xml.c php_encoding.c php_http.c php_packet_soap.c
+LTLIBRARY_SHARED_NAME = soap.la
+LTLIBRARY_SHARED_LIBADD  = $(SOAP_SHARED_LIBADD)
+
+include $(top_srcdir)/build/dynlib.mk
diff --git a/ext/soap/TODO b/ext/soap/TODO
new file mode 100644 (file)
index 0000000..b70760a
--- /dev/null
@@ -0,0 +1,36 @@
+TODO:
+make sure soap 1.1 and 1.2 is supported fully
+Better WSDL support Client and server (how much validation is needed here?)
+UDDI??
+make internal refrences for soap encoding (use seralization logic)
+add ini option for always soap_error_handler
+provide user space overriding of serialization certin objects and types
+serialization in general needs to be polished/finished... all xsd types
+make perstistant objects and work with or without register_globals on
+look to see if php-soap will work with out always_populate_raw_post_data on
+see if client will work with ssl.. should be eaiser with php_streams
+work on soap seralizer (php serialization)
+work on a soap-service 'regiestry' and 'proxy' (apache soap style)
+convert all string mainpulation to use smart_str
+make the 'soap' packet abstract.. maybe incorperate xml-rpc
+make the transport layer abstract.. what other transport layers are needed?... who uses smtp? what about jabber?
+make $soap_object->data = 'text'; maybe invoke a set_*() and/or get_*() method
+when using wsdls and function names are similar find the best match
+       void test(int);
+       void test(string);
+       maybe use the same alogrithim as ext/java.
+investigate further http keep_alive... inital testing proved slower.. maybe php_streams will speed things up..
+provide schema 1999/2001 support....
+through memory leak testing
+possible using shared memory for sdl caching...
+api for clearing/checking sdl caching...
+make php-soap work as a standalone server using php_streams and the new socket extension
+http authication
+proxy support
+wsdl generation static and auto (.net style (http://server.com/soapserver.php?WSDL)) using phpdoc parsing engine
+interpo testing...
+BENCHMARKING...... lets prove how fast it is.
+do some more work on website
+
+does this list stop... what exactly have i done?
+im sure im forgetting 20 thousand more things....
diff --git a/ext/soap/config.m4 b/ext/soap/config.m4
new file mode 100644 (file)
index 0000000..44c12cb
--- /dev/null
@@ -0,0 +1,16 @@
+dnl $Id$
+dnl config.m4 for extension soap
+
+dnl Comments in this file start with the string 'dnl'.
+dnl Remove where necessary. This file will not work
+dnl without editing.
+
+PHP_ARG_ENABLE(soap, whether to enable soap support,
+Make sure that the comment is aligned:
+[  --enable-soap           Enable soap support])
+
+if test "$PHP_SOAP" != "no"; then
+  PHP_ADD_INCLUDE(/usr/local/include/libxml2)
+  PHP_ADD_LIBRARY_WITH_PATH(xml2,/usr/local/lib,SOAP_SHARED_LIBADD)
+  PHP_EXTENSION(soap, $ext_shared)
+fi
diff --git a/ext/soap/libs.mk b/ext/soap/libs.mk
new file mode 100644 (file)
index 0000000..7c6e176
--- /dev/null
@@ -0,0 +1,7 @@
+include $(top_builddir)/config_vars.mk
+LTLIBRARY_OBJECTS = $(LTLIBRARY_SOURCES:.c=.lo) $(LTLIBRARY_OBJECTS_X)
+LTLIBRARY_SHARED_OBJECTS = $(LTLIBRARY_OBJECTS:.lo=.slo)
+$(LTLIBRARY_NAME): $(LTLIBRARY_OBJECTS) $(LTLIBRARY_DEPENDENCIES)
+       $(LINK) $(LTLIBRARY_LDFLAGS) $(LTLIBRARY_OBJECTS) $(LTLIBRARY_LIBADD)
+
+targets = $(LTLIBRARY_NAME)
diff --git a/ext/soap/package.xml b/ext/soap/package.xml
new file mode 100644 (file)
index 0000000..2299be5
--- /dev/null
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!-- do not use the "Type" attribute here, that one is only for
+     generated package.xml files -->
+<package>
+  <name>php_soap</name>
+  <summary>Provides SOAP Services</summary>
+  <status>beta</status>
+  <maintainer>
+    <user>rodif_bl</user>
+    <name>Brad Lafountain</name>
+    <email>rodif_bl@yahoo.com</email>
+    <role>lead</role>
+  </maintainer>
+  <maintainer>
+    <user>shane</user>
+    <name>Shane Caraveo</name>
+    <email>shane@caraveo.com</email>
+    <role>lead</role>
+  </maintainer>
+  <release>
+    <version>0.1</version>
+    <date>2002-07-07</date>
+    <notes>
+       - First offical PEAR/PECL release
+    </notes>
+  </release>
+  <filelist>
+    <dir role="source" name="/" baseinstalldir="iisfunc">
+        <file>EXPERIMENTAL</file>
+        <file>TODO</file>
+        <file>config.m4</file>
+        <file>Makefile</file>
+        <file>Makefile.in</file>
+        <file>libs.mk</file>
+        <file>php_encoding.c</file>
+        <file>php_encoding.h</file>
+        <file>php_http.c</file>
+        <file>php_http.h</file>
+        <file>php_packet_soap.c</file>
+        <file>php_packet_soap.h</file>
+        <file>php_schema.c</file>
+        <file>php_schema.h</file>
+        <file>php_sdl.c</file>
+        <file>php_sdl.h</file>
+        <file>php_soap.h</file>
+        <file>php_soap.h</file>
+        <file>php_xml.c</file>
+        <file>php_xml.h</file>
+        <file>soap.c</file>
+        <file>soap.dsp</file>
+    </dir>
+  </filelist>
+</package>
+
diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c
new file mode 100644 (file)
index 0000000..55e4e4f
--- /dev/null
@@ -0,0 +1,1085 @@
+#include <time.h>
+
+#include "php_soap.h"
+
+encode defaultEncoding[] = {
+       {{UNKNOWN_TYPE, NULL, NULL, NULL}, guess_zval_convert, guess_xml_convert},
+
+       {{IS_NULL, "null", "null", NULL}, to_zval_null, to_xml_null},
+       {{IS_STRING, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
+       {{IS_LONG, XSD_INT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
+       {{IS_DOUBLE, XSD_FLOAT_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_string},
+       {{IS_BOOL, XSD_BOOLEAN_STRING, XSD_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
+       {{IS_CONSTANT, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
+       {{IS_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_ENC_NAMESPACE, NULL}, to_zval_array, guess_array_map},
+       {{IS_CONSTANT_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
+       {{IS_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
+
+       {{XSD_STRING, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
+       {{XSD_BOOLEAN, XSD_BOOLEAN_STRING, XSD_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
+       {{XSD_DECIMAL, XSD_DECIMAL_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_string},
+       {{XSD_FLOAT, XSD_FLOAT_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_string},
+       {{XSD_DOUBLE, XSD_DOUBLE_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_string},
+       {{XSD_DATETIME, XSD_DATETIME_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_datetime},
+       {{XSD_TIME, XSD_TIME_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_time},
+       {{XSD_DATE, XSD_DATE_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_date},
+       {{XSD_GYEARMONTH, XSD_GYEARMONTH_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_gyearmonth},
+       {{XSD_GYEAR, XSD_GYEAR_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_gyear},
+       {{XSD_GMONTHDAY, XSD_GMONTHDAY_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_gmonthday},
+       {{XSD_GDAY, XSD_GDAY_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_gday},
+       {{XSD_GMONTH, XSD_GMONTH_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_gmonth},
+       {{XSD_HEXBINARY, XSD_HEXBINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_stringl},
+       {{XSD_BASE64BINARY, XSD_BASE64BINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_stringl},
+
+       {{XSD_LONG, XSD_LONG_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
+       {{XSD_INT, XSD_INT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_string},
+       {{XSD_SHORT, XSD_SHORT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_string},
+
+       {{APACHE_MAP, APACHE_MAP_STRING, APACHE_NAMESPACE, NULL}, to_zval_map, to_xml_map},
+
+       {{SOAP_ENC_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
+       {{SOAP_ENC_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
+
+       //support some of the 1999 data types
+       {{XSD_STRING, XSD_STRING_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_string, to_xml_string},
+       {{XSD_BOOLEAN, XSD_BOOLEAN_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
+       {{XSD_DECIMAL, XSD_DECIMAL_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_string},
+       {{XSD_FLOAT, XSD_FLOAT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_double, to_xml_string},
+       {{XSD_DOUBLE, XSD_DOUBLE_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_double, to_xml_string},
+       {{XSD_LONG, XSD_LONG_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
+       {{XSD_INT, XSD_INT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_string},
+       {{XSD_SHORT, XSD_SHORT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_string},
+       {{XSD_1999_TIMEINSTANT, XSD_1999_TIMEINSTANT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_string, to_xml_string},
+
+       {{END_KNOWN_TYPES, NULL, NULL, NULL}, guess_zval_convert, guess_xml_convert}
+
+//TODO: finish off encoding
+/*
+#define XSD_DURATION 107
+#define XSD_DURATION_STRING "duration"
+#define XSD_ANYURI 118
+#define XSD_ANYURI_STRING "anyURI"
+#define XSD_QNAME 119
+#define XSD_QNAME_STRING "QName"
+#define XSD_NOTATION 120
+#define XSD_NOTATION_STRING "NOTATION"
+*/
+
+/*
+#define XSD_NORMALIZEDSTRING 121
+#define XSD_NORMALIZEDSTRING_STRING "normalizedString"
+#define XSD_TOKEN 122
+#define XSD_TOKEN_STRING "token"
+#define XSD_LANGUAGE 123
+#define XSD_LANGUAGE_STRING "language"
+#define XSD_NMTOKEN 124
+#define XSD_NMTOKEN_STRING "NMTOKEN"
+#define XSD_NAME 124
+#define XSD_NAME_STRING "Name"
+#define XSD_NCNAME 125
+#define XSD_NCNAME_STRING "NCName"
+#define XSD_ID 126
+#define XSD_ID_STRING "ID"
+#define XSD_IDREF 127
+#define XSD_IDREF_STRING "IDREF"
+#define XSD_IDREFS 127
+#define XSD_IDREFS_STRING "IDREFS"
+#define XSD_ENTITY 128
+#define XSD_ENTITY_STRING "ENTITY"
+#define XSD_ENTITYS 129
+#define XSD_ENTITYS_STRING "ENTITYS"
+#define XSD_INTEGER 130
+#define XSD_INTEGER_STRING "integer"
+#define XSD_NONPOSITIVEINTEGER 131
+#define XSD_NONPOSITIVEINTEGER_STRING "nonPositiveInteger"
+#define XSD_NEGATIVEINTEGER 132
+#define XSD_NEGATIVEINTEGER_STRING "negativeInteger"
+#define XSD_NONNEGATIVEINTEGER 137
+#define XSD_NONNEGATIVEINTEGER_STRING "nonNegativeInteger"
+#define XSD_UNSIGNEDLONG 138
+#define XSD_UNSIGNEDLONG_STRING "unsignedLong"
+#define XSD_UNSIGNEDINT 139
+#define XSD_UNSIGNEDINT_STRING "unsignedInt"
+#define XSD_UNSIGNEDSHORT 140
+#define XSD_UNSIGNEDSHORT_STRING "unsignedShort"
+#define XSD_UNSIGNEDBYTE 141
+#define XSD_UNSIGNEDBYTE_STRING "unsignedByte"
+#define XSD_POSITIVEINTEGER 142
+#define XSD_POSITIVEINTEGER_STRING "positiveInteger"
+*/
+};
+
+xmlNodePtr master_to_xml(encodePtr encode, zval *data)
+{
+       xmlNodePtr node;
+
+       if(encode->to_xml_before)
+               data = encode->to_xml_before(encode->details, data);
+       if(encode->to_xml)
+               node = encode->to_xml(encode->details, data);
+       if(encode->to_xml_after)
+               node = encode->to_xml_after(encode->details, node);
+
+       return node;
+}
+
+zval *master_to_zval(encodePtr encode, xmlNodePtr data)
+{
+       zval *ret;
+
+       data = check_and_resolve_href(data);
+       if(encode->to_zval_before)
+               data = encode->to_zval_before(encode->details, data);
+       if(encode->to_zval)
+               ret = encode->to_zval(encode->details, data);
+       if(encode->to_zval_after)
+               ret = encode->to_zval_after(encode->details, ret);
+
+       return ret;
+}
+
+#ifdef HAVE_PHP_DOMXML
+zval *to_xml_before_user(encodeType type, zval *data)
+{
+       TSRMLS_FETCH();
+
+       if(type.map->map_functions.to_xml_before)
+       {
+               if(call_user_function(EG(function_table), NULL, type.map->map_functions.to_xml_before, data, 1, &data  TSRMLS_CC) == FAILURE)
+                       php_error(E_ERROR, "Error calling to_xml_before");
+       }
+       return data;
+}
+
+xmlNodePtr to_xml_user(encodeType type, zval *data)
+{
+       zval *ret, **addr;
+       xmlNodePtr node;
+       TSRMLS_FETCH();
+
+       if(type.map->map_functions.to_xml)
+       {
+               MAKE_STD_ZVAL(ret);
+               if(call_user_function(EG(function_table), NULL, type.map->map_functions.to_xml, ret, 1, &data  TSRMLS_CC) == FAILURE)
+                       php_error(E_ERROR, "Error calling to_xml");
+
+               if(Z_TYPE_P(ret) != IS_OBJECT)
+                       php_error(E_ERROR, "Error serializing object from to_xml_user");
+
+               if(zend_hash_index_find(Z_OBJPROP_P(ret), 1, (void **)&addr) == SUCCESS)
+               {
+                       node = (xmlNodePtr)Z_LVAL_PP(addr);
+                       node = xmlCopyNode(node, 1);
+                       set_ns_and_type(node, type);
+               }
+               zval_ptr_dtor(&ret);
+       }
+       return node;
+}
+
+xmlNodePtr to_xml_after_user(encodeType type, xmlNodePtr node)
+{
+       zval *ret, *param, **addr;
+       int found;
+       TSRMLS_FETCH();
+
+       if(type.map->map_functions.to_xml_after)
+       {
+               MAKE_STD_ZVAL(ret);
+               MAKE_STD_ZVAL(param);
+               param = php_domobject_new(node, &found, NULL TSRMLS_CC);
+
+               if(call_user_function(EG(function_table), NULL, type.map->map_functions.to_xml_after, ret, 1, &param  TSRMLS_CC) == FAILURE)
+                       php_error(E_ERROR, "Error calling to_xml_after");
+               if(zend_hash_index_find(Z_OBJPROP_P(ret), 1, (void **)&addr) == SUCCESS)
+               {
+                       node = (xmlNodePtr)Z_LVAL_PP(addr);
+                       set_ns_and_type(node, type);
+               }
+               zval_ptr_dtor(&ret);
+               zval_ptr_dtor(&param);
+       }
+       return node;
+}
+
+xmlNodePtr to_zval_before_user(encodeType type, xmlNodePtr node)
+{
+       zval *ret, *param, **addr;
+       int found;
+       TSRMLS_FETCH();
+
+       if(type.map->map_functions.to_zval_before)
+       {
+               MAKE_STD_ZVAL(ret);
+               MAKE_STD_ZVAL(param);
+               param = php_domobject_new(node, &found, NULL TSRMLS_CC);
+
+               if(call_user_function(EG(function_table), NULL, type.map->map_functions.to_zval_before, ret, 1, &param  TSRMLS_CC) == FAILURE)
+                       php_error(E_ERROR, "Error calling to_zval_before");
+               if(zend_hash_index_find(Z_OBJPROP_P(ret), 1, (void **)&addr) == SUCCESS)
+               {
+                       node = (xmlNodePtr)Z_LVAL_PP(addr);
+                       set_ns_and_type(node, type);
+               }
+               zval_ptr_dtor(&ret);
+               zval_ptr_dtor(&param);
+       }
+       return node;
+}
+
+zval *to_zval_user(encodeType type, xmlNodePtr node)
+{
+       zval *ret, *param;
+       int found;
+       TSRMLS_FETCH();
+
+       if(type.map->map_functions.to_zval)
+       {
+               MAKE_STD_ZVAL(ret);
+               MAKE_STD_ZVAL(param);
+               param = php_domobject_new(node, &found, NULL TSRMLS_CC);
+
+               if(call_user_function(EG(function_table), NULL, type.map->map_functions.to_zval, ret, 1, &param  TSRMLS_CC) == FAILURE)
+                       php_error(E_ERROR, "Error calling to_zval");
+               zval_ptr_dtor(&param);
+       }
+       return ret;
+}
+
+zval *to_zval_after_user(encodeType type, zval *data)
+{
+       TSRMLS_FETCH();
+
+       if(type.map->map_functions.to_zval_after)
+       {
+               if(call_user_function(EG(function_table), NULL, type.map->map_functions.to_zval_after, data, 1, &data  TSRMLS_CC) == FAILURE)
+                       php_error(E_ERROR, "Error calling to_xml_before");
+       }
+       return data;
+}
+#endif
+
+//TODO: get rid of "bogus".. ither by passing in the already created xmlnode or passing in the node name
+//String encode/decode
+zval *to_zval_string(encodeType type, xmlNodePtr data)
+{
+       zval *ret;
+       MAKE_STD_ZVAL(ret);
+       FIND_XML_NULL(data, ret);
+
+       if(data && data->children)
+               ZVAL_STRING(ret, data->children->content, 1);
+       return ret;
+}
+
+zval *to_zval_stringl(encodeType type, xmlNodePtr data)
+{
+       zval *ret;
+       MAKE_STD_ZVAL(ret);
+       FIND_XML_NULL(data, ret);
+
+       if(data && data->children)
+               ZVAL_STRINGL(ret, data->children->content, xmlStrlen(data->children->content), 1);
+       return ret;
+}
+
+xmlNodePtr to_xml_string(encodeType type, zval *data)
+{
+       xmlNodePtr ret;
+       char *str;
+       int new_len;
+
+       ret = xmlNewNode(NULL, "BOGUS");
+       FIND_ZVAL_NULL(data, ret);
+
+       convert_to_string(data);
+       str = php_escape_html_entities(Z_STRVAL_P(data), Z_STRLEN_P(data), &new_len, 0, 0, NULL);
+       xmlNodeSetContentLen(ret, str, new_len);
+       set_ns_and_type(ret, type);
+       return ret;
+}
+
+xmlNodePtr to_xml_stringl(encodeType type, zval *data)
+{
+       xmlNodePtr ret;
+
+       ret = xmlNewNode(NULL, "BOGUS");
+       FIND_ZVAL_NULL(data, ret);
+
+       convert_to_string(data);
+       xmlNodeSetContentLen(ret, estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data)), Z_STRLEN_P(data));
+       set_ns_and_type(ret, type);
+       return ret;
+}
+
+zval *to_zval_double(encodeType type, xmlNodePtr data)
+{
+       zval *ret;
+       MAKE_STD_ZVAL(ret);
+       FIND_XML_NULL(data, ret);
+
+       ZVAL_DOUBLE(ret, atof(data->children->content));
+       return ret;
+}
+
+zval *to_zval_long(encodeType type, xmlNodePtr data)
+{
+       zval *ret;
+       MAKE_STD_ZVAL(ret);
+       FIND_XML_NULL(data, ret);
+
+       ZVAL_LONG(ret, atol(data->children->content));
+       return ret;
+}
+
+xmlNodePtr to_xml_long(encodeType type, zval *data)
+{
+       xmlNodePtr ret;
+
+       ret = xmlNewNode(NULL, "BOGUS");
+       FIND_ZVAL_NULL(data, ret);
+
+       convert_to_long(data);
+       convert_to_string(data);
+       xmlNodeSetContentLen(ret, Z_STRVAL_P(data), Z_STRLEN_P(data));
+       set_ns_and_type(ret, type);
+       return ret;
+}
+
+zval *to_zval_bool(encodeType type, xmlNodePtr data)
+{
+       zval *ret;
+       MAKE_STD_ZVAL(ret);
+       FIND_XML_NULL(data, ret);
+
+       if(stricmp(data->children->content,"true") == 0 ||
+               stricmp(data->children->content,"t") == 0 ||
+               strcmp(data->children->content,"1") == 0)
+       {
+               ZVAL_BOOL(ret, 1);
+       }
+       else
+       {
+               ZVAL_BOOL(ret, 0);
+       }
+       return ret;
+}
+
+xmlNodePtr to_xml_bool(encodeType type, zval *data)
+{
+       xmlNodePtr ret;
+
+       ret = xmlNewNode(NULL, "BOGUS");
+       FIND_ZVAL_NULL(data, ret);
+
+       convert_to_boolean(data);
+       if(data->value.lval == 1)
+               xmlNodeSetContent(ret, "1");
+       else
+               xmlNodeSetContent(ret, "0");
+
+       set_ns_and_type(ret, type);
+       return ret;
+}
+
+//Null encode/decode
+zval *to_zval_null(encodeType type, xmlNodePtr data)
+{
+       zval *ret;
+       MAKE_STD_ZVAL(ret);
+       ZVAL_NULL(ret);
+       return ret;
+}
+
+xmlNodePtr to_xml_null(encodeType type, zval *data)
+{
+       xmlNodePtr ret;
+
+       ret = xmlNewNode(NULL, "BOGUS");
+       FIND_ZVAL_NULL(data, ret);
+       xmlSetProp(ret, "xsi:null", "1");
+
+       return ret;
+}
+
+//Struct encode/decode
+zval *to_zval_object(encodeType type, xmlNodePtr data)
+{
+       zval *ret;
+       xmlNodePtr trav;
+       encodePtr enc;
+       TSRMLS_FETCH();
+
+       MAKE_STD_ZVAL(ret);
+       FIND_XML_NULL(data, ret);
+
+       object_init(ret);
+       trav = data->children;
+
+       enc = get_conversion(UNKNOWN_TYPE);
+       do
+       {
+               if(trav->type == XML_ELEMENT_NODE)
+               {
+                       zval *tmpVal;
+
+                       tmpVal = master_to_zval(enc, trav);
+                       add_property_zval(ret, (char *)trav->name, tmpVal);
+               }
+       }
+       while(trav = trav->next);
+
+       return ret;
+}
+
+xmlNodePtr to_xml_object(encodeType type, zval *data)
+{
+       xmlNodePtr xmlParam;
+       HashTable *prop;
+       int i;
+       TSRMLS_FETCH();
+
+       //Special handling of class SoapVar
+       if(data && Z_TYPE_P(data) == IS_OBJECT && !strcmp(Z_OBJCE_P(data)->name, soap_var_class_entry.name))
+       {
+               zval **ztype, **zdata, **zns, **zstype;
+               encodePtr enc;
+
+               if(zend_hash_find(Z_OBJPROP_P(data), "enc_type", sizeof("enc_type"), (void **)&ztype) == FAILURE)
+                       php_error(E_ERROR, "error encoding SoapVar");
+               if(zend_hash_find(Z_OBJPROP_P(data), "enc_value", sizeof("enc_value"), (void **)&zdata) == FAILURE)
+                       php_error(E_ERROR, "error encoding SoapVar");
+
+               enc = get_conversion(Z_LVAL_P(*ztype));
+               xmlParam = master_to_xml(enc, *zdata);
+
+               if(zend_hash_find(Z_OBJPROP_P(data), "enc_stype", sizeof("enc_stype"), (void **)&zstype) == SUCCESS)
+               {
+                       if(zend_hash_find(Z_OBJPROP_P(data), "enc_ns", sizeof("enc_ns"), (void **)&zns) == SUCCESS)
+                               set_ns_and_type_ex(xmlParam, Z_STRVAL_PP(zns), Z_STRVAL_PP(zstype));
+                       else
+                               set_ns_and_type_ex(xmlParam, NULL, Z_STRVAL_PP(zstype));
+               }
+       }
+       else
+       {
+               xmlParam = xmlNewNode(NULL, "BOGUS");
+               FIND_ZVAL_NULL(data, xmlParam);
+
+               if(Z_TYPE_P(data) == IS_OBJECT)
+               {
+               prop = Z_OBJPROP_P(data);
+               i = zend_hash_num_elements(prop);
+               zend_hash_internal_pointer_reset(prop);
+
+               for(;i > 0;i--)
+               {
+                       xmlNodePtr property;
+                       encodePtr enc;
+                       zval **zprop;
+                       char *str_key;
+
+                       zend_hash_get_current_key(prop, &str_key, NULL, FALSE);
+                       zend_hash_get_current_data(prop, (void **)&zprop);
+
+                       enc = get_conversion((*zprop)->type);
+                       property = master_to_xml(enc, (*zprop));
+
+                       xmlNodeSetName(property, str_key);
+                       xmlAddChild(xmlParam, property);
+                       zend_hash_move_forward(prop);
+               }
+               }
+               set_ns_and_type(xmlParam, type);
+       }
+       return xmlParam;
+}
+
+//Array encode/decode
+xmlNodePtr guess_array_map(encodeType type, zval *data)
+{
+       encodePtr enc = NULL;
+       TSRMLS_FETCH();
+
+       if(data && Z_TYPE_P(data) == IS_ARRAY)
+       {
+               if(zend_hash_num_elements(Z_ARRVAL_P(data)) > 0)
+               {
+                       if(is_map(data))
+                               enc = get_conversion(APACHE_MAP);
+                       else
+                               enc = get_conversion(SOAP_ENC_ARRAY);
+               }
+       }
+       if(!enc)
+               enc = get_conversion(IS_NULL);
+
+       return master_to_xml(enc, data);
+}
+
+xmlNodePtr to_xml_array(encodeType type, zval *data)
+{
+       smart_str array_type_and_size = {0}, array_type = {0};
+       int i;
+       xmlNodePtr xmlParam;
+       TSRMLS_FETCH();
+
+       xmlParam = xmlNewNode(NULL,"BOGUS");
+
+       FIND_ZVAL_NULL(data, xmlParam);
+
+       if(Z_TYPE_P(data) == IS_ARRAY)
+       {
+               i = zend_hash_num_elements(Z_ARRVAL_P(data));
+               get_array_type(data, &array_type);
+               smart_str_append(&array_type_and_size, &array_type);
+               smart_str_appendc(&array_type_and_size, '[');
+               smart_str_append_long(&array_type_and_size, i);
+               smart_str_appendc(&array_type_and_size, ']');
+               smart_str_0(&array_type_and_size);
+
+               xmlSetProp(xmlParam, "SOAP-ENC:arrayType", array_type_and_size.c);
+
+               smart_str_free(&array_type_and_size);
+               smart_str_free(&array_type);
+
+               zend_hash_internal_pointer_reset(data->value.ht);
+               for(;i > 0;i--)
+               {
+                       xmlNodePtr xparam;
+                       zval **zdata;
+                       encodePtr enc;
+                       zend_hash_get_current_data(data->value.ht, (void **)&zdata);
+
+                       enc = get_conversion((*zdata)->type);
+                       xparam = master_to_xml(enc, (*zdata));
+
+                       xmlNodeSetName(xparam, "val");
+                       xmlAddChild(xmlParam, xparam);
+                       zend_hash_move_forward(data->value.ht);
+               }
+       }
+       set_ns_and_type(xmlParam, type);
+       return xmlParam;
+}
+
+zval *to_zval_array(encodeType type, xmlNodePtr data)
+{
+       zval *ret;
+       xmlNodePtr trav;
+       encodePtr enc;
+       TSRMLS_FETCH();
+
+       MAKE_STD_ZVAL(ret);
+       FIND_XML_NULL(data, ret);
+
+       array_init(ret);
+       trav = data->children;
+
+       enc = get_conversion(UNKNOWN_TYPE);
+       while(trav)
+       {
+               if(trav->type == XML_ELEMENT_NODE)
+               {
+                       zval *tmpVal;
+                       tmpVal = master_to_zval(enc, trav);
+                       zend_hash_next_index_insert(Z_ARRVAL_P(ret), &tmpVal, sizeof(zval *), NULL);
+               }
+               trav = trav->next;
+       }
+
+       return ret;
+}
+
+//Map encode/decode
+xmlNodePtr to_xml_map(encodeType type, zval *data)
+{
+       xmlNodePtr xmlParam;
+       int i;
+       TSRMLS_FETCH();
+
+       xmlParam = xmlNewNode(NULL, "BOGUS");
+       FIND_ZVAL_NULL(data, xmlParam);
+
+       if(Z_TYPE_P(data) == IS_ARRAY)
+       {
+       i = zend_hash_num_elements(Z_ARRVAL_P(data));
+       //TODO: Register namespace...???
+       xmlSetProp(xmlParam, "xmlns:apache", "http://xml.apache.org/xml-soap");
+       zend_hash_internal_pointer_reset(data->value.ht);
+       for(;i > 0;i--)
+       {
+               xmlNodePtr xparam, item;
+               xmlNodePtr key;
+               zval **temp_data;
+               char *key_val;
+               int int_val;
+               encodePtr enc;
+
+                       zend_hash_get_current_data(data->value.ht, (void **)&temp_data);
+                       if(Z_TYPE_PP(temp_data) != IS_NULL)
+                       {
+               item = xmlNewNode(NULL, "item");
+               key = xmlNewNode(NULL, "key");
+               if(zend_hash_get_current_key(data->value.ht, &key_val, (long *)&int_val, FALSE) == HASH_KEY_IS_STRING)
+               {
+                       xmlSetProp(key, "xsi:type", "xsd:string");
+                       xmlNodeSetContent(key, key_val);
+               }
+               else
+               {
+                       smart_str tmp = {0};
+                       smart_str_append_long(&tmp, int_val);
+                       smart_str_0(&tmp);
+
+                       xmlSetProp(key, "xsi:type", "xsd:int");
+                       xmlNodeSetContentLen(key, tmp.c, tmp.len);
+
+                       smart_str_free(&tmp);
+               }
+
+
+               enc = get_conversion((*temp_data)->type);
+               xparam = master_to_xml(enc, (*temp_data));
+
+               xmlNodeSetName(xparam, "value");
+               xmlAddChild(item, key);
+               xmlAddChild(item, xparam);
+               xmlAddChild(xmlParam, item);
+                       }
+               zend_hash_move_forward(data->value.ht);
+       }
+       }
+       set_ns_and_type(xmlParam, type);
+
+       return xmlParam;
+}
+
+zval *to_zval_map(encodeType type, xmlNodePtr data)
+{
+       zval *ret, *key, *value;
+       xmlNodePtr trav, item, xmlKey, xmlValue;
+       encodePtr enc;
+       TSRMLS_FETCH();
+
+       MAKE_STD_ZVAL(ret);
+       FIND_XML_NULL(data, ret);
+
+       array_init(ret);
+       trav = data->children;
+
+       enc = get_conversion(UNKNOWN_TYPE);
+       trav = data->children;
+       FOREACHNODE(trav, "item", item)
+       {
+               xmlKey = get_node(item->children, "key");
+               if(!xmlKey)
+                       php_error(E_ERROR, "Error encoding apache map, missing key");
+
+               xmlValue = get_node(item->children, "value");
+               if(!xmlKey)
+                       php_error(E_ERROR, "Error encoding apache map, missing value");
+
+               key = master_to_zval(enc, xmlKey);
+               value = master_to_zval(enc, xmlValue);
+
+               if(Z_TYPE_P(key) == IS_STRING)
+                       zend_hash_update(Z_ARRVAL_P(ret), Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof(zval *), NULL);
+               else if(Z_TYPE_P(key) == IS_LONG)
+                       zend_hash_index_update(Z_ARRVAL_P(ret), Z_LVAL_P(key), &value, sizeof(zval *), NULL);
+               else
+                       php_error(E_ERROR, "Error encoding apache map, only Strings or Longs are allowd as keys");
+       }
+       ENDFOREACH(trav);
+
+       return ret;
+}
+
+//Unknown encode/decode
+xmlNodePtr guess_xml_convert(encodeType type, zval *data)
+{
+       encodePtr enc;
+       TSRMLS_FETCH();
+
+       if(data)
+               enc = get_conversion(data->type);
+       else
+               enc = get_conversion(IS_NULL);
+       return master_to_xml(enc, data);
+}
+
+zval *guess_zval_convert(encodeType type, xmlNodePtr data)
+{
+       encodePtr enc = NULL;
+       xmlAttrPtr tmpattr;
+       TSRMLS_FETCH();
+
+       data = check_and_resolve_href(data);
+
+       if(data == NULL || data->children == NULL)
+               enc = get_conversion(IS_NULL);
+       else
+       {
+               tmpattr = get_attribute(data->properties,"type");
+               if(tmpattr != NULL)
+               {
+                       enc = get_conversion_from_type(data, tmpattr->children->content);
+               //      if(enc == NULL)
+               //              php_error(E_ERROR, "Error (Don't know how to encode/decode \"%s\")", tmpattr->children->content);
+               }
+
+               if(enc == NULL)
+               {
+                       //Didn't have a type, totally guess here
+                       //Logic: has children = IS_OBJECT else IS_STRING
+                       xmlNodePtr trav;
+
+                       if(get_attribute(data->properties, "arrayType"))
+                               enc = get_conversion(SOAP_ENC_ARRAY);
+                       else
+                       {
+                               enc = get_conversion(XSD_STRING);
+                               trav = data->children;
+                               do
+                               {
+                                       if(trav->type == XML_ELEMENT_NODE)
+                                       {
+                                               enc = get_conversion(SOAP_ENC_OBJECT);
+                                               break;
+                                       }
+                               }
+                               while(trav = trav->next);
+                       }
+               }
+       }
+       return master_to_zval(enc, data);
+}
+
+//Time encode/decode
+xmlNodePtr to_xml_datetime_ex(encodeType type, zval *data, char *format)
+{
+       //logic hacked from ext/standard/datetime.c
+       struct tm *ta, tmbuf;
+       time_t timestamp;
+       int max_reallocs = 5;
+       size_t buf_len=64, real_len;
+       char *buf;
+       xmlNodePtr xmlParam;
+
+       xmlParam = xmlNewNode(NULL, "BOGUS");
+       FIND_ZVAL_NULL(data, xmlParam);
+
+       timestamp = Z_LVAL_P(data);
+
+       time(&timestamp);
+       ta = php_localtime_r(&timestamp, &tmbuf);
+
+       buf = (char *) emalloc(buf_len);
+       while ((real_len = strftime(buf, buf_len, format, ta)) == buf_len || real_len == 0)
+       {
+               buf_len *= 2;
+               buf = (char *) erealloc(buf, buf_len);
+               if(!--max_reallocs) break;
+       }
+
+       xmlNodeSetContent(xmlParam, buf);
+       efree(buf);
+       set_ns_and_type(xmlParam, type);
+       return xmlParam;
+}
+
+xmlNodePtr to_xml_datetime(encodeType type, zval *data)
+{
+       return to_xml_datetime_ex(type, data, "%Y-%m-%dT%H:%M:%S");
+}
+
+xmlNodePtr to_xml_time(encodeType type, zval *data)
+{
+       return to_xml_datetime_ex(type, data, "%H:%M:%S");
+}
+
+xmlNodePtr to_xml_date(encodeType type, zval *data)
+{
+       return to_xml_datetime_ex(type, data, "%Y-%m-%d");
+}
+
+xmlNodePtr to_xml_gyearmonth(encodeType type, zval *data)
+{
+       return to_xml_datetime_ex(type, data, "%Y-%m");
+}
+
+xmlNodePtr to_xml_gyear(encodeType type, zval *data)
+{
+       return to_xml_datetime_ex(type, data, "%Y");
+}
+
+xmlNodePtr to_xml_gmonthday(encodeType type, zval *data)
+{
+       return to_xml_datetime_ex(type, data, "--%m-%d");
+}
+
+xmlNodePtr to_xml_gday(encodeType type, zval *data)
+{
+       return to_xml_datetime_ex(type, data, "%d");
+}
+
+xmlNodePtr to_xml_gmonth(encodeType type, zval *data)
+{
+       return to_xml_datetime_ex(type, data, "%m");
+}
+
+void set_ns_and_type(xmlNodePtr node, encodeType type)
+{
+       set_ns_and_type_ex(node, type.ns, type.type_str);
+}
+
+void set_ns_and_type_ex(xmlNodePtr node, char *ns, char *type)
+{
+       if(ns != NULL)
+       {
+               char *sprefix;
+               smart_str *prefix;
+               smart_str xmlns = {0}, nstype = {0};
+
+               TSRMLS_FETCH();
+
+               if(zend_hash_find(SOAP_GLOBAL(defEncNs), ns, strlen(ns) + 1, (void **)&sprefix) == FAILURE)
+               {
+                       prefix = encode_new_ns();
+                       smart_str_appendl(&xmlns, "xmlns:", 6);
+                       smart_str_append(&xmlns, prefix);
+                       smart_str_0(&xmlns);
+
+                       xmlSetProp(node, xmlns.c, ns);
+               }
+               else
+               {
+                       prefix = emalloc(sizeof(smart_str));
+                       memset(prefix, 0, sizeof(smart_str));
+                       smart_str_appends(prefix, sprefix);
+               }
+
+               smart_str_append(&nstype, prefix);
+               smart_str_appendc(&nstype, ':');
+               smart_str_appends(&nstype, type);
+               smart_str_0(&nstype);
+               xmlSetProp(node, "xsi:type", nstype.c);
+               smart_str_free(&nstype);
+               smart_str_free(&xmlns);
+               smart_str_free(prefix);
+               efree(prefix);
+       }
+       else
+               xmlSetProp(node, "xsi:type", type);
+}
+
+smart_str *encode_new_ns()
+{
+       int num;
+       smart_str *ns = emalloc(sizeof(smart_str));
+
+       TSRMLS_FETCH();
+
+       memset(ns, 0, sizeof(smart_str));
+       num = ++SOAP_GLOBAL(cur_uniq_ns);
+       smart_str_appendl(ns, "ns", 2);
+       smart_str_append_long(ns, num);
+       smart_str_0(ns);
+       return ns;
+}
+
+void encode_reset_ns()
+{
+       TSRMLS_FETCH();
+       SOAP_GLOBAL(cur_uniq_ns) = 0;
+}
+
+encodePtr get_conversion_ex(HashTable *encoding, int encode)
+{
+       encodePtr *enc;
+       TSRMLS_FETCH();
+
+       if(zend_hash_index_find(encoding, encode, (void **)&enc) == FAILURE)
+               php_error(E_ERROR, "Cannot find encoding");
+
+       if(SOAP_GLOBAL(overrides))
+       {
+               smart_str nscat = {0};
+
+               smart_str_appendl(&nscat, (*enc)->details.ns, strlen((*enc)->details.ns));
+               smart_str_appendc(&nscat, ':');
+               smart_str_appendl(&nscat, (*enc)->details.type_str, strlen((*enc)->details.type_str));
+               smart_str_0(&nscat);
+
+               zend_hash_find(SOAP_GLOBAL(overrides), nscat.c, nscat.len + 1, (void **)&enc);
+               smart_str_free(&nscat);
+       }
+
+       return *enc;
+}
+
+encodePtr get_conversion_from_href_type_ex(HashTable *encoding, char *type)
+{
+       encodePtr *enc = NULL;
+
+       if(encoding == NULL)
+               return NULL;
+
+       if(zend_hash_find(encoding, type, strlen(type), (void **)&enc) == FAILURE)
+               return NULL;
+
+       return (*enc);
+}
+
+encodePtr get_conversion_from_type_ex(HashTable *encoding, xmlNodePtr node, char *type)
+{
+       encodePtr *enc = NULL;
+       xmlNsPtr nsptr;
+       char *ns, *cptype;
+       char *nscat;
+
+       if(encoding == NULL)
+               return NULL;
+
+       parse_namespace(type, &cptype, &ns);
+       nsptr = xmlSearchNs(node->doc, node, ns);
+       if(nsptr != NULL)
+       {
+               nscat = emalloc(strlen(nsptr->href) + strlen(cptype) + 2);
+               sprintf(nscat, "%s:%s", nsptr->href, cptype);
+
+               if(zend_hash_find(encoding, nscat, strlen(nscat), (void **)&enc) == FAILURE)
+               {
+                       if(zend_hash_find(encoding, type, strlen(type) + 1, (void **)&enc) == FAILURE)
+                               enc = NULL;
+               }
+               efree(nscat);
+       }
+       else
+       {
+               if(zend_hash_find(encoding, type, strlen(type) + 1, (void **)&enc) == FAILURE)
+                       enc = NULL;
+       }
+
+       if(cptype) efree(cptype);
+       if(ns) efree(ns);
+       if(enc == NULL)
+               return NULL;
+       else
+               return (*enc);
+}
+
+int is_map(zval *array)
+{
+       int i, count = zend_hash_num_elements(Z_ARRVAL_P(array));
+       for(i = 0;i < count;i++)
+       {
+               if(zend_hash_get_current_key_type(Z_ARRVAL_P(array)) == HASH_KEY_IS_STRING)
+                       return TRUE;
+               zend_hash_move_forward(Z_ARRVAL_P(array));
+       }
+       return FALSE;
+}
+
+void get_array_type(zval *array, smart_str *type)
+{
+       HashTable *ht = array->value.ht;
+       int i, count, cur_type, prev_type, different;
+       char *name = NULL;
+       zval **tmp;
+       TSRMLS_FETCH();
+
+       if(!array || Z_TYPE_P(array) != IS_ARRAY)
+               smart_str_appendl(type, "xsd:ur-type", 11);
+
+       different = FALSE;
+       cur_type = prev_type = 0;
+       count = zend_hash_num_elements(ht);
+
+       zend_hash_internal_pointer_reset(ht);
+       for(i = 0;i < count;i++)
+       {
+               zend_hash_get_current_data(ht, (void **)&tmp);
+
+               if(Z_TYPE_PP(tmp) == IS_OBJECT && !strcmp(Z_OBJCE_PP(tmp)->name, soap_var_class_entry.name))
+               {
+                       zval **ztype;
+
+                       if(zend_hash_find(Z_OBJPROP_PP(tmp), "enc_type", sizeof("enc_type"), (void **)&ztype) == FAILURE)
+                               php_error(E_ERROR, "error encoding SoapVar");
+                       cur_type = Z_LVAL_P(*ztype);
+               }
+               else if(Z_TYPE_PP(tmp) == IS_ARRAY && is_map(*tmp))
+                       cur_type = APACHE_MAP;
+               else
+                       cur_type = Z_TYPE_PP(tmp);
+
+               if(i > 0)
+               {
+                       if(cur_type != prev_type)
+                       {
+                               different = TRUE;
+                               break;
+                       }
+               }
+
+               prev_type = cur_type;
+               zend_hash_move_forward(ht);
+       }
+
+       if(different)
+               smart_str_appendl(type, "xsd:ur-type", 11);
+       else
+       {
+               encodePtr enc;
+               char *prefix;
+
+               enc = get_conversion(cur_type);
+
+               if(enc->details.ns != NULL)
+               {
+                       if(zend_hash_find(SOAP_GLOBAL(defEncNs), enc->details.ns, strlen(enc->details.ns) + 1, (void **)&prefix) == FAILURE)
+                               php_error(E_ERROR, "fix me");
+
+                       smart_str_appendl(type, prefix, strlen(prefix));
+                       smart_str_appendc(type, ':');
+                       smart_str_appendl(type, enc->details.type_str, strlen(enc->details.type_str));
+                       smart_str_0(type);
+               }
+               else
+                       smart_str_appendl(type, enc->details.type_str, strlen(enc->details.type_str));
+       }
+}
+
+
+smart_str *build_soap_action(zval *this_ptr, char *soapaction)
+{
+       zval **uri;
+       smart_str *tmp;
+
+       tmp = emalloc(sizeof(smart_str));
+       memset(tmp, 0, sizeof(smart_str));
+
+       if(zend_hash_find(Z_OBJPROP_P(this_ptr), "uri", sizeof("uri"), (void *)&uri) == FAILURE)
+               php_error(E_ERROR, "Error finding uri");
+
+       smart_str_appendl(tmp, Z_STRVAL_PP(uri), Z_STRLEN_PP(uri));
+       smart_str_appends(tmp, "/#");
+       smart_str_appendl(tmp, soapaction, strlen(soapaction));
+       smart_str_0(tmp);
+
+       return tmp;
+}
+
+void delete_encoder(void *encode)
+{
+       encodePtr t = *((encodePtr*)encode);
+       if(t->details.ns)
+               free(t->details.ns);
+       if(t->details.type_str)
+               free(t->details.type_str);
+       if(t->details.map)
+               delete_mapping(t->details.map);
+       free(t);
+}
+
diff --git a/ext/soap/php_encoding.h b/ext/soap/php_encoding.h
new file mode 100644 (file)
index 0000000..7e422dc
--- /dev/null
@@ -0,0 +1,248 @@
+#ifndef PHP_ENCODING_H
+#define PHP_ENCODING_H
+
+#define XSD_1999_NAMESPACE "http://www.w3.org/1999/XMLSchema"
+#define XSD_1999_TIMEINSTANT 401
+#define XSD_1999_TIMEINSTANT_STRING "timeInstant"
+
+#define XSD_NAMESPACE "http://www.w3.org/2001/XMLSchema"
+#define XSD_NS_PREFIX "xsd"
+#define XSD_STRING 101
+#define XSD_STRING_STRING "string"
+#define XSD_BOOLEAN 103
+#define XSD_BOOLEAN_STRING "boolean"
+#define XSD_DECIMAL 104
+#define XSD_DECIMAL_STRING "decimal"
+#define XSD_FLOAT 105
+#define XSD_FLOAT_STRING "float"
+#define XSD_DOUBLE 106
+#define XSD_DOUBLE_STRING "double"
+#define XSD_DURATION 107
+#define XSD_DURATION_STRING "duration"
+#define XSD_DATETIME 108
+#define XSD_DATETIME_STRING "dateTime"
+#define XSD_TIME 109
+#define XSD_TIME_STRING "time"
+#define XSD_DATE 110
+#define XSD_DATE_STRING "date"
+#define XSD_GYEARMONTH 111
+#define XSD_GYEARMONTH_STRING "gYearMonth"
+#define XSD_GYEAR 112
+#define XSD_GYEAR_STRING "gYear"
+#define XSD_GMONTHDAY 113
+#define XSD_GMONTHDAY_STRING "gMonthDay"
+#define XSD_GDAY 114
+#define XSD_GDAY_STRING "gDay"
+#define XSD_GMONTH 115
+#define XSD_GMONTH_STRING "gMonth"
+#define XSD_HEXBINARY 116
+#define XSD_HEXBINARY_STRING "hexBinary"
+#define XSD_BASE64BINARY 117
+#define XSD_BASE64BINARY_STRING "base64Binary"
+#define XSD_ANYURI 118
+#define XSD_ANYURI_STRING "anyURI"
+#define XSD_QNAME 119
+#define XSD_QNAME_STRING "QName"
+#define XSD_NOTATION 120
+#define XSD_NOTATION_STRING "NOTATION"
+#define XSD_NORMALIZEDSTRING 121
+#define XSD_NORMALIZEDSTRING_STRING "normalizedString"
+#define XSD_TOKEN 122
+#define XSD_TOKEN_STRING "token"
+#define XSD_LANGUAGE 123
+#define XSD_LANGUAGE_STRING "language"
+#define XSD_NMTOKEN 124
+#define XSD_NMTOKEN_STRING "NMTOKEN"
+#define XSD_NAME 124
+#define XSD_NAME_STRING "Name"
+#define XSD_NCNAME 125
+#define XSD_NCNAME_STRING "NCName"
+#define XSD_ID 126
+#define XSD_ID_STRING "ID"
+#define XSD_IDREF 127
+#define XSD_IDREF_STRING "IDREF"
+#define XSD_IDREFS 127
+#define XSD_IDREFS_STRING "IDREFS"
+#define XSD_ENTITY 128
+#define XSD_ENTITY_STRING "ENTITY"
+#define XSD_ENTITYS 129
+#define XSD_ENTITYS_STRING "ENTITYS"
+#define XSD_INTEGER 130
+#define XSD_INTEGER_STRING "integer"
+#define XSD_NONPOSITIVEINTEGER 131
+#define XSD_NONPOSITIVEINTEGER_STRING "nonPositiveInteger"
+#define XSD_NEGATIVEINTEGER 132
+#define XSD_NEGATIVEINTEGER_STRING "negativeInteger"
+#define XSD_LONG 133
+#define XSD_LONG_STRING "long"
+#define XSD_INT 134
+#define XSD_INT_STRING "int"
+#define XSD_SHORT 135
+#define XSD_SHORT_STRING "short"
+#define XSD_BYTE 136
+#define XSD_BYTE_STRING "byte"
+#define XSD_NONNEGATIVEINTEGER 137
+#define XSD_NONNEGATIVEINTEGER_STRING "nonNegativeInteger"
+#define XSD_UNSIGNEDLONG 138
+#define XSD_UNSIGNEDLONG_STRING "unsignedLong"
+#define XSD_UNSIGNEDINT 139
+#define XSD_UNSIGNEDINT_STRING "unsignedInt"
+#define XSD_UNSIGNEDSHORT 140
+#define XSD_UNSIGNEDSHORT_STRING "unsignedShort"
+#define XSD_UNSIGNEDBYTE 141
+#define XSD_UNSIGNEDBYTE_STRING "unsignedByte"
+#define XSD_POSITIVEINTEGER 142
+#define XSD_POSITIVEINTEGER_STRING "positiveInteger"
+
+#define APACHE_NAMESPACE "http://xml.apache.org/xml-soap"
+#define APACHE_NS_PREFIX "apache"
+#define APACHE_MAP 200
+#define APACHE_MAP_STRING "Map"
+
+#define SOAP_ENC_NAMESPACE "http://schemas.xmlsoap.org/soap/encoding/"
+#define SOAP_ENC_NS_PREFIX "SOAP-ENC"
+#define SOAP_ENC_ARRAY 300
+#define SOAP_ENC_ARRAY_STRING "Array"
+#define SOAP_ENC_OBJECT 301
+#define SOAP_ENC_OBJECT_STRING "Struct"
+
+#define SCHEMA_NAMESPACE "http://www.w3.org/2001/XMLSchema"
+#define SCHEMA_NS_PREFIX "s"
+
+#define WSDL_NAMESPACE "http://schemas.xmlsoap.org/wsdl/"
+#define WSDL_NS_PREFIX "wsdl"
+
+#define UNKNOWN_TYPE 999998
+#define END_KNOWN_TYPES 999999
+
+struct _encodeType
+{
+       int type;
+       char *type_str;
+       char *ns;
+       sdlTypePtr sdl_type;
+       soapMappingPtr map;
+};
+
+struct _encode
+{
+       encodeType details;
+       zval *(*to_zval)(encodeType type, xmlNodePtr data);
+       xmlNodePtr (*to_xml)(encodeType type, zval *data);
+
+       xmlNodePtr (*to_zval_before)(encodeType type, xmlNodePtr data);
+       zval *(*to_zval_after)(encodeType type, zval *data);
+
+       zval *(*to_xml_before)(encodeType type, zval *data);
+       xmlNodePtr (*to_xml_after)(encodeType type, xmlNodePtr data);
+};
+
+smart_str *build_soap_action(zval *this_ptr, char *soapaction);
+
+// Master functions all encode/decode should be called thur these functions
+xmlNodePtr master_to_xml(encodePtr encode, zval *data);
+zval *master_to_zval(encodePtr encode, xmlNodePtr data);
+
+#ifdef HAVE_PHP_DOMXML
+//user defined mapping
+zval *to_xml_before_user(encodeType type, zval *data);
+xmlNodePtr to_xml_user(encodeType type, zval *data);
+xmlNodePtr to_xml_after_user(encodeType type, xmlNodePtr node);
+xmlNodePtr to_zval_before_user(encodeType type, xmlNodePtr node);
+zval *to_zval_user(encodeType type, xmlNodePtr node);
+zval *to_zval_after_user(encodeType type, zval *data);
+#endif
+
+//zval type decode
+zval *to_zval_double(encodeType type, xmlNodePtr data);
+zval *to_zval_long(encodeType type, xmlNodePtr data);
+zval *to_zval_bool(encodeType type, xmlNodePtr data);
+zval *to_zval_object(encodeType type, xmlNodePtr data);
+zval *to_zval_string(encodeType type, xmlNodePtr data);
+zval *to_zval_array(encodeType type, xmlNodePtr data);
+zval *to_zval_map(encodeType type, xmlNodePtr data);
+zval *to_zval_null(encodeType type, xmlNodePtr data);
+zval *guess_zval_convert(encodeType type, xmlNodePtr data);
+
+xmlNodePtr to_xml_long(encodeType type, zval *data);
+xmlNodePtr to_xml_bool(encodeType type, zval *data);
+
+//String encode
+xmlNodePtr to_xml_string(encodeType type, zval *data);
+xmlNodePtr to_xml_stringl(encodeType type, zval *data);
+
+//Null encode
+xmlNodePtr to_xml_null(encodeType type, zval *data);
+
+//Struct encode
+xmlNodePtr to_xml_object(encodeType type, zval *data);
+
+//Array encode
+xmlNodePtr guess_array_map(encodeType type, zval *data);
+xmlNodePtr to_xml_array(encodeType type, zval *data);
+xmlNodePtr to_xml_map(encodeType type, zval *data);
+
+//Try and guess for non-wsdl clients and servers
+xmlNodePtr guess_xml_convert(encodeType type, zval *data);
+
+//Datetime encode/decode
+xmlNodePtr to_xml_datetime_ex(encodeType type, zval *data, char *format);
+xmlNodePtr to_xml_datetime(encodeType type, zval *data);
+xmlNodePtr to_xml_time(encodeType type, zval *data);
+xmlNodePtr to_xml_date(encodeType type, zval *data);
+xmlNodePtr to_xml_gyearmonth(encodeType type, zval *data);
+xmlNodePtr to_xml_gyear(encodeType type, zval *data);
+xmlNodePtr to_xml_gmonthday(encodeType type, zval *data);
+xmlNodePtr to_xml_gday(encodeType type, zval *data);
+xmlNodePtr to_xml_gmonth(encodeType type, zval *data);
+
+#define get_conversion(e) get_conversion_ex(SOAP_GLOBAL(defEncIndex), e)
+#define get_conversion_from_type(n, t) get_conversion_from_type_ex(SOAP_GLOBAL(defEnc), n, t)
+#define get_conversion_from_href_type(t) get_conversion_from_href_type_ex(SOAP_GLOBAL(defEnc), t)
+
+void encode_reset_ns();
+smart_str *encode_new_ns();
+
+void set_ns_and_type(xmlNodePtr node, encodeType type);
+void set_ns_and_type_ex(xmlNodePtr node, char *ns, char *type);
+encodePtr get_conversion_ex(HashTable *encoding, int encode);
+encodePtr get_conversion_from_type_ex(HashTable *encoding, xmlNodePtr node, char *type);
+encodePtr get_conversion_from_href_type_ex(HashTable *encoding, char *type);
+
+int is_map(zval *array);
+void get_array_type(zval *array, smart_str *out_type);
+
+void delete_encoder(void *handle);
+
+extern encode defaultEncoding[];
+
+#define FIND_XML_NULL(xml,zval) \
+       { \
+               xmlAttrPtr null; \
+               if(!xml || !xml->children) \
+               { \
+                       ZVAL_NULL(zval); \
+                       return zval; \
+               } \
+               if(xml->properties) \
+               { \
+                       null = get_attribute(xml->properties, "null"); \
+                       if(null) \
+                       { \
+                               ZVAL_NULL(zval); \
+                               return zval; \
+                       } \
+               } \
+       }
+
+#define FIND_ZVAL_NULL(zval, xml) \
+{ \
+       if(!zval) \
+       { \
+               xmlSetProp(xml, "xsi:null", "1"); \
+               return xml; \
+       } \
+}
+
+
+#endif
diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c
new file mode 100644 (file)
index 0000000..73c60a3
--- /dev/null
@@ -0,0 +1,495 @@
+#include "php_soap.h"
+
+void send_http_soap_request(zval *this_ptr, xmlDoc *doc, char *function_name, char *soapaction)
+{
+       xmlChar *buf;
+       char *soap_headers;
+       int buf_size,err,ret;
+       sdlPtr sdl;
+       php_url *phpurl = NULL;
+       SOAP_STREAM stream;
+
+#ifdef PHP_DEBUG
+       zval *raw_request;
+#endif
+
+       TSRMLS_FETCH();
+
+       FETCH_THIS_SOCKET(stream);
+       FETCH_THIS_URL(phpurl);
+       FETCH_THIS_SDL(sdl);
+
+       xmlDocDumpMemory(doc, &buf, &buf_size);
+
+#ifdef PHP_DEBUG
+       MAKE_STD_ZVAL(raw_request);
+       ZVAL_STRINGL(raw_request, buf, buf_size, 1);
+       add_property_zval(this_ptr, "__last_request", raw_request);
+#endif
+
+       if(!stream)
+       {
+               char *url;
+
+               if(sdl == NULL)
+               {
+                       zval **location;
+                       if(zend_hash_find(Z_OBJPROP_P(this_ptr), "location", sizeof("location"),(void **) &location) == FAILURE)
+                               php_error(E_ERROR, "Error could not find location");
+                       url = Z_STRVAL_PP(location);
+               }
+               else
+                       url = sdl->location;
+
+               phpurl = php_url_parse(url);
+
+#ifdef PHP_STREAMS
+               stream = php_stream_sock_open_host(phpurl->host, (unsigned short)(phpurl->port == 0 ? 80 : phpurl->port), SOCK_STREAM, 0, 0);
+#else
+               stream = get_socket(phpurl->host, (phpurl->port == 0 ? 80 : phpurl->port), 10);
+#endif
+               if(stream)
+               {
+                       ret = zend_list_insert((void *)stream, le_http_socket);
+                       add_property_resource(this_ptr, "httpsocket", ret);
+                       zend_list_addref(ret);
+
+                       ret = zend_list_insert(phpurl, le_url);
+                       add_property_resource(this_ptr, "httpurl", ret);
+                       zend_list_addref(ret);
+               }
+               else
+                       php_error(E_ERROR,"Could not connect to host");
+               //php_url_free(phpurl);
+       }
+
+       if(stream)
+       {
+               zval **cookies;
+               char *header = "POST %s HTTP/1.1\r\nConnection: close\r\nAccept: text/html; text/xml; text/plain\r\nUser-Agent: PHP SOAP 0.1\r\nHost: %s\r\nContent-Type: text/xml\r\nContent-Length: %d\r\nSOAPAction: \"%s\"\r\n";
+               int size = strlen(header) + strlen(phpurl->host) + strlen(phpurl->path) + 10;
+
+               // TODO: Add authication
+               if(sdl != NULL)
+               {
+                       // TODO: need to grab soap action from wsdl....
+                       soap_headers = emalloc(size + strlen(soapaction));
+                       sprintf(soap_headers, header, phpurl->path, phpurl->host, buf_size, soapaction);
+               }
+               else
+               {
+                       soap_headers = emalloc(size + strlen(soapaction));
+                       sprintf(soap_headers, header, phpurl->path, phpurl->host, buf_size, soapaction);
+               }
+
+#ifdef PHP_STREAMS
+               err = php_stream_write(stream, soap_headers, strlen(soap_headers));
+#else
+               err = send(stream, soap_headers, strlen(soap_headers), 0);
+#endif
+               if(err != (int)strlen(soap_headers))
+                       php_error(E_ERROR,"Failed Sending HTTP Headers");
+
+               // Send cookies along with request
+               if(zend_hash_find(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), (void **)&cookies) == SUCCESS)
+               {
+                       smart_str cookie_str = {0};
+                       zval **data;
+                       char *key;
+                       int index, i;
+
+                       zend_hash_internal_pointer_reset(Z_ARRVAL_PP(cookies));
+                       for(i = 0;i < (int)Z_ARRVAL_PP(cookies)->nNumOfElements;i++)
+                       {
+                               zend_hash_get_current_data(Z_ARRVAL_PP(cookies), (void **)&data);
+                               zend_hash_get_current_key(Z_ARRVAL_PP(cookies), &key, (long *)&index, FALSE);
+
+                               smart_str_appendl(&cookie_str, "Cookie: ", 8);
+                               smart_str_appendl(&cookie_str, key, strlen(key));
+                               smart_str_appendc(&cookie_str, '=');
+                               smart_str_appendl(&cookie_str, Z_STRVAL_PP(data), Z_STRLEN_PP(data));
+                               smart_str_appendc(&cookie_str, ';');
+                               zend_hash_move_forward(Z_ARRVAL_PP(cookies));
+                       }
+                       smart_str_appendl(&cookie_str, "\r\n", 2);
+                       smart_str_0(&cookie_str);
+
+#ifdef PHP_STREAMS
+                       err = php_stream_write(stream, cookie_str.c, cookie_str.len);
+#else
+                       err = send(stream, cookie_str.c, cookie_str.len,0);
+#endif
+                       if(err != (int)cookie_str.len)
+                               php_error(E_ERROR,"Failed Sending HTTP Headers");
+
+                       smart_str_free(&cookie_str);
+               }
+
+#ifdef PHP_STREAMS
+               err = php_stream_write(stream, "\r\n", 2);
+#else
+               err = send(stream, "\r\n", 2, 0);
+#endif
+               if(err != 2)
+                       php_error(E_ERROR,"Failed Sending HTTP Headers");
+
+
+#ifdef PHP_STREAMS
+               err = php_stream_write(stream, buf, buf_size);
+#else
+               err = send(stream, buf, buf_size, 0);
+#endif
+               if(err != (int)strlen(buf))
+                       php_error(E_ERROR,"Failed Sending HTTP Content");
+
+               efree(soap_headers);
+       }
+       xmlFree(buf);
+}
+
+void get_http_soap_response(zval *this_ptr, char **buffer, int *buffer_len)
+{
+       char *http_headers, *http_body, *content_type, *http_version, http_status[4], *cookie_itt, *connection;
+       int http_header_size, http_body_size, http_close;
+       sdlPtr sdl;
+       zval **socket_ref;
+       SOAP_STREAM stream;
+
+#ifdef PHP_DEBUG
+       zval *raw_response;
+#endif
+
+       TSRMLS_FETCH();
+
+       FETCH_THIS_SDL(sdl);
+
+       if(FIND_SOCKET_PROPERTY(this_ptr, socket_ref) != FAILURE)
+       {
+               FETCH_SOCKET_RES(stream, socket_ref);
+       }
+
+       if(!get_http_headers(stream, &http_headers, &http_header_size))
+               php_error(E_ERROR, "Error Fetching http headers");
+
+       //Check to see what HTTP status was sent
+       http_version = get_http_header_value(http_headers,"HTTP/");
+       if(http_version)
+       {
+               char *tmp;
+
+               tmp = strstr(http_version," ");
+
+               if(tmp != NULL)
+               {
+                       tmp++;
+                       strncpy(http_status,tmp,4);
+                       http_status[3] = '\0';
+               }
+
+               /*
+               Try and process any respsone that is xml might contain fault code
+
+               Maybe try and test for some of the 300's 400's specfics but not
+               right now.
+
+               if(strcmp(http_status,"200"))
+               {
+                       zval *err;
+                       char *http_err;
+
+                       MAKE_STD_ZVAL(err);
+                       ZVAL_STRING(err, http_body, 1);
+                       http_err = emalloc(strlen("HTTP request failed ()") + 4);
+                       sprintf(http_err, "HTTP request failed (%s)", http_status);
+                       add_soap_fault(thisObj, "SOAP-ENV:Client", http_err, NULL, err);
+                       efree(http_err);
+                       return;
+               }*/
+
+               //Try and get headers again
+               if(!strcmp(http_status, "100"))
+               {
+                       if(!get_http_headers(stream, &http_headers, &http_header_size))
+                               php_error(E_ERROR, "Error Fetching http headers");
+               }
+
+               efree(http_version);
+       }
+
+
+       if(!get_http_body(stream, http_headers, &http_body, &http_body_size))
+               php_error(E_ERROR, "Error Fetching http body");
+
+#ifdef PHP_DEBUG
+       MAKE_STD_ZVAL(raw_response);
+       ZVAL_STRINGL(raw_response, http_body, http_body_size, 1);
+       add_property_zval(this_ptr, "__last_response", raw_response);
+#endif
+
+       // Close every time right now till i can spend more time on it
+       //  it works.. it's just slower??
+       //See if the server requested a close
+       http_close = TRUE;
+       connection = get_http_header_value(http_headers,"Connection: ");
+       if(connection)
+       {
+               if(!strcmp(connection, "Keep-Alive"))
+                       http_close = FALSE;
+               efree(connection);
+       }
+       else
+       {
+               if(!strncmp(http_version,"1.1", 3))
+                               http_close = FALSE;
+       }
+
+       if(http_close)
+       {
+#ifdef PHP_STREAMS
+               php_stream_close(stream);
+#else
+               SOCK_CLOSE(stream);
+#endif
+               zend_list_delete(Z_RESVAL_PP(socket_ref));
+               zend_hash_del(Z_OBJPROP_P(this_ptr), "httpsocket", strlen("httpsocket") + 1);
+       }
+
+       //Check and see if the server even sent a xml document
+       content_type = get_http_header_value(http_headers,"Content-Type: ");
+       if(content_type)
+       {
+               char *pos = NULL;
+               int cmplen;
+               pos = strstr(content_type,";");
+               if(pos != NULL)
+                       cmplen = pos - content_type;
+               else
+                       cmplen = strlen(content_type);
+
+               if(strncmp(content_type, "text/xml", cmplen))
+               {
+                       if(strncmp(http_body, "<?xml", 5))
+                       {
+                               zval *err;
+                               MAKE_STD_ZVAL(err);
+                               ZVAL_STRINGL(err, http_body, http_body_size, 1);
+                               add_soap_fault(this_ptr, "SOAP-ENV:Client", "Didn't recieve an xml document", NULL, err);
+                               efree(content_type);
+                               return;
+                       }
+               }
+               efree(content_type);
+       }
+
+       //Grab and send back every cookie
+       //Not going to worry about Path: because
+       //we shouldn't be changing urls so path dont
+       //matter too much
+       cookie_itt = strstr(http_headers,"Set-Cookie: ");
+       while(cookie_itt)
+       {
+               char *end_pos, *cookie;
+               char *eqpos, *sempos;
+               smart_str name = {0}, value = {0};
+               zval **cookies, *z_cookie;
+
+               if(zend_hash_find(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), (void **)&cookies) == FAILURE)
+               {
+                       zval *tmp_cookies;
+                       MAKE_STD_ZVAL(tmp_cookies);
+                       array_init(tmp_cookies);
+                       zend_hash_update(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), &tmp_cookies, sizeof(zval *), (void **)&cookies);
+               }
+
+               end_pos = strstr(cookie_itt,"\r\n");
+               cookie = get_http_header_value(cookie_itt,"Set-Cookie: ");
+
+               eqpos = strstr(cookie, "=");
+               sempos = strstr(cookie, ";");
+
+               smart_str_appendl(&name, cookie, eqpos - cookie);
+               smart_str_0(&name);
+
+               smart_str_appendl(&value, eqpos + 1, sempos - (eqpos + 1));
+               smart_str_0(&value);
+
+               MAKE_STD_ZVAL(z_cookie);
+               ZVAL_STRINGL(z_cookie, value.c, value.len, 1);
+
+               zend_hash_update(Z_ARRVAL_PP(cookies), name.c, name.len + 1, &z_cookie, sizeof(zval *), NULL);
+
+               cookie_itt = strstr(cookie_itt + sizeof("Set-Cookie: "), "Set-Cookie: ");
+
+               smart_str_free(&value);
+               smart_str_free(&name);
+               efree(cookie);
+               cookie_itt = FALSE;
+       }
+
+       *buffer = http_body;
+       *buffer_len = http_body_size;
+       efree(http_headers);
+}
+
+char *get_http_header_value(char *headers, char *type)
+{
+       char *tmp = NULL,*var = NULL;
+       int size;
+
+       tmp = strstr(headers, type);
+       if(tmp != NULL)
+       {
+               tmp += strlen(type);
+               size = strstr(tmp, "\r\n") - tmp;
+               var = emalloc(size + 1);
+               strncpy(var, tmp, size);
+               var[size] = '\0';
+       }
+       return var;
+}
+
+int get_http_body(SOAP_STREAM stream, char *headers,  char **response, int *out_size)
+{
+       char *trans_enc, *content_length, *http_buf;
+       int http_buf_size = 0;
+       TSRMLS_FETCH();
+
+       trans_enc = get_http_header_value(headers, "Transfer-Encoding: ");
+       content_length = get_http_header_value(headers, "Content-Length: ");
+
+       //this is temp...
+       // netscape enterprise server sends in lowercase???
+       if(content_length == NULL)
+               content_length = get_http_header_value(headers, "Content-length: ");
+
+       if(trans_enc && !strcmp(trans_enc, "chunked"))
+       {
+               int cur = 0, size = 0, buf_size = 0, len_size;
+               char done, chunk_size[10];
+
+               done = FALSE;
+               http_buf = emalloc(1);
+               while(!done)
+               {
+                       cur = 0;
+                       while(!(chunk_size[cur - 2] == '\r' && chunk_size[cur - 1] == '\n'))
+#ifdef PHP_STREAMS
+                               chunk_size[cur++] = php_stream_getc(stream);
+#else
+                               chunk_size[cur++] = php_sock_fgetc(stream);
+#endif
+                       if(sscanf(chunk_size,"%x",&buf_size) != -1)
+                       {
+                               http_buf = erealloc(http_buf,http_buf_size + buf_size);
+                               len_size = 0;
+                               while(http_buf_size < buf_size)
+                               {
+#ifdef PHP_STREAMS
+                                       len_size += php_stream_read(stream, &http_buf[http_buf_size], buf_size - len_size);
+#else
+                                       len_size += php_sock_fread(&http_buf[http_buf_size], buf_size - len_size, stream);
+#endif
+                                       http_buf_size += len_size;
+                               }
+#ifdef PHP_STREAMS
+                               php_stream_getc(stream);php_stream_getc(stream);
+#else
+                               //Eat up '\r' '\n'
+                               php_sock_fgetc(stream);php_sock_fgetc(stream);
+#endif
+                       }
+                       if(buf_size == 0)
+                               done = TRUE;
+               }
+               efree(trans_enc);
+       }
+       else if(content_length)
+       {
+               int size;
+               size = atoi(content_length);
+               http_buf = emalloc(size + 1);
+
+               while(http_buf_size < size)
+#ifdef PHP_STREAMS
+                       http_buf_size += php_stream_read(stream, &http_buf[http_buf_size], size - http_buf_size);
+#else
+                       http_buf_size += php_sock_fread(&http_buf[http_buf_size], size - http_buf_size, stream);
+#endif
+               http_buf[size] = '\0';
+               efree(content_length);
+       }
+       else
+               php_error(E_ERROR,"Don't know how to read http body, No Content-Length or chunked data");
+
+       (*response) = http_buf;
+       (*out_size) = http_buf_size;
+       return TRUE;
+}
+
+int get_http_headers(SOAP_STREAM stream, char **response, int *out_size)
+{
+       int done;
+       char chr;
+       smart_str tmp_response = {0};
+       TSRMLS_FETCH();
+
+       done = FALSE;
+
+       while(!done)
+       {
+#ifdef PHP_STREAMS
+               chr = php_stream_getc(stream);
+#else
+               chr = php_sock_fgetc(stream);
+#endif
+               if(chr != EOF)
+               {
+                       smart_str_appendc(&tmp_response, chr);
+                       if(tmp_response.c[tmp_response.len - 2] == '\r' && tmp_response.c[tmp_response.len - 1] == '\n' &&
+                               tmp_response.c[tmp_response.len - 4] == '\r' && tmp_response.c[tmp_response.len - 3] == '\n')
+                       {
+                               smart_str_0(&tmp_response);
+                               done = TRUE;
+                       }
+               }
+               else
+                       return FALSE;
+       }
+       (*response) = tmp_response.c;
+       (*out_size) = tmp_response.len;
+       return TRUE;
+}
+
+#ifndef PHP_STREAMS
+SOCKET get_socket(char* host,int portno,int time)
+{
+       SOCKET socketd = -1;
+       struct sockaddr_in server;
+       struct timeval timeout;
+
+       memset(&server, 0, sizeof(server));
+       socketd = socket(AF_INET,SOCK_STREAM,0);
+       if (socketd == SOCK_ERR) {
+               if(socketd > 0)
+                       SOCK_CLOSE(socketd);
+               return FALSE;
+       }
+       server.sin_family = AF_INET;
+
+       if(php_lookup_hostname(host,&server.sin_addr)) {
+               if(socketd > 0)
+                       SOCK_CLOSE(socketd);
+               return FALSE;
+       }
+       server.sin_port = htons((unsigned short)portno);
+       timeout.tv_sec = time;
+       timeout.tv_usec = 0;
+       if (php_connect_nonb(socketd, (struct sockaddr *)&server, sizeof(struct sockaddr_in), &timeout) == SOCK_CONN_ERR) {
+               if(socketd > 0)
+                       SOCK_CLOSE(socketd);
+               return FALSE;
+       }
+
+       return socketd;
+}
+#endif
diff --git a/ext/soap/php_http.h b/ext/soap/php_http.h
new file mode 100644 (file)
index 0000000..4e4fff7
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef PHP_HTTP_H
+#define PHP_HTTP_H
+
+void send_http_soap_request(zval *this_ptr, xmlDoc *doc, char *function_name, char *soapaction);
+void get_http_soap_response(zval *this_ptr, char **buffer, int *buffer_len);
+
+char *get_http_header_value(char *headers, char *type);
+int get_http_body(SOAP_STREAM socketd, char *headers,  char **response, int *out_size);
+int get_http_headers(SOAP_STREAM socketd,char **response, int *out_size);
+
+#ifndef PHP_STREAMS
+#ifndef ZEND_WIN32
+# ifndef closesocket
+#  define closesocket close
+# endif
+#endif
+
+#ifndef SOCK_CLOSE
+# define SOCK_CLOSE(s) shutdown(s, 0); closesocket(s)
+#endif
+
+SOCKET get_socket(char* host,int portno,int timeout);
+#endif
+
+#endif
diff --git a/ext/soap/php_packet_soap.c b/ext/soap/php_packet_soap.c
new file mode 100644 (file)
index 0000000..3414f97
--- /dev/null
@@ -0,0 +1,124 @@
+#include "php_soap.h"
+
+int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctionPtr fn, char *fn_name, zval ***ret, int *num_params)
+{
+       xmlDocPtr response;
+       xmlNodePtr trav, trav2, env, body, resp, cur, fault;
+       zval **tmp_ret;
+       TSRMLS_FETCH();
+
+       response = xmlParseMemory(buffer, buffer_size);
+       xmlCleanupParser();
+
+       trav = response->children;
+       FOREACHNODE(trav,"Envelope",env)
+       {
+               trav2 = env->children;
+               FOREACHNODE(trav2,"Body",body)
+               {
+                       fault = get_node(body->children,"Fault");
+                       if(fault != NULL)
+                       {
+                               char *faultcode = NULL, *faultstring = NULL, *faultactor = NULL;
+                               zval *details = NULL;
+                               xmlNodePtr tmp;
+
+                               tmp = get_node(fault->children,"faultcode");
+                               if(tmp != NULL && tmp->children != NULL)
+                                       faultcode = tmp->children->content;
+
+                               tmp = get_node(fault->children,"faultstring");
+                               if(tmp != NULL && tmp->children != NULL)
+                                       faultstring = tmp->children->content;
+
+                               tmp = get_node(fault->children,"faultactor");
+                               if(tmp != NULL && tmp->children != NULL)
+                                       faultactor = tmp->children->content;
+
+                               tmp = get_node(fault->children,"detail");
+                               if(tmp != NULL)
+                               {
+                                       encodePtr enc;
+                                       enc = get_conversion(UNKNOWN_TYPE);
+                                       details = enc->to_zval(enc->details, tmp);
+                               }
+
+                               add_soap_fault(this_ptr, faultcode, faultstring, faultactor, details);
+                       }
+                       else
+                       {
+                               resp = body->children;
+                               if(fn != NULL)
+                               {
+                                       cur = get_node(resp, fn->responseName);
+                                       if(cur != NULL)
+                                       {
+                                               int num_resp = zend_hash_num_elements(fn->responseParameters);
+                                               if(num_resp <= 1)
+                                               {
+                                                       sdlParamPtr *h_param, param;
+                                                       xmlNodePtr val;
+
+                                                       zend_hash_internal_pointer_reset(fn->responseParameters);
+                                                       if(zend_hash_get_current_data(fn->responseParameters, (void **)&h_param) != SUCCESS)
+                                                       {
+                                                               (*num_params) = 0;
+                                                       }
+                                                       else
+                                                       {
+                                                               param = (*h_param);
+                                                               val = get_node(cur->children, param->paramName);
+                                                               if(val != NULL)
+                                                               {
+                                                                       encodePtr enc;
+                                                                       tmp_ret = emalloc(sizeof(zval **));
+                                                                       if(param != NULL)
+                                                                               enc = param->encode;
+                                                                       else
+                                                                               enc = get_conversion(UNKNOWN_TYPE);
+
+                                                                       tmp_ret[0] = master_to_zval(enc, val);
+                                                                       (*ret) = tmp_ret;
+                                                                       (*num_params) = 1;
+                                                               }
+                                                               else
+                                                                       php_error(E_ERROR, "Can't find response parameter \"%s\"", param->paramName);
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       php_error(E_ERROR,"Doesn't handle multiple return values");
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       cur = resp;
+                                       while(cur && cur->type != XML_ELEMENT_NODE)
+                                                       cur = cur->next;
+                                       if(cur != NULL)
+                                       {
+                                               xmlNodePtr val;
+                                               val = cur->children;
+                                               while(val && val->type != XML_ELEMENT_NODE)
+                                                       val = val->next;
+
+                                               if(val != NULL)
+                                               {
+                                                       encodePtr enc;
+                                                       enc = get_conversion(UNKNOWN_TYPE);
+                                                       tmp_ret = emalloc(sizeof(zval **));
+                                                       tmp_ret[0] = master_to_zval(enc, val);
+                                                       (*ret) = tmp_ret;
+                                                       (*num_params) = 1;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               ENDFOREACH(trav2);
+       }
+       ENDFOREACH(trav);
+       xmlFreeDoc(response);
+       return TRUE;
+}
diff --git a/ext/soap/php_packet_soap.h b/ext/soap/php_packet_soap.h
new file mode 100644 (file)
index 0000000..0d09426
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef PHP_PACKET_SOAP_H
+#define PHP_PACKET_SOAP_H
+
+int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctionPtr fn, char *fn_name, zval ***ret, int *num_params);
+
+#endif
\ No newline at end of file
diff --git a/ext/soap/php_schema.c b/ext/soap/php_schema.c
new file mode 100644 (file)
index 0000000..020b299
--- /dev/null
@@ -0,0 +1,1047 @@
+#include "php_soap.h"
+/*
+2.6.1 xsi:type
+2.6.2 xsi:nil
+2.6.3 xsi:schemaLocation, xsi:noNamespaceSchemaLocation
+*/
+
+/*
+<schema
+  attributeFormDefault = (qualified | unqualified) : unqualified
+  blockDefault = (#all | List of (extension | restriction | substitution))  : ''
+  elementFormDefault = (qualified | unqualified) : unqualified
+  finalDefault = (#all | List of (extension | restriction))  : ''
+  id = ID
+  targetNamespace = anyURI
+  version = token
+  xml:lang = language
+  {any attributes with non-schema namespace . . .}>
+  Content: ((include | import | redefine | annotation)*, (((simpleType | complexType | group | attributeGroup) | element | attribute | notation), annotation*)*)
+</schema>
+*/
+int load_schema(sdlPtr *sdl,xmlNodePtr schema)
+{
+       xmlNodePtr trav, element, compType, simpleType, attribute;
+       xmlAttrPtr tns;
+
+       if(!(*sdl)->types)
+       {
+               (*sdl)->types = malloc(sizeof(HashTable));
+               zend_hash_init((*sdl)->types, 0, NULL, delete_type, 1);
+       }
+
+       tns = get_attribute(schema->properties, "targetNamespace");
+
+       trav = schema->children;
+       FOREACHNODE(trav,"complexType",compType)
+       {
+               schema_complexType(sdl, tns, compType, NULL);
+       }
+       ENDFOREACH(trav);
+
+       trav = schema->children;
+       FOREACHNODE(trav,"simpleType",simpleType)
+       {
+               schema_simpleType(sdl, tns, simpleType, NULL);
+       }
+       ENDFOREACH(trav);
+
+       trav = schema->children;
+       FOREACHNODE(trav,"element",element)
+       {
+               schema_element(sdl, tns, element, NULL);
+       }
+       ENDFOREACH(trav);
+
+       trav = schema->children;
+       FOREACHNODE(trav, "attribute", attribute)
+       {
+               schema_attribute(sdl, tns, attribute, NULL);
+       }
+       ENDFOREACH(trav);
+       return FALSE;
+}
+/*
+<simpleType
+  final = (#all | (list | union | restriction))
+  id = ID
+  name = NCName
+  {any attributes with non-schema namespace . . .}>
+  Content: (annotation?, (restriction | list | union))
+</simpleType>
+*/
+int schema_simpleType(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr simpleType, sdlTypePtr cur_type)
+{
+       xmlNodePtr content;
+       xmlAttrPtr name, ns;
+
+       ns = get_attribute(simpleType->properties, "targetNamespace");
+       if(ns == NULL)
+               ns = tsn;
+
+       name = get_attribute(simpleType->properties, "name");
+       if(name != NULL)
+       {
+               HashTable *ht;
+               char *key;
+               sdlTypePtr newType, *ptr;
+
+               newType = malloc(sizeof(sdlType));
+               memset(newType, 0, sizeof(sdlType));
+               newType->name = strdup(name->children->content);
+               newType->namens = strdup(ns->children->content);
+
+               if(cur_type == NULL)
+               {
+                       ht = (*sdl)->types;
+                       key = emalloc(strlen(newType->namens) + strlen(newType->name) + 2);
+                       sprintf(key, "%s:%s", newType->namens, newType->name);
+               }
+               else
+               {
+                       if(cur_type->elements == NULL)
+                       {
+                               cur_type->elements = malloc(sizeof(HashTable));
+                               zend_hash_init(cur_type->elements, 0, NULL, delete_type, 1);
+                       }
+                       key = strdup(newType->name);
+                       ht = cur_type->elements;
+               }
+
+               zend_hash_add(ht, key, strlen(key), &newType, sizeof(sdlTypePtr), (void **)&ptr);
+               cur_type = (*ptr);
+               efree(key);
+       }
+
+       content = get_node(simpleType->children, "restriction");
+       if(content != NULL)
+       {
+               schema_restriction_simpleType(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       content = get_node(simpleType->children, "list");
+       if(content != NULL)
+       {
+               schema_list(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       content = get_node(simpleType->children, "union");
+       if(content != NULL)
+       {
+               schema_union(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+/*
+<list
+  id = ID
+  itemType = QName
+  {any attributes with non-schema namespace . . .}>
+  Content: (annotation?, (simpleType?))
+</list>
+*/
+int schema_list(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr listType, sdlTypePtr cur_type)
+{
+       return TRUE;
+}
+
+/*
+<union
+  id = ID
+  memberTypes = List of QName
+  {any attributes with non-schema namespace . . .}>
+  Content: (annotation?, (simpleType*))
+</union>
+*/
+int schema_union(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr unionType, sdlTypePtr cur_type)
+{
+       return TRUE;
+}
+
+/*
+<simpleContent
+  id = ID
+  {any attributes with non-schema namespace . . .}>
+  Content: (annotation?, (restriction | extension))
+</simpleContent>
+*/
+int schema_simpleContent(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr simpCompType, sdlTypePtr cur_type)
+{
+       xmlNodePtr content;
+
+       content = get_node(simpCompType->children, "restriction");
+       if(content == NULL)
+       {
+               schema_restriction_simpleContent(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       content = get_node(simpCompType->children, "extension");
+       if(content == NULL)
+       {
+               //schema_extension(sdl, tsn, content, cur_type);
+               php_error(E_ERROR, "Error parsing schema (doesn't support extensions on simpleContent)");
+               return TRUE;
+       }
+
+       php_error(E_ERROR, "Error parsing schema (simpleContent)");
+       return FALSE;
+}
+
+/*
+<restriction
+  base = QName
+  id = ID
+  {any attributes with non-schema namespace . . .}>
+  Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))
+</restriction>
+*/
+int schema_restriction_simpleType(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr restType, sdlTypePtr cur_type)
+{
+       xmlNodePtr content, trav;
+       xmlAttrPtr base;
+
+       content = get_node(restType->children, "simpleType");
+       if(content != NULL)
+       {
+               schema_simpleType(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       base = get_attribute(restType->properties, "base");
+       if(base != NULL)
+       {
+               //cur_type->base = estrdup(base->children->content);
+       }
+
+       if(cur_type->restrictions == NULL)
+       {
+               cur_type->restrictions = malloc(sizeof(sdlRestrictions));
+               memset(cur_type->restrictions, 0, sizeof(sdlRestrictions));
+       }
+
+       trav = restType->children;
+       do
+       {
+               if(trav->type == XML_ELEMENT_NODE)
+               {
+                       if(!strcmp(trav->name, "minExclusive"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->minExclusive);
+                       else if(!strcmp(trav->name, "minInclusive"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->minInclusive);
+                       else if(!strcmp(trav->name, "maxExclusive"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->maxExclusive);
+                       else if(!strcmp(trav->name, "maxInclusive"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->maxInclusive);
+                       else if(!strcmp(trav->name, "totalDigits"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->totalDigits);
+                       else if(!strcmp(trav->name, "fractionDigits"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->fractionDigits);
+                       else if(!strcmp(trav->name, "length"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->length);
+                       else if(!strcmp(trav->name, "minLength"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->minLength);
+                       else if(!strcmp(trav->name, "maxLength"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->maxLength);
+                       else if(!strcmp(trav->name, "whiteSpace"))
+                               schema_restriction_var_char(trav, &cur_type->restrictions->whiteSpace);
+                       else if(!strcmp(trav->name, "pattern"))
+                               schema_restriction_var_char(trav, &cur_type->restrictions->pattern);
+                       else if(!strcmp(trav->name, "enumeration"))
+                       {
+                               sdlRestrictionCharPtr enumval = NULL;
+
+                               schema_restriction_var_char(trav, &enumval);
+                               if(cur_type->restrictions->enumeration == NULL)
+                               {
+                                       cur_type->restrictions->enumeration = malloc(sizeof(HashTable));
+                                       zend_hash_init(cur_type->restrictions->enumeration, 0, NULL, delete_schema_restriction_var_char, 1);
+                               }
+                               zend_hash_next_index_insert(cur_type->restrictions->enumeration, &enumval, sizeof(sdlRestrictionCharPtr), NULL);
+                       }
+               }
+       }while(trav = trav->next);
+
+       return TRUE;
+}
+
+/*
+<restriction
+  base = QName
+  id = ID
+  {any attributes with non-schema namespace . . .}>
+  Content: (annotation?, (group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?))
+</restriction>
+*/
+int schema_restriction_complexContent(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr restType, sdlTypePtr cur_type)
+{
+       xmlAttrPtr base;
+       xmlNodePtr trav;
+
+       base = get_attribute(restType->properties, "base");
+       if(base != NULL)
+       {
+               char *type, *ns;
+               xmlNsPtr nsptr;
+
+               parse_namespace(base->children->content, &type, &ns);
+               nsptr = xmlSearchNs(restType->doc, restType, ns);
+               if(nsptr != NULL)
+               {
+                       cur_type->encode = get_encoder((*sdl), (char *)nsptr->href, type);
+               }
+               if(type) efree(type);
+               if(ns) efree(ns);
+       }
+
+       trav = restType->children;
+       do
+       {
+               if(trav->type == XML_ELEMENT_NODE)
+               {
+                       if(!strcmp(trav->name, "group"))
+                       {
+                               schema_group(sdl, tsn, trav, cur_type);
+                               return TRUE;
+                       }
+                       else if(!strcmp(trav->name, "all"))
+                       {
+                               schema_all(sdl, tsn, trav, cur_type);
+                               return TRUE;
+                       }
+                       else if(!strcmp(trav->name, "choice"))
+                       {
+                               schema_choice(sdl, tsn, trav, cur_type);
+                               return TRUE;
+                       }
+                       else if(!strcmp(trav->name, "sequence"))
+                       {
+                               schema_sequence(sdl, tsn, trav, cur_type);
+                               return TRUE;
+                       }
+                       else if(!strcmp(trav->name, "attribute"))
+                       {
+                               schema_attribute(sdl, tsn, trav, cur_type);
+                       }
+               }
+       }while(trav = trav->next);
+
+       return TRUE;
+}
+
+/*
+<restriction
+  base = QName
+  id = ID
+  {any attributes with non-schema Namespace . . .}>
+  Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*))
+</restriction>
+*/
+int schema_restriction_simpleContent(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr restType, sdlTypePtr cur_type)
+{
+       xmlNodePtr content, trav;
+       xmlAttrPtr base;
+
+       base = get_attribute(restType->properties, "base");
+       if(base != NULL)
+               cur_type->encode = get_encoder_from_prefix((*sdl), restType, base->children->content);
+
+       content = get_node(restType->children, "simpleType");
+       if(content != NULL)
+       {
+               schema_simpleType(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       if(cur_type->restrictions == NULL)
+               cur_type->restrictions = malloc(sizeof(sdlRestrictions));
+
+       trav = restType->children;
+       do
+       {
+               if(trav->type == XML_ELEMENT_NODE)
+               {
+                       if(!strcmp(trav->name, "minExclusive"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->minExclusive);
+                       else if(!strcmp(trav->name, "minInclusive"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->minInclusive);
+                       else if(!strcmp(trav->name, "maxExclusive"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->maxExclusive);
+                       else if(!strcmp(trav->name, "maxInclusive"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->maxInclusive);
+                       else if(!strcmp(trav->name, "totalDigits"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->totalDigits);
+                       else if(!strcmp(trav->name, "fractionDigits"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->fractionDigits);
+                       else if(!strcmp(trav->name, "length"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->length);
+                       else if(!strcmp(trav->name, "minLength"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->minLength);
+                       else if(!strcmp(trav->name, "maxLength"))
+                               schema_restriction_var_int(trav, &cur_type->restrictions->maxLength);
+                       else if(!strcmp(trav->name, "whiteSpace"))
+                               schema_restriction_var_char(trav, &cur_type->restrictions->whiteSpace);
+                       else if(!strcmp(trav->name, "pattern"))
+                               schema_restriction_var_char(trav, &cur_type->restrictions->pattern);
+                       else if(!strcmp(trav->name, "enumeration"))
+                       {
+                               sdlRestrictionCharPtr enumval = NULL;
+
+                               schema_restriction_var_char(trav, &enumval);
+                               if(cur_type->restrictions->enumeration == NULL)
+                               {
+                                       cur_type->restrictions->enumeration = malloc(sizeof(HashTable));
+                                       zend_hash_init(cur_type->restrictions->enumeration, 0, NULL, delete_schema_restriction_var_char, 1);
+                               }
+                               zend_hash_next_index_insert(cur_type->restrictions->enumeration, &enumval, sizeof(sdlRestrictionCharPtr), NULL);
+                       }
+               }
+       }while(trav = trav->next);
+
+       return TRUE;
+}
+
+int schema_restriction_var_int(xmlNodePtr val, sdlRestrictionIntPtr *valptr)
+{
+       xmlAttrPtr fixed, value, id;
+
+       if((*valptr) == NULL)
+               (*valptr) = malloc(sizeof(sdlRestrictionInt));
+
+       fixed = get_attribute(val->properties, "fixed");
+       (*valptr)->fixed = FALSE;
+       if(fixed != NULL)
+       {
+               if(!strcmp(fixed->children->content, "true") ||
+                       !strcmp(fixed->children->content, "1"))
+                       (*valptr)->fixed = TRUE;
+       }
+
+       id = get_attribute(val->properties, "id");
+       if(id != NULL)
+               (*valptr)->id = strdup(id->children->content);
+
+       value = get_attribute(val->properties, "value");
+       if(value == NULL)
+               php_error(E_ERROR, "Error parsing wsdl schema \"missing value for minExclusive\"");
+
+       (*valptr)->value = atoi(value->children->content);
+
+       return TRUE;
+}
+
+void delete_restriction_var_int(void *rvi)
+{
+       sdlRestrictionIntPtr ptr = *((sdlRestrictionIntPtr*)rvi);
+       if(ptr->id);
+               free(ptr->id);
+
+       free(ptr);
+}
+
+int schema_restriction_var_char(xmlNodePtr val, sdlRestrictionCharPtr *valptr)
+{
+       xmlAttrPtr fixed, value, id;
+
+       if((*valptr) == NULL)
+               (*valptr) = malloc(sizeof(sdlRestrictionChar));
+
+       fixed = get_attribute(val->properties, "fixed");
+       (*valptr)->fixed = FALSE;
+       if(fixed != NULL)
+       {
+               if(!strcmp(fixed->children->content, "true") ||
+                       !strcmp(fixed->children->content, "1"))
+                       (*valptr)->fixed = TRUE;
+       }
+
+       id = get_attribute(val->properties, "id");
+       if(id != NULL)
+               (*valptr)->id = strdup(id->children->content);
+
+       value = get_attribute(val->properties, "value");
+       if(value == NULL)
+               php_error(E_ERROR, "Error parsing wsdl schema \"missing value restriction\"");
+
+       (*valptr)->value = strdup(value->children->content);
+       return TRUE;
+}
+
+void delete_schema_restriction_var_char(void *srvc)
+{
+       sdlRestrictionCharPtr ptr = *((sdlRestrictionCharPtr*)srvc);
+       if(ptr->id)
+               free(ptr->id);
+       if(ptr->value)
+               free(ptr->value);
+       free(ptr);
+}
+
+/*
+From simpleContent (not supported):
+<extension
+  base = QName
+  id = ID
+  {any attributes with non-schema namespace . . .}>
+  Content: (annotation?, ((attribute | attributeGroup)*, anyAttribute?))
+</extension>
+
+From complexContent:
+<extension
+  base = QName
+  id = ID
+  {any attributes with non-schema namespace . . .}>
+  Content: (annotation?, ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?)))
+</extension>
+*/
+int schema_extension(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr extType, sdlTypePtr cur_type)
+{
+       xmlNodePtr content;
+       xmlAttrPtr base;
+
+       base = get_attribute(extType->properties, "base");
+
+       content = get_node(extType->children, "group");
+       if(content != NULL)
+       {
+               schema_group(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       content = get_node(extType->children, "all");
+       if(content != NULL)
+       {
+               schema_all(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       content = get_node(extType->children, "choice");
+       if(content != NULL)
+       {
+               schema_choice(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       content = get_node(extType->children, "sequence");
+       if(content != NULL)
+       {
+               schema_sequence(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+       return FALSE;
+}
+
+/*
+<all
+  id = ID
+  maxOccurs = 1 : 1
+  minOccurs = (0 | 1) : 1
+  {any attributes with non-schema namespace . . .}>
+  Content: (annotation?, element*)
+</all>
+*/
+int schema_all(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr all, sdlTypePtr cur_type)
+{
+       xmlNodePtr element, trav;
+
+       trav = all->children;
+       FOREACHNODE(trav, "element", element)
+       {
+               schema_element(sdl, tsn, element, cur_type);
+       }
+       ENDFOREACH(trav);
+       return TRUE;
+}
+
+/*
+<group
+  name = NCName>
+  Content: (annotation?, (all | choice | sequence))
+</group>
+*/
+int schema_group(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr groupType, sdlTypePtr cur_type)
+{
+       xmlNodePtr content;
+       xmlAttrPtr name;
+
+       name = get_attribute(groupType->properties, "name");
+       if(name != NULL)
+       {
+
+       }
+
+       content = get_node(groupType->children, "all");
+       if(content != NULL)
+       {
+               schema_all(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       content = get_node(groupType->children, "choice");
+       if(content != NULL)
+       {
+               schema_choice(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       content = get_node(groupType->children, "sequence");
+       if(content != NULL)
+       {
+               schema_sequence(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+       return FALSE;
+}
+/*
+<choice
+  id = ID
+  maxOccurs = (nonNegativeInteger | unbounded)  : 1
+  minOccurs = nonNegativeInteger : 1
+  {any attributes with non-schema namespace . . .}>
+  Content: (annotation?, (element | group | choice | sequence | any)*)
+</choice>
+*/
+int schema_choice(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr choiceType, sdlTypePtr cur_type)
+{
+       xmlNodePtr trav, data;
+
+       //cur_type->property_type = CHOICE;
+
+       trav = choiceType->children;
+       FOREACHNODE(trav, "element", data)
+       {
+               schema_element(sdl, tsn, data, cur_type);
+       }
+       ENDFOREACH(trav);
+
+       trav = choiceType->children;
+       FOREACHNODE(trav, "group", data)
+       {
+               schema_group(sdl, tsn, data, cur_type);
+       }
+       ENDFOREACH(trav);
+
+       trav = choiceType->children;
+       FOREACHNODE(trav, "choice", data)
+       {
+               schema_choice(sdl, tsn, data, cur_type);
+       }
+       ENDFOREACH(trav);
+
+       trav = choiceType->children;
+       FOREACHNODE(trav, "sequence", data)
+       {
+               schema_sequence(sdl, tsn, data, cur_type);
+       }
+       ENDFOREACH(trav);
+
+       trav = choiceType->children;
+       FOREACHNODE(trav, "any", data)
+       {
+               schema_any(sdl, tsn, data, cur_type);
+       }
+       ENDFOREACH(trav);
+
+       return TRUE;
+}
+
+/*
+<sequence
+  id = ID
+  maxOccurs = (nonNegativeInteger | unbounded)  : 1
+  minOccurs = nonNegativeInteger : 1
+  {any attributes with non-schema namespace . . .}>
+  Content: (annotation?, (element | group | choice | sequence | any)*)
+</sequence>
+*/
+int schema_sequence(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr seqType, sdlTypePtr cur_type)
+{
+       xmlNodePtr trav;
+
+       trav = seqType->children;
+       do
+       {
+               if(trav->type == XML_ELEMENT_NODE)
+               {
+                       if(!strcmp(trav->name, "element"))
+                       {
+                               schema_element(sdl, tsn, trav, cur_type);
+                       }
+                       else if(!strcmp(trav->name, "group"))
+                       {
+                               schema_group(sdl, tsn, trav, cur_type);
+                       }
+                       else if(!strcmp(trav->name, "choice"))
+                       {
+                               schema_choice(sdl, tsn, trav, cur_type);
+                       }
+                       else if(!strcmp(trav->name, "sequence"))
+                       {
+                               schema_sequence(sdl, tsn, trav, cur_type);
+                       }
+                       else if(!strcmp(trav->name, "any"))
+                       {
+                               schema_any(sdl, tsn, trav, cur_type);
+                       }
+               }
+       }
+       while(trav = trav->next);
+
+       return TRUE;
+}
+
+int schema_any(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr extType, sdlTypePtr cur_type)
+{
+       return TRUE;
+}
+
+/*
+<complexContent
+  id = ID
+  mixed = boolean
+  {any attributes with non-schema namespace . . .}>
+  Content: (annotation?, (restriction | extension))
+</complexContent>
+*/
+int schema_complexContent(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr compCont, sdlTypePtr cur_type)
+{
+       xmlNodePtr content;
+
+       content = get_node(compCont->children, "restriction");
+       if(content != NULL)
+       {
+               schema_restriction_complexContent(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       return TRUE;
+}
+
+/*
+<complexType
+  abstract = boolean : false
+  block = (#all | List of (extension | restriction))
+  final = (#all | List of (extension | restriction))
+  id = ID
+  mixed = boolean : false
+  name = NCName
+  {any attributes with non-schema namespace . . .}>
+  Content: (annotation?, (simpleContent | complexContent | ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?))))
+</complexType>
+*/
+int schema_complexType(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr compType, sdlTypePtr cur_type)
+{
+       xmlNodePtr content;
+       xmlAttrPtr attrs, name, ns;
+
+       attrs = compType->properties;
+       ns = get_attribute(attrs, "targetNamespace");
+       if(ns == NULL)
+               ns = tsn;
+
+       name = get_attribute(attrs, "name");
+       if(name)
+       {
+               HashTable *ht;
+               sdlTypePtr newType, *ptr;
+               char *key;
+
+               newType = malloc(sizeof(sdlType));
+               memset(newType, 0, sizeof(sdlType));
+               newType->name = strdup(name->children->content);
+               newType->namens = strdup(ns->children->content);
+
+               if(cur_type == NULL)
+               {
+                       ht = (*sdl)->types;
+                       key = emalloc(strlen(newType->namens) + strlen(newType->name) + 2);
+                       sprintf(key, "%s:%s", newType->namens, newType->name);
+               }
+               else
+               {
+                       if(cur_type->elements == NULL)
+                       {
+                               cur_type->elements = malloc(sizeof(HashTable));
+                               zend_hash_init(cur_type->elements, 0, NULL, delete_type, 1);
+                       }
+                       ht = cur_type->elements;
+                       key = estrdup(cur_type->name);
+               }
+
+               zend_hash_add(ht, key, strlen(key), &newType, sizeof(sdlTypePtr), (void **)&ptr);
+               cur_type = (*ptr);
+               create_encoder((*sdl), cur_type, ns->children->content, name->children->content);
+               efree(key);
+       }
+
+       content = get_node(compType->children, "simpleContent");
+       if(content != NULL)
+       {
+               schema_simpleContent(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       content = get_node(compType->children, "complexContent");
+       if(content != NULL)
+       {
+               schema_complexContent(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       //(group | all | choice | sequence)
+       content = get_node(compType->children, "group");
+       if(content != NULL)
+       {
+               schema_group(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       content = get_node(compType->children, "all");
+       if(content != NULL)
+       {
+               schema_all(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       content = get_node(compType->children, "choice");
+       if(content != NULL)
+       {
+               schema_choice(sdl, tsn, content, cur_type);
+               return TRUE;
+       }
+
+       content = get_node(compType->children, "sequence");
+       if(content != NULL)
+               schema_sequence(sdl, tsn, content, cur_type);
+
+       return TRUE;
+}
+/*
+<element
+  abstract = boolean : false
+  block = (#all | List of (extension | restriction | substitution))
+  default = string
+  final = (#all | List of (extension | restriction))
+  fixed = string
+  form = (qualified | unqualified)
+  id = ID
+  maxOccurs = (nonNegativeInteger | unbounded)  : 1
+  minOccurs = nonNegativeInteger : 1
+  name = NCName
+  nillable = boolean : false
+  ref = QName
+  substitutionGroup = QName
+  type = QName
+  {any attributes with non-schema namespace . . .}>
+  Content: (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*))
+</element>
+*/
+int schema_element(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr element, sdlTypePtr cur_type)
+{
+       xmlNodePtr content;
+       xmlAttrPtr attrs, curattr, name, ns;
+       TSRMLS_FETCH();
+
+       attrs = element->properties;
+       ns = get_attribute(attrs, "targetNamespace");
+       if(ns == NULL)
+               ns = tsn;
+
+       name = get_attribute(attrs, "name");
+       if(!name)
+               name = get_attribute(attrs, "ref");
+       if(name)
+       {
+               HashTable *addHash;
+               sdlTypePtr newType, *tmp;
+
+               newType = malloc(sizeof(sdlType));
+
+               memset(newType, 0, sizeof(sdlType));
+               newType->name = strdup(name->children->content);
+               newType->namens = strdup(tsn->children->content);
+               newType->nullable = FALSE;
+               newType->min_occurs = 1;
+               newType->max_occurs = 1;
+
+               if(cur_type == NULL)
+                       addHash = (*sdl)->types;
+               else
+               {
+                       if(cur_type->elements == NULL)
+                       {
+                               cur_type->elements = malloc(sizeof(HashTable));
+                               zend_hash_init(cur_type->elements, 0, NULL, delete_type, 1);
+                       }
+                       addHash = cur_type->elements;
+               }
+
+               zend_hash_add(addHash, newType->name, strlen(newType->name), &newType, sizeof(sdlTypePtr), (void **)&tmp);
+               cur_type = (*tmp);
+       }
+
+       //nillable = boolean : false
+       attrs = element->properties;
+       curattr = get_attribute(attrs, "nillable");
+       if(curattr != NULL)
+       {
+               if(!stricmp(curattr->children->content, "true") ||
+                       !stricmp(curattr->children->content, "1"))
+                       cur_type->nullable = TRUE;
+               else
+                       cur_type->nullable = FALSE;
+       }
+       else
+               cur_type->nullable = FALSE;
+
+       //type = QName
+       curattr = get_attribute(attrs, "type");
+       if(!curattr)
+               curattr = name;
+       if(curattr)
+       {
+               char *cptype, *str_ns;
+               xmlNsPtr nsptr;
+
+               parse_namespace(curattr->children->content, &cptype, &str_ns);
+               if(str_ns)
+                       nsptr = xmlSearchNs(element->doc, element, str_ns);
+               else
+                       nsptr = xmlSearchNsByHref(element->doc, element, ns->children->content);
+
+               cur_type->encode = get_create_encoder((*sdl), cur_type, (char *)nsptr->href, (char *)cptype);
+               if(str_ns) efree(str_ns);
+               if(cptype) efree(cptype);
+       }
+
+       content = get_node(element->children, "simpleType");
+       if(content)
+               schema_simpleType(sdl, tsn, content, cur_type);
+
+       content = get_node(element->children, "complexType");
+       if(content)
+               schema_complexType(sdl, tsn, content, cur_type);
+
+       return FALSE;
+}
+
+/*
+<attribute
+  default = string
+  fixed = string
+  form = (qualified | unqualified)
+  id = ID
+  name = NCName
+  ref = QName
+  type = QName
+  use = (optional | prohibited | required) : optional
+  {any attributes with non-schema namespace . . .}>
+  Content: (annotation?, (simpleType?))
+</attribute>
+*/
+int schema_attribute(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr attrType, sdlTypePtr cur_type)
+{
+       xmlAttrPtr attr;
+       sdlAttributePtr newAttr;
+       xmlAttrPtr trav;
+       smart_str key = {0};
+
+       newAttr = malloc(sizeof(sdlAttribute));
+       memset(newAttr, 0, sizeof(sdlAttribute));
+
+       if(cur_type->attributes == NULL)
+       {
+               cur_type->attributes = malloc(sizeof(HashTable));
+               zend_hash_init(cur_type->attributes, 0, NULL, delete_attribute, 1);
+       }
+
+       trav = attrType->properties;
+       FOREACHATTRNODE(trav, NULL, attr)
+       {
+               if(attr_is_equal_ex(trav, "default", SCHEMA_NAMESPACE))
+                       newAttr->def = strdup(attr->children->content);
+               else if(attr_is_equal_ex(trav, "fixed", SCHEMA_NAMESPACE))
+                       newAttr->fixed = strdup(attr->children->content);
+               else if(attr_is_equal_ex(trav, "form", SCHEMA_NAMESPACE))
+                       newAttr->form = strdup(attr->children->content);
+               else if(attr_is_equal_ex(trav, "id", SCHEMA_NAMESPACE))
+                       newAttr->id = strdup(attr->children->content);
+               else if(attr_is_equal_ex(trav, "name", SCHEMA_NAMESPACE))
+                       newAttr->name = strdup(attr->children->content);
+               else if(attr_is_equal_ex(trav, "ref", SCHEMA_NAMESPACE))
+                       newAttr->ref= strdup(attr->children->content);
+               else if(attr_is_equal_ex(trav, "type", SCHEMA_NAMESPACE))
+                       newAttr->type = strdup(attr->children->content);
+               else if(attr_is_equal_ex(trav, "use", SCHEMA_NAMESPACE))
+                       newAttr->use = strdup(attr->children->content);
+               else
+               {
+                       xmlNsPtr nsPtr = attr_find_ns(trav);
+
+                       if(strcmp(nsPtr->href, SCHEMA_NAMESPACE))
+                       {
+                               smart_str key2 = {0};
+
+                               if(!newAttr->extraAttributes)
+                               {
+                                       newAttr->extraAttributes = malloc(sizeof(HashTable));
+                                       zend_hash_init(newAttr->extraAttributes, 0, NULL, NULL, 1);
+                               }
+
+                               smart_str_appends(&key2, nsPtr->href);
+                               smart_str_appendc(&key2, ':');
+                               smart_str_appends(&key2, trav->name);
+                               smart_str_0(&key2);
+                               zend_hash_add(newAttr->extraAttributes, key2.c, key2.len + 1, &trav, sizeof(xmlAttrPtr), NULL);
+                               smart_str_free(&key2);
+                       }
+               }
+       }
+       ENDFOREACH(trav);
+
+
+       if(newAttr->ref || newAttr->name)
+       {
+               xmlNsPtr ns;
+
+               if(newAttr->ref)
+               {
+                       char *value, *prefix = NULL;
+
+                       parse_namespace(newAttr->ref, &value, &prefix);
+                       ns = xmlSearchNs(attrType->doc, attrType, prefix);
+                       smart_str_appends(&key, ns->href);
+                       smart_str_appendc(&key, ':');
+                       smart_str_appends(&key, value);
+
+                       if(value)
+                               efree(value);
+                       if(prefix)
+                               efree(prefix);
+               }
+               else
+               {
+                       ns = node_find_ns(attrType);
+                       smart_str_appends(&key, ns->href);
+                       smart_str_appendc(&key, ':');
+                       smart_str_appends(&key, newAttr->name);
+               }
+
+
+               if(ns)
+               {
+                       smart_str_0(&key);
+                       zend_hash_add(cur_type->attributes, key.c, key.len + 1, &newAttr, sizeof(sdlAttributePtr), NULL);
+                       smart_str_free(&key);
+                       return TRUE;
+               }
+       }
+
+       zend_hash_next_index_insert(cur_type->attributes, &newAttr, sizeof(sdlAttributePtr), NULL);
+       return TRUE;
+}
\ No newline at end of file
diff --git a/ext/soap/php_schema.h b/ext/soap/php_schema.h
new file mode 100644 (file)
index 0000000..c43a221
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef PHP_SCHEMA_H
+#define PHP_SCHEMA_H
+
+int load_schema(sdlPtr *sdl,xmlNodePtr schema);
+int schema_simpleType(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr simpleType, sdlTypePtr cur_type);
+int schema_complexType(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr compType, sdlTypePtr cur_type);
+int schema_sequence(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr seqType, sdlTypePtr cur_type);
+int schema_list(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr listType, sdlTypePtr cur_type);
+int schema_union(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr unionType, sdlTypePtr cur_type);
+int schema_simpleContent(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr simpCompType, sdlTypePtr cur_type);
+int schema_restriction_simpleType(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr restType, sdlTypePtr cur_type);
+int schema_restriction_simpleContent(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr restType, sdlTypePtr cur_type);
+int schema_restriction_complexContent(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr restType, sdlTypePtr cur_type);
+int schema_extension(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr extType, sdlTypePtr cur_type);
+int schema_all(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr extType, sdlTypePtr cur_type);
+int schema_group(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr groupType, sdlTypePtr cur_type);
+int schema_choice(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr choiceType, sdlTypePtr cur_type);
+int schema_element(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr element, sdlTypePtr cur_type);
+int schema_attribute(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr attrType, sdlTypePtr cur_type);
+int schema_any(sdlPtr *sdl, xmlAttrPtr tsn, xmlNodePtr extType, sdlTypePtr cur_type);
+
+int schema_restriction_var_int(xmlNodePtr val, sdlRestrictionIntPtr *valptr);
+void delete_restriction_var_int(void *rvi);
+
+int schema_restriction_var_char(xmlNodePtr val, sdlRestrictionCharPtr *valptr);
+void delete_schema_restriction_var_char(void *srvc);
+
+#endif
diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c
new file mode 100644 (file)
index 0000000..9d73d2f
--- /dev/null
@@ -0,0 +1,915 @@
+#include "php_soap.h"
+
+encodePtr get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr data, char *type)
+{
+       encodePtr enc = NULL;
+       TSRMLS_FETCH();
+
+       enc = get_conversion_from_type(data, type);
+       if(enc == NULL && sdl)
+               enc = get_conversion_from_type_ex(sdl->encoders, data, type);
+       if(enc == NULL)
+               enc = get_conversion(UNKNOWN_TYPE);
+
+       return enc;
+}
+
+encodePtr get_encoder(sdlPtr sdl, char *ns, char *type)
+{
+       encodePtr enc = NULL;
+       char *nscat;
+       TSRMLS_FETCH();
+
+       nscat = emalloc(strlen(ns) + strlen(type) + 2);
+       sprintf(nscat, "%s:%s", ns, type);
+
+       enc = get_encoder_ex(sdl, nscat);
+
+       efree(nscat);
+       return enc;
+}
+
+encodePtr get_encoder_ex(sdlPtr sdl, char *nscat)
+{
+       encodePtr enc = NULL;
+       TSRMLS_FETCH();
+
+       enc = get_conversion_from_href_type(nscat);
+       if(enc == NULL && sdl)
+               enc = get_conversion_from_href_type_ex(sdl->encoders, nscat);
+       if(enc == NULL)
+               enc = get_conversion(UNKNOWN_TYPE);
+       return enc;
+}
+
+encodePtr get_create_encoder(sdlPtr sdl, sdlTypePtr cur_type, char *ns, char *type)
+{
+       encodePtr enc = NULL;
+       char *nscat;
+       TSRMLS_FETCH();
+
+       nscat = emalloc(strlen(ns) + strlen(type) + 2);
+       sprintf(nscat, "%s:%s", ns, type);
+
+       enc = get_conversion_from_href_type(nscat);
+       if(enc == NULL)
+               enc = get_conversion_from_href_type_ex(sdl->encoders, nscat);
+       if(enc == NULL)
+               enc = create_encoder(sdl, cur_type, ns, type);
+
+       efree(nscat);
+       return enc;
+}
+
+encodePtr create_encoder(sdlPtr sdl, sdlTypePtr cur_type, char *ns, char *type)
+{
+       char *nscat;
+       encodePtr enc;
+
+       enc = malloc(sizeof(encode));
+       memset(enc, 0, sizeof(encode));
+
+       nscat = emalloc(strlen(ns) + strlen(type) + 2);
+       sprintf(nscat, "%s:%s", ns, type);
+
+       enc->details.ns = strdup(ns);
+       enc->details.type_str = strdup(type);
+       enc->details.sdl_type = cur_type;
+       enc->to_xml = sdl_guess_convert_xml;
+       enc->to_zval = guess_zval_convert;
+
+       if(sdl->encoders == NULL)
+       {
+               sdl->encoders = malloc(sizeof(HashTable));
+               zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, 1);
+       }
+       zend_hash_add(sdl->encoders, nscat, strlen(nscat), &enc, sizeof(encodePtr), NULL);
+       efree(nscat);
+       return enc;
+}
+xmlNodePtr sdl_guess_convert_xml(encodeType enc, zval *data)
+{
+       sdlTypePtr type;
+       xmlNodePtr ret;
+
+       ret = xmlNewNode(NULL, "BOGUS");
+       type = enc.sdl_type;
+
+       if(type->encode->details.type == IS_ARRAY ||
+               type->encode->details.type == SOAP_ENC_ARRAY)
+       {
+               ret = sdl_to_xml_array(type, data);
+       }
+       else if(type->encode != NULL)
+       {
+               ret = master_to_xml(type->encode, data);
+       }
+       else if(type->elements != NULL)
+       {
+               ret = sdl_to_xml_object(type, data);
+       }
+       else
+       {
+               ret = guess_xml_convert(enc, data);
+       }
+
+       //set_ns_and_type(ret, enc);
+       return ret;
+}
+
+xmlNodePtr sdl_to_xml_object(sdlTypePtr type, zval *data)
+{
+       xmlNodePtr ret;
+       sdlTypePtr *t, tmp;
+
+       ret = xmlNewNode(NULL, "BOGUS");
+
+       zend_hash_internal_pointer_reset(type->elements);
+       while(zend_hash_get_current_data(type->elements, (void **)&t) != FAILURE)
+       {
+               zval **prop;
+               tmp = *t;
+               if(zend_hash_find(Z_OBJPROP_P(data), tmp->name, strlen(tmp->name) + 1, (void **)&prop) == FAILURE)
+               {
+                       if(tmp->nullable == FALSE)
+                               php_error(E_ERROR, "Error encoding object to xml missing property \"%s\"", tmp->name);
+               }
+               else
+               {
+                       xmlNodePtr newNode;
+
+                       newNode = master_to_xml(tmp->encode, (*prop));
+                       xmlNodeSetName(newNode, tmp->name);
+                       xmlAddChild(ret, newNode);
+               }
+               zend_hash_move_forward(type->elements);
+       }
+
+       return ret;
+}
+
+xmlNodePtr sdl_to_xml_array(sdlTypePtr type, zval *data)
+{
+       smart_str array_type_and_size = {0}, array_type = {0};
+       int i;
+       xmlNodePtr xmlParam;
+       TSRMLS_FETCH();
+
+       xmlParam = xmlNewNode(NULL,"BOGUS");
+
+       FIND_ZVAL_NULL(data, xmlParam);
+
+       if(Z_TYPE_P(data) == IS_ARRAY)
+       {
+               sdlAttributePtr *arrayType;
+               i = zend_hash_num_elements(Z_ARRVAL_P(data));
+
+               if(zend_hash_find(type->attributes, SOAP_ENC_NAMESPACE":arrayType", sizeof(SOAP_ENC_NAMESPACE":arrayType"), (void **)&arrayType) == SUCCESS)
+               {
+                       xmlAttrPtr *wsdl;
+                       if(zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arrayType", sizeof(WSDL_NAMESPACE":arrayType"), (void **)&wsdl) == SUCCESS)
+                       {
+                               char *ns = NULL, *value;
+                               smart_str *prefix = encode_new_ns();
+                               smart_str smart_ns = {0};
+                               xmlNsPtr myNs;
+
+                               parse_namespace((*wsdl)->children->content, &value, &ns);
+                               myNs = xmlSearchNs((*wsdl)->doc, (*wsdl)->parent, ns);
+
+                               smart_str_appendl(&smart_ns, "xmlns:", sizeof("xmlns:") - 1);
+                               smart_str_appendl(&smart_ns, prefix->c, prefix->len);
+                               smart_str_0(&smart_ns);
+
+                               xmlSetProp(xmlParam, smart_ns.c, myNs->href);
+                               smart_str_appends(&array_type_and_size, prefix->c);
+                               smart_str_appendc(&array_type_and_size, ':');
+                               smart_str_appends(&array_type_and_size, value);
+                               smart_str_0(&array_type_and_size);
+                       }
+               }
+               else
+               {
+                       smart_str_appends(&array_type_and_size, type->name);
+                       smart_str_appendc(&array_type_and_size, '[');
+                       smart_str_append_long(&array_type_and_size, i);
+                       smart_str_appendc(&array_type_and_size, ']');
+                       smart_str_0(&array_type_and_size);
+               }
+
+               xmlSetProp(xmlParam, SOAP_ENC_NS_PREFIX":arrayType", array_type_and_size.c);
+
+               smart_str_free(&array_type_and_size);
+               smart_str_free(&array_type);
+
+               zend_hash_internal_pointer_reset(data->value.ht);
+               for(;i > 0;i--)
+               {
+                       xmlNodePtr xparam;
+                       zval **zdata;
+                       encodePtr enc;
+                       zend_hash_get_current_data(data->value.ht, (void **)&zdata);
+
+                       enc = get_conversion((*zdata)->type);
+                       xparam = master_to_xml(enc, (*zdata));
+
+                       xmlNodeSetName(xparam, "val");
+                       xmlAddChild(xmlParam, xparam);
+                       zend_hash_move_forward(data->value.ht);
+               }
+       }
+       set_ns_and_type_ex(xmlParam, type->namens, type->name);
+       return xmlParam;
+}
+
+zval *sdl_convert_zval(encodeType enc, xmlNodePtr data)
+{
+       zval *ret;
+       MAKE_STD_ZVAL(ret);
+       ZVAL_STRING(ret, "blah", 1);
+
+       return ret;
+}
+
+/*
+zval *sdl_convert_zval(xmlNodePtr data, sdlTypePtr type)
+{
+       found = zend_hash_find(EG(class_table), class_name, class_name_len + 1, (void **)&ce);
+       if(found != FAILURE)
+       {
+               service->type = SOAP_CLASS;
+               service->soap_class.ce = ce;
+       }
+}
+//this function will take a zval and apply all attributes of sldTypePtr
+zval *sdl_convert_zval_to_zval(zval *data, sdlTypePtr type)
+{
+}
+*/
+
+
+sdlPtr get_sdl(char *uri)
+{
+       sdlPtr tmp, *hndl;
+       TSRMLS_FETCH();
+
+       tmp = NULL;
+       hndl = NULL;
+       if(zend_hash_find(SOAP_GLOBAL(sdls), uri, strlen(uri), (void **)&hndl) == FAILURE)
+       {
+               tmp = load_wsdl(uri);
+               zend_hash_add(SOAP_GLOBAL(sdls), uri, strlen(uri), &tmp, sizeof(sdlPtr), NULL);
+       }
+       else
+               tmp = *hndl;
+
+       return tmp;
+}
+
+int load_php_sdl()
+{
+/*     xmlNodePtr rootElement;
+       xmlNodePtr services;
+
+       SOAP_SERVER_GLOBAL_VARS();
+       SOAP_SERVER_GLOBAL(availableServices) = xmlParseFile(servicesFile);
+       rootElement = SOAP_SERVER_GLOBAL(availableServices)->children;
+       services = rootElement->children;
+
+       do
+       {
+               if(IS_ELEMENT_TYPE(services,PHP_SOAPSERVER_SERVICE))
+               {
+                       phpSoapServicePtr newService;
+                       xmlNodePtr attrib, trav;
+                       HashTable *fn = NULL;
+                       HashTable *include = NULL;
+                       HashTable *cl = NULL;
+
+                       //Init New Service
+                       newService = emalloc(sizeof(phpSoapService));
+                       newService->serviceNode = services;
+                       newService->started = FALSE;
+
+                       fn = newService->functions = emalloc(sizeof(HashTable));
+                       include = newService->include_files = emalloc(sizeof(HashTable));
+                       zend_hash_init(fn, 0, NULL, free_function, 0);
+                       zend_hash_init(include, 0, NULL, ZVAL_PTR_DTOR, 0);
+
+                       attrib = services->properties;
+                       trav = attrib;
+                       //Get Attributes of Service
+                       do
+                       {
+                               if(IS_ATTRIBUTE_TYPE(trav,PHP_SOAPSERVER_SERVICE_NAME))
+                               {
+                                       char* name = ATTRIBUTE_VALUE(trav);
+
+                                       //Assign Service Vals
+                                       ALLOC_INIT_ZVAL(newService->serviceName);
+                                       ZVAL_STRING(newService->serviceName,name,1);
+                               }
+
+                               if(IS_ATTRIBUTE_TYPE(trav,PHP_SOAPSERVER_SERVICE_STARTED))
+                               {
+                                       char* started = ATTRIBUTE_VALUE(trav);
+
+                                       //Assign Service Vals
+                                       if(!stricmp(started,"true"))
+                                               newService->started = TRUE;
+                               }
+                       }
+                       while(trav = trav->next);
+
+                       //Get ChildNodes of Service
+                       trav = services->children;
+                       do
+                       {
+                               //Include Files
+                               if(IS_ELEMENT_TYPE(trav,PHP_SOAPSERVER_SERVICE_INCLUDE_FILE))
+                               {
+                                       xmlNodePtr trav1 = trav->properties;
+                                       do
+                                       {
+                                               if(IS_ATTRIBUTE_TYPE(trav1,PHP_SOAPSERVER_SERVICE_INCLUDE_FILE_NAME))
+                                               {
+                                                       char* name = ATTRIBUTE_VALUE(trav1);
+                                                       zval* z_name;
+                                                       ALLOC_INIT_ZVAL(z_name);
+                                                       ZVAL_STRING(z_name,name,1);
+                                                       zend_hash_next_index_insert(include,&z_name,sizeof(zval),NULL);
+                                               }
+                                       }
+                                       while(trav1 = trav1->next);
+                               }
+
+                               //Functions
+                               if(IS_ELEMENT_TYPE(trav,PHP_SOAPSERVER_SERVICE_FUNCTION))
+                               {
+                                       phpSoapServiceFunctionPtr function;
+                                       xmlNodePtr trav1;
+                                       HashTable *par = NULL;
+
+                                       function = emalloc(sizeof(phpSoapServiceFunction));
+                                       function->functionNode = trav;
+
+                                       par = function->functionParams = emalloc(sizeof(HashTable));
+                                       zend_hash_init(par, 0, NULL, free_param, 0);
+
+                                       trav1 = trav->properties;
+
+                                       do
+                                       {
+                                               if(IS_ATTRIBUTE_TYPE(trav1,PHP_SOAPSERVER_SERVICE_FUNCTION_NAME))
+                                               {
+                                                       char* name = ATTRIBUTE_VALUE(trav1);
+                                                       ALLOC_INIT_ZVAL(function->functionName);
+                                                       ZVAL_STRING(function->functionName,name,1);
+                                               }
+                                       }
+                                       while(trav1 = trav1->next);
+
+                                       trav1 = trav->children;
+                                       do
+                                       {
+                                               if(IS_ELEMENT_TYPE(trav1,PHP_SOAPSERVER_SERVICE_FUNCTION_PARAM))
+                                               {
+                                                       phpSoapServiceParamPtr param;
+                                                       xmlNodePtr trav2;
+
+                                                       param = emalloc(sizeof(phpSoapServiceParam));
+                                                       param->paramNode = trav1;
+
+                                                       trav2 = trav1->properties;
+
+                                                       do
+                                                       {
+                                                               if(IS_ATTRIBUTE_TYPE(trav2,PHP_SOAPSERVER_SERVICE_FUNCTION_PARAM_NAME))
+                                                               {
+                                                                       char* name = ATTRIBUTE_VALUE(trav2);
+                                                                       ALLOC_INIT_ZVAL(param->paramName);
+                                                                       ZVAL_STRING(param->paramName,name,1);
+                                                               }
+                                                               else if(IS_ATTRIBUTE_TYPE(trav2,PHP_SOAPSERVER_SERVICE_FUNCTION_PARAM_TYPE))
+                                                               {
+                                                                       char* type = ATTRIBUTE_VALUE(trav2);
+                                                                       ALLOC_INIT_ZVAL(param->paramType);
+                                                                       ZVAL_STRING(param->paramType,type,1);
+                                                               }
+                                                               else if(IS_ATTRIBUTE_TYPE(trav2,PHP_SOAPSERVER_SERVICE_FUNCTION_PARAM_POSITION))
+                                                               {
+                                                                       char* val = ATTRIBUTE_VALUE(trav2);
+                                                                       ALLOC_INIT_ZVAL(param->paramName);
+                                                                       ZVAL_LONG(param->paramName,atoi(val));
+                                                               }
+                                                       }
+                                                       while(trav2 = trav2->next);
+                                                       zend_hash_add(par,Z_STRVAL_P(param->paramName),Z_STRLEN_P(param->paramName),param,sizeof(phpSoapServiceParam),NULL);
+                                               }
+                                       }
+                                       while(trav1 = trav1->next);
+                                       zend_hash_add(fn,Z_STRVAL_P(function->functionName),Z_STRLEN_P(function->functionName),function,sizeof(phpSoapServiceFunction),NULL);
+                               }
+
+                               //Classes
+                               if(IS_ELEMENT_TYPE(trav,PHP_SOAPSERVER_SERVICE_CLASS))
+                               {
+                                       xmlNodePtr att, func;
+                                       att = trav->properties;
+
+                                       if(fn == NULL)
+                                       {
+                                               fn = newService->functions = emalloc(sizeof(HashTable));
+                                               zend_hash_init(fn, 0, NULL, ZVAL_PTR_DTOR, 0);
+                                       }
+
+                               }
+
+                       }while(trav = trav->next);
+
+                       zend_hash_add(SOAP_SERVER_GLOBAL(services),Z_STRVAL_P(newService->serviceName),Z_STRLEN_P(newService->serviceName),newService,sizeof(phpSoapService),NULL);
+               }
+       }
+       while(services = services->next);
+*/
+       return TRUE;
+}
+
+int write_php_sdl()
+{
+       return TRUE;
+}
+
+sdlPtr load_wsdl(char *struri)
+{
+       xmlDocPtr wsdl;
+       xmlNodePtr root, definitions, types, binding, schema, service;
+       xmlNodePtr trav, trav2, trav3;
+       xmlAttrPtr targetNamespace;
+       sdlPtr tmpsdl;
+       TSRMLS_FETCH();
+
+       tmpsdl = malloc(sizeof(sdl));
+       memset(tmpsdl, 0, sizeof(sdl));
+
+       tmpsdl->source = strdup(struri);
+
+       wsdl = xmlParseFile(struri);
+       xmlCleanupParser();
+
+       if(!wsdl)
+               php_error(E_ERROR, "Error parsing wsdl file");
+
+       tmpsdl->doc = wsdl;
+       root = wsdl->children;
+       definitions = get_node(root, "definitions");
+       if(!definitions)
+               php_error(E_ERROR, "Error parsing wsdl file");
+
+       targetNamespace = get_attribute(definitions->properties, "targetNamespace");
+       if(targetNamespace)
+       {
+               tmpsdl->target_ns = strdup(targetNamespace->children->content);
+       }
+
+       types = get_node(definitions->children, "types");
+       if(types)
+       {
+               trav = types->children;
+               FOREACHNODE(trav, "schema", schema)
+               {
+                       load_schema(&tmpsdl, schema);
+               }
+               ENDFOREACH(trav);
+       }
+
+       service = get_node(definitions->children, "service");
+       if(service != NULL)
+       {
+               xmlAttrPtr name;
+               xmlNodePtr trav, port;
+
+               name = get_attribute(service->properties, "name");
+               if(name == NULL)
+                       php_error(E_ERROR, "Error parsing wsdl (\"No name associated with service\")");
+
+               trav = service->children;
+               FOREACHNODE(trav, "port", port)
+               {
+                       xmlAttrPtr name, binding, location;
+                       xmlNodePtr address;
+
+                       name = get_attribute(port->properties, "name");
+                       if(name == NULL)
+                               php_error(E_ERROR, "Error parsing wsdl (\"No name associated with port\")");
+
+                       binding = get_attribute(port->properties, "binding");
+                       if(binding == NULL)
+                               php_error(E_ERROR, "Error parsing wsdl (\"No binding associated with port\")");
+
+                       //TODO: validate this is "soap" namespace
+                       address = get_node(port->children, "address");
+                       if(address == NULL)
+                               php_error(E_ERROR, "Error parsing wsdl (\"No soap:address associated with port\")");
+
+                       location = get_attribute(address->properties, "location");
+                       if(location == NULL)
+                               php_error(E_ERROR, "Error parsing wsdl (\"No location associated with soap:address\")");
+
+                       tmpsdl->location = strdup(location->children->content);
+               }
+               ENDFOREACH(trav);
+
+       }
+       else
+               php_error(E_ERROR, "Error parsing wsdl (\"Couldn't bind to service\")");
+
+       trav = definitions->children;
+       FOREACHNODE(trav, "binding", binding)
+       {
+               xmlAttrPtr name, type;
+               xmlNodePtr portType, operation;
+               char *ns, *ctype;
+
+               name = get_attribute(binding->properties, "name");
+               if(name == NULL)
+                       php_error(E_ERROR, "Error parsing wsdl (Missing \"name\" attribute for \"binding\")");
+
+               type = get_attribute(binding->properties, "type");
+               if(type == NULL)
+                       php_error(E_ERROR, "Error parsing wsdl (Missing \"type\" attribute for \"binding\")");
+
+               parse_namespace(type->children->content, &ctype, &ns);
+               portType = get_node_with_attribute(definitions->children, "portType", "name", ctype);
+               if(portType == NULL)
+                       php_error(E_ERROR, "Error parsing wsdl (Missing \"portType\" with name \"%s\")", name->children->content);
+               if(ctype) efree(ctype);
+               if(ns) efree(ns);
+
+               trav2 = binding->children;
+               FOREACHNODE(trav2, "operation", operation)
+               {
+                       sdlFunctionPtr function;
+                       xmlNodePtr input, output, fault, portTypeOperation, msgInput, msgOutput, soapOperation;
+                       xmlAttrPtr op_name, paramOrder;
+
+                       op_name = get_attribute(operation->properties, "name");
+                       if(op_name == NULL)
+                               php_error(E_ERROR, "Error parsing wsdl (Missing \"name\" attribute for \"operation\")");
+
+                       portTypeOperation = get_node_with_attribute(portType->children, "operation", "name", op_name->children->content);
+                       if(portTypeOperation == NULL)
+                               php_error(E_ERROR, "Error parsing wsdl (Missing \"portType/operation\" with name \"%s\")", op_name->children->content);
+
+                       if(tmpsdl->functions == NULL)
+                       {
+                               tmpsdl->functions = malloc(sizeof(HashTable));
+                               zend_hash_init(tmpsdl->functions, 0, NULL, delete_function, 1);
+                       }
+
+                       function = malloc(sizeof(sdlFunction));
+                       function->functionName = strdup(op_name->children->content);
+                       function->requestParameters = NULL;
+                       function->responseParameters = NULL;
+                       function->responseName = NULL;
+                       function->soapAction = NULL;
+
+                       soapOperation = get_node(operation->children, "operation");
+                       if(soapOperation)
+                       {
+                               xmlAttrPtr action = get_attribute(soapOperation->properties, "soapAction");
+                               if(action)
+                                       function->soapAction = strdup(action->children->content);
+                       }
+
+                       input = get_node(portTypeOperation->children, "input");
+                       if(input != NULL)
+                       {
+                               xmlAttrPtr message;
+                               xmlNodePtr part;
+                               char *ns, *ctype;
+
+                               message = get_attribute(input->properties, "message");
+                               if(message == NULL)
+                                       php_error(E_ERROR, "Error parsing wsdl (Missing name for \"input\" of \"%s\")", op_name->children->content);
+
+                               function->requestName = strdup(function->functionName);
+                               function->requestParameters = malloc(sizeof(HashTable));
+                               zend_hash_init(function->requestParameters, 0, NULL, delete_paramater, 1);
+
+                               parse_namespace(message->children->content, &ctype, &ns);
+                               msgInput = get_node_with_attribute(definitions->children, "message", "name", ctype);
+                               if(msgInput == NULL)
+                                       php_error(E_ERROR, "Error parsing wsdl (Missing \"message\" with name \"%s\")", message->children->content);
+                               if(ctype) efree(ctype);
+                               if(ns) efree(ns);
+
+                               trav3 = msgInput->children;
+                               FOREACHNODE(trav3, "part", part)
+                               {
+                                       xmlAttrPtr element, type, name;
+                                       sdlParamPtr param;
+
+                                       param = malloc(sizeof(sdlParam));
+                                       param->order = 0;
+
+                                       name = get_attribute(part->properties, "name");
+                                       if(name == NULL)
+                                               php_error(E_ERROR, "Error parsing wsdl (No name associated with part \"%s\")", msgInput->name);
+
+                                       param->paramName = strdup(name->children->content);
+
+                                       element = get_attribute(part->properties, "element");
+                                       if(element != NULL)
+                                               param->encode = get_encoder_from_prefix(tmpsdl, part, element->children->content);
+
+                                       type = get_attribute(part->properties, "type");
+                                       if(type != NULL)
+                                               param->encode = get_encoder_from_prefix(tmpsdl, part, type->children->content);
+
+                                       zend_hash_next_index_insert(function->requestParameters, &param, sizeof(sdlParamPtr), NULL);
+                               }
+                               ENDFOREACH(trav3);
+                       }
+
+                       paramOrder = get_attribute(portTypeOperation->properties, "parameterOrder");
+                       if(paramOrder)
+                       {
+
+                       }
+
+                       output = get_node(portTypeOperation->children, "output");
+                       if(output != NULL)
+                       {
+                               xmlAttrPtr message;
+                               xmlNodePtr part;
+                               char *ns, *ctype;
+
+
+                               function->responseName = malloc(strlen(function->functionName) + strlen("Response") + 1);
+                               sprintf(function->responseName, "%sResponse\0", function->functionName);
+                               function->responseParameters = malloc(sizeof(HashTable));
+                               zend_hash_init(function->responseParameters, 0, NULL, delete_paramater, 1);
+
+                               message = get_attribute(output->properties, "message");
+                               if(message == NULL)
+                                       php_error(E_ERROR, "Error parsing wsdl (Missing name for \"output\" of \"%s\")", op_name->children->content);
+
+                               parse_namespace(message->children->content, &ctype, &ns);
+                               msgOutput = get_node_with_attribute(definitions->children, "message", "name", ctype);
+                               if(msgOutput == NULL)
+                                       php_error(E_ERROR, "Error parsing wsdl (Missing \"message\" with name \"%s\")", message->children->content);
+                               if(ctype) efree(ctype);
+                               if(ns) efree(ns);
+
+                               trav3 = msgOutput->children;
+                               FOREACHNODE(trav3, "part", part)
+                               {
+                                       sdlParamPtr param;
+                                       xmlAttrPtr element, type, name;
+
+                                       param = malloc(sizeof(sdlParam));
+                                       param->order = 0;
+
+                                       name = get_attribute(part->properties, "name");
+                                       if(name == NULL)
+                                               php_error(E_ERROR, "Error parsing wsdl (No name associated with part \"%s\")", msgOutput->name);
+
+                                       param->paramName = strdup(name->children->content);
+
+                                       element = get_attribute(part->properties, "element");
+                                       if(element)
+                                               param->encode = get_encoder_from_prefix(tmpsdl, part, element->children->content);
+
+                                       type = get_attribute(part->properties, "type");
+                                       if(type)
+                                               param->encode = get_encoder_from_prefix(tmpsdl, part, type->children->content);
+
+                                       zend_hash_next_index_insert(function->responseParameters, &param, sizeof(sdlParamPtr), NULL);
+                               }
+                               ENDFOREACH(trav3);
+                       }
+
+                       fault = get_node(operation->children, "fault");
+                       if(fault != NULL)
+                       {
+                       }
+
+                       zend_hash_add(tmpsdl->functions, php_strtolower(function->functionName, strlen(function->functionName)), strlen(function->functionName), &function, sizeof(sdlFunctionPtr), NULL);
+               }
+               ENDFOREACH(trav2);
+       }
+       ENDFOREACH(trav);
+
+       return tmpsdl;
+}
+
+int write_wsdl()
+{
+       return TRUE;
+}
+
+int write_ms_sdl()
+{
+       return TRUE;
+}
+
+int load_ms_sdl(char *struri,int force_load)
+{
+/* Commenting this out. Does anyone need it?
+
+       if(get_sdl(struri) == NULL || force_load)
+       {
+               SOAP_TLS_VARS();
+               xmlDocPtr sdl = xmlParseFile(struri);
+               xmlNodePtr schema,trav,trav2,req,res,paramOrd,reqRes,address,serviceAdd,service,soap,serviceDesc,root = sdl->children;
+               xmlAttrPtr tmpattr,uri;
+               char *add,*functionName,*soapAction,*request,*response,*parameterOrder,*value,*namespace;
+               SDLPtr sdlPtr;
+               SoapFunctionPtr tmpFunction;
+               zval *tempZval;
+               serviceDesc = get_node(root,"serviceDescription");
+               soap = get_node(serviceDesc->children,"soap");
+               trav = soap->children;
+               sdlPtr = emalloc(sizeof(SDL));
+
+               ALLOC_INIT_ZVAL(sdlPtr->sdlUri);
+               ZVAL_STRING(sdlPtr->sdlUri,struri,1);
+
+               FOREACHNODE(trav,"service",service)
+               {
+                       sdlPtr->soapFunctions = emalloc(sizeof(HashTable));
+                       sdlPtr->addresses = emalloc(sizeof(HashTable));
+                   zend_hash_init(sdlPtr->soapFunctions, 0, NULL, delete_function, 0);
+                   zend_hash_init(sdlPtr->addresses, 0, NULL, ZVAL_PTR_DTOR, 0);
+
+                       serviceAdd = get_node(service->children,"addresses");
+                       trav2 = serviceAdd->children;
+                       ALLOC_INIT_ZVAL(tempZval);
+                       FOREACHNODE(trav2,"address",address)
+                       {
+                               uri = get_attribute(address->properties,"uri");
+                               add = uri->children->content;
+                               ZVAL_STRING(tempZval,add,1);
+                               zend_hash_next_index_insert(sdlPtr->addresses,tempZval,sizeof(zval),NULL);
+                       }
+                       ENDFOREACH(trav2);
+                       trav2 = service->children;
+                       FOREACHNODE(trav2,"requestResponse",reqRes)
+                       {
+                               tmpFunction = emalloc(sizeof(SoapFunction));
+
+                               tmpattr = get_attribute(reqRes->properties,"name");
+                               functionName = tmpattr->children->content;
+                               ALLOC_INIT_ZVAL(tmpFunction->functionName);
+                               ZVAL_STRING(tmpFunction->functionName,functionName,1);
+
+                               tmpattr = get_attribute(reqRes->properties,"soapAction");
+                               soapAction = tmpattr->children->content;
+                               ALLOC_INIT_ZVAL(tmpFunction->soapAction);
+                               ZVAL_STRING(tmpFunction->soapAction,soapAction,1);
+
+                               //Request
+                               req = get_node(reqRes->children,"request");
+                               tmpattr = get_attribute(req->properties,"ref");
+                               if(tmpattr != NULL)
+                               {
+                                       request = tmpattr->children->content;
+                                       parse_namespace(request,&value,&namespace);
+                                       ALLOC_INIT_ZVAL(tmpFunction->requestName);
+                                       ZVAL_STRING(tmpFunction->requestName,value,1);
+                                       tmpFunction->requestParameters = emalloc(sizeof(HashTable));
+                                       zend_hash_init(tmpFunction->requestParameters, 0, NULL, delete_paramater, 0);
+                                       efree(value);
+                                       efree(namespace);
+                               }
+
+                               //Response
+                               res = get_node(reqRes->children,"response");
+                               tmpattr = get_attribute(res->properties,"ref");
+                               if(tmpattr != NULL)
+                               {
+                                       response = tmpattr->children->content;
+                                       parse_namespace(response,&value,&namespace);
+                                       ALLOC_INIT_ZVAL(tmpFunction->responseName);
+                                       ZVAL_STRING(tmpFunction->responseName,value,1);
+                                       tmpFunction->responseParameters = emalloc(sizeof(HashTable));
+                                       zend_hash_init(tmpFunction->responseParameters, 0, NULL, delete_paramater, 0);
+                                       efree(value);
+                                       efree(namespace);
+                               }
+
+                               //Parameters
+                               paramOrd = get_node(reqRes->children,"parameterorder");
+                               if(paramOrd != NULL)
+                               {
+                                       zval *space,*array,**strval;
+                                       int count,i;
+                                       ALLOC_INIT_ZVAL(space);
+                                       ZVAL_STRING(space," ",0);
+                                       parameterOrder = paramOrd->children->content;
+                                       ZVAL_STRING(tempZval,parameterOrder,1);
+                                       ALLOC_INIT_ZVAL(array);
+                                       array_init(array);
+
+                                       //Split on space
+                                       php_explode(space, tempZval, array, -1);
+                                       zend_hash_internal_pointer_reset(array->value.ht);
+                                       count = zend_hash_num_elements(array->value.ht);
+
+                                       for(i = 0;i < count;i++)
+                                       {
+                                               SoapParamPtr param;
+                                               param = emalloc(sizeof(SoapParam));
+                                               param->order = i+1;
+                                               param->type = NULL;
+                                               zend_hash_get_current_data(array->value.ht,(void **)&strval);
+                                               ALLOC_INIT_ZVAL(param->paramName);
+                                               ZVAL_STRING(param->paramName,Z_STRVAL_PP(strval),1);
+                                               zend_hash_next_index_insert(tmpFunction->requestParameters,param,sizeof(SoapParam),NULL);
+                                               zend_hash_move_forward(array->value.ht);
+                                       }
+                               }
+                               zend_hash_add(sdlPtr->soapFunctions,(char *)php_strtolower(functionName,strlen(functionName)),strlen(functionName),tmpFunction,sizeof(SoapFunction),NULL);
+                       }
+                       ENDFOREACH(trav2);
+               }
+               ENDFOREACH(trav);
+
+               trav = serviceDesc->children;
+               FOREACHNODE(trav,"schema",schema)
+               {
+                       load_schema(&sdlPtr, schema);
+               }
+               ENDFOREACH(trav);
+               sdlPtr->have_sdl = 1;
+               map_types_to_functions(sdlPtr);
+               zend_hash_add(SOAP_GLOBAL(SDLs),struri,strlen(struri),sdlPtr,sizeof(SDL),NULL);
+       }*/
+       return FALSE;
+}
+
+void delete_type(void *data)
+{
+       sdlTypePtr type = *((sdlTypePtr*)data);
+       if(type->name)
+               free(type->name);
+       if(type->namens)
+               free(type->namens);
+       if(type->elements)
+       {
+               zend_hash_destroy(type->elements);
+               free(type->elements);
+       }
+       if(type->attributes)
+       {
+               zend_hash_destroy(type->attributes);
+               free(type->attributes);
+       }
+       if(type->restrictions)
+       {
+               delete_restriction_var_int(&type->restrictions->minExclusive);
+               delete_restriction_var_int(&type->restrictions->minInclusive);
+               delete_restriction_var_int(&type->restrictions->maxExclusive);
+               delete_restriction_var_int(&type->restrictions->maxInclusive);
+               delete_restriction_var_int(&type->restrictions->totalDigits);
+               delete_restriction_var_int(&type->restrictions->fractionDigits);
+               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);
+               zend_hash_destroy(type->restrictions->enumeration);
+               free(type->restrictions->enumeration);
+               free(type->restrictions);
+       }
+       free(type);
+}
+
+void delete_attribute(void *attribute)
+{
+       sdlAttributePtr attr = *((sdlAttributePtr*)attribute);
+
+       if(attr->def)
+               free(attr->def);
+       if(attr->fixed)
+               free(attr->fixed);
+       if(attr->form)
+               free(attr->form);
+       if(attr->id)
+               free(attr->id);
+       if(attr->name)
+               free(attr->name);
+       if(attr->ref)
+               free(attr->ref);
+       if(attr->type)
+               free(attr->type);
+       if(attr->use)
+               free(attr->use);
+       if(attr->extraAttributes)
+       {
+               zend_hash_destroy(attr->extraAttributes);
+               free(attr->extraAttributes);
+       }
+}
diff --git a/ext/soap/php_sdl.h b/ext/soap/php_sdl.h
new file mode 100644 (file)
index 0000000..66a2520
--- /dev/null
@@ -0,0 +1,112 @@
+#ifndef PHP_SDL_H
+#define PHP_SDL_H
+
+#define XSD_WHITESPACE_COLLAPSE 1
+#define XSD_WHITESPACE_PRESERVE 1
+#define XSD_WHITESPACE_REPLACE 1
+
+struct _sdl
+{
+       xmlDocPtr doc;
+       HashTable *functions;   //array of SoapFunctionsPtr
+       HashTable *types;               //array of sdlTypesPtr
+       HashTable *encoders;    //array of encodePtr
+       char *location;
+       char *target_ns;
+       char *source;
+};
+
+struct _sdlRestrictionInt
+{
+       int value;
+       char fixed;
+       char *id;
+};
+
+struct _sdlRestrictionChar
+{
+       char *value;
+       char fixed;
+       char *id;
+};
+
+struct _sdlRestrictions
+{
+       HashTable *enumeration;                         //array of sdlRestrictionCharPtr
+       sdlRestrictionIntPtr minExclusive;
+       sdlRestrictionIntPtr minInclusive;
+       sdlRestrictionIntPtr maxExclusive;
+       sdlRestrictionIntPtr maxInclusive;
+       sdlRestrictionIntPtr totalDigits;
+       sdlRestrictionIntPtr fractionDigits;
+       sdlRestrictionIntPtr length;
+       sdlRestrictionIntPtr minLength;
+       sdlRestrictionIntPtr maxLength;
+       sdlRestrictionCharPtr whiteSpace;
+       sdlRestrictionCharPtr pattern;
+};
+
+struct _sdlType
+{
+       char *name;
+       char *namens;
+       int nullable;
+       int min_occurs;
+       int max_occurs;
+       HashTable *elements;                            //array of sdlTypePtr
+       HashTable *attributes;                          //array of sdlAttributePtr
+       sdlRestrictionsPtr restrictions;
+       encodePtr encode;
+};
+
+struct _sdlParam
+{
+       int order;
+       encodePtr encode;
+       char *paramName;
+};
+
+struct _sdlFunction
+{
+       int enabled;
+       char *functionName;
+       char *requestName;
+       char *responseName;
+       HashTable *requestParameters;           //array of sdlParamPtr
+       HashTable *responseParameters;          //array of sdlParamPtr (this should only be one)
+       char *soapAction;
+};
+
+struct _sdlAttribute
+{
+       char *def;
+       char *fixed;
+       char *form;
+       char *id;
+       char *name;
+       char *ref;
+       char *type;
+       char *use;
+       HashTable *extraAttributes;
+};
+
+sdlPtr get_sdl(char *uri);
+sdlPtr load_wsdl(char *struri);
+int load_sdl(char *struri, int force_load);
+int load_ms_sdl(char *struri, int force_load);
+
+encodePtr get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr data, char *type);
+encodePtr get_encoder(sdlPtr sdl, char *ns, char *type);
+encodePtr get_encoder_ex(sdlPtr sdl, char *nscat);
+encodePtr get_create_encoder(sdlPtr sdl, sdlTypePtr cur_type, char *ns, char *type);
+encodePtr create_encoder(sdlPtr sdl, sdlTypePtr cur_type, char *ns, char *type);
+
+xmlNodePtr sdl_guess_convert_xml(encodeType enc, zval* data);
+
+xmlNodePtr sdl_to_xml_array(sdlTypePtr type, zval *data);
+xmlNodePtr sdl_to_xml_object(sdlTypePtr type, zval *data);
+
+void delete_type(void *type);
+void delete_attribute(void *attribute);
+#endif
+
diff --git a/ext/soap/php_soap.dsp b/ext/soap/php_soap.dsp
new file mode 100644 (file)
index 0000000..7ee1277
--- /dev/null
@@ -0,0 +1,156 @@
+# Microsoft Developer Studio Project File - Name="php_soap" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
+\r
+CFG=php_soap - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "php_soap.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "php_soap.mak" CFG="php_soap - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "php_soap - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE "php_soap - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "php_soap - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PHP_SOAP_EXPORTS" /YX /FD /c\r
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\php4" /I "..\..\..\php4\Zend" /I "..\..\..\php4\TSRM" /I "..\..\..\php4\main" /I "..\..\..\libxml2-2.4.12\include" /I "..\..\bind" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PHP_SOAP_EXPORTSWS" /D "PHP_SOAP_EXPORTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "ZTS" /D ZEND_DEBUG=0 /D "COMPILE_DL_SOAP" /YX /FD /c\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib libxml2.lib wsock32.lib resolv.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS\php_soap.dll" /libpath:"..\..\..\php4\Release_TS" /libpath:"..\..\..\libxml2-2.4.12\lib"\r
+\r
+!ELSEIF  "$(CFG)" == "php_soap - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PHP_SOAP_EXPORTS" /YX /FD /GZ /c\r
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\php4" /I "..\..\..\php4\Zend" /I "..\..\..\php4\TSRM" /I "..\..\..\php4\main" /I "..\..\..\libxml2-2.4.12\include" /I "..\..\..\bind" /D "WS" /D "_MBCS" /D "_USRDLL" /D "PHP_SOAP_EXPORTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "ZTS" /D ZEND_DEBUG=1 /D "COMPILE_DL_SOAP" /FR"Release_TS/" /Fp"Release_TS/gd.pch" /YX /Fo"Release_TS/" /Fd"Release_TS/" /FD /c\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts_debug.lib libxml2.lib wsock32.lib resolv.lib /nologo /dll /debug /machine:I386 /out:"..\..\Debug_TS\php_soap.dll" /implib:"Release_TS/php_gd.lib" /pdbtype:sept /libpath:"..\..\..\php4\Debug_TS" /libpath:"..\..\..\libxml2-2.4.12\lib"\r
+# SUBTRACT LINK32 /pdb:none /incremental:no\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "php_soap - Win32 Release"\r
+# Name "php_soap - Win32 Debug"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=.\php_encoding.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\php_http.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\php_packet_soap.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\php_schema.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\php_sdl.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\php_xml.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\soap.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# Begin Source File\r
+\r
+SOURCE=.\php_encoding.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\php_http.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\php_packet_soap.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\php_schema.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\php_sdl.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\php_soap.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\php_xml.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/ext/soap/php_soap.h b/ext/soap/php_soap.h
new file mode 100644 (file)
index 0000000..98c9e57
--- /dev/null
@@ -0,0 +1,375 @@
+#ifndef PHP_SOAP_H
+#define PHP_SOAP_H
+
+#include "php.h"
+#include "php_globals.h"
+#include "ext/standard/info.h"
+#include "ext/standard/php_standard.h"
+#include "ext/session/php_session.h"
+#include "ext/standard/php_smart_str.h"
+#include "php_ini.h"
+#include "SAPI.h"
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+
+#ifdef HAVE_PHP_DOMXML
+# include "ext/domxml/php_domxml.h"
+#endif
+
+// PHP_STREAMS were introduced php-4.2.0.. i think
+//  Make this part of configure
+#ifdef STREAMS_DC
+# define PHP_STREAMS
+#endif
+
+#ifdef PHP_WIN32
+# ifdef PHP_STREAMS
+#  define SOAP_STREAM php_stream *
+# else
+#  define SOAP_STREAM SOCKET
+# endif
+#else
+# ifdef PHP_STREAMS
+#  define SOAP_STREAM php_stream *
+# else
+#  define SOCKET unsigned int
+#  define SOAP_STREAM SOCKET
+# endif
+# define TRUE 1
+# define FALSE 0
+# define stricmp strcasecmp
+#endif
+
+typedef struct _encodeType encodeType, *encodeTypePtr;
+typedef struct _encode encode, *encodePtr;
+
+typedef struct _sdl sdl, *sdlPtr;
+typedef struct _sdlRestrictionInt sdlRestrictionInt, *sdlRestrictionIntPtr;
+typedef struct _sdlRestrictionChar sdlRestrictionChar, *sdlRestrictionCharPtr;
+typedef struct _sdlRestrictions sdlRestrictions, *sdlRestrictionsPtr;
+typedef struct _sdlType sdlType, *sdlTypePtr;
+typedef struct _sdlParam sdlParam, *sdlParamPtr;
+typedef struct _sdlFunction sdlFunction, *sdlFunctionPtr;
+typedef struct _sdlAttribute sdlAttribute, *sdlAttributePtr;
+
+typedef struct _soapMapping soapMapping, *soapMappingPtr;
+typedef struct _soapService soapService, *soapServicePtr;
+
+#include "php_xml.h"
+#include "php_encoding.h"
+#include "php_sdl.h"
+#include "php_schema.h"
+#include "php_http.h"
+#include "php_packet_soap.h"
+
+extern int le_sdl;
+extern int le_http_socket;
+extern int le_url;
+extern int le_service;
+
+struct _soapMapping
+{
+       char *ns;
+       char *ctype;
+       int type;
+
+       struct _map_functions
+       {
+               zval *to_xml_before;
+               zval *to_xml;
+               zval *to_xml_after;
+               zval *to_zval_before;
+               zval *to_zval;
+               zval *to_zval_after;
+       } map_functions;
+
+       struct _map_class
+       {
+               int type;
+               zend_class_entry *ce;
+       } map_class;
+};
+
+struct _soapService
+{
+       sdlPtr sdl;
+
+       struct _soap_functions
+       {
+               HashTable *ft;
+               int functions_all;
+       } soap_functions;
+
+       struct _soap_class
+       {
+               zend_class_entry *ce;
+               zval **argv;
+               int argc;
+               int persistance;
+       } soap_class;
+
+       HashTable *mapping;
+       int type;
+       int enabled;
+       char *uri;
+};
+
+#define SOAP_CLASS 1
+#define SOAP_FUNCTIONS 2
+#define SOAP_FUNCTIONS_ALL 999
+
+#define SOAP_MAP_FUNCTION 1
+#define SOAP_MAP_CLASS 2
+
+#define SOAP_PERSISTENCE_SESSION 1
+#define SOAP_PERSISTENCE_REQUEST 2
+
+ZEND_BEGIN_MODULE_GLOBALS(soap)
+       HashTable *defEncNs;
+       HashTable *defEncPrefix;
+       HashTable *defEnc;
+       HashTable *defEncIndex;
+       HashTable *sdls;
+       HashTable *services;
+       HashTable *overrides;
+       int cur_uniq_ns;
+ZEND_END_MODULE_GLOBALS(soap)
+
+ZEND_EXTERN_MODULE_GLOBALS(soap);
+
+#ifdef ZTS
+# define SOAP_GLOBAL(v) TSRMG(soap_globals_id, zend_soap_globals *, v)
+#else
+# define SOAP_GLOBAL(v) (soap_globals.v)
+#endif
+
+#define PHP_SOAP_SERVER_CLASSNAME "soapserver"
+#define PHP_SOAP_CLASSNAME "soapobject"
+#define PHP_SOAP_VAR_CLASSNAME "soapvar"
+#define PHP_SOAP_FAULT_CLASSNAME "soapfault"
+#define PHP_SOAP_PARAM_CLASSNAME "soapparam"
+
+
+extern zend_module_entry soap_module_entry;
+#define  soap_module_ptr & soap_module_entry
+
+PHP_MINIT_FUNCTION(soap);
+PHP_MSHUTDOWN_FUNCTION(soap);
+PHP_MINFO_FUNCTION(soap);
+
+//Registry Functions
+//TODO: this!
+PHP_FUNCTION(load_sdl);
+PHP_FUNCTION(unload_sdl);
+PHP_FUNCTION(unload_all_sdls);
+PHP_FUNCTION(get_available_sdls);
+PHP_FUNCTION(get_available_functions);
+PHP_FUNCTION(get_function_parameters);
+PHP_FUNCTION(soap_encode_to_xml);
+PHP_FUNCTION(soap_encode_to_zval);
+
+
+//Server Functions
+PHP_FUNCTION(soapserver);
+PHP_FUNCTION(setclass);
+PHP_FUNCTION(addfunction);
+PHP_FUNCTION(getfunctions);
+PHP_FUNCTION(handle);
+PHP_FUNCTION(setpersistence);
+PHP_FUNCTION(bind);
+#ifdef HAVE_PHP_DOMXML
+PHP_FUNCTION(map);
+#endif
+
+//Client Functions
+PHP_FUNCTION(soapobject);
+PHP_FUNCTION(__isfault);
+PHP_FUNCTION(__getfault);
+PHP_FUNCTION(__call);
+PHP_FUNCTION(__parse);
+#ifdef PHP_DEBUG
+PHP_FUNCTION(__getfunctions);
+PHP_FUNCTION(__gettypes);
+PHP_FUNCTION(__getlastresponse);
+PHP_FUNCTION(__getlastrequest);
+#endif
+
+//SoapVar Functions
+PHP_FUNCTION(soapvar);
+
+//SoapFault Functions
+PHP_FUNCTION(soapfault);
+
+//SoapParam Functions
+PHP_FUNCTION(soapparam);
+
+
+#define DECLARE_TRACE(file) \
+       FILE *trace_fp; \
+       char *trace_file = file;
+
+#define TRACE(place) \
+       trace_fp = fopen(trace_file, "a+"); \
+       fwrite(place, strlen(place), 1, trace_fp); \
+       fclose(trace_fp);
+
+extern zend_class_entry soap_var_class_entry;
+
+PS_SERIALIZER_FUNCS(soap);
+
+void clear_soap_fault(zval *obj);
+void set_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail);
+void add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail);
+
+sdlParamPtr get_param(sdlFunctionPtr function, char *param_name, int index, int);
+sdlFunctionPtr get_function(sdlPtr sdl, char *function_name);
+void delete_sdl(void *handle);
+void delete_function(void *function);
+void delete_paramater(void *paramater);
+void delete_service(void *service);
+void delete_http_socket(void *handle);
+void delete_url(void *handle);
+void delete_mapping(void *data);
+
+void soap_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
+zval soap_get_property_handler(zend_property_reference *property_reference);
+int soap_set_property_handler(zend_property_reference *property_reference, zval *value);
+void soap_destructor(void *jobject);
+
+void deseralize_function_call(sdlPtr sdl, xmlDocPtr request, zval *function_name, int *num_params, zval **parameters[]);
+xmlDocPtr seralize_response_call(sdlFunctionPtr function, char *function_name,char *uri,zval *ret);
+xmlDocPtr seralize_function_call(sdlFunctionPtr function, char *urn, char *function_name, zval **arguments, int arg_count);
+xmlNodePtr seralize_parameter(sdlParamPtr param,zval *param_val,int index,char *name);
+xmlNodePtr seralize_zval(zval *val, sdlParamPtr param, char *paramName);
+zval *desearlize_zval(sdlPtr sdl, xmlNodePtr data, sdlParamPtr param);
+
+void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args);
+int my_call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, int param_count, zval *params[] TSRMLS_DC);
+
+#define phpext_soap_ptr soap_module_ptr
+
+#define HTTP_RAW_POST_DATA "HTTP_RAW_POST_DATA"
+
+#define SOAP_SERVER_BEGIN_CODE() \
+       zend_error_cb = soap_error_handler
+
+#define SOAP_SERVER_END_CODE() \
+       zend_error_cb = old_handler
+
+
+#define FOREACHATTRNODE(n,c,i) \
+       do \
+       { \
+               if(n == NULL) \
+                       break; \
+               if(c) \
+                       i = get_attribute(n,c); \
+               else \
+                       i = n; \
+               if(i != NULL) \
+               { \
+                       n = i;
+
+#define FOREACHNODE(n,c,i) \
+       do \
+       { \
+               if(n == NULL) \
+                       break; \
+               if(c) \
+                       i = get_node(n,c); \
+               else \
+                       i = n; \
+               if(i != NULL) \
+               { \
+                       n = i;
+
+#define ENDFOREACH(n) \
+               } \
+       } while(n = n->next);
+
+#define ZERO_PARAM() \
+       if(ZEND_NUM_ARGS() != 0) \
+               WRONG_PARAM_COUNT;
+
+#define ONE_PARAM(p) \
+       if(ZEND_NUM_ARGS() != 1 || getParameters(ht, 1, &p) == FAILURE) \
+               WRONG_PARAM_COUNT;
+
+#define TWO_PARAM(p,p1) \
+       if(ZEND_NUM_ARGS() != 1 || getParameters(ht, 2, &p, &p1) == FAILURE) \
+               WRONG_PARAM_COUNT;
+
+#define THREE_PARAM(p,p1,p2) \
+       if(ZEND_NUM_ARGS() != 1 || getParameters(ht, 3, &p, &p1, &p2) == FAILURE) \
+               WRONG_PARAM_COUNT;
+
+#define FETCH_THIS_SDL(ss) \
+       { \
+               zval *__thisObj,**__tmp; \
+               GET_THIS_OBJECT(__thisObj) \
+               if(FIND_SDL_PROPERTY(__thisObj,__tmp) != FAILURE) \
+               { \
+                       FETCH_SDL_RES(ss,__tmp); \
+               } \
+               else \
+                       ss = NULL; \
+       }
+
+#define FIND_SDL_PROPERTY(ss,tmp) zend_hash_find(ss->value.obj.properties, "sdl", sizeof("sdl"), (void **)&tmp)
+#define FETCH_SDL_RES(ss,tmp) ss = (sdlPtr) zend_fetch_resource(tmp TSRMLS_CC, -1, "sdl", NULL, 1, le_sdl)
+
+#define FETCH_THIS_SERVICE(ss) \
+       { \
+               zval *__thisObj,**__tmp; \
+               GET_THIS_OBJECT(__thisObj) \
+               if(FIND_SERVICE_PROPERTY(__thisObj,__tmp) != FAILURE) \
+               { \
+                       FETCH_SERVICE_RES(ss,__tmp); \
+               } \
+               else \
+                       ss = NULL; \
+       }
+
+#define FIND_SERVICE_PROPERTY(ss,tmp) zend_hash_find(ss->value.obj.properties, "service", sizeof("service"), (void **)&tmp)
+#define FETCH_SERVICE_RES(ss,tmp) ss = (soapServicePtr) zend_fetch_resource(tmp TSRMLS_CC, -1, "service", NULL, 1, le_service)
+
+#define FETCH_THIS_URL(ss) \
+       { \
+               zval *__thisObj,**__tmp; \
+               GET_THIS_OBJECT(__thisObj) \
+               if(FIND_URL_PROPERTY(__thisObj,__tmp) != FAILURE) \
+               { \
+                       FETCH_URL_RES(ss,__tmp); \
+               } \
+               else \
+                       ss = NULL; \
+       }
+
+#define FIND_URL_PROPERTY(ss,tmp) zend_hash_find(ss->value.obj.properties, "httpurl", sizeof("httpurl"), (void **)&tmp)
+#define FETCH_URL_RES(ss,tmp) ss = (php_url *) zend_fetch_resource(tmp TSRMLS_CC, -1, "httpurl", NULL, 1, le_url)
+
+#define FETCH_THIS_SOCKET(ss) \
+       { \
+               zval *__thisObj,**__tmp; \
+               GET_THIS_OBJECT(__thisObj) \
+               if(FIND_SOCKET_PROPERTY(__thisObj,__tmp) != FAILURE) \
+               { \
+                       FETCH_SOCKET_RES(ss,__tmp); \
+               } \
+               else \
+                       ss = NULL; \
+       }
+
+#define FIND_SOCKET_PROPERTY(ss,tmp) zend_hash_find(ss->value.obj.properties, "httpsocket", sizeof("httpsocket"), (void **)&tmp)
+#define FETCH_SOCKET_RES(ss,tmp) ss = (SOAP_STREAM)zend_fetch_resource(tmp TSRMLS_CC, -1, "httpsocket", NULL, 1, le_http_socket)
+
+#define GET_THIS_OBJECT(o) \
+       o = getThis(); \
+       if (!o) \
+       { \
+               php_error(E_WARNING, "Cannot Get Class Info"); \
+               return; \
+       }
+
+
+#endif
diff --git a/ext/soap/php_xml.c b/ext/soap/php_xml.c
new file mode 100644 (file)
index 0000000..707d073
--- /dev/null
@@ -0,0 +1,214 @@
+#include "php_soap.h"
+
+xmlNsPtr attr_find_ns(xmlAttrPtr node)
+{
+       if(node->ns)
+               return node->ns;
+       else if(node->parent->ns)
+               return node->parent->ns;
+       else
+               return xmlSearchNs(node->doc, node->parent, NULL);
+}
+
+xmlNsPtr node_find_ns(xmlNodePtr node)
+{
+       if(node->ns)
+               return node->ns;
+       else
+               return xmlSearchNs(node->doc, node, NULL);
+}
+
+int attr_is_equal_ex(xmlAttrPtr node, char *name, char *ns)
+{
+       if(!strcmp(node->name, name))
+       {
+               if(ns)
+               {
+                       xmlNsPtr nsPtr;
+                       if(node->ns)
+                               nsPtr = node->ns;
+                       else if(node->parent->ns)
+                               nsPtr = node->parent->ns;
+                       else
+                               nsPtr = xmlSearchNs(node->doc, node->parent, NULL);
+                       if(!strcmp(nsPtr->href, ns))
+                               return TRUE;
+                       return FALSE;
+               }
+               return TRUE;
+       }
+       return FALSE;
+}
+
+int node_is_equal_ex(xmlNodePtr node, char *name, char *ns)
+{
+       if(!strcmp(node->name, name))
+       {
+               if(ns)
+               {
+                       xmlNsPtr nsPtr;
+                       if(node->ns)
+                               nsPtr = node->ns;
+                       else
+                               nsPtr = xmlSearchNs(node->doc, node, NULL);
+                       if(!strcmp(nsPtr->href, ns))
+                               return TRUE;
+                       return FALSE;
+               }
+               return TRUE;
+       }
+       return FALSE;
+}
+
+xmlAttrPtr get_attribute_ex(xmlAttrPtr node, char *name, char *ns)
+{
+       xmlAttrPtr trav = node;
+       if(node == NULL) return NULL;
+       do {
+               if(attr_is_equal_ex(trav, name, ns))
+                       return trav;
+       } while(trav = trav->next);
+       return NULL;
+}
+
+xmlNodePtr get_node_ex(xmlNodePtr node, char *name, char *ns)
+{
+       xmlNodePtr trav = node;
+       if(node == NULL) return NULL;
+       do {
+               if(node_is_equal_ex(trav, name, ns))
+                       return trav;
+       } while(trav = trav->next);
+       return NULL;
+}
+
+xmlNodePtr get_node_recurisve_ex(xmlNodePtr node, char *name, char *ns)
+{
+       xmlNodePtr trav = node;
+       if(node == NULL) return NULL;
+       do
+       {
+               if(node_is_equal_ex(trav, name, ns))
+                       return trav;
+               else
+               {
+                       if(node->children != NULL)
+                       {
+                               xmlNodePtr tmp;
+                               tmp = get_node_recurisve_ex(node->children, name, ns);
+                               if(tmp)
+                                       return tmp;
+                       }
+               }
+       } while(trav = trav->next);
+       return NULL;
+}
+
+xmlNodePtr get_node_with_attribute_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns)
+{
+       xmlNodePtr trav = node, cur;
+       xmlAttrPtr attr;
+
+       if(node == NULL) return NULL;
+       do
+       {
+               if(name != NULL)
+               {
+                       cur = get_node_ex(trav, name, name_ns);
+                       if(!cur)
+                               return cur;
+               }
+               else
+                       cur = trav;
+
+               attr = get_attribute_ex(cur->properties, attribute, attr_ns);
+               if(attr != NULL && strcmp(attr->children->content, value) == 0)
+                       return cur;
+               else
+               {
+                       if(cur->children != NULL)
+                       {
+                               xmlNodePtr tmp;
+                               tmp = get_node_with_attribute_ex(cur->children, name, name_ns, attribute, value, attr_ns);
+                               if(tmp)
+                                       return tmp;
+                       }
+               }
+       }while(trav = trav->next);
+       return NULL;
+}
+
+xmlNodePtr get_node_with_attribute_recursive_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns)
+{
+       xmlNodePtr trav = node, cur;
+       xmlAttrPtr attr;
+
+       if(node == NULL) return NULL;
+       do
+       {
+               if(name != NULL)
+               {
+                       cur = get_node_recurisve_ex(trav, name, name_ns);
+                       if(!cur)
+                               return cur;
+               }
+               else
+                       cur = trav;
+
+               attr = get_attribute_ex(cur->properties, attribute, attr_ns);
+               if(attr != NULL && strcmp(attr->children->content, value) == 0)
+                       return cur;
+               else
+               {
+                       if(cur->children != NULL)
+                       {
+                               xmlNodePtr tmp;
+                               tmp = get_node_with_attribute_recursive_ex(cur->children, name, name_ns, attribute, value, attr_ns);
+                               if(tmp)
+                                       return tmp;
+                       }
+               }
+       }while(trav = trav->next);
+       return NULL;
+}
+
+xmlNodePtr check_and_resolve_href(xmlNodePtr data)
+{
+       xmlAttrPtr href;
+       xmlNodePtr ret = data;
+
+       if(!data || !data->properties)
+               return ret;
+
+       href = get_attribute(data->properties, "href");
+       if(href)
+       {
+               // Internal href try and find node
+               if(href->children->content[0] == '#')
+               {
+                       ret = get_node_with_attribute_recursive(data->doc->children, NULL, "id", &href->children->content[1]);
+               }
+               // External href....?
+       }
+
+       return ret;
+}
+
+int parse_namespace(char *inval, char **value, char **namespace)
+{
+       char *found = strchr(inval, ':');
+
+       if(found != NULL)
+       {
+               (*namespace) = estrndup(inval, found - inval);
+               (*value) = estrdup(++found);
+       }
+       else
+       {
+               (*value) = estrdup(inval);
+               (*namespace) = NULL;
+       }
+
+       return FALSE;
+}
+
diff --git a/ext/soap/php_xml.h b/ext/soap/php_xml.h
new file mode 100644 (file)
index 0000000..d17caba
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef PHP_SOAP_XML_H
+#define PHP_SOAP_XML_H
+
+#define get_attribute(node, name) get_attribute_ex(node, name, NULL)
+#define get_node(node, name) get_node_ex(node, name, NULL)
+#define get_node_recursive(node, name) get_node_recursive_ex(node, name, NULL)
+#define get_node_with_attribute(node, name, attr, val) get_node_with_attribute_ex(node, name, NULL, attr, val, NULL)
+#define get_node_with_attribute_recursive(node, name, attr, val) get_node_with_attribute_recursive_ex(node, name, NULL, attr, val, NULL)
+#define attr_is_equal(node, name) attr_is_equal_ex(node, name, NULL)
+
+xmlNsPtr attr_find_ns(xmlAttrPtr node);
+xmlNsPtr node_find_ns(xmlNodePtr node);
+int attr_is_equal_ex(xmlAttrPtr node, char *name, char *ns);
+int node_is_equal_ex(xmlNodePtr node, char *name, char *ns);
+xmlAttrPtr get_attribute_ex(xmlAttrPtr node,char *name, char *ns);
+xmlNodePtr get_node_ex(xmlNodePtr node,char *name, char *ns);
+xmlNodePtr get_node_recurisve_ex(xmlNodePtr node,char *name, char *ns);
+xmlNodePtr get_node_with_attribute_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns);
+xmlNodePtr get_node_with_attribute_recursive_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns);
+int parse_namespace(char *inval,char **value,char **namespace);
+xmlNodePtr check_and_resolve_href(xmlNodePtr data);
+
+#endif
diff --git a/ext/soap/soap.c b/ext/soap/soap.c
new file mode 100644 (file)
index 0000000..fbc889a
--- /dev/null
@@ -0,0 +1,2037 @@
+#include "php_soap.h"
+
+int le_sdl = 0;
+int le_http_socket = 0;
+int le_url = 0;
+int le_service = 0;
+
+// Local functions
+static void function_to_string(sdlFunctionPtr function, smart_str *buf);
+static void type_to_string(sdlTypePtr type, smart_str *buf, int level);
+
+static zend_class_entry soap_class_entry;
+static zend_class_entry soap_server_class_entry;
+static zend_class_entry soap_fault_class_entry;
+zend_class_entry soap_var_class_entry;
+zend_class_entry soap_param_class_entry;
+
+ZEND_DECLARE_MODULE_GLOBALS(soap);
+
+static void (*old_handler)(int, const char *, const uint, const char*, va_list);
+
+static zend_function_entry soap_functions[] = {
+#ifdef HAVE_PHP_DOMXML
+       PHP_FE(soap_encode_to_xml, NULL)
+       PHP_FE(soap_encode_to_zval, NULL)
+#endif
+       {NULL, NULL, NULL}
+};
+
+static zend_function_entry soap_fault_functions[] = {
+       PHP_FE(soapfault, NULL)
+       {NULL, NULL, NULL}
+};
+
+static zend_function_entry soap_server_functions[] = {
+       PHP_FE(soapserver,NULL)
+       PHP_FE(setpersistence,NULL)
+       PHP_FE(setclass,NULL)
+       PHP_FE(addfunction,NULL)
+       PHP_FE(getfunctions,NULL)
+       PHP_FE(handle,NULL)
+       PHP_FE(bind,NULL)
+#ifdef HAVE_PHP_DOMXML
+       PHP_FE(map, NULL)
+#endif
+       {NULL, NULL, NULL}
+};
+
+static zend_function_entry soap_client_functions[] = {
+       PHP_FE(soapobject, NULL)
+       PHP_FE(__isfault, NULL)
+       PHP_FE(__getfault, NULL)
+       PHP_FE(__call, NULL)
+       PHP_FE(__parse, NULL)
+#ifdef PHP_DEBUG
+       PHP_FE(__getlastrequest, NULL)
+       PHP_FE(__getlastresponse, NULL)
+       PHP_FE(__getfunctions, NULL)
+       PHP_FE(__gettypes, NULL)
+#endif
+       {NULL, NULL, NULL}
+};
+
+static zend_function_entry soap_var_functions[] = {
+       PHP_FE(soapvar, NULL)
+       {NULL, NULL, NULL}
+};
+
+static zend_function_entry soap_param_functions[] = {
+       PHP_FE(soapparam, NULL)
+       {NULL, NULL, NULL}
+};
+
+zend_module_entry soap_module_entry = {
+#ifdef STANDARD_MODULE_HEADER
+  STANDARD_MODULE_HEADER,
+#endif
+  "soap",
+  soap_functions,
+  PHP_MINIT(soap),
+  PHP_MSHUTDOWN(soap),
+  NULL,
+  NULL,
+  PHP_MINFO(soap),
+#ifdef STANDARD_MODULE_HEADER
+  NO_VERSION_YET,
+#endif
+  STANDARD_MODULE_PROPERTIES,
+};
+
+#ifdef COMPILE_DL_SOAP
+ZEND_GET_MODULE(soap)
+#endif
+
+static void php_soap_init_globals(zend_soap_globals *soap_globals)
+{
+       int i;
+       long enc;
+
+       soap_globals->sdls = malloc(sizeof(HashTable));
+       zend_hash_init(soap_globals->sdls, 0, NULL, delete_sdl, 1);
+
+       soap_globals->services = malloc(sizeof(HashTable));
+       zend_hash_init(soap_globals->services, 0, NULL, delete_service, 1);
+
+       soap_globals->defEnc = malloc(sizeof(HashTable));
+       zend_hash_init(soap_globals->defEnc, 0, NULL, NULL, 1);
+
+       soap_globals->defEncIndex = malloc(sizeof(HashTable));
+       zend_hash_init(soap_globals->defEncIndex, 0, NULL, NULL, 1);
+
+       soap_globals->defEncNs = malloc(sizeof(HashTable));
+       zend_hash_init(soap_globals->defEncNs, 0, NULL, NULL, 1);
+
+       soap_globals->defEncPrefix = malloc(sizeof(HashTable));
+       zend_hash_init(soap_globals->defEncPrefix, 0, NULL, NULL, 1);
+
+       soap_globals->overrides = NULL;
+
+       i = 0;
+       do
+       {
+               enc = (long)&defaultEncoding[i];
+
+               //If has a ns and a str_type then index it
+               if(defaultEncoding[i].details.type_str)
+               {
+                       if(defaultEncoding[i].details.ns != NULL)
+                       {
+                               char *ns_type;
+                               ns_type = emalloc(strlen(defaultEncoding[i].details.ns) + strlen(defaultEncoding[i].details.type_str) + 2);
+                               sprintf(ns_type, "%s:%s", defaultEncoding[i].details.ns, defaultEncoding[i].details.type_str);
+                               zend_hash_add(soap_globals->defEnc, ns_type, strlen(ns_type), &enc, sizeof(encodePtr), NULL);
+                               efree(ns_type);
+                       }
+                       else
+                       {
+                               zend_hash_add(soap_globals->defEnc, defaultEncoding[i].details.type_str, strlen(defaultEncoding[i].details.type_str), &enc, sizeof(encodePtr), NULL);
+                       }
+               }
+               //Index everything by number
+               zend_hash_index_update(soap_globals->defEncIndex, defaultEncoding[i].details.type, &enc, sizeof(encodePtr), NULL);
+               i++;
+       }
+       while(defaultEncoding[i].details.type != END_KNOWN_TYPES);
+
+       //hash by namespace
+       zend_hash_add(soap_globals->defEncNs, XSD_1999_NAMESPACE, sizeof(XSD_1999_NAMESPACE), XSD_NS_PREFIX, sizeof(XSD_NS_PREFIX), NULL);
+       zend_hash_add(soap_globals->defEncNs, XSD_NAMESPACE, sizeof(XSD_NAMESPACE), XSD_NS_PREFIX, sizeof(XSD_NS_PREFIX), NULL);
+       zend_hash_add(soap_globals->defEncNs, APACHE_NAMESPACE, sizeof(APACHE_NAMESPACE), APACHE_NS_PREFIX, sizeof(APACHE_NS_PREFIX), NULL);
+       zend_hash_add(soap_globals->defEncNs, SOAP_ENC_NAMESPACE, sizeof(SOAP_ENC_NAMESPACE), SOAP_ENC_NS_PREFIX, sizeof(SOAP_ENC_NS_PREFIX), NULL);
+       //and by prefix
+       zend_hash_add(soap_globals->defEncPrefix, XSD_NS_PREFIX, sizeof(XSD_NS_PREFIX), XSD_NAMESPACE, sizeof(XSD_NAMESPACE), NULL);
+       zend_hash_add(soap_globals->defEncPrefix, APACHE_NS_PREFIX, sizeof(APACHE_NS_PREFIX), APACHE_NAMESPACE, sizeof(APACHE_NAMESPACE), NULL);
+       zend_hash_add(soap_globals->defEncPrefix, SOAP_ENC_NS_PREFIX, sizeof(SOAP_ENC_NS_PREFIX), SOAP_ENC_NAMESPACE, sizeof(SOAP_ENC_NAMESPACE), NULL);
+
+}
+
+static void php_soap_del_globals(zend_soap_globals *soap_globals)
+{
+/*     zend_hash_destroy(soap_globals->sdls);
+       zend_hash_destroy(soap_globals->services);
+       zend_hash_destroy(soap_globals->defEnc);
+       zend_hash_destroy(soap_globals->defEncIndex);
+       zend_hash_destroy(soap_globals->defEncNs);*/
+}
+
+PHP_MSHUTDOWN_FUNCTION(soap)
+{
+       zend_hash_destroy(SOAP_GLOBAL(sdls));
+       zend_hash_destroy(SOAP_GLOBAL(services));
+       zend_hash_destroy(SOAP_GLOBAL(defEnc));
+       zend_hash_destroy(SOAP_GLOBAL(defEncIndex));
+       zend_hash_destroy(SOAP_GLOBAL(defEncNs));
+       zend_hash_destroy(SOAP_GLOBAL(defEncPrefix));
+       return SUCCESS;
+}
+
+PHP_MINIT_FUNCTION(soap)
+{
+       //TODO: add ini entry for always use soap errors
+       ZEND_INIT_MODULE_GLOBALS(soap, php_soap_init_globals, php_soap_del_globals);
+
+       //Register SoapObject class
+       INIT_OVERLOADED_CLASS_ENTRY(soap_class_entry, PHP_SOAP_CLASSNAME, soap_client_functions, soap_call_function_handler, NULL, NULL);
+       zend_register_internal_class(&soap_class_entry TSRMLS_CC);
+
+       //Register SoapVar class
+       INIT_CLASS_ENTRY(soap_var_class_entry, PHP_SOAP_VAR_CLASSNAME, soap_var_functions);
+       zend_register_internal_class(&soap_var_class_entry TSRMLS_CC);
+
+       //Register SoapServer class
+       INIT_CLASS_ENTRY(soap_server_class_entry, PHP_SOAP_SERVER_CLASSNAME, soap_server_functions);
+       zend_register_internal_class(&soap_server_class_entry TSRMLS_CC);
+
+       //Register SoapFault class
+       INIT_CLASS_ENTRY(soap_fault_class_entry, PHP_SOAP_FAULT_CLASSNAME, soap_fault_functions);
+       zend_register_internal_class(&soap_fault_class_entry TSRMLS_CC);
+
+       //Register SoapParam class
+       INIT_CLASS_ENTRY(soap_param_class_entry, PHP_SOAP_PARAM_CLASSNAME, soap_param_functions);
+       zend_register_internal_class(&soap_param_class_entry TSRMLS_CC);
+
+       le_sdl = register_list_destructors(NULL, NULL);
+       le_http_socket = register_list_destructors(delete_http_socket, NULL);
+       le_url = register_list_destructors(delete_url, NULL);
+       le_service = register_list_destructors(delete_service, NULL);
+
+       REGISTER_LONG_CONSTANT("SOAP_PERSISTENCE_SESSION", SOAP_PERSISTENCE_SESSION, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("SOAP_PERSISTENCE_REQUEST", SOAP_PERSISTENCE_REQUEST, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("SOAP_FUNCTIONS_ALL", SOAP_FUNCTIONS_ALL, CONST_CS | CONST_PERSISTENT);
+
+       REGISTER_LONG_CONSTANT("XSD_1999_TIMEINSTANT", XSD_1999_TIMEINSTANT, CONST_CS | CONST_PERSISTENT);
+
+       REGISTER_LONG_CONSTANT("UNKNOWN_TYPE", UNKNOWN_TYPE, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("SOAP_ENC_OBJECT", SOAP_ENC_OBJECT, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("SOAP_ENC_ARRAY", SOAP_ENC_ARRAY, CONST_CS | CONST_PERSISTENT);
+
+       REGISTER_LONG_CONSTANT("XSD_STRING", XSD_STRING, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_BOOLEAN", XSD_BOOLEAN, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_DECIMAL", XSD_DECIMAL, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_FLOAT", XSD_FLOAT, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_DOUBLE", XSD_DOUBLE, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_DURATION", XSD_DURATION, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_DATETIME", XSD_DATETIME, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_TIME", XSD_TIME, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_DATE", XSD_DATE, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_GYEARMONTH", XSD_GYEARMONTH, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_GYEAR", XSD_GYEAR, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_GMONTHDAY", XSD_GMONTHDAY, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_GDAY", XSD_GDAY, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_GMONTH", XSD_GMONTH, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_HEXBINARY", XSD_HEXBINARY, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_BASE64BINARY", XSD_BASE64BINARY, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_ANYURI", XSD_ANYURI, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_QNAME", XSD_QNAME, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_NOTATION", XSD_NOTATION, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_NORMALIZEDSTRING", XSD_NORMALIZEDSTRING, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_TOKEN", XSD_TOKEN, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_LANGUAGE", XSD_LANGUAGE, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_NMTOKEN", XSD_NMTOKEN, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_NAME", XSD_NAME, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_NCNAME", XSD_NCNAME, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_ID", XSD_ID, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_IDREF", XSD_IDREF, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_IDREFS", XSD_IDREFS, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_ENTITY", XSD_ENTITY, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_ENTITYS", XSD_ENTITYS, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_INTEGER", XSD_INTEGER, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_NONPOSITIVEINTEGER", XSD_NONPOSITIVEINTEGER, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_NEGATIVEINTEGER", XSD_NEGATIVEINTEGER, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_LONG", XSD_LONG, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_INT", XSD_INT, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_SHORT", XSD_SHORT, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_BYTE", XSD_BYTE, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_NONNEGATIVEINTEGER", XSD_NONNEGATIVEINTEGER, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_UNSIGNEDLONG", XSD_UNSIGNEDLONG, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_UNSIGNEDINT", XSD_UNSIGNEDINT, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_UNSIGNEDSHORT", XSD_UNSIGNEDSHORT, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_UNSIGNEDBYTE", XSD_UNSIGNEDBYTE, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSD_POSITIVEINTEGER", XSD_POSITIVEINTEGER, CONST_CS | CONST_PERSISTENT);
+
+       old_handler = zend_error_cb;
+
+#if HAVE_PHP_SESSION
+       php_session_register_serializer("soap", PS_SERIALIZER_ENCODE_NAME(soap), PS_SERIALIZER_DECODE_NAME(soap));
+#endif
+
+       return SUCCESS;
+}
+
+#if HAVE_PHP_SESSION
+PS_SERIALIZER_ENCODE_FUNC(soap)
+{
+/*
+       char *key;                                                                                                      \
+       uint key_length;                                                                                        \
+       ulong num_key;                                                                                          \
+       zval **struc;
+
+    wddx_packet *packet;
+       PS_ENCODE_VARS;
+
+       packet = php_wddx_constructor();
+       if (!packet)
+               return FAILURE;
+
+       php_wddx_packet_start(packet, NULL, 0);
+       php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
+
+       PS_ENCODE_LOOP(
+
+               php_wddx_serialize_var(packet, *struc, key, key_length);
+       );
+
+       php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
+       php_wddx_packet_end(packet);
+       *newstr = php_wddx_gather(packet);
+       php_wddx_destructor(packet);
+
+       if (newlen)
+               *newlen = strlen(*newstr);
+*/
+       return SUCCESS;
+}
+
+PS_SERIALIZER_DECODE_FUNC(soap)
+{
+/*     zval *retval;
+       zval **ent;
+       char *key;
+       uint key_length;
+       char tmp[128];
+       ulong idx;
+       int hash_type;
+       int ret;
+
+       if (vallen == 0)
+               return SUCCESS;
+
+       MAKE_STD_ZVAL(retval);
+
+       if ((ret = php_wddx_deserialize_ex((char *)val, vallen, retval)) == SUCCESS) {
+
+               for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(retval));
+                        zend_hash_get_current_data(Z_ARRVAL_P(retval), (void **) &ent) == SUCCESS;
+                        zend_hash_move_forward(Z_ARRVAL_P(retval))) {
+                       hash_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(retval), &key, &key_length, &idx, 0, NULL);
+
+                       switch (hash_type) {
+                               case HASH_KEY_IS_LONG:
+                                       sprintf(tmp, "%ld", idx);
+                                       key = tmp;
+                               case HASH_KEY_IS_STRING:
+                                       php_set_session_var(key, key_length-1, *ent, NULL TSRMLS_CC);
+                                       PS_ADD_VAR(key);
+                       }
+               }
+       }
+
+       zval_ptr_dtor(&retval);
+*/
+       return TRUE;
+}
+#endif
+
+
+PHP_MINFO_FUNCTION(soap)
+{
+       php_info_print_table_start();
+       php_info_print_table_row(2, "Soap Client", "enabled");
+       php_info_print_table_row(2, "Soap Server", "enabled");
+#if HAVE_PHP_SESSION
+       php_info_print_table_row(2, "Soap Serializer", "enabled");
+#endif
+       php_info_print_table_end();
+}
+
+#ifdef HAVE_PHP_DOMXML
+PHP_FUNCTION(soap_encode_to_xml)
+{
+       zval *pzval, *ret;
+       encodePtr enc;
+       char *name;
+       int found, name_len;
+
+       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name, &name_len, &pzval) == FAILURE)
+               php_error(E_ERROR, "wrong number of parameters to soap_encode_to_xml");
+
+       enc = get_conversion(Z_TYPE_P(pzval));
+       ret = php_domobject_new(seralize_zval(pzval, NULL, name), &found, NULL TSRMLS_CC);
+       *return_value = *ret;
+       zval_copy_ctor(return_value);
+       zval_ptr_dtor(&ret);
+}
+
+PHP_FUNCTION(soap_encode_to_zval)
+{
+       zval *dom, **addr, *ret;
+       xmlNodePtr node;
+
+       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &dom) == FAILURE)
+               php_error(E_ERROR, "wrong number of parameters to soap_encode_to_zval");
+
+       if(zend_hash_index_find(Z_OBJPROP_P(dom), 1, (void **)&addr) == FAILURE)
+               php_error(E_ERROR, "Cannot find domaddress to parameter passed to soap_encode_to_zval");
+
+       node = (xmlNodePtr)Z_LVAL_PP(addr);
+       ret = master_to_zval(get_conversion(UNKNOWN_TYPE), node);
+       *return_value = *ret;
+}
+#endif
+
+//SoapParam functions
+PHP_FUNCTION(soapparam)
+{
+       zval *thisObj, *data;
+       char *name;
+       int name_length;
+
+       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &data, &name, &name_length) == FAILURE)
+               php_error(E_ERROR, "Invalid arguments to SoapParam constructor");
+
+       GET_THIS_OBJECT(thisObj);
+
+       zval_add_ref(&data);
+       add_property_stringl(thisObj, "param_name", name, name_length, 1);
+       add_property_zval(thisObj, "param_data", data);
+}
+
+//SoapFault functions
+PHP_FUNCTION(soapfault)
+{
+       char *fault_string = NULL, *fault_code = NULL, *fault_actor = NULL;
+       int fault_string_len, fault_code_len, fault_actor_len;
+       zval *thisObj, *details = NULL;
+
+       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|zs", &fault_string, &fault_string_len,
+               &fault_code, &fault_code_len, &details, &fault_actor, &fault_actor_len) == FAILURE)
+               php_error(E_ERROR, "Invalid arguments to SoapFault constructor");
+
+       GET_THIS_OBJECT(thisObj);
+
+       if(details)
+               zval_add_ref(&details);
+       set_soap_fault(thisObj, fault_code, fault_string, fault_actor, details);
+}
+
+//SoapVar functions
+PHP_FUNCTION(soapvar)
+{
+       zval *data, *thisObj, *type;
+       char *stype = NULL, *ns = NULL;
+       int stype_len, ns_len;
+
+       GET_THIS_OBJECT(thisObj);
+       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!z|ss", &data, &type, &stype, &stype_len, &ns, &ns_len) == FAILURE)
+                       php_error(E_ERROR, "Invalid arguments to SoapVal constructor");
+
+       zval_add_ref(&data);
+       if(Z_TYPE_P(type) == IS_NULL)
+               add_property_long(thisObj, "enc_type", UNKNOWN_TYPE);
+       else
+       {
+               if(zend_hash_index_exists(SOAP_GLOBAL(defEncIndex), Z_LVAL_P(type)))
+                       add_property_long(thisObj, "enc_type", Z_LVAL_P(type));
+               else
+                       php_error(E_ERROR, "Cannot find encoding for SoapVar");
+       }
+
+       add_property_zval(thisObj, "enc_value", data);
+
+       if(stype)
+               add_property_stringl(thisObj, "enc_stype", stype, stype_len, 1);
+       if(ns)
+               add_property_stringl(thisObj, "enc_ns", ns, ns_len, 1);
+}
+
+//SoapServer functions
+PHP_FUNCTION(soapserver)
+{
+       zval *thisObj;
+       soapServicePtr service;
+       char *uri;
+       int ret, uri_len;
+
+       SOAP_SERVER_BEGIN_CODE();
+
+       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &uri, &uri_len) == FAILURE)
+               php_error(E_ERROR, "Wrong number of parameters to SoapServer constructor");
+
+       GET_THIS_OBJECT(thisObj);
+
+       service = emalloc(sizeof(soapService));
+       memset(service, 0, sizeof(soapService));
+
+       service->uri = estrndup(uri, uri_len);
+       service->type = SOAP_FUNCTIONS;
+       service->soap_functions.functions_all = FALSE;
+       service->soap_functions.ft = emalloc(sizeof(HashTable));
+       zend_hash_init(service->soap_functions.ft, 0, NULL, ZVAL_PTR_DTOR, 0);
+
+       ret = zend_list_insert(service, le_service);
+       add_property_resource(thisObj, "service", ret);
+       zend_list_addref(ret);
+
+       SOAP_SERVER_END_CODE();
+}
+
+#define NULL_OR_STRING(zval) \
+       (!zval || Z_TYPE_P(zval) == IS_NULL || Z_TYPE_P(zval) == IS_STRING)
+
+#define IS_VALID_FUNCTION(zval) \
+       (zval && Z_TYPE_P(zval) != IS_NULL)
+
+#ifdef HAVE_PHP_DOMXML
+PHP_FUNCTION(map)
+{
+       char *type, *class_name;
+       zval *to_xml_before = NULL, *to_xml = NULL, *to_xml_after = NULL,
+               *to_zval_before = NULL, *to_zval = NULL, *to_zval_after = NULL;
+       int type_len, class_name_len;
+       char *ns, *ctype;
+       soapServicePtr service;
+
+       SOAP_SERVER_BEGIN_CODE();
+
+       if(zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "sz|zzzzz",
+               &type, &type_len, &to_xml_before, &to_xml, &to_xml_after, &to_zval_before, &to_zval,
+               &to_zval_after) == SUCCESS && NULL_OR_STRING(to_xml_before) && NULL_OR_STRING(to_xml) &&
+               NULL_OR_STRING(to_xml_after) && NULL_OR_STRING(to_zval_before) && NULL_OR_STRING(to_zval) &&
+               NULL_OR_STRING(to_zval_after))
+       {
+               soapMappingPtr map;
+               encodePtr enc, new_enc;
+               smart_str resloved_ns = {0};
+
+               FETCH_THIS_SERVICE(service);
+
+               new_enc = malloc(sizeof(encode));
+               memset(new_enc, 0, sizeof(encode));
+
+               ctype = strrchr(type, ':');
+               if(ctype) {
+                       smart_str_appendl(&resloved_ns, type, ctype - type);
+                       smart_str_0(&resloved_ns);
+                       ctype++;
+               } else {
+                       ns = NULL;
+               }
+
+               if(ns)
+               {
+                       if(zend_hash_find(SOAP_GLOBAL(defEncPrefix),  resloved_ns.c, resloved_ns.len + 1, &ns) == SUCCESS)
+                       {
+                               enc = get_encoder(service->sdl, ns, ctype);
+                               smart_str_free(&resloved_ns);
+                               smart_str_appendl(&resloved_ns, ns, strlen(ns));
+                               smart_str_appendc(&resloved_ns, ':');
+                               smart_str_appendl(&resloved_ns, ctype, strlen(ctype));
+                               smart_str_0(&resloved_ns);
+                               type = resloved_ns.c;
+                               type_len = resloved_ns.len;
+                       }
+                       else
+                               enc = get_encoder_ex(service->sdl, type);
+               }
+               else
+                       enc = get_encoder_ex(service->sdl, type);
+
+               new_enc->details.type = enc->details.type;
+               new_enc->details.ns = strdup(enc->details.ns);
+               new_enc->details.type_str = strdup(enc->details.type_str);
+               new_enc->details.sdl_type = enc->details.sdl_type;
+               new_enc->to_xml = enc->to_xml;
+               new_enc->to_zval = enc->to_zval;
+               new_enc->to_xml_before = enc->to_xml_before;
+               new_enc->to_zval_before = enc->to_zval_before;
+               new_enc->to_xml_after = enc->to_xml_after;
+               new_enc->to_zval_after = enc->to_zval_after;
+
+               map = emalloc(sizeof(soapMapping));
+               memset(map, 0, sizeof(soapMapping));
+
+               map->type = SOAP_MAP_FUNCTION;
+               if(IS_VALID_FUNCTION(to_xml_before))
+               {
+                       zval_add_ref(&to_xml_before);
+                       map->map_functions.to_xml_before = to_xml_before;
+                       new_enc->to_xml_before = to_xml_before_user;
+               }
+               if(IS_VALID_FUNCTION(to_xml))
+               {
+                       zval_add_ref(&to_xml);
+                       map->map_functions.to_xml = to_xml;
+                       new_enc->to_xml = to_xml_user;
+               }
+               if(IS_VALID_FUNCTION(to_xml_after))
+               {
+                       zval_add_ref(&to_xml_after);
+                       map->map_functions.to_xml_after = to_xml_after;
+                       new_enc->to_xml_after = to_xml_after_user;
+               }
+               if(IS_VALID_FUNCTION(to_zval_before))
+               {
+                       zval_add_ref(&to_zval_before);
+                       map->map_functions.to_zval_before = to_zval_before;
+                       new_enc->to_zval_before = to_zval_before_user;
+               }
+               if(IS_VALID_FUNCTION(to_zval))
+               {
+                       zval_add_ref(&to_zval);
+                       map->map_functions.to_zval = to_zval;
+                       new_enc->to_zval = to_zval_user;
+               }
+               if(IS_VALID_FUNCTION(to_zval_after))
+               {
+                       zval_add_ref(&to_zval_after);
+                       map->map_functions.to_zval_after = to_zval_after;
+                       new_enc->to_zval_after = to_zval_after_user;
+               }
+
+               new_enc->details.map = map;
+
+               if(!service->mapping)
+               {
+                       service->mapping = emalloc(sizeof(HashTable));
+                       zend_hash_init(service->mapping, 0, NULL, delete_encoder, 0);
+               }
+               zend_hash_update(service->mapping, type, type_len + 1, &new_enc, sizeof(encodePtr), NULL);
+               smart_str_free(&resloved_ns);
+       }
+       else if(zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &type, &type_len, &class_name, &class_name_len, &type) == SUCCESS)
+       {
+       }
+       else
+               php_error(E_ERROR, "Wrong number of parameters to SoapServer->map");
+}
+#endif
+
+PHP_FUNCTION(bind)
+{
+       char *wsdl;
+       int wsdl_len;
+       soapServicePtr service;
+
+       SOAP_SERVER_BEGIN_CODE();
+
+       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &wsdl, &wsdl_len) == FAILURE)
+               php_error(E_ERROR, "Wrong number of parameters to SoapServer->bind");
+
+       FETCH_THIS_SERVICE(service);
+       service->sdl = get_sdl(wsdl);
+
+       SOAP_SERVER_END_CODE();
+}
+
+PHP_FUNCTION(setpersistence)
+{
+       soapServicePtr service;
+       int value;
+
+       SOAP_SERVER_BEGIN_CODE();
+       FETCH_THIS_SERVICE(service);
+
+       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) != FAILURE)
+       {
+               if(service->type == SOAP_CLASS)
+               {
+                       if(value == SOAP_PERSISTENCE_SESSION ||
+                               value == SOAP_PERSISTENCE_REQUEST)
+                               service->soap_class.persistance = value;
+                       else
+                               php_error(E_ERROR, "Tried to set persistence with bogus value (%ld)", value);
+               }
+               else
+                       php_error(E_ERROR, "Tried to set persistence when you are using you SOAP SERVER in function mode, no persistence needed");
+       }
+
+       SOAP_SERVER_END_CODE();
+}
+
+PHP_FUNCTION(setclass)
+{
+       soapServicePtr service;
+       zend_class_entry *ce;
+       char *class_name = NULL;
+       int found, argc;
+       zval ***argv;
+
+       SOAP_SERVER_BEGIN_CODE();
+
+       FETCH_THIS_SERVICE(service);
+
+       argc = ZEND_NUM_ARGS();
+       argv = emalloc(argc * sizeof(zval **));
+
+       if (argc < 1 || zend_get_parameters_array_ex(argc, argv) == FAILURE)
+       {
+               efree(argv);
+               WRONG_PARAM_COUNT;
+       }
+
+       if(Z_TYPE_PP(argv[0]) == IS_STRING)
+       {
+               class_name = estrdup(Z_STRVAL_PP(argv[0]));
+
+               found = zend_hash_find(EG(class_table), php_strtolower(class_name, Z_STRLEN_PP(argv[0])), Z_STRLEN_PP(argv[0])   + 1, (void **)&ce);
+               efree(class_name);
+               if(found != FAILURE)
+               {
+                       service->type = SOAP_CLASS;
+                       service->soap_class.ce = ce;
+                       service->soap_class.persistance = SOAP_PERSISTENCE_REQUEST;
+                       service->soap_class.argc = argc - 1;
+                       if(service->soap_class.argc > 0)
+                       {
+                               int i;
+                               service->soap_class.argv = emalloc(sizeof(zval) * service->soap_class.argc);
+                               for(i = 0;i < service->soap_class.argc;i++)
+                               {
+                                       service->soap_class.argv[i] = *(argv[i + 1]);
+                                       zval_add_ref(&service->soap_class.argv[i]);
+                               }
+                       }
+               }
+               else
+                       php_error(E_ERROR, "Tried to set a non existant class (%s)", Z_STRVAL_PP(argv[0]));
+       }
+       else
+               php_error(E_ERROR, "You must pass in a string to setclass");
+
+       efree(argv);
+       SOAP_SERVER_END_CODE();
+}
+
+PHP_FUNCTION(getfunctions)
+{
+       soapServicePtr service;
+
+       SOAP_SERVER_BEGIN_CODE();
+
+       FETCH_THIS_SERVICE(service);
+
+       array_init(return_value);
+       if(service->type == SOAP_CLASS)
+       {
+               zend_function *f;
+               zend_hash_internal_pointer_reset(&service->soap_class.ce->function_table);
+               while(zend_hash_get_current_data(&service->soap_class.ce->function_table, (void **)&f) != FAILURE)
+               {
+                       add_next_index_string(return_value, f->common.function_name, 1);
+                       zend_hash_move_forward(&service->soap_class.ce->function_table);
+               }
+       }
+       else if(service->soap_functions.functions_all == TRUE)
+       {
+               zend_function *f;
+               zend_hash_internal_pointer_reset(EG(function_table));
+               while(zend_hash_get_current_data(EG(function_table), (void **)&f) != FAILURE)
+               {
+                       add_next_index_string(return_value, f->common.function_name, 1);
+                       zend_hash_move_forward(EG(function_table));
+               }
+       }
+       else if(service->soap_functions.ft != NULL)
+               zend_hash_copy(Z_ARRVAL_P(return_value), service->soap_functions.ft, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
+
+       SOAP_SERVER_END_CODE();
+}
+
+PHP_FUNCTION(addfunction)
+{
+       soapServicePtr service;
+       zval *function_name, *function_copy;
+
+       SOAP_SERVER_BEGIN_CODE();
+
+       FETCH_THIS_SERVICE(service);
+
+       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &function_name) == FAILURE)
+               php_error(E_ERROR, "Invalid parameters passed to addfunction");
+
+       if(function_name->type == IS_ARRAY)
+       {
+               if(service->type == SOAP_FUNCTIONS)
+               {
+                       zval **tmp_function, *function_copy;
+
+                       if(service->soap_functions.ft == NULL)
+                       {
+                               service->soap_functions.ft = emalloc(sizeof(HashTable));
+                               zend_hash_init(service->soap_functions.ft, 0, NULL, ZVAL_PTR_DTOR, 0);
+                       }
+
+                       zend_hash_internal_pointer_reset(Z_ARRVAL_P(function_name));
+                       while(zend_hash_get_current_data(Z_ARRVAL_P(function_name), (void **)&tmp_function) != FAILURE)
+                       {
+                               if(Z_TYPE_PP(tmp_function) != IS_STRING)
+                                       php_error(E_ERROR, "Tried to add a function that isn't a string");
+
+                               MAKE_STD_ZVAL(function_copy);
+                               *function_copy = *(*tmp_function);
+                               zval_copy_ctor(function_copy);
+
+                               php_strtolower(Z_STRVAL_P(function_copy), Z_STRLEN_P(function_copy));
+
+                               if(zend_hash_exists(EG(function_table), Z_STRVAL_P(function_copy), Z_STRLEN_P(function_copy) + 1) == FALSE)
+                                       php_error(E_ERROR, "Tried to add a non existant function (\"%s\")", Z_STRVAL_PP(tmp_function));
+
+                               zend_hash_update(service->soap_functions.ft, Z_STRVAL_P(function_copy), Z_STRLEN_P(function_copy) + 1, &function_copy, sizeof(zval *), NULL);
+                               zend_hash_move_forward(Z_ARRVAL_P(function_name));
+                       }
+               }
+       }
+       else if(function_name->type == IS_STRING)
+       {
+               MAKE_STD_ZVAL(function_copy);
+               *function_copy = *function_name;
+               zval_copy_ctor(function_copy);
+
+               php_strtolower(Z_STRVAL_P(function_copy), Z_STRLEN_P(function_copy));
+
+               if(zend_hash_exists(EG(function_table), Z_STRVAL_P(function_copy), Z_STRLEN_P(function_copy) + 1) == FALSE)
+                       php_error(E_ERROR, "Tried to add a non existant function (\"%s\")", Z_STRVAL_P(function_name));
+               if(service->soap_functions.ft == NULL)
+               {
+                       service->soap_functions.functions_all = FALSE;
+                       service->soap_functions.ft = emalloc(sizeof(HashTable));
+                       zend_hash_init(service->soap_functions.ft, 0, NULL, ZVAL_PTR_DTOR, 0);
+               }
+
+               zend_hash_update(service->soap_functions.ft, Z_STRVAL_P(function_copy), Z_STRLEN_P(function_copy) + 1, &function_copy, sizeof(zval *), NULL);
+       }
+       else if(function_name->type == IS_LONG)
+       {
+               if(Z_LVAL_P(function_name) == SOAP_FUNCTIONS_ALL)
+               {
+                       if(service->soap_functions.ft != NULL)
+                       {
+                               zend_hash_destroy(service->soap_functions.ft);
+                               efree(service->soap_functions.ft);
+                               service->soap_functions.ft = NULL;
+                       }
+                       service->soap_functions.functions_all = TRUE;
+               }
+               else
+                       php_error(E_ERROR, "Invalid value passed to addfunction (%ld)", Z_LVAL_P(function_name));
+       }
+
+       SOAP_SERVER_END_CODE();
+}
+
+PHP_FUNCTION(handle)
+{
+       soapServicePtr service;
+       xmlDocPtr doc_request, doc_return;
+       zval function_name, **params, **raw_post, *soap_obj, retval, **server_vars;
+       char *fn_name, cont_len[30], *response_name;
+       int num_params = 0, size, i, call_status;
+       xmlChar *buf;
+       HashTable *function_table;
+
+       FETCH_THIS_SERVICE(service);
+
+       SOAP_SERVER_BEGIN_CODE();
+       ZERO_PARAM();
+
+       INIT_ZVAL(retval);
+
+       if(zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **)&server_vars) == SUCCESS)
+       {
+               zval **req_method, **query_string;
+               if(zend_hash_find(Z_ARRVAL_PP(server_vars), "REQUEST_METHOD", sizeof("REQUEST_METHOD"), (void **)&req_method) == SUCCESS)
+               {
+                       if(!strcmp(Z_STRVAL_PP(req_method), "GET") && zend_hash_find(Z_ARRVAL_PP(server_vars), "QUERY_STRING", sizeof("QUERY_STRING"), (void **)&query_string) == SUCCESS)
+                       {
+                               if(!strcmp(Z_STRVAL_PP(query_string), "WSDL"))
+                               {
+                                       if(service->sdl)
+                                       {
+                                               zval readfile, readfile_ret, *param;
+
+                                               INIT_ZVAL(readfile);
+                                               INIT_ZVAL(readfile_ret);
+                                               MAKE_STD_ZVAL(param);
+
+                                               sapi_add_header("Content-Type: text/xml", sizeof("Content-Type: text/xml"), 1);
+                                               ZVAL_STRING(param, service->sdl->source, 1);
+                                               ZVAL_STRING(&readfile, "readfile", 1);
+                                               if(call_user_function(EG(function_table), NULL, &readfile, &readfile_ret, 1, &param  TSRMLS_CC) == FAILURE)
+                                                       php_error(E_ERROR, "Couldn't find WSDL");
+
+                                               zval_ptr_dtor(&param);
+                                               zval_dtor(&readfile);
+                                               zval_dtor(&readfile_ret);
+                                               SOAP_SERVER_END_CODE();
+                                               return;
+                                       }
+                               }
+                       }
+               }
+       }
+
+//Turn on output buffering... we don't want people print in their methods
+//#if PHP_API_VERSION <= 20010901
+//     if(php_start_ob_buffer(NULL, 0 TSRMLS_CC) != SUCCESS)
+//#else
+       if(php_start_ob_buffer(NULL, 0, 0 TSRMLS_CC) != SUCCESS)
+//#endif
+               php_error(E_ERROR,"ob_start failed");
+
+       if (zend_hash_find(&EG(symbol_table), HTTP_RAW_POST_DATA, sizeof(HTTP_RAW_POST_DATA), (void **) &raw_post)!=FAILURE
+               && ((*raw_post)->type==IS_STRING))
+       {
+               doc_request = xmlParseMemory(Z_STRVAL_PP(raw_post),Z_STRLEN_PP(raw_post));
+               xmlCleanupParser();
+
+               deseralize_function_call(service->sdl, doc_request, &function_name, &num_params, &params);
+               xmlFreeDoc(doc_request);
+
+               fn_name = estrndup(Z_STRVAL(function_name),Z_STRLEN(function_name));
+               response_name = emalloc(Z_STRLEN(function_name) + strlen("Response") + 1);
+               sprintf(response_name,"%sResponse\0",fn_name);
+
+               if(service->type == SOAP_CLASS)
+               {
+                       soap_obj = NULL;
+                       //If persistent then set soap_obj from from the previous created session (if available)
+                       if(service->soap_class.persistance == SOAP_PERSISTENCE_SESSION)
+                       {
+                               zval **tmp_soap;
+
+                               //Try and call session regiser for our dummy session object
+                               //The only reason that i use call_user_function is that
+                               //their isn't a way to start the session from an extension
+                               //so calling session_register will both register the var
+                               //and start the session
+                               {
+                                       zval *bogus_session_name, session_register, sess_retval;
+
+                                       INIT_ZVAL(session_register);
+                                       INIT_ZVAL(sess_retval);
+
+                                       if(!zend_ini_long("register_globals", sizeof("register_globals"), 0))
+                                               php_error(E_ERROR, "PHP-SOAP requires 'register_globals' to be on when using persistent objects please check your php.ini file");
+
+                                       MAKE_STD_ZVAL(bogus_session_name);
+
+                                       ZVAL_STRING(bogus_session_name, "_bogus_session_name", 1);
+                                       ZVAL_STRING(&session_register, "session_register", 1);
+
+                                       if(call_user_function(EG(function_table), NULL, &session_register, &sess_retval, 1, &bogus_session_name  TSRMLS_CC) == FAILURE)
+                                               php_error(E_ERROR,"session_register failed");
+
+                                       zval_ptr_dtor(&bogus_session_name);
+                                       zval_dtor(&session_register);
+                                       zval_dtor(&sess_retval);
+                               }
+
+                               //Find the soap object and assign
+                               if(zend_hash_find(&EG(symbol_table), "_bogus_session_name", sizeof("_bogus_session_name"), (void **) &tmp_soap) == SUCCESS)
+                                       soap_obj = *tmp_soap;
+                       }
+
+                       //If new session or something wierd happned
+                       if(soap_obj == NULL)
+                       {
+                               zval *tmp_soap;
+                               MAKE_STD_ZVAL(tmp_soap);
+                               object_init_ex(tmp_soap, service->soap_class.ce);
+
+                               //Call constructor
+                               if(zend_hash_exists(&Z_OBJCE_P(tmp_soap)->function_table, service->soap_class.ce->name, strlen(service->soap_class.ce->name) + 1))
+                               {
+                                       zval c_ret, constructor;
+
+                                       INIT_ZVAL(c_ret);
+                                       INIT_ZVAL(constructor);
+
+                                       ZVAL_STRING(&constructor, service->soap_class.ce->name, 1);
+                                       if(call_user_function(NULL, &tmp_soap, &constructor, &c_ret, service->soap_class.argc, service->soap_class.argv TSRMLS_CC) == FAILURE)
+                                               php_error(E_ERROR, "Error calling constructor");
+                                       zval_dtor(&constructor);
+                                       zval_dtor(&c_ret);
+                               }
+
+                               //If session then update session hash with new object
+                               if(service->soap_class.persistance == SOAP_PERSISTENCE_SESSION)
+                               {
+                                       zval **tmp_soap_pp;
+                                       if(zend_hash_update(&EG(symbol_table), "_bogus_session_name", sizeof("_bogus_session_name"), &tmp_soap, sizeof(zval *), (void **)&tmp_soap_pp) == SUCCESS)
+                                               soap_obj = *tmp_soap_pp;
+                               }
+                               else
+                                       soap_obj = tmp_soap;
+                       }
+                       function_table = &(soap_obj->value.obj.ce->function_table);
+               }
+               else
+               {
+                       if(service->soap_functions.functions_all == TRUE)
+                               function_table = EG(function_table);
+                       else
+                               function_table = service->soap_functions.ft;
+               }
+
+               doc_return = NULL;
+               if(zend_hash_exists(function_table, php_strtolower(Z_STRVAL(function_name), Z_STRLEN(function_name)), Z_STRLEN(function_name) + 1))
+               {
+                       if(service->type == SOAP_CLASS)
+                       {
+                               call_status = call_user_function(NULL, &soap_obj, &function_name, &retval, num_params, params TSRMLS_CC);
+                               if(service->soap_class.persistance != SOAP_PERSISTENCE_SESSION)
+                                       zval_ptr_dtor(&soap_obj);
+                       }
+                       else
+                               call_status = call_user_function(EG(function_table), NULL, &function_name, &retval, num_params, params TSRMLS_CC);
+               }
+               else
+                       php_error(E_ERROR, "Function (%s) doesn't exist", Z_STRVAL(function_name));
+
+               if(call_status == SUCCESS)
+               {
+                       sdlFunctionPtr function;
+                       function = get_function(service->sdl, Z_STRVAL(function_name));
+                       SOAP_GLOBAL(overrides) = service->mapping;
+                       doc_return = seralize_response_call(function, response_name, service->uri, &retval);
+                       SOAP_GLOBAL(overrides) = NULL;
+               }
+               else
+                       php_error(E_ERROR, "Function (%s) call failed", Z_STRVAL(function_name));
+
+               //Flush buffer
+               php_end_ob_buffer(0, 0 TSRMLS_CC);
+
+               //xmlDocDumpMemoryEnc(doc_return, &buf, &size, XML_CHAR_ENCODING_UTF8);
+               xmlDocDumpMemory(doc_return, &buf, &size);
+
+               if(size == 0)
+                       php_error(E_ERROR, "Dump memory failed");
+
+               sprintf(cont_len, "Content-Length: %d\0", size);
+               sapi_add_header("Content-Type: text/xml", sizeof("Content-Type: text/xml"), 1);
+               sapi_add_header(cont_len, strlen(cont_len) + 1, 1);
+
+               //Free Memory
+               if(num_params > 0)
+               {
+                       for(i = 0; i < num_params;i++)
+                               zval_ptr_dtor(&params[i]);
+                       efree(params);
+               }
+
+               zval_dtor(&function_name);
+               xmlFreeDoc(doc_return);
+               efree(response_name);
+               efree(fn_name);
+
+               php_write(buf, size TSRMLS_CC);
+               xmlFree(buf);
+       }
+       else
+       {
+               if(!zend_ini_long("always_populate_raw_post_data", sizeof("always_populate_raw_post_data"), 0))
+                       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, "Couln't find HTTP_RAW_POST_DATA");
+       }
+
+       zval_dtor(&retval);
+       SOAP_SERVER_END_CODE();
+}
+
+void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args)
+{
+       char buffer[1024];
+       int buffer_len;
+       TSRMLS_FETCH();
+
+       buffer_len = vsnprintf(buffer, sizeof(buffer)-1, format, args);
+       buffer[sizeof(buffer)-1]=0;
+       if(buffer_len > sizeof(buffer) - 1 || buffer_len < 0) {
+               buffer_len = sizeof(buffer) - 1;
+       }
+
+       //Trap all errors
+       //What do do with these warnings
+       //    E_WARNING, E_NOTICE, E_CORE_WARNING, E_COMPILE_WARNING, E_USER_WARNING, E_USER_NOTICE
+       if(error_num == E_USER_ERROR || error_num == E_COMPILE_ERROR || error_num == E_CORE_ERROR ||
+               error_num == E_ERROR || error_num == E_PARSE)
+       {
+               zval outbuf, outbuflen, ret;
+               xmlChar *buf, cont_len[30];
+               int size;
+               xmlDocPtr doc_return;
+
+               INIT_ZVAL(outbuf);
+               INIT_ZVAL(outbuflen);
+               INIT_ZVAL(ret);
+
+               //Get output buffer and send as fault detials
+               if(php_ob_get_length(&outbuflen TSRMLS_CC) != FAILURE && Z_LVAL(outbuflen) != 0)
+                       php_ob_get_buffer(&outbuf TSRMLS_CC);
+               php_end_ob_buffer(0, 0 TSRMLS_CC);
+
+               set_soap_fault(&ret, "SOAP-ENV:Server", buffer, NULL, &outbuf);
+               doc_return = seralize_response_call(NULL, NULL, NULL, &ret);
+
+               //Build and send our headers + http 500 status
+               //xmlDocDumpMemoryEnc(doc_return, &buf, &size, XML_CHAR_ENCODING_UTF8);
+               xmlDocDumpMemory(doc_return, &buf, &size);
+               sprintf(cont_len,"Content-Length: %d\0", size);
+               sapi_add_header(cont_len, strlen(cont_len) + 1, 1);
+               sapi_add_header("Content-Type: text/xml", sizeof("Content-Type: text/xml"), 1);
+
+               // Want to return HTTP 500 but apache wants to over write
+               // our fault code with their own handling... Figure this out later
+               // sapi_add_header("HTTP/1.1 500 Internal Service Error", sizeof("HTTP/1.1 500 Internal Service Error"), 1);
+               php_write(buf, size TSRMLS_CC);
+
+               xmlFreeDoc(doc_return);
+               xmlFree(buf);
+
+               zval_dtor(&outbuf);
+               zval_dtor(&outbuflen);
+               zval_dtor(&ret);
+
+               zend_bailout();
+       }
+}
+
+// SoapObject functions
+PHP_FUNCTION(soapobject)
+{
+       char *location, *uri = NULL;
+       int location_len, uri_len = 0;
+       zval *thisObj;
+
+       GET_THIS_OBJECT(thisObj);
+
+       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &location, &location_len, &uri, &uri_len) == SUCCESS)
+       {
+               if(uri)
+               {
+                       // if two parameters assume 'proxy' and 'uri'
+                       add_property_stringl(thisObj, "location", location, location_len, 1);
+                       add_property_stringl(thisObj, "uri", uri, uri_len, 1);
+               }
+               else
+               {
+                       // if one parameter assume 'wsdl'
+                       sdlPtr sdl;
+                       int ret;
+
+                       sdl = get_sdl(location);
+                       ret = zend_list_insert(sdl, le_sdl);
+                       add_property_resource(thisObj, "sdl", ret);
+                       zend_list_addref(ret);
+               }
+       }
+}
+
+PHP_FUNCTION(__parse)
+{
+       char *message, *function;
+       int message_len, function_len;
+       int num_params;
+       zval **ret_params;
+       sdlPtr sdl;
+       sdlFunctionPtr fn;
+
+       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &message, &message_len, &function, &function_len) == FAILURE)
+               php_error(E_ERROR, "Invalid arguments to SoapObject->__parse");
+
+       FETCH_THIS_SDL(sdl);
+
+       if(sdl != NULL)
+       {
+               fn = get_function(sdl, function);
+               if(fn != NULL)
+                       parse_packet_soap(getThis(), message, message_len, fn, NULL, &ret_params, &num_params);
+       }
+       else
+                       parse_packet_soap(getThis(), message, message_len, NULL, function, &ret_params, &num_params);
+
+       if(num_params > 0)
+       {
+               *return_value = *ret_params[0];
+               zval_add_ref(&return_value);
+               efree(ret_params);
+       }
+       else
+               ZVAL_NULL(return_value)
+}
+
+PHP_FUNCTION(__call)
+{
+       char *function, *soap_action, *uri;
+       int function_len, soap_action_len, uri_len, i = 0;
+       zval *args;
+       zval **real_args;
+       zval **param;
+       xmlDocPtr request = NULL;
+       int num_params, arg_count;
+       zval **ret_params;
+       char *buffer;
+       int len;
+
+       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|ss",
+               &function, &function_len, &args, &soap_action, &soap_action_len, &uri, &uri_len) == FAILURE)
+               php_error(E_ERROR, "Invalid arguments to SoapObject->__call");
+
+       arg_count = zend_hash_num_elements(Z_ARRVAL_P(args));
+
+       real_args = emalloc(sizeof(zval *) * arg_count);
+       for(zend_hash_internal_pointer_reset(Z_ARRVAL_P(args));
+               zend_hash_get_current_data(Z_ARRVAL_P(args), (void **) &param) == SUCCESS;
+               zend_hash_move_forward(Z_ARRVAL_P(args)))
+       {
+                       zval_add_ref(param);
+                       real_args[i++] = *param;
+       }
+
+       request = seralize_function_call(NULL, uri, function, real_args, arg_count);
+       send_http_soap_request(getThis(), request, function, soap_action);
+       xmlFreeDoc(request);
+
+       get_http_soap_response(getThis(), &buffer, &len);
+       parse_packet_soap(getThis(), buffer, len, NULL, function, &ret_params, &num_params);
+       efree(buffer);
+
+       if(num_params > 0)
+       {
+               *return_value = *ret_params[0];
+               zval_add_ref(&return_value);
+               efree(ret_params);
+       }
+       else
+               ZVAL_NULL(return_value)
+}
+
+PHP_FUNCTION(__isfault)
+{
+       zval *thisObj;
+
+       GET_THIS_OBJECT(thisObj);
+
+       if(zend_hash_exists(Z_OBJPROP_P(thisObj), "__soap_fault", sizeof("__soap_fault")) == SUCCESS)
+               RETURN_TRUE
+       else
+               RETURN_FALSE
+}
+
+PHP_FUNCTION(__getfault)
+{
+       zval *thisObj;
+       zval **tmp;
+
+       GET_THIS_OBJECT(thisObj);
+
+       if(zend_hash_find(Z_OBJPROP_P(thisObj), "__soap_fault", sizeof("__soap_fault"), (void **)&tmp) == SUCCESS)
+       {
+               *return_value = *(*tmp);
+               zval_copy_ctor(return_value);
+               return;
+       }
+       RETURN_NULL();
+}
+
+#ifdef PHP_DEBUG
+PHP_FUNCTION(__getfunctions)
+{
+       sdlPtr sdl;
+       zval *thisObj;
+
+       GET_THIS_OBJECT(thisObj);
+
+       FETCH_THIS_SDL(sdl);
+
+       if(sdl)
+       {
+               smart_str buf = {0};
+               sdlFunctionPtr *function;
+
+               array_init(return_value);
+               zend_hash_internal_pointer_reset(sdl->functions);
+               while(zend_hash_get_current_data(sdl->functions, (void **)&function) != FAILURE)
+               {
+                       function_to_string((*function), &buf);
+                       add_next_index_stringl(return_value, buf.c, buf.len, 1);
+                       zend_hash_move_forward(sdl->functions);
+                       smart_str_free(&buf);
+               }
+       }
+}
+
+PHP_FUNCTION(__gettypes)
+{
+       sdlPtr sdl;
+       zval *thisObj;
+
+       GET_THIS_OBJECT(thisObj);
+
+       FETCH_THIS_SDL(sdl);
+
+       if(sdl)
+       {
+               sdlTypePtr *type;
+               smart_str buf = {0};
+
+               array_init(return_value);
+               if(sdl->types)
+               {
+                       zend_hash_internal_pointer_reset(sdl->types);
+                       while(zend_hash_get_current_data(sdl->types, (void **)&type) != FAILURE)
+                       {
+                               type_to_string((*type), &buf, 0);
+                               add_next_index_stringl(return_value, buf.c, buf.len, 1);
+                               zend_hash_move_forward(sdl->types);
+                               smart_str_free(&buf);
+                       }
+               }
+       }
+}
+
+PHP_FUNCTION(__getlastrequest)
+{
+       zval *thisObj;
+       zval **tmp;
+
+       GET_THIS_OBJECT(thisObj);
+
+       if(zend_hash_find(Z_OBJPROP_P(thisObj), "__last_request", sizeof("__last_request"), (void **)&tmp) == SUCCESS)
+       {
+               *return_value = *(*tmp);
+               zval_copy_ctor(return_value);
+               return;
+       }
+       RETURN_NULL();
+}
+
+PHP_FUNCTION(__getlastresponse)
+{
+       zval *thisObj;
+       zval **tmp;
+
+       GET_THIS_OBJECT(thisObj);
+
+       if(zend_hash_find(Z_OBJPROP_P(thisObj), "__last_response", sizeof("__last_response"), (void **)&tmp) == SUCCESS)
+       {
+               *return_value = *(*tmp);
+               zval_copy_ctor(return_value);
+               return;
+       }
+       RETURN_NULL();
+}
+#endif
+
+
+void soap_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference)
+{
+       pval *object = property_reference->object;
+       zend_overloaded_element *function_name = (zend_overloaded_element *)property_reference->elements_list->tail->data;
+       zval *thisObj;
+       char *function = Z_STRVAL(function_name->element);
+       zend_function *builtin_function;
+
+       GET_THIS_OBJECT(thisObj);
+
+       //Find if the function being called is already defined...
+       //  ( IMHO: zend should handle this functionality )
+       if(zend_hash_find(&Z_OBJCE_P(thisObj)->function_table, function, Z_STRLEN(function_name->element) + 1, (void **) &builtin_function) == SUCCESS)
+       {
+               builtin_function->internal_function.handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+       }
+       else
+       {
+               zval **arguments = (zval **) emalloc(sizeof(zval *) * ZEND_NUM_ARGS());
+               int arg_count = ZEND_NUM_ARGS();
+               xmlDocPtr request = NULL;
+               sdlPtr sdl;
+               sdlFunctionPtr fn;
+
+               zend_get_parameters_array(ht, arg_count, arguments);
+
+               FETCH_THIS_SDL(sdl);
+
+               clear_soap_fault(thisObj);
+
+               if(sdl != NULL)
+               {
+                       fn = get_function(sdl, function);
+                       if(fn != NULL)
+                       {
+                               int num_params;
+                               zval **ret_params;
+                               char *buffer;
+                               int len;
+
+                               request = seralize_function_call(fn, sdl->target_ns, NULL, arguments, arg_count);
+
+                               send_http_soap_request(getThis(), request, fn->soapAction, fn->soapAction);
+
+                               xmlFreeDoc(request);
+
+                               get_http_soap_response(getThis(), &buffer, &len);
+                               parse_packet_soap(getThis(), buffer, len, fn, NULL, &ret_params, &num_params);
+                               efree(buffer);
+
+                               if(num_params > 0)
+                               {
+                                       *return_value = *ret_params[0];
+                                       zval_add_ref(&return_value);
+                                       efree(ret_params);
+                               }
+                               else
+                                       ZVAL_NULL(return_value);
+                       }
+                       else
+                       {
+                               php_error(E_WARNING,"Function (\"%s\") not is not a valid method for this service", function);
+                       }
+               }
+               else
+               {
+                       int num_params;
+                       zval **ret_params;
+                       zval **uri;
+                       smart_str *action;
+                       char *buffer;
+                       int len;
+
+                       if(zend_hash_find(Z_OBJPROP_P(thisObj), "uri", sizeof("uri"), (void *)&uri) == FAILURE)
+                               php_error(E_ERROR, "Error finding uri in soap_call_function_handler");
+
+                       request = seralize_function_call(NULL, Z_STRVAL_PP(uri), function, arguments, arg_count);
+                       action = build_soap_action(thisObj, function);
+                       send_http_soap_request(getThis(), request, function, action->c);
+
+                       smart_str_free(action);
+                       xmlFreeDoc(request);
+
+                       get_http_soap_response(getThis(), &buffer, &len);
+                       parse_packet_soap(getThis(), buffer, len, NULL, function, &ret_params, &num_params);
+                       efree(buffer);
+
+                       if(num_params > 0)
+                       {
+                               *return_value = *ret_params[0];
+                               zval_add_ref(&return_value);
+                               efree(ret_params);
+                       }
+                       else
+                               ZVAL_NULL(return_value);
+               }
+               efree(arguments);
+       }
+
+       zval_dtor(&function_name->element);
+}
+
+void clear_soap_fault(zval *obj)
+{
+       if(obj != NULL && obj->type == IS_OBJECT)
+               zend_hash_del(obj->value.obj.properties, "__soap_fault", sizeof("__soap_fault"));
+}
+
+void add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail)
+{
+       zval *fault;
+       MAKE_STD_ZVAL(fault);
+       set_soap_fault(fault, fault_string, fault_code, fault_actor, fault_detail);
+       add_property_zval(obj, "__soap_fault", fault);
+}
+
+void set_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail)
+{
+       TSRMLS_FETCH();
+
+       if(Z_TYPE_P(obj) != IS_OBJECT)
+               object_init_ex(obj, &soap_fault_class_entry);
+
+       if(fault_string != NULL)
+               add_property_string(obj, "faultstring", fault_string, 1);
+
+       if(fault_code != NULL)
+               add_property_string(obj, "faultcode", fault_code, 1);
+
+       if(fault_actor != NULL)
+               add_property_string(obj, "faultactor", fault_actor, 1);
+
+       if(fault_detail != NULL)
+       {
+               zval_add_ref(&fault_detail);
+               add_property_zval(obj, "detail", fault_detail);
+       }
+}
+
+void deseralize_function_call(sdlPtr sdl, xmlDocPtr request, zval *function_name, int *num_params, zval ***parameters)
+{
+       xmlNodePtr trav,trav2,trav3,trav4,env,body;
+       int cur_param = 0,num_of_params = 0;
+       TSRMLS_FETCH();
+
+       trav = request->children;
+       FOREACHNODE(trav,"Envelope",env)
+       {
+               trav2 = env->children;
+               FOREACHNODE(trav2,"Body",body)
+               {
+                       trav3 = body->children;
+                       do
+                       {
+                               // TODO: make 'strict' (use th sdl defnintions)
+                               if(trav3->type == XML_ELEMENT_NODE)
+                               {
+                                       zval tmp_function_name, **tmp_parameters;
+                                       sdlFunctionPtr function;
+
+                                       INIT_ZVAL(tmp_function_name);
+                                       ZVAL_STRING(&tmp_function_name, (char *)trav3->name, 1);
+
+                                       (*function_name) = tmp_function_name;
+
+                                       function = get_function(sdl, php_strtolower((char *)trav3->name, strlen(trav3->name)));
+                                       if(sdl != NULL && function == NULL)
+                                               php_error(E_ERROR, "Error function \"%s\" doesn't exists for this service \"%s\"", trav3->name, sdl->location);
+
+                                       if(trav3->children)
+                                       {
+                                               trav4 = trav3->children;
+                                               if(function == NULL)
+                                               {
+                                                       do
+                                                       {
+                                                               if(trav4->type == XML_ELEMENT_NODE)
+                                                                       num_of_params++;
+
+                                                       }while(trav4 = trav4->next);
+                                               }
+                                               else
+                                                       num_of_params = zend_hash_num_elements(function->requestParameters);
+
+                                               tmp_parameters = emalloc(num_of_params * sizeof(zval *));
+                                               trav4 = trav3->children;
+                                               do
+                                               {
+                                                       if(trav4->type == XML_ELEMENT_NODE)
+                                                       {
+                                                               encodePtr enc;
+                                                               sdlParamPtr *param = NULL;
+
+                                                               if(function != NULL && zend_hash_index_find(function->requestParameters, cur_param, (void **)&param) == FAILURE)
+                                                                       php_error(E_ERROR, "Error cannot find parameter");
+                                                               if(param == NULL)
+                                                                       enc = get_conversion(UNKNOWN_TYPE);
+                                                               else
+                                                                       enc = (*param)->encode;
+
+                                                               tmp_parameters[cur_param] = master_to_zval(enc, trav4);
+                                                               cur_param++;
+                                                       }
+
+                                               }while(trav4 = trav4->next);
+                                       }
+                                       (*parameters) = tmp_parameters;
+                                       (*num_params) = num_of_params;
+                                       break;
+                               }
+                       }while(trav3 = trav3->next);
+
+               }
+               ENDFOREACH(trav2);
+       }
+       ENDFOREACH(trav);
+}
+
+
+
+xmlDocPtr seralize_response_call(sdlFunctionPtr function, char *function_name, char *uri, zval *ret)
+{
+       xmlDoc *doc;
+       xmlNode *envelope,*body,*method, *param;
+       xmlNs *ns;
+       sdlParamPtr parameter = NULL;
+       smart_str *gen_ns;
+
+       encode_reset_ns();
+
+       doc = xmlNewDoc("1.0");
+       doc->charset = XML_CHAR_ENCODING_UTF8;
+       doc->encoding = xmlStrdup((xmlChar*)"UTF-8");
+       doc->children = xmlNewDocNode(doc, NULL, "SOAP-ENV:Envelope", NULL);
+       envelope = doc->children;
+
+       xmlSetProp(envelope, "SOAP-ENV:encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/");
+       xmlSetProp(envelope, "xmlns:SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/");
+       xmlSetProp(envelope, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+       xmlSetProp(envelope, "xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
+       xmlSetProp(envelope, "xmlns:" APACHE_NS_PREFIX , APACHE_NAMESPACE);
+
+       ns = xmlNewNs(envelope,"http://schemas.xmlsoap.org/soap/envelope/","SOAP-ENV");
+       body = xmlNewChild(envelope, ns, "Body", NULL);
+
+       if(Z_TYPE_P(ret) == IS_OBJECT &&
+               Z_OBJCE_P(ret)->refcount == soap_var_class_entry.refcount)
+       {
+               param = seralize_zval(ret, NULL, "SOAP-ENV:Fault");
+               xmlAddChild(body, param);
+       }
+       else
+       {
+               gen_ns = encode_new_ns();
+               ns = xmlNewNs(envelope, uri, gen_ns->c);
+
+               if(function != NULL)
+                       method = xmlNewChild(body, ns, function->responseName , NULL);
+               else
+                       method = xmlNewChild(body, ns, function_name, NULL);
+
+               if(uri)
+                       ns = xmlNewNs(method, uri, NULL);
+
+               parameter = get_param(function, NULL, 0, TRUE);
+
+               if(Z_TYPE_P(ret) == IS_OBJECT &&
+                       Z_OBJCE_P(ret)->refcount == soap_param_class_entry.refcount)
+               {
+                       zval **ret_name;
+                       zval **ret_data;
+
+                       if(zend_hash_find(Z_OBJPROP_P(ret), "param_name", sizeof("param_name"), (void **)&ret_name) == SUCCESS &&
+                               zend_hash_find(Z_OBJPROP_P(ret), "param_data", sizeof("param_data"), (void **)&ret_data) == SUCCESS)
+                               param = seralize_parameter(parameter, *ret_data, 0, Z_STRVAL_PP(ret_name));
+                       else
+                               param = seralize_parameter(parameter, ret, 0, "return");
+               }
+               else
+                       param = seralize_parameter(parameter, ret, 0, "return");
+
+               xmlAddChild(method,param);
+       }
+
+       return doc;
+}
+
+xmlDocPtr seralize_function_call(sdlFunctionPtr function, char *uri, char *function_name, zval **arguments, int arg_count)
+{
+       xmlDoc *doc;
+       xmlNode *envelope,*body,*method;
+       xmlNs *ns;
+       int i;
+       smart_str *gen_ns;
+
+       encode_reset_ns();
+
+       doc = xmlNewDoc("1.0");
+       doc->encoding = xmlStrdup((xmlChar*)"UTF-8");
+       doc->charset = XML_CHAR_ENCODING_UTF8;
+       envelope = xmlNewDocNode(doc, NULL, "SOAP-ENV:Envelope", NULL);
+       xmlDocSetRootElement(doc, envelope);
+       xmlSetProp(envelope, "SOAP-ENV:encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/");
+       xmlSetProp(envelope, "xmlns:SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/");
+       xmlSetProp(envelope, "xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
+       xmlSetProp(envelope, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+       ns = xmlNewNs(envelope,"http://schemas.xmlsoap.org/soap/envelope/","SOAP-ENV");
+       body = xmlNewChild(envelope, ns, "Body", NULL);
+
+       gen_ns = encode_new_ns();
+       ns = xmlNewNs(envelope, uri, gen_ns->c);
+
+       if(function != NULL)
+               method = xmlNewChild(body, ns, function->requestName , NULL);
+       else
+               method = xmlNewChild(body, ns, function_name , NULL);
+
+       ns = xmlNewNs(method, uri, NULL);
+
+       for(i = 0;i < arg_count;i++)
+       {
+               xmlNodePtr param;
+               sdlParamPtr parameter = get_param(function, NULL, i, FALSE);
+
+               if(Z_TYPE_P(arguments[i]) == IS_OBJECT &&
+                       Z_OBJCE_P(arguments[i])->refcount == soap_param_class_entry.refcount)
+               {
+                       zval **ret_name;
+                       zval **ret_data;
+
+                       if(zend_hash_find(Z_OBJPROP_P(arguments[i]), "param_name", sizeof("param_name"), (void **)&ret_name) == SUCCESS &&
+                               zend_hash_find(Z_OBJPROP_P(arguments[i]), "param_data", sizeof("param_data"), (void **)&ret_data) == SUCCESS)
+                               param = seralize_parameter(parameter, *ret_data, i, Z_STRVAL_PP(ret_name));
+                       else
+                               param = seralize_parameter(parameter, arguments[i], i, NULL);
+               }
+               else
+                       param = seralize_parameter(parameter, arguments[i], i, NULL);
+               xmlAddChild(method,param);
+       }
+
+       return doc;
+}
+
+xmlNodePtr seralize_parameter(sdlParamPtr param, zval *param_val, int index, char *name)
+{
+       int type = 0;
+       char *paramName;
+       xmlNodePtr xmlParam;
+
+       if(param != NULL && param->paramName != NULL)
+       {
+               paramName = estrdup(param->paramName);
+       }
+       else
+       {
+               if(name == NULL)
+               {
+                       paramName = emalloc(10);
+                       sprintf(paramName,"param%d",index);
+               }
+               else
+                       paramName = estrdup(name);
+       }
+
+       xmlParam = seralize_zval(param_val, param, paramName);
+
+       efree(paramName);
+
+       return xmlParam;
+}
+
+zval *desearlize_zval(sdlPtr sdl, xmlNodePtr data, sdlParamPtr param)
+{
+       encodePtr enc;
+       TSRMLS_FETCH();
+
+       if(param != NULL)
+               enc = param->encode;
+       else
+               enc = get_conversion(UNKNOWN_TYPE);
+
+       return enc->to_zval(enc->details, data);
+}
+
+xmlNodePtr seralize_zval(zval *val, sdlParamPtr param, char *paramName)
+{
+       xmlNodePtr xmlParam;
+       encodePtr enc;
+       TSRMLS_FETCH();
+
+       if(param != NULL)
+               enc = param->encode;
+       else
+               enc = get_conversion(val->type);
+
+       xmlParam = master_to_xml(enc, val);
+       xmlNodeSetName(xmlParam, paramName);
+
+       return xmlParam;
+}
+
+sdlParamPtr get_param(sdlFunctionPtr function, char *param_name, int index, int response)
+{
+       sdlParamPtr *tmp = NULL;
+       HashTable *h;
+
+       if(function == NULL)
+               return NULL;
+
+       if(response == FALSE)
+               h = function->requestParameters;
+       else
+               h = function->responseParameters;
+
+       if (function != NULL && (param_name == NULL || zend_hash_find(h, param_name, strlen(param_name), (void **)&tmp) == FAILURE))
+       {
+               if(index != -1)
+                       if(zend_hash_index_find(h, index, (void **)&tmp) != FAILURE)
+                               return (*tmp);
+       }
+       else
+               return (*tmp);
+
+       return NULL;
+}
+
+sdlFunctionPtr get_function(sdlPtr sdl, char *function_name)
+{
+       sdlFunctionPtr *tmp;
+       if(sdl != NULL)
+               if(zend_hash_find(sdl->functions, function_name, strlen(function_name), (void **)&tmp) != FAILURE)
+                       return (*tmp);
+       return NULL;
+}
+
+static void function_to_string(sdlFunctionPtr function, smart_str *buf)
+{
+       int i = 0;
+
+       if(function->responseParameters)
+       {
+               sdlParamPtr *param;
+               param = function->responseParameters->pListHead->pData;
+               smart_str_appendl(buf, (*param)->encode->details.type_str, strlen((*param)->encode->details.type_str));
+               smart_str_appendc(buf, ' ');
+       }
+       else
+               smart_str_appendl(buf, "void ", 5);
+
+       smart_str_appendl(buf, function->functionName, strlen(function->functionName));
+
+       smart_str_appendc(buf, '(');
+       if(function->requestParameters)
+       {
+               sdlParamPtr *param;
+
+               i = 0;
+               zend_hash_internal_pointer_reset(function->requestParameters);
+               while(zend_hash_get_current_data(function->requestParameters, (void **)&param) != FAILURE)
+               {
+                       smart_str_appendl(buf, (*param)->encode->details.type_str, strlen((*param)->encode->details.type_str));
+                       smart_str_appendc(buf, ' ');
+                       smart_str_appendc(buf, '$');
+                       smart_str_appendl(buf, (*param)->paramName, strlen((*param)->paramName));
+                       if(zend_hash_num_elements(function->requestParameters) > i + 1)
+                               smart_str_appendl(buf, ", ", 2);
+                       zend_hash_move_forward(function->requestParameters);
+                       i++;
+               }
+       }
+       smart_str_appendc(buf, ')');
+}
+
+static void type_to_string(sdlTypePtr type, smart_str *buf, int level)
+{
+       int i;
+       smart_str spaces = {0};
+
+       for(i = 0;i < level;i++)
+               smart_str_appendc(&spaces, ' ');
+
+       smart_str_appendl(buf, spaces.c, spaces.len);
+       if(type->elements)
+       {
+               sdlTypePtr *t_type;
+
+               smart_str_appendl(buf, "struct ", 7);
+               smart_str_appendl(buf, type->name, strlen(type->name));
+               smart_str_appendc(buf, '\n');
+               smart_str_appendl(buf, spaces.c, spaces.len);
+               smart_str_appendl(buf, "{\n", 2);
+
+               zend_hash_internal_pointer_reset(type->elements);
+               level++;
+               while(zend_hash_get_current_data(type->elements, (void **)&t_type) != FAILURE)
+               {
+                       type_to_string((*t_type), buf, level);
+                       zend_hash_move_forward(type->elements);
+               }
+
+               smart_str_appendl(buf, spaces.c, spaces.len);
+               smart_str_appendl(buf, "}\n", 2);
+       }
+       else
+       {
+               smart_str_appendl(buf, type->encode->details.type_str, strlen(type->encode->details.type_str));
+               smart_str_appendc(buf, ' ');
+               smart_str_appendl(buf, type->name, strlen(type->name));
+               smart_str_appendl(buf, ";\n", 2);
+       }
+}
+
+//Deletes
+void delete_sdl(void *handle)
+{
+       sdlPtr tmp = *((sdlPtr*)handle);
+
+       xmlFreeDoc(tmp->doc);
+       if(tmp->source)
+               free(tmp->source);
+       if(tmp->target_ns)
+               free(tmp->target_ns);
+       if(tmp->location)
+               free(tmp->location);
+       if(tmp->encoders)
+       {
+               zend_hash_destroy(tmp->encoders);
+               free(tmp->encoders);
+       }
+       if(tmp->types)
+       {
+               zend_hash_destroy(tmp->types);
+               free(tmp->types);
+       }
+       if(tmp->functions)
+       {
+               zend_hash_destroy(tmp->functions);
+               free(tmp->functions);
+       }
+       free(tmp);
+}
+
+void delete_http_socket(void *handle)
+{
+       SOAP_STREAM stream = (SOAP_STREAM)handle;
+#ifdef PHP_STREAMS
+       TSRMLS_FETCH();
+       php_stream_close(stream);
+#else
+       close(stream);
+#endif
+}
+
+void delete_url(void *handle)
+{
+       php_url_free((php_url*)handle);
+}
+
+void delete_service(void *data)
+{
+       soapServicePtr service = (soapServicePtr)data;
+
+       if(service->soap_functions.ft)
+       {
+               zend_hash_destroy(service->soap_functions.ft);
+               efree(service->soap_functions.ft);
+       }
+
+       if(service->mapping)
+       {
+               zend_hash_destroy(service->mapping);
+               efree(service->mapping);
+       }
+
+       if(service->soap_class.argc)
+       {
+               int i;
+               for(i = 0; i < service->soap_class.argc;i++)
+                       zval_ptr_dtor(&service->soap_class.argv[i]);
+               efree(service->soap_class.argv);
+       }
+
+       efree(service->uri);
+       efree(service);
+}
+
+void delete_function(void *data)
+{
+       sdlFunctionPtr function = *((sdlFunctionPtr*)data);
+
+       if(function->functionName)
+               free(function->functionName);
+       if(function->requestName)
+               free(function->requestName);
+       if(function->responseName)
+               free(function->responseName);
+       if(function->soapAction)
+               free(function->soapAction);
+
+       if(function->requestParameters)
+       {
+               zend_hash_destroy(function->requestParameters);
+               free(function->requestParameters);
+       }
+       if(function->responseParameters)
+       {
+               zend_hash_destroy(function->responseParameters);
+               free(function->responseParameters);
+       }
+}
+
+void delete_paramater(void *data)
+{
+       sdlParamPtr param = *((sdlParamPtr*)data);
+       if(param->paramName)
+               free(param->paramName);
+       free(param);
+}
+
+void delete_mapping(void *data)
+{
+       soapMappingPtr map = (soapMappingPtr)data;
+
+       if(map->ns)
+               efree(map->ns);
+       if(map->ctype)
+               efree(map->ctype);
+
+       if(map->type == SOAP_MAP_FUNCTION)
+       {
+               if(map->map_functions.to_xml_before)
+                       zval_ptr_dtor(&map->map_functions.to_xml_before);
+               if(map->map_functions.to_xml)
+                       zval_ptr_dtor(&map->map_functions.to_xml);
+               if(map->map_functions.to_xml_after)
+                       zval_ptr_dtor(&map->map_functions.to_xml_after);
+
+               if(map->map_functions.to_zval_before)
+                       zval_ptr_dtor(&map->map_functions.to_zval_before);
+               if(map->map_functions.to_zval)
+                       zval_ptr_dtor(&map->map_functions.to_zval);
+               if(map->map_functions.to_zval_after)
+                       zval_ptr_dtor(&map->map_functions.to_zval_after);
+       }
+       efree(map);
+}
+
+// Should not need
+int my_call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, int param_count, zval *params[] TSRMLS_DC)
+{
+       if(call_user_function(function_table, object_pp, function_name, retval_ptr, param_count, params TSRMLS_CC) == FAILURE)
+       {
+               if(Z_OBJCE_PP(object_pp)->handle_function_call != NULL)
+               {
+                       zend_overloaded_element overloaded_element;
+                       zend_property_reference property_reference;
+                       zend_function_state function_state;
+                       zend_function_state *original_function_state_ptr;
+                       int i;
+
+                       overloaded_element.element = *function_name;
+                       overloaded_element.type = OE_IS_METHOD;
+
+                       function_state.function = (zend_function *) emalloc(sizeof(zend_function));
+                       function_state.function->type = ZEND_OVERLOADED_FUNCTION;
+                       function_state.function->common.arg_types = NULL;
+                       function_state.function->overloaded_function.function_name = Z_STRVAL_P(function_name);
+
+                       property_reference.object = *object_pp;
+                       property_reference.type = BP_VAR_NA;
+                       property_reference.elements_list = (zend_llist *)emalloc(sizeof(zend_llist));
+                       zend_llist_init(property_reference.elements_list, sizeof(zend_overloaded_element), NULL, 0);
+                       zend_llist_add_element(property_reference.elements_list, &overloaded_element);
+
+                       //Build argument stack
+                       for(i = 0;i < param_count;i++)
+                               zend_ptr_stack_push(&EG(argument_stack), params[i]);
+                       zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *)param_count, NULL);
+
+                       original_function_state_ptr = EG(function_state_ptr);
+                       EG(function_state_ptr) = &function_state;
+                       Z_OBJCE_PP(object_pp)->handle_function_call(param_count, retval_ptr, *object_pp, 1 TSRMLS_CC, &property_reference);
+                       EG(function_state_ptr) = original_function_state_ptr;
+
+                       zend_llist_destroy(property_reference.elements_list);
+                       efree(property_reference.elements_list);
+                       efree(function_state.function);
+
+                       zend_ptr_stack_clear_multiple(TSRMLS_C);
+                       return SUCCESS;
+               }
+       }
+       return FAILURE;
+}
+
+