You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3767 lines
114 KiB

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