Back to index

php5  5.3.10
php_encoding.c
Go to the documentation of this file.
00001 /*
00002   +----------------------------------------------------------------------+
00003   | PHP Version 5                                                        |
00004   +----------------------------------------------------------------------+
00005   | Copyright (c) 1997-2012 The PHP Group                                |
00006   +----------------------------------------------------------------------+
00007   | This source file is subject to version 3.01 of the PHP license,      |
00008   | that is bundled with this package in the file LICENSE, and is        |
00009   | available through the world-wide-web at the following url:           |
00010   | http://www.php.net/license/3_01.txt                                  |
00011   | If you did not receive a copy of the PHP license and are unable to   |
00012   | obtain it through the world-wide-web, please send a note to          |
00013   | license@php.net so we can mail you a copy immediately.               |
00014   +----------------------------------------------------------------------+
00015   | Authors: Brad Lafountain <rodif_bl@yahoo.com>                        |
00016   |          Shane Caraveo <shane@caraveo.com>                           |
00017   |          Dmitry Stogov <dmitry@zend.com>                             |
00018   +----------------------------------------------------------------------+
00019 */
00020 /* $Id: php_encoding.c 321634 2012-01-01 13:15:04Z felipe $ */
00021 
00022 #include <time.h>
00023 
00024 #include "php_soap.h"
00025 #include "ext/libxml/php_libxml.h"
00026 #include "ext/standard/base64.h"
00027 #include <libxml/parserInternals.h>
00028 #include "zend_strtod.h"
00029 #include "zend_interfaces.h"
00030 
00031 /* zval type decode */
00032 static zval *to_zval_double(encodeTypePtr type, xmlNodePtr data);
00033 static zval *to_zval_long(encodeTypePtr type, xmlNodePtr data);
00034 static zval *to_zval_bool(encodeTypePtr type, xmlNodePtr data);
00035 static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data);
00036 static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data);
00037 static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data);
00038 static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data);
00039 static zval *to_zval_null(encodeTypePtr type, xmlNodePtr data);
00040 static zval *to_zval_base64(encodeTypePtr type, xmlNodePtr data);
00041 static zval *to_zval_hexbin(encodeTypePtr type, xmlNodePtr data);
00042 
00043 static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00044 static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00045 static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00046 
00047 /* String encode */
00048 static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00049 static xmlNodePtr to_xml_base64(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00050 static xmlNodePtr to_xml_hexbin(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00051 
00052 /* Null encode */
00053 static xmlNodePtr to_xml_null(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00054 
00055 /* Array encode */
00056 static xmlNodePtr guess_array_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00057 static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00058 
00059 static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent);
00060 static xmlNodePtr to_xml_list1(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent);
00061 
00062 /* Datetime encode/decode */
00063 static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, int style, xmlNodePtr parent);
00064 static xmlNodePtr to_xml_datetime(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00065 static xmlNodePtr to_xml_time(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00066 static xmlNodePtr to_xml_date(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00067 static xmlNodePtr to_xml_gyearmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00068 static xmlNodePtr to_xml_gyear(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00069 static xmlNodePtr to_xml_gmonthday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00070 static xmlNodePtr to_xml_gday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00071 static xmlNodePtr to_xml_gmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00072 static xmlNodePtr to_xml_duration(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00073 
00074 static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data);
00075 static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data);
00076 
00077 static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00078 static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00079 
00080 static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data);
00081 static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00082 
00083 /* Try and guess for non-wsdl clients and servers */
00084 static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data);
00085 static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
00086 
00087 static int is_map(zval *array);
00088 static encodePtr get_array_type(xmlNodePtr node, zval *array, smart_str *out_type TSRMLS_DC);
00089 
00090 static xmlNodePtr check_and_resolve_href(xmlNodePtr data);
00091 
00092 static void set_ns_prop(xmlNodePtr node, char *ns, char *name, char *val);
00093 static void set_xsi_nil(xmlNodePtr node);
00094 static void set_xsi_type(xmlNodePtr node, char *type);
00095 
00096 static void get_type_str(xmlNodePtr node, const char* ns, const char* type, smart_str* ret);
00097 static void set_ns_and_type_ex(xmlNodePtr node, char *ns, char *type);
00098 
00099 static void set_ns_and_type(xmlNodePtr node, encodeTypePtr type);
00100 
00101 #define FIND_XML_NULL(xml,zval) \
00102        { \
00103               xmlAttrPtr null; \
00104               if (!xml) { \
00105                      ZVAL_NULL(zval); \
00106                      return zval; \
00107               } \
00108               if (xml->properties) { \
00109                      null = get_attribute(xml->properties, "nil"); \
00110                      if (null) { \
00111                             ZVAL_NULL(zval); \
00112                             return zval; \
00113                      } \
00114               } \
00115        }
00116 
00117 #define CHECK_XML_NULL(xml) \
00118        { \
00119               xmlAttrPtr null; \
00120               if (!xml) { \
00121                      zval *ret; \
00122                      ALLOC_INIT_ZVAL(ret); \
00123                      ZVAL_NULL(ret); \
00124                      return ret; \
00125               } \
00126               if (xml->properties) { \
00127                      null = get_attribute(xml->properties, "nil"); \
00128                      if (null) { \
00129                             zval *ret; \
00130                             ALLOC_INIT_ZVAL(ret); \
00131                             ZVAL_NULL(ret); \
00132                             return ret; \
00133                      } \
00134               } \
00135        }
00136 
00137 #define FIND_ZVAL_NULL(zval, xml, style) \
00138 { \
00139        if (!zval || Z_TYPE_P(zval) == IS_NULL) { \
00140          if (style == SOAP_ENCODED) {\
00141                      set_xsi_nil(xml); \
00142               } \
00143               return xml; \
00144        } \
00145 }
00146 
00147 encode defaultEncoding[] = {
00148        {{UNKNOWN_TYPE, NULL, NULL, NULL}, guess_zval_convert, guess_xml_convert},
00149 
00150        {{IS_NULL, "nil", XSI_NAMESPACE, NULL}, to_zval_null, to_xml_null},
00151        {{IS_STRING, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
00152        {{IS_LONG, XSD_INT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00153        {{IS_DOUBLE, XSD_FLOAT_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_double},
00154        {{IS_BOOL, XSD_BOOLEAN_STRING, XSD_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
00155        {{IS_CONSTANT, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
00156        {{IS_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_array, guess_array_map},
00157        {{IS_CONSTANT_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
00158        {{IS_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
00159        {{IS_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_array, guess_array_map},
00160        {{IS_CONSTANT_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
00161        {{IS_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
00162 
00163        {{XSD_STRING, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
00164        {{XSD_BOOLEAN, XSD_BOOLEAN_STRING, XSD_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
00165        {{XSD_DECIMAL, XSD_DECIMAL_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
00166        {{XSD_FLOAT, XSD_FLOAT_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_double},
00167        {{XSD_DOUBLE, XSD_DOUBLE_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_double},
00168 
00169        {{XSD_DATETIME, XSD_DATETIME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_datetime},
00170        {{XSD_TIME, XSD_TIME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_time},
00171        {{XSD_DATE, XSD_DATE_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_date},
00172        {{XSD_GYEARMONTH, XSD_GYEARMONTH_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gyearmonth},
00173        {{XSD_GYEAR, XSD_GYEAR_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gyear},
00174        {{XSD_GMONTHDAY, XSD_GMONTHDAY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gmonthday},
00175        {{XSD_GDAY, XSD_GDAY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gday},
00176        {{XSD_GMONTH, XSD_GMONTH_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gmonth},
00177        {{XSD_DURATION, XSD_DURATION_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_duration},
00178 
00179        {{XSD_HEXBINARY, XSD_HEXBINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_hexbin, to_xml_hexbin},
00180        {{XSD_BASE64BINARY, XSD_BASE64BINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_base64, to_xml_base64},
00181 
00182        {{XSD_LONG, XSD_LONG_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00183        {{XSD_INT, XSD_INT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00184        {{XSD_SHORT, XSD_SHORT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00185        {{XSD_BYTE, XSD_BYTE_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00186        {{XSD_NONPOSITIVEINTEGER, XSD_NONPOSITIVEINTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00187        {{XSD_POSITIVEINTEGER, XSD_POSITIVEINTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00188        {{XSD_NONNEGATIVEINTEGER, XSD_NONNEGATIVEINTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00189        {{XSD_NEGATIVEINTEGER, XSD_NEGATIVEINTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00190        {{XSD_UNSIGNEDBYTE, XSD_UNSIGNEDBYTE_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00191        {{XSD_UNSIGNEDSHORT, XSD_UNSIGNEDSHORT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00192        {{XSD_UNSIGNEDINT, XSD_UNSIGNEDINT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00193        {{XSD_UNSIGNEDLONG, XSD_UNSIGNEDLONG_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00194        {{XSD_INTEGER, XSD_INTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00195 
00196        {{XSD_ANYTYPE, XSD_ANYTYPE_STRING, XSD_NAMESPACE, NULL}, guess_zval_convert, guess_xml_convert},
00197        {{XSD_UR_TYPE, XSD_UR_TYPE_STRING, XSD_NAMESPACE, NULL}, guess_zval_convert, guess_xml_convert},
00198        {{XSD_ANYURI, XSD_ANYURI_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
00199        {{XSD_QNAME, XSD_QNAME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
00200        {{XSD_NOTATION, XSD_NOTATION_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
00201        {{XSD_NORMALIZEDSTRING, XSD_NORMALIZEDSTRING_STRING, XSD_NAMESPACE, NULL}, to_zval_stringr, to_xml_string},
00202        {{XSD_TOKEN, XSD_TOKEN_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
00203        {{XSD_LANGUAGE, XSD_LANGUAGE_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
00204        {{XSD_NMTOKEN, XSD_NMTOKEN_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
00205        {{XSD_NMTOKENS, XSD_NMTOKENS_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_list1},
00206        {{XSD_NAME, XSD_NAME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
00207        {{XSD_NCNAME, XSD_NCNAME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
00208        {{XSD_ID, XSD_ID_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
00209        {{XSD_IDREF, XSD_IDREF_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
00210        {{XSD_IDREFS, XSD_IDREFS_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_list1},
00211        {{XSD_ENTITY, XSD_ENTITY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
00212        {{XSD_ENTITIES, XSD_ENTITIES_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_list1},
00213 
00214        {{APACHE_MAP, APACHE_MAP_STRING, APACHE_NAMESPACE, NULL}, to_zval_map, to_xml_map},
00215 
00216        {{SOAP_ENC_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
00217        {{SOAP_ENC_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
00218        {{SOAP_ENC_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
00219        {{SOAP_ENC_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
00220 
00221        /* support some of the 1999 data types */
00222        {{XSD_STRING, XSD_STRING_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_string, to_xml_string},
00223        {{XSD_BOOLEAN, XSD_BOOLEAN_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
00224        {{XSD_DECIMAL, XSD_DECIMAL_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
00225        {{XSD_FLOAT, XSD_FLOAT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_double, to_xml_double},
00226        {{XSD_DOUBLE, XSD_DOUBLE_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_double, to_xml_double},
00227 
00228        {{XSD_LONG, XSD_LONG_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00229        {{XSD_INT, XSD_INT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00230        {{XSD_SHORT, XSD_SHORT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00231        {{XSD_BYTE, XSD_BYTE_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
00232        {{XSD_1999_TIMEINSTANT, XSD_1999_TIMEINSTANT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
00233 
00234        {{XSD_ANYXML, "<anyXML>", "<anyXML>", NULL}, to_zval_any, to_xml_any},
00235 
00236        {{END_KNOWN_TYPES, NULL, NULL, NULL}, guess_zval_convert, guess_xml_convert}
00237 };
00238 
00239 int numDefaultEncodings = sizeof(defaultEncoding)/sizeof(encode);
00240 
00241 
00242 void whiteSpace_replace(xmlChar* str)
00243 {
00244        while (*str != '\0') {
00245               if (*str == '\x9' || *str == '\xA' || *str == '\xD') {
00246                      *str = ' ';
00247               }
00248               str++;
00249        }
00250 }
00251 
00252 void whiteSpace_collapse(xmlChar* str)
00253 {
00254        xmlChar *pos;
00255        xmlChar old;
00256 
00257        pos = str;
00258        whiteSpace_replace(str);
00259        while (*str == ' ') {
00260               str++;
00261        }
00262        old = '\0';
00263        while (*str != '\0') {
00264               if (*str != ' ' || old != ' ') {
00265                      *pos = *str;
00266                      pos++;
00267               }
00268               old = *str;
00269               str++;
00270        }
00271        if (old == ' ') {
00272               --pos;
00273        }
00274        *pos = '\0';
00275 }
00276 
00277 static encodePtr find_encoder_by_type_name(sdlPtr sdl, const char *type)
00278 {
00279        if (sdl && sdl->encoders) {
00280               HashPosition pos;
00281               encodePtr *enc;
00282 
00283               for (zend_hash_internal_pointer_reset_ex(sdl->encoders, &pos);
00284                    zend_hash_get_current_data_ex(sdl->encoders, (void **) &enc, &pos) == SUCCESS;
00285                    zend_hash_move_forward_ex(sdl->encoders, &pos)) {
00286                   if (strcmp((*enc)->details.type_str, type) == 0) {
00287                             return *enc;
00288                      }
00289               }
00290        }
00291        return NULL;
00292 }
00293 
00294 static zend_bool soap_check_zval_ref(zval *data, xmlNodePtr node TSRMLS_DC) {
00295        xmlNodePtr *node_ptr;
00296 
00297        if (SOAP_GLOBAL(ref_map)) {
00298               if (Z_TYPE_P(data) == IS_OBJECT) {
00299                      data = (zval*)zend_objects_get_address(data TSRMLS_CC);
00300               }
00301               if (zend_hash_index_find(SOAP_GLOBAL(ref_map), (ulong)data, (void**)&node_ptr) == SUCCESS) {
00302                      xmlAttrPtr attr = (*node_ptr)->properties;
00303                      char *id;
00304                      smart_str prefix = {0};
00305 
00306                      if (*node_ptr == node) {
00307                             return 0;
00308                      }
00309                      xmlNodeSetName(node, (*node_ptr)->name);
00310                      xmlSetNs(node, (*node_ptr)->ns);
00311                      if (SOAP_GLOBAL(soap_version) == SOAP_1_1) {
00312                             while (1) {
00313                                    attr = get_attribute(attr, "id");
00314                                    if (attr == NULL || attr->ns == NULL) {
00315                                           break;
00316                                    }
00317                                    attr = attr->next;
00318                             }
00319                             if (attr) {
00320                                    id = (char*)attr->children->content;
00321                                    smart_str_appendc(&prefix, '#');
00322                                    smart_str_appends(&prefix, id);
00323                                    smart_str_0(&prefix);
00324                                    id = prefix.c;
00325                             } else {
00326                                    SOAP_GLOBAL(cur_uniq_ref)++;
00327                                    smart_str_appendl(&prefix, "#ref", 4);
00328                                    smart_str_append_long(&prefix, SOAP_GLOBAL(cur_uniq_ref));
00329                                    smart_str_0(&prefix);
00330                                    id = prefix.c;
00331                                    xmlSetProp((*node_ptr), BAD_CAST("id"), BAD_CAST(id+1));
00332                             }
00333                             xmlSetProp(node, BAD_CAST("href"), BAD_CAST(id));
00334                      } else {
00335                             attr = get_attribute_ex(attr, "id", SOAP_1_2_ENC_NAMESPACE);
00336                             if (attr) {
00337                                    id = (char*)attr->children->content;
00338                                    smart_str_appendc(&prefix, '#');
00339                                    smart_str_appends(&prefix, id);
00340                                    smart_str_0(&prefix);
00341                                    id = prefix.c;
00342                             } else {
00343                                    SOAP_GLOBAL(cur_uniq_ref)++;
00344                                    smart_str_appendl(&prefix, "#ref", 4);
00345                                    smart_str_append_long(&prefix, SOAP_GLOBAL(cur_uniq_ref));
00346                                    smart_str_0(&prefix);
00347                                    id = prefix.c;
00348                                    set_ns_prop((*node_ptr), SOAP_1_2_ENC_NAMESPACE, "id", id+1);
00349                             }
00350                             set_ns_prop(node, SOAP_1_2_ENC_NAMESPACE, "ref", id);
00351                      }
00352                      smart_str_free(&prefix);
00353                      return 1;
00354               } else {
00355                      zend_hash_index_update(SOAP_GLOBAL(ref_map), (ulong)data, (void**)&node, sizeof(xmlNodePtr), NULL);
00356               }
00357        }
00358        return 0;
00359 }
00360 
00361 static zval* soap_find_xml_ref(xmlNodePtr node TSRMLS_DC)
00362 {
00363        zval **data_ptr;
00364 
00365        if (SOAP_GLOBAL(ref_map) && 
00366            zend_hash_index_find(SOAP_GLOBAL(ref_map), (ulong)node, (void**)&data_ptr) == SUCCESS) {
00367               Z_SET_ISREF_PP(data_ptr);
00368               Z_ADDREF_PP(data_ptr);
00369               return *data_ptr;
00370        }
00371        return NULL;
00372 }
00373 
00374 static zend_bool soap_check_xml_ref(zval **data, xmlNodePtr node TSRMLS_DC)
00375 {
00376        zval **data_ptr;
00377 
00378        if (SOAP_GLOBAL(ref_map)) {
00379               if (zend_hash_index_find(SOAP_GLOBAL(ref_map), (ulong)node, (void**)&data_ptr) == SUCCESS) {
00380                      if (*data != *data_ptr) {
00381                             zval_ptr_dtor(data);
00382                             *data = *data_ptr;
00383                             Z_SET_ISREF_PP(data);
00384                             Z_ADDREF_PP(data);
00385                             return 1;
00386                      }
00387               } else {
00388                      zend_hash_index_update(SOAP_GLOBAL(ref_map), (ulong)node, (void**)data, sizeof(zval*), NULL);
00389               }
00390        }
00391        return 0;
00392 }
00393 
00394 static xmlNodePtr master_to_xml_int(encodePtr encode, zval *data, int style, xmlNodePtr parent, int check_class_map)
00395 {
00396        xmlNodePtr node = NULL;
00397        int add_type = 0;
00398        TSRMLS_FETCH();
00399 
00400        /* Special handling of class SoapVar */
00401        if (data &&
00402            Z_TYPE_P(data) == IS_OBJECT &&
00403            Z_OBJCE_P(data) == soap_var_class_entry) {
00404               zval **ztype, **zdata, **zns, **zstype, **zname, **znamens;
00405               encodePtr enc = NULL;
00406               HashTable *ht = Z_OBJPROP_P(data);
00407 
00408               if (zend_hash_find(ht, "enc_type", sizeof("enc_type"), (void **)&ztype) == FAILURE) {
00409                      soap_error0(E_ERROR, "Encoding: SoapVar has no 'enc_type' property");
00410               }
00411 
00412               if (zend_hash_find(ht, "enc_stype", sizeof("enc_stype"), (void **)&zstype) == SUCCESS) {
00413                      if (zend_hash_find(ht, "enc_ns", sizeof("enc_ns"), (void **)&zns) == SUCCESS) {
00414                             enc = get_encoder(SOAP_GLOBAL(sdl), Z_STRVAL_PP(zns), Z_STRVAL_PP(zstype));
00415                      } else {
00416                             zns = NULL;
00417                             enc = get_encoder_ex(SOAP_GLOBAL(sdl), Z_STRVAL_PP(zstype), Z_STRLEN_PP(zstype));
00418                      }
00419                      if (enc == NULL && SOAP_GLOBAL(typemap)) {
00420                             encodePtr *new_enc;
00421                             smart_str nscat = {0};
00422 
00423                             if (zns != NULL) {
00424                                    smart_str_appendl(&nscat, Z_STRVAL_PP(zns), Z_STRLEN_PP(zns));
00425                                    smart_str_appendc(&nscat, ':');
00426                             }
00427                             smart_str_appendl(&nscat, Z_STRVAL_PP(zstype), Z_STRLEN_PP(zstype));
00428                             smart_str_0(&nscat);
00429                             if (zend_hash_find(SOAP_GLOBAL(typemap), nscat.c, nscat.len + 1, (void**)&new_enc) == SUCCESS) {
00430                                    enc = *new_enc;
00431                             }
00432                             smart_str_free(&nscat);                   
00433                      }
00434               }
00435               if (enc == NULL) {
00436                      enc = get_conversion(Z_LVAL_P(*ztype));
00437               }
00438               if (enc == NULL) {
00439                      enc = encode;
00440               }
00441 
00442               if (zend_hash_find(ht, "enc_value", sizeof("enc_value"), (void **)&zdata) == FAILURE) {
00443                      node = master_to_xml(enc, NULL, style, parent);
00444               } else {
00445                      node = master_to_xml(enc, *zdata, style, parent);
00446               }
00447 
00448               if (style == SOAP_ENCODED || (SOAP_GLOBAL(sdl) && encode != enc)) {
00449                      if (zend_hash_find(ht, "enc_stype", sizeof("enc_stype"), (void **)&zstype) == SUCCESS) {
00450                             if (zend_hash_find(ht, "enc_ns", sizeof("enc_ns"), (void **)&zns) == SUCCESS) {
00451                                    set_ns_and_type_ex(node, Z_STRVAL_PP(zns), Z_STRVAL_PP(zstype));
00452                             } else {
00453                                    set_ns_and_type_ex(node, NULL, Z_STRVAL_PP(zstype));
00454                             }
00455                      }
00456               }
00457 
00458               if (zend_hash_find(ht, "enc_name", sizeof("enc_name"), (void **)&zname) == SUCCESS) {
00459                      xmlNodeSetName(node, BAD_CAST(Z_STRVAL_PP(zname)));
00460               }
00461               if (zend_hash_find(ht, "enc_namens", sizeof("enc_namens"), (void **)&znamens) == SUCCESS) {
00462                      xmlNsPtr nsp = encode_add_ns(node, Z_STRVAL_PP(znamens));
00463                      xmlSetNs(node, nsp);
00464               }
00465        } else {
00466               if (check_class_map && SOAP_GLOBAL(class_map) && data &&
00467                   Z_TYPE_P(data) == IS_OBJECT &&
00468                   !Z_OBJPROP_P(data)->nApplyCount) {
00469                      zend_class_entry *ce = Z_OBJCE_P(data);
00470                      HashPosition pos;
00471                      zval **tmp;
00472                      char *type_name = NULL;
00473                      uint type_len;
00474                      ulong idx;
00475 
00476                      for (zend_hash_internal_pointer_reset_ex(SOAP_GLOBAL(class_map), &pos);
00477                           zend_hash_get_current_data_ex(SOAP_GLOBAL(class_map), (void **) &tmp, &pos) == SUCCESS;
00478                           zend_hash_move_forward_ex(SOAP_GLOBAL(class_map), &pos)) {
00479                             if (Z_TYPE_PP(tmp) == IS_STRING &&
00480                                 ce->name_length == Z_STRLEN_PP(tmp) &&
00481                                 zend_binary_strncasecmp(ce->name, ce->name_length, Z_STRVAL_PP(tmp), ce->name_length, ce->name_length) == 0 &&
00482                                 zend_hash_get_current_key_ex(SOAP_GLOBAL(class_map), &type_name, &type_len, &idx, 0, &pos) == HASH_KEY_IS_STRING) {
00483 
00484                                    /* TODO: namespace isn't stored */
00485                                    encodePtr enc = NULL;
00486                                    if (SOAP_GLOBAL(sdl)) {
00487                                           enc = get_encoder(SOAP_GLOBAL(sdl), SOAP_GLOBAL(sdl)->target_ns, type_name);
00488                                           if (!enc) {
00489                                                  enc = find_encoder_by_type_name(SOAP_GLOBAL(sdl), type_name);
00490                                           }
00491                                    }
00492                                    if (enc) {
00493                                           if (encode != enc && style == SOAP_LITERAL) {
00494                                                  add_type = 1;                                    
00495                                           }
00496                                           encode = enc;
00497                                    }
00498                                    break;
00499                             }
00500                      }
00501               }
00502 
00503               if (encode == NULL) {
00504                      encode = get_conversion(UNKNOWN_TYPE);
00505               }
00506               if (SOAP_GLOBAL(typemap) && encode->details.type_str) {
00507                      smart_str nscat = {0};
00508                      encodePtr *new_enc;
00509 
00510                      if (encode->details.ns) {
00511                             smart_str_appends(&nscat, encode->details.ns);
00512                             smart_str_appendc(&nscat, ':');
00513                      }
00514                      smart_str_appends(&nscat, encode->details.type_str);
00515                      smart_str_0(&nscat);
00516                      if (zend_hash_find(SOAP_GLOBAL(typemap), nscat.c, nscat.len + 1, (void**)&new_enc) == SUCCESS) {
00517                             encode = *new_enc;
00518                      }
00519                      smart_str_free(&nscat);                   
00520               }
00521               if (encode->to_xml) {
00522                      node = encode->to_xml(&encode->details, data, style, parent);
00523                      if (add_type) {
00524                             set_ns_and_type(node, &encode->details);
00525                      }
00526               }
00527        }
00528        return node;
00529 }
00530 
00531 xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr parent)
00532 {
00533        return master_to_xml_int(encode, data, style, parent, 1);
00534 }
00535 
00536 static zval *master_to_zval_int(encodePtr encode, xmlNodePtr data)
00537 {
00538        zval *ret = NULL;
00539        TSRMLS_FETCH();
00540 
00541        if (SOAP_GLOBAL(typemap)) {
00542               if (encode->details.type_str) {
00543                      smart_str nscat = {0};
00544                      encodePtr *new_enc;
00545 
00546                      if (encode->details.ns) {
00547                             smart_str_appends(&nscat, encode->details.ns);
00548                             smart_str_appendc(&nscat, ':');
00549                      }
00550                      smart_str_appends(&nscat, encode->details.type_str);
00551                      smart_str_0(&nscat);
00552                      if (zend_hash_find(SOAP_GLOBAL(typemap), nscat.c, nscat.len + 1, (void**)&new_enc) == SUCCESS) {
00553                             encode = *new_enc;
00554                      }
00555                      smart_str_free(&nscat);                   
00556               } else {
00557                      xmlAttrPtr type_attr = get_attribute_ex(data->properties,"type", XSI_NAMESPACE);
00558 
00559                      if (type_attr != NULL) {
00560                             encodePtr *new_enc;
00561                             xmlNsPtr nsptr;
00562                             char *ns, *cptype;
00563                             smart_str nscat = {0};
00564 
00565                             parse_namespace(type_attr->children->content, &cptype, &ns);
00566                             nsptr = xmlSearchNs(data->doc, data, BAD_CAST(ns));
00567                             if (nsptr != NULL) {
00568                                    smart_str_appends(&nscat, (char*)nsptr->href);
00569                                    smart_str_appendc(&nscat, ':');
00570                             }
00571                             smart_str_appends(&nscat, cptype);
00572                             smart_str_0(&nscat);
00573                             efree(cptype);
00574                             if (ns) {efree(ns);}
00575                             if (zend_hash_find(SOAP_GLOBAL(typemap), nscat.c, nscat.len + 1, (void**)&new_enc) == SUCCESS) {
00576                                    encode = *new_enc;
00577                             }
00578                             smart_str_free(&nscat);                   
00579                      }
00580               }
00581        }
00582        if (encode->to_zval) {
00583               ret = encode->to_zval(&encode->details, data);
00584        }
00585        return ret;
00586 }
00587 
00588 zval *master_to_zval(encodePtr encode, xmlNodePtr data)
00589 {
00590        TSRMLS_FETCH();
00591        data = check_and_resolve_href(data);
00592 
00593        if (encode == NULL) {
00594               encode = get_conversion(UNKNOWN_TYPE);
00595        } else {
00596               /* Use xsi:type if it is defined */
00597               xmlAttrPtr type_attr = get_attribute_ex(data->properties,"type", XSI_NAMESPACE);
00598 
00599               if (type_attr != NULL) {
00600                      encodePtr  enc = get_encoder_from_prefix(SOAP_GLOBAL(sdl), data, type_attr->children->content);
00601 
00602                      if (enc != NULL && enc != encode) {
00603                        encodePtr tmp = enc;
00604                        while (tmp &&
00605                               tmp->details.sdl_type != NULL &&
00606                               tmp->details.sdl_type->kind != XSD_TYPEKIND_COMPLEX) {
00607                          if (enc == tmp->details.sdl_type->encode ||
00608                              tmp == tmp->details.sdl_type->encode) {
00609                             enc = NULL;
00610                             break;
00611                          }
00612                          tmp = tmp->details.sdl_type->encode;
00613                        }
00614                        if (enc != NULL) {
00615                          encode = enc;
00616                        }
00617                      }
00618               }
00619        }
00620        return master_to_zval_int(encode, data);
00621 }
00622 
00623 xmlNodePtr to_xml_user(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
00624 {
00625        xmlNodePtr ret = NULL;
00626        zval *return_value;
00627        TSRMLS_FETCH();
00628 
00629        if (type && type->map && type->map->to_xml) {
00630               MAKE_STD_ZVAL(return_value);
00631 
00632               if (call_user_function(EG(function_table), NULL, type->map->to_xml, return_value, 1, &data TSRMLS_CC) == FAILURE) {
00633                      soap_error0(E_ERROR, "Encoding: Error calling to_xml callback");
00634               }
00635               if (Z_TYPE_P(return_value) == IS_STRING) {              
00636                      xmlDocPtr doc = soap_xmlParseMemory(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value));
00637                      if (doc && doc->children) {                      
00638                             ret = xmlDocCopyNode(doc->children, parent->doc, 1);
00639                      }
00640                      xmlFreeDoc(doc);
00641               }
00642 
00643               zval_ptr_dtor(&return_value);
00644        }
00645        if (!ret) {
00646               ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
00647        }
00648        xmlAddChild(parent, ret);
00649        if (style == SOAP_ENCODED) {
00650               set_ns_and_type(ret, type);
00651        }
00652        return ret;
00653 }
00654 
00655 zval *to_zval_user(encodeTypePtr type, xmlNodePtr node)
00656 {
00657        zval *return_value;
00658        TSRMLS_FETCH();
00659 
00660        if (type && type->map && type->map->to_zval) {
00661               xmlBufferPtr buf;
00662               zval *data;
00663               xmlNodePtr copy;
00664 
00665               copy = xmlCopyNode(node, 1);
00666               buf = xmlBufferCreate();
00667               xmlNodeDump(buf, NULL, copy, 0, 0);
00668               MAKE_STD_ZVAL(data);
00669               ZVAL_STRING(data, (char*)xmlBufferContent(buf), 1);
00670               xmlBufferFree(buf);
00671               xmlFreeNode(copy);
00672 
00673               ALLOC_INIT_ZVAL(return_value);
00674               
00675               if (call_user_function(EG(function_table), NULL, type->map->to_zval, return_value, 1, &data TSRMLS_CC) == FAILURE) {
00676                      soap_error0(E_ERROR, "Encoding: Error calling from_xml callback");
00677               }
00678               zval_ptr_dtor(&data);
00679        } else {
00680               ALLOC_INIT_ZVAL(return_value);
00681        }
00682        return return_value;
00683 }
00684 
00685 /* TODO: get rid of "bogus".. ither by passing in the already created xmlnode or passing in the node name */
00686 /* String encode/decode */
00687 static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data)
00688 {
00689        zval *ret;
00690        MAKE_STD_ZVAL(ret);
00691        FIND_XML_NULL(data, ret);
00692        if (data && data->children) {
00693               if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
00694                      TSRMLS_FETCH();
00695 
00696                      if (SOAP_GLOBAL(encoding) != NULL) {
00697                             xmlBufferPtr in  = xmlBufferCreateStatic(data->children->content, xmlStrlen(data->children->content));
00698                             xmlBufferPtr out = xmlBufferCreate();
00699                             int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
00700 
00701                             if (n >= 0) {
00702                                    ZVAL_STRING(ret, (char*)xmlBufferContent(out), 1);
00703                             } else {
00704                                    ZVAL_STRING(ret, (char*)data->children->content, 1);
00705                             }
00706                             xmlBufferFree(out);
00707                             xmlBufferFree(in);
00708                      } else {
00709                             ZVAL_STRING(ret, (char*)data->children->content, 1);
00710                      }
00711               } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
00712                      ZVAL_STRING(ret, (char*)data->children->content, 1);
00713               } else {
00714                      soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
00715               }
00716        } else {
00717               ZVAL_EMPTY_STRING(ret);
00718        }
00719        return ret;
00720 }
00721 
00722 static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data)
00723 {
00724        zval *ret;
00725        MAKE_STD_ZVAL(ret);
00726        FIND_XML_NULL(data, ret);
00727        if (data && data->children) {
00728               if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
00729                      TSRMLS_FETCH();
00730 
00731                      whiteSpace_replace(data->children->content);
00732                      if (SOAP_GLOBAL(encoding) != NULL) {
00733                             xmlBufferPtr in  = xmlBufferCreateStatic(data->children->content, xmlStrlen(data->children->content));
00734                             xmlBufferPtr out = xmlBufferCreate();
00735                             int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
00736 
00737                             if (n >= 0) {
00738                                    ZVAL_STRING(ret, (char*)xmlBufferContent(out), 1);
00739                             } else {
00740                                    ZVAL_STRING(ret, (char*)data->children->content, 1);
00741                             }
00742                             xmlBufferFree(out);
00743                             xmlBufferFree(in);
00744                      } else {
00745                             ZVAL_STRING(ret, (char*)data->children->content, 1);
00746                      }
00747               } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
00748                      ZVAL_STRING(ret, (char*)data->children->content, 1);
00749               } else {
00750                      soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
00751               }
00752        } else {
00753               ZVAL_EMPTY_STRING(ret);
00754        }
00755        return ret;
00756 }
00757 
00758 static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data)
00759 {
00760        zval *ret;
00761        MAKE_STD_ZVAL(ret);
00762        FIND_XML_NULL(data, ret);
00763        if (data && data->children) {
00764               if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
00765                      TSRMLS_FETCH();
00766 
00767                      whiteSpace_collapse(data->children->content);
00768                      if (SOAP_GLOBAL(encoding) != NULL) {
00769                             xmlBufferPtr in  = xmlBufferCreateStatic(data->children->content, xmlStrlen(data->children->content));
00770                             xmlBufferPtr out = xmlBufferCreate();
00771                             int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
00772 
00773                             if (n >= 0) {
00774                                    ZVAL_STRING(ret, (char*)xmlBufferContent(out), 1);
00775                             } else {
00776                                    ZVAL_STRING(ret, (char*)data->children->content, 1);
00777                             }
00778                             xmlBufferFree(out);
00779                             xmlBufferFree(in);
00780                      } else {
00781                             ZVAL_STRING(ret, (char*)data->children->content, 1);
00782                      }
00783               } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
00784                      ZVAL_STRING(ret, (char*)data->children->content, 1);
00785               } else {
00786                      soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
00787               }
00788        } else {
00789               ZVAL_EMPTY_STRING(ret);
00790        }
00791        return ret;
00792 }
00793 
00794 static zval *to_zval_base64(encodeTypePtr type, xmlNodePtr data)
00795 {
00796        zval *ret;
00797        char *str;
00798        int str_len;
00799 
00800        MAKE_STD_ZVAL(ret);
00801        FIND_XML_NULL(data, ret);
00802        if (data && data->children) {
00803               if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
00804                      whiteSpace_collapse(data->children->content);
00805                      str = (char*)php_base64_decode(data->children->content, strlen((char*)data->children->content), &str_len);
00806                      if (!str) {
00807                             soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
00808                      }
00809                      ZVAL_STRINGL(ret, str, str_len, 0);
00810               } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
00811                      str = (char*)php_base64_decode(data->children->content, strlen((char*)data->children->content), &str_len);
00812                      if (!str) {
00813                             soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
00814                      }
00815                      ZVAL_STRINGL(ret, str, str_len, 0);
00816               } else {
00817                      soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
00818               }
00819        } else {
00820               ZVAL_EMPTY_STRING(ret);
00821        }
00822        return ret;
00823 }
00824 
00825 static zval *to_zval_hexbin(encodeTypePtr type, xmlNodePtr data)
00826 {
00827        zval *ret;
00828        unsigned char *str;
00829        int str_len, i, j;
00830        unsigned char c;
00831 
00832        MAKE_STD_ZVAL(ret);
00833        FIND_XML_NULL(data, ret);
00834        if (data && data->children) {
00835               if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
00836                      whiteSpace_collapse(data->children->content);
00837               } else if (data->children->type != XML_CDATA_SECTION_NODE || data->children->next != NULL) {
00838                      soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
00839                      return ret;
00840               }
00841               str_len = strlen((char*)data->children->content) / 2;
00842               str = emalloc(str_len+1);
00843               for (i = j = 0; i < str_len; i++) {
00844                      c = data->children->content[j++];
00845                      if (c >= '0' && c <= '9') {
00846                             str[i] = (c - '0') << 4;
00847                      } else if (c >= 'a' && c <= 'f') {
00848                             str[i] = (c - 'a' + 10) << 4;
00849                      } else if (c >= 'A' && c <= 'F') {
00850                             str[i] = (c - 'A' + 10) << 4;
00851                      } else {
00852                             soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
00853                      }
00854                      c = data->children->content[j++];
00855                      if (c >= '0' && c <= '9') {
00856                             str[i] |= c - '0';
00857                      } else if (c >= 'a' && c <= 'f') {
00858                             str[i] |= c - 'a' + 10;
00859                      } else if (c >= 'A' && c <= 'F') {
00860                             str[i] |= c - 'A' + 10;
00861                      } else {
00862                             soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
00863                      }
00864               }
00865               str[str_len] = '\0';
00866               ZVAL_STRINGL(ret, (char*)str, str_len, 0);
00867        } else {
00868               ZVAL_EMPTY_STRING(ret);
00869        }
00870        return ret;
00871 }
00872 
00873 static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
00874 {
00875        xmlNodePtr ret, text;
00876        char *str;
00877        int new_len;
00878        TSRMLS_FETCH();
00879 
00880        ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
00881        xmlAddChild(parent, ret);
00882        FIND_ZVAL_NULL(data, ret, style);
00883 
00884        if (Z_TYPE_P(data) == IS_STRING) {
00885               str = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
00886               new_len = Z_STRLEN_P(data);
00887        } else {
00888               zval tmp = *data;
00889 
00890               zval_copy_ctor(&tmp);
00891               convert_to_string(&tmp);
00892               str = estrndup(Z_STRVAL(tmp), Z_STRLEN(tmp));
00893               new_len = Z_STRLEN(tmp);
00894               zval_dtor(&tmp);
00895        }
00896 
00897        if (SOAP_GLOBAL(encoding) != NULL) {
00898               xmlBufferPtr in  = xmlBufferCreateStatic(str, new_len);
00899               xmlBufferPtr out = xmlBufferCreate();
00900               int n = xmlCharEncInFunc(SOAP_GLOBAL(encoding), out, in);
00901 
00902               if (n >= 0) {
00903                      efree(str);
00904                      str = estrdup((char*)xmlBufferContent(out));
00905                      new_len = n;
00906               }
00907               xmlBufferFree(out);
00908               xmlBufferFree(in);
00909        }
00910 
00911        if (!php_libxml_xmlCheckUTF8(BAD_CAST(str))) {
00912               char *err = emalloc(new_len + 8);
00913               char c;
00914               int i;
00915               
00916               memcpy(err, str, new_len+1);
00917               for (i = 0; (c = err[i++]);) {
00918                      if ((c & 0x80) == 0) {
00919                      } else if ((c & 0xe0) == 0xc0) {
00920                             if ((err[i] & 0xc0) != 0x80) {
00921                                    break;
00922                             }
00923                             i++;
00924                      } else if ((c & 0xf0) == 0xe0) {
00925                             if ((err[i] & 0xc0) != 0x80 || (err[i+1] & 0xc0) != 0x80) {
00926                                    break;
00927                             }
00928                             i += 2;
00929                      } else if ((c & 0xf8) == 0xf0) {
00930                             if ((err[i] & 0xc0) != 0x80 || (err[i+1] & 0xc0) != 0x80 || (err[i+2] & 0xc0) != 0x80) {
00931                                    break;
00932                             }
00933                             i += 3;
00934                      } else {
00935                             break;
00936                      }
00937               }
00938               if (c) {
00939                      err[i-1] = '\\';
00940                      err[i++] = 'x';
00941                      err[i++] = ((unsigned char)c >> 4) + ((((unsigned char)c >> 4) > 9) ? ('a' - 10) : '0');
00942                      err[i++] = (c & 15) + (((c & 15) > 9) ? ('a' - 10) : '0');
00943                      err[i++] = '.';
00944                      err[i++] = '.';
00945                      err[i++] = '.';
00946                      err[i++] = 0;
00947               }
00948 
00949               soap_error1(E_ERROR,  "Encoding: string '%s' is not a valid utf-8 string", err);
00950        }
00951 
00952        text = xmlNewTextLen(BAD_CAST(str), new_len);
00953        xmlAddChild(ret, text);
00954        efree(str);
00955 
00956        if (style == SOAP_ENCODED) {
00957               set_ns_and_type(ret, type);
00958        }
00959        return ret;
00960 }
00961 
00962 static xmlNodePtr to_xml_base64(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
00963 {
00964        xmlNodePtr ret, text;
00965        unsigned char *str;
00966        int str_len;
00967 
00968        ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
00969        xmlAddChild(parent, ret);
00970        FIND_ZVAL_NULL(data, ret, style);
00971 
00972        if (Z_TYPE_P(data) == IS_STRING) {
00973               str = php_base64_encode((unsigned char*)Z_STRVAL_P(data), Z_STRLEN_P(data), &str_len);
00974               text = xmlNewTextLen(str, str_len);
00975               xmlAddChild(ret, text);
00976               efree(str);
00977        } else {
00978               zval tmp = *data;
00979 
00980               zval_copy_ctor(&tmp);
00981               convert_to_string(&tmp);
00982               str = php_base64_encode((unsigned char*)Z_STRVAL(tmp), Z_STRLEN(tmp), &str_len);
00983               text = xmlNewTextLen(str, str_len);
00984               xmlAddChild(ret, text);
00985               efree(str);
00986               zval_dtor(&tmp);
00987        }
00988 
00989        if (style == SOAP_ENCODED) {
00990               set_ns_and_type(ret, type);
00991        }
00992        return ret;
00993 }
00994 
00995 static xmlNodePtr to_xml_hexbin(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
00996 {
00997        static char hexconvtab[] = "0123456789ABCDEF";
00998        xmlNodePtr ret, text;
00999        unsigned char *str;
01000        zval tmp;
01001        int i, j;
01002 
01003        ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01004        xmlAddChild(parent, ret);
01005        FIND_ZVAL_NULL(data, ret, style);
01006 
01007        if (Z_TYPE_P(data) != IS_STRING) {
01008               tmp = *data;
01009               zval_copy_ctor(&tmp);
01010               convert_to_string(&tmp);
01011               data = &tmp;
01012        }
01013        str = (unsigned char *) safe_emalloc(Z_STRLEN_P(data) * 2, sizeof(char), 1);
01014 
01015        for (i = j = 0; i < Z_STRLEN_P(data); i++) {
01016               str[j++] = hexconvtab[((unsigned char)Z_STRVAL_P(data)[i]) >> 4];
01017               str[j++] = hexconvtab[((unsigned char)Z_STRVAL_P(data)[i]) & 15];
01018        }
01019        str[j] = '\0';
01020 
01021        text = xmlNewTextLen(str, Z_STRLEN_P(data) * 2 * sizeof(char));
01022        xmlAddChild(ret, text);
01023        efree(str);
01024        if (data == &tmp) {
01025               zval_dtor(&tmp);
01026        }
01027 
01028        if (style == SOAP_ENCODED) {
01029               set_ns_and_type(ret, type);
01030        }
01031        return ret;
01032 }
01033 
01034 static zval *to_zval_double(encodeTypePtr type, xmlNodePtr data)
01035 {
01036        zval *ret;
01037        MAKE_STD_ZVAL(ret);
01038        FIND_XML_NULL(data, ret);
01039 
01040        if (data && data->children) {
01041               if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
01042                      long lval;
01043                      double dval;
01044 
01045                      whiteSpace_collapse(data->children->content);
01046                      switch (is_numeric_string((char*)data->children->content, strlen((char*)data->children->content), &lval, &dval, 0)) {
01047                             case IS_LONG:
01048                                    Z_TYPE_P(ret) = IS_DOUBLE;
01049                                    Z_DVAL_P(ret) = lval;
01050                                    break;
01051                             case IS_DOUBLE:
01052                                    Z_TYPE_P(ret) = IS_DOUBLE;
01053                                    Z_DVAL_P(ret) = dval;
01054                                    break;
01055                             default:
01056                                    if (strncasecmp((char*)data->children->content, "NaN", sizeof("NaN")-1) == 0) {
01057                                           ZVAL_DOUBLE(ret, php_get_nan());
01058                                    } else if (strncasecmp((char*)data->children->content, "INF", sizeof("INF")-1) == 0) {
01059                                           ZVAL_DOUBLE(ret, php_get_inf());
01060                                    } else if (strncasecmp((char*)data->children->content, "-INF", sizeof("-INF")-1) == 0) {
01061                                           ZVAL_DOUBLE(ret, -php_get_inf());
01062                                    } else {
01063                                           soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
01064                                    }
01065                      }
01066               } else {
01067                      soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
01068               }
01069        } else {
01070               ZVAL_NULL(ret);
01071        }
01072        return ret;
01073 }
01074 
01075 static zval *to_zval_long(encodeTypePtr type, xmlNodePtr data)
01076 {
01077        zval *ret;
01078        MAKE_STD_ZVAL(ret);
01079        FIND_XML_NULL(data, ret);
01080 
01081        if (data && data->children) {
01082               if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
01083                      long lval;
01084                      double dval;
01085 
01086                      whiteSpace_collapse(data->children->content);
01087                      errno = 0;
01088 
01089                      switch ((Z_TYPE_P(ret) = is_numeric_string((char*)data->children->content, strlen((char*)data->children->content), &lval, &dval, 0))) {
01090                             case IS_LONG:
01091                                    Z_LVAL_P(ret) = lval;
01092                                    break;
01093                             case IS_DOUBLE:
01094                                    Z_DVAL_P(ret) = dval;
01095                                    break;
01096                             default:
01097                                    soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
01098                      }
01099               } else {
01100                      soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
01101               }
01102        } else {
01103               ZVAL_NULL(ret);
01104        }
01105        return ret;
01106 }
01107 
01108 static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
01109 {
01110        xmlNodePtr ret;
01111 
01112        ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01113        xmlAddChild(parent, ret);
01114        FIND_ZVAL_NULL(data, ret, style);
01115 
01116        if (Z_TYPE_P(data) == IS_DOUBLE) {
01117               char s[256];
01118 
01119               snprintf(s, sizeof(s), "%0.0F",floor(Z_DVAL_P(data)));
01120               xmlNodeSetContent(ret, BAD_CAST(s));
01121        } else {
01122               zval tmp = *data;
01123 
01124               zval_copy_ctor(&tmp);
01125               if (Z_TYPE(tmp) != IS_LONG) {
01126                      convert_to_long(&tmp);
01127               }
01128               convert_to_string(&tmp);
01129               xmlNodeSetContentLen(ret, BAD_CAST(Z_STRVAL(tmp)), Z_STRLEN(tmp));
01130               zval_dtor(&tmp);
01131        }
01132 
01133        if (style == SOAP_ENCODED) {
01134               set_ns_and_type(ret, type);
01135        }
01136        return ret;
01137 }
01138 
01139 static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
01140 {
01141        xmlNodePtr ret;
01142        zval tmp;
01143        char *str;
01144        TSRMLS_FETCH();
01145 
01146        ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01147        xmlAddChild(parent, ret);
01148        FIND_ZVAL_NULL(data, ret, style);
01149 
01150        tmp = *data;
01151        if (Z_TYPE(tmp) != IS_DOUBLE) {
01152               zval_copy_ctor(&tmp);
01153               convert_to_double(&tmp);
01154        }
01155        
01156        str = (char *) safe_emalloc(EG(precision), 1, MAX_LENGTH_OF_DOUBLE + 1);
01157        php_gcvt(Z_DVAL(tmp), EG(precision), '.', 'E', str);
01158        xmlNodeSetContentLen(ret, BAD_CAST(str), strlen(str));
01159        efree(str);
01160 
01161        if (style == SOAP_ENCODED) {
01162               set_ns_and_type(ret, type);
01163        }
01164        return ret;
01165 }
01166 
01167 static zval *to_zval_bool(encodeTypePtr type, xmlNodePtr data)
01168 {
01169        zval *ret;
01170        MAKE_STD_ZVAL(ret);
01171        FIND_XML_NULL(data, ret);
01172 
01173        if (data && data->children) {
01174               if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
01175                      whiteSpace_collapse(data->children->content);
01176                      if (stricmp((char*)data->children->content, "true") == 0 ||
01177                             stricmp((char*)data->children->content, "t") == 0 ||
01178                             strcmp((char*)data->children->content, "1") == 0) {
01179                             ZVAL_BOOL(ret, 1);
01180                      } else if (stricmp((char*)data->children->content, "false") == 0 ||
01181                             stricmp((char*)data->children->content, "f") == 0 ||
01182                             strcmp((char*)data->children->content, "0") == 0) {
01183                             ZVAL_BOOL(ret, 0);
01184                      } else {
01185                             ZVAL_STRING(ret, (char*)data->children->content, 1);
01186                             convert_to_boolean(ret);
01187                      }
01188               } else {
01189                      soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
01190               }
01191        } else {
01192               ZVAL_NULL(ret);
01193        }
01194        return ret;
01195 }
01196 
01197 static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
01198 {
01199        xmlNodePtr ret;
01200 
01201        ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01202        xmlAddChild(parent, ret);
01203        FIND_ZVAL_NULL(data, ret, style);
01204 
01205        if (zend_is_true(data)) {
01206               xmlNodeSetContent(ret, BAD_CAST("true"));
01207        } else {
01208               xmlNodeSetContent(ret, BAD_CAST("false"));
01209        }
01210 
01211        if (style == SOAP_ENCODED) {
01212               set_ns_and_type(ret, type);
01213        }
01214        return ret;
01215 }
01216 
01217 /* Null encode/decode */
01218 static zval *to_zval_null(encodeTypePtr type, xmlNodePtr data)
01219 {
01220        zval *ret;
01221        MAKE_STD_ZVAL(ret);
01222        ZVAL_NULL(ret);
01223        return ret;
01224 }
01225 
01226 static xmlNodePtr to_xml_null(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
01227 {
01228        xmlNodePtr ret;
01229 
01230        ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01231        xmlAddChild(parent, ret);
01232        if (style == SOAP_ENCODED) {
01233               set_xsi_nil(ret);
01234        }
01235        return ret;
01236 }
01237 
01238 static void set_zval_property(zval* object, char* name, zval* val TSRMLS_DC)
01239 {
01240        zend_class_entry *old_scope;
01241 
01242        old_scope = EG(scope);
01243        EG(scope) = Z_OBJCE_P(object);
01244 #ifdef ZEND_ENGINE_2
01245        Z_DELREF_P(val);
01246 #endif
01247        add_property_zval(object, name, val);
01248        EG(scope) = old_scope;
01249 }
01250 
01251 static zval* get_zval_property(zval* object, char* name TSRMLS_DC)
01252 {
01253        if (Z_TYPE_P(object) == IS_OBJECT) {
01254               zval member;
01255               zval *data;
01256               zend_class_entry *old_scope;
01257 
01258               INIT_PZVAL(&member);
01259               ZVAL_STRING(&member, name, 0);
01260               old_scope = EG(scope);
01261               EG(scope) = Z_OBJCE_P(object);
01262               data = Z_OBJ_HT_P(object)->read_property(object, &member, BP_VAR_IS TSRMLS_CC);
01263               if (data == EG(uninitialized_zval_ptr)) {
01264                      /* Hack for bug #32455 */
01265                      zend_property_info *property_info;
01266 
01267                      property_info = zend_get_property_info(Z_OBJCE_P(object), &member, 1 TSRMLS_CC);
01268                      EG(scope) = old_scope;
01269                      if (property_info && zend_hash_quick_exists(Z_OBJPROP_P(object), property_info->name, property_info->name_length+1, property_info->h)) {
01270                             return data;
01271                      }
01272                      return NULL;
01273               }
01274               EG(scope) = old_scope;
01275               return data;
01276        } else if (Z_TYPE_P(object) == IS_ARRAY) {
01277               zval **data_ptr;
01278 
01279               if (zend_hash_find(Z_ARRVAL_P(object), name, strlen(name)+1, (void**)&data_ptr) == SUCCESS) {
01280                 return *data_ptr;
01281               }
01282        }
01283   return NULL;
01284 }
01285 
01286 static void unset_zval_property(zval* object, char* name TSRMLS_DC)
01287 {
01288        if (Z_TYPE_P(object) == IS_OBJECT) {
01289               zval member;
01290               zend_class_entry *old_scope;
01291 
01292               INIT_PZVAL(&member);
01293               ZVAL_STRING(&member, name, 0);
01294               old_scope = EG(scope);
01295               EG(scope) = Z_OBJCE_P(object);
01296               Z_OBJ_HT_P(object)->unset_property(object, &member TSRMLS_CC);
01297               EG(scope) = old_scope;
01298        } else if (Z_TYPE_P(object) == IS_ARRAY) {
01299               zend_hash_del(Z_ARRVAL_P(object), name, strlen(name)+1);
01300        }
01301 }
01302 
01303 static void model_to_zval_any(zval *ret, xmlNodePtr node TSRMLS_DC)
01304 {
01305        zval* any = NULL;
01306        char* name = NULL;
01307 
01308        while (node != NULL) {
01309               if (get_zval_property(ret, (char*)node->name TSRMLS_CC) == NULL) {
01310                      zval* val = master_to_zval(get_conversion(XSD_ANYXML), node);
01311                      
01312                      if (any && Z_TYPE_P(any) != IS_ARRAY) {
01313                             /* Convert into array */
01314                             zval *arr;
01315 
01316                             MAKE_STD_ZVAL(arr);
01317                             array_init(arr);
01318                             if (name) {
01319                                    add_assoc_zval(arr, name, any);
01320                             } else {
01321                                    add_next_index_zval(arr, any);
01322                             }
01323                             any = arr;
01324                      }
01325 
01326                      if (Z_TYPE_P(val) == IS_STRING && *Z_STRVAL_P(val) == '<') {
01327                             name = NULL;
01328                             while (node->next != NULL) {
01329                                    zval* val2 = master_to_zval(get_conversion(XSD_ANYXML), node->next);
01330                                    if (Z_TYPE_P(val2) != IS_STRING ||  *Z_STRVAL_P(val) != '<') {
01331                                           break;
01332                                    }
01333                                    add_string_to_string(val, val, val2);
01334                                    zval_ptr_dtor(&val2);
01335                                    node = node->next;
01336                             }
01337                      } else {
01338                             name = (char*)node->name;
01339                      }
01340 
01341                      if (any == NULL) {
01342                             if (name) {
01343                                    /* Convert into array */
01344                                    zval *arr;
01345 
01346                                    MAKE_STD_ZVAL(arr);
01347                                    array_init(arr);
01348                                    add_assoc_zval(arr, name, val);
01349                                    any = arr;
01350                                    name = NULL;
01351                             } else {
01352                                    any = val;
01353                             }
01354                      } else {
01355                             /* Add array element */
01356                             if (name) {
01357                                    zval **el;
01358                                    if (zend_hash_find(Z_ARRVAL_P(any), name, strlen(name)+1, (void**)&el) == SUCCESS) {
01359                                           if (Z_TYPE_PP(el) != IS_ARRAY) {
01360                                                  /* Convert into array */
01361                                                  zval *arr;
01362        
01363                                                  MAKE_STD_ZVAL(arr);
01364                                                  array_init(arr);
01365                                                  add_next_index_zval(arr, *el);
01366                                                  *el = arr;
01367                                           }
01368                                           add_next_index_zval(*el, val);
01369                                    } else {
01370                                           add_assoc_zval(any, name, val);
01371                                    }
01372                             } else {
01373                                    add_next_index_zval(any, val);
01374                             }
01375                             name = NULL;
01376                      }
01377               }
01378               node = node->next;
01379        }
01380        if (any) {
01381               set_zval_property(ret, name ? name : "any", any TSRMLS_CC);
01382        }
01383 }
01384 
01385 static void model_to_zval_object(zval *ret, sdlContentModelPtr model, xmlNodePtr data, sdlPtr sdl TSRMLS_DC)
01386 {
01387        switch (model->kind) {
01388               case XSD_CONTENT_ELEMENT:
01389                      if (model->u.element->name) {
01390                             xmlNodePtr node = get_node(data->children, model->u.element->name);
01391 
01392                             if (node) {
01393                                    zval *val;
01394                                    xmlNodePtr r_node;
01395 
01396                                    r_node = check_and_resolve_href(node);
01397                                    if (r_node && r_node->children && r_node->children->content) {
01398                                           if (model->u.element->fixed && strcmp(model->u.element->fixed, (char*)r_node->children->content) != 0) {
01399                                                  soap_error3(E_ERROR, "Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)", model->u.element->name, model->u.element->fixed, r_node->children->content);
01400                                           }
01401                                           val = master_to_zval(model->u.element->encode, r_node);
01402                                    } else if (model->u.element->fixed) {
01403                                           xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01404                                           xmlNodeSetContent(dummy, BAD_CAST(model->u.element->fixed));
01405                                           val = master_to_zval(model->u.element->encode, dummy);
01406                                           xmlFreeNode(dummy);
01407                                    } else if (model->u.element->def && !model->u.element->nillable) {
01408                                           xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01409                                           xmlNodeSetContent(dummy, BAD_CAST(model->u.element->def));
01410                                           val = master_to_zval(model->u.element->encode, dummy);
01411                                           xmlFreeNode(dummy);
01412                                    } else {
01413                                           val = master_to_zval(model->u.element->encode, r_node);
01414                                    }
01415                                    if ((node = get_node(node->next, model->u.element->name)) != NULL) {
01416                                           zval *array;
01417 
01418                                           MAKE_STD_ZVAL(array);
01419                                           array_init(array);
01420                                           add_next_index_zval(array, val);
01421                                           do {
01422                                                  if (node && node->children && node->children->content) {
01423                                                         if (model->u.element->fixed && strcmp(model->u.element->fixed, (char*)node->children->content) != 0) {
01424                                                                soap_error3(E_ERROR, "Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)", model->u.element->name, model->u.element->fixed, node->children->content);
01425                                                         }
01426                                                         val = master_to_zval(model->u.element->encode, node);
01427                                                  } else if (model->u.element->fixed) {
01428                                                         xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01429                                                         xmlNodeSetContent(dummy, BAD_CAST(model->u.element->fixed));
01430                                                         val = master_to_zval(model->u.element->encode, dummy);
01431                                                         xmlFreeNode(dummy);
01432                                                  } else if (model->u.element->def && !model->u.element->nillable) {
01433                                                         xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01434                                                         xmlNodeSetContent(dummy, BAD_CAST(model->u.element->def));
01435                                                         val = master_to_zval(model->u.element->encode, dummy);
01436                                                         xmlFreeNode(dummy);
01437                                                  } else {
01438                                                         val = master_to_zval(model->u.element->encode, node);
01439                                                  }
01440                                                  add_next_index_zval(array, val);
01441                                           } while ((node = get_node(node->next, model->u.element->name)) != NULL);
01442                                           val = array;
01443                                    } else if ((Z_TYPE_P(val) != IS_NULL || !model->u.element->nillable) &&
01444                                               (SOAP_GLOBAL(features) & SOAP_SINGLE_ELEMENT_ARRAYS) &&
01445                                               (model->max_occurs == -1 || model->max_occurs > 1)) {
01446                                           zval *array;
01447 
01448                                           MAKE_STD_ZVAL(array);
01449                                           array_init(array);
01450                                           add_next_index_zval(array, val);
01451                                           val = array;
01452                                    }
01453                                    set_zval_property(ret, model->u.element->name, val TSRMLS_CC);
01454                             }
01455                      }
01456                      break;
01457               case XSD_CONTENT_ALL:
01458               case XSD_CONTENT_SEQUENCE:
01459               case XSD_CONTENT_CHOICE: {
01460                      sdlContentModelPtr *tmp;
01461                      HashPosition pos;
01462                      sdlContentModelPtr any = NULL;
01463 
01464                      zend_hash_internal_pointer_reset_ex(model->u.content, &pos);
01465                      while (zend_hash_get_current_data_ex(model->u.content, (void**)&tmp, &pos) == SUCCESS) {
01466                             if ((*tmp)->kind == XSD_CONTENT_ANY) {
01467                                    any = *tmp;
01468                             } else {
01469                                    model_to_zval_object(ret, *tmp, data, sdl TSRMLS_CC);
01470                             }
01471                             zend_hash_move_forward_ex(model->u.content, &pos);
01472                      }
01473                      if (any) {
01474                             model_to_zval_any(ret, data->children TSRMLS_CC);
01475                      }
01476                      break;
01477               }
01478               case XSD_CONTENT_GROUP:
01479                      model_to_zval_object(ret, model->u.group->model, data, sdl TSRMLS_CC);
01480                      break;
01481               default:
01482                 break;
01483        }
01484 }
01485 
01486 /* Struct encode/decode */
01487 static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_entry *pce)
01488 {
01489        zval *ret;
01490        xmlNodePtr trav;
01491        sdlPtr sdl;
01492        sdlTypePtr sdlType = type->sdl_type;
01493        zend_class_entry *ce = ZEND_STANDARD_CLASS_DEF_PTR;
01494        zval *redo_any = NULL;
01495        TSRMLS_FETCH();
01496 
01497        if (pce) {
01498               ce = pce;
01499        } else if (SOAP_GLOBAL(class_map) && type->type_str) {
01500               zval             **classname;
01501               zend_class_entry  *tmp;
01502 
01503               if (zend_hash_find(SOAP_GLOBAL(class_map), type->type_str, strlen(type->type_str)+1, (void**)&classname) == SUCCESS &&
01504                   Z_TYPE_PP(classname) == IS_STRING &&
01505                   (tmp = zend_fetch_class(Z_STRVAL_PP(classname), Z_STRLEN_PP(classname), ZEND_FETCH_CLASS_AUTO TSRMLS_CC)) != NULL) {
01506                      ce = tmp;
01507               }
01508        }
01509        sdl = SOAP_GLOBAL(sdl);
01510        if (sdlType) {
01511               if (sdlType->kind == XSD_TYPEKIND_RESTRICTION &&
01512                   sdlType->encode && type != &sdlType->encode->details) {
01513                      encodePtr enc;
01514 
01515                      enc = sdlType->encode;
01516                      while (enc && enc->details.sdl_type &&
01517                             enc->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
01518                             enc->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
01519                             enc->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
01520                             enc = enc->details.sdl_type->encode;
01521                      }
01522                      if (enc) {
01523                             zval *base;
01524 
01525                             ALLOC_INIT_ZVAL(ret);
01526                             if (soap_check_xml_ref(&ret, data TSRMLS_CC)) {
01527                                    return ret;
01528                             }
01529 
01530                             object_init_ex(ret, ce);
01531                             base = master_to_zval_int(enc, data);
01532                             set_zval_property(ret, "_", base TSRMLS_CC);
01533                      } else {
01534                             ALLOC_INIT_ZVAL(ret);
01535                             FIND_XML_NULL(data, ret);
01536                             if (soap_check_xml_ref(&ret, data TSRMLS_CC)) {
01537                                    return ret;
01538                             }
01539                             object_init_ex(ret, ce);
01540                      }
01541               } else if (sdlType->kind == XSD_TYPEKIND_EXTENSION &&
01542                          sdlType->encode &&
01543                          type != &sdlType->encode->details) {
01544                      if (sdlType->encode->details.sdl_type &&
01545                          sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
01546                          sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
01547                          sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
01548 
01549                             CHECK_XML_NULL(data);
01550                             if ((ret = soap_find_xml_ref(data TSRMLS_CC)) != NULL) {
01551                                    return ret;
01552                             }
01553 
01554                          if (ce != ZEND_STANDARD_CLASS_DEF_PTR &&
01555                              sdlType->encode->to_zval == sdl_guess_convert_zval &&
01556                              sdlType->encode->details.sdl_type != NULL &&
01557                              (sdlType->encode->details.sdl_type->kind == XSD_TYPEKIND_COMPLEX ||
01558                               sdlType->encode->details.sdl_type->kind == XSD_TYPEKIND_RESTRICTION ||
01559                               sdlType->encode->details.sdl_type->kind == XSD_TYPEKIND_EXTENSION) &&
01560                              (sdlType->encode->details.sdl_type->encode == NULL ||
01561                               (sdlType->encode->details.sdl_type->encode->details.type != IS_ARRAY &&
01562                                sdlType->encode->details.sdl_type->encode->details.type != SOAP_ENC_ARRAY))) {
01563                                    ret = to_zval_object_ex(&sdlType->encode->details, data, ce);
01564                          } else {
01565                                    ret = master_to_zval_int(sdlType->encode, data);
01566                             }
01567                             if (soap_check_xml_ref(&ret, data TSRMLS_CC)) {
01568                                    return ret;
01569                             }
01570                             redo_any = get_zval_property(ret, "any" TSRMLS_CC);
01571                             if (Z_TYPE_P(ret) == IS_OBJECT && ce != ZEND_STANDARD_CLASS_DEF_PTR) {
01572                                    zend_object *zobj = zend_objects_get_address(ret TSRMLS_CC);
01573                                    zobj->ce = ce;
01574                             }
01575                      } else {
01576                             zval *base;
01577 
01578                             ALLOC_INIT_ZVAL(ret);
01579                             if (soap_check_xml_ref(&ret, data TSRMLS_CC)) {
01580                                    return ret;
01581                             }
01582 
01583                             object_init_ex(ret, ce);
01584                             base = master_to_zval_int(sdlType->encode, data);
01585                             set_zval_property(ret, "_", base TSRMLS_CC);
01586                      }
01587               } else {
01588                      ALLOC_INIT_ZVAL(ret);
01589                      FIND_XML_NULL(data, ret);
01590                      if (soap_check_xml_ref(&ret, data TSRMLS_CC)) {
01591                             return ret;
01592                      }
01593                      object_init_ex(ret, ce);
01594               }
01595               if (sdlType->model) {
01596                      if (redo_any) {
01597                             Z_ADDREF_P(redo_any);
01598                             unset_zval_property(ret, "any" TSRMLS_CC);
01599                      }
01600                      model_to_zval_object(ret, sdlType->model, data, sdl TSRMLS_CC);
01601                      if (redo_any) {
01602                             zval *tmp = get_zval_property(ret, "any" TSRMLS_CC);
01603 
01604                             if (tmp == NULL) {
01605                                    model_to_zval_any(ret, data->children TSRMLS_CC);
01606                             } else if (Z_REFCOUNT_P(tmp) == 0) {
01607                                    zval_dtor(tmp);
01608                                    efree(tmp);
01609                             }
01610                             zval_ptr_dtor(&redo_any);
01611                      }
01612               }
01613               if (sdlType->attributes) {
01614                      sdlAttributePtr *attr;
01615                      HashPosition pos;
01616 
01617                      zend_hash_internal_pointer_reset_ex(sdlType->attributes, &pos);
01618                      while (zend_hash_get_current_data_ex(sdlType->attributes, (void**)&attr, &pos) == SUCCESS) {
01619                             if ((*attr)->name) {
01620                                    xmlAttrPtr val = get_attribute(data->properties, (*attr)->name);
01621                                    char *str_val = NULL;
01622 
01623                                    if (val && val->children && val->children->content) {
01624                                           str_val = (char*)val->children->content;
01625                                           if ((*attr)->fixed && strcmp((*attr)->fixed, str_val) != 0) {
01626                                                  soap_error3(E_ERROR, "Encoding: Attribute '%s' has fixed value '%s' (value '%s' is not allowed)", (*attr)->name, (*attr)->fixed, str_val);
01627                                           }
01628                                    } else if ((*attr)->fixed) {
01629                                           str_val = (*attr)->fixed;
01630                                    } else if ((*attr)->def) {
01631                                           str_val = (*attr)->def;
01632                                    }
01633                                    if (str_val) {
01634                                           xmlNodePtr dummy, text;
01635                                           zval *data;
01636 
01637                                           dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01638                                           text = xmlNewText(BAD_CAST(str_val));
01639                                           xmlAddChild(dummy, text);
01640                                           data = master_to_zval((*attr)->encode, dummy);
01641                                           xmlFreeNode(dummy);
01642                                           set_zval_property(ret, (*attr)->name, data TSRMLS_CC);
01643                                    }
01644                             }
01645                             zend_hash_move_forward_ex(sdlType->attributes, &pos);
01646                      }
01647               }
01648        } else {
01649 
01650               ALLOC_INIT_ZVAL(ret);
01651               FIND_XML_NULL(data, ret);
01652               if (soap_check_xml_ref(&ret, data TSRMLS_CC)) {
01653                      return ret;
01654               }
01655 
01656               object_init_ex(ret, ce);
01657               trav = data->children;
01658 
01659               while (trav != NULL) {
01660                      if (trav->type == XML_ELEMENT_NODE) {
01661                             zval  *tmpVal;
01662                             zval *prop;
01663 
01664                             tmpVal = master_to_zval(NULL, trav);
01665 
01666                             prop = get_zval_property(ret, (char*)trav->name TSRMLS_CC);
01667                             if (!prop) {
01668                                    if (!trav->next || !get_node(trav->next, (char*)trav->name)) {
01669                                           set_zval_property(ret, (char*)trav->name, tmpVal TSRMLS_CC);
01670                                    } else {
01671                                           zval *arr;
01672 
01673                                           MAKE_STD_ZVAL(arr);
01674                                           array_init(arr);
01675                                           add_next_index_zval(arr, tmpVal);
01676                                           set_zval_property(ret, (char*)trav->name, arr TSRMLS_CC);
01677                                    }
01678                             } else {
01679                                    /* Property already exist - make array */
01680                                    if (Z_TYPE_P(prop) != IS_ARRAY) {
01681                                           /* Convert into array */
01682                                           zval *arr;
01683 
01684                                           MAKE_STD_ZVAL(arr);
01685                                           array_init(arr);
01686                                           Z_ADDREF_P(prop);
01687                                           add_next_index_zval(arr, prop);
01688                                           set_zval_property(ret, (char*)trav->name, arr TSRMLS_CC);
01689                                           prop = arr;
01690                                    }
01691                                    /* Add array element */
01692                                    add_next_index_zval(prop, tmpVal);
01693                             }
01694                      }
01695                      trav = trav->next;
01696               }
01697        }
01698        return ret;
01699 }
01700 
01701 static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data)
01702 {
01703        return to_zval_object_ex(type, data, NULL);
01704 }
01705 
01706 
01707 static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, zval *object, int style, int strict TSRMLS_DC)
01708 {
01709        switch (model->kind) {
01710               case XSD_CONTENT_ELEMENT: {
01711                      zval *data;
01712                      xmlNodePtr property;
01713                      encodePtr enc;
01714 
01715                      data = get_zval_property(object, model->u.element->name TSRMLS_CC);
01716                      if (data &&
01717                          Z_TYPE_P(data) == IS_NULL &&
01718                          !model->u.element->nillable &&
01719                          model->min_occurs > 0 &&
01720                          !strict) {
01721                             return 0;
01722                      }
01723                      if (data) {
01724                             enc = model->u.element->encode;
01725                             if ((model->max_occurs == -1 || model->max_occurs > 1) &&
01726                                 Z_TYPE_P(data) == IS_ARRAY &&
01727                                 !is_map(data)) {
01728                                    HashTable *ht = Z_ARRVAL_P(data);
01729                                    zval **val;
01730 
01731                                    zend_hash_internal_pointer_reset(ht);
01732                                    while (zend_hash_get_current_data(ht,(void**)&val) == SUCCESS) {
01733                                           if (Z_TYPE_PP(val) == IS_NULL && model->u.element->nillable) {
01734                                                  property = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01735                                                  xmlAddChild(node, property);
01736                                                  set_xsi_nil(property);
01737                                           } else {
01738                                                  property = master_to_xml(enc, *val, style, node);
01739                                                  if (property->children && property->children->content &&
01740                                                      model->u.element->fixed && strcmp(model->u.element->fixed, (char*)property->children->content) != 0) {
01741                                                         soap_error3(E_ERROR, "Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)", model->u.element->name, model->u.element->fixed, property->children->content);
01742                                                  }
01743                                           }
01744                                           xmlNodeSetName(property, BAD_CAST(model->u.element->name));
01745                                           if (style == SOAP_LITERAL &&
01746                                               model->u.element->namens &&
01747                                               model->u.element->form == XSD_FORM_QUALIFIED) {
01748                                                  xmlNsPtr nsp = encode_add_ns(property, model->u.element->namens);
01749                                                  xmlSetNs(property, nsp);
01750                                           }
01751                                           zend_hash_move_forward(ht);
01752                                    }
01753                             } else {
01754                                    if (Z_TYPE_P(data) == IS_NULL && model->u.element->nillable) {
01755                                           property = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01756                                           xmlAddChild(node, property);
01757                                           set_xsi_nil(property);
01758                                    } else if (Z_TYPE_P(data) == IS_NULL && model->min_occurs == 0) {
01759                                           return 1;
01760                                    } else {
01761                                           property = master_to_xml(enc, data, style, node);
01762                                           if (property->children && property->children->content &&
01763                                               model->u.element->fixed && strcmp(model->u.element->fixed, (char*)property->children->content) != 0) {
01764                                                  soap_error3(E_ERROR, "Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)", model->u.element->name, model->u.element->fixed, property->children->content);
01765                                           }
01766                                    }
01767                                    xmlNodeSetName(property, BAD_CAST(model->u.element->name));
01768                                    if (style == SOAP_LITERAL &&
01769                                        model->u.element->namens &&
01770                                        model->u.element->form == XSD_FORM_QUALIFIED) {
01771                                           xmlNsPtr nsp = encode_add_ns(property, model->u.element->namens);
01772                                           xmlSetNs(property, nsp);
01773                                    }
01774                             }
01775                             return 1;
01776                      } else if (strict && model->u.element->nillable && model->min_occurs > 0) {
01777                             property = xmlNewNode(NULL, BAD_CAST(model->u.element->name));
01778                             xmlAddChild(node, property);
01779                             set_xsi_nil(property);
01780                             if (style == SOAP_LITERAL &&
01781                                 model->u.element->namens &&
01782                                 model->u.element->form == XSD_FORM_QUALIFIED) {
01783                                    xmlNsPtr nsp = encode_add_ns(property, model->u.element->namens);
01784                                    xmlSetNs(property, nsp);
01785                             }
01786                             return 1;
01787                      } else if (model->min_occurs == 0) {
01788                             return 2;
01789                      } else {
01790                             if (strict) {
01791                                    soap_error1(E_ERROR,  "Encoding: object has no '%s' property", model->u.element->name);
01792                             }
01793                             return 0;
01794                      }
01795                      break;
01796               }
01797               case XSD_CONTENT_ANY: {
01798                      zval *data;
01799                      xmlNodePtr property;
01800                      encodePtr enc;
01801 
01802                      data = get_zval_property(object, "any" TSRMLS_CC);
01803                      if (data) {
01804                             enc = get_conversion(XSD_ANYXML);
01805                             if ((model->max_occurs == -1 || model->max_occurs > 1) &&
01806                                 Z_TYPE_P(data) == IS_ARRAY &&
01807                                 !is_map(data)) {
01808                                    HashTable *ht = Z_ARRVAL_P(data);
01809                                    zval **val;
01810 
01811                                    zend_hash_internal_pointer_reset(ht);
01812                                    while (zend_hash_get_current_data(ht,(void**)&val) == SUCCESS) {
01813                                           property = master_to_xml(enc, *val, style, node);
01814                                           zend_hash_move_forward(ht);
01815                                    }
01816                             } else {
01817                                    property = master_to_xml(enc, data, style, node);
01818                             }
01819                             return 1;
01820                      } else if (model->min_occurs == 0) {
01821                             return 2;
01822                      } else {
01823                             if (strict) {
01824                                    soap_error0(E_ERROR,  "Encoding: object has no 'any' property");
01825                             }
01826                             return 0;
01827                      }
01828                      break;
01829               }
01830               case XSD_CONTENT_SEQUENCE:
01831               case XSD_CONTENT_ALL: {
01832                      sdlContentModelPtr *tmp;
01833                      HashPosition pos;
01834 
01835                      zend_hash_internal_pointer_reset_ex(model->u.content, &pos);
01836                      while (zend_hash_get_current_data_ex(model->u.content, (void**)&tmp, &pos) == SUCCESS) {
01837                             if (!model_to_xml_object(node, *tmp, object, style, (*tmp)->min_occurs > 0 TSRMLS_CC)) {
01838                                    if ((*tmp)->min_occurs > 0) {
01839                                           return 0;
01840                                    }
01841                             }
01842                             zend_hash_move_forward_ex(model->u.content, &pos);
01843                      }
01844                      return 1;
01845               }
01846               case XSD_CONTENT_CHOICE: {
01847                      sdlContentModelPtr *tmp;
01848                      HashPosition pos;
01849                      int ret = 0;
01850 
01851                      zend_hash_internal_pointer_reset_ex(model->u.content, &pos);
01852                      while (zend_hash_get_current_data_ex(model->u.content, (void**)&tmp, &pos) == SUCCESS) {
01853                             int tmp_ret = model_to_xml_object(node, *tmp, object, style, 0 TSRMLS_CC);
01854                             if (tmp_ret == 1) {
01855                                    return 1;
01856                             } else if (tmp_ret != 0) {
01857                                    ret = 1;
01858                             }
01859                             zend_hash_move_forward_ex(model->u.content, &pos);
01860                      }
01861                      return ret;
01862               }
01863               case XSD_CONTENT_GROUP: {
01864                      return model_to_xml_object(node, model->u.group->model, object, style, model->min_occurs > 0 TSRMLS_CC);
01865               }
01866               default:
01867                 break;
01868        }
01869        return 1;
01870 }
01871 
01872 static sdlTypePtr model_array_element(sdlContentModelPtr model)
01873 {
01874        switch (model->kind) {
01875               case XSD_CONTENT_ELEMENT: {
01876                      if (model->max_occurs == -1 || model->max_occurs > 1) {
01877                        return model->u.element;
01878                      } else {
01879                        return NULL;
01880                      }
01881               }
01882               case XSD_CONTENT_SEQUENCE:
01883               case XSD_CONTENT_ALL:
01884               case XSD_CONTENT_CHOICE: {
01885                      sdlContentModelPtr *tmp;
01886                      HashPosition pos;
01887 
01888                      if (zend_hash_num_elements(model->u.content) != 1) {
01889                        return NULL;
01890                      }
01891                      zend_hash_internal_pointer_reset_ex(model->u.content, &pos);
01892                      zend_hash_get_current_data_ex(model->u.content, (void**)&tmp, &pos);
01893                      return model_array_element(*tmp);
01894               }
01895               case XSD_CONTENT_GROUP: {
01896                      return model_array_element(model->u.group->model);
01897               }
01898               default:
01899                 break;
01900        }
01901        return NULL;
01902 }
01903 
01904 static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
01905 {
01906        xmlNodePtr xmlParam;
01907        HashTable *prop = NULL;
01908        int i;
01909        sdlTypePtr sdlType = type->sdl_type;
01910        TSRMLS_FETCH();
01911 
01912        if (!data || Z_TYPE_P(data) == IS_NULL) {
01913               xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01914               xmlAddChild(parent, xmlParam);
01915               if (style == SOAP_ENCODED) {
01916                      set_xsi_nil(xmlParam);
01917                      set_ns_and_type(xmlParam, type);
01918               }
01919               return xmlParam;
01920        }
01921 
01922        if (Z_TYPE_P(data) == IS_OBJECT) {
01923               prop = Z_OBJPROP_P(data);
01924        } else if (Z_TYPE_P(data) == IS_ARRAY) {
01925               prop = Z_ARRVAL_P(data);
01926        }
01927 
01928        if (sdlType) {
01929               if (sdlType->kind == XSD_TYPEKIND_RESTRICTION &&
01930                   sdlType->encode && type != &sdlType->encode->details) {
01931                      encodePtr enc;
01932 
01933                      enc = sdlType->encode;
01934                      while (enc && enc->details.sdl_type &&
01935                             enc->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
01936                             enc->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
01937                             enc->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
01938                             enc = enc->details.sdl_type->encode;
01939                      }
01940                      if (enc) {
01941                             zval *tmp = get_zval_property(data, "_" TSRMLS_CC);
01942                             if (tmp) {
01943                                    xmlParam = master_to_xml(enc, tmp, style, parent);
01944                             } else if (prop == NULL) {
01945                                    xmlParam = master_to_xml(enc, data, style, parent);
01946                             } else {
01947                                    xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01948                                    xmlAddChild(parent, xmlParam);
01949                             }
01950                      } else {
01951                             xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01952                             xmlAddChild(parent, xmlParam);
01953                      }
01954               } else if (sdlType->kind == XSD_TYPEKIND_EXTENSION &&
01955                          sdlType->encode && type != &sdlType->encode->details) {
01956                      if (sdlType->encode->details.sdl_type &&
01957                          sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
01958                          sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
01959                          sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
01960 
01961                             if (prop) prop->nApplyCount++;
01962                             xmlParam = master_to_xml(sdlType->encode, data, style, parent);
01963                             if (prop) prop->nApplyCount--;
01964                      } else {
01965                             zval *tmp = get_zval_property(data, "_" TSRMLS_CC);
01966 
01967                             if (tmp) {
01968                                    xmlParam = master_to_xml(sdlType->encode, tmp, style, parent);
01969                             } else if (prop == NULL) {
01970                                    xmlParam = master_to_xml(sdlType->encode, data, style, parent);
01971                             } else {
01972                                    xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01973                                    xmlAddChild(parent, xmlParam);
01974                             }
01975                      }
01976               } else {
01977                      xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01978                      xmlAddChild(parent, xmlParam);
01979               }
01980 
01981               if (soap_check_zval_ref(data, xmlParam TSRMLS_CC)) {
01982                      return xmlParam;
01983               }
01984               if (prop != NULL) {
01985                      sdlTypePtr array_el;
01986 
01987                      if (Z_TYPE_P(data) == IS_ARRAY &&
01988                     !is_map(data) &&
01989                     sdlType->attributes == NULL &&
01990                     sdlType->model != NULL &&
01991                     (array_el = model_array_element(sdlType->model)) != NULL) {
01992                             zval **val;
01993 
01994                             zend_hash_internal_pointer_reset(prop);
01995                             while (zend_hash_get_current_data(prop,(void**)&val) == SUCCESS) {
01996                                    xmlNodePtr property;
01997                                    if (Z_TYPE_PP(val) == IS_NULL && array_el->nillable) {
01998                                           property = xmlNewNode(NULL, BAD_CAST("BOGUS"));
01999                                           xmlAddChild(xmlParam, property);
02000                                           set_xsi_nil(property);
02001                                    } else {
02002                                           property = master_to_xml(array_el->encode, *val, style, xmlParam);
02003                                    }
02004                                    xmlNodeSetName(property, BAD_CAST(array_el->name));
02005                                    if (style == SOAP_LITERAL &&
02006                                       array_el->namens &&
02007                                       array_el->form == XSD_FORM_QUALIFIED) {
02008                                           xmlNsPtr nsp = encode_add_ns(property, array_el->namens);
02009                                           xmlSetNs(property, nsp);
02010                                    }
02011                                    zend_hash_move_forward(prop);
02012                             }
02013                      } else if (sdlType->model) {
02014                             model_to_xml_object(xmlParam, sdlType->model, data, style, 1 TSRMLS_CC);
02015                      }
02016                      if (sdlType->attributes) {
02017                             sdlAttributePtr *attr;
02018                             zval *zattr;
02019                             HashPosition pos;
02020 
02021                             zend_hash_internal_pointer_reset_ex(sdlType->attributes, &pos);
02022                             while (zend_hash_get_current_data_ex(sdlType->attributes, (void**)&attr, &pos) == SUCCESS) {
02023                                    if ((*attr)->name) {
02024                                           zattr = get_zval_property(data, (*attr)->name TSRMLS_CC);
02025                                           if (zattr) {
02026                                                  xmlNodePtr dummy;
02027 
02028                                                  dummy = master_to_xml((*attr)->encode, zattr, SOAP_LITERAL, xmlParam);
02029                                                  if (dummy->children && dummy->children->content) {
02030                                                         if ((*attr)->fixed && strcmp((*attr)->fixed, (char*)dummy->children->content) != 0) {
02031                                                                soap_error3(E_ERROR, "Encoding: Attribute '%s' has fixed value '%s' (value '%s' is not allowed)", (*attr)->name, (*attr)->fixed, dummy->children->content);
02032                                                         }
02033                                                         /* we need to handle xml: namespace specially, since it is
02034                                                            an implicit schema. Otherwise, use form.
02035                                                         */
02036                                                         if ((*attr)->namens &&
02037                                                             (!strncmp((*attr)->namens, XML_NAMESPACE, sizeof(XML_NAMESPACE)) ||
02038                                                              (*attr)->form == XSD_FORM_QUALIFIED)) {
02039                                                                xmlNsPtr nsp = encode_add_ns(xmlParam, (*attr)->namens);
02040 
02041                                                                xmlSetNsProp(xmlParam, nsp, BAD_CAST((*attr)->name), dummy->children->content);
02042                                                         } else {
02043                                                                xmlSetProp(xmlParam, BAD_CAST((*attr)->name), dummy->children->content);
02044                                                         }
02045                                                  }
02046                                                  xmlUnlinkNode(dummy);
02047                                                  xmlFreeNode(dummy);
02048                                           }
02049                                    }
02050                                    zend_hash_move_forward_ex(sdlType->attributes, &pos);
02051                             }
02052                      }
02053               }
02054               if (style == SOAP_ENCODED) {
02055                      set_ns_and_type(xmlParam, type);
02056               }
02057        } else {
02058               xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
02059               xmlAddChild(parent, xmlParam);
02060 
02061               if (soap_check_zval_ref(data, xmlParam TSRMLS_CC)) {
02062                      return xmlParam;
02063               }
02064               if (prop != NULL) {
02065                      i = zend_hash_num_elements(prop);
02066                      zend_hash_internal_pointer_reset(prop);
02067 
02068                      for (;i > 0;i--) {
02069                             xmlNodePtr property;
02070                             zval **zprop;
02071                             char *str_key;
02072                             ulong index;
02073                             int key_type;
02074                             unsigned int str_key_len;
02075 
02076                             key_type = zend_hash_get_current_key_ex(prop, &str_key, &str_key_len, &index, FALSE, NULL);
02077                             zend_hash_get_current_data(prop, (void **)&zprop);
02078 
02079                             property = master_to_xml(get_conversion((*zprop)->type), (*zprop), style, xmlParam);
02080 
02081                             if (key_type == HASH_KEY_IS_STRING) {
02082                             char *prop_name;
02083 
02084                                    if (Z_TYPE_P(data) == IS_OBJECT) {
02085                                           char *class_name;
02086 
02087                                           zend_unmangle_property_name(str_key, str_key_len-1, &class_name, &prop_name);
02088                                    } else {
02089                                           prop_name = str_key;
02090                                    }
02091                                    if (prop_name) {
02092                                           xmlNodeSetName(property, BAD_CAST(prop_name));
02093                                    }
02094                             }
02095                             zend_hash_move_forward(prop);
02096                      }
02097               }
02098               if (style == SOAP_ENCODED) {
02099                      set_ns_and_type(xmlParam, type);
02100               }
02101        }
02102        return xmlParam;
02103 }
02104 
02105 /* Array encode/decode */
02106 static xmlNodePtr guess_array_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
02107 {
02108        encodePtr enc = NULL;
02109 
02110        if (data && Z_TYPE_P(data) == IS_ARRAY) {
02111               if (is_map(data)) {
02112                      enc = get_conversion(APACHE_MAP);
02113               } else {
02114                      enc = get_conversion(SOAP_ENC_ARRAY);
02115               }
02116        }
02117        if (!enc) {
02118               enc = get_conversion(IS_NULL);
02119        }
02120 
02121        return master_to_xml(enc, data, style, parent);
02122 }
02123 
02124 static int calc_dimension_12(const char* str)
02125 {
02126        int i = 0, flag = 0;
02127        while (*str != '\0' && (*str < '0' || *str > '9') && (*str != '*')) {
02128               str++;
02129        }
02130        if (*str == '*') {
02131               i++;
02132               str++;
02133        }
02134        while (*str != '\0') {
02135               if (*str >= '0' && *str <= '9') {
02136                      if (flag == 0) {
02137                      i++;
02138                      flag = 1;
02139               }
02140          } else if (*str == '*') {
02141                      soap_error0(E_ERROR, "Encoding: '*' may only be first arraySize value in list");
02142               } else {
02143                      flag = 0;
02144               }
02145               str++;
02146        }
02147        return i;
02148 }
02149 
02150 static int* get_position_12(int dimension, const char* str)
02151 {
02152        int *pos;
02153        int i = -1, flag = 0;
02154 
02155        pos = safe_emalloc(sizeof(int), dimension, 0);
02156        memset(pos,0,sizeof(int)*dimension);
02157        while (*str != '\0' && (*str < '0' || *str > '9') && (*str != '*')) {
02158               str++;
02159        }
02160        if (*str == '*') {
02161               str++;
02162               i++;
02163        }
02164        while (*str != '\0') {
02165               if (*str >= '0' && *str <= '9') {
02166                      if (flag == 0) {
02167                             i++;
02168                             flag = 1;
02169                      }
02170                      pos[i] = (pos[i]*10)+(*str-'0');
02171               } else if (*str == '*') {
02172                      soap_error0(E_ERROR, "Encoding: '*' may only be first arraySize value in list");
02173               } else {
02174                 flag = 0;
02175               }
02176               str++;
02177        }
02178        return pos;
02179 }
02180 
02181 static int calc_dimension(const char* str)
02182 {
02183        int i = 1;
02184        while (*str != ']' && *str != '\0') {
02185               if (*str == ',') {
02186               i++;
02187               }
02188               str++;
02189        }
02190        return i;
02191 }
02192 
02193 static void get_position_ex(int dimension, const char* str, int** pos)
02194 {
02195        int i = 0;
02196 
02197        memset(*pos,0,sizeof(int)*dimension);
02198        while (*str != ']' && *str != '\0' && i < dimension) {
02199               if (*str >= '0' && *str <= '9') {
02200                      (*pos)[i] = ((*pos)[i]*10)+(*str-'0');
02201               } else if (*str == ',') {
02202                      i++;
02203               }
02204               str++;
02205        }
02206 }
02207 
02208 static int* get_position(int dimension, const char* str)
02209 {
02210        int *pos;
02211 
02212        pos = safe_emalloc(sizeof(int), dimension, 0);
02213        get_position_ex(dimension, str, &pos);
02214        return pos;
02215 }
02216 
02217 static void add_xml_array_elements(xmlNodePtr xmlParam,
02218                                    sdlTypePtr type,
02219                                    encodePtr enc,
02220                                    xmlNsPtr ns,
02221                                    int dimension ,
02222                                    int* dims,
02223                                    zval* data,
02224                                    int style)
02225 {
02226        int j;
02227 
02228        if (data && Z_TYPE_P(data) == IS_ARRAY) {
02229               zend_hash_internal_pointer_reset(data->value.ht);
02230               for (j=0; j<dims[0]; j++) {
02231                      zval **zdata;
02232 
02233                      if (zend_hash_get_current_data(data->value.ht, (void **)&zdata) != SUCCESS) {
02234                             zdata = NULL;
02235                      }
02236                      if (dimension == 1) {
02237                             xmlNodePtr xparam;
02238 
02239                             if (zdata) {
02240                                    if (enc == NULL) {
02241                                           xparam = master_to_xml(get_conversion((*zdata)->type), (*zdata), style, xmlParam);
02242                                    } else {
02243                                           xparam = master_to_xml(enc, (*zdata), style, xmlParam);
02244                                    }
02245                             } else {
02246                                    xparam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
02247                                    xmlAddChild(xmlParam, xparam);
02248                             }
02249 
02250                             if (type) {
02251                                    xmlNodeSetName(xparam, BAD_CAST(type->name));
02252                             } else if (style == SOAP_LITERAL && enc && enc->details.type_str) {
02253                                    xmlNodeSetName(xparam, BAD_CAST(enc->details.type_str));
02254                                    xmlSetNs(xparam, ns);
02255                             } else {
02256                                    xmlNodeSetName(xparam, BAD_CAST("item"));
02257                             }
02258                      } else {
02259                             if (zdata) {
02260                               add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, *zdata, style);
02261                             } else {
02262                               add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, NULL, style);
02263                             }
02264                      }
02265                      zend_hash_move_forward(data->value.ht);
02266               }
02267        } else {
02268               for (j=0; j<dims[0]; j++) {
02269                      if (dimension == 1) {
02270                             xmlNodePtr xparam;
02271 
02272                             xparam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
02273                             xmlAddChild(xmlParam, xparam);
02274                             if (type) {
02275                                    xmlNodeSetName(xparam, BAD_CAST(type->name));
02276                             } else if (style == SOAP_LITERAL && enc && enc->details.type_str) {
02277                                    xmlNodeSetName(xparam, BAD_CAST(enc->details.type_str));
02278                                    xmlSetNs(xparam, ns);
02279                             } else {
02280                                    xmlNodeSetName(xparam, BAD_CAST("item"));
02281                             }
02282                      } else {
02283                        add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, NULL, style);
02284                      }
02285               }
02286        }
02287 }
02288 
02289 static inline int array_num_elements(HashTable* ht)
02290 {
02291        if (ht->pListTail && ht->pListTail->nKeyLength == 0) {
02292               return ht->pListTail->h-1;
02293        }
02294        return 0;
02295 }
02296 
02297 static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
02298 {
02299        sdlTypePtr sdl_type = type->sdl_type;
02300        sdlTypePtr element_type = NULL;
02301        smart_str array_type = {0}, array_size = {0};
02302        int i;
02303        xmlNodePtr xmlParam;
02304        encodePtr enc = NULL;
02305        int dimension = 1;
02306        int* dims;
02307        int soap_version;
02308        zval *array_copy = NULL;
02309        TSRMLS_FETCH();
02310 
02311        soap_version = SOAP_GLOBAL(soap_version);
02312 
02313        xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
02314        xmlAddChild(parent, xmlParam);
02315 
02316        if (!data || Z_TYPE_P(data) == IS_NULL) {
02317               if (style == SOAP_ENCODED) {
02318                      set_xsi_nil(xmlParam);
02319                      if (SOAP_GLOBAL(features) & SOAP_USE_XSI_ARRAY_TYPE) {
02320                             set_ns_and_type_ex(xmlParam, (soap_version == SOAP_1_1) ? SOAP_1_1_ENC_NAMESPACE : SOAP_1_2_ENC_NAMESPACE, "Array");
02321                      } else {
02322                             set_ns_and_type(xmlParam, type);
02323                      }
02324               }
02325               return xmlParam;
02326        }
02327 
02328        if (Z_TYPE_P(data) == IS_OBJECT && instanceof_function(Z_OBJCE_P(data), zend_ce_traversable TSRMLS_CC)) {
02329               zend_object_iterator   *iter;
02330               zend_class_entry       *ce = Z_OBJCE_P(data);
02331               zval                  **val;
02332               char                   *str_key;
02333               uint                    str_key_len;
02334               ulong                   int_key;
02335               int                     key_type;
02336 
02337               ALLOC_ZVAL(array_copy);
02338               INIT_PZVAL(array_copy);
02339               array_init(array_copy);
02340 
02341               iter = ce->get_iterator(ce, data, 0 TSRMLS_CC);
02342 
02343               if (EG(exception)) {
02344                      goto iterator_done;
02345               }
02346 
02347               if (iter->funcs->rewind) {
02348                      iter->funcs->rewind(iter TSRMLS_CC);
02349                      if (EG(exception)) {
02350                             goto iterator_done;
02351                      }
02352               }
02353 
02354               while (iter->funcs->valid(iter TSRMLS_CC) == SUCCESS) {
02355                      if (EG(exception)) {
02356                             goto iterator_done;
02357                      }
02358 
02359                      iter->funcs->get_current_data(iter, &val TSRMLS_CC);
02360                      if (EG(exception)) {
02361                             goto iterator_done;
02362                      }
02363                      if (iter->funcs->get_current_key) {
02364                             key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC);
02365                             if (EG(exception)) {
02366                                    goto iterator_done;
02367                             }
02368                             switch(key_type) {
02369                                    case HASH_KEY_IS_STRING:
02370                                           add_assoc_zval_ex(array_copy, str_key, str_key_len, *val);
02371                                           efree(str_key);
02372                                           break;
02373                                    case HASH_KEY_IS_LONG:
02374                                           add_index_zval(array_copy, int_key, *val);
02375                                           break;
02376                             }
02377                      } else {
02378                             add_next_index_zval(array_copy, *val);
02379                      }
02380                      Z_ADDREF_PP(val);
02381 
02382                      iter->funcs->move_forward(iter TSRMLS_CC);
02383                      if (EG(exception)) {
02384                             goto iterator_done;
02385                      }
02386               }
02387 iterator_done:
02388               iter->funcs->dtor(iter TSRMLS_CC);
02389               if (EG(exception)) {
02390                      zval_ptr_dtor(&array_copy);
02391                      array_copy = NULL;
02392               } else {
02393                      data = array_copy;
02394               }
02395        }
02396 
02397        if (Z_TYPE_P(data) == IS_ARRAY) {
02398               sdlAttributePtr *arrayType;
02399               sdlExtraAttributePtr *ext;
02400               sdlTypePtr elementType;
02401 
02402               i = zend_hash_num_elements(Z_ARRVAL_P(data));
02403 
02404               if (sdl_type &&
02405                   sdl_type->attributes &&
02406                   zend_hash_find(sdl_type->attributes, SOAP_1_1_ENC_NAMESPACE":arrayType",
02407                     sizeof(SOAP_1_1_ENC_NAMESPACE":arrayType"),
02408                     (void **)&arrayType) == SUCCESS &&
02409                   (*arrayType)->extraAttributes &&
02410                   zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arrayType", sizeof(WSDL_NAMESPACE":arrayType"), (void **)&ext) == SUCCESS) {
02411 
02412                      char *value, *end;
02413                      zval** el;
02414 
02415                      value = estrdup((*ext)->val);
02416                      end = strrchr(value,'[');
02417                      if (end) {
02418                             *end = '\0';
02419                             end++;
02420                             dimension = calc_dimension(end);
02421                      }
02422                      if ((*ext)->ns != NULL) {
02423                             enc = get_encoder(SOAP_GLOBAL(sdl), (*ext)->ns, value);
02424                             get_type_str(xmlParam, (*ext)->ns, value, &array_type);
02425                      } else {
02426                             smart_str_appends(&array_type, value);
02427                      }
02428 
02429                      dims = safe_emalloc(sizeof(int), dimension, 0);
02430                      dims[0] = i;
02431                      el = &data;
02432                      for (i = 1; i < dimension; i++) {
02433                             if (el != NULL && Z_TYPE_PP(el) == IS_ARRAY &&
02434                                 zend_hash_num_elements(Z_ARRVAL_PP(el)) > 0) {
02435                               zend_hash_internal_pointer_reset(Z_ARRVAL_PP(el));
02436                                    zend_hash_get_current_data(Z_ARRVAL_PP(el), (void**)&el);
02437                                    if (Z_TYPE_PP(el) == IS_ARRAY) {
02438                                           dims[i] = zend_hash_num_elements(Z_ARRVAL_PP(el));
02439                                    } else {
02440                                           dims[i] = 0;
02441                                    }
02442                             }
02443                      }
02444 
02445                      smart_str_append_long(&array_size, dims[0]);
02446                      for (i=1; i<dimension; i++) {
02447                             smart_str_appendc(&array_size, ',');
02448                             smart_str_append_long(&array_size, dims[i]);
02449                      }
02450 
02451                      efree(value);
02452 
02453               } else if (sdl_type &&
02454                          sdl_type->attributes &&
02455                          zend_hash_find(sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":itemType",
02456                            sizeof(SOAP_1_2_ENC_NAMESPACE":itemType"),
02457                            (void **)&arrayType) == SUCCESS &&
02458                          (*arrayType)->extraAttributes &&
02459                          zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":itemType", sizeof(WSDL_NAMESPACE":itemType"), (void **)&ext) == SUCCESS) {
02460                      if ((*ext)->ns != NULL) {
02461                             enc = get_encoder(SOAP_GLOBAL(sdl), (*ext)->ns, (*ext)->val);
02462                             get_type_str(xmlParam, (*ext)->ns, (*ext)->val, &array_type);
02463                      } else {
02464                             smart_str_appends(&array_type, (*ext)->val);
02465                      }
02466                      if (zend_hash_find(sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
02467                                         sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize"),
02468                                         (void **)&arrayType) == SUCCESS &&
02469                          (*arrayType)->extraAttributes &&
02470                          zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arraySize", sizeof(WSDL_NAMESPACE":arraysize"), (void **)&ext) == SUCCESS) {
02471                             dimension = calc_dimension_12((*ext)->val);
02472                             dims = get_position_12(dimension, (*ext)->val);
02473                             if (dims[0] == 0) {dims[0] = i;}
02474 
02475                             smart_str_append_long(&array_size, dims[0]);
02476                             for (i=1; i<dimension; i++) {
02477                                    smart_str_appendc(&array_size, ',');
02478                                    smart_str_append_long(&array_size, dims[i]);
02479                             }
02480                      } else {
02481                             dims = emalloc(sizeof(int));
02482                             *dims = 0;
02483                             smart_str_append_long(&array_size, i);
02484                      }
02485               } else if (sdl_type &&
02486                          sdl_type->attributes &&
02487                          zend_hash_find(sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
02488                            sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize"),
02489                            (void **)&arrayType) == SUCCESS &&
02490                          (*arrayType)->extraAttributes &&
02491                          zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arraySize", sizeof(WSDL_NAMESPACE":arraySize"), (void **)&ext) == SUCCESS) {
02492                      dimension = calc_dimension_12((*ext)->val);
02493                      dims = get_position_12(dimension, (*ext)->val);
02494                      if (dims[0] == 0) {dims[0] = i;}
02495 
02496                      smart_str_append_long(&array_size, dims[0]);
02497                      for (i=1; i<dimension; i++) {
02498                             smart_str_appendc(&array_size, ',');
02499                             smart_str_append_long(&array_size, dims[i]);
02500                      }
02501 
02502                      if (sdl_type && sdl_type->elements &&
02503                          zend_hash_num_elements(sdl_type->elements) == 1 &&
02504                          (zend_hash_internal_pointer_reset(sdl_type->elements),
02505                           zend_hash_get_current_data(sdl_type->elements, (void**)&elementType) == SUCCESS) &&
02506                                    (elementType = *(sdlTypePtr*)elementType) != NULL &&
02507                           elementType->encode && elementType->encode->details.type_str) {
02508                             element_type = elementType;
02509                             enc = elementType->encode;
02510                             get_type_str(xmlParam, elementType->encode->details.ns, elementType->encode->details.type_str, &array_type);
02511                      } else {
02512                             enc = get_array_type(xmlParam, data, &array_type TSRMLS_CC);
02513                      }
02514               } else if (sdl_type && sdl_type->elements &&
02515                          zend_hash_num_elements(sdl_type->elements) == 1 &&
02516                          (zend_hash_internal_pointer_reset(sdl_type->elements),
02517                           zend_hash_get_current_data(sdl_type->elements, (void**)&elementType) == SUCCESS) &&
02518                          (elementType = *(sdlTypePtr*)elementType) != NULL &&
02519                          elementType->encode && elementType->encode->details.type_str) {
02520 
02521                      element_type = elementType;
02522                      enc = elementType->encode;
02523                      get_type_str(xmlParam, elementType->encode->details.ns, elementType->encode->details.type_str, &array_type);
02524 
02525                      smart_str_append_long(&array_size, i);
02526 
02527                      dims = safe_emalloc(sizeof(int), dimension, 0);
02528                      dims[0] = i;
02529               } else {
02530 
02531                      enc = get_array_type(xmlParam, data, &array_type TSRMLS_CC);
02532                      smart_str_append_long(&array_size, i);
02533                      dims = safe_emalloc(sizeof(int), dimension, 0);
02534                      dims[0] = i;
02535               }
02536 
02537               if (style == SOAP_ENCODED) {
02538                      if (soap_version == SOAP_1_1) {
02539                             smart_str_0(&array_type);
02540                             if (strcmp(array_type.c,"xsd:anyType") == 0) {
02541                                    smart_str_free(&array_type);
02542                                    smart_str_appendl(&array_type,"xsd:ur-type",sizeof("xsd:ur-type")-1);
02543                             }
02544                             smart_str_appendc(&array_type, '[');
02545                             smart_str_append(&array_type, &array_size);
02546                             smart_str_appendc(&array_type, ']');
02547                             smart_str_0(&array_type);
02548                             set_ns_prop(xmlParam, SOAP_1_1_ENC_NAMESPACE, "arrayType", array_type.c);
02549                      } else {
02550                             int i = 0;
02551                             while (i < array_size.len) {
02552                                    if (array_size.c[i] == ',') {array_size.c[i] = ' ';}
02553                                    ++i;
02554                             }
02555                             smart_str_0(&array_type);
02556                             smart_str_0(&array_size);
02557                             set_ns_prop(xmlParam, SOAP_1_2_ENC_NAMESPACE, "itemType", array_type.c);
02558                             set_ns_prop(xmlParam, SOAP_1_2_ENC_NAMESPACE, "arraySize", array_size.c);
02559                      }
02560               }
02561               smart_str_free(&array_type);
02562               smart_str_free(&array_size);
02563 
02564               add_xml_array_elements(xmlParam, element_type, enc, enc?encode_add_ns(xmlParam,enc->details.ns):NULL, dimension, dims, data, style);
02565               efree(dims);
02566        }
02567        if (style == SOAP_ENCODED) {
02568               if (SOAP_GLOBAL(features) & SOAP_USE_XSI_ARRAY_TYPE) {
02569                      set_ns_and_type_ex(xmlParam, (soap_version == SOAP_1_1) ? SOAP_1_1_ENC_NAMESPACE : SOAP_1_2_ENC_NAMESPACE, "Array");
02570               } else {
02571                      set_ns_and_type(xmlParam, type);
02572               }
02573        }
02574 
02575        if (array_copy) {
02576               zval_ptr_dtor(&array_copy);
02577        }
02578 
02579        return xmlParam;
02580 }
02581 
02582 static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data)
02583 {
02584        zval *ret;
02585        xmlNodePtr trav;
02586        encodePtr enc = NULL;
02587        int dimension = 1;
02588        int* dims = NULL;
02589        int* pos = NULL;
02590        xmlAttrPtr attr;
02591        sdlPtr sdl;
02592        sdlAttributePtr *arrayType;
02593        sdlExtraAttributePtr *ext;
02594        sdlTypePtr elementType;
02595 
02596        TSRMLS_FETCH();
02597 
02598        MAKE_STD_ZVAL(ret);
02599        FIND_XML_NULL(data, ret);
02600        sdl = SOAP_GLOBAL(sdl);
02601 
02602        if (data &&
02603            (attr = get_attribute(data->properties,"arrayType")) &&
02604            attr->children && attr->children->content) {
02605               char *type, *end, *ns;
02606               xmlNsPtr nsptr;
02607 
02608               parse_namespace(attr->children->content, &type, &ns);
02609               nsptr = xmlSearchNs(attr->doc, attr->parent, BAD_CAST(ns));
02610 
02611               end = strrchr(type,'[');
02612               if (end) {
02613                      *end = '\0';
02614                      dimension = calc_dimension(end+1);
02615                      dims = get_position(dimension, end+1);
02616               }
02617               if (nsptr != NULL) {
02618                      enc = get_encoder(SOAP_GLOBAL(sdl), (char*)nsptr->href, type);
02619               }
02620               efree(type);
02621               if (ns) {efree(ns);}
02622 
02623        } else if ((attr = get_attribute(data->properties,"itemType")) &&
02624            attr->children &&
02625            attr->children->content) {
02626               char *type, *ns;
02627               xmlNsPtr nsptr;
02628 
02629               parse_namespace(attr->children->content, &type, &ns);
02630               nsptr = xmlSearchNs(attr->doc, attr->parent, BAD_CAST(ns));
02631               if (nsptr != NULL) {
02632                      enc = get_encoder(SOAP_GLOBAL(sdl), (char*)nsptr->href, type);
02633               }
02634               efree(type);
02635               if (ns) {efree(ns);}
02636 
02637               if ((attr = get_attribute(data->properties,"arraySize")) &&
02638                   attr->children && attr->children->content) {
02639                      dimension = calc_dimension_12((char*)attr->children->content);
02640                      dims = get_position_12(dimension, (char*)attr->children->content);
02641               } else {
02642                      dims = emalloc(sizeof(int));
02643                      *dims = 0;
02644               }
02645 
02646        } else if ((attr = get_attribute(data->properties,"arraySize")) &&
02647            attr->children && attr->children->content) {
02648 
02649               dimension = calc_dimension_12((char*)attr->children->content);
02650               dims = get_position_12(dimension, (char*)attr->children->content);
02651 
02652        } else if (type->sdl_type != NULL &&
02653                   type->sdl_type->attributes != NULL &&
02654                   zend_hash_find(type->sdl_type->attributes, SOAP_1_1_ENC_NAMESPACE":arrayType",
02655                                  sizeof(SOAP_1_1_ENC_NAMESPACE":arrayType"),
02656                                  (void **)&arrayType) == SUCCESS &&
02657                   (*arrayType)->extraAttributes &&
02658                   zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arrayType", sizeof(WSDL_NAMESPACE":arrayType"), (void **)&ext) == SUCCESS) {
02659               char *type, *end;
02660 
02661               type = estrdup((*ext)->val);
02662               end = strrchr(type,'[');
02663               if (end) {
02664                      *end = '\0';
02665               }
02666               if ((*ext)->ns != NULL) {
02667                      enc = get_encoder(SOAP_GLOBAL(sdl), (*ext)->ns, type);
02668               }
02669               efree(type);
02670 
02671               dims = emalloc(sizeof(int));
02672               *dims = 0;
02673 
02674        } else if (type->sdl_type != NULL &&
02675                   type->sdl_type->attributes != NULL &&
02676                   zend_hash_find(type->sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":itemType",
02677                                  sizeof(SOAP_1_2_ENC_NAMESPACE":itemType"),
02678                                  (void **)&arrayType) == SUCCESS &&
02679                   (*arrayType)->extraAttributes &&
02680                   zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":itemType", sizeof(WSDL_NAMESPACE":itemType"), (void **)&ext) == SUCCESS) {
02681 
02682               if ((*ext)->ns != NULL) {
02683                      enc = get_encoder(SOAP_GLOBAL(sdl), (*ext)->ns, (*ext)->val);
02684               }
02685 
02686               if (zend_hash_find(type->sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
02687                                  sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize"),
02688                                  (void **)&arrayType) == SUCCESS &&
02689                   (*arrayType)->extraAttributes &&
02690                   zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arraySize", sizeof(WSDL_NAMESPACE":arraysize"), (void **)&ext) == SUCCESS) {
02691                      dimension = calc_dimension_12((*ext)->val);
02692                      dims = get_position_12(dimension, (*ext)->val);
02693               } else {
02694                      dims = emalloc(sizeof(int));
02695                      *dims = 0;
02696               }
02697        } else if (type->sdl_type != NULL &&
02698                   type->sdl_type->attributes != NULL &&
02699                   zend_hash_find(type->sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
02700                                  sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize"),
02701                                  (void **)&arrayType) == SUCCESS &&
02702                   (*arrayType)->extraAttributes &&
02703                   zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arraySize", sizeof(WSDL_NAMESPACE":arraysize"), (void **)&ext) == SUCCESS) {
02704 
02705               dimension = calc_dimension_12((*ext)->val);
02706               dims = get_position_12(dimension, (*ext)->val);
02707               if (type->sdl_type && type->sdl_type->elements &&
02708                   zend_hash_num_elements(type->sdl_type->elements) == 1 &&
02709                   (zend_hash_internal_pointer_reset(type->sdl_type->elements),
02710                    zend_hash_get_current_data(type->sdl_type->elements, (void**)&elementType) == SUCCESS) &&
02711                   (elementType = *(sdlTypePtr*)elementType) != NULL &&
02712                   elementType->encode) {
02713                      enc = elementType->encode;
02714               }
02715        } else if (type->sdl_type && type->sdl_type->elements &&
02716                   zend_hash_num_elements(type->sdl_type->elements) == 1 &&
02717                   (zend_hash_internal_pointer_reset(type->sdl_type->elements),
02718                    zend_hash_get_current_data(type->sdl_type->elements, (void**)&elementType) == SUCCESS) &&
02719                   (elementType = *(sdlTypePtr*)elementType) != NULL &&
02720                   elementType->encode) {
02721               enc = elementType->encode;
02722        }
02723        if (dims == NULL) {
02724               dimension = 1;
02725               dims = emalloc(sizeof(int));
02726               *dims = 0;
02727        }
02728        pos = safe_emalloc(sizeof(int), dimension, 0);
02729        memset(pos,0,sizeof(int)*dimension);
02730        if (data &&
02731            (attr = get_attribute(data->properties,"offset")) &&
02732             attr->children && attr->children->content) {
02733               char* tmp = strrchr((char*)attr->children->content,'[');
02734 
02735               if (tmp == NULL) {
02736                      tmp = (char*)attr->children->content;
02737               }
02738               get_position_ex(dimension, tmp, &pos);
02739        }
02740 
02741        array_init(ret);
02742        trav = data->children;
02743        while (trav) {
02744               if (trav->type == XML_ELEMENT_NODE) {
02745                      int i;
02746                      zval *tmpVal, *ar;
02747                      xmlAttrPtr position = get_attribute(trav->properties,"position");
02748 
02749                      tmpVal = master_to_zval(enc, trav);
02750                      if (position != NULL && position->children && position->children->content) {
02751                             char* tmp = strrchr((char*)position->children->content, '[');
02752                             if (tmp == NULL) {
02753                                    tmp = (char*)position->children->content;
02754                             }
02755                             get_position_ex(dimension, tmp, &pos);
02756                      }
02757 
02758                      /* Get/Create intermediate arrays for multidimensional arrays */
02759                      i = 0;
02760                      ar = ret;
02761                      while (i < dimension-1) {
02762                             zval** ar2;
02763                             if (zend_hash_index_find(Z_ARRVAL_P(ar), pos[i], (void**)&ar2) == SUCCESS) {
02764                                    ar = *ar2;
02765                             } else {
02766                                    zval *tmpAr;
02767                                    MAKE_STD_ZVAL(tmpAr);
02768                                    array_init(tmpAr);
02769                                    zend_hash_index_update(Z_ARRVAL_P(ar), pos[i], &tmpAr, sizeof(zval*), (void**)&ar2);
02770                                    ar = *ar2;
02771                             }
02772                             i++;
02773                      }
02774                      zend_hash_index_update(Z_ARRVAL_P(ar), pos[i], &tmpVal, sizeof(zval *), NULL);
02775 
02776                      /* Increment position */
02777                      i = dimension;
02778                      while (i > 0) {
02779                        i--;
02780                        pos[i]++;
02781                             if (pos[i] >= dims[i]) {
02782                                    if (i > 0) {
02783                                           pos[i] = 0;
02784                                    } else {
02785                                           /* TODO: Array index overflow */
02786                                    }
02787                             } else {
02788                               break;
02789                             }
02790                      }
02791               }
02792               trav = trav->next;
02793        }
02794        efree(dims);
02795        efree(pos);
02796        return ret;
02797 }
02798 
02799 /* Map encode/decode */
02800 static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
02801 {
02802        xmlNodePtr xmlParam;
02803        int i;
02804 
02805        xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
02806        xmlAddChild(parent, xmlParam);
02807        FIND_ZVAL_NULL(data, xmlParam, style);
02808 
02809        if (Z_TYPE_P(data) == IS_ARRAY) {
02810               i = zend_hash_num_elements(Z_ARRVAL_P(data));
02811               zend_hash_internal_pointer_reset(data->value.ht);
02812               for (;i > 0;i--) {
02813                      xmlNodePtr xparam, item;
02814                      xmlNodePtr key;
02815                      zval **temp_data;
02816                      char *key_val;
02817                      ulong int_val;
02818 
02819                      zend_hash_get_current_data(data->value.ht, (void **)&temp_data);
02820                      item = xmlNewNode(NULL, BAD_CAST("item"));
02821                      xmlAddChild(xmlParam, item);
02822                      key = xmlNewNode(NULL, BAD_CAST("key"));
02823                      xmlAddChild(item,key);
02824                      if (zend_hash_get_current_key(data->value.ht, &key_val, &int_val, FALSE) == HASH_KEY_IS_STRING) {
02825                             if (style == SOAP_ENCODED) {
02826                                    set_xsi_type(key, "xsd:string");
02827                             }
02828                             xmlNodeSetContent(key, BAD_CAST(key_val));
02829                      } else {
02830                             smart_str tmp = {0};
02831                             smart_str_append_long(&tmp, int_val);
02832                             smart_str_0(&tmp);
02833 
02834                             if (style == SOAP_ENCODED) {
02835                                    set_xsi_type(key, "xsd:int");
02836                             }
02837                             xmlNodeSetContentLen(key, BAD_CAST(tmp.c), tmp.len);
02838 
02839                             smart_str_free(&tmp);
02840                      }
02841 
02842                      xparam = master_to_xml(get_conversion((*temp_data)->type), (*temp_data), style, item);
02843                      xmlNodeSetName(xparam, BAD_CAST("value"));
02844 
02845                      zend_hash_move_forward(data->value.ht);
02846               }
02847        }
02848        if (style == SOAP_ENCODED) {
02849               set_ns_and_type(xmlParam, type);
02850        }
02851 
02852        return xmlParam;
02853 }
02854 
02855 static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data)
02856 {
02857        zval *ret, *key, *value;
02858        xmlNodePtr trav, item, xmlKey, xmlValue;
02859 
02860        MAKE_STD_ZVAL(ret);
02861        FIND_XML_NULL(data, ret);
02862 
02863        if (data && data->children) {
02864               array_init(ret);
02865               trav = data->children;
02866 
02867               trav = data->children;
02868               FOREACHNODE(trav, "item", item) {
02869                      xmlKey = get_node(item->children, "key");
02870                      if (!xmlKey) {
02871                             soap_error0(E_ERROR,  "Encoding: Can't decode apache map, missing key");
02872                      }
02873 
02874                      xmlValue = get_node(item->children, "value");
02875                      if (!xmlKey) {
02876                             soap_error0(E_ERROR,  "Encoding: Can't decode apache map, missing value");
02877                      }
02878 
02879                      key = master_to_zval(NULL, xmlKey);
02880                      value = master_to_zval(NULL, xmlValue);
02881 
02882                      if (Z_TYPE_P(key) == IS_STRING) {
02883                             zend_symtable_update(Z_ARRVAL_P(ret), Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof(zval *), NULL);
02884                      } else if (Z_TYPE_P(key) == IS_LONG) {
02885                             zend_hash_index_update(Z_ARRVAL_P(ret), Z_LVAL_P(key), &value, sizeof(zval *), NULL);
02886                      } else {
02887                             soap_error0(E_ERROR,  "Encoding: Can't decode apache map, only Strings or Longs are allowd as keys");
02888                      }
02889                      zval_ptr_dtor(&key);
02890               }
02891               ENDFOREACH(trav);
02892        } else {
02893               ZVAL_NULL(ret);
02894        }
02895        return ret;
02896 }
02897 
02898 /* Unknown encode/decode */
02899 static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
02900 {
02901        encodePtr  enc;
02902        xmlNodePtr ret;
02903 
02904        if (data) {
02905               enc = get_conversion(data->type);
02906        } else {
02907               enc = get_conversion(IS_NULL);
02908        }
02909        ret = master_to_xml_int(enc, data, style, parent, 0);
02910 /*
02911        if (style == SOAP_LITERAL && SOAP_GLOBAL(sdl)) {
02912               set_ns_and_type(ret, &enc->details);
02913        }
02914 */
02915        return ret;
02916 }
02917 
02918 static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data)
02919 {
02920        encodePtr enc = NULL;
02921        xmlAttrPtr tmpattr;
02922        xmlChar *type_name = NULL;
02923        zval *ret;
02924        TSRMLS_FETCH();
02925 
02926        data = check_and_resolve_href(data);
02927 
02928        if (data == NULL) {
02929               enc = get_conversion(IS_NULL);
02930        } else if (data->properties && get_attribute_ex(data->properties, "nil", XSI_NAMESPACE)) {
02931               enc = get_conversion(IS_NULL);
02932        } else {
02933               tmpattr = get_attribute_ex(data->properties,"type", XSI_NAMESPACE);
02934               if (tmpattr != NULL) {
02935                 type_name = tmpattr->children->content;
02936                      enc = get_encoder_from_prefix(SOAP_GLOBAL(sdl), data, tmpattr->children->content);
02937                      if (enc && type == &enc->details) {
02938                             enc = NULL;
02939                      }
02940                      if (enc != NULL) {
02941                        encodePtr tmp = enc;
02942                        while (tmp &&
02943                               tmp->details.sdl_type != NULL &&
02944                               tmp->details.sdl_type->kind != XSD_TYPEKIND_COMPLEX) {
02945                          if (enc == tmp->details.sdl_type->encode ||
02946                              tmp == tmp->details.sdl_type->encode) {
02947                             enc = NULL;
02948                             break;
02949                          }
02950                          tmp = tmp->details.sdl_type->encode;
02951                        }
02952                      }
02953               }
02954 
02955               if (enc == NULL) {
02956                      /* Didn't have a type, totally guess here */
02957                      /* Logic: has children = IS_OBJECT else IS_STRING */
02958                      xmlNodePtr trav;
02959 
02960                      if (get_attribute(data->properties, "arrayType") ||
02961                          get_attribute(data->properties, "itemType") ||
02962                          get_attribute(data->properties, "arraySize")) {
02963                             enc = get_conversion(SOAP_ENC_ARRAY);
02964                      } else {
02965                             enc = get_conversion(XSD_STRING);
02966                             trav = data->children;
02967                             while (trav != NULL) {
02968                                    if (trav->type == XML_ELEMENT_NODE) {
02969                                           enc = get_conversion(SOAP_ENC_OBJECT);
02970                                           break;
02971                                    }
02972                                    trav = trav->next;
02973                             }
02974                      }
02975               }
02976        }
02977        ret = master_to_zval_int(enc, data);
02978        if (SOAP_GLOBAL(sdl) && type_name && enc->details.sdl_type) {
02979               zval* soapvar;
02980               char *ns, *cptype;
02981               xmlNsPtr nsptr;
02982 
02983               MAKE_STD_ZVAL(soapvar);
02984               object_init_ex(soapvar, soap_var_class_entry);
02985               add_property_long(soapvar, "enc_type", enc->details.type);
02986 #ifdef ZEND_ENGINE_2
02987               Z_DELREF_P(ret);
02988 #endif
02989               add_property_zval(soapvar, "enc_value", ret);
02990               parse_namespace(type_name, &cptype, &ns);
02991               nsptr = xmlSearchNs(data->doc, data, BAD_CAST(ns));
02992               add_property_string(soapvar, "enc_stype", cptype, 1);
02993               if (nsptr) {
02994                      add_property_string(soapvar, "enc_ns", (char*)nsptr->href, 1);
02995               }
02996               efree(cptype);
02997               if (ns) {efree(ns);}
02998               ret = soapvar;
02999        }
03000        return ret;
03001 }
03002 
03003 /* Time encode/decode */
03004 static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, int style, xmlNodePtr parent)
03005 {
03006        /* logic hacked from ext/standard/datetime.c */
03007        struct tm *ta, tmbuf;
03008        time_t timestamp;
03009        int max_reallocs = 5;
03010        size_t buf_len=64, real_len;
03011        char *buf;
03012        char tzbuf[8];
03013 
03014        xmlNodePtr xmlParam;
03015 
03016        xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
03017        xmlAddChild(parent, xmlParam);
03018        FIND_ZVAL_NULL(data, xmlParam, style);
03019 
03020        if (Z_TYPE_P(data) == IS_LONG) {
03021               timestamp = Z_LVAL_P(data);
03022               ta = php_localtime_r(&timestamp, &tmbuf);
03023               /*ta = php_gmtime_r(&timestamp, &tmbuf);*/
03024               if (!ta) {
03025                      soap_error1(E_ERROR, "Encoding: Invalid timestamp %ld", Z_LVAL_P(data));
03026               }
03027 
03028               buf = (char *) emalloc(buf_len);
03029               while ((real_len = strftime(buf, buf_len, format, ta)) == buf_len || real_len == 0) {
03030                      buf_len *= 2;
03031                      buf = (char *) erealloc(buf, buf_len);
03032                      if (!--max_reallocs) break;
03033               }
03034 
03035               /* Time zone support */
03036 #ifdef HAVE_TM_GMTOFF
03037               snprintf(tzbuf, sizeof(tzbuf), "%c%02d:%02d", (ta->tm_gmtoff < 0) ? '-' : '+', abs(ta->tm_gmtoff / 3600), abs( (ta->tm_gmtoff % 3600) / 60 ));
03038 #else
03039 # if defined(__CYGWIN__) || defined(NETWARE)
03040               snprintf(tzbuf, sizeof(tzbuf), "%c%02d:%02d", ((ta->tm_isdst ? _timezone - 3600:_timezone)>0)?'-':'+', abs((ta->tm_isdst ? _timezone - 3600 : _timezone) / 3600), abs(((ta->tm_isdst ? _timezone - 3600 : _timezone) % 3600) / 60));
03041 # else
03042               snprintf(tzbuf, sizeof(tzbuf), "%c%02d:%02d", ((ta->tm_isdst ? timezone - 3600:timezone)>0)?'-':'+', abs((ta->tm_isdst ? timezone - 3600 : timezone) / 3600), abs(((ta->tm_isdst ? timezone - 3600 : timezone) % 3600) / 60));
03043 # endif
03044 #endif
03045               if (strcmp(tzbuf,"+00:00") == 0) {
03046                 strcpy(tzbuf,"Z");
03047                 real_len++;
03048               } else {
03049                      real_len += 6;
03050               }
03051               if (real_len >= buf_len) {
03052                      buf = (char *) erealloc(buf, real_len+1);
03053               }
03054               strcat(buf, tzbuf);
03055 
03056               xmlNodeSetContent(xmlParam, BAD_CAST(buf));
03057               efree(buf);
03058        } else if (Z_TYPE_P(data) == IS_STRING) {
03059               xmlNodeSetContentLen(xmlParam, BAD_CAST(Z_STRVAL_P(data)), Z_STRLEN_P(data));
03060        }
03061 
03062        if (style == SOAP_ENCODED) {
03063               set_ns_and_type(xmlParam, type);
03064        }
03065        return xmlParam;
03066 }
03067 
03068 static xmlNodePtr to_xml_duration(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
03069 {
03070        /* TODO: '-'?P([0-9]+Y)?([0-9]+M)?([0-9]+D)?T([0-9]+H)?([0-9]+M)?([0-9]+S)? */
03071        return to_xml_string(type, data, style, parent);
03072 }
03073 
03074 static xmlNodePtr to_xml_datetime(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
03075 {
03076        return to_xml_datetime_ex(type, data, "%Y-%m-%dT%H:%M:%S", style, parent);
03077 }
03078 
03079 static xmlNodePtr to_xml_time(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
03080 {
03081        /* TODO: microsecconds */
03082        return to_xml_datetime_ex(type, data, "%H:%M:%S", style, parent);
03083 }
03084 
03085 static xmlNodePtr to_xml_date(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
03086 {
03087        return to_xml_datetime_ex(type, data, "%Y-%m-%d", style, parent);
03088 }
03089 
03090 static xmlNodePtr to_xml_gyearmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
03091 {
03092        return to_xml_datetime_ex(type, data, "%Y-%m", style, parent);
03093 }
03094 
03095 static xmlNodePtr to_xml_gyear(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
03096 {
03097        return to_xml_datetime_ex(type, data, "%Y", style, parent);
03098 }
03099 
03100 static xmlNodePtr to_xml_gmonthday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
03101 {
03102        return to_xml_datetime_ex(type, data, "--%m-%d", style, parent);
03103 }
03104 
03105 static xmlNodePtr to_xml_gday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
03106 {
03107        return to_xml_datetime_ex(type, data, "---%d", style, parent);
03108 }
03109 
03110 static xmlNodePtr to_xml_gmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
03111 {
03112        return to_xml_datetime_ex(type, data, "--%m--", style, parent);
03113 }
03114 
03115 static zval* to_zval_list(encodeTypePtr enc, xmlNodePtr data) {
03116        /*FIXME*/
03117        return to_zval_stringc(enc, data);
03118 }
03119 
03120 static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent) {
03121        xmlNodePtr ret;
03122        encodePtr list_enc = NULL;
03123 
03124        if (enc->sdl_type && enc->sdl_type->kind == XSD_TYPEKIND_LIST && enc->sdl_type->elements) {
03125               sdlTypePtr *type;
03126 
03127               zend_hash_internal_pointer_reset(enc->sdl_type->elements);
03128               if (zend_hash_get_current_data(enc->sdl_type->elements, (void**)&type) == SUCCESS) {
03129                      list_enc = (*type)->encode;
03130               }
03131        }
03132 
03133        ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
03134        xmlAddChild(parent, ret);
03135        FIND_ZVAL_NULL(data, ret, style);
03136        if (Z_TYPE_P(data) == IS_ARRAY) {
03137               zval **tmp;
03138               smart_str list = {0};
03139               HashTable *ht = Z_ARRVAL_P(data);
03140 
03141               zend_hash_internal_pointer_reset(ht);
03142               while (zend_hash_get_current_data(ht, (void**)&tmp) == SUCCESS) {
03143                      xmlNodePtr dummy = master_to_xml(list_enc, *tmp, SOAP_LITERAL, ret);
03144                      if (dummy && dummy->children && dummy->children->content) {
03145                             if (list.len != 0) {
03146                                    smart_str_appendc(&list, ' ');
03147                             }
03148                             smart_str_appends(&list, (char*)dummy->children->content);
03149                      } else {
03150                             soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
03151                      }
03152                      xmlUnlinkNode(dummy);
03153                      xmlFreeNode(dummy);
03154                      zend_hash_move_forward(ht);
03155               }
03156               smart_str_0(&list);
03157               xmlNodeSetContentLen(ret, BAD_CAST(list.c), list.len);
03158               smart_str_free(&list);
03159        } else {
03160               zval tmp = *data;
03161               char *str, *start, *next;
03162               smart_str list = {0};
03163 
03164               if (Z_TYPE_P(data) != IS_STRING) {
03165                      zval_copy_ctor(&tmp);
03166                      convert_to_string(&tmp);
03167                      data = &tmp;
03168               }
03169               str = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
03170               whiteSpace_collapse(BAD_CAST(str));
03171               start = str;
03172               while (start != NULL && *start != '\0') {
03173                      xmlNodePtr dummy;
03174                      zval dummy_zval;
03175 
03176                      next = strchr(start,' ');
03177                      if (next != NULL) {
03178                        *next = '\0';
03179                        next++;
03180                      }
03181                      ZVAL_STRING(&dummy_zval, start, 0);
03182                      dummy = master_to_xml(list_enc, &dummy_zval, SOAP_LITERAL, ret);
03183                      if (dummy && dummy->children && dummy->children->content) {
03184                             if (list.len != 0) {
03185                                    smart_str_appendc(&list, ' ');
03186                             }
03187                             smart_str_appends(&list, (char*)dummy->children->content);
03188                      } else {
03189                             soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
03190                      }
03191                      xmlUnlinkNode(dummy);
03192                      xmlFreeNode(dummy);
03193 
03194                      start = next;
03195               }
03196               smart_str_0(&list);
03197               xmlNodeSetContentLen(ret, BAD_CAST(list.c), list.len);
03198               smart_str_free(&list);
03199               efree(str);
03200               if (data == &tmp) {zval_dtor(&tmp);}
03201        }
03202        return ret;
03203 }
03204 
03205 static xmlNodePtr to_xml_list1(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent) {
03206        /*FIXME: minLength=1 */
03207        return to_xml_list(enc,data,style, parent);
03208 }
03209 
03210 static zval* to_zval_union(encodeTypePtr enc, xmlNodePtr data) {
03211        /*FIXME*/
03212        return to_zval_list(enc, data);
03213 }
03214 
03215 static xmlNodePtr to_xml_union(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent) {
03216        /*FIXME*/
03217        return to_xml_list(enc,data,style, parent);
03218 }
03219 
03220 static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data)
03221 {
03222        xmlBufferPtr buf;
03223        zval *ret;
03224        TSRMLS_FETCH();
03225 
03226        if (SOAP_GLOBAL(sdl) && SOAP_GLOBAL(sdl)->elements && data->name) {
03227               smart_str nscat = {0};             
03228               sdlTypePtr *sdl_type;
03229 
03230               if (data->ns && data->ns->href) {
03231                      smart_str_appends(&nscat, (char*)data->ns->href);
03232                      smart_str_appendc(&nscat, ':');                  
03233               }
03234               smart_str_appends(&nscat, (char*)data->name);
03235               smart_str_0(&nscat);
03236 
03237               if (zend_hash_find(SOAP_GLOBAL(sdl)->elements, nscat.c, nscat.len+1, (void **)&sdl_type) == SUCCESS &&
03238                   (*sdl_type)->encode) {
03239                      smart_str_free(&nscat);
03240                      return master_to_zval_int((*sdl_type)->encode, data);
03241               }             
03242               smart_str_free(&nscat);
03243        }
03244 
03245        buf = xmlBufferCreate();
03246        xmlNodeDump(buf, NULL, data, 0, 0);
03247        MAKE_STD_ZVAL(ret);
03248        ZVAL_STRING(ret, (char*)xmlBufferContent(buf), 1);
03249        xmlBufferFree(buf);
03250        return ret;
03251 }
03252 
03253 static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
03254 {
03255        xmlNodePtr ret = NULL;
03256 
03257        if (Z_TYPE_P(data) == IS_ARRAY) {
03258               HashPosition pos;
03259               zval **el;
03260               encodePtr enc = get_conversion(XSD_ANYXML);
03261               char *name;
03262               uint name_len;
03263               ulong idx;
03264 
03265               for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(data), &pos);
03266                    zend_hash_get_current_data_ex(Z_ARRVAL_P(data), (void **) &el, &pos) == SUCCESS;
03267                    zend_hash_move_forward_ex(Z_ARRVAL_P(data), &pos)) {
03268                      ret = master_to_xml(enc, *el, style, parent);
03269                   if (ret &&
03270                       ret->name != xmlStringTextNoenc &&
03271                       zend_hash_get_current_key_ex(Z_ARRVAL_P(data), &name, &name_len, &idx, 0, &pos) == HASH_KEY_IS_STRING) {
03272                             xmlNodeSetName(ret, BAD_CAST(name));
03273                   }
03274               }
03275               return ret;
03276        }
03277        if (Z_TYPE_P(data) == IS_STRING) {
03278               ret = xmlNewTextLen(BAD_CAST(Z_STRVAL_P(data)), Z_STRLEN_P(data));
03279        } else {
03280               zval tmp = *data;
03281 
03282               zval_copy_ctor(&tmp);
03283               convert_to_string(&tmp);
03284               ret = xmlNewTextLen(BAD_CAST(Z_STRVAL(tmp)), Z_STRLEN(tmp));
03285               zval_dtor(&tmp);
03286        }
03287 
03288        ret->name = xmlStringTextNoenc;
03289        ret->parent = parent;
03290        ret->doc = parent->doc;
03291        ret->prev = parent->last;
03292        ret->next = NULL;
03293        if (parent->last) {
03294               parent->last->next = ret;
03295        } else {
03296               parent->children = ret;
03297        }
03298        parent->last = ret;
03299 
03300        return ret;
03301 }
03302 
03303 zval *sdl_guess_convert_zval(encodeTypePtr enc, xmlNodePtr data)
03304 {
03305        sdlTypePtr type;
03306 
03307        type = enc->sdl_type;
03308        if (type == NULL) {
03309               return guess_zval_convert(enc, data);
03310        }
03311 /*FIXME: restriction support
03312        if (type && type->restrictions &&
03313            data &&  data->children && data->children->content) {
03314               if (type->restrictions->whiteSpace && type->restrictions->whiteSpace->value) {
03315                      if (strcmp(type->restrictions->whiteSpace->value,"replace") == 0) {
03316                             whiteSpace_replace(data->children->content);
03317                      } else if (strcmp(type->restrictions->whiteSpace->value,"collapse") == 0) {
03318                             whiteSpace_collapse(data->children->content);
03319                      }
03320               }
03321               if (type->restrictions->enumeration) {
03322                      if (!zend_hash_exists(type->restrictions->enumeration,data->children->content,strlen(data->children->content)+1)) {
03323                             soap_error1(E_WARNING, "Encoding: Restriction: invalid enumeration value \"%s\"", data->children->content);
03324                      }
03325               }
03326               if (type->restrictions->minLength &&
03327                   strlen(data->children->content) < type->restrictions->minLength->value) {
03328                 soap_error0(E_WARNING, "Encoding: Restriction: length less than 'minLength'");
03329               }
03330               if (type->restrictions->maxLength &&
03331                   strlen(data->children->content) > type->restrictions->maxLength->value) {
03332                 soap_error0(E_WARNING, "Encoding: Restriction: length greater than 'maxLength'");
03333               }
03334               if (type->restrictions->length &&
03335                   strlen(data->children->content) != type->restrictions->length->value) {
03336                 soap_error0(E_WARNING, "Encoding: Restriction: length is not equal to 'length'");
03337               }
03338        }
03339 */
03340        switch (type->kind) {
03341               case XSD_TYPEKIND_SIMPLE:
03342                      if (type->encode && enc != &type->encode->details) {
03343                             return master_to_zval_int(type->encode, data);
03344                      } else {
03345                             return guess_zval_convert(enc, data);
03346                      }
03347                      break;
03348               case XSD_TYPEKIND_LIST:
03349                      return to_zval_list(enc, data);
03350               case XSD_TYPEKIND_UNION:
03351                      return to_zval_union(enc, data);
03352               case XSD_TYPEKIND_COMPLEX:
03353               case XSD_TYPEKIND_RESTRICTION:
03354               case XSD_TYPEKIND_EXTENSION:
03355                      if (type->encode &&
03356                          (type->encode->details.type == IS_ARRAY ||
03357                           type->encode->details.type == SOAP_ENC_ARRAY)) {
03358                             return to_zval_array(enc, data);
03359                      }
03360                      return to_zval_object(enc, data);
03361               default:
03362               soap_error0(E_ERROR, "Encoding: Internal Error");
03363                      return guess_zval_convert(enc, data);
03364        }
03365 }
03366 
03367 xmlNodePtr sdl_guess_convert_xml(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent)
03368 {
03369        sdlTypePtr type;
03370        xmlNodePtr ret = NULL;
03371 
03372        type = enc->sdl_type;
03373 
03374        if (type == NULL) {
03375               ret = guess_xml_convert(enc, data, style, parent);
03376               if (style == SOAP_ENCODED) {
03377                      set_ns_and_type(ret, enc);
03378               }
03379               return ret;
03380        }
03381 /*FIXME: restriction support
03382        if (type) {
03383               if (type->restrictions && Z_TYPE_P(data) == IS_STRING) {
03384                      if (type->restrictions->enumeration) {
03385                             if (!zend_hash_exists(type->restrictions->enumeration,Z_STRVAL_P(data),Z_STRLEN_P(data)+1)) {
03386                                    soap_error1(E_WARNING, "Encoding: Restriction: invalid enumeration value \"%s\".", Z_STRVAL_P(data));
03387                             }
03388                      }
03389                      if (type->restrictions->minLength &&
03390                          Z_STRLEN_P(data) < type->restrictions->minLength->value) {
03391                      soap_error0(E_WARNING, "Encoding: Restriction: length less than 'minLength'");
03392                      }
03393                      if (type->restrictions->maxLength &&
03394                          Z_STRLEN_P(data) > type->restrictions->maxLength->value) {
03395                      soap_error0(E_WARNING, "Encoding: Restriction: length greater than 'maxLength'");
03396                      }
03397                      if (type->restrictions->length &&
03398                          Z_STRLEN_P(data) != type->restrictions->length->value) {
03399                      soap_error0(E_WARNING, "Encoding: Restriction: length is not equal to 'length'");
03400                      }
03401               }
03402        }
03403 */
03404        switch(type->kind) {
03405               case XSD_TYPEKIND_SIMPLE:
03406                      if (type->encode && enc != &type->encode->details) {
03407                             ret = master_to_xml(type->encode, data, style, parent);
03408                      } else {
03409                             ret = guess_xml_convert(enc, data, style, parent);
03410                      }
03411                      break;
03412               case XSD_TYPEKIND_LIST:
03413                      ret = to_xml_list(enc, data, style, parent);
03414                      break;
03415               case XSD_TYPEKIND_UNION:
03416                      ret = to_xml_union(enc, data, style, parent);
03417                      break;
03418               case XSD_TYPEKIND_COMPLEX:
03419               case XSD_TYPEKIND_RESTRICTION:
03420               case XSD_TYPEKIND_EXTENSION:
03421                      if (type->encode &&
03422                          (type->encode->details.type == IS_ARRAY ||
03423                           type->encode->details.type == SOAP_ENC_ARRAY)) {
03424                             return to_xml_array(enc, data, style, parent);
03425                      } else {
03426                             return to_xml_object(enc, data, style, parent);
03427                      }
03428                      break;
03429               default:
03430               soap_error0(E_ERROR, "Encoding: Internal Error");
03431                      break;
03432        }
03433        if (style == SOAP_ENCODED) {
03434               set_ns_and_type(ret, enc);
03435        }
03436        return ret;
03437 }
03438 
03439 static xmlNodePtr check_and_resolve_href(xmlNodePtr data)
03440 {
03441        if (data && data->properties) {
03442               xmlAttrPtr href;
03443 
03444               href = data->properties;
03445               while (1) {
03446                      href = get_attribute(href, "href");
03447                      if (href == NULL || href->ns == NULL) {break;}
03448                      href = href->next;
03449               }
03450               if (href) {
03451                      /*  Internal href try and find node */
03452                      if (href->children->content[0] == '#') {
03453                             xmlNodePtr ret = get_node_with_attribute_recursive(data->doc->children, NULL, "id", (char*)&href->children->content[1]);
03454                             if (!ret) {
03455                                    soap_error1(E_ERROR, "Encoding: Unresolved reference '%s'", href->children->content);
03456                             }
03457                             return ret;
03458                      } else {
03459                             /*  TODO: External href....? */
03460                             soap_error1(E_ERROR, "Encoding: External reference '%s'", href->children->content);
03461                      }
03462               }
03463               /* SOAP 1.2 enc:id enc:ref */
03464               href = get_attribute_ex(data->properties, "ref", SOAP_1_2_ENC_NAMESPACE);
03465               if (href) {
03466                      xmlChar* id;
03467                      xmlNodePtr ret;
03468 
03469                      if (href->children->content[0] == '#') {
03470                             id = href->children->content+1;
03471                      } else {
03472                             id = href->children->content;
03473                      }
03474                      ret = get_node_with_attribute_recursive_ex(data->doc->children, NULL, NULL, "id", (char*)id, SOAP_1_2_ENC_NAMESPACE);
03475                      if (!ret) {
03476                             soap_error1(E_ERROR, "Encoding: Unresolved reference '%s'", href->children->content);
03477                      } else if (ret == data) {
03478                             soap_error1(E_ERROR, "Encoding: Violation of id and ref information items '%s'", href->children->content);
03479                      }
03480                      return ret;
03481               }
03482        }
03483        return data;
03484 }
03485 
03486 static void set_ns_and_type(xmlNodePtr node, encodeTypePtr type)
03487 {
03488        set_ns_and_type_ex(node, type->ns, type->type_str);
03489 }
03490 
03491 static void set_ns_and_type_ex(xmlNodePtr node, char *ns, char *type)
03492 {
03493        smart_str nstype = {0};
03494        get_type_str(node, ns, type, &nstype);
03495        set_xsi_type(node, nstype.c);
03496        smart_str_free(&nstype);
03497 }
03498 
03499 static xmlNsPtr xmlSearchNsPrefixByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href)
03500 {
03501        xmlNsPtr cur;
03502        xmlNodePtr orig = node;
03503 
03504        while (node) {
03505               if (node->type == XML_ENTITY_REF_NODE ||
03506                   node->type == XML_ENTITY_NODE ||
03507                   node->type == XML_ENTITY_DECL) {
03508                      return NULL;
03509               }
03510               if (node->type == XML_ELEMENT_NODE) {
03511                      cur = node->nsDef;
03512                      while (cur != NULL) {
03513                             if (cur->prefix && cur->href && xmlStrEqual(cur->href, href)) {
03514                                    if (xmlSearchNs(doc, node, cur->prefix) == cur) {
03515                                           return cur;
03516                                    }
03517                             }
03518                             cur = cur->next;
03519                      }
03520                      if (orig != node) {
03521                             cur = node->ns;
03522                             if (cur != NULL) {
03523                                    if (cur->prefix && cur->href && xmlStrEqual(cur->href, href)) {
03524                                           if (xmlSearchNs(doc, node, cur->prefix) == cur) {
03525                                                  return cur;
03526                                           }
03527                                    }
03528                             }
03529                      }    
03530               }
03531               node = node->parent;
03532        }
03533        return NULL;
03534 }
03535 
03536 xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns)
03537 {
03538        xmlNsPtr xmlns;
03539 
03540        if (ns == NULL) {
03541          return NULL;
03542        }
03543 
03544        xmlns = xmlSearchNsByHref(node->doc, node, BAD_CAST(ns));
03545        if (xmlns != NULL && xmlns->prefix == NULL) {
03546               xmlns = xmlSearchNsPrefixByHref(node->doc, node, BAD_CAST(ns));
03547        }
03548        if (xmlns == NULL) {
03549               xmlChar* prefix;
03550               TSRMLS_FETCH();
03551 
03552               if (zend_hash_find(&SOAP_GLOBAL(defEncNs), (char*)ns, strlen(ns) + 1, (void **)&prefix) == SUCCESS) {
03553                      xmlns = xmlNewNs(node->doc->children, BAD_CAST(ns), prefix);
03554               } else {
03555                      smart_str prefix = {0};
03556                      int num = ++SOAP_GLOBAL(cur_uniq_ns);
03557 
03558                      while (1) {
03559                             smart_str_appendl(&prefix, "ns", 2);
03560                             smart_str_append_long(&prefix, num);
03561                             smart_str_0(&prefix);
03562                             if (xmlSearchNs(node->doc, node, BAD_CAST(prefix.c)) == NULL) {
03563                                    break;
03564                             }
03565                             smart_str_free(&prefix);
03566                             prefix.c = NULL;
03567                             prefix.len = 0;
03568                             num = ++SOAP_GLOBAL(cur_uniq_ns);
03569                      }
03570 
03571                      xmlns = xmlNewNs(node->doc->children, BAD_CAST(ns), BAD_CAST(prefix.c));
03572                      smart_str_free(&prefix);
03573               }
03574        }
03575        return xmlns;
03576 }
03577 
03578 static void set_ns_prop(xmlNodePtr node, char *ns, char *name, char *val)
03579 {
03580        xmlSetNsProp(node, encode_add_ns(node, ns), BAD_CAST(name), BAD_CAST(val));
03581 }
03582 
03583 static void set_xsi_nil(xmlNodePtr node)
03584 {
03585        set_ns_prop(node, XSI_NAMESPACE, "nil", "true");
03586 }
03587 
03588 static void set_xsi_type(xmlNodePtr node, char *type)
03589 {
03590        set_ns_prop(node, XSI_NAMESPACE, "type", type);
03591 }
03592 
03593 void encode_reset_ns()
03594 {
03595        TSRMLS_FETCH();
03596        SOAP_GLOBAL(cur_uniq_ns) = 0;
03597        SOAP_GLOBAL(cur_uniq_ref) = 0;
03598        if (SOAP_GLOBAL(ref_map)) {
03599               zend_hash_destroy(SOAP_GLOBAL(ref_map));
03600        } else {
03601               SOAP_GLOBAL(ref_map) = emalloc(sizeof(HashTable));
03602        }
03603        zend_hash_init(SOAP_GLOBAL(ref_map), 0, NULL, NULL, 0);
03604 }
03605 
03606 void encode_finish()
03607 {
03608        TSRMLS_FETCH();
03609        SOAP_GLOBAL(cur_uniq_ns) = 0;
03610        SOAP_GLOBAL(cur_uniq_ref) = 0;
03611        if (SOAP_GLOBAL(ref_map)) {
03612               zend_hash_destroy(SOAP_GLOBAL(ref_map));
03613               efree(SOAP_GLOBAL(ref_map));
03614               SOAP_GLOBAL(ref_map) = NULL;
03615        }
03616 }
03617 
03618 encodePtr get_conversion(int encode)
03619 {
03620        encodePtr *enc = NULL;
03621        TSRMLS_FETCH();
03622 
03623        if (zend_hash_index_find(&SOAP_GLOBAL(defEncIndex), encode, (void **)&enc) == FAILURE) {
03624               soap_error0(E_ERROR,  "Encoding: Cannot find encoding");
03625               return NULL;
03626        } else {
03627               return *enc;
03628        }
03629 }
03630 
03631 static int is_map(zval *array)
03632 {
03633        int i, count = zend_hash_num_elements(Z_ARRVAL_P(array));
03634 
03635        zend_hash_internal_pointer_reset(Z_ARRVAL_P(array));
03636        for (i = 0; i < count; i++) {
03637               char *str_index;
03638               ulong num_index;
03639 
03640               if (zend_hash_get_current_key(Z_ARRVAL_P(array), &str_index, &num_index, 0) == HASH_KEY_IS_STRING ||
03641                   num_index != i) {
03642                      return TRUE;
03643               }
03644               zend_hash_move_forward(Z_ARRVAL_P(array));
03645        }
03646        return FALSE;
03647 }
03648 
03649 static encodePtr get_array_type(xmlNodePtr node, zval *array, smart_str *type TSRMLS_DC)
03650 {
03651        HashTable *ht;
03652        int i, count, cur_type, prev_type, different;
03653        zval **tmp;
03654        char *prev_stype = NULL, *cur_stype = NULL, *prev_ns = NULL, *cur_ns = NULL;
03655 
03656        if (!array || Z_TYPE_P(array) != IS_ARRAY) {
03657               smart_str_appendl(type, "xsd:anyType", sizeof("xsd:anyType")-1);
03658               return get_conversion(XSD_ANYTYPE);
03659        }
03660 
03661        different = FALSE;
03662        cur_type = prev_type = 0;
03663        ht = HASH_OF(array);
03664        count = zend_hash_num_elements(ht);
03665 
03666        zend_hash_internal_pointer_reset(ht);
03667        for (i = 0;i < count;i++) {
03668               zend_hash_get_current_data(ht, (void **)&tmp);
03669 
03670               if (Z_TYPE_PP(tmp) == IS_OBJECT &&
03671                   Z_OBJCE_PP(tmp) == soap_var_class_entry) {
03672                      zval **ztype;
03673 
03674                      if (zend_hash_find(Z_OBJPROP_PP(tmp), "enc_type", sizeof("enc_type"), (void **)&ztype) == FAILURE) {
03675                             soap_error0(E_ERROR,  "Encoding: SoapVar has no 'enc_type' property");
03676                      }
03677                      cur_type = Z_LVAL_PP(ztype);
03678 
03679                      if (zend_hash_find(Z_OBJPROP_PP(tmp), "enc_stype", sizeof("enc_stype"), (void **)&ztype) == SUCCESS) {
03680                             cur_stype = Z_STRVAL_PP(ztype);
03681                      } else {
03682                             cur_stype = NULL;
03683                      }
03684 
03685                      if (zend_hash_find(Z_OBJPROP_PP(tmp), "enc_ns", sizeof("enc_ns"), (void **)&ztype) == SUCCESS) {
03686                             cur_ns = Z_STRVAL_PP(ztype);
03687                      } else {
03688                             cur_ns = NULL;
03689                      }
03690 
03691               } else if (Z_TYPE_PP(tmp) == IS_ARRAY && is_map(*tmp)) {
03692                      cur_type = APACHE_MAP;
03693                      cur_stype = NULL;
03694                      cur_ns = NULL;
03695               } else {
03696                      cur_type = Z_TYPE_PP(tmp);
03697                      cur_stype = NULL;
03698                      cur_ns = NULL;
03699               }
03700 
03701               if (i > 0) {
03702                      if ((cur_type != prev_type) ||
03703                          (cur_stype != NULL && prev_stype != NULL && strcmp(cur_stype,prev_stype) != 0) ||
03704                          (cur_stype == NULL && cur_stype != prev_stype) ||
03705                          (cur_ns != NULL && prev_ns != NULL && strcmp(cur_ns,prev_ns) != 0) ||
03706                          (cur_ns == NULL && cur_ns != prev_ns)) {
03707                             different = TRUE;
03708                             break;
03709                      }
03710               }
03711 
03712               prev_type = cur_type;
03713               prev_stype = cur_stype;
03714               prev_ns = cur_ns;
03715               zend_hash_move_forward(ht);
03716        }
03717 
03718        if (different || count == 0) {
03719               smart_str_appendl(type, "xsd:anyType", sizeof("xsd:anyType")-1);
03720               return get_conversion(XSD_ANYTYPE);
03721        } else {
03722               encodePtr enc;
03723 
03724               if (cur_stype != NULL) {
03725                      smart_str array_type = {0};
03726 
03727                      if (cur_ns) {
03728                             xmlNsPtr ns = encode_add_ns(node,cur_ns);
03729 
03730                             smart_str_appends(type, (char*)ns->prefix);
03731                             smart_str_appendc(type, ':');
03732                             smart_str_appends(&array_type, cur_ns);
03733                             smart_str_appendc(&array_type, ':');
03734                      }
03735                      smart_str_appends(type, cur_stype);
03736                      smart_str_0(type);
03737                      smart_str_appends(&array_type, cur_stype);
03738                      smart_str_0(&array_type);
03739 
03740                      enc = get_encoder_ex(SOAP_GLOBAL(sdl), array_type.c, array_type.len);
03741                      smart_str_free(&array_type);
03742                      return enc;
03743               } else {
03744                      enc = get_conversion(cur_type);
03745                      get_type_str(node, enc->details.ns, enc->details.type_str, type);
03746                      return enc;
03747               }
03748        }
03749 }
03750 
03751 static void get_type_str(xmlNodePtr node, const char* ns, const char* type, smart_str* ret)
03752 {
03753        TSRMLS_FETCH();
03754 
03755        if (ns) {
03756               xmlNsPtr xmlns;
03757               if (SOAP_GLOBAL(soap_version) == SOAP_1_2 &&
03758                   strcmp(ns,SOAP_1_1_ENC_NAMESPACE) == 0) {
03759                      ns = SOAP_1_2_ENC_NAMESPACE;
03760               } else if (SOAP_GLOBAL(soap_version) == SOAP_1_1 &&
03761                          strcmp(ns,SOAP_1_2_ENC_NAMESPACE) == 0) {
03762                      ns = SOAP_1_1_ENC_NAMESPACE;
03763               }
03764               xmlns = encode_add_ns(node,ns);
03765               smart_str_appends(ret, (char*)xmlns->prefix);
03766               smart_str_appendc(ret, ':');
03767        }
03768        smart_str_appendl(ret, type, strlen(type));
03769        smart_str_0(ret);
03770 }
03771 
03772 static void delete_mapping(void *data)
03773 {
03774        soapMappingPtr map = (soapMappingPtr)data;
03775 
03776        if (map->to_xml) {
03777               zval_ptr_dtor(&map->to_xml);
03778        }
03779        if (map->to_zval) {
03780               zval_ptr_dtor(&map->to_zval);
03781        }
03782        efree(map);
03783 }
03784 
03785 void delete_encoder(void *encode)
03786 {
03787        encodePtr t = *((encodePtr*)encode);
03788        if (t->details.ns) {
03789               efree(t->details.ns);
03790        }
03791        if (t->details.type_str) {
03792               efree(t->details.type_str);
03793        }
03794        if (t->details.map) {
03795               delete_mapping(t->details.map);
03796        }
03797        efree(t);
03798 }
03799 
03800 void delete_encoder_persistent(void *encode)
03801 {
03802        encodePtr t = *((encodePtr*)encode);
03803        if (t->details.ns) {
03804               free(t->details.ns);
03805        }
03806        if (t->details.type_str) {
03807               free(t->details.type_str);
03808        }
03809        /* we should never have mapping in persistent encoder */
03810        assert(t->details.map == NULL);
03811        free(t);
03812 }