summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShane Caraveo <shane@php.net>2002-07-07 23:03:43 +0000
committerShane Caraveo <shane@php.net>2002-07-07 23:03:43 +0000
commitf8875adaab9fe973ab798ead093e21972ed43a13 (patch)
treed5495bb982d966a5bb42afb20fb80338cccce1f4
parenta6d815fb7c98c32a4180e30dfaca316cbeae8912 (diff)
downloadphp-git-f8875adaab9fe973ab798ead093e21972ed43a13.tar.gz
import php-soap library from sourceforge
-rw-r--r--ext/soap/EXPERIMENTAL0
-rw-r--r--ext/soap/Makefile13
-rw-r--r--ext/soap/Makefile.in8
-rw-r--r--ext/soap/TODO36
-rw-r--r--ext/soap/config.m416
-rw-r--r--ext/soap/libs.mk7
-rw-r--r--ext/soap/package.xml54
-rw-r--r--ext/soap/php_encoding.c1085
-rw-r--r--ext/soap/php_encoding.h248
-rw-r--r--ext/soap/php_http.c495
-rw-r--r--ext/soap/php_http.h25
-rw-r--r--ext/soap/php_packet_soap.c124
-rw-r--r--ext/soap/php_packet_soap.h6
-rw-r--r--ext/soap/php_schema.c1047
-rw-r--r--ext/soap/php_schema.h28
-rw-r--r--ext/soap/php_sdl.c915
-rw-r--r--ext/soap/php_sdl.h112
-rw-r--r--ext/soap/php_soap.dsp156
-rw-r--r--ext/soap/php_soap.h375
-rw-r--r--ext/soap/php_xml.c214
-rw-r--r--ext/soap/php_xml.h23
-rw-r--r--ext/soap/soap.c2037
22 files changed, 7024 insertions, 0 deletions
diff --git a/ext/soap/EXPERIMENTAL b/ext/soap/EXPERIMENTAL
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/ext/soap/EXPERIMENTAL
diff --git a/ext/soap/Makefile b/ext/soap/Makefile
new file mode 100644
index 0000000000..1107a700bd
--- /dev/null
+++ b/ext/soap/Makefile
@@ -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
index 0000000000..eb52167d2d
--- /dev/null
+++ b/ext/soap/Makefile.in
@@ -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
index 0000000000..b70760add7
--- /dev/null
+++ b/ext/soap/TODO
@@ -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
index 0000000000..44c12cb037
--- /dev/null
+++ b/ext/soap/config.m4
@@ -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
index 0000000000..7c6e176717
--- /dev/null
+++ b/ext/soap/libs.mk
@@ -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
index 0000000000..2299be5468
--- /dev/null
+++ b/ext/soap/package.xml
@@ -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
index 0000000000..55e4e4f4f4
--- /dev/null
+++ b/ext/soap/php_encoding.c
@@ -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
index 0000000000..7e422dcf9e
--- /dev/null
+++ b/ext/soap/php_encoding.h
@@ -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
index 0000000000..73c60a3e05
--- /dev/null
+++ b/ext/soap/php_http.c
@@ -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
index 0000000000..4e4fff7f4d
--- /dev/null
+++ b/ext/soap/php_http.h
@@ -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
index 0000000000..3414f970eb
--- /dev/null
+++ b/ext/soap/php_packet_soap.c
@@ -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
index 0000000000..0d094269da
--- /dev/null
+++ b/ext/soap/php_packet_soap.h
@@ -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
index 0000000000..020b299d47
--- /dev/null
+++ b/ext/soap/php_schema.c
@@ -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
index 0000000000..c43a221608
--- /dev/null
+++ b/ext/soap/php_schema.h
@@ -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
index 0000000000..9d73d2fbe8
--- /dev/null
+++ b/ext/soap/php_sdl.c
@@ -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
index 0000000000..66a2520bfb
--- /dev/null
+++ b/ext/soap/php_sdl.h
@@ -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
index 0000000000..7ee12777e1
--- /dev/null
+++ b/ext/soap/php_soap.dsp
@@ -0,0 +1,156 @@
+# Microsoft Developer Studio Project File - Name="php_soap" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=php_soap - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "php_soap.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "php_soap.mak" CFG="php_soap - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "php_soap - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "php_soap - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "php_soap - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# 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
+# 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
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# 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
+# 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"
+
+!ELSEIF "$(CFG)" == "php_soap - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# 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
+# 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
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# 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
+# 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"
+# SUBTRACT LINK32 /pdb:none /incremental:no
+
+!ENDIF
+
+# Begin Target
+
+# Name "php_soap - Win32 Release"
+# Name "php_soap - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\php_encoding.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_http.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_packet_soap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_schema.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_sdl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_xml.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\soap.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\php_encoding.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_http.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_packet_soap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_schema.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_sdl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_soap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_xml.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/ext/soap/php_soap.h b/ext/soap/php_soap.h
new file mode 100644
index 0000000000..98c9e57f35
--- /dev/null
+++ b/ext/soap/php_soap.h
@@ -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
index 0000000000..707d073984
--- /dev/null
+++ b/ext/soap/php_xml.c
@@ -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
index 0000000000..d17caba007
--- /dev/null
+++ b/ext/soap/php_xml.h
@@ -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
index 0000000000..fbc889a81b
--- /dev/null
+++ b/ext/soap/soap.c
@@ -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;
+}
+
+