root/ext/soap/php_encoding.c

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

DEFINITIONS

This source file includes following definitions.
  1. whiteSpace_replace
  2. whiteSpace_collapse
  3. find_encoder_by_type_name
  4. soap_check_zval_ref
  5. soap_check_xml_ref
  6. soap_add_xml_ref
  7. master_to_xml_int
  8. master_to_xml
  9. master_to_zval_int
  10. master_to_zval
  11. to_xml_user
  12. to_zval_user
  13. to_zval_string
  14. to_zval_stringr
  15. to_zval_stringc
  16. to_zval_base64
  17. to_zval_hexbin
  18. to_xml_string
  19. to_xml_base64
  20. to_xml_hexbin
  21. to_zval_double
  22. to_zval_long
  23. to_xml_long
  24. to_xml_double
  25. to_zval_bool
  26. to_xml_bool
  27. to_zval_null
  28. to_xml_null
  29. set_zval_property
  30. get_zval_property
  31. unset_zval_property
  32. model_to_zval_any
  33. model_to_zval_object
  34. to_zval_object_ex
  35. to_zval_object
  36. model_to_xml_object
  37. model_array_element
  38. to_xml_object
  39. guess_array_map
  40. calc_dimension_12
  41. get_position_12
  42. calc_dimension
  43. get_position_ex
  44. get_position
  45. add_xml_array_elements
  46. array_num_elements
  47. to_xml_array
  48. to_zval_array
  49. to_xml_map
  50. to_zval_map
  51. guess_xml_convert
  52. guess_zval_convert
  53. to_xml_datetime_ex
  54. to_xml_duration
  55. to_xml_datetime
  56. to_xml_time
  57. to_xml_date
  58. to_xml_gyearmonth
  59. to_xml_gyear
  60. to_xml_gmonthday
  61. to_xml_gday
  62. to_xml_gmonth
  63. to_zval_list
  64. to_xml_list
  65. to_xml_list1
  66. to_zval_union
  67. to_xml_union
  68. to_zval_any
  69. to_xml_any
  70. sdl_guess_convert_zval
  71. sdl_guess_convert_xml
  72. check_and_resolve_href
  73. set_ns_and_type
  74. set_ns_and_type_ex
  75. xmlSearchNsPrefixByHref
  76. encode_add_ns
  77. set_ns_prop
  78. set_xsi_nil
  79. set_xsi_type
  80. encode_reset_ns
  81. encode_finish
  82. get_conversion
  83. is_map
  84. get_array_type
  85. get_type_str
  86. delete_mapping
  87. delete_encoder
  88. delete_encoder_persistent

   1 /*
   2   +----------------------------------------------------------------------+
   3   | PHP Version 7                                                        |
   4   +----------------------------------------------------------------------+
   5   | Copyright (c) 1997-2016 The PHP Group                                |
   6   +----------------------------------------------------------------------+
   7   | This source file is subject to version 3.01 of the PHP license,      |
   8   | that is bundled with this package in the file LICENSE, and is        |
   9   | available through the world-wide-web at the following url:           |
  10   | http://www.php.net/license/3_01.txt                                  |
  11   | If you did not receive a copy of the PHP license and are unable to   |
  12   | obtain it through the world-wide-web, please send a note to          |
  13   | license@php.net so we can mail you a copy immediately.               |
  14   +----------------------------------------------------------------------+
  15   | Authors: Brad Lafountain <rodif_bl@yahoo.com>                        |
  16   |          Shane Caraveo <shane@caraveo.com>                           |
  17   |          Dmitry Stogov <dmitry@zend.com>                             |
  18   +----------------------------------------------------------------------+
  19 */
  20 /* $Id$ */
  21 
  22 #include <time.h>
  23 
  24 #include "php_soap.h"
  25 #include "ext/libxml/php_libxml.h"
  26 #include "ext/standard/base64.h"
  27 #include <libxml/parserInternals.h>
  28 #include "zend_strtod.h"
  29 #include "zend_interfaces.h"
  30 
  31 /* zval type decode */
  32 static zval *to_zval_double(zval* ret, encodeTypePtr type, xmlNodePtr data);
  33 static zval *to_zval_long(zval* ret, encodeTypePtr type, xmlNodePtr data);
  34 static zval *to_zval_bool(zval* ret, encodeTypePtr type, xmlNodePtr data);
  35 static zval *to_zval_string(zval* ret, encodeTypePtr type, xmlNodePtr data);
  36 static zval *to_zval_stringr(zval* ret, encodeTypePtr type, xmlNodePtr data);
  37 static zval *to_zval_stringc(zval* ret, encodeTypePtr type, xmlNodePtr data);
  38 static zval *to_zval_map(zval* ret, encodeTypePtr type, xmlNodePtr data);
  39 static zval *to_zval_null(zval* ret, encodeTypePtr type, xmlNodePtr data);
  40 static zval *to_zval_base64(zval* ret, encodeTypePtr type, xmlNodePtr data);
  41 static zval *to_zval_hexbin(zval* ret, encodeTypePtr type, xmlNodePtr data);
  42 
  43 static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  44 static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  45 static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  46 
  47 /* String encode */
  48 static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  49 static xmlNodePtr to_xml_base64(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  50 static xmlNodePtr to_xml_hexbin(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  51 
  52 /* Null encode */
  53 static xmlNodePtr to_xml_null(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  54 
  55 /* Array encode */
  56 static xmlNodePtr guess_array_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  57 static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  58 
  59 static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent);
  60 static xmlNodePtr to_xml_list1(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent);
  61 
  62 /* Datetime encode/decode */
  63 static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, int style, xmlNodePtr parent);
  64 static xmlNodePtr to_xml_datetime(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  65 static xmlNodePtr to_xml_time(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  66 static xmlNodePtr to_xml_date(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  67 static xmlNodePtr to_xml_gyearmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  68 static xmlNodePtr to_xml_gyear(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  69 static xmlNodePtr to_xml_gmonthday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  70 static xmlNodePtr to_xml_gday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  71 static xmlNodePtr to_xml_gmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  72 static xmlNodePtr to_xml_duration(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  73 
  74 static zval *to_zval_object(zval *ret, encodeTypePtr type, xmlNodePtr data);
  75 static zval *to_zval_array(zval *ret, encodeTypePtr type, xmlNodePtr data);
  76 
  77 static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  78 static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  79 
  80 static zval *to_zval_any(zval *ret, encodeTypePtr type, xmlNodePtr data);
  81 static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  82 
  83 /* Try and guess for non-wsdl clients and servers */
  84 static zval *guess_zval_convert(zval *ret, encodeTypePtr type, xmlNodePtr data);
  85 static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  86 
  87 static int is_map(zval *array);
  88 static encodePtr get_array_type(xmlNodePtr node, zval *array, smart_str *out_type);
  89 
  90 static xmlNodePtr check_and_resolve_href(xmlNodePtr data);
  91 
  92 static void set_ns_prop(xmlNodePtr node, char *ns, char *name, char *val);
  93 static void set_xsi_nil(xmlNodePtr node);
  94 static void set_xsi_type(xmlNodePtr node, char *type);
  95 
  96 static void get_type_str(xmlNodePtr node, const char* ns, const char* type, smart_str* ret);
  97 static void set_ns_and_type_ex(xmlNodePtr node, char *ns, char *type);
  98 
  99 static void set_ns_and_type(xmlNodePtr node, encodeTypePtr type);
 100 
 101 #define FIND_XML_NULL(xml,zval) \
 102         { \
 103                 xmlAttrPtr null; \
 104                 if (!xml) { \
 105                         ZVAL_NULL(zval); \
 106                         return zval; \
 107                 } \
 108                 if (xml->properties) { \
 109                         null = get_attribute(xml->properties, "nil"); \
 110                         if (null) { \
 111                                 ZVAL_NULL(zval); \
 112                                 return zval; \
 113                         } \
 114                 } \
 115         }
 116 
 117 #define CHECK_XML_NULL(xml) \
 118         { \
 119                 xmlAttrPtr null; \
 120                 if (!xml) { \
 121                         ZVAL_NULL(ret); \
 122                         return ret; \
 123                 } \
 124                 if (xml->properties) { \
 125                         null = get_attribute(xml->properties, "nil"); \
 126                         if (null) { \
 127                                 ZVAL_NULL(ret); \
 128                                 return ret; \
 129                         } \
 130                 } \
 131         }
 132 
 133 #define FIND_ZVAL_NULL(zval, xml, style) \
 134 { \
 135         if (!zval || Z_TYPE_P(zval) == IS_NULL) { \
 136           if (style == SOAP_ENCODED) {\
 137                         set_xsi_nil(xml); \
 138                 } \
 139                 return xml; \
 140         } \
 141 }
 142 
 143 encode defaultEncoding[] = {
 144         {{UNKNOWN_TYPE, NULL, NULL, NULL}, guess_zval_convert, guess_xml_convert},
 145 
 146         {{IS_NULL, "nil", XSI_NAMESPACE, NULL}, to_zval_null, to_xml_null},
 147         {{IS_STRING, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
 148         {{IS_LONG, XSD_INT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 149         {{IS_DOUBLE, XSD_FLOAT_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_double},
 150         {{IS_FALSE, XSD_BOOLEAN_STRING, XSD_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
 151         {{IS_TRUE, XSD_BOOLEAN_STRING, XSD_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
 152         {{IS_CONSTANT, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
 153         {{IS_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_array, guess_array_map},
 154         {{IS_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
 155         {{IS_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_array, guess_array_map},
 156         {{IS_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
 157 
 158         {{XSD_STRING, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
 159         {{XSD_BOOLEAN, XSD_BOOLEAN_STRING, XSD_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
 160         {{XSD_DECIMAL, XSD_DECIMAL_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
 161         {{XSD_FLOAT, XSD_FLOAT_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_double},
 162         {{XSD_DOUBLE, XSD_DOUBLE_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_double},
 163 
 164         {{XSD_DATETIME, XSD_DATETIME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_datetime},
 165         {{XSD_TIME, XSD_TIME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_time},
 166         {{XSD_DATE, XSD_DATE_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_date},
 167         {{XSD_GYEARMONTH, XSD_GYEARMONTH_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gyearmonth},
 168         {{XSD_GYEAR, XSD_GYEAR_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gyear},
 169         {{XSD_GMONTHDAY, XSD_GMONTHDAY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gmonthday},
 170         {{XSD_GDAY, XSD_GDAY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gday},
 171         {{XSD_GMONTH, XSD_GMONTH_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gmonth},
 172         {{XSD_DURATION, XSD_DURATION_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_duration},
 173 
 174         {{XSD_HEXBINARY, XSD_HEXBINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_hexbin, to_xml_hexbin},
 175         {{XSD_BASE64BINARY, XSD_BASE64BINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_base64, to_xml_base64},
 176 
 177         {{XSD_LONG, XSD_LONG_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 178         {{XSD_INT, XSD_INT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 179         {{XSD_SHORT, XSD_SHORT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 180         {{XSD_BYTE, XSD_BYTE_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 181         {{XSD_NONPOSITIVEINTEGER, XSD_NONPOSITIVEINTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 182         {{XSD_POSITIVEINTEGER, XSD_POSITIVEINTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 183         {{XSD_NONNEGATIVEINTEGER, XSD_NONNEGATIVEINTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 184         {{XSD_NEGATIVEINTEGER, XSD_NEGATIVEINTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 185         {{XSD_UNSIGNEDBYTE, XSD_UNSIGNEDBYTE_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 186         {{XSD_UNSIGNEDSHORT, XSD_UNSIGNEDSHORT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 187         {{XSD_UNSIGNEDINT, XSD_UNSIGNEDINT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 188         {{XSD_UNSIGNEDLONG, XSD_UNSIGNEDLONG_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 189         {{XSD_INTEGER, XSD_INTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 190 
 191         {{XSD_ANYTYPE, XSD_ANYTYPE_STRING, XSD_NAMESPACE, NULL}, guess_zval_convert, guess_xml_convert},
 192         {{XSD_UR_TYPE, XSD_UR_TYPE_STRING, XSD_NAMESPACE, NULL}, guess_zval_convert, guess_xml_convert},
 193         {{XSD_ANYURI, XSD_ANYURI_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
 194         {{XSD_QNAME, XSD_QNAME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
 195         {{XSD_NOTATION, XSD_NOTATION_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
 196         {{XSD_NORMALIZEDSTRING, XSD_NORMALIZEDSTRING_STRING, XSD_NAMESPACE, NULL}, to_zval_stringr, to_xml_string},
 197         {{XSD_TOKEN, XSD_TOKEN_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
 198         {{XSD_LANGUAGE, XSD_LANGUAGE_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
 199         {{XSD_NMTOKEN, XSD_NMTOKEN_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
 200         {{XSD_NMTOKENS, XSD_NMTOKENS_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_list1},
 201         {{XSD_NAME, XSD_NAME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
 202         {{XSD_NCNAME, XSD_NCNAME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
 203         {{XSD_ID, XSD_ID_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
 204         {{XSD_IDREF, XSD_IDREF_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
 205         {{XSD_IDREFS, XSD_IDREFS_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_list1},
 206         {{XSD_ENTITY, XSD_ENTITY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
 207         {{XSD_ENTITIES, XSD_ENTITIES_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_list1},
 208 
 209         {{APACHE_MAP, APACHE_MAP_STRING, APACHE_NAMESPACE, NULL}, to_zval_map, to_xml_map},
 210 
 211         {{SOAP_ENC_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
 212         {{SOAP_ENC_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
 213         {{SOAP_ENC_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
 214         {{SOAP_ENC_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
 215 
 216         /* support some of the 1999 data types */
 217         {{XSD_STRING, XSD_STRING_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_string, to_xml_string},
 218         {{XSD_BOOLEAN, XSD_BOOLEAN_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
 219         {{XSD_DECIMAL, XSD_DECIMAL_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
 220         {{XSD_FLOAT, XSD_FLOAT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_double, to_xml_double},
 221         {{XSD_DOUBLE, XSD_DOUBLE_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_double, to_xml_double},
 222 
 223         {{XSD_LONG, XSD_LONG_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 224         {{XSD_INT, XSD_INT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 225         {{XSD_SHORT, XSD_SHORT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 226         {{XSD_BYTE, XSD_BYTE_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 227         {{XSD_1999_TIMEINSTANT, XSD_1999_TIMEINSTANT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
 228 
 229         {{XSD_ANYXML, "<anyXML>", "<anyXML>", NULL}, to_zval_any, to_xml_any},
 230 
 231         {{END_KNOWN_TYPES, NULL, NULL, NULL}, guess_zval_convert, guess_xml_convert}
 232 };
 233 
 234 int numDefaultEncodings = sizeof(defaultEncoding)/sizeof(encode);
 235 
 236 
 237 void whiteSpace_replace(xmlChar* str)
 238 {
 239         while (*str != '\0') {
 240                 if (*str == '\x9' || *str == '\xA' || *str == '\xD') {
 241                         *str = ' ';
 242                 }
 243                 str++;
 244         }
 245 }
 246 
 247 void whiteSpace_collapse(xmlChar* str)
 248 {
 249         xmlChar *pos;
 250         xmlChar old;
 251 
 252         pos = str;
 253         whiteSpace_replace(str);
 254         while (*str == ' ') {
 255                 str++;
 256         }
 257         old = '\0';
 258         while (*str != '\0') {
 259                 if (*str != ' ' || old != ' ') {
 260                         *pos = *str;
 261                         pos++;
 262                 }
 263                 old = *str;
 264                 str++;
 265         }
 266         if (old == ' ') {
 267                 --pos;
 268         }
 269         *pos = '\0';
 270 }
 271 
 272 static encodePtr find_encoder_by_type_name(sdlPtr sdl, const char *type)
 273 {
 274         if (sdl && sdl->encoders) {
 275                 encodePtr enc;
 276 
 277                 ZEND_HASH_FOREACH_PTR(sdl->encoders, enc)  {
 278                     if (strcmp(enc->details.type_str, type) == 0) {
 279                                 return enc;
 280                         }
 281                 } ZEND_HASH_FOREACH_END();
 282         }
 283         return NULL;
 284 }
 285 
 286 static zend_bool soap_check_zval_ref(zval *data, xmlNodePtr node) {
 287         xmlNodePtr node_ptr;
 288 
 289         if (SOAP_GLOBAL(ref_map)) {
 290                 if (Z_TYPE_P(data) == IS_OBJECT) {
 291                         data = (zval*)Z_OBJ_P(data);
 292                 }
 293                 if ((node_ptr = zend_hash_index_find_ptr(SOAP_GLOBAL(ref_map), (zend_ulong)data)) != NULL) {
 294                         xmlAttrPtr attr = node_ptr->properties;
 295                         char *id;
 296                         smart_str prefix = {0};
 297 
 298                         if (node_ptr == node) {
 299                                 return 0;
 300                         }
 301                         xmlNodeSetName(node, node_ptr->name);
 302                         xmlSetNs(node, node_ptr->ns);
 303                         if (SOAP_GLOBAL(soap_version) == SOAP_1_1) {
 304                                 while (1) {
 305                                         attr = get_attribute(attr, "id");
 306                                         if (attr == NULL || attr->ns == NULL) {
 307                                                 break;
 308                                         }
 309                                         attr = attr->next;
 310                                 }
 311                                 if (attr) {
 312                                         id = (char*)attr->children->content;
 313                                         smart_str_appendc(&prefix, '#');
 314                                         smart_str_appends(&prefix, id);
 315                                         smart_str_0(&prefix);
 316                                         id = ZSTR_VAL(prefix.s);
 317                                 } else {
 318                                         SOAP_GLOBAL(cur_uniq_ref)++;
 319                                         smart_str_appendl(&prefix, "#ref", 4);
 320                                         smart_str_append_long(&prefix, SOAP_GLOBAL(cur_uniq_ref));
 321                                         smart_str_0(&prefix);
 322                                         id = ZSTR_VAL(prefix.s);
 323                                         xmlSetProp(node_ptr, BAD_CAST("id"), BAD_CAST(id+1));
 324                                 }
 325                                 xmlSetProp(node, BAD_CAST("href"), BAD_CAST(id));
 326                         } else {
 327                                 attr = get_attribute_ex(attr, "id", SOAP_1_2_ENC_NAMESPACE);
 328                                 if (attr) {
 329                                         id = (char*)attr->children->content;
 330                                         smart_str_appendc(&prefix, '#');
 331                                         smart_str_appends(&prefix, id);
 332                                         smart_str_0(&prefix);
 333                                         id = ZSTR_VAL(prefix.s);
 334                                 } else {
 335                                         SOAP_GLOBAL(cur_uniq_ref)++;
 336                                         smart_str_appendl(&prefix, "#ref", 4);
 337                                         smart_str_append_long(&prefix, SOAP_GLOBAL(cur_uniq_ref));
 338                                         smart_str_0(&prefix);
 339                                         id = ZSTR_VAL(prefix.s);
 340                                         set_ns_prop(node_ptr, SOAP_1_2_ENC_NAMESPACE, "id", id+1);
 341                                 }
 342                                 set_ns_prop(node, SOAP_1_2_ENC_NAMESPACE, "ref", id);
 343                         }
 344                         smart_str_free(&prefix);
 345                         return 1;
 346                 } else {
 347                         zend_hash_index_update_ptr(SOAP_GLOBAL(ref_map), (zend_ulong)data, node);
 348                 }
 349         }
 350         return 0;
 351 }
 352 
 353 static zend_bool soap_check_xml_ref(zval *data, xmlNodePtr node)
 354 {
 355         zval *data_ptr;
 356 
 357         if (SOAP_GLOBAL(ref_map)) {
 358                 if ((data_ptr = zend_hash_index_find(SOAP_GLOBAL(ref_map), (zend_ulong)node)) != NULL) {
 359                         if (!Z_REFCOUNTED_P(data) ||
 360                             !Z_REFCOUNTED_P(data_ptr) ||
 361                             Z_COUNTED_P(data) != Z_COUNTED_P(data_ptr)) {
 362                                 zval_ptr_dtor(data);
 363                                 ZVAL_COPY(data, data_ptr);
 364                                 return 1;
 365                         }
 366                 }
 367         }
 368         return 0;
 369 }
 370 
 371 static void soap_add_xml_ref(zval *data, xmlNodePtr node)
 372 {
 373         if (SOAP_GLOBAL(ref_map)) {
 374                 zend_hash_index_update(SOAP_GLOBAL(ref_map), (zend_ulong)node, data);
 375         }
 376 }
 377 
 378 static xmlNodePtr master_to_xml_int(encodePtr encode, zval *data, int style, xmlNodePtr parent, int check_class_map)
 379 {
 380         xmlNodePtr node = NULL;
 381         int add_type = 0;
 382 
 383         /* Special handling of class SoapVar */
 384         if (data &&
 385             Z_TYPE_P(data) == IS_OBJECT &&
 386             Z_OBJCE_P(data) == soap_var_class_entry) {
 387                 zval *ztype, *zdata, *zns, *zstype, *zname, *znamens;
 388                 encodePtr enc = NULL;
 389                 HashTable *ht = Z_OBJPROP_P(data);
 390 
 391                 if ((ztype = zend_hash_str_find(ht, "enc_type", sizeof("enc_type")-1)) == NULL ||
 392                     Z_TYPE_P(ztype) != IS_LONG) {
 393                         soap_error0(E_ERROR, "Encoding: SoapVar has no 'enc_type' property");
 394                 }
 395 
 396                 if ((zstype = zend_hash_str_find(ht, "enc_stype", sizeof("enc_stype")-1)) != NULL &&
 397                     Z_TYPE_P(zstype) == IS_STRING) {
 398                         if ((zns = zend_hash_str_find(ht, "enc_ns", sizeof("enc_ns")-1)) != NULL &&
 399                             Z_TYPE_P(zns) == IS_STRING) {
 400                                 enc = get_encoder(SOAP_GLOBAL(sdl), Z_STRVAL_P(zns), Z_STRVAL_P(zstype));
 401                         } else {
 402                                 zns = NULL;
 403                                 enc = get_encoder_ex(SOAP_GLOBAL(sdl), Z_STRVAL_P(zstype), Z_STRLEN_P(zstype));
 404                         }
 405                         if (enc == NULL && SOAP_GLOBAL(typemap)) {
 406                                 smart_str nscat = {0};
 407 
 408                                 if (zns != NULL) {
 409                                         smart_str_appendl(&nscat, Z_STRVAL_P(zns), Z_STRLEN_P(zns));
 410                                         smart_str_appendc(&nscat, ':');
 411                                 }
 412                                 smart_str_appendl(&nscat, Z_STRVAL_P(zstype), Z_STRLEN_P(zstype));
 413                                 smart_str_0(&nscat);
 414                                 enc = zend_hash_find_ptr(SOAP_GLOBAL(typemap), nscat.s);
 415                                 smart_str_free(&nscat);
 416                         }
 417                 }
 418                 if (enc == NULL) {
 419                         enc = get_conversion(Z_LVAL_P(ztype));
 420                 }
 421                 if (enc == NULL) {
 422                         enc = encode;
 423                 }
 424 
 425                 zdata = zend_hash_str_find(ht, "enc_value", sizeof("enc_value")-1);
 426                 node = master_to_xml(enc, zdata, style, parent);
 427 
 428                 if (style == SOAP_ENCODED || (SOAP_GLOBAL(sdl) && encode != enc)) {
 429                         if ((zstype = zend_hash_str_find(ht, "enc_stype", sizeof("enc_stype")-1)) != NULL &&
 430                             Z_TYPE_P(zstype) == IS_STRING) {
 431                                 if ((zns = zend_hash_str_find(ht, "enc_ns", sizeof("enc_ns")-1)) != NULL &&
 432                                     Z_TYPE_P(zns) == IS_STRING) {
 433                                         set_ns_and_type_ex(node, Z_STRVAL_P(zns), Z_STRVAL_P(zstype));
 434                                 } else {
 435                                         set_ns_and_type_ex(node, NULL, Z_STRVAL_P(zstype));
 436                                 }
 437                         }
 438                 }
 439 
 440                 if ((zname = zend_hash_str_find(ht, "enc_name", sizeof("enc_name")-1)) != NULL &&
 441                     Z_TYPE_P(zname) == IS_STRING) {
 442                         xmlNodeSetName(node, BAD_CAST(Z_STRVAL_P(zname)));
 443                 }
 444                 if ((znamens = zend_hash_str_find(ht, "enc_namens", sizeof("enc_namens")-1)) != NULL &&
 445                     Z_TYPE_P(znamens) == IS_STRING) {
 446                         xmlNsPtr nsp = encode_add_ns(node, Z_STRVAL_P(znamens));
 447                         xmlSetNs(node, nsp);
 448                 }
 449         } else {
 450                 if (check_class_map && SOAP_GLOBAL(class_map) && data &&
 451                     Z_TYPE_P(data) == IS_OBJECT &&
 452                     !ZEND_HASH_GET_APPLY_COUNT(Z_OBJPROP_P(data))) {
 453                         zend_class_entry *ce = Z_OBJCE_P(data);
 454                         zval *tmp;
 455                         zend_string *type_name;
 456 
 457                         ZEND_HASH_FOREACH_STR_KEY_VAL(SOAP_GLOBAL(class_map), type_name, tmp) {
 458                                 if (Z_TYPE_P(tmp) == IS_STRING &&
 459                                     ZSTR_LEN(ce->name) == Z_STRLEN_P(tmp) &&
 460                                     zend_binary_strncasecmp(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), Z_STRVAL_P(tmp), ZSTR_LEN(ce->name), ZSTR_LEN(ce->name)) == 0 &&
 461                                     type_name) {
 462 
 463                                         /* TODO: namespace isn't stored */
 464                                         encodePtr enc = NULL;
 465                                         if (SOAP_GLOBAL(sdl)) {
 466                                                 enc = get_encoder(SOAP_GLOBAL(sdl), SOAP_GLOBAL(sdl)->target_ns, ZSTR_VAL(type_name));
 467                                                 if (!enc) {
 468                                                         enc = find_encoder_by_type_name(SOAP_GLOBAL(sdl), ZSTR_VAL(type_name));
 469                                                 }
 470                                         }
 471                                         if (enc) {
 472                                                 if (encode != enc && style == SOAP_LITERAL) {
 473                                                         add_type = 1;
 474                                                 }
 475                                                 encode = enc;
 476                                         }
 477                                         break;
 478                                 }
 479                         } ZEND_HASH_FOREACH_END();
 480                 }
 481 
 482                 if (encode == NULL) {
 483                         encode = get_conversion(UNKNOWN_TYPE);
 484                 }
 485                 if (SOAP_GLOBAL(typemap) && encode->details.type_str) {
 486                         smart_str nscat = {0};
 487                         encodePtr new_enc;
 488 
 489                         if (encode->details.ns) {
 490                                 smart_str_appends(&nscat, encode->details.ns);
 491                                 smart_str_appendc(&nscat, ':');
 492                         }
 493                         smart_str_appends(&nscat, encode->details.type_str);
 494                         smart_str_0(&nscat);
 495                         if ((new_enc = zend_hash_find_ptr(SOAP_GLOBAL(typemap), nscat.s)) != NULL) {
 496                                 encode = new_enc;
 497                         }
 498                         smart_str_free(&nscat);
 499                 }
 500                 if (encode->to_xml) {
 501                         node = encode->to_xml(&encode->details, data, style, parent);
 502                         if (add_type) {
 503                                 set_ns_and_type(node, &encode->details);
 504                         }
 505                 }
 506         }
 507         return node;
 508 }
 509 
 510 xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr parent)
 511 {
 512         return master_to_xml_int(encode, data, style, parent, 1);
 513 }
 514 
 515 static zval *master_to_zval_int(zval *ret, encodePtr encode, xmlNodePtr data)
 516 {
 517         if (SOAP_GLOBAL(typemap)) {
 518                 if (encode->details.type_str) {
 519                         smart_str nscat = {0};
 520                         encodePtr new_enc;
 521 
 522                         if (encode->details.ns) {
 523                                 smart_str_appends(&nscat, encode->details.ns);
 524                                 smart_str_appendc(&nscat, ':');
 525                         }
 526                         smart_str_appends(&nscat, encode->details.type_str);
 527                         smart_str_0(&nscat);
 528                         if ((new_enc = zend_hash_find_ptr(SOAP_GLOBAL(typemap), nscat.s)) != NULL) {
 529                                 encode = new_enc;
 530                         }
 531                         smart_str_free(&nscat);
 532                 } else {
 533                         xmlAttrPtr type_attr = get_attribute_ex(data->properties,"type", XSI_NAMESPACE);
 534 
 535                         if (type_attr != NULL) {
 536                                 encodePtr new_enc;
 537                                 xmlNsPtr nsptr;
 538                                 char *ns, *cptype;
 539                                 smart_str nscat = {0};
 540 
 541                                 parse_namespace(type_attr->children->content, &cptype, &ns);
 542                                 nsptr = xmlSearchNs(data->doc, data, BAD_CAST(ns));
 543                                 if (nsptr != NULL) {
 544                                         smart_str_appends(&nscat, (char*)nsptr->href);
 545                                         smart_str_appendc(&nscat, ':');
 546                                 }
 547                                 smart_str_appends(&nscat, cptype);
 548                                 smart_str_0(&nscat);
 549                                 efree(cptype);
 550                                 if (ns) {efree(ns);}
 551                                 if ((new_enc = zend_hash_find_ptr(SOAP_GLOBAL(typemap), nscat.s)) != NULL) {
 552                                         encode = new_enc;
 553                                 }
 554                                 smart_str_free(&nscat);
 555                         }
 556                 }
 557         }
 558         if (encode->to_zval) {
 559                 ret = encode->to_zval(ret, &encode->details, data);
 560         }
 561         return ret;
 562 }
 563 
 564 zval *master_to_zval(zval *ret, encodePtr encode, xmlNodePtr data)
 565 {
 566         data = check_and_resolve_href(data);
 567 
 568         if (encode == NULL) {
 569                 encode = get_conversion(UNKNOWN_TYPE);
 570         } else {
 571                 /* Use xsi:type if it is defined */
 572                 xmlAttrPtr type_attr = get_attribute_ex(data->properties,"type", XSI_NAMESPACE);
 573 
 574                 if (type_attr != NULL) {
 575                         encodePtr  enc = get_encoder_from_prefix(SOAP_GLOBAL(sdl), data, type_attr->children->content);
 576 
 577                         if (enc != NULL && enc != encode) {
 578                           encodePtr tmp = enc;
 579                           while (tmp &&
 580                                  tmp->details.sdl_type != NULL &&
 581                                  tmp->details.sdl_type->kind != XSD_TYPEKIND_COMPLEX) {
 582                             if (enc == tmp->details.sdl_type->encode ||
 583                                 tmp == tmp->details.sdl_type->encode) {
 584                                 enc = NULL;
 585                                 break;
 586                             }
 587                             tmp = tmp->details.sdl_type->encode;
 588                           }
 589                           if (enc != NULL) {
 590                             encode = enc;
 591                           }
 592                         }
 593                 }
 594         }
 595         return master_to_zval_int(ret, encode, data);
 596 }
 597 
 598 xmlNodePtr to_xml_user(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
 599 {
 600         xmlNodePtr ret = NULL;
 601         zval return_value;
 602 
 603         if (type && type->map && Z_TYPE(type->map->to_xml) != IS_UNDEF) {
 604                 ZVAL_NULL(&return_value);
 605 
 606                 if (call_user_function(EG(function_table), NULL, &type->map->to_xml, &return_value, 1, data) == FAILURE) {
 607                         soap_error0(E_ERROR, "Encoding: Error calling to_xml callback");
 608                 }
 609                 if (Z_TYPE(return_value) == IS_STRING) {
 610                         xmlDocPtr doc = soap_xmlParseMemory(Z_STRVAL(return_value), Z_STRLEN(return_value));
 611                         if (doc && doc->children) {
 612                                 ret = xmlDocCopyNode(doc->children, parent->doc, 1);
 613                         }
 614                         xmlFreeDoc(doc);
 615                 }
 616 
 617                 zval_ptr_dtor(&return_value);
 618         }
 619         if (!ret) {
 620                 ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
 621         }
 622         xmlAddChild(parent, ret);
 623         if (style == SOAP_ENCODED) {
 624                 set_ns_and_type(ret, type);
 625         }
 626         return ret;
 627 }
 628 
 629 zval *to_zval_user(zval *ret, encodeTypePtr type, xmlNodePtr node)
 630 {
 631         if (type && type->map && Z_TYPE(type->map->to_zval) != IS_UNDEF) {
 632                 xmlBufferPtr buf;
 633                 zval data;
 634                 xmlNodePtr copy;
 635 
 636                 copy = xmlCopyNode(node, 1);
 637                 buf = xmlBufferCreate();
 638                 xmlNodeDump(buf, NULL, copy, 0, 0);
 639                 ZVAL_STRING(&data, (char*)xmlBufferContent(buf));
 640                 xmlBufferFree(buf);
 641                 xmlFreeNode(copy);
 642 
 643                 if (call_user_function(EG(function_table), NULL, &type->map->to_zval, ret, 1, &data) == FAILURE) {
 644                         soap_error0(E_ERROR, "Encoding: Error calling from_xml callback");
 645                 } else if (EG(exception)) {
 646                         ZVAL_NULL(ret);
 647                 }
 648                 zval_ptr_dtor(&data);
 649         } else {
 650                 ZVAL_NULL(ret);
 651         }
 652         return ret;
 653 }
 654 
 655 /* TODO: get rid of "bogus".. ither by passing in the already created xmlnode or passing in the node name */
 656 /* String encode/decode */
 657 static zval *to_zval_string(zval *ret, encodeTypePtr type, xmlNodePtr data)
 658 {
 659         ZVAL_NULL(ret);
 660         FIND_XML_NULL(data, ret);
 661         if (data && data->children) {
 662                 if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
 663                         if (SOAP_GLOBAL(encoding) != NULL) {
 664                                 xmlBufferPtr in  = xmlBufferCreateStatic(data->children->content, xmlStrlen(data->children->content));
 665                                 xmlBufferPtr out = xmlBufferCreate();
 666                                 int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
 667 
 668                                 if (n >= 0) {
 669                                         ZVAL_STRING(ret, (char*)xmlBufferContent(out));
 670                                 } else {
 671                                         ZVAL_STRING(ret, (char*)data->children->content);
 672                                 }
 673                                 xmlBufferFree(out);
 674                                 xmlBufferFree(in);
 675                         } else {
 676                                 ZVAL_STRING(ret, (char*)data->children->content);
 677                         }
 678                 } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
 679                         ZVAL_STRING(ret, (char*)data->children->content);
 680                 } else {
 681                         soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
 682                 }
 683         } else {
 684                 ZVAL_EMPTY_STRING(ret);
 685         }
 686         return ret;
 687 }
 688 
 689 static zval *to_zval_stringr(zval *ret, encodeTypePtr type, xmlNodePtr data)
 690 {
 691         ZVAL_NULL(ret);
 692         FIND_XML_NULL(data, ret);
 693         if (data && data->children) {
 694                 if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
 695                         whiteSpace_replace(data->children->content);
 696                         if (SOAP_GLOBAL(encoding) != NULL) {
 697                                 xmlBufferPtr in  = xmlBufferCreateStatic(data->children->content, xmlStrlen(data->children->content));
 698                                 xmlBufferPtr out = xmlBufferCreate();
 699                                 int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
 700 
 701                                 if (n >= 0) {
 702                                         ZVAL_STRING(ret, (char*)xmlBufferContent(out));
 703                                 } else {
 704                                         ZVAL_STRING(ret, (char*)data->children->content);
 705                                 }
 706                                 xmlBufferFree(out);
 707                                 xmlBufferFree(in);
 708                         } else {
 709                                 ZVAL_STRING(ret, (char*)data->children->content);
 710                         }
 711                 } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
 712                         ZVAL_STRING(ret, (char*)data->children->content);
 713                 } else {
 714                         soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
 715                 }
 716         } else {
 717                 ZVAL_EMPTY_STRING(ret);
 718         }
 719         return ret;
 720 }
 721 
 722 static zval *to_zval_stringc(zval *ret, encodeTypePtr type, xmlNodePtr data)
 723 {
 724         ZVAL_NULL(ret);
 725         FIND_XML_NULL(data, ret);
 726         if (data && data->children) {
 727                 if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
 728                         whiteSpace_collapse(data->children->content);
 729                         if (SOAP_GLOBAL(encoding) != NULL) {
 730                                 xmlBufferPtr in  = xmlBufferCreateStatic(data->children->content, xmlStrlen(data->children->content));
 731                                 xmlBufferPtr out = xmlBufferCreate();
 732                                 int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
 733 
 734                                 if (n >= 0) {
 735                                         ZVAL_STRING(ret, (char*)xmlBufferContent(out));
 736                                 } else {
 737                                         ZVAL_STRING(ret, (char*)data->children->content);
 738                                 }
 739                                 xmlBufferFree(out);
 740                                 xmlBufferFree(in);
 741                         } else {
 742                                 ZVAL_STRING(ret, (char*)data->children->content);
 743                         }
 744                 } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
 745                         ZVAL_STRING(ret, (char*)data->children->content);
 746                 } else {
 747                         soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
 748                 }
 749         } else {
 750                 ZVAL_EMPTY_STRING(ret);
 751         }
 752         return ret;
 753 }
 754 
 755 static zval *to_zval_base64(zval *ret, encodeTypePtr type, xmlNodePtr data)
 756 {
 757         zend_string *str;
 758 
 759         ZVAL_NULL(ret);
 760         FIND_XML_NULL(data, ret);
 761         if (data && data->children) {
 762                 if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
 763                         whiteSpace_collapse(data->children->content);
 764                         str = php_base64_decode(data->children->content, strlen((char*)data->children->content));
 765                         if (!str) {
 766                                 soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
 767                         }
 768                         ZVAL_STR(ret, str);
 769                 } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
 770                         str = php_base64_decode(data->children->content, strlen((char*)data->children->content));
 771                         if (!str) {
 772                                 soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
 773                         }
 774                         ZVAL_STR(ret, str);
 775                 } else {
 776                         soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
 777                 }
 778         } else {
 779                 ZVAL_EMPTY_STRING(ret);
 780         }
 781         return ret;
 782 }
 783 
 784 static zval *to_zval_hexbin(zval *ret, encodeTypePtr type, xmlNodePtr data)
 785 {
 786         zend_string *str;
 787         int i, j;
 788         unsigned char c;
 789 
 790         ZVAL_NULL(ret);
 791         FIND_XML_NULL(data, ret);
 792         if (data && data->children) {
 793                 if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
 794                         whiteSpace_collapse(data->children->content);
 795                 } else if (data->children->type != XML_CDATA_SECTION_NODE || data->children->next != NULL) {
 796                         soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
 797                         return ret;
 798                 }
 799                 str = zend_string_alloc(strlen((char*)data->children->content) / 2, 0);
 800                 for (i = j = 0; i < ZSTR_LEN(str); i++) {
 801                         c = data->children->content[j++];
 802                         if (c >= '0' && c <= '9') {
 803                                 ZSTR_VAL(str)[i] = (c - '0') << 4;
 804                         } else if (c >= 'a' && c <= 'f') {
 805                                 ZSTR_VAL(str)[i] = (c - 'a' + 10) << 4;
 806                         } else if (c >= 'A' && c <= 'F') {
 807                                 ZSTR_VAL(str)[i] = (c - 'A' + 10) << 4;
 808                         } else {
 809                                 soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
 810                         }
 811                         c = data->children->content[j++];
 812                         if (c >= '0' && c <= '9') {
 813                                 ZSTR_VAL(str)[i] |= c - '0';
 814                         } else if (c >= 'a' && c <= 'f') {
 815                                 ZSTR_VAL(str)[i] |= c - 'a' + 10;
 816                         } else if (c >= 'A' && c <= 'F') {
 817                                 ZSTR_VAL(str)[i] |= c - 'A' + 10;
 818                         } else {
 819                                 soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
 820                         }
 821                 }
 822                 ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
 823                 ZVAL_NEW_STR(ret, str);
 824         } else {
 825                 ZVAL_EMPTY_STRING(ret);
 826         }
 827         return ret;
 828 }
 829 
 830 static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
 831 {
 832         xmlNodePtr ret, text;
 833         char *str;
 834         int new_len;
 835 
 836         ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
 837         xmlAddChild(parent, ret);
 838         FIND_ZVAL_NULL(data, ret, style);
 839 
 840         if (Z_TYPE_P(data) == IS_STRING) {
 841                 str = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
 842                 new_len = Z_STRLEN_P(data);
 843         } else {
 844                 zend_string *tmp = zval_get_string(data);
 845                 str = estrndup(ZSTR_VAL(tmp), ZSTR_LEN(tmp));
 846                 new_len = ZSTR_LEN(tmp);
 847                 zend_string_release(tmp);
 848         }
 849 
 850         if (SOAP_GLOBAL(encoding) != NULL) {
 851                 xmlBufferPtr in  = xmlBufferCreateStatic(str, new_len);
 852                 xmlBufferPtr out = xmlBufferCreate();
 853                 int n = xmlCharEncInFunc(SOAP_GLOBAL(encoding), out, in);
 854 
 855                 if (n >= 0) {
 856                         efree(str);
 857                         str = estrdup((char*)xmlBufferContent(out));
 858                         new_len = n;
 859                 }
 860                 xmlBufferFree(out);
 861                 xmlBufferFree(in);
 862         }
 863 
 864         if (!php_libxml_xmlCheckUTF8(BAD_CAST(str))) {
 865                 char *err = emalloc(new_len + 8);
 866                 char c;
 867                 int i;
 868 
 869                 memcpy(err, str, new_len+1);
 870                 for (i = 0; (c = err[i++]);) {
 871                         if ((c & 0x80) == 0) {
 872                         } else if ((c & 0xe0) == 0xc0) {
 873                                 if ((err[i] & 0xc0) != 0x80) {
 874                                         break;
 875                                 }
 876                                 i++;
 877                         } else if ((c & 0xf0) == 0xe0) {
 878                                 if ((err[i] & 0xc0) != 0x80 || (err[i+1] & 0xc0) != 0x80) {
 879                                         break;
 880                                 }
 881                                 i += 2;
 882                         } else if ((c & 0xf8) == 0xf0) {
 883                                 if ((err[i] & 0xc0) != 0x80 || (err[i+1] & 0xc0) != 0x80 || (err[i+2] & 0xc0) != 0x80) {
 884                                         break;
 885                                 }
 886                                 i += 3;
 887                         } else {
 888                                 break;
 889                         }
 890                 }
 891                 if (c) {
 892                         err[i-1] = '\\';
 893                         err[i++] = 'x';
 894                         err[i++] = ((unsigned char)c >> 4) + ((((unsigned char)c >> 4) > 9) ? ('a' - 10) : '0');
 895                         err[i++] = (c & 15) + (((c & 15) > 9) ? ('a' - 10) : '0');
 896                         err[i++] = '.';
 897                         err[i++] = '.';
 898                         err[i++] = '.';
 899                         err[i++] = 0;
 900                 }
 901 
 902                 soap_error1(E_ERROR,  "Encoding: string '%s' is not a valid utf-8 string", err);
 903         }
 904 
 905         text = xmlNewTextLen(BAD_CAST(str), new_len);
 906         xmlAddChild(ret, text);
 907         efree(str);
 908 
 909         if (style == SOAP_ENCODED) {
 910                 set_ns_and_type(ret, type);
 911         }
 912         return ret;
 913 }
 914 
 915 static xmlNodePtr to_xml_base64(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
 916 {
 917         xmlNodePtr ret, text;
 918         zend_string *str;
 919 
 920         ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
 921         xmlAddChild(parent, ret);
 922         FIND_ZVAL_NULL(data, ret, style);
 923 
 924         if (Z_TYPE_P(data) == IS_STRING) {
 925                 str = php_base64_encode((unsigned char*)Z_STRVAL_P(data), Z_STRLEN_P(data));
 926         } else {
 927                 zend_string *tmp = zval_get_string(data);
 928                 str = php_base64_encode((unsigned char*) ZSTR_VAL(tmp), ZSTR_LEN(tmp));
 929                 zend_string_release(tmp);
 930         }
 931 
 932         text = xmlNewTextLen(BAD_CAST(ZSTR_VAL(str)), ZSTR_LEN(str));
 933         xmlAddChild(ret, text);
 934         zend_string_release(str);
 935 
 936         if (style == SOAP_ENCODED) {
 937                 set_ns_and_type(ret, type);
 938         }
 939         return ret;
 940 }
 941 
 942 static xmlNodePtr to_xml_hexbin(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
 943 {
 944         static char hexconvtab[] = "0123456789ABCDEF";
 945         xmlNodePtr ret, text;
 946         unsigned char *str;
 947         zval tmp;
 948         int i, j;
 949 
 950         ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
 951         xmlAddChild(parent, ret);
 952         FIND_ZVAL_NULL(data, ret, style);
 953 
 954         if (Z_TYPE_P(data) != IS_STRING) {
 955                 ZVAL_STR(&tmp, zval_get_string(data));
 956                 data = &tmp;
 957         }
 958         str = (unsigned char *) safe_emalloc(Z_STRLEN_P(data) * 2, sizeof(char), 1);
 959 
 960         for (i = j = 0; i < Z_STRLEN_P(data); i++) {
 961                 str[j++] = hexconvtab[((unsigned char)Z_STRVAL_P(data)[i]) >> 4];
 962                 str[j++] = hexconvtab[((unsigned char)Z_STRVAL_P(data)[i]) & 15];
 963         }
 964         str[j] = '\0';
 965 
 966         text = xmlNewTextLen(str, Z_STRLEN_P(data) * 2 * sizeof(char));
 967         xmlAddChild(ret, text);
 968         efree(str);
 969         if (data == &tmp) {
 970                 zval_dtor(&tmp);
 971         }
 972 
 973         if (style == SOAP_ENCODED) {
 974                 set_ns_and_type(ret, type);
 975         }
 976         return ret;
 977 }
 978 
 979 static zval *to_zval_double(zval *ret, encodeTypePtr type, xmlNodePtr data)
 980 {
 981         ZVAL_NULL(ret);
 982         FIND_XML_NULL(data, ret);
 983 
 984         if (data && data->children) {
 985                 if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
 986                         zend_long lval;
 987                         double dval;
 988 
 989                         whiteSpace_collapse(data->children->content);
 990                         switch (is_numeric_string((char*)data->children->content, strlen((char*)data->children->content), &lval, &dval, 0)) {
 991                                 case IS_LONG:
 992                                         ZVAL_DOUBLE(ret, lval);
 993                                         break;
 994                                 case IS_DOUBLE:
 995                                         ZVAL_DOUBLE(ret, dval);
 996                                         break;
 997                                 default:
 998                                         if (strncasecmp((char*)data->children->content, "NaN", sizeof("NaN")-1) == 0) {
 999                                                 ZVAL_DOUBLE(ret, php_get_nan());
1000                                         } else if (strncasecmp((char*)data->children->content, "INF", sizeof("INF")-1) == 0) {
1001                                                 ZVAL_DOUBLE(ret, php_get_inf());
1002                                         } else if (strncasecmp((char*)data->children->content, "-INF", sizeof("-INF")-1) == 0) {
1003                                                 ZVAL_DOUBLE(ret, -php_get_inf());
1004                                         } else {
1005                                                 soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
1006                                         }
1007                         }
1008                 } else {
1009                         soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
1010                 }
1011         } else {
1012                 ZVAL_NULL(ret);
1013         }
1014         return ret;
1015 }
1016 
1017 static zval *to_zval_long(zval *ret, encodeTypePtr type, xmlNodePtr data)
1018 {
1019         ZVAL_NULL(ret);
1020         FIND_XML_NULL(data, ret);
1021 
1022         if (data && data->children) {
1023                 if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
1024                         zend_long lval;
1025                         double dval;
1026 
1027                         whiteSpace_collapse(data->children->content);
1028                         errno = 0;
1029 
1030                         switch (is_numeric_string((char*)data->children->content, strlen((char*)data->children->content), &lval, &dval, 0)) {
1031                                 case IS_LONG:
1032                                         ZVAL_LONG(ret, lval);
1033                                         break;
1034                                 case IS_DOUBLE:
1035                                         ZVAL_DOUBLE(ret, dval);
1036                                         break;
1037                                 default:
1038                                         soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
1039                         }
1040                 } else {
1041                         soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
1042                 }
1043         } else {
1044                 ZVAL_NULL(ret);
1045         }
1046         return ret;
1047 }
1048 
1049 static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
1050 {
1051         xmlNodePtr ret;
1052 
1053         ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1054         xmlAddChild(parent, ret);
1055         FIND_ZVAL_NULL(data, ret, style);
1056 
1057         if (Z_TYPE_P(data) == IS_DOUBLE) {
1058                 char s[256];
1059 
1060                 snprintf(s, sizeof(s), "%0.0F",floor(Z_DVAL_P(data)));
1061                 xmlNodeSetContent(ret, BAD_CAST(s));
1062         } else {
1063                 zend_string *str = zend_long_to_str(zval_get_long(data));
1064                 xmlNodeSetContentLen(ret, BAD_CAST(ZSTR_VAL(str)), ZSTR_LEN(str));
1065                 zend_string_release(str);
1066         }
1067 
1068         if (style == SOAP_ENCODED) {
1069                 set_ns_and_type(ret, type);
1070         }
1071         return ret;
1072 }
1073 
1074 static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
1075 {
1076         xmlNodePtr ret;
1077         zval tmp;
1078         char *str;
1079 
1080         ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1081         xmlAddChild(parent, ret);
1082         FIND_ZVAL_NULL(data, ret, style);
1083 
1084         ZVAL_DOUBLE(&tmp, zval_get_double(data));
1085 
1086         str = (char *) safe_emalloc(EG(precision), 1, MAX_LENGTH_OF_DOUBLE + 1);
1087         php_gcvt(Z_DVAL(tmp), EG(precision), '.', 'E', str);
1088         xmlNodeSetContentLen(ret, BAD_CAST(str), strlen(str));
1089         efree(str);
1090 
1091         if (style == SOAP_ENCODED) {
1092                 set_ns_and_type(ret, type);
1093         }
1094         return ret;
1095 }
1096 
1097 static zval *to_zval_bool(zval *ret, encodeTypePtr type, xmlNodePtr data)
1098 {
1099         ZVAL_NULL(ret);
1100         FIND_XML_NULL(data, ret);
1101 
1102         if (data && data->children) {
1103                 if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
1104                         whiteSpace_collapse(data->children->content);
1105                         if (stricmp((char*)data->children->content, "true") == 0 ||
1106                                 stricmp((char*)data->children->content, "t") == 0 ||
1107                                 strcmp((char*)data->children->content, "1") == 0) {
1108                                 ZVAL_TRUE(ret);
1109                         } else if (stricmp((char*)data->children->content, "false") == 0 ||
1110                                 stricmp((char*)data->children->content, "f") == 0 ||
1111                                 strcmp((char*)data->children->content, "0") == 0) {
1112                                 ZVAL_FALSE(ret);
1113                         } else {
1114                                 ZVAL_STRING(ret, (char*)data->children->content);
1115                                 convert_to_boolean(ret);
1116                         }
1117                 } else {
1118                         soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
1119                 }
1120         } else {
1121                 ZVAL_NULL(ret);
1122         }
1123         return ret;
1124 }
1125 
1126 static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
1127 {
1128         xmlNodePtr ret;
1129 
1130         ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1131         xmlAddChild(parent, ret);
1132         FIND_ZVAL_NULL(data, ret, style);
1133 
1134         if (zend_is_true(data)) {
1135                 xmlNodeSetContent(ret, BAD_CAST("true"));
1136         } else {
1137                 xmlNodeSetContent(ret, BAD_CAST("false"));
1138         }
1139 
1140         if (style == SOAP_ENCODED) {
1141                 set_ns_and_type(ret, type);
1142         }
1143         return ret;
1144 }
1145 
1146 /* Null encode/decode */
1147 static zval *to_zval_null(zval *ret, encodeTypePtr type, xmlNodePtr data)
1148 {
1149         ZVAL_NULL(ret);
1150         return ret;
1151 }
1152 
1153 static xmlNodePtr to_xml_null(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
1154 {
1155         xmlNodePtr ret;
1156 
1157         ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1158         xmlAddChild(parent, ret);
1159         if (style == SOAP_ENCODED) {
1160                 set_xsi_nil(ret);
1161         }
1162         return ret;
1163 }
1164 
1165 static void set_zval_property(zval* object, char* name, zval* val)
1166 {
1167         zend_class_entry *old_scope;
1168 
1169         old_scope = EG(scope);
1170         EG(scope) = Z_OBJCE_P(object);
1171         add_property_zval(object, name, val);
1172         if (Z_REFCOUNTED_P(val)) Z_DELREF_P(val);
1173         EG(scope) = old_scope;
1174 }
1175 
1176 static zval* get_zval_property(zval* object, char* name, zval *rv)
1177 {
1178         if (Z_TYPE_P(object) == IS_OBJECT) {
1179                 zval member;
1180                 zval *data;
1181                 zend_class_entry *old_scope;
1182 
1183                 ZVAL_STRING(&member, name);
1184                 old_scope = EG(scope);
1185                 EG(scope) = Z_OBJCE_P(object);
1186                 data = Z_OBJ_HT_P(object)->read_property(object, &member, BP_VAR_IS, NULL, rv);
1187                 if (data == &EG(uninitialized_zval)) {
1188                         /* Hack for bug #32455 */
1189                         zend_property_info *property_info;
1190 
1191                         property_info = zend_get_property_info(Z_OBJCE_P(object), Z_STR(member), 1);
1192                         EG(scope) = old_scope;
1193                         if (property_info != ZEND_WRONG_PROPERTY_INFO && property_info &&
1194                             zend_hash_exists(Z_OBJPROP_P(object), property_info->name)) {
1195                                 zval_ptr_dtor(&member);
1196                                 return data;
1197                         }
1198                         zval_ptr_dtor(&member);
1199                         return NULL;
1200                 }
1201                 zval_ptr_dtor(&member);
1202                 EG(scope) = old_scope;
1203                 return data;
1204         } else if (Z_TYPE_P(object) == IS_ARRAY) {
1205                 zval *data_ptr;
1206 
1207                 if ((data_ptr = zend_hash_str_find(Z_ARRVAL_P(object), name, strlen(name))) != NULL) {
1208                   return data_ptr;
1209                 }
1210         }
1211         return NULL;
1212 }
1213 
1214 static void unset_zval_property(zval* object, char* name)
1215 {
1216         if (Z_TYPE_P(object) == IS_OBJECT) {
1217                 zval member;
1218                 zend_class_entry *old_scope;
1219 
1220                 ZVAL_STRING(&member, name);
1221                 old_scope = EG(scope);
1222                 EG(scope) = Z_OBJCE_P(object);
1223                 Z_OBJ_HT_P(object)->unset_property(object, &member, NULL);
1224                 EG(scope) = old_scope;
1225                 zval_ptr_dtor(&member);
1226         } else if (Z_TYPE_P(object) == IS_ARRAY) {
1227                 zend_hash_str_del(Z_ARRVAL_P(object), name, strlen(name));
1228         }
1229 }
1230 
1231 static void model_to_zval_any(zval *ret, xmlNodePtr node)
1232 {
1233         zval rv, arr, val;
1234         zval* any = NULL;
1235         char* name = NULL;
1236 
1237         while (node != NULL) {
1238                 if (get_zval_property(ret, (char*)node->name, &rv) == NULL) {
1239 
1240                         ZVAL_NULL(&val);
1241                         master_to_zval(&val, get_conversion(XSD_ANYXML), node);
1242 
1243                         if (any && Z_TYPE_P(any) != IS_ARRAY) {
1244                                 /* Convert into array */
1245                                 array_init(&arr);
1246                                 if (name) {
1247                                         add_assoc_zval(&arr, name, any);
1248                                 } else {
1249                                         add_next_index_zval(&arr, any);
1250                                 }
1251                                 any = &arr;
1252                         }
1253 
1254                         if (Z_TYPE(val) == IS_STRING && *Z_STRVAL(val) == '<') {
1255                                 name = NULL;
1256                                 while (node->next != NULL) {
1257                                         zval val2;
1258 
1259                                         ZVAL_NULL(&val2);
1260                                         master_to_zval(&val2, get_conversion(XSD_ANYXML), node->next);
1261                                         if (Z_TYPE(val2) != IS_STRING ||  *Z_STRVAL(val) != '<') {
1262                                                 break;
1263                                         }
1264                                         concat_function(&val, &val, &val2);
1265                                         zval_ptr_dtor(&val2);
1266                                         node = node->next;
1267                                 }
1268                         } else {
1269                                 name = (char*)node->name;
1270                         }
1271 
1272                         if (any == NULL) {
1273                                 if (name) {
1274                                         /* Convert into array */
1275                                         array_init(&arr);
1276                                         add_assoc_zval(&arr, name, &val);
1277                                         any = &arr;
1278                                         name = NULL;
1279                                 } else {
1280                                         any = &val;
1281                                 }
1282                         } else {
1283                                 /* Add array element */
1284                                 if (name) {
1285                                         zval *el;
1286                                         if ((el = zend_hash_str_find(Z_ARRVAL_P(any), name, strlen(name))) != NULL) {
1287                                                 if (Z_TYPE_P(el) != IS_ARRAY) {
1288                                                         /* Convert into array */
1289                                                         array_init(&arr);
1290                                                         add_next_index_zval(&arr, el);
1291                                                         el = &arr;
1292                                                 }
1293                                                 add_next_index_zval(el, &val);
1294                                         } else {
1295                                                 add_assoc_zval(any, name, &val);
1296                                         }
1297                                 } else {
1298                                         add_next_index_zval(any, &val);
1299                                 }
1300                                 name = NULL;
1301                         }
1302                 }
1303                 node = node->next;
1304         }
1305         if (any) {
1306                 set_zval_property(ret, name ? name : "any", any);
1307         }
1308 }
1309 
1310 static void model_to_zval_object(zval *ret, sdlContentModelPtr model, xmlNodePtr data, sdlPtr sdl)
1311 {
1312         switch (model->kind) {
1313                 case XSD_CONTENT_ELEMENT:
1314                         if (model->u.element->name) {
1315                                 xmlNodePtr node = get_node(data->children, model->u.element->name);
1316 
1317                                 if (node) {
1318                                         zval val;
1319                                         xmlNodePtr r_node;
1320 
1321                                         ZVAL_NULL(&val);
1322                                         r_node = check_and_resolve_href(node);
1323                                         if (r_node && r_node->children && r_node->children->content) {
1324                                                 if (model->u.element->fixed && strcmp(model->u.element->fixed, (char*)r_node->children->content) != 0) {
1325                                                         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);
1326                                                 }
1327                                                 master_to_zval(&val, model->u.element->encode, r_node);
1328                                         } else if (model->u.element->fixed) {
1329                                                 xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1330                                                 xmlNodeSetContent(dummy, BAD_CAST(model->u.element->fixed));
1331                                                 master_to_zval(&val, model->u.element->encode, dummy);
1332                                                 xmlFreeNode(dummy);
1333                                         } else if (model->u.element->def && !model->u.element->nillable) {
1334                                                 xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1335                                                 xmlNodeSetContent(dummy, BAD_CAST(model->u.element->def));
1336                                                 master_to_zval(&val, model->u.element->encode, dummy);
1337                                                 xmlFreeNode(dummy);
1338                                         } else {
1339                                                 master_to_zval(&val, model->u.element->encode, r_node);
1340                                         }
1341                                         if ((node = get_node(node->next, model->u.element->name)) != NULL) {
1342                                                 zval array;
1343 
1344                                                 array_init(&array);
1345                                                 add_next_index_zval(&array, &val);
1346                                                 do {
1347                                                         if (node && node->children && node->children->content) {
1348                                                                 if (model->u.element->fixed && strcmp(model->u.element->fixed, (char*)node->children->content) != 0) {
1349                                                                         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);
1350                                                                 }
1351                                                                 master_to_zval(&val, model->u.element->encode, node);
1352                                                         } else if (model->u.element->fixed) {
1353                                                                 xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1354                                                                 xmlNodeSetContent(dummy, BAD_CAST(model->u.element->fixed));
1355                                                                 master_to_zval(&val, model->u.element->encode, dummy);
1356                                                                 xmlFreeNode(dummy);
1357                                                         } else if (model->u.element->def && !model->u.element->nillable) {
1358                                                                 xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1359                                                                 xmlNodeSetContent(dummy, BAD_CAST(model->u.element->def));
1360                                                                 master_to_zval(&val, model->u.element->encode, dummy);
1361                                                                 xmlFreeNode(dummy);
1362                                                         } else {
1363                                                                 master_to_zval(&val, model->u.element->encode, node);
1364                                                         }
1365                                                         add_next_index_zval(&array, &val);
1366                                                 } while ((node = get_node(node->next, model->u.element->name)) != NULL);
1367                                                 ZVAL_COPY_VALUE(&val, &array);
1368                                         } else if ((Z_TYPE(val) != IS_NULL || !model->u.element->nillable) &&
1369                                                    (SOAP_GLOBAL(features) & SOAP_SINGLE_ELEMENT_ARRAYS) &&
1370                                                    (model->max_occurs == -1 || model->max_occurs > 1)) {
1371                                                 zval array;
1372 
1373                                                 array_init(&array);
1374                                                 add_next_index_zval(&array, &val);
1375                                                 ZVAL_COPY_VALUE(&val, &array);
1376                                         }
1377                                         set_zval_property(ret, model->u.element->name, &val);
1378                                 }
1379                         }
1380                         break;
1381                 case XSD_CONTENT_ALL:
1382                 case XSD_CONTENT_SEQUENCE:
1383                 case XSD_CONTENT_CHOICE: {
1384                         sdlContentModelPtr tmp;
1385                         sdlContentModelPtr any = NULL;
1386 
1387                         ZEND_HASH_FOREACH_PTR(model->u.content, tmp) {
1388                                 if (tmp->kind == XSD_CONTENT_ANY) {
1389                                         any = tmp;
1390                                 } else {
1391                                         model_to_zval_object(ret, tmp, data, sdl);
1392                                 }
1393                         } ZEND_HASH_FOREACH_END();
1394                         if (any) {
1395                                 model_to_zval_any(ret, data->children);
1396                         }
1397                         break;
1398                 }
1399                 case XSD_CONTENT_GROUP:
1400                         model_to_zval_object(ret, model->u.group->model, data, sdl);
1401                         break;
1402                 default:
1403                   break;
1404         }
1405 }
1406 
1407 /* Struct encode/decode */
1408 static zval *to_zval_object_ex(zval *ret, encodeTypePtr type, xmlNodePtr data, zend_class_entry *pce)
1409 {
1410         xmlNodePtr trav;
1411         sdlPtr sdl;
1412         sdlTypePtr sdlType = type->sdl_type;
1413         zend_class_entry *ce = ZEND_STANDARD_CLASS_DEF_PTR;
1414         zval *redo_any = NULL, rv, arr;
1415 
1416         if (pce) {
1417                 ce = pce;
1418         } else if (SOAP_GLOBAL(class_map) && type->type_str) {
1419                 zval              *classname;
1420                 zend_class_entry  *tmp;
1421 
1422                 if ((classname = zend_hash_str_find(SOAP_GLOBAL(class_map), type->type_str, strlen(type->type_str))) != NULL &&
1423                     Z_TYPE_P(classname) == IS_STRING &&
1424                     (tmp = zend_fetch_class(Z_STR_P(classname), ZEND_FETCH_CLASS_AUTO)) != NULL) {
1425                         ce = tmp;
1426                 }
1427         }
1428         sdl = SOAP_GLOBAL(sdl);
1429         if (sdlType) {
1430                 if (sdlType->kind == XSD_TYPEKIND_RESTRICTION &&
1431                     sdlType->encode && type != &sdlType->encode->details) {
1432                         encodePtr enc;
1433 
1434                         enc = sdlType->encode;
1435                         while (enc && enc->details.sdl_type &&
1436                                enc->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
1437                                enc->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
1438                                enc->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
1439                                 enc = enc->details.sdl_type->encode;
1440                         }
1441                         if (enc) {
1442                                 zval base;
1443 
1444                                 ZVAL_NULL(ret);
1445                                 if (soap_check_xml_ref(ret, data)) {
1446                                         return ret;
1447                                 }
1448 
1449                                 object_init_ex(ret, ce);
1450                                 master_to_zval_int(&base, enc, data);
1451                                 set_zval_property(ret, "_", &base);
1452                         } else {
1453                                 ZVAL_NULL(ret);
1454                                 FIND_XML_NULL(data, ret);
1455                                 if (soap_check_xml_ref(ret, data)) {
1456                                         return ret;
1457                                 }
1458                                 object_init_ex(ret, ce);
1459                                 soap_add_xml_ref(ret, data);
1460                         }
1461                 } else if (sdlType->kind == XSD_TYPEKIND_EXTENSION &&
1462                            sdlType->encode &&
1463                            type != &sdlType->encode->details) {
1464                         if (sdlType->encode->details.sdl_type &&
1465                             sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
1466                             sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
1467                             sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
1468 
1469                                 CHECK_XML_NULL(data);
1470                                 if (soap_check_xml_ref(ret, data)) {
1471                                         return ret;
1472                                 }
1473 
1474                             if (ce != ZEND_STANDARD_CLASS_DEF_PTR &&
1475                                 sdlType->encode->to_zval == sdl_guess_convert_zval &&
1476                                 sdlType->encode->details.sdl_type != NULL &&
1477                                 (sdlType->encode->details.sdl_type->kind == XSD_TYPEKIND_COMPLEX ||
1478                                  sdlType->encode->details.sdl_type->kind == XSD_TYPEKIND_RESTRICTION ||
1479                                  sdlType->encode->details.sdl_type->kind == XSD_TYPEKIND_EXTENSION) &&
1480                                 (sdlType->encode->details.sdl_type->encode == NULL ||
1481                                  (sdlType->encode->details.sdl_type->encode->details.type != IS_ARRAY &&
1482                                   sdlType->encode->details.sdl_type->encode->details.type != SOAP_ENC_ARRAY))) {
1483                                         to_zval_object_ex(ret, &sdlType->encode->details, data, ce);
1484                             } else {
1485                                         master_to_zval_int(ret, sdlType->encode, data);
1486                                 }
1487 
1488                                 soap_add_xml_ref(ret, data);
1489 
1490                                 redo_any = get_zval_property(ret, "any", &rv);
1491                                 if (Z_TYPE_P(ret) == IS_OBJECT && ce != ZEND_STANDARD_CLASS_DEF_PTR) {
1492                                         zend_object *zobj = Z_OBJ_P(ret);
1493                                         zobj->ce = ce;
1494                                 }
1495                         } else {
1496                                 zval base;
1497 
1498                                 ZVAL_NULL(ret);
1499                                 if (soap_check_xml_ref(ret, data)) {
1500                                         return ret;
1501                                 }
1502 
1503                                 object_init_ex(ret, ce);
1504                                 soap_add_xml_ref(ret, data);
1505                                 master_to_zval_int(&base, sdlType->encode, data);
1506                                 set_zval_property(ret, "_", &base);
1507                         }
1508                 } else {
1509                         ZVAL_NULL(ret);
1510                         FIND_XML_NULL(data, ret);
1511                         if (soap_check_xml_ref(ret, data)) {
1512                                 return ret;
1513                         }
1514                         object_init_ex(ret, ce);
1515                         soap_add_xml_ref(ret, data);
1516                 }
1517                 if (sdlType->model) {
1518                         model_to_zval_object(ret, sdlType->model, data, sdl);
1519                         if (redo_any) {
1520                                 if (!get_zval_property(ret, "any", &rv)) {
1521                                         model_to_zval_any(ret, data->children);
1522                                         soap_add_xml_ref(ret, data);
1523                                 } else {
1524                                         unset_zval_property(ret, "any");
1525                                 }
1526                         }
1527                 }
1528                 if (sdlType->attributes) {
1529                         sdlAttributePtr attr;
1530 
1531                         ZEND_HASH_FOREACH_PTR(sdlType->attributes, attr) {
1532                                 if (attr->name) {
1533                                         xmlAttrPtr val = get_attribute(data->properties, attr->name);
1534                                         char *str_val = NULL;
1535 
1536                                         if (val && val->children && val->children->content) {
1537                                                 str_val = (char*)val->children->content;
1538                                                 if (attr->fixed && strcmp(attr->fixed, str_val) != 0) {
1539                                                         soap_error3(E_ERROR, "Encoding: Attribute '%s' has fixed value '%s' (value '%s' is not allowed)", attr->name, attr->fixed, str_val);
1540                                                 }
1541                                         } else if (attr->fixed) {
1542                                                 str_val = attr->fixed;
1543                                         } else if (attr->def) {
1544                                                 str_val = attr->def;
1545                                         }
1546                                         if (str_val) {
1547                                                 xmlNodePtr dummy, text;
1548                                                 zval data;
1549 
1550                                                 dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1551                                                 text = xmlNewText(BAD_CAST(str_val));
1552                                                 xmlAddChild(dummy, text);
1553                                                 ZVAL_NULL(&data);
1554                                                 master_to_zval(&data, attr->encode, dummy);
1555                                                 xmlFreeNode(dummy);
1556                                                 set_zval_property(ret, attr->name, &data);
1557                                         }
1558                                 }
1559                         } ZEND_HASH_FOREACH_END();
1560                 }
1561         } else {
1562                 ZVAL_NULL(ret);
1563                 FIND_XML_NULL(data, ret);
1564                 if (soap_check_xml_ref(ret, data)) {
1565                         return ret;
1566                 }
1567 
1568                 object_init_ex(ret, ce);
1569                 soap_add_xml_ref(ret, data);
1570                 trav = data->children;
1571 
1572                 while (trav != NULL) {
1573                         if (trav->type == XML_ELEMENT_NODE) {
1574                                 zval  tmpVal, rv;
1575                                 zval *prop;
1576 
1577                                 ZVAL_NULL(&tmpVal);
1578                                 master_to_zval(&tmpVal, NULL, trav);
1579 
1580                                 prop = get_zval_property(ret, (char*)trav->name, &rv);
1581                                 if (!prop) {
1582                                         if (!trav->next || !get_node(trav->next, (char*)trav->name)) {
1583                                                 set_zval_property(ret, (char*)trav->name, &tmpVal);
1584                                         } else {
1585                                                 zval arr;
1586 
1587                                                 array_init(&arr);
1588                                                 add_next_index_zval(&arr, &tmpVal);
1589                                                 set_zval_property(ret, (char*)trav->name, &arr);
1590                                         }
1591                                 } else {
1592                                         /* Property already exist - make array */
1593                                         if (Z_TYPE_P(prop) != IS_ARRAY) {
1594                                                 /* Convert into array */
1595                                                 array_init(&arr);
1596                                                 Z_ADDREF_P(prop);
1597                                                 add_next_index_zval(&arr, prop);
1598                                                 set_zval_property(ret, (char*)trav->name, &arr);
1599                                                 prop = &arr;
1600                                         }
1601                                         /* Add array element */
1602                                         add_next_index_zval(prop, &tmpVal);
1603                                 }
1604                         }
1605                         trav = trav->next;
1606                 }
1607         }
1608         return ret;
1609 }
1610 
1611 static zval *to_zval_object(zval *ret, encodeTypePtr type, xmlNodePtr data)
1612 {
1613         return to_zval_object_ex(ret, type, data, NULL);
1614 }
1615 
1616 
1617 static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, zval *object, int style, int strict)
1618 {
1619         switch (model->kind) {
1620                 case XSD_CONTENT_ELEMENT: {
1621                         zval *data;
1622                         xmlNodePtr property;
1623                         encodePtr enc;
1624                         zval rv;
1625 
1626                         data = get_zval_property(object, model->u.element->name, &rv);
1627                         if (data &&
1628                             Z_TYPE_P(data) == IS_NULL &&
1629                             !model->u.element->nillable &&
1630                             model->min_occurs > 0 &&
1631                             !strict) {
1632                                 return 0;
1633                         }
1634                         if (data) {
1635                                 enc = model->u.element->encode;
1636                                 if ((model->max_occurs == -1 || model->max_occurs > 1) &&
1637                                     Z_TYPE_P(data) == IS_ARRAY &&
1638                                     !is_map(data)) {
1639                                         HashTable *ht = Z_ARRVAL_P(data);
1640                                         zval *val;
1641 
1642                                         ZEND_HASH_FOREACH_VAL(ht, val) {
1643                                                 if (Z_TYPE_P(val) == IS_NULL && model->u.element->nillable) {
1644                                                         property = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1645                                                         xmlAddChild(node, property);
1646                                                         set_xsi_nil(property);
1647                                                 } else {
1648                                                         property = master_to_xml(enc, val, style, node);
1649                                                         if (property->children && property->children->content &&
1650                                                             model->u.element->fixed && strcmp(model->u.element->fixed, (char*)property->children->content) != 0) {
1651                                                                 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);
1652                                                         }
1653                                                 }
1654                                                 xmlNodeSetName(property, BAD_CAST(model->u.element->name));
1655                                                 if (style == SOAP_LITERAL &&
1656                                                     model->u.element->namens &&
1657                                                     model->u.element->form == XSD_FORM_QUALIFIED) {
1658                                                         xmlNsPtr nsp = encode_add_ns(property, model->u.element->namens);
1659                                                         xmlSetNs(property, nsp);
1660                                                 }
1661                                         } ZEND_HASH_FOREACH_END();
1662                                 } else {
1663                                         if (Z_TYPE_P(data) == IS_NULL && model->u.element->nillable) {
1664                                                 property = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1665                                                 xmlAddChild(node, property);
1666                                                 set_xsi_nil(property);
1667                                         } else if (Z_TYPE_P(data) == IS_NULL && model->min_occurs == 0) {
1668                                                 return 1;
1669                                         } else {
1670                                                 property = master_to_xml(enc, data, style, node);
1671                                                 if (property->children && property->children->content &&
1672                                                     model->u.element->fixed && strcmp(model->u.element->fixed, (char*)property->children->content) != 0) {
1673                                                         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);
1674                                                 }
1675                                         }
1676                                         xmlNodeSetName(property, BAD_CAST(model->u.element->name));
1677                                         if (style == SOAP_LITERAL &&
1678                                             model->u.element->namens &&
1679                                             model->u.element->form == XSD_FORM_QUALIFIED) {
1680                                                 xmlNsPtr nsp = encode_add_ns(property, model->u.element->namens);
1681                                                 xmlSetNs(property, nsp);
1682                                         }
1683                                 }
1684                                 return 1;
1685                         } else if (strict && model->u.element->nillable && model->min_occurs > 0) {
1686                                 property = xmlNewNode(NULL, BAD_CAST(model->u.element->name));
1687                                 xmlAddChild(node, property);
1688                                 set_xsi_nil(property);
1689                                 if (style == SOAP_LITERAL &&
1690                                     model->u.element->namens &&
1691                                     model->u.element->form == XSD_FORM_QUALIFIED) {
1692                                         xmlNsPtr nsp = encode_add_ns(property, model->u.element->namens);
1693                                         xmlSetNs(property, nsp);
1694                                 }
1695                                 return 1;
1696                         } else if (model->min_occurs == 0) {
1697                                 return 2;
1698                         } else {
1699                                 if (strict) {
1700                                         soap_error1(E_ERROR,  "Encoding: object has no '%s' property", model->u.element->name);
1701                                 }
1702                                 return 0;
1703                         }
1704                         break;
1705                 }
1706                 case XSD_CONTENT_ANY: {
1707                         zval *data;
1708                         encodePtr enc;
1709                         zval rv;
1710 
1711                         data = get_zval_property(object, "any", &rv);
1712                         if (data) {
1713                                 enc = get_conversion(XSD_ANYXML);
1714                                 if ((model->max_occurs == -1 || model->max_occurs > 1) &&
1715                                     Z_TYPE_P(data) == IS_ARRAY &&
1716                                     !is_map(data)) {
1717                                         HashTable *ht = Z_ARRVAL_P(data);
1718                                         zval *val;
1719 
1720                                         ZEND_HASH_FOREACH_VAL(ht, val) {
1721                                                 master_to_xml(enc, val, style, node);
1722                                         } ZEND_HASH_FOREACH_END();
1723                                 } else {
1724                                         master_to_xml(enc, data, style, node);
1725                                 }
1726                                 return 1;
1727                         } else if (model->min_occurs == 0) {
1728                                 return 2;
1729                         } else {
1730                                 if (strict) {
1731                                         soap_error0(E_ERROR,  "Encoding: object has no 'any' property");
1732                                 }
1733                                 return 0;
1734                         }
1735                         break;
1736                 }
1737                 case XSD_CONTENT_SEQUENCE:
1738                 case XSD_CONTENT_ALL: {
1739                         sdlContentModelPtr tmp;
1740 
1741                         ZEND_HASH_FOREACH_PTR(model->u.content, tmp) {
1742                                 if (!model_to_xml_object(node, tmp, object, style, strict && (tmp->min_occurs > 0))) {
1743                                         if (!strict || tmp->min_occurs > 0) {
1744                                                 return 0;
1745                                         }
1746                                 }
1747                                 strict = 1;
1748                         } ZEND_HASH_FOREACH_END();
1749                         return 1;
1750                 }
1751                 case XSD_CONTENT_CHOICE: {
1752                         sdlContentModelPtr tmp;
1753                         int ret = 0;
1754 
1755                         ZEND_HASH_FOREACH_PTR(model->u.content, tmp) {
1756                                 int tmp_ret = model_to_xml_object(node, tmp, object, style, 0);
1757                                 if (tmp_ret == 1) {
1758                                         return 1;
1759                                 } else if (tmp_ret != 0) {
1760                                         ret = 1;
1761                                 }
1762                         } ZEND_HASH_FOREACH_END();
1763                         return ret;
1764                 }
1765                 case XSD_CONTENT_GROUP: {
1766                         return model_to_xml_object(node, model->u.group->model, object, style, strict && model->min_occurs > 0);
1767                 }
1768                 default:
1769                   break;
1770         }
1771         return 1;
1772 }
1773 
1774 static sdlTypePtr model_array_element(sdlContentModelPtr model)
1775 {
1776         switch (model->kind) {
1777                 case XSD_CONTENT_ELEMENT: {
1778                         if (model->max_occurs == -1 || model->max_occurs > 1) {
1779                           return model->u.element;
1780                         } else {
1781                           return NULL;
1782                         }
1783                 }
1784                 case XSD_CONTENT_SEQUENCE:
1785                 case XSD_CONTENT_ALL:
1786                 case XSD_CONTENT_CHOICE: {
1787                         sdlContentModelPtr tmp;
1788 
1789                         if (zend_hash_num_elements(model->u.content) != 1) {
1790                           return NULL;
1791                         }
1792                         ZEND_HASH_FOREACH_PTR(model->u.content, tmp) {
1793                                 return model_array_element(tmp);
1794                         } ZEND_HASH_FOREACH_END();
1795                 }
1796                 case XSD_CONTENT_GROUP: {
1797                         return model_array_element(model->u.group->model);
1798                 }
1799                 default:
1800                   break;
1801         }
1802         return NULL;
1803 }
1804 
1805 static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
1806 {
1807         xmlNodePtr xmlParam;
1808         HashTable *prop = NULL;
1809         sdlTypePtr sdlType = type->sdl_type;
1810 
1811         if (!data || Z_TYPE_P(data) == IS_NULL) {
1812                 xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1813                 xmlAddChild(parent, xmlParam);
1814                 if (style == SOAP_ENCODED) {
1815                         set_xsi_nil(xmlParam);
1816                         set_ns_and_type(xmlParam, type);
1817                 }
1818                 return xmlParam;
1819         }
1820 
1821         if (Z_TYPE_P(data) == IS_OBJECT) {
1822                 prop = Z_OBJPROP_P(data);
1823         } else if (Z_TYPE_P(data) == IS_ARRAY) {
1824                 prop = Z_ARRVAL_P(data);
1825         }
1826 
1827         if (sdlType) {
1828                 if (sdlType->kind == XSD_TYPEKIND_RESTRICTION &&
1829                     sdlType->encode && type != &sdlType->encode->details) {
1830                         encodePtr enc;
1831 
1832                         enc = sdlType->encode;
1833                         while (enc && enc->details.sdl_type &&
1834                                enc->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
1835                                enc->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
1836                                enc->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
1837                                 enc = enc->details.sdl_type->encode;
1838                         }
1839                         if (enc) {
1840                                 zval rv;
1841                                 zval *tmp = get_zval_property(data, "_", &rv);
1842                                 if (tmp) {
1843                                         xmlParam = master_to_xml(enc, tmp, style, parent);
1844                                 } else if (prop == NULL) {
1845                                         xmlParam = master_to_xml(enc, data, style, parent);
1846                                 } else {
1847                                         xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1848                                         xmlAddChild(parent, xmlParam);
1849                                 }
1850                         } else {
1851                                 xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1852                                 xmlAddChild(parent, xmlParam);
1853                         }
1854                 } else if (sdlType->kind == XSD_TYPEKIND_EXTENSION &&
1855                            sdlType->encode && type != &sdlType->encode->details) {
1856                         if (sdlType->encode->details.sdl_type &&
1857                             sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
1858                             sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
1859                             sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
1860 
1861                                 if (prop) ZEND_HASH_INC_APPLY_COUNT(prop);
1862                                 xmlParam = master_to_xml(sdlType->encode, data, style, parent);
1863                                 if (prop) ZEND_HASH_DEC_APPLY_COUNT(prop);
1864                         } else {
1865                                 zval rv;
1866                                 zval *tmp = get_zval_property(data, "_", &rv);
1867 
1868                                 if (tmp) {
1869                                         xmlParam = master_to_xml(sdlType->encode, tmp, style, parent);
1870                                 } else if (prop == NULL) {
1871                                         xmlParam = master_to_xml(sdlType->encode, data, style, parent);
1872                                 } else {
1873                                         xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1874                                         xmlAddChild(parent, xmlParam);
1875                                 }
1876                         }
1877                 } else {
1878                         xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1879                         xmlAddChild(parent, xmlParam);
1880                 }
1881 
1882                 if (soap_check_zval_ref(data, xmlParam)) {
1883                         return xmlParam;
1884                 }
1885                 if (prop != NULL) {
1886                         sdlTypePtr array_el;
1887 
1888                         if (Z_TYPE_P(data) == IS_ARRAY &&
1889                       !is_map(data) &&
1890                       sdlType->attributes == NULL &&
1891                       sdlType->model != NULL &&
1892                       (array_el = model_array_element(sdlType->model)) != NULL) {
1893                                 zval *val;
1894 
1895                                 ZEND_HASH_FOREACH_VAL(prop, val) {
1896                                         xmlNodePtr property;
1897                                         if (Z_TYPE_P(val) == IS_NULL && array_el->nillable) {
1898                                                 property = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1899                                                 xmlAddChild(xmlParam, property);
1900                                                 set_xsi_nil(property);
1901                                         } else {
1902                                                 property = master_to_xml(array_el->encode, val, style, xmlParam);
1903                                         }
1904                                         xmlNodeSetName(property, BAD_CAST(array_el->name));
1905                                         if (style == SOAP_LITERAL &&
1906                                            array_el->namens &&
1907                                            array_el->form == XSD_FORM_QUALIFIED) {
1908                                                 xmlNsPtr nsp = encode_add_ns(property, array_el->namens);
1909                                                 xmlSetNs(property, nsp);
1910                                         }
1911                                 } ZEND_HASH_FOREACH_END();
1912                         } else if (sdlType->model) {
1913                                 model_to_xml_object(xmlParam, sdlType->model, data, style, 1);
1914                         }
1915                         if (sdlType->attributes) {
1916                                 sdlAttributePtr attr;
1917                                 zval *zattr, rv;
1918 
1919                                 ZEND_HASH_FOREACH_PTR(sdlType->attributes, attr) {
1920                                         if (attr->name) {
1921                                                 zattr = get_zval_property(data, attr->name, &rv);
1922                                                 if (zattr) {
1923                                                         xmlNodePtr dummy;
1924 
1925                                                         dummy = master_to_xml(attr->encode, zattr, SOAP_LITERAL, xmlParam);
1926                                                         if (dummy->children && dummy->children->content) {
1927                                                                 if (attr->fixed && strcmp(attr->fixed, (char*)dummy->children->content) != 0) {
1928                                                                         soap_error3(E_ERROR, "Encoding: Attribute '%s' has fixed value '%s' (value '%s' is not allowed)", attr->name, attr->fixed, dummy->children->content);
1929                                                                 }
1930                                                                 /* we need to handle xml: namespace specially, since it is
1931                                                                    an implicit schema. Otherwise, use form.
1932                                                                 */
1933                                                                 if (attr->namens &&
1934                                                                     (!strncmp(attr->namens, XML_NAMESPACE, sizeof(XML_NAMESPACE)) ||
1935                                                                      attr->form == XSD_FORM_QUALIFIED)) {
1936                                                                         xmlNsPtr nsp = encode_add_ns(xmlParam, attr->namens);
1937 
1938                                                                         xmlSetNsProp(xmlParam, nsp, BAD_CAST(attr->name), dummy->children->content);
1939                                                                 } else {
1940                                                                         xmlSetProp(xmlParam, BAD_CAST(attr->name), dummy->children->content);
1941                                                                 }
1942                                                         }
1943                                                         xmlUnlinkNode(dummy);
1944                                                         xmlFreeNode(dummy);
1945                                                 }
1946                                         }
1947                                 } ZEND_HASH_FOREACH_END();
1948                         }
1949                 }
1950                 if (style == SOAP_ENCODED) {
1951                         set_ns_and_type(xmlParam, type);
1952                 }
1953         } else {
1954                 xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1955                 xmlAddChild(parent, xmlParam);
1956 
1957                 if (soap_check_zval_ref(data, xmlParam)) {
1958                         return xmlParam;
1959                 }
1960                 if (prop != NULL) {
1961                         zval *zprop;
1962                         zend_string *str_key;
1963                         xmlNodePtr property;
1964 
1965                         ZEND_HASH_FOREACH_STR_KEY_VAL_IND(prop, str_key, zprop) {
1966 
1967                                 property = master_to_xml(get_conversion(Z_TYPE_P(zprop)), zprop, style, xmlParam);
1968 
1969                                 if (str_key) {
1970                                         const char *prop_name;
1971 
1972                                         if (Z_TYPE_P(data) == IS_OBJECT) {
1973                                                 const char *class_name;
1974 
1975                                                 zend_unmangle_property_name(str_key, &class_name, &prop_name);
1976                                         } else {
1977                                                 prop_name = ZSTR_VAL(str_key);
1978                                         }
1979                                         if (prop_name) {
1980                                                 xmlNodeSetName(property, BAD_CAST(prop_name));
1981                                         }
1982                                 }
1983                         } ZEND_HASH_FOREACH_END();
1984                 }
1985                 if (style == SOAP_ENCODED) {
1986                         set_ns_and_type(xmlParam, type);
1987                 }
1988         }
1989         return xmlParam;
1990 }
1991 
1992 /* Array encode/decode */
1993 static xmlNodePtr guess_array_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
1994 {
1995         encodePtr enc = NULL;
1996 
1997         if (data && Z_TYPE_P(data) == IS_ARRAY) {
1998                 if (is_map(data)) {
1999                         enc = get_conversion(APACHE_MAP);
2000                 } else {
2001                         enc = get_conversion(SOAP_ENC_ARRAY);
2002                 }
2003         }
2004         if (!enc) {
2005                 enc = get_conversion(IS_NULL);
2006         }
2007 
2008         return master_to_xml(enc, data, style, parent);
2009 }
2010 
2011 static int calc_dimension_12(const char* str)
2012 {
2013         int i = 0, flag = 0;
2014         while (*str != '\0' && (*str < '0' || *str > '9') && (*str != '*')) {
2015                 str++;
2016         }
2017         if (*str == '*') {
2018                 i++;
2019                 str++;
2020         }
2021         while (*str != '\0') {
2022                 if (*str >= '0' && *str <= '9') {
2023                         if (flag == 0) {
2024                         i++;
2025                         flag = 1;
2026                 }
2027           } else if (*str == '*') {
2028                         soap_error0(E_ERROR, "Encoding: '*' may only be first arraySize value in list");
2029                 } else {
2030                         flag = 0;
2031                 }
2032                 str++;
2033         }
2034         return i;
2035 }
2036 
2037 static int* get_position_12(int dimension, const char* str)
2038 {
2039         int *pos;
2040         int i = -1, flag = 0;
2041 
2042         pos = safe_emalloc(sizeof(int), dimension, 0);
2043         memset(pos,0,sizeof(int)*dimension);
2044         while (*str != '\0' && (*str < '0' || *str > '9') && (*str != '*')) {
2045                 str++;
2046         }
2047         if (*str == '*') {
2048                 str++;
2049                 i++;
2050         }
2051         while (*str != '\0') {
2052                 if (*str >= '0' && *str <= '9') {
2053                         if (flag == 0) {
2054                                 i++;
2055                                 flag = 1;
2056                         }
2057                         pos[i] = (pos[i]*10)+(*str-'0');
2058                 } else if (*str == '*') {
2059                         soap_error0(E_ERROR, "Encoding: '*' may only be first arraySize value in list");
2060                 } else {
2061                   flag = 0;
2062                 }
2063                 str++;
2064         }
2065         return pos;
2066 }
2067 
2068 static int calc_dimension(const char* str)
2069 {
2070         int i = 1;
2071         while (*str != ']' && *str != '\0') {
2072                 if (*str == ',') {
2073                 i++;
2074                 }
2075                 str++;
2076         }
2077         return i;
2078 }
2079 
2080 static void get_position_ex(int dimension, const char* str, int** pos)
2081 {
2082         int i = 0;
2083 
2084         memset(*pos,0,sizeof(int)*dimension);
2085         while (*str != ']' && *str != '\0' && i < dimension) {
2086                 if (*str >= '0' && *str <= '9') {
2087                         (*pos)[i] = ((*pos)[i]*10)+(*str-'0');
2088                 } else if (*str == ',') {
2089                         i++;
2090                 }
2091                 str++;
2092         }
2093 }
2094 
2095 static int* get_position(int dimension, const char* str)
2096 {
2097         int *pos;
2098 
2099         pos = safe_emalloc(sizeof(int), dimension, 0);
2100         get_position_ex(dimension, str, &pos);
2101         return pos;
2102 }
2103 
2104 static void add_xml_array_elements(xmlNodePtr xmlParam,
2105                                    sdlTypePtr type,
2106                                    encodePtr enc,
2107                                    xmlNsPtr ns,
2108                                    int dimension ,
2109                                    int* dims,
2110                                    zval* data,
2111                                    int style
2112                                   )
2113 {
2114         int j = 0;
2115         zval *zdata;
2116         xmlNodePtr xparam;
2117 
2118         if (data && Z_TYPE_P(data) == IS_ARRAY) {
2119                 ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(data), zdata) {
2120                         if (j >= dims[0]) {
2121                                 break;
2122                         }
2123                         if (dimension == 1) {
2124                                 if (enc == NULL) {
2125                                         xparam = master_to_xml(get_conversion(Z_TYPE_P(zdata)), zdata, style, xmlParam);
2126                                 } else {
2127                                         xparam = master_to_xml(enc, zdata, style, xmlParam);
2128                                 }
2129 
2130                                 if (type) {
2131                                         xmlNodeSetName(xparam, BAD_CAST(type->name));
2132                                 } else if (style == SOAP_LITERAL && enc && enc->details.type_str) {
2133                                         xmlNodeSetName(xparam, BAD_CAST(enc->details.type_str));
2134                                         xmlSetNs(xparam, ns);
2135                                 } else {
2136                                         xmlNodeSetName(xparam, BAD_CAST("item"));
2137                                 }
2138                         } else {
2139                                 add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, zdata, style);
2140                         }
2141                         j++;
2142                 } ZEND_HASH_FOREACH_END();
2143 
2144                 if (dimension == 1) {
2145                         while (j < dims[0]) {
2146                                 xparam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
2147                                 xmlAddChild(xmlParam, xparam);
2148 
2149                                 if (type) {
2150                                         xmlNodeSetName(xparam, BAD_CAST(type->name));
2151                                 } else if (style == SOAP_LITERAL && enc && enc->details.type_str) {
2152                                         xmlNodeSetName(xparam, BAD_CAST(enc->details.type_str));
2153                                         xmlSetNs(xparam, ns);
2154                                 } else {
2155                                         xmlNodeSetName(xparam, BAD_CAST("item"));
2156                                 }
2157 
2158                                 j++;
2159                         }
2160                 } else {
2161                         while (j < dims[0]) {
2162                                 add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, NULL, style);
2163                                 j++;
2164                         }
2165                 }
2166         } else {
2167                 for (j=0; j<dims[0]; j++) {
2168                         if (dimension == 1) {
2169                                 xmlNodePtr xparam;
2170 
2171                                 xparam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
2172                                 xmlAddChild(xmlParam, xparam);
2173                                 if (type) {
2174                                         xmlNodeSetName(xparam, BAD_CAST(type->name));
2175                                 } else if (style == SOAP_LITERAL && enc && enc->details.type_str) {
2176                                         xmlNodeSetName(xparam, BAD_CAST(enc->details.type_str));
2177                                         xmlSetNs(xparam, ns);
2178                                 } else {
2179                                         xmlNodeSetName(xparam, BAD_CAST("item"));
2180                                 }
2181                         } else {
2182                           add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, NULL, style);
2183                         }
2184                 }
2185         }
2186 }
2187 
2188 static inline int array_num_elements(HashTable* ht)
2189 {
2190         if (ht->nNumUsed &&
2191             Z_TYPE(ht->arData[ht->nNumUsed-1].val) != IS_UNDEF &&
2192             ht->arData[ht->nNumUsed-1].key == NULL) {
2193             return ht->arData[ht->nNumUsed-1].h - 1;
2194         }
2195         return 0;
2196 }
2197 
2198 static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
2199 {
2200         sdlTypePtr sdl_type = type->sdl_type;
2201         sdlTypePtr element_type = NULL;
2202         smart_str array_type = {0}, array_size = {0};
2203         int i;
2204         xmlNodePtr xmlParam;
2205         encodePtr enc = NULL;
2206         int dimension = 1;
2207         int* dims;
2208         int soap_version;
2209         zval array_copy;
2210 
2211         ZVAL_UNDEF(&array_copy);
2212         soap_version = SOAP_GLOBAL(soap_version);
2213 
2214         xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
2215         xmlAddChild(parent, xmlParam);
2216 
2217         if (!data || Z_TYPE_P(data) == IS_NULL) {
2218                 if (style == SOAP_ENCODED) {
2219                         set_xsi_nil(xmlParam);
2220                         if (SOAP_GLOBAL(features) & SOAP_USE_XSI_ARRAY_TYPE) {
2221                                 set_ns_and_type_ex(xmlParam, (soap_version == SOAP_1_1) ? SOAP_1_1_ENC_NAMESPACE : SOAP_1_2_ENC_NAMESPACE, "Array");
2222                         } else {
2223                                 set_ns_and_type(xmlParam, type);
2224                         }
2225                 }
2226                 return xmlParam;
2227         }
2228 
2229         if (Z_TYPE_P(data) == IS_OBJECT && instanceof_function(Z_OBJCE_P(data), zend_ce_traversable)) {
2230                 zend_object_iterator   *iter;
2231                 zend_class_entry       *ce = Z_OBJCE_P(data);
2232                 zval                   *val;
2233 
2234                 array_init(&array_copy);
2235 
2236                 iter = ce->get_iterator(ce, data, 0);
2237 
2238                 if (EG(exception)) {
2239                         goto iterator_done;
2240                 }
2241 
2242                 if (iter->funcs->rewind) {
2243                         iter->funcs->rewind(iter);
2244                         if (EG(exception)) {
2245                                 goto iterator_done;
2246                         }
2247                 }
2248 
2249                 while (iter->funcs->valid(iter) == SUCCESS) {
2250                         if (EG(exception)) {
2251                                 goto iterator_done;
2252                         }
2253 
2254                         val = iter->funcs->get_current_data(iter);
2255                         if (EG(exception)) {
2256                                 goto iterator_done;
2257                         }
2258                         if (iter->funcs->get_current_key) {
2259                                 zval key;
2260                                 iter->funcs->get_current_key(iter, &key);
2261                                 if (EG(exception)) {
2262                                         goto iterator_done;
2263                                 }
2264                                 array_set_zval_key(Z_ARRVAL(array_copy), &key, val);
2265                                 zval_ptr_dtor(val);
2266                                 zval_dtor(&key);
2267                         } else {
2268                                 add_next_index_zval(&array_copy, val);
2269                         }
2270                         Z_ADDREF_P(val);
2271 
2272                         iter->funcs->move_forward(iter);
2273                         if (EG(exception)) {
2274                                 goto iterator_done;
2275                         }
2276                 }
2277 iterator_done:
2278                 OBJ_RELEASE(&iter->std);
2279                 if (EG(exception)) {
2280                         zval_ptr_dtor(&array_copy);
2281                         ZVAL_UNDEF(&array_copy);
2282                 } else {
2283                         data = &array_copy;
2284                 }
2285         }
2286 
2287         if (Z_TYPE_P(data) == IS_ARRAY) {
2288                 sdlAttributePtr arrayType;
2289                 sdlExtraAttributePtr ext;
2290                 sdlTypePtr elementType;
2291 
2292                 i = zend_hash_num_elements(Z_ARRVAL_P(data));
2293 
2294                 if (sdl_type &&
2295                     sdl_type->attributes &&
2296                     (arrayType = zend_hash_str_find_ptr(sdl_type->attributes, SOAP_1_1_ENC_NAMESPACE":arrayType",
2297                       sizeof(SOAP_1_1_ENC_NAMESPACE":arrayType")-1)) != NULL &&
2298                     arrayType->extraAttributes &&
2299                     (ext = zend_hash_str_find_ptr(arrayType->extraAttributes, WSDL_NAMESPACE":arrayType", sizeof(WSDL_NAMESPACE":arrayType")-1)) != NULL) {
2300 
2301                         char *value, *end;
2302                         zval *el;
2303 
2304                         value = estrdup(ext->val);
2305                         end = strrchr(value,'[');
2306                         if (end) {
2307                                 *end = '\0';
2308                                 end++;
2309                                 dimension = calc_dimension(end);
2310                         }
2311                         if (ext->ns != NULL) {
2312                                 enc = get_encoder(SOAP_GLOBAL(sdl), ext->ns, value);
2313                                 get_type_str(xmlParam, ext->ns, value, &array_type);
2314                         } else {
2315                                 smart_str_appends(&array_type, value);
2316                         }
2317 
2318                         dims = safe_emalloc(sizeof(int), dimension, 0);
2319                         dims[0] = i;
2320                         el = data;
2321                         for (i = 1; i < dimension; i++) {
2322                                 if (el != NULL && Z_TYPE_P(el) == IS_ARRAY &&
2323                                     zend_hash_num_elements(Z_ARRVAL_P(el)) > 0) {
2324                                     ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(el), el) {
2325                                         break;
2326                                     } ZEND_HASH_FOREACH_END();
2327                                         if (Z_TYPE_P(el) == IS_ARRAY) {
2328                                                 dims[i] = zend_hash_num_elements(Z_ARRVAL_P(el));
2329                                         } else {
2330                                                 dims[i] = 0;
2331                                         }
2332                                 }
2333                         }
2334 
2335                         smart_str_append_long(&array_size, dims[0]);
2336                         for (i=1; i<dimension; i++) {
2337                                 smart_str_appendc(&array_size, ',');
2338                                 smart_str_append_long(&array_size, dims[i]);
2339                         }
2340 
2341                         efree(value);
2342 
2343                 } else if (sdl_type &&
2344                            sdl_type->attributes &&
2345                            (arrayType = zend_hash_str_find_ptr(sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":itemType",
2346                              sizeof(SOAP_1_2_ENC_NAMESPACE":itemType")-1)) != NULL &&
2347                            arrayType->extraAttributes &&
2348                            (ext = zend_hash_str_find_ptr(arrayType->extraAttributes, WSDL_NAMESPACE":itemType", sizeof(WSDL_NAMESPACE":itemType")-1)) != NULL) {
2349                         if (ext->ns != NULL) {
2350                                 enc = get_encoder(SOAP_GLOBAL(sdl), ext->ns, ext->val);
2351                                 get_type_str(xmlParam, ext->ns, ext->val, &array_type);
2352                         } else {
2353                                 smart_str_appends(&array_type, ext->val);
2354                         }
2355                         if ((arrayType = zend_hash_str_find_ptr(sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
2356                                            sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize")-1)) != NULL &&
2357                             arrayType->extraAttributes &&
2358                             (ext = zend_hash_str_find_ptr(arrayType->extraAttributes, WSDL_NAMESPACE":arraySize", sizeof(WSDL_NAMESPACE":arraysize")-1)) != NULL) {
2359                                 dimension = calc_dimension_12(ext->val);
2360                                 dims = get_position_12(dimension, ext->val);
2361                                 if (dims[0] == 0) {dims[0] = i;}
2362 
2363                                 smart_str_append_long(&array_size, dims[0]);
2364                                 for (i=1; i<dimension; i++) {
2365                                         smart_str_appendc(&array_size, ',');
2366                                         smart_str_append_long(&array_size, dims[i]);
2367                                 }
2368                         } else {
2369                                 dims = emalloc(sizeof(int));
2370                                 *dims = 0;
2371                                 smart_str_append_long(&array_size, i);
2372                         }
2373                 } else if (sdl_type &&
2374                            sdl_type->attributes &&
2375                            (arrayType = zend_hash_str_find_ptr(sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
2376                              sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize")-1)) != NULL &&
2377                            arrayType->extraAttributes &&
2378                            (ext = zend_hash_str_find_ptr(arrayType->extraAttributes, WSDL_NAMESPACE":arraySize", sizeof(WSDL_NAMESPACE":arraySize")-1)) != NULL) {
2379                         dimension = calc_dimension_12(ext->val);
2380                         dims = get_position_12(dimension, ext->val);
2381                         if (dims[0] == 0) {dims[0] = i;}
2382 
2383                         smart_str_append_long(&array_size, dims[0]);
2384                         for (i=1; i<dimension; i++) {
2385                                 smart_str_appendc(&array_size, ',');
2386                                 smart_str_append_long(&array_size, dims[i]);
2387                         }
2388 
2389                         if (sdl_type && sdl_type->elements &&
2390                             zend_hash_num_elements(sdl_type->elements) == 1 &&
2391                             (zend_hash_internal_pointer_reset(sdl_type->elements),
2392                              (elementType = zend_hash_get_current_data_ptr(sdl_type->elements)) != NULL) &&
2393                              elementType->encode && elementType->encode->details.type_str) {
2394                                 element_type = elementType;
2395                                 enc = elementType->encode;
2396                                 get_type_str(xmlParam, elementType->encode->details.ns, elementType->encode->details.type_str, &array_type);
2397                         } else {
2398                                 enc = get_array_type(xmlParam, data, &array_type);
2399                         }
2400                 } else if (sdl_type && sdl_type->elements &&
2401                            zend_hash_num_elements(sdl_type->elements) == 1 &&
2402                            (zend_hash_internal_pointer_reset(sdl_type->elements),
2403                             (elementType = zend_hash_get_current_data_ptr(sdl_type->elements)) != NULL) &&
2404                            elementType->encode && elementType->encode->details.type_str) {
2405 
2406                         element_type = elementType;
2407                         enc = elementType->encode;
2408                         get_type_str(xmlParam, elementType->encode->details.ns, elementType->encode->details.type_str, &array_type);
2409 
2410                         smart_str_append_long(&array_size, i);
2411 
2412                         dims = safe_emalloc(sizeof(int), dimension, 0);
2413                         dims[0] = i;
2414                 } else {
2415 
2416                         enc = get_array_type(xmlParam, data, &array_type);
2417                         smart_str_append_long(&array_size, i);
2418                         dims = safe_emalloc(sizeof(int), dimension, 0);
2419                         dims[0] = i;
2420                 }
2421 
2422                 if (style == SOAP_ENCODED) {
2423                         if (soap_version == SOAP_1_1) {
2424                                 smart_str_0(&array_type);
2425                                 if (strcmp(ZSTR_VAL(array_type.s),"xsd:anyType") == 0) {
2426                                         smart_str_free(&array_type);
2427                                         smart_str_appendl(&array_type,"xsd:ur-type",sizeof("xsd:ur-type")-1);
2428                                 }
2429                                 smart_str_appendc(&array_type, '[');
2430                                 smart_str_append_smart_str(&array_type, &array_size);
2431                                 smart_str_appendc(&array_type, ']');
2432                                 smart_str_0(&array_type);
2433                                 set_ns_prop(xmlParam, SOAP_1_1_ENC_NAMESPACE, "arrayType", ZSTR_VAL(array_type.s));
2434                         } else {
2435                                 int i = 0;
2436                                 while (i < ZSTR_LEN(array_size.s)) {
2437                                         if (ZSTR_VAL(array_size.s)[i] == ',') {ZSTR_VAL(array_size.s)[i] = ' ';}
2438                                         ++i;
2439                                 }
2440                                 smart_str_0(&array_type);
2441                                 smart_str_0(&array_size);
2442                                 set_ns_prop(xmlParam, SOAP_1_2_ENC_NAMESPACE, "itemType", ZSTR_VAL(array_type.s));
2443                                 set_ns_prop(xmlParam, SOAP_1_2_ENC_NAMESPACE, "arraySize", ZSTR_VAL(array_size.s));
2444                         }
2445                 }
2446                 smart_str_free(&array_type);
2447                 smart_str_free(&array_size);
2448 
2449                 add_xml_array_elements(xmlParam, element_type, enc, enc?encode_add_ns(xmlParam,enc->details.ns):NULL, dimension, dims, data, style);
2450                 efree(dims);
2451         }
2452         if (style == SOAP_ENCODED) {
2453                 if (SOAP_GLOBAL(features) & SOAP_USE_XSI_ARRAY_TYPE) {
2454                         set_ns_and_type_ex(xmlParam, (soap_version == SOAP_1_1) ? SOAP_1_1_ENC_NAMESPACE : SOAP_1_2_ENC_NAMESPACE, "Array");
2455                 } else {
2456                         set_ns_and_type(xmlParam, type);
2457                 }
2458         }
2459 
2460         zval_ptr_dtor(&array_copy);
2461 
2462         return xmlParam;
2463 }
2464 
2465 static zval *to_zval_array(zval *ret, encodeTypePtr type, xmlNodePtr data)
2466 {
2467         xmlNodePtr trav;
2468         encodePtr enc = NULL;
2469         int dimension = 1;
2470         int* dims = NULL;
2471         int* pos = NULL;
2472         xmlAttrPtr attr;
2473         sdlAttributePtr arrayType;
2474         sdlExtraAttributePtr ext;
2475         sdlTypePtr elementType;
2476 
2477         ZVAL_NULL(ret);
2478         FIND_XML_NULL(data, ret);
2479 
2480         if (data &&
2481             (attr = get_attribute(data->properties,"arrayType")) &&
2482             attr->children && attr->children->content) {
2483                 char *type, *end, *ns;
2484                 xmlNsPtr nsptr;
2485 
2486                 parse_namespace(attr->children->content, &type, &ns);
2487                 nsptr = xmlSearchNs(attr->doc, attr->parent, BAD_CAST(ns));
2488 
2489                 end = strrchr(type,'[');
2490                 if (end) {
2491                         *end = '\0';
2492                         dimension = calc_dimension(end+1);
2493                         dims = get_position(dimension, end+1);
2494                 }
2495                 if (nsptr != NULL) {
2496                         enc = get_encoder(SOAP_GLOBAL(sdl), (char*)nsptr->href, type);
2497                 }
2498                 efree(type);
2499                 if (ns) {efree(ns);}
2500 
2501         } else if ((attr = get_attribute(data->properties,"itemType")) &&
2502             attr->children &&
2503             attr->children->content) {
2504                 char *type, *ns;
2505                 xmlNsPtr nsptr;
2506 
2507                 parse_namespace(attr->children->content, &type, &ns);
2508                 nsptr = xmlSearchNs(attr->doc, attr->parent, BAD_CAST(ns));
2509                 if (nsptr != NULL) {
2510                         enc = get_encoder(SOAP_GLOBAL(sdl), (char*)nsptr->href, type);
2511                 }
2512                 efree(type);
2513                 if (ns) {efree(ns);}
2514 
2515                 if ((attr = get_attribute(data->properties,"arraySize")) &&
2516                     attr->children && attr->children->content) {
2517                         dimension = calc_dimension_12((char*)attr->children->content);
2518                         dims = get_position_12(dimension, (char*)attr->children->content);
2519                 } else {
2520                         dims = emalloc(sizeof(int));
2521                         *dims = 0;
2522                 }
2523 
2524         } else if ((attr = get_attribute(data->properties,"arraySize")) &&
2525             attr->children && attr->children->content) {
2526 
2527                 dimension = calc_dimension_12((char*)attr->children->content);
2528                 dims = get_position_12(dimension, (char*)attr->children->content);
2529 
2530         } else if (type->sdl_type != NULL &&
2531                    type->sdl_type->attributes != NULL &&
2532                    (arrayType = zend_hash_str_find_ptr(type->sdl_type->attributes, SOAP_1_1_ENC_NAMESPACE":arrayType",
2533                                   sizeof(SOAP_1_1_ENC_NAMESPACE":arrayType")-1)) != NULL &&
2534                    arrayType->extraAttributes &&
2535                    (ext = zend_hash_str_find_ptr(arrayType->extraAttributes, WSDL_NAMESPACE":arrayType", sizeof(WSDL_NAMESPACE":arrayType")-1)) != NULL) {
2536                 char *type, *end;
2537 
2538                 type = estrdup(ext->val);
2539                 end = strrchr(type,'[');
2540                 if (end) {
2541                         *end = '\0';
2542                 }
2543                 if (ext->ns != NULL) {
2544                         enc = get_encoder(SOAP_GLOBAL(sdl), ext->ns, type);
2545                 }
2546                 efree(type);
2547 
2548                 dims = emalloc(sizeof(int));
2549                 *dims = 0;
2550 
2551         } else if (type->sdl_type != NULL &&
2552                    type->sdl_type->attributes != NULL &&
2553                    (arrayType = zend_hash_str_find_ptr(type->sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":itemType",
2554                                   sizeof(SOAP_1_2_ENC_NAMESPACE":itemType")-1)) != NULL &&
2555                    arrayType->extraAttributes &&
2556                    (ext = zend_hash_str_find_ptr(arrayType->extraAttributes, WSDL_NAMESPACE":itemType", sizeof(WSDL_NAMESPACE":itemType")-1)) != NULL) {
2557 
2558                 if (ext->ns != NULL) {
2559                         enc = get_encoder(SOAP_GLOBAL(sdl), ext->ns, ext->val);
2560                 }
2561 
2562                 if ((arrayType = zend_hash_str_find_ptr(type->sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
2563                                    sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize")-1)) != NULL &&
2564                     arrayType->extraAttributes &&
2565                     (ext = zend_hash_str_find_ptr(arrayType->extraAttributes, WSDL_NAMESPACE":arraySize", sizeof(WSDL_NAMESPACE":arraysize")-1)) != NULL) {
2566                         dimension = calc_dimension_12(ext->val);
2567                         dims = get_position_12(dimension, ext->val);
2568                 } else {
2569                         dims = emalloc(sizeof(int));
2570                         *dims = 0;
2571                 }
2572         } else if (type->sdl_type != NULL &&
2573                    type->sdl_type->attributes != NULL &&
2574                    (arrayType = zend_hash_str_find_ptr(type->sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
2575                                   sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize")-1)) != NULL &&
2576                    arrayType->extraAttributes &&
2577                    (ext = zend_hash_str_find_ptr(arrayType->extraAttributes, WSDL_NAMESPACE":arraySize", sizeof(WSDL_NAMESPACE":arraysize")-1)) != NULL) {
2578 
2579                 dimension = calc_dimension_12(ext->val);
2580                 dims = get_position_12(dimension, ext->val);
2581                 if (type->sdl_type && type->sdl_type->elements &&
2582                     zend_hash_num_elements(type->sdl_type->elements) == 1 &&
2583                     (zend_hash_internal_pointer_reset(type->sdl_type->elements),
2584                      (elementType = zend_hash_get_current_data_ptr(type->sdl_type->elements)) != NULL) &&
2585                     elementType->encode) {
2586                         enc = elementType->encode;
2587                 }
2588         } else if (type->sdl_type && type->sdl_type->elements &&
2589                    zend_hash_num_elements(type->sdl_type->elements) == 1 &&
2590                    (zend_hash_internal_pointer_reset(type->sdl_type->elements),
2591                     (elementType = zend_hash_get_current_data_ptr(type->sdl_type->elements)) != NULL) &&
2592                    elementType->encode) {
2593                 enc = elementType->encode;
2594         }
2595         if (dims == NULL) {
2596                 dimension = 1;
2597                 dims = emalloc(sizeof(int));
2598                 *dims = 0;
2599         }
2600         pos = safe_emalloc(sizeof(int), dimension, 0);
2601         memset(pos,0,sizeof(int)*dimension);
2602         if (data &&
2603             (attr = get_attribute(data->properties,"offset")) &&
2604              attr->children && attr->children->content) {
2605                 char* tmp = strrchr((char*)attr->children->content,'[');
2606 
2607                 if (tmp == NULL) {
2608                         tmp = (char*)attr->children->content;
2609                 }
2610                 get_position_ex(dimension, tmp, &pos);
2611         }
2612 
2613         array_init(ret);
2614         trav = data->children;
2615         while (trav) {
2616                 if (trav->type == XML_ELEMENT_NODE) {
2617                         int i;
2618                         zval tmpVal, *ar;
2619                         xmlAttrPtr position = get_attribute(trav->properties,"position");
2620 
2621                         ZVAL_NULL(&tmpVal);
2622                         master_to_zval(&tmpVal, enc, trav);
2623                         if (position != NULL && position->children && position->children->content) {
2624                                 char* tmp = strrchr((char*)position->children->content, '[');
2625                                 if (tmp == NULL) {
2626                                         tmp = (char*)position->children->content;
2627                                 }
2628                                 get_position_ex(dimension, tmp, &pos);
2629                         }
2630 
2631                         /* Get/Create intermediate arrays for multidimensional arrays */
2632                         i = 0;
2633                         ar = ret;
2634                         while (i < dimension-1) {
2635                                 zval* ar2;
2636                                 if ((ar2 = zend_hash_index_find(Z_ARRVAL_P(ar), pos[i])) != NULL) {
2637                                         ar = ar2;
2638                                 } else {
2639                                         zval tmpAr;
2640                                         array_init(&tmpAr);
2641                                         ar = zend_hash_index_update(Z_ARRVAL_P(ar), pos[i], &tmpAr);
2642                                 }
2643                                 i++;
2644                         }
2645                         zend_hash_index_update(Z_ARRVAL_P(ar), pos[i], &tmpVal);
2646 
2647                         /* Increment position */
2648                         i = dimension;
2649                         while (i > 0) {
2650                           i--;
2651                           pos[i]++;
2652                                 if (pos[i] >= dims[i]) {
2653                                         if (i > 0) {
2654                                                 pos[i] = 0;
2655                                         } else {
2656                                                 /* TODO: Array index overflow */
2657                                         }
2658                                 } else {
2659                                   break;
2660                                 }
2661                         }
2662                 }
2663                 trav = trav->next;
2664         }
2665         efree(dims);
2666         efree(pos);
2667         return ret;
2668 }
2669 
2670 /* Map encode/decode */
2671 static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
2672 {
2673         zval *temp_data;
2674         zend_string *key_val;
2675         zend_ulong int_val;
2676         xmlNodePtr xmlParam;
2677         xmlNodePtr xparam, item;
2678         xmlNodePtr key;
2679 
2680         xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
2681         xmlAddChild(parent, xmlParam);
2682         FIND_ZVAL_NULL(data, xmlParam, style);
2683 
2684         if (Z_TYPE_P(data) == IS_ARRAY) {
2685                 ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(data), int_val, key_val, temp_data) {
2686 
2687                         item = xmlNewNode(NULL, BAD_CAST("item"));
2688                         xmlAddChild(xmlParam, item);
2689                         key = xmlNewNode(NULL, BAD_CAST("key"));
2690                         xmlAddChild(item,key);
2691                         if (key_val) {
2692                                 if (style == SOAP_ENCODED) {
2693                                         set_xsi_type(key, "xsd:string");
2694                                 }
2695                                 xmlNodeSetContent(key, BAD_CAST(ZSTR_VAL(key_val)));
2696                         } else {
2697                                 smart_str tmp = {0};
2698                                 smart_str_append_long(&tmp, int_val);
2699                                 smart_str_0(&tmp);
2700 
2701                                 if (style == SOAP_ENCODED) {
2702                                         set_xsi_type(key, "xsd:int");
2703                                 }
2704                                 xmlNodeSetContentLen(key, BAD_CAST(ZSTR_VAL(tmp.s)), ZSTR_LEN(tmp.s));
2705 
2706                                 smart_str_free(&tmp);
2707                         }
2708 
2709                         xparam = master_to_xml(get_conversion(Z_TYPE_P(temp_data)), temp_data, style, item);
2710                         xmlNodeSetName(xparam, BAD_CAST("value"));
2711                 } ZEND_HASH_FOREACH_END();
2712         }
2713         if (style == SOAP_ENCODED) {
2714                 set_ns_and_type(xmlParam, type);
2715         }
2716 
2717         return xmlParam;
2718 }
2719 
2720 static zval *to_zval_map(zval *ret, encodeTypePtr type, xmlNodePtr data)
2721 {
2722         zval key, value;
2723         xmlNodePtr trav, item, xmlKey, xmlValue;
2724 
2725         ZVAL_NULL(ret);
2726         FIND_XML_NULL(data, ret);
2727 
2728         if (data && data->children) {
2729                 array_init(ret);
2730                 trav = data->children;
2731 
2732                 trav = data->children;
2733                 FOREACHNODE(trav, "item", item) {
2734                         xmlKey = get_node(item->children, "key");
2735                         if (!xmlKey) {
2736                                 soap_error0(E_ERROR,  "Encoding: Can't decode apache map, missing key");
2737                         }
2738 
2739                         xmlValue = get_node(item->children, "value");
2740                         if (!xmlKey) {
2741                                 soap_error0(E_ERROR,  "Encoding: Can't decode apache map, missing value");
2742                         }
2743 
2744                         ZVAL_NULL(&key);
2745                         master_to_zval(&key, NULL, xmlKey);
2746                         ZVAL_NULL(&value);
2747                         master_to_zval(&value, NULL, xmlValue);
2748 
2749                         if (Z_TYPE(key) == IS_STRING) {
2750                                 zend_symtable_update(Z_ARRVAL_P(ret), Z_STR(key), &value);
2751                         } else if (Z_TYPE(key) == IS_LONG) {
2752                                 zend_hash_index_update(Z_ARRVAL_P(ret), Z_LVAL(key), &value);
2753                         } else {
2754                                 soap_error0(E_ERROR,  "Encoding: Can't decode apache map, only Strings or Longs are allowd as keys");
2755                         }
2756                         zval_ptr_dtor(&key);
2757                 }
2758                 ENDFOREACH(trav);
2759         } else {
2760                 ZVAL_NULL(ret);
2761         }
2762         return ret;
2763 }
2764 
2765 /* Unknown encode/decode */
2766 static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
2767 {
2768         encodePtr  enc;
2769         xmlNodePtr ret;
2770 
2771         if (data) {
2772                 enc = get_conversion(Z_TYPE_P(data));
2773         } else {
2774                 enc = get_conversion(IS_NULL);
2775         }
2776         ret = master_to_xml_int(enc, data, style, parent, 0);
2777 /*
2778         if (style == SOAP_LITERAL && SOAP_GLOBAL(sdl)) {
2779                 set_ns_and_type(ret, &enc->details);
2780         }
2781 */
2782         return ret;
2783 }
2784 
2785 static zval *guess_zval_convert(zval *ret, encodeTypePtr type, xmlNodePtr data)
2786 {
2787         encodePtr enc = NULL;
2788         xmlAttrPtr tmpattr;
2789         xmlChar *type_name = NULL;
2790 
2791         data = check_and_resolve_href(data);
2792 
2793         if (data == NULL) {
2794                 enc = get_conversion(IS_NULL);
2795         } else if (data->properties && get_attribute_ex(data->properties, "nil", XSI_NAMESPACE)) {
2796                 enc = get_conversion(IS_NULL);
2797         } else {
2798                 tmpattr = get_attribute_ex(data->properties,"type", XSI_NAMESPACE);
2799                 if (tmpattr != NULL) {
2800                   type_name = tmpattr->children->content;
2801                         enc = get_encoder_from_prefix(SOAP_GLOBAL(sdl), data, tmpattr->children->content);
2802                         if (enc && type == &enc->details) {
2803                                 enc = NULL;
2804                         }
2805                         if (enc != NULL) {
2806                           encodePtr tmp = enc;
2807                           while (tmp &&
2808                                  tmp->details.sdl_type != NULL &&
2809                                  tmp->details.sdl_type->kind != XSD_TYPEKIND_COMPLEX) {
2810                             if (enc == tmp->details.sdl_type->encode ||
2811                                 tmp == tmp->details.sdl_type->encode) {
2812                                 enc = NULL;
2813                                 break;
2814                             }
2815                             tmp = tmp->details.sdl_type->encode;
2816                           }
2817                         }
2818                 }
2819 
2820                 if (enc == NULL) {
2821                         /* Didn't have a type, totally guess here */
2822                         /* Logic: has children = IS_OBJECT else IS_STRING */
2823                         xmlNodePtr trav;
2824 
2825                         if (get_attribute(data->properties, "arrayType") ||
2826                             get_attribute(data->properties, "itemType") ||
2827                             get_attribute(data->properties, "arraySize")) {
2828                                 enc = get_conversion(SOAP_ENC_ARRAY);
2829                         } else {
2830                                 enc = get_conversion(XSD_STRING);
2831                                 trav = data->children;
2832                                 while (trav != NULL) {
2833                                         if (trav->type == XML_ELEMENT_NODE) {
2834                                                 enc = get_conversion(SOAP_ENC_OBJECT);
2835                                                 break;
2836                                         }
2837                                         trav = trav->next;
2838                                 }
2839                         }
2840                 }
2841         }
2842         master_to_zval_int(ret, enc, data);
2843         if (SOAP_GLOBAL(sdl) && type_name && enc->details.sdl_type) {
2844                 zval soapvar;
2845                 char *ns, *cptype;
2846                 xmlNsPtr nsptr;
2847 
2848                 object_init_ex(&soapvar, soap_var_class_entry);
2849                 add_property_long(&soapvar, "enc_type", enc->details.type);
2850                 Z_DELREF_P(ret);
2851                 add_property_zval(&soapvar, "enc_value", ret);
2852                 parse_namespace(type_name, &cptype, &ns);
2853                 nsptr = xmlSearchNs(data->doc, data, BAD_CAST(ns));
2854                 add_property_string(&soapvar, "enc_stype", cptype);
2855                 if (nsptr) {
2856                         add_property_string(&soapvar, "enc_ns", (char*)nsptr->href);
2857                 }
2858                 efree(cptype);
2859                 if (ns) {efree(ns);}
2860                 ZVAL_COPY_VALUE(ret, &soapvar);
2861         }
2862         return ret;
2863 }
2864 
2865 /* Time encode/decode */
2866 static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, int style, xmlNodePtr parent)
2867 {
2868         /* logic hacked from ext/standard/datetime.c */
2869         struct tm *ta, tmbuf;
2870         time_t timestamp;
2871         int max_reallocs = 5;
2872         size_t buf_len=64, real_len;
2873         char *buf;
2874         char tzbuf[8];
2875 
2876         xmlNodePtr xmlParam;
2877 
2878         xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
2879         xmlAddChild(parent, xmlParam);
2880         FIND_ZVAL_NULL(data, xmlParam, style);
2881 
2882         if (Z_TYPE_P(data) == IS_LONG) {
2883                 timestamp = Z_LVAL_P(data);
2884                 ta = php_localtime_r(&timestamp, &tmbuf);
2885                 /*ta = php_gmtime_r(&timestamp, &tmbuf);*/
2886                 if (!ta) {
2887                         soap_error1(E_ERROR, "Encoding: Invalid timestamp %pd", Z_LVAL_P(data));
2888                 }
2889 
2890                 buf = (char *) emalloc(buf_len);
2891                 while ((real_len = strftime(buf, buf_len, format, ta)) == buf_len || real_len == 0) {
2892                         buf_len *= 2;
2893                         buf = (char *) erealloc(buf, buf_len);
2894                         if (!--max_reallocs) break;
2895                 }
2896 
2897                 /* Time zone support */
2898 #ifdef HAVE_TM_GMTOFF
2899                 snprintf(tzbuf, sizeof(tzbuf), "%c%02d:%02d", (ta->tm_gmtoff < 0) ? '-' : '+', abs(ta->tm_gmtoff / 3600), abs( (ta->tm_gmtoff % 3600) / 60 ));
2900 #else
2901 # if defined(__CYGWIN__) || defined(NETWARE) || (defined(PHP_WIN32) && defined(_MSC_VER) && _MSC_VER >= 1900)
2902                 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));
2903 # else
2904                 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));
2905 # endif
2906 #endif
2907                 if (strcmp(tzbuf,"+00:00") == 0) {
2908                   strcpy(tzbuf,"Z");
2909                   real_len++;
2910                 } else {
2911                         real_len += 6;
2912                 }
2913                 if (real_len >= buf_len) {
2914                         buf = (char *) erealloc(buf, real_len+1);
2915                 }
2916                 strcat(buf, tzbuf);
2917 
2918                 xmlNodeSetContent(xmlParam, BAD_CAST(buf));
2919                 efree(buf);
2920         } else if (Z_TYPE_P(data) == IS_STRING) {
2921                 xmlNodeSetContentLen(xmlParam, BAD_CAST(Z_STRVAL_P(data)), Z_STRLEN_P(data));
2922         }
2923 
2924         if (style == SOAP_ENCODED) {
2925                 set_ns_and_type(xmlParam, type);
2926         }
2927         return xmlParam;
2928 }
2929 
2930 static xmlNodePtr to_xml_duration(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
2931 {
2932         /* TODO: '-'?P([0-9]+Y)?([0-9]+M)?([0-9]+D)?T([0-9]+H)?([0-9]+M)?([0-9]+S)? */
2933         return to_xml_string(type, data, style, parent);
2934 }
2935 
2936 static xmlNodePtr to_xml_datetime(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
2937 {
2938         return to_xml_datetime_ex(type, data, "%Y-%m-%dT%H:%M:%S", style, parent);
2939 }
2940 
2941 static xmlNodePtr to_xml_time(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
2942 {
2943         /* TODO: microsecconds */
2944         return to_xml_datetime_ex(type, data, "%H:%M:%S", style, parent);
2945 }
2946 
2947 static xmlNodePtr to_xml_date(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
2948 {
2949         return to_xml_datetime_ex(type, data, "%Y-%m-%d", style, parent);
2950 }
2951 
2952 static xmlNodePtr to_xml_gyearmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
2953 {
2954         return to_xml_datetime_ex(type, data, "%Y-%m", style, parent);
2955 }
2956 
2957 static xmlNodePtr to_xml_gyear(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
2958 {
2959         return to_xml_datetime_ex(type, data, "%Y", style, parent);
2960 }
2961 
2962 static xmlNodePtr to_xml_gmonthday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
2963 {
2964         return to_xml_datetime_ex(type, data, "--%m-%d", style, parent);
2965 }
2966 
2967 static xmlNodePtr to_xml_gday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
2968 {
2969         return to_xml_datetime_ex(type, data, "---%d", style, parent);
2970 }
2971 
2972 static xmlNodePtr to_xml_gmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
2973 {
2974         return to_xml_datetime_ex(type, data, "--%m--", style, parent);
2975 }
2976 
2977 static zval* to_zval_list(zval *ret, encodeTypePtr enc, xmlNodePtr data) {
2978         /*FIXME*/
2979         return to_zval_stringc(ret, enc, data);
2980 }
2981 
2982 static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent) {
2983         xmlNodePtr ret;
2984         encodePtr list_enc = NULL;
2985 
2986         if (enc->sdl_type && enc->sdl_type->kind == XSD_TYPEKIND_LIST && enc->sdl_type->elements) {
2987                 sdlTypePtr type;
2988 
2989                 ZEND_HASH_FOREACH_PTR(enc->sdl_type->elements, type) {
2990                         list_enc = type->encode;
2991                         break;
2992                 } ZEND_HASH_FOREACH_END();
2993         }
2994 
2995         ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
2996         xmlAddChild(parent, ret);
2997         FIND_ZVAL_NULL(data, ret, style);
2998         if (Z_TYPE_P(data) == IS_ARRAY) {
2999                 zval *tmp;
3000                 smart_str list = {0};
3001                 HashTable *ht = Z_ARRVAL_P(data);
3002 
3003                 ZEND_HASH_FOREACH_VAL(ht, tmp) {
3004                         xmlNodePtr dummy = master_to_xml(list_enc, tmp, SOAP_LITERAL, ret);
3005                         if (dummy && dummy->children && dummy->children->content) {
3006                                 if (list.s && ZSTR_LEN(list.s) != 0) {
3007                                         smart_str_appendc(&list, ' ');
3008                                 }
3009                                 smart_str_appends(&list, (char*)dummy->children->content);
3010                         } else {
3011                                 soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
3012                         }
3013                         xmlUnlinkNode(dummy);
3014                         xmlFreeNode(dummy);
3015                 } ZEND_HASH_FOREACH_END();
3016                 smart_str_0(&list);
3017                 if (list.s) {
3018                         xmlNodeSetContentLen(ret, BAD_CAST(ZSTR_VAL(list.s)), ZSTR_LEN(list.s));
3019                 } else {
3020                         xmlNodeSetContentLen(ret, BAD_CAST(""), 0);
3021                 }
3022                 smart_str_free(&list);
3023         } else {
3024                 zval tmp;
3025                 char *str, *start, *next;
3026                 smart_str list = {0};
3027 
3028                 if (Z_TYPE_P(data) != IS_STRING) {
3029                         ZVAL_STR(&tmp, zval_get_string(data));
3030                         data = &tmp;
3031                 }
3032                 str = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
3033                 whiteSpace_collapse(BAD_CAST(str));
3034                 start = str;
3035                 while (start != NULL && *start != '\0') {
3036                         xmlNodePtr dummy;
3037                         zval dummy_zval;
3038 
3039                         next = strchr(start,' ');
3040                         if (next != NULL) {
3041                           *next = '\0';
3042                           next++;
3043                         }
3044                         ZVAL_STRING(&dummy_zval, start);
3045                         dummy = master_to_xml(list_enc, &dummy_zval, SOAP_LITERAL, ret);
3046                         zval_ptr_dtor(&dummy_zval);
3047                         if (dummy && dummy->children && dummy->children->content) {
3048                                 if (list.s && ZSTR_LEN(list.s) != 0) {
3049                                         smart_str_appendc(&list, ' ');
3050                                 }
3051                                 smart_str_appends(&list, (char*)dummy->children->content);
3052                         } else {
3053                                 soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
3054                         }
3055                         xmlUnlinkNode(dummy);
3056                         xmlFreeNode(dummy);
3057 
3058                         start = next;
3059                 }
3060                 smart_str_0(&list);
3061                 if (list.s) {
3062                         xmlNodeSetContentLen(ret, BAD_CAST(ZSTR_VAL(list.s)), ZSTR_LEN(list.s));
3063                 } else {
3064                         xmlNodeSetContentLen(ret, BAD_CAST(""), 0);
3065                 }
3066                 smart_str_free(&list);
3067                 efree(str);
3068                 if (data == &tmp) {zval_dtor(&tmp);}
3069         }
3070         return ret;
3071 }
3072 
3073 static xmlNodePtr to_xml_list1(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent) {
3074         /*FIXME: minLength=1 */
3075         return to_xml_list(enc,data,style, parent);
3076 }
3077 
3078 static zval* to_zval_union(zval *ret, encodeTypePtr enc, xmlNodePtr data) {
3079         /*FIXME*/
3080         return to_zval_list(ret, enc, data);
3081 }
3082 
3083 static xmlNodePtr to_xml_union(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent) {
3084         /*FIXME*/
3085         return to_xml_list(enc,data,style, parent);
3086 }
3087 
3088 static zval *to_zval_any(zval *ret, encodeTypePtr type, xmlNodePtr data)
3089 {
3090         xmlBufferPtr buf;
3091 
3092         if (SOAP_GLOBAL(sdl) && SOAP_GLOBAL(sdl)->elements && data->name) {
3093                 smart_str nscat = {0};
3094                 sdlTypePtr sdl_type;
3095 
3096                 if (data->ns && data->ns->href) {
3097                         smart_str_appends(&nscat, (char*)data->ns->href);
3098                         smart_str_appendc(&nscat, ':');
3099                 }
3100                 smart_str_appends(&nscat, (char*)data->name);
3101                 smart_str_0(&nscat);
3102 
3103                 if ((sdl_type = zend_hash_find_ptr(SOAP_GLOBAL(sdl)->elements, nscat.s)) != NULL &&
3104                     sdl_type->encode) {
3105                         smart_str_free(&nscat);
3106                         return master_to_zval_int(ret, sdl_type->encode, data);
3107                 }
3108                 smart_str_free(&nscat);
3109         }
3110 
3111         buf = xmlBufferCreate();
3112         xmlNodeDump(buf, NULL, data, 0, 0);
3113         ZVAL_STRING(ret, (char*)xmlBufferContent(buf));
3114         xmlBufferFree(buf);
3115         return ret;
3116 }
3117 
3118 static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
3119 {
3120         xmlNodePtr ret = NULL;
3121 
3122         if (Z_TYPE_P(data) == IS_ARRAY) {
3123                 zval *el;
3124                 encodePtr enc = get_conversion(XSD_ANYXML);
3125                 zend_string *name;
3126 
3127                 ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(data), name, el) {
3128                         ret = master_to_xml(enc, el, style, parent);
3129                     if (ret &&
3130                         ret->name != xmlStringTextNoenc) {
3131                                 xmlNodeSetName(ret, BAD_CAST(ZSTR_VAL(name)));
3132                     }
3133                 } ZEND_HASH_FOREACH_END();
3134                 return ret;
3135         }
3136         if (Z_TYPE_P(data) == IS_STRING) {
3137                 ret = xmlNewTextLen(BAD_CAST(Z_STRVAL_P(data)), Z_STRLEN_P(data));
3138         } else {
3139                 zend_string *tmp = zval_get_string(data);
3140                 ret = xmlNewTextLen(BAD_CAST(ZSTR_VAL(tmp)), ZSTR_LEN(tmp));
3141                 zend_string_release(tmp);
3142         }
3143 
3144         ret->name = xmlStringTextNoenc;
3145         ret->parent = parent;
3146         ret->doc = parent->doc;
3147         ret->prev = parent->last;
3148         ret->next = NULL;
3149         if (parent->last) {
3150                 parent->last->next = ret;
3151         } else {
3152                 parent->children = ret;
3153         }
3154         parent->last = ret;
3155 
3156         return ret;
3157 }
3158 
3159 zval *sdl_guess_convert_zval(zval *ret, encodeTypePtr enc, xmlNodePtr data)
3160 {
3161         sdlTypePtr type;
3162 
3163         type = enc->sdl_type;
3164         if (type == NULL) {
3165                 return guess_zval_convert(ret, enc, data);
3166         }
3167 /*FIXME: restriction support
3168         if (type && type->restrictions &&
3169             data &&  data->children && data->children->content) {
3170                 if (type->restrictions->whiteSpace && type->restrictions->whiteSpace->value) {
3171                         if (strcmp(type->restrictions->whiteSpace->value,"replace") == 0) {
3172                                 whiteSpace_replace(data->children->content);
3173                         } else if (strcmp(type->restrictions->whiteSpace->value,"collapse") == 0) {
3174                                 whiteSpace_collapse(data->children->content);
3175                         }
3176                 }
3177                 if (type->restrictions->enumeration) {
3178                         if (!zend_hash_exists(type->restrictions->enumeration,data->children->content,strlen(data->children->content)+1)) {
3179                                 soap_error1(E_WARNING, "Encoding: Restriction: invalid enumeration value \"%s\"", data->children->content);
3180                         }
3181                 }
3182                 if (type->restrictions->minLength &&
3183                     strlen(data->children->content) < type->restrictions->minLength->value) {
3184                   soap_error0(E_WARNING, "Encoding: Restriction: length less than 'minLength'");
3185                 }
3186                 if (type->restrictions->maxLength &&
3187                     strlen(data->children->content) > type->restrictions->maxLength->value) {
3188                   soap_error0(E_WARNING, "Encoding: Restriction: length greater than 'maxLength'");
3189                 }
3190                 if (type->restrictions->length &&
3191                     strlen(data->children->content) != type->restrictions->length->value) {
3192                   soap_error0(E_WARNING, "Encoding: Restriction: length is not equal to 'length'");
3193                 }
3194         }
3195 */
3196         switch (type->kind) {
3197                 case XSD_TYPEKIND_SIMPLE:
3198                         if (type->encode && enc != &type->encode->details) {
3199                                 return master_to_zval_int(ret, type->encode, data);
3200                         } else {
3201                                 return guess_zval_convert(ret, enc, data);
3202                         }
3203                         break;
3204                 case XSD_TYPEKIND_LIST:
3205                         return to_zval_list(ret, enc, data);
3206                 case XSD_TYPEKIND_UNION:
3207                         return to_zval_union(ret, enc, data);
3208                 case XSD_TYPEKIND_COMPLEX:
3209                 case XSD_TYPEKIND_RESTRICTION:
3210                 case XSD_TYPEKIND_EXTENSION:
3211                         if (type->encode &&
3212                             (type->encode->details.type == IS_ARRAY ||
3213                              type->encode->details.type == SOAP_ENC_ARRAY)) {
3214                                 return to_zval_array(ret, enc, data);
3215                         }
3216                         return to_zval_object(ret, enc, data);
3217                 default:
3218                 soap_error0(E_ERROR, "Encoding: Internal Error");
3219                         return guess_zval_convert(ret, enc, data);
3220         }
3221 }
3222 
3223 xmlNodePtr sdl_guess_convert_xml(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent)
3224 {
3225         sdlTypePtr type;
3226         xmlNodePtr ret = NULL;
3227 
3228         type = enc->sdl_type;
3229 
3230         if (type == NULL) {
3231                 ret = guess_xml_convert(enc, data, style, parent);
3232                 if (style == SOAP_ENCODED) {
3233                         set_ns_and_type(ret, enc);
3234                 }
3235                 return ret;
3236         }
3237 /*FIXME: restriction support
3238         if (type) {
3239                 if (type->restrictions && Z_TYPE_P(data) == IS_STRING) {
3240                         if (type->restrictions->enumeration) {
3241                                 if (!zend_hash_exists(type->restrictions->enumeration,Z_STRVAL_P(data),Z_STRLEN_P(data)+1)) {
3242                                         soap_error1(E_WARNING, "Encoding: Restriction: invalid enumeration value \"%s\".", Z_STRVAL_P(data));
3243                                 }
3244                         }
3245                         if (type->restrictions->minLength &&
3246                             Z_STRLEN_P(data) < type->restrictions->minLength->value) {
3247                         soap_error0(E_WARNING, "Encoding: Restriction: length less than 'minLength'");
3248                         }
3249                         if (type->restrictions->maxLength &&
3250                             Z_STRLEN_P(data) > type->restrictions->maxLength->value) {
3251                         soap_error0(E_WARNING, "Encoding: Restriction: length greater than 'maxLength'");
3252                         }
3253                         if (type->restrictions->length &&
3254                             Z_STRLEN_P(data) != type->restrictions->length->value) {
3255                         soap_error0(E_WARNING, "Encoding: Restriction: length is not equal to 'length'");
3256                         }
3257                 }
3258         }
3259 */
3260         switch(type->kind) {
3261                 case XSD_TYPEKIND_SIMPLE:
3262                         if (type->encode && enc != &type->encode->details) {
3263                                 ret = master_to_xml(type->encode, data, style, parent);
3264                         } else {
3265                                 ret = guess_xml_convert(enc, data, style, parent);
3266                         }
3267                         break;
3268                 case XSD_TYPEKIND_LIST:
3269                         ret = to_xml_list(enc, data, style, parent);
3270                         break;
3271                 case XSD_TYPEKIND_UNION:
3272                         ret = to_xml_union(enc, data, style, parent);
3273                         break;
3274                 case XSD_TYPEKIND_COMPLEX:
3275                 case XSD_TYPEKIND_RESTRICTION:
3276                 case XSD_TYPEKIND_EXTENSION:
3277                         if (type->encode &&
3278                             (type->encode->details.type == IS_ARRAY ||
3279                              type->encode->details.type == SOAP_ENC_ARRAY)) {
3280                                 return to_xml_array(enc, data, style, parent);
3281                         } else {
3282                                 return to_xml_object(enc, data, style, parent);
3283                         }
3284                         break;
3285                 default:
3286                 soap_error0(E_ERROR, "Encoding: Internal Error");
3287                         break;
3288         }
3289         if (style == SOAP_ENCODED) {
3290                 set_ns_and_type(ret, enc);
3291         }
3292         return ret;
3293 }
3294 
3295 static xmlNodePtr check_and_resolve_href(xmlNodePtr data)
3296 {
3297         if (data && data->properties) {
3298                 xmlAttrPtr href;
3299 
3300                 href = data->properties;
3301                 while (1) {
3302                         href = get_attribute(href, "href");
3303                         if (href == NULL || href->ns == NULL) {break;}
3304                         href = href->next;
3305                 }
3306                 if (href) {
3307                         /*  Internal href try and find node */
3308                         if (href->children->content[0] == '#') {
3309                                 xmlNodePtr ret = get_node_with_attribute_recursive(data->doc->children, NULL, "id", (char*)&href->children->content[1]);
3310                                 if (!ret) {
3311                                         soap_error1(E_ERROR, "Encoding: Unresolved reference '%s'", href->children->content);
3312                                 }
3313                                 return ret;
3314                         } else {
3315                                 /*  TODO: External href....? */
3316                                 soap_error1(E_ERROR, "Encoding: External reference '%s'", href->children->content);
3317                         }
3318                 }
3319                 /* SOAP 1.2 enc:id enc:ref */
3320                 href = get_attribute_ex(data->properties, "ref", SOAP_1_2_ENC_NAMESPACE);
3321                 if (href) {
3322                         xmlChar* id;
3323                         xmlNodePtr ret;
3324 
3325                         if (href->children->content[0] == '#') {
3326                                 id = href->children->content+1;
3327                         } else {
3328                                 id = href->children->content;
3329                         }
3330                         ret = get_node_with_attribute_recursive_ex(data->doc->children, NULL, NULL, "id", (char*)id, SOAP_1_2_ENC_NAMESPACE);
3331                         if (!ret) {
3332                                 soap_error1(E_ERROR, "Encoding: Unresolved reference '%s'", href->children->content);
3333                         } else if (ret == data) {
3334                                 soap_error1(E_ERROR, "Encoding: Violation of id and ref information items '%s'", href->children->content);
3335                         }
3336                         return ret;
3337                 }
3338         }
3339         return data;
3340 }
3341 
3342 static void set_ns_and_type(xmlNodePtr node, encodeTypePtr type)
3343 {
3344         set_ns_and_type_ex(node, type->ns, type->type_str);
3345 }
3346 
3347 static void set_ns_and_type_ex(xmlNodePtr node, char *ns, char *type)
3348 {
3349         smart_str nstype = {0};
3350         get_type_str(node, ns, type, &nstype);
3351         set_xsi_type(node, ZSTR_VAL(nstype.s));
3352         smart_str_free(&nstype);
3353 }
3354 
3355 static xmlNsPtr xmlSearchNsPrefixByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href)
3356 {
3357         xmlNsPtr cur;
3358         xmlNodePtr orig = node;
3359 
3360         while (node) {
3361                 if (node->type == XML_ENTITY_REF_NODE ||
3362                     node->type == XML_ENTITY_NODE ||
3363                     node->type == XML_ENTITY_DECL) {
3364                         return NULL;
3365                 }
3366                 if (node->type == XML_ELEMENT_NODE) {
3367                         cur = node->nsDef;
3368                         while (cur != NULL) {
3369                                 if (cur->prefix && cur->href && xmlStrEqual(cur->href, href)) {
3370                                         if (xmlSearchNs(doc, node, cur->prefix) == cur) {
3371                                                 return cur;
3372                                         }
3373                                 }
3374                                 cur = cur->next;
3375                         }
3376                         if (orig != node) {
3377                                 cur = node->ns;
3378                                 if (cur != NULL) {
3379                                         if (cur->prefix && cur->href && xmlStrEqual(cur->href, href)) {
3380                                                 if (xmlSearchNs(doc, node, cur->prefix) == cur) {
3381                                                         return cur;
3382                                                 }
3383                                         }
3384                                 }
3385                         }
3386                 }
3387                 node = node->parent;
3388         }
3389         return NULL;
3390 }
3391 
3392 xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns)
3393 {
3394         xmlNsPtr xmlns;
3395 
3396         if (ns == NULL) {
3397           return NULL;
3398         }
3399 
3400         xmlns = xmlSearchNsByHref(node->doc, node, BAD_CAST(ns));
3401         if (xmlns != NULL && xmlns->prefix == NULL) {
3402                 xmlns = xmlSearchNsPrefixByHref(node->doc, node, BAD_CAST(ns));
3403         }
3404         if (xmlns == NULL) {
3405                 xmlChar* prefix;
3406 
3407                 if ((prefix = zend_hash_str_find_ptr(&SOAP_GLOBAL(defEncNs), (char*)ns, strlen(ns))) != NULL) {
3408                         xmlns = xmlNewNs(node->doc->children, BAD_CAST(ns), prefix);
3409                 } else {
3410                         smart_str prefix = {0};
3411                         int num = ++SOAP_GLOBAL(cur_uniq_ns);
3412 
3413                         while (1) {
3414                                 smart_str_appendl(&prefix, "ns", 2);
3415                                 smart_str_append_long(&prefix, num);
3416                                 smart_str_0(&prefix);
3417                                 if (xmlSearchNs(node->doc, node, BAD_CAST(ZSTR_VAL(prefix.s))) == NULL) {
3418                                         break;
3419                                 }
3420                                 smart_str_free(&prefix);
3421                                 prefix.s = NULL;
3422                                 num = ++SOAP_GLOBAL(cur_uniq_ns);
3423                         }
3424 
3425                         xmlns = xmlNewNs(node->doc->children, BAD_CAST(ns), BAD_CAST(prefix.s ? ZSTR_VAL(prefix.s) : ""));
3426                         smart_str_free(&prefix);
3427                 }
3428         }
3429         return xmlns;
3430 }
3431 
3432 static void set_ns_prop(xmlNodePtr node, char *ns, char *name, char *val)
3433 {
3434         xmlSetNsProp(node, encode_add_ns(node, ns), BAD_CAST(name), BAD_CAST(val));
3435 }
3436 
3437 static void set_xsi_nil(xmlNodePtr node)
3438 {
3439         set_ns_prop(node, XSI_NAMESPACE, "nil", "true");
3440 }
3441 
3442 static void set_xsi_type(xmlNodePtr node, char *type)
3443 {
3444         set_ns_prop(node, XSI_NAMESPACE, "type", type);
3445 }
3446 
3447 void encode_reset_ns()
3448 {
3449         SOAP_GLOBAL(cur_uniq_ns) = 0;
3450         SOAP_GLOBAL(cur_uniq_ref) = 0;
3451         if (SOAP_GLOBAL(ref_map)) {
3452                 zend_hash_destroy(SOAP_GLOBAL(ref_map));
3453         } else {
3454                 SOAP_GLOBAL(ref_map) = emalloc(sizeof(HashTable));
3455         }
3456         zend_hash_init(SOAP_GLOBAL(ref_map), 0, NULL, NULL, 0);
3457 }
3458 
3459 void encode_finish()
3460 {
3461         SOAP_GLOBAL(cur_uniq_ns) = 0;
3462         SOAP_GLOBAL(cur_uniq_ref) = 0;
3463         if (SOAP_GLOBAL(ref_map)) {
3464                 zend_hash_destroy(SOAP_GLOBAL(ref_map));
3465                 efree(SOAP_GLOBAL(ref_map));
3466                 SOAP_GLOBAL(ref_map) = NULL;
3467         }
3468 }
3469 
3470 encodePtr get_conversion(int encode)
3471 {
3472         encodePtr enc;
3473 
3474         if ((enc = zend_hash_index_find_ptr(&SOAP_GLOBAL(defEncIndex), encode)) == NULL) {
3475                 soap_error0(E_ERROR,  "Encoding: Cannot find encoding");
3476                 return NULL;
3477         } else {
3478                 return enc;
3479         }
3480 }
3481 
3482 static int is_map(zval *array)
3483 {
3484         zend_ulong index;
3485         zend_string *key;
3486         int i = 0;
3487 
3488         ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(array), index, key) {
3489                 if (key || index != i) {
3490                         return TRUE;
3491                 }
3492                 i++;
3493         } ZEND_HASH_FOREACH_END();
3494         return FALSE;
3495 }
3496 
3497 static encodePtr get_array_type(xmlNodePtr node, zval *array, smart_str *type)
3498 {
3499         HashTable *ht;
3500         int i, cur_type, prev_type, different;
3501         zval *tmp;
3502         char *prev_stype = NULL, *cur_stype = NULL, *prev_ns = NULL, *cur_ns = NULL;
3503 
3504         if (!array || Z_TYPE_P(array) != IS_ARRAY) {
3505                 smart_str_appendl(type, "xsd:anyType", sizeof("xsd:anyType")-1);
3506                 return get_conversion(XSD_ANYTYPE);
3507         }
3508 
3509         i = 0;
3510         different = FALSE;
3511         cur_type = prev_type = 0;
3512         ht = Z_ARRVAL_P(array);
3513 
3514         ZEND_HASH_FOREACH_VAL_IND(ht, tmp) {
3515                 if (Z_TYPE_P(tmp) == IS_OBJECT &&
3516                     Z_OBJCE_P(tmp) == soap_var_class_entry) {
3517                         zval *ztype;
3518 
3519                         if ((ztype = zend_hash_str_find(Z_OBJPROP_P(tmp), "enc_type", sizeof("enc_type")-1)) == NULL ||
3520                             Z_TYPE_P(ztype) != IS_LONG) {
3521                                 soap_error0(E_ERROR,  "Encoding: SoapVar has no 'enc_type' property");
3522                         }
3523                         cur_type = Z_LVAL_P(ztype);
3524 
3525                         if ((ztype = zend_hash_str_find(Z_OBJPROP_P(tmp), "enc_stype", sizeof("enc_stype")-1)) != NULL &&
3526                             Z_TYPE_P(ztype) == IS_STRING) {
3527                                 cur_stype = Z_STRVAL_P(ztype);
3528                         } else {
3529                                 cur_stype = NULL;
3530                         }
3531 
3532                         if ((ztype = zend_hash_str_find(Z_OBJPROP_P(tmp), "enc_ns", sizeof("enc_ns")-1)) != NULL &&
3533                             Z_TYPE_P(ztype) == IS_STRING) {
3534                                 cur_ns = Z_STRVAL_P(ztype);
3535                         } else {
3536                                 cur_ns = NULL;
3537                         }
3538 
3539                 } else if (Z_TYPE_P(tmp) == IS_ARRAY && is_map(tmp)) {
3540                         cur_type = APACHE_MAP;
3541                         cur_stype = NULL;
3542                         cur_ns = NULL;
3543                 } else {
3544                         cur_type = Z_TYPE_P(tmp);
3545                         cur_stype = NULL;
3546                         cur_ns = NULL;
3547                 }
3548 
3549                 if (i > 0) {
3550                         if ((cur_type != prev_type) ||
3551                             (cur_stype != NULL && prev_stype != NULL && strcmp(cur_stype,prev_stype) != 0) ||
3552                             (cur_stype == NULL && cur_stype != prev_stype) ||
3553                             (cur_ns != NULL && prev_ns != NULL && strcmp(cur_ns,prev_ns) != 0) ||
3554                             (cur_ns == NULL && cur_ns != prev_ns)) {
3555                                 different = TRUE;
3556                                 break;
3557                         }
3558                 }
3559 
3560                 prev_type = cur_type;
3561                 prev_stype = cur_stype;
3562                 prev_ns = cur_ns;
3563                 i++;
3564         } ZEND_HASH_FOREACH_END();
3565 
3566         if (different || i == 0) {
3567                 smart_str_appendl(type, "xsd:anyType", sizeof("xsd:anyType")-1);
3568                 return get_conversion(XSD_ANYTYPE);
3569         } else {
3570                 encodePtr enc;
3571 
3572                 if (cur_stype != NULL) {
3573                         smart_str array_type = {0};
3574 
3575                         if (cur_ns) {
3576                                 xmlNsPtr ns = encode_add_ns(node, cur_ns);
3577 
3578                                 smart_str_appends(type, (char*)ns->prefix);
3579                                 smart_str_appendc(type, ':');
3580                                 smart_str_appends(&array_type, cur_ns);
3581                                 smart_str_appendc(&array_type, ':');
3582                         }
3583                         smart_str_appends(type, cur_stype);
3584                         smart_str_0(type);
3585                         smart_str_appends(&array_type, cur_stype);
3586                         smart_str_0(&array_type);
3587 
3588                         enc = get_encoder_ex(SOAP_GLOBAL(sdl), ZSTR_VAL(array_type.s), ZSTR_LEN(array_type.s));
3589                         smart_str_free(&array_type);
3590                         return enc;
3591                 } else {
3592                         enc = get_conversion(cur_type);
3593                         get_type_str(node, enc->details.ns, enc->details.type_str, type);
3594                         return enc;
3595                 }
3596         }
3597         return NULL;
3598 }
3599 
3600 static void get_type_str(xmlNodePtr node, const char* ns, const char* type, smart_str* ret)
3601 {
3602 
3603         if (ns) {
3604                 xmlNsPtr xmlns;
3605                 if (SOAP_GLOBAL(soap_version) == SOAP_1_2 &&
3606                     strcmp(ns,SOAP_1_1_ENC_NAMESPACE) == 0) {
3607                         ns = SOAP_1_2_ENC_NAMESPACE;
3608                 } else if (SOAP_GLOBAL(soap_version) == SOAP_1_1 &&
3609                            strcmp(ns,SOAP_1_2_ENC_NAMESPACE) == 0) {
3610                         ns = SOAP_1_1_ENC_NAMESPACE;
3611                 }
3612                 xmlns = encode_add_ns(node, ns);
3613                 smart_str_appends(ret, (char*)xmlns->prefix);
3614                 smart_str_appendc(ret, ':');
3615         }
3616         smart_str_appendl(ret, type, strlen(type));
3617         smart_str_0(ret);
3618 }
3619 
3620 static void delete_mapping(void *data)
3621 {
3622         soapMappingPtr map = (soapMappingPtr)data;
3623 
3624         zval_ptr_dtor(&map->to_xml);
3625         zval_ptr_dtor(&map->to_zval);
3626         efree(map);
3627 }
3628 
3629 void delete_encoder(zval *zv)
3630 {
3631         encodePtr t = Z_PTR_P(zv);
3632         if (t->details.ns) {
3633                 efree(t->details.ns);
3634         }
3635         if (t->details.type_str) {
3636                 efree(t->details.type_str);
3637         }
3638         if (t->details.map) {
3639                 delete_mapping(t->details.map);
3640         }
3641         efree(t);
3642 }
3643 
3644 void delete_encoder_persistent(zval *zv)
3645 {
3646         encodePtr t = Z_PTR_P(zv);
3647         if (t->details.ns) {
3648                 free(t->details.ns);
3649         }
3650         if (t->details.type_str) {
3651                 free(t->details.type_str);
3652         }
3653         /* we should never have mapping in persistent encoder */
3654         assert(t->details.map == NULL);
3655         free(t);
3656 }

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