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.

2757 lines
84 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
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
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-2004 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.0 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_0.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. /* zval type decode */
  24. static zval *to_zval_double(encodeTypePtr type, xmlNodePtr data);
  25. static zval *to_zval_long(encodeTypePtr type, xmlNodePtr data);
  26. static zval *to_zval_ulong(encodeTypePtr type, xmlNodePtr data);
  27. static zval *to_zval_bool(encodeTypePtr type, xmlNodePtr data);
  28. static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data);
  29. static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data);
  30. static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data);
  31. static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data);
  32. static zval *to_zval_null(encodeTypePtr type, xmlNodePtr data);
  33. static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  34. static xmlNodePtr to_xml_ulong(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  35. static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  36. static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  37. /* String encode */
  38. static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  39. static xmlNodePtr to_xml_stringl(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  40. /* Null encode */
  41. static xmlNodePtr to_xml_null(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  42. /* Array encode */
  43. static xmlNodePtr guess_array_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  44. static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  45. static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent);
  46. static xmlNodePtr to_xml_list1(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent);
  47. /* Datetime encode/decode */
  48. static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, int style, xmlNodePtr parent);
  49. static xmlNodePtr to_xml_datetime(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  50. static xmlNodePtr to_xml_time(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  51. static xmlNodePtr to_xml_date(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  52. static xmlNodePtr to_xml_gyearmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  53. static xmlNodePtr to_xml_gyear(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  54. static xmlNodePtr to_xml_gmonthday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  55. static xmlNodePtr to_xml_gday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  56. static xmlNodePtr to_xml_gmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  57. static xmlNodePtr to_xml_duration(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  58. static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data);
  59. static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data);
  60. static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  61. static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  62. /* Try and guess for non-wsdl clients and servers */
  63. static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data);
  64. static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
  65. static int is_map(zval *array);
  66. static void get_array_type(xmlNodePtr node, zval *array, smart_str *out_type TSRMLS_DC);
  67. static xmlNodePtr check_and_resolve_href(xmlNodePtr data);
  68. static encodePtr get_conversion(int encode);
  69. static void get_type_str(xmlNodePtr node, const char* ns, const char* type, smart_str* ret);
  70. static void set_ns_and_type_ex(xmlNodePtr node, char *ns, char *type);
  71. static void set_ns_and_type(xmlNodePtr node, encodeTypePtr type);
  72. #define FIND_XML_NULL(xml,zval) \
  73. { \
  74. xmlAttrPtr null; \
  75. if (!xml) { \
  76. ZVAL_NULL(zval); \
  77. return zval; \
  78. } \
  79. if (xml->properties) { \
  80. null = get_attribute(xml->properties, "nil"); \
  81. if (null) { \
  82. ZVAL_NULL(zval); \
  83. return zval; \
  84. } \
  85. } \
  86. }
  87. #define FIND_ZVAL_NULL(zval, xml, style) \
  88. { \
  89. if (!zval || Z_TYPE_P(zval) == IS_NULL) { \
  90. if (style == SOAP_ENCODED) {\
  91. xmlSetProp(xml, "xsi:nil", "1"); \
  92. } \
  93. return xml; \
  94. } \
  95. }
  96. encode defaultEncoding[] = {
  97. {{UNKNOWN_TYPE, NULL, NULL, NULL}, guess_zval_convert, guess_xml_convert},
  98. {{IS_NULL, "nil", XSI_NAMESPACE, NULL}, to_zval_null, to_xml_null},
  99. {{IS_STRING, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
  100. {{IS_LONG, XSD_INT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  101. {{IS_DOUBLE, XSD_FLOAT_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_double},
  102. {{IS_BOOL, XSD_BOOLEAN_STRING, XSD_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
  103. {{IS_CONSTANT, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
  104. {{IS_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_array, guess_array_map},
  105. {{IS_CONSTANT_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
  106. {{IS_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
  107. {{IS_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_array, guess_array_map},
  108. {{IS_CONSTANT_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
  109. {{IS_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
  110. {{XSD_STRING, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
  111. {{XSD_BOOLEAN, XSD_BOOLEAN_STRING, XSD_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
  112. {{XSD_DECIMAL, XSD_DECIMAL_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
  113. {{XSD_FLOAT, XSD_FLOAT_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_double},
  114. {{XSD_DOUBLE, XSD_DOUBLE_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_double},
  115. {{XSD_DATETIME, XSD_DATETIME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_datetime},
  116. {{XSD_TIME, XSD_TIME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_time},
  117. {{XSD_DATE, XSD_DATE_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_date},
  118. {{XSD_GYEARMONTH, XSD_GYEARMONTH_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gyearmonth},
  119. {{XSD_GYEAR, XSD_GYEAR_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gyear},
  120. {{XSD_GMONTHDAY, XSD_GMONTHDAY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gmonthday},
  121. {{XSD_GDAY, XSD_GDAY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gday},
  122. {{XSD_GMONTH, XSD_GMONTH_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gmonth},
  123. {{XSD_DURATION, XSD_DURATION_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_duration},
  124. {{XSD_HEXBINARY, XSD_HEXBINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_stringl},
  125. {{XSD_BASE64BINARY, XSD_BASE64BINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_stringl},
  126. {{XSD_LONG, XSD_LONG_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  127. {{XSD_INT, XSD_INT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  128. {{XSD_SHORT, XSD_SHORT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  129. {{XSD_BYTE, XSD_BYTE_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  130. {{XSD_NONPOSITIVEINTEGER, XSD_NONPOSITIVEINTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  131. {{XSD_POSITIVEINTEGER, XSD_POSITIVEINTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  132. {{XSD_NONNEGATIVEINTEGER, XSD_NONNEGATIVEINTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  133. {{XSD_NEGATIVEINTEGER, XSD_NEGATIVEINTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  134. {{XSD_UNSIGNEDBYTE, XSD_UNSIGNEDBYTE_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  135. {{XSD_UNSIGNEDSHORT, XSD_UNSIGNEDSHORT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  136. {{XSD_UNSIGNEDINT, XSD_UNSIGNEDINT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  137. {{XSD_UNSIGNEDLONG, XSD_UNSIGNEDLONG_STRING, XSD_NAMESPACE, NULL}, to_zval_ulong, to_xml_ulong},
  138. {{XSD_ANYTYPE, XSD_ANYTYPE_STRING, XSD_NAMESPACE, NULL}, guess_zval_convert, guess_xml_convert},
  139. {{XSD_UR_TYPE, XSD_UR_TYPE_STRING, XSD_NAMESPACE, NULL}, guess_zval_convert, guess_xml_convert},
  140. {{XSD_ANYURI, XSD_ANYURI_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
  141. {{XSD_QNAME, XSD_QNAME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
  142. {{XSD_NOTATION, XSD_NOTATION_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
  143. {{XSD_NORMALIZEDSTRING, XSD_NORMALIZEDSTRING_STRING, XSD_NAMESPACE, NULL}, to_zval_stringr, to_xml_string},
  144. {{XSD_TOKEN, XSD_TOKEN_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
  145. {{XSD_LANGUAGE, XSD_LANGUAGE_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
  146. {{XSD_NMTOKEN, XSD_NMTOKEN_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
  147. {{XSD_NMTOKENS, XSD_NMTOKENS_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_list1},
  148. {{XSD_NAME, XSD_NAME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
  149. {{XSD_NCNAME, XSD_NCNAME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
  150. {{XSD_ID, XSD_ID_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
  151. {{XSD_IDREF, XSD_IDREF_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
  152. {{XSD_IDREFS, XSD_IDREFS_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_list1},
  153. {{XSD_ENTITY, XSD_ENTITY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
  154. {{XSD_ENTITIES, XSD_ENTITIES_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_list1},
  155. {{APACHE_MAP, APACHE_MAP_STRING, APACHE_NAMESPACE, NULL}, to_zval_map, to_xml_map},
  156. {{SOAP_ENC_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
  157. {{SOAP_ENC_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
  158. {{SOAP_ENC_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
  159. {{SOAP_ENC_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
  160. /* support some of the 1999 data types */
  161. {{XSD_STRING, XSD_STRING_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_string, to_xml_string},
  162. {{XSD_BOOLEAN, XSD_BOOLEAN_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
  163. {{XSD_DECIMAL, XSD_DECIMAL_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
  164. {{XSD_FLOAT, XSD_FLOAT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_double, to_xml_double},
  165. {{XSD_DOUBLE, XSD_DOUBLE_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_double, to_xml_double},
  166. {{XSD_LONG, XSD_LONG_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  167. {{XSD_INT, XSD_INT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  168. {{XSD_SHORT, XSD_SHORT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  169. {{XSD_BYTE, XSD_BYTE_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  170. {{XSD_1999_TIMEINSTANT, XSD_1999_TIMEINSTANT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
  171. {{END_KNOWN_TYPES, NULL, NULL, NULL}, guess_zval_convert, guess_xml_convert}
  172. };
  173. void whiteSpace_replace(char* str)
  174. {
  175. while (*str != '\0') {
  176. if (*str == '\x9' || *str == '\xA' || *str == '\xD') {
  177. *str = ' ';
  178. }
  179. str++;
  180. }
  181. }
  182. void whiteSpace_collapse(char* str)
  183. {
  184. char *pos;
  185. char old;
  186. pos = str;
  187. whiteSpace_replace(str);
  188. while (*str == ' ') {
  189. str++;
  190. }
  191. old = '\0';
  192. while (*str != '\0') {
  193. if (*str != ' ' || old != ' ') {
  194. *pos = *str;
  195. pos++;
  196. }
  197. old = *str;
  198. str++;
  199. }
  200. if (old == ' ') {
  201. --pos;
  202. }
  203. *pos = '\0';
  204. }
  205. xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr parent)
  206. {
  207. xmlNodePtr node = NULL;
  208. TSRMLS_FETCH();
  209. /* Special handling of class SoapVar */
  210. if (data &&
  211. Z_TYPE_P(data) == IS_OBJECT &&
  212. Z_OBJCE_P(data) == soap_var_class_entry) {
  213. zval **ztype, **zdata, **zns, **zstype, **zname, **znamens;
  214. encodePtr enc = NULL;
  215. HashTable *ht = Z_OBJPROP_P(data);
  216. if (zend_hash_find(ht, "enc_type", sizeof("enc_type"), (void **)&ztype) == FAILURE) {
  217. php_error(E_ERROR, "SOAP-ERROR: Encoding: SoapVar hasn't 'enc_type' propery");
  218. }
  219. if (SOAP_GLOBAL(sdl) && encode == NULL) {
  220. if (zend_hash_find(ht, "enc_stype", sizeof("enc_stype"), (void **)&zstype) == SUCCESS) {
  221. if (zend_hash_find(ht, "enc_ns", sizeof("enc_ns"), (void **)&zns) == SUCCESS) {
  222. enc = get_encoder(SOAP_GLOBAL(sdl), Z_STRVAL_PP(zns), Z_STRVAL_PP(zstype));
  223. } else {
  224. enc = get_encoder(SOAP_GLOBAL(sdl), NULL, Z_STRVAL_PP(zstype));
  225. }
  226. }
  227. }
  228. if (enc == NULL) {
  229. enc = get_conversion(Z_LVAL_P(*ztype));
  230. }
  231. if (zend_hash_find(ht, "enc_value", sizeof("enc_value"), (void **)&zdata) == FAILURE) {
  232. node = master_to_xml(enc, NULL, style, parent);
  233. } else {
  234. node = master_to_xml(enc, *zdata, style, parent);
  235. }
  236. if (style == SOAP_ENCODED || (SOAP_GLOBAL(sdl) && encode == NULL)) {
  237. if (zend_hash_find(ht, "enc_stype", sizeof("enc_stype"), (void **)&zstype) == SUCCESS) {
  238. if (style == SOAP_LITERAL) {
  239. encode_add_ns(node, XSI_NAMESPACE);
  240. }
  241. if (zend_hash_find(ht, "enc_ns", sizeof("enc_ns"), (void **)&zns) == SUCCESS) {
  242. set_ns_and_type_ex(node, Z_STRVAL_PP(zns), Z_STRVAL_PP(zstype));
  243. } else {
  244. set_ns_and_type_ex(node, NULL, Z_STRVAL_PP(zstype));
  245. }
  246. }
  247. }
  248. if (zend_hash_find(ht, "enc_name", sizeof("enc_name"), (void **)&zname) == SUCCESS) {
  249. xmlNodeSetName(node, Z_STRVAL_PP(zname));
  250. }
  251. if (zend_hash_find(ht, "enc_namens", sizeof("enc_namens"), (void **)&znamens) == SUCCESS) {
  252. xmlNsPtr nsp = encode_add_ns(node, Z_STRVAL_PP(znamens));
  253. xmlSetNs(node, nsp);
  254. }
  255. } else {
  256. if (encode == NULL) {
  257. encode = get_conversion(UNKNOWN_TYPE);
  258. }
  259. if (encode->to_xml_before) {
  260. data = encode->to_xml_before(&encode->details, data);
  261. }
  262. if (encode->to_xml) {
  263. node = encode->to_xml(&encode->details, data, style, parent);
  264. }
  265. if (encode->to_xml_after) {
  266. node = encode->to_xml_after(&encode->details, node, style);
  267. }
  268. }
  269. return node;
  270. }
  271. zval *master_to_zval(encodePtr encode, xmlNodePtr data)
  272. {
  273. zval *ret = NULL;
  274. TSRMLS_FETCH();
  275. if (encode == NULL) {
  276. encode = get_conversion(UNKNOWN_TYPE);
  277. }
  278. data = check_and_resolve_href(data);
  279. if (encode->to_zval_before) {
  280. data = encode->to_zval_before(&encode->details, data, 0);
  281. }
  282. if (encode->to_zval) {
  283. ret = encode->to_zval(&encode->details, data);
  284. }
  285. if (encode->to_zval_after) {
  286. ret = encode->to_zval_after(&encode->details, ret);
  287. }
  288. return ret;
  289. }
  290. #ifdef HAVE_PHP_DOMXML
  291. zval *to_xml_before_user(encodeTypePtr type, zval *data)
  292. {
  293. TSRMLS_FETCH();
  294. if (type.map->map_functions.to_xml_before) {
  295. if (call_user_function(EG(function_table), NULL, type.map->map_functions.to_xml_before, data, 1, &data TSRMLS_CC) == FAILURE) {
  296. php_error(E_ERROR, "SOAP-ERROR: Encoding: Error calling to_xml_before");
  297. }
  298. }
  299. return data;
  300. }
  301. xmlNodePtr to_xml_user(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  302. {
  303. zval *ret, **addr;
  304. xmlNodePtr node;
  305. TSRMLS_FETCH();
  306. if (type.map->map_functions.to_xml) {
  307. MAKE_STD_ZVAL(ret);
  308. if (call_user_function(EG(function_table), NULL, type.map->map_functions.to_xml, ret, 1, &data TSRMLS_CC) == FAILURE) {
  309. php_error(E_ERROR, "SOAP-ERROR: Encoding: Error calling to_xml");
  310. }
  311. if (Z_TYPE_P(ret) != IS_OBJECT) {
  312. php_error(E_ERROR, "SOAP-ERROR: Encoding: Error serializing object from to_xml_user");
  313. }
  314. if (zend_hash_index_find(Z_OBJPROP_P(ret), 1, (void **)&addr) == SUCCESS) {
  315. node = (xmlNodePtr)Z_LVAL_PP(addr);
  316. node = xmlCopyNode(node, 1);
  317. set_ns_and_type(node, type);
  318. }
  319. zval_ptr_dtor(&ret);
  320. }
  321. return node;
  322. }
  323. xmlNodePtr to_xml_after_user(encodeTypePtr type, xmlNodePtr node, int style)
  324. {
  325. zval *ret, *param, **addr;
  326. int found;
  327. TSRMLS_FETCH();
  328. if (type.map->map_functions.to_xml_after) {
  329. MAKE_STD_ZVAL(ret);
  330. MAKE_STD_ZVAL(param);
  331. param = php_domobject_new(node, &found, NULL TSRMLS_CC);
  332. if (call_user_function(EG(function_table), NULL, type.map->map_functions.to_xml_after, ret, 1, &param TSRMLS_CC) == FAILURE) {
  333. php_error(E_ERROR, "SOAP-ERROR: Encoding: Error calling to_xml_after");
  334. }
  335. if (zend_hash_index_find(Z_OBJPROP_P(ret), 1, (void **)&addr) == SUCCESS) {
  336. node = (xmlNodePtr)Z_LVAL_PP(addr);
  337. set_ns_and_type(node, type);
  338. }
  339. zval_ptr_dtor(&ret);
  340. zval_ptr_dtor(&param);
  341. }
  342. return node;
  343. }
  344. xmlNodePtr to_zval_before_user(encodeTypePtr type, xmlNodePtr node, int style)
  345. {
  346. zval *ret, *param, **addr;
  347. int found;
  348. TSRMLS_FETCH();
  349. if (type.map->map_functions.to_zval_before) {
  350. MAKE_STD_ZVAL(ret);
  351. MAKE_STD_ZVAL(param);
  352. param = php_domobject_new(node, &found, NULL TSRMLS_CC);
  353. if (call_user_function(EG(function_table), NULL, type.map->map_functions.to_zval_before, ret, 1, &param TSRMLS_CC) == FAILURE) {
  354. php_error(E_ERROR, "SOAP-ERROR: Encoding: Error calling to_zval_before");
  355. }
  356. if (zend_hash_index_find(Z_OBJPROP_P(ret), 1, (void **)&addr) == SUCCESS) {
  357. node = (xmlNodePtr)Z_LVAL_PP(addr);
  358. set_ns_and_type(node, type);
  359. }
  360. zval_ptr_dtor(&ret);
  361. zval_ptr_dtor(&param);
  362. }
  363. return node;
  364. }
  365. zval *to_zval_user(encodeTypePtr type, xmlNodePtr node)
  366. {
  367. zval *ret, *param;
  368. int found;
  369. TSRMLS_FETCH();
  370. if (type.map->map_functions.to_zval) {
  371. MAKE_STD_ZVAL(ret);
  372. MAKE_STD_ZVAL(param);
  373. param = php_domobject_new(node, &found, NULL TSRMLS_CC);
  374. if (call_user_function(EG(function_table), NULL, type.map->map_functions.to_zval, ret, 1, &param TSRMLS_CC) == FAILURE) {
  375. php_error(E_ERROR, "SOAP-ERROR: Encoding: Error calling to_zval");
  376. }
  377. zval_ptr_dtor(&param);
  378. efree(param);
  379. }
  380. return ret;
  381. }
  382. zval *to_zval_after_user(encodeTypePtr type, zval *data)
  383. {
  384. TSRMLS_FETCH();
  385. if (type.map->map_functions.to_zval_after) {
  386. if (call_user_function(EG(function_table), NULL, type.map->map_functions.to_zval_after, data, 1, &data TSRMLS_CC) == FAILURE) {
  387. php_error(E_ERROR, "SOAP-ERROR: Encoding: Error calling to_zval_after");
  388. }
  389. }
  390. return data;
  391. }
  392. #endif
  393. /* TODO: get rid of "bogus".. ither by passing in the already created xmlnode or passing in the node name */
  394. /* String encode/decode */
  395. static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data)
  396. {
  397. zval *ret;
  398. MAKE_STD_ZVAL(ret);
  399. FIND_XML_NULL(data, ret);
  400. if (data && data->children) {
  401. if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
  402. ZVAL_STRING(ret, data->children->content, 1);
  403. } else {
  404. php_error(E_ERROR,"SOAP-ERROR: Encoding: Violation of encoding rules");
  405. }
  406. } else {
  407. ZVAL_EMPTY_STRING(ret);
  408. }
  409. return ret;
  410. }
  411. static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data)
  412. {
  413. zval *ret;
  414. MAKE_STD_ZVAL(ret);
  415. FIND_XML_NULL(data, ret);
  416. if (data && data->children) {
  417. if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
  418. whiteSpace_replace(data->children->content);
  419. ZVAL_STRING(ret, data->children->content, 1);
  420. } else {
  421. php_error(E_ERROR,"SOAP-ERROR: Encoding: Violation of encoding rules");
  422. }
  423. } else {
  424. ZVAL_EMPTY_STRING(ret);
  425. }
  426. return ret;
  427. }
  428. static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data)
  429. {
  430. zval *ret;
  431. MAKE_STD_ZVAL(ret);
  432. FIND_XML_NULL(data, ret);
  433. if (data && data->children) {
  434. if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
  435. whiteSpace_collapse(data->children->content);
  436. ZVAL_STRING(ret, data->children->content, 1);
  437. } else {
  438. php_error(E_ERROR,"SOAP-ERROR: Encoding: Violation of encoding rules");
  439. }
  440. } else {
  441. ZVAL_EMPTY_STRING(ret);
  442. }
  443. return ret;
  444. }
  445. static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  446. {
  447. xmlNodePtr ret;
  448. char *str;
  449. int new_len;
  450. TSRMLS_FETCH();
  451. ret = xmlNewNode(NULL,"BOGUS");
  452. xmlAddChild(parent, ret);
  453. FIND_ZVAL_NULL(data, ret, style);
  454. if (Z_TYPE_P(data) == IS_STRING) {
  455. str = php_escape_html_entities(Z_STRVAL_P(data), Z_STRLEN_P(data), &new_len, 0, 0, NULL TSRMLS_CC);
  456. } else {
  457. zval tmp = *data;
  458. zval_copy_ctor(&tmp);
  459. convert_to_string(&tmp);
  460. str = php_escape_html_entities(Z_STRVAL(tmp), Z_STRLEN(tmp), &new_len, 0, 0, NULL TSRMLS_CC);
  461. zval_dtor(&tmp);
  462. }
  463. xmlNodeSetContentLen(ret, str, new_len);
  464. efree(str);
  465. if (style == SOAP_ENCODED) {
  466. set_ns_and_type(ret, type);
  467. }
  468. return ret;
  469. }
  470. static xmlNodePtr to_xml_stringl(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  471. {
  472. xmlNodePtr ret;
  473. ret = xmlNewNode(NULL,"BOGUS");
  474. xmlAddChild(parent, ret);
  475. FIND_ZVAL_NULL(data, ret, style);
  476. if (Z_TYPE_P(data) == IS_STRING) {
  477. xmlNodeSetContentLen(ret, Z_STRVAL_P(data), Z_STRLEN_P(data));
  478. } else {
  479. zval tmp = *data;
  480. zval_copy_ctor(&tmp);
  481. convert_to_string(&tmp);
  482. xmlNodeSetContentLen(ret, Z_STRVAL(tmp), Z_STRLEN(tmp));
  483. zval_dtor(&tmp);
  484. }
  485. if (style == SOAP_ENCODED) {
  486. set_ns_and_type(ret, type);
  487. }
  488. return ret;
  489. }
  490. static zval *to_zval_double(encodeTypePtr type, xmlNodePtr data)
  491. {
  492. zval *ret;
  493. MAKE_STD_ZVAL(ret);
  494. FIND_XML_NULL(data, ret);
  495. if (data && data->children) {
  496. if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
  497. whiteSpace_collapse(data->children->content);
  498. ZVAL_DOUBLE(ret, atof(data->children->content));
  499. } else {
  500. php_error(E_ERROR,"SOAP-ERROR: Encoding: Violation of encoding rules");
  501. }
  502. } else {
  503. ZVAL_NULL(ret);
  504. }
  505. return ret;
  506. }
  507. static zval *to_zval_long(encodeTypePtr type, xmlNodePtr data)
  508. {
  509. zval *ret;
  510. MAKE_STD_ZVAL(ret);
  511. FIND_XML_NULL(data, ret);
  512. if (data && data->children) {
  513. if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
  514. whiteSpace_collapse(data->children->content);
  515. ZVAL_LONG(ret, atol(data->children->content));
  516. } else {
  517. php_error(E_ERROR,"SOAP-ERROR: Encoding: Violation of encoding rules");
  518. }
  519. } else {
  520. ZVAL_NULL(ret);
  521. }
  522. return ret;
  523. }
  524. static zval *to_zval_ulong(encodeTypePtr type, xmlNodePtr data)
  525. {
  526. zval *ret;
  527. MAKE_STD_ZVAL(ret);
  528. FIND_XML_NULL(data, ret);
  529. if (data && data->children) {
  530. if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
  531. whiteSpace_collapse(data->children->content);
  532. errno = 0;
  533. ret->value.lval = strtol(data->children->content, NULL, 0);
  534. if (errno == ERANGE) { /* overflow */
  535. ret->value.dval = strtod(data->children->content, NULL);
  536. ret->type = IS_DOUBLE;
  537. } else {
  538. ret->type = IS_LONG;
  539. }
  540. } else {
  541. php_error(E_ERROR,"SOAP-ERROR: Encoding: Violation of encoding rules");
  542. }
  543. } else {
  544. ZVAL_NULL(ret);
  545. }
  546. return ret;
  547. }
  548. static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  549. {
  550. xmlNodePtr ret;
  551. zval tmp;
  552. ret = xmlNewNode(NULL,"BOGUS");
  553. xmlAddChild(parent, ret);
  554. FIND_ZVAL_NULL(data, ret, style);
  555. tmp = *data;
  556. zval_copy_ctor(&tmp);
  557. if (Z_TYPE(tmp) != IS_LONG) {
  558. convert_to_long(&tmp);
  559. }
  560. convert_to_string(&tmp);
  561. xmlNodeSetContentLen(ret, Z_STRVAL(tmp), Z_STRLEN(tmp));
  562. zval_dtor(&tmp);
  563. if (style == SOAP_ENCODED) {
  564. set_ns_and_type(ret, type);
  565. }
  566. return ret;
  567. }
  568. static xmlNodePtr to_xml_ulong(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  569. {
  570. xmlNodePtr ret;
  571. ret = xmlNewNode(NULL,"BOGUS");
  572. xmlAddChild(parent, ret);
  573. FIND_ZVAL_NULL(data, ret, style);
  574. if (Z_TYPE_P(data) == IS_DOUBLE) {
  575. char s[16];
  576. sprintf(s, "%0.0f",Z_DVAL_P(data));
  577. xmlNodeSetContent(ret, s);
  578. } else {
  579. zval tmp = *data;
  580. zval_copy_ctor(&tmp);
  581. if (Z_TYPE(tmp) != IS_LONG) {
  582. convert_to_long(&tmp);
  583. }
  584. convert_to_string(&tmp);
  585. xmlNodeSetContentLen(ret, Z_STRVAL(tmp), Z_STRLEN(tmp));
  586. zval_dtor(&tmp);
  587. }
  588. if (style == SOAP_ENCODED) {
  589. set_ns_and_type(ret, type);
  590. }
  591. return ret;
  592. }
  593. static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  594. {
  595. xmlNodePtr ret;
  596. zval tmp;
  597. ret = xmlNewNode(NULL,"BOGUS");
  598. xmlAddChild(parent, ret);
  599. FIND_ZVAL_NULL(data, ret, style);
  600. tmp = *data;
  601. zval_copy_ctor(&tmp);
  602. if (Z_TYPE(tmp) != IS_DOUBLE) {
  603. convert_to_double(&tmp);
  604. }
  605. convert_to_string(&tmp);
  606. xmlNodeSetContentLen(ret, Z_STRVAL(tmp), Z_STRLEN(tmp));
  607. zval_dtor(&tmp);
  608. if (style == SOAP_ENCODED) {
  609. set_ns_and_type(ret, type);
  610. }
  611. return ret;
  612. }
  613. static zval *to_zval_bool(encodeTypePtr type, xmlNodePtr data)
  614. {
  615. zval *ret;
  616. MAKE_STD_ZVAL(ret);
  617. FIND_XML_NULL(data, ret);
  618. if (data && data->children) {
  619. if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
  620. whiteSpace_collapse(data->children->content);
  621. if (stricmp(data->children->content,"true") == 0 ||
  622. stricmp(data->children->content,"t") == 0 ||
  623. strcmp(data->children->content,"1") == 0) {
  624. ZVAL_BOOL(ret, 1);
  625. } else {
  626. ZVAL_BOOL(ret, 0);
  627. }
  628. } else {
  629. php_error(E_ERROR,"SOAP-ERROR: Encoding: Violation of encoding rules");
  630. }
  631. } else {
  632. ZVAL_NULL(ret);
  633. }
  634. return ret;
  635. }
  636. static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  637. {
  638. xmlNodePtr ret;
  639. zval tmp;
  640. ret = xmlNewNode(NULL,"BOGUS");
  641. xmlAddChild(parent, ret);
  642. FIND_ZVAL_NULL(data, ret, style);
  643. if (Z_TYPE_P(data) != IS_BOOL) {
  644. tmp = *data;
  645. zval_copy_ctor(&tmp);
  646. convert_to_boolean(data);
  647. data = &tmp;
  648. }
  649. if (data->value.lval == 1) {
  650. xmlNodeSetContent(ret, "1");
  651. } else {
  652. xmlNodeSetContent(ret, "0");
  653. }
  654. if (data == &tmp) {
  655. zval_dtor(&tmp);
  656. }
  657. if (style == SOAP_ENCODED) {
  658. set_ns_and_type(ret, type);
  659. }
  660. return ret;
  661. }
  662. /* Null encode/decode */
  663. static zval *to_zval_null(encodeTypePtr type, xmlNodePtr data)
  664. {
  665. zval *ret;
  666. MAKE_STD_ZVAL(ret);
  667. ZVAL_NULL(ret);
  668. return ret;
  669. }
  670. static xmlNodePtr to_xml_null(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  671. {
  672. xmlNodePtr ret;
  673. ret = xmlNewNode(NULL,"BOGUS");
  674. xmlAddChild(parent, ret);
  675. if (style == SOAP_ENCODED) {
  676. xmlSetProp(ret, "xsi:nil", "1");
  677. }
  678. return ret;
  679. }
  680. static void model_to_zval_object(zval *ret, sdlContentModelPtr model, xmlNodePtr data, sdlPtr sdl TSRMLS_DC)
  681. {
  682. switch (model->kind) {
  683. case XSD_CONTENT_ELEMENT:
  684. if (model->u.element->name) {
  685. xmlNodePtr node = get_node(data->children, model->u.element->name);
  686. if (node) {
  687. zval *val;
  688. if (node && node->children && node->children->content) {
  689. if (model->u.element->fixed && strcmp(model->u.element->fixed,node->children->content) != 0) {
  690. php_error(E_ERROR,"SOAP-ERROR: Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)",model->u.element->name,model->u.element->fixed,node->children->content);
  691. }
  692. val = master_to_zval(model->u.element->encode, node);
  693. } else if (model->u.element->fixed) {
  694. xmlNodePtr dummy = xmlNewNode(NULL, "BOGUS");
  695. xmlNodeSetContent(dummy, model->u.element->fixed);
  696. val = master_to_zval(model->u.element->encode, dummy);
  697. xmlFreeNode(dummy);
  698. } else if (model->u.element->def && !model->u.element->nillable) {
  699. xmlNodePtr dummy = xmlNewNode(NULL, "BOGUS");
  700. xmlNodeSetContent(dummy, model->u.element->def);
  701. val = master_to_zval(model->u.element->encode, dummy);
  702. xmlFreeNode(dummy);
  703. } else {
  704. val = master_to_zval(model->u.element->encode, node);
  705. }
  706. if ((node = get_node(node->next, model->u.element->name)) != NULL) {
  707. zval *array;
  708. MAKE_STD_ZVAL(array);
  709. array_init(array);
  710. add_next_index_zval(array, val);
  711. do {
  712. if (node && node->children && node->children->content) {
  713. if (model->u.element->fixed && strcmp(model->u.element->fixed,node->children->content) != 0) {
  714. php_error(E_ERROR,"SOAP-ERROR: Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)",model->u.element->name,model->u.element->fixed,node->children->content);
  715. }
  716. val = master_to_zval(model->u.element->encode, node);
  717. } else if (model->u.element->fixed) {
  718. xmlNodePtr dummy = xmlNewNode(NULL, "BOGUS");
  719. xmlNodeSetContent(dummy, model->u.element->fixed);
  720. val = master_to_zval(model->u.element->encode, dummy);
  721. xmlFreeNode(dummy);
  722. } else if (model->u.element->def && !model->u.element->nillable) {
  723. xmlNodePtr dummy = xmlNewNode(NULL, "BOGUS");
  724. xmlNodeSetContent(dummy, model->u.element->def);
  725. val = master_to_zval(model->u.element->encode, dummy);
  726. xmlFreeNode(dummy);
  727. } else {
  728. val = master_to_zval(model->u.element->encode, node);
  729. }
  730. add_next_index_zval(array, val);
  731. } while ((node = get_node(node->next, model->u.element->name)) != NULL);
  732. val = array;
  733. }
  734. #ifdef ZEND_ENGINE_2
  735. val->refcount--;
  736. #endif
  737. add_property_zval(ret, model->u.element->name, val);
  738. }
  739. }
  740. break;
  741. case XSD_CONTENT_SEQUENCE:
  742. case XSD_CONTENT_ALL:
  743. case XSD_CONTENT_CHOICE: {
  744. sdlContentModelPtr *tmp;
  745. zend_hash_internal_pointer_reset(model->u.content);
  746. while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
  747. model_to_zval_object(ret, *tmp, data, sdl TSRMLS_CC);
  748. zend_hash_move_forward(model->u.content);
  749. }
  750. break;
  751. }
  752. case XSD_CONTENT_GROUP:
  753. model_to_zval_object(ret, model->u.group->model, data, sdl TSRMLS_CC);
  754. break;
  755. default:
  756. break;
  757. }
  758. }
  759. /* Struct encode/decode */
  760. static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data)
  761. {
  762. zval *ret;
  763. xmlNodePtr trav;
  764. sdlPtr sdl;
  765. sdlTypePtr sdlType = type->sdl_type;
  766. TSRMLS_FETCH();
  767. sdl = SOAP_GLOBAL(sdl);
  768. if (sdlType) {
  769. if (sdlType->kind == XSD_TYPEKIND_RESTRICTION &&
  770. sdlType->encode && type != &sdlType->encode->details) {
  771. encodePtr enc;
  772. enc = sdlType->encode;
  773. while (enc && enc->details.sdl_type &&
  774. enc->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
  775. enc->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
  776. enc->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
  777. enc = enc->details.sdl_type->encode;
  778. }
  779. if (enc) {
  780. zval *base;
  781. MAKE_STD_ZVAL(ret);
  782. object_init(ret);
  783. base = master_to_zval(enc, data);
  784. #ifdef ZEND_ENGINE_2
  785. base->refcount--;
  786. #endif
  787. add_property_zval(ret, "_", base);
  788. } else {
  789. MAKE_STD_ZVAL(ret);
  790. FIND_XML_NULL(data, ret);
  791. object_init(ret);
  792. }
  793. } else if (sdlType->kind == XSD_TYPEKIND_EXTENSION &&
  794. sdlType->encode &&
  795. type != &sdlType->encode->details) {
  796. if (sdlType->encode->details.sdl_type &&
  797. sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
  798. sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
  799. sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
  800. ret = master_to_zval(sdlType->encode, data);
  801. FIND_XML_NULL(data, ret);
  802. } else {
  803. zval *base;
  804. MAKE_STD_ZVAL(ret);
  805. object_init(ret);
  806. base = master_to_zval(sdlType->encode, data);
  807. #ifdef ZEND_ENGINE_2
  808. base->refcount--;
  809. #endif
  810. add_property_zval(ret, "_", base);
  811. }
  812. } else {
  813. MAKE_STD_ZVAL(ret);
  814. FIND_XML_NULL(data, ret);
  815. object_init(ret);
  816. }
  817. if (sdlType->model) {
  818. model_to_zval_object(ret, sdlType->model, data, sdl TSRMLS_CC);
  819. }
  820. if (sdlType->attributes) {
  821. sdlAttributePtr *attr;
  822. zend_hash_internal_pointer_reset(sdlType->attributes);
  823. while (zend_hash_get_current_data(sdlType->attributes, (void**)&attr) == SUCCESS) {
  824. if ((*attr)->name) {
  825. xmlAttrPtr val = get_attribute(data->properties, (*attr)->name);
  826. xmlChar *str_val = NULL;
  827. if (val && val->children && val->children->content) {
  828. str_val = val->children->content;
  829. if ((*attr)->fixed && strcmp((*attr)->fixed,str_val) != 0) {
  830. php_error(E_ERROR,"SOAP-ERROR: Encoding: Attribute '%s' has fixed value '%s' (value '%s' is not allowed)",(*attr)->name,(*attr)->fixed,str_val);
  831. }
  832. } else if ((*attr)->fixed) {
  833. str_val = (*attr)->fixed;
  834. } else if ((*attr)->def) {
  835. str_val = (*attr)->def;
  836. }
  837. if (str_val) {
  838. xmlNodePtr dummy;
  839. zval *data;
  840. dummy = xmlNewNode(NULL, "BOGUS");
  841. xmlNodeSetContent(dummy, str_val);
  842. data = master_to_zval((*attr)->encode, dummy);
  843. xmlFreeNode(dummy);
  844. #ifdef ZEND_ENGINE_2
  845. data->refcount--;
  846. #endif
  847. add_property_zval(ret, (*attr)->name, data);
  848. }
  849. }
  850. zend_hash_move_forward(sdlType->attributes);
  851. }
  852. }
  853. } else {
  854. MAKE_STD_ZVAL(ret);
  855. FIND_XML_NULL(data, ret);
  856. object_init(ret);
  857. trav = data->children;
  858. while (trav != NULL) {
  859. if (trav->type == XML_ELEMENT_NODE) {
  860. zval *tmpVal;
  861. tmpVal = master_to_zval(NULL, trav);
  862. #ifdef ZEND_ENGINE_2
  863. tmpVal->refcount--;
  864. #endif
  865. add_property_zval(ret, (char *)trav->name, tmpVal);
  866. }
  867. trav = trav->next;
  868. }
  869. }
  870. return ret;
  871. }
  872. static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, HashTable *prop, int style, int strict)
  873. {
  874. switch (model->kind) {
  875. case XSD_CONTENT_ELEMENT: {
  876. zval **data;
  877. xmlNodePtr property;
  878. encodePtr enc;
  879. if (zend_hash_find(prop, model->u.element->name, strlen(model->u.element->name)+1, (void**)&data) == SUCCESS) {
  880. enc = model->u.element->encode;
  881. if ((model->max_occurs == -1 || model->max_occurs > 1) && Z_TYPE_PP(data) == IS_ARRAY) {
  882. HashTable *ht = Z_ARRVAL_PP(data);
  883. zval **val;
  884. zend_hash_internal_pointer_reset(ht);
  885. while (zend_hash_get_current_data(ht,(void**)&val) == SUCCESS) {
  886. if (Z_TYPE_PP(val) == IS_NULL && model->u.element->nillable) {
  887. property = xmlNewNode(NULL,"BOGUS");
  888. xmlAddChild(node, property);
  889. if (style == SOAP_ENCODED) {
  890. xmlSetProp(property, "xsi:nil", "1");
  891. } else {
  892. xmlNsPtr xsi = encode_add_ns(property,XSI_NAMESPACE);
  893. xmlSetNsProp(property, xsi, "nil", "1");
  894. }
  895. } else {
  896. property = master_to_xml(enc, *val, style, node);
  897. if (property->children && property->children->content &&
  898. model->u.element->fixed && strcmp(model->u.element->fixed,property->children->content) != 0) {
  899. php_error(E_ERROR,"SOAP-ERROR: Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)",model->u.element->name,model->u.element->fixed,property->children->content);
  900. }
  901. }
  902. xmlNodeSetName(property, model->u.element->name);
  903. if (style == SOAP_LITERAL && model->u.element->namens) {
  904. xmlNsPtr nsp = encode_add_ns(property, model->u.element->namens);
  905. xmlSetNs(property, nsp);
  906. }
  907. zend_hash_move_forward(ht);
  908. }
  909. } else {
  910. if (Z_TYPE_PP(data) == IS_NULL && model->u.element->nillable) {
  911. property = xmlNewNode(NULL,"BOGUS");
  912. xmlAddChild(node, property);
  913. if (style == SOAP_ENCODED) {
  914. xmlSetProp(property, "xsi:nil", "1");
  915. } else {
  916. xmlNsPtr xsi = encode_add_ns(property,XSI_NAMESPACE);
  917. xmlSetNsProp(property, xsi, "nil", "1");
  918. }
  919. } else {
  920. property = master_to_xml(enc, *data, style, node);
  921. if (property->children && property->children->content &&
  922. model->u.element->fixed && strcmp(model->u.element->fixed,property->children->content) != 0) {
  923. php_error(E_ERROR,"SOAP-ERROR: Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)",model->u.element->name,model->u.element->fixed,property->children->content);
  924. }
  925. }
  926. xmlNodeSetName(property, model->u.element->name);
  927. if (style == SOAP_LITERAL && model->u.element->namens) {
  928. xmlNsPtr nsp = encode_add_ns(property, model->u.element->namens);
  929. xmlSetNs(property, nsp);
  930. }
  931. }
  932. return 1;
  933. } else if (model->min_occurs == 0) {
  934. return 2;
  935. } else {
  936. if (strict) {
  937. php_error(E_ERROR, "SOAP-ERROR: Encoding: object hasn't '%s' property",model->u.element->name);
  938. }
  939. return 0;
  940. }
  941. break;
  942. }
  943. case XSD_CONTENT_SEQUENCE:
  944. case XSD_CONTENT_ALL: {
  945. sdlContentModelPtr *tmp;
  946. zend_hash_internal_pointer_reset(model->u.content);
  947. while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
  948. if (!model_to_xml_object(node, *tmp, prop, style, model->min_occurs > 0)) {
  949. return 0;
  950. }
  951. zend_hash_move_forward(model->u.content);
  952. }
  953. return 1;
  954. }
  955. case XSD_CONTENT_CHOICE: {
  956. sdlContentModelPtr *tmp;
  957. int ret = 0;
  958. zend_hash_internal_pointer_reset(model->u.content);
  959. while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
  960. int tmp_ret = model_to_xml_object(node, *tmp, prop, style, 0);
  961. if (tmp_ret == 1) {
  962. return 1;
  963. } else if (tmp_ret != 0) {
  964. ret = 1;
  965. }
  966. zend_hash_move_forward(model->u.content);
  967. }
  968. return ret;
  969. }
  970. case XSD_CONTENT_GROUP: {
  971. return model_to_xml_object(node, model->u.group->model, prop, style, model->min_occurs > 0);
  972. }
  973. default:
  974. break;
  975. }
  976. return 1;
  977. }
  978. static sdlTypePtr model_array_element(sdlContentModelPtr model)
  979. {
  980. switch (model->kind) {
  981. case XSD_CONTENT_ELEMENT: {
  982. if (model->max_occurs == -1 || model->max_occurs > 1) {
  983. return model->u.element;
  984. } else {
  985. return NULL;
  986. }
  987. }
  988. case XSD_CONTENT_SEQUENCE:
  989. case XSD_CONTENT_ALL:
  990. case XSD_CONTENT_CHOICE: {
  991. sdlContentModelPtr *tmp;
  992. if (zend_hash_num_elements(model->u.content) != 1) {
  993. return NULL;
  994. }
  995. zend_hash_internal_pointer_reset(model->u.content);
  996. zend_hash_get_current_data(model->u.content, (void**)&tmp);
  997. return model_array_element(*tmp);
  998. }
  999. case XSD_CONTENT_GROUP: {
  1000. return model_array_element(model->u.group->model);
  1001. }
  1002. default:
  1003. break;
  1004. }
  1005. return NULL;
  1006. }
  1007. static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  1008. {
  1009. xmlNodePtr xmlParam;
  1010. HashTable *prop;
  1011. int i;
  1012. sdlTypePtr sdlType = type->sdl_type;
  1013. TSRMLS_FETCH();
  1014. if (!data || Z_TYPE_P(data) == IS_NULL) {
  1015. xmlParam = xmlNewNode(NULL,"BOGUS");
  1016. xmlAddChild(parent, xmlParam);
  1017. if (style == SOAP_ENCODED) {
  1018. xmlSetProp(xmlParam, "xsi:nil", "1");
  1019. }
  1020. return xmlParam;
  1021. }
  1022. if (sdlType) {
  1023. prop = NULL;
  1024. if (Z_TYPE_P(data) == IS_OBJECT) {
  1025. prop = Z_OBJPROP_P(data);
  1026. } else if (Z_TYPE_P(data) == IS_ARRAY) {
  1027. prop = Z_ARRVAL_P(data);
  1028. }
  1029. if (sdlType->kind == XSD_TYPEKIND_RESTRICTION &&
  1030. sdlType->encode && type != &sdlType->encode->details) {
  1031. encodePtr enc;
  1032. enc = sdlType->encode;
  1033. while (enc && enc->details.sdl_type &&
  1034. enc->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
  1035. enc->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
  1036. enc->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
  1037. enc = enc->details.sdl_type->encode;
  1038. }
  1039. if (enc) {
  1040. zval **tmp;
  1041. if (prop && zend_hash_find(prop, "_", sizeof("_"), (void**)&tmp) == SUCCESS) {
  1042. xmlParam = master_to_xml(enc, *tmp, style, parent);
  1043. } else if (prop == NULL) {
  1044. xmlParam = master_to_xml(enc, data, style, parent);
  1045. } else {
  1046. xmlParam = xmlNewNode(NULL,"BOGUS");
  1047. xmlAddChild(parent, xmlParam);
  1048. }
  1049. } else {
  1050. xmlParam = xmlNewNode(NULL,"BOGUS");
  1051. xmlAddChild(parent, xmlParam);
  1052. }
  1053. } else if (sdlType->kind == XSD_TYPEKIND_EXTENSION &&
  1054. sdlType->encode && type != &sdlType->encode->details) {
  1055. if (sdlType->encode->details.sdl_type &&
  1056. sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
  1057. sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
  1058. sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
  1059. xmlParam = master_to_xml(sdlType->encode, data, style, parent);
  1060. } else {
  1061. zval **tmp;
  1062. if (prop && zend_hash_find(prop, "_", sizeof("_"), (void**)&tmp) == SUCCESS) {
  1063. xmlParam = master_to_xml(sdlType->encode, *tmp, style, parent);
  1064. } else if (prop == NULL) {
  1065. xmlParam = master_to_xml(sdlType->encode, data, style, parent);
  1066. } else {
  1067. xmlParam = xmlNewNode(NULL,"BOGUS");
  1068. xmlAddChild(parent, xmlParam);
  1069. }
  1070. }
  1071. } else {
  1072. xmlParam = xmlNewNode(NULL,"BOGUS");
  1073. xmlAddChild(parent, xmlParam);
  1074. }
  1075. FIND_ZVAL_NULL(data, xmlParam, style);
  1076. if (prop != NULL) {
  1077. sdlTypePtr array_el;
  1078. if (Z_TYPE_P(data) == IS_ARRAY &&
  1079. !is_map(data) &&
  1080. sdlType->attributes == NULL &&
  1081. sdlType->model != NULL &&
  1082. (array_el = model_array_element(sdlType->model)) != NULL) {
  1083. zval **val;
  1084. zend_hash_internal_pointer_reset(prop);
  1085. while (zend_hash_get_current_data(prop,(void**)&val) == SUCCESS) {
  1086. xmlNodePtr property;
  1087. if (Z_TYPE_PP(val) == IS_NULL && array_el->nillable) {
  1088. property = xmlNewNode(NULL,"BOGUS");
  1089. xmlAddChild(xmlParam, property);
  1090. if (style == SOAP_ENCODED) {
  1091. xmlSetProp(property, "xsi:nil", "1");
  1092. } else {
  1093. xmlNsPtr xsi = encode_add_ns(property,XSI_NAMESPACE);
  1094. xmlSetNsProp(property, xsi, "nil", "1");
  1095. }
  1096. } else {
  1097. property = master_to_xml(array_el->encode, *val, style, xmlParam);
  1098. }
  1099. xmlNodeSetName(property, array_el->name);
  1100. if (style == SOAP_LITERAL && array_el->namens) {
  1101. xmlNsPtr nsp = encode_add_ns(property, array_el->namens);
  1102. xmlSetNs(property, nsp);
  1103. }
  1104. zend_hash_move_forward(prop);
  1105. }
  1106. } else if (sdlType->model) {
  1107. model_to_xml_object(xmlParam, sdlType->model, prop, style, 1);
  1108. }
  1109. if (sdlType->attributes) {
  1110. sdlAttributePtr *attr;
  1111. zval **data;
  1112. zend_hash_internal_pointer_reset(sdlType->attributes);
  1113. while (zend_hash_get_current_data(sdlType->attributes, (void**)&attr) == SUCCESS) {
  1114. if ((*attr)->name) {
  1115. if (zend_hash_find(prop, (*attr)->name, strlen((*attr)->name)+1, (void**)&data) == SUCCESS) {
  1116. xmlNodePtr dummy;
  1117. dummy = master_to_xml((*attr)->encode, *data, SOAP_LITERAL, xmlParam);
  1118. if (dummy->children && dummy->children->content) {
  1119. if ((*attr)->fixed && strcmp((*attr)->fixed,dummy->children->content) != 0) {
  1120. php_error(E_ERROR,"SOAP-ERROR: Encoding: Attribute '%s' has fixed value '%s' (value '%s' is not allowed)",(*attr)->name,(*attr)->fixed,dummy->children->content);
  1121. }
  1122. xmlSetProp(xmlParam, (*attr)->name, dummy->children->content);
  1123. }
  1124. xmlUnlinkNode(dummy);
  1125. xmlFreeNode(dummy);
  1126. }
  1127. }
  1128. zend_hash_move_forward(sdlType->attributes);
  1129. }
  1130. }
  1131. }
  1132. if (style == SOAP_ENCODED) {
  1133. set_ns_and_type(xmlParam, type);
  1134. }
  1135. } else {
  1136. xmlParam = xmlNewNode(NULL,"BOGUS");
  1137. xmlAddChild(parent, xmlParam);
  1138. FIND_ZVAL_NULL(data, xmlParam, style);
  1139. prop = NULL;
  1140. if (Z_TYPE_P(data) == IS_OBJECT) {
  1141. prop = Z_OBJPROP_P(data);
  1142. } else if (Z_TYPE_P(data) == IS_ARRAY) {
  1143. prop = Z_ARRVAL_P(data);
  1144. }
  1145. if (prop != NULL) {
  1146. i = zend_hash_num_elements(prop);
  1147. zend_hash_internal_pointer_reset(prop);
  1148. for (;i > 0;i--) {
  1149. xmlNodePtr property;
  1150. zval **zprop;
  1151. char *str_key;
  1152. ulong index;
  1153. int key_type;
  1154. key_type = zend_hash_get_current_key(prop, &str_key, &index, FALSE);
  1155. zend_hash_get_current_data(prop, (void **)&zprop);
  1156. property = master_to_xml(get_conversion((*zprop)->type), (*zprop), style, xmlParam);
  1157. if (key_type == HASH_KEY_IS_STRING) {
  1158. xmlNodeSetName(property, str_key);
  1159. }
  1160. zend_hash_move_forward(prop);
  1161. }
  1162. }
  1163. if (style == SOAP_ENCODED) {
  1164. set_ns_and_type(xmlParam, type);
  1165. }
  1166. }
  1167. return xmlParam;
  1168. }
  1169. /* Array encode/decode */
  1170. static xmlNodePtr guess_array_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  1171. {
  1172. encodePtr enc = NULL;
  1173. TSRMLS_FETCH();
  1174. if (data && Z_TYPE_P(data) == IS_ARRAY) {
  1175. if (is_map(data)) {
  1176. enc = get_conversion(APACHE_MAP);
  1177. } else {
  1178. enc = get_conversion(SOAP_ENC_ARRAY);
  1179. }
  1180. }
  1181. if (!enc) {
  1182. enc = get_conversion(IS_NULL);
  1183. }
  1184. return master_to_xml(enc, data, style, parent);
  1185. }
  1186. static int calc_dimension_12(const char* str)
  1187. {
  1188. int i = 0, flag = 0;
  1189. while (*str != '\0' && (*str < '0' || *str > '9') && (*str != '*')) {
  1190. str++;
  1191. }
  1192. if (*str == '*') {
  1193. i++;
  1194. str++;
  1195. }
  1196. while (*str != '\0') {
  1197. if (*str >= '0' && *str <= '9') {
  1198. if (flag == 0) {
  1199. i++;
  1200. flag = 1;
  1201. }
  1202. } else if (*str == '*') {
  1203. php_error(E_ERROR,"SOAP-ERROR: Encoding: '*' may only be first arraySize value in list");
  1204. } else {
  1205. flag = 0;
  1206. }
  1207. str++;
  1208. }
  1209. return i;
  1210. }
  1211. static int* get_position_12(int dimension, const char* str)
  1212. {
  1213. int *pos;
  1214. int i = -1, flag = 0;
  1215. pos = safe_emalloc(sizeof(int), dimension, 0);
  1216. memset(pos,0,sizeof(int)*dimension);
  1217. while (*str != '\0' && (*str < '0' || *str > '9') && (*str != '*')) {
  1218. str++;
  1219. }
  1220. if (*str == '*') {
  1221. str++;
  1222. i++;
  1223. }
  1224. while (*str != '\0') {
  1225. if (*str >= '0' && *str <= '9') {
  1226. if (flag == 0) {
  1227. i++;
  1228. flag = 1;
  1229. }
  1230. pos[i] = (pos[i]*10)+(*str-'0');
  1231. } else if (*str == '*') {
  1232. php_error(E_ERROR,"SOAP-ERROR: Encoding: '*' may only be first arraySize value in list");
  1233. } else {
  1234. flag = 0;
  1235. }
  1236. str++;
  1237. }
  1238. return pos;
  1239. }
  1240. static int calc_dimension(const char* str)
  1241. {
  1242. int i = 1;
  1243. while (*str != ']' && *str != '\0') {
  1244. if (*str == ',') {
  1245. i++;
  1246. }
  1247. str++;
  1248. }
  1249. return i;
  1250. }
  1251. static void get_position_ex(int dimension, const char* str, int** pos)
  1252. {
  1253. int i = 0;
  1254. memset(*pos,0,sizeof(int)*dimension);
  1255. while (*str != ']' && *str != '\0' && i < dimension) {
  1256. if (*str >= '0' && *str <= '9') {
  1257. (*pos)[i] = ((*pos)[i]*10)+(*str-'0');
  1258. } else if (*str == ',') {
  1259. i++;
  1260. }
  1261. str++;
  1262. }
  1263. }
  1264. static int* get_position(int dimension, const char* str)
  1265. {
  1266. int *pos;
  1267. pos = safe_emalloc(sizeof(int), dimension, 0);
  1268. get_position_ex(dimension, str, &pos);
  1269. return pos;
  1270. }
  1271. static void add_xml_array_elements(xmlNodePtr xmlParam,
  1272. sdlTypePtr type,
  1273. encodePtr enc,
  1274. xmlNsPtr ns,
  1275. int dimension ,
  1276. int* dims,
  1277. zval* data,
  1278. int style)
  1279. {
  1280. int j;
  1281. if (data && Z_TYPE_P(data) == IS_ARRAY) {
  1282. zend_hash_internal_pointer_reset(data->value.ht);
  1283. for (j=0; j<dims[0]; j++) {
  1284. zval **zdata;
  1285. if (zend_hash_get_current_data(data->value.ht, (void **)&zdata) != SUCCESS) {
  1286. zdata = NULL;
  1287. }
  1288. if (dimension == 1) {
  1289. xmlNodePtr xparam;
  1290. if (zdata) {
  1291. if (enc == NULL) {
  1292. TSRMLS_FETCH();
  1293. xparam = master_to_xml(get_conversion((*zdata)->type), (*zdata), style, xmlParam);
  1294. } else {
  1295. xparam = master_to_xml(enc, (*zdata), style, xmlParam);
  1296. }
  1297. } else {
  1298. xparam = xmlNewNode(NULL,"BOGUS");
  1299. xmlAddChild(xmlParam, xparam);
  1300. }
  1301. if (type) {
  1302. xmlNodeSetName(xparam, type->name);
  1303. } else if (style == SOAP_LITERAL && enc && enc->details.type_str) {
  1304. xmlNodeSetName(xparam, enc->details.type_str);
  1305. xmlSetNs(xparam, ns);
  1306. } else {
  1307. xmlNodeSetName(xparam, "item");
  1308. }
  1309. } else {
  1310. if (zdata) {
  1311. add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, *zdata, style);
  1312. } else {
  1313. add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, NULL, style);
  1314. }
  1315. }
  1316. zend_hash_move_forward(data->value.ht);
  1317. }
  1318. } else {
  1319. for (j=0; j<dims[0]; j++) {
  1320. if (dimension == 1) {
  1321. xmlNodePtr xparam;
  1322. xparam = xmlNewNode(NULL,"BOGUS");
  1323. xmlAddChild(xmlParam, xparam);
  1324. if (type) {
  1325. xmlNodeSetName(xparam, type->name);
  1326. } else if (style == SOAP_LITERAL && enc && enc->details.type_str) {
  1327. xmlNodeSetName(xparam, enc->details.type_str);
  1328. xmlSetNs(xparam, ns);
  1329. } else {
  1330. xmlNodeSetName(xparam, "item");
  1331. }
  1332. } else {
  1333. add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, NULL, style);
  1334. }
  1335. }
  1336. }
  1337. }
  1338. static inline int array_num_elements(HashTable* ht)
  1339. {
  1340. if (ht->pListTail && ht->pListTail->nKeyLength == 0) {
  1341. return ht->pListTail->h-1;
  1342. }
  1343. return 0;
  1344. }
  1345. static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  1346. {
  1347. sdlTypePtr sdl_type = type->sdl_type;
  1348. sdlTypePtr element_type = NULL;
  1349. smart_str array_type = {0}, array_size = {0};
  1350. int i;
  1351. xmlNodePtr xmlParam;
  1352. encodePtr enc = NULL;
  1353. int dimension = 1;
  1354. int* dims;
  1355. int soap_version;
  1356. TSRMLS_FETCH();
  1357. soap_version = SOAP_GLOBAL(soap_version);
  1358. xmlParam = xmlNewNode(NULL,"BOGUS");
  1359. xmlAddChild(parent, xmlParam);
  1360. FIND_ZVAL_NULL(data, xmlParam, style);
  1361. if (Z_TYPE_P(data) == IS_ARRAY) {
  1362. sdlAttributePtr *arrayType;
  1363. sdlExtraAttributePtr *ext;
  1364. sdlTypePtr elementType;
  1365. i = zend_hash_num_elements(Z_ARRVAL_P(data));
  1366. if (sdl_type &&
  1367. sdl_type->attributes &&
  1368. zend_hash_find(sdl_type->attributes, SOAP_1_1_ENC_NAMESPACE":arrayType",
  1369. sizeof(SOAP_1_1_ENC_NAMESPACE":arrayType"),
  1370. (void **)&arrayType) == SUCCESS &&
  1371. zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arrayType", sizeof(WSDL_NAMESPACE":arrayType"), (void **)&ext) == SUCCESS) {
  1372. char *value, *end;
  1373. zval** el;
  1374. value = estrdup((*ext)->val);
  1375. end = strrchr(value,'[');
  1376. if (end) {
  1377. *end = '\0';
  1378. end++;
  1379. dimension = calc_dimension(end);
  1380. }
  1381. if ((*ext)->ns != NULL) {
  1382. enc = get_encoder(SOAP_GLOBAL(sdl), (*ext)->ns, value);
  1383. get_type_str(xmlParam, (*ext)->ns, value, &array_type);
  1384. } else {
  1385. smart_str_appends(&array_type, value);
  1386. }
  1387. dims = safe_emalloc(sizeof(int), dimension, 0);
  1388. dims[0] = i;
  1389. el = &data;
  1390. for (i = 1; i < dimension; i++) {
  1391. if (el != NULL && Z_TYPE_PP(el) == IS_ARRAY &&
  1392. zend_hash_num_elements(Z_ARRVAL_PP(el)) > 0) {
  1393. zend_hash_internal_pointer_reset(Z_ARRVAL_PP(el));
  1394. zend_hash_get_current_data(Z_ARRVAL_PP(el), (void**)&el);
  1395. if (Z_TYPE_PP(el) == IS_ARRAY) {
  1396. dims[i] = zend_hash_num_elements(Z_ARRVAL_PP(el));
  1397. } else {
  1398. dims[i] = 0;
  1399. }
  1400. }
  1401. }
  1402. smart_str_append_long(&array_size, dims[0]);
  1403. for (i=1; i<dimension; i++) {
  1404. smart_str_appendc(&array_size, ',');
  1405. smart_str_append_long(&array_size, dims[i]);
  1406. }
  1407. efree(value);
  1408. } else if (sdl_type &&
  1409. sdl_type->attributes &&
  1410. zend_hash_find(sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":itemType",
  1411. sizeof(SOAP_1_2_ENC_NAMESPACE":itemType"),
  1412. (void **)&arrayType) == SUCCESS &&
  1413. zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":itemType", sizeof(WSDL_NAMESPACE":itemType"), (void **)&ext) == SUCCESS) {
  1414. if ((*ext)->ns != NULL) {
  1415. enc = get_encoder(SOAP_GLOBAL(sdl), (*ext)->ns, (*ext)->val);
  1416. get_type_str(xmlParam, (*ext)->ns, (*ext)->val, &array_type);
  1417. } else {
  1418. smart_str_appends(&array_type, (*ext)->val);
  1419. }
  1420. if (zend_hash_find(sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
  1421. sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize"),
  1422. (void **)&arrayType) == SUCCESS &&
  1423. zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arraySize", sizeof(WSDL_NAMESPACE":arraysize"), (void **)&ext) == SUCCESS) {
  1424. dimension = calc_dimension_12((*ext)->val);
  1425. dims = get_position_12(dimension, (*ext)->val);
  1426. if (dims[0] == 0) {dims[0] = i;}
  1427. smart_str_append_long(&array_size, dims[0]);
  1428. for (i=1; i<dimension; i++) {
  1429. smart_str_appendc(&array_size, ',');
  1430. smart_str_append_long(&array_size, dims[i]);
  1431. }
  1432. } else {
  1433. dims = emalloc(sizeof(int));
  1434. *dims = 0;
  1435. smart_str_append_long(&array_size, i);
  1436. }
  1437. } else if (sdl_type &&
  1438. sdl_type->attributes &&
  1439. zend_hash_find(sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
  1440. sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize"),
  1441. (void **)&arrayType) == SUCCESS &&
  1442. zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arraySize", sizeof(WSDL_NAMESPACE":arraySize"), (void **)&ext) == SUCCESS) {
  1443. dimension = calc_dimension_12((*ext)->val);
  1444. dims = get_position_12(dimension, (*ext)->val);
  1445. if (dims[0] == 0) {dims[0] = i;}
  1446. smart_str_append_long(&array_size, dims[0]);
  1447. for (i=1; i<dimension; i++) {
  1448. smart_str_appendc(&array_size, ',');
  1449. smart_str_append_long(&array_size, dims[i]);
  1450. }
  1451. if (sdl_type && sdl_type->elements &&
  1452. zend_hash_num_elements(sdl_type->elements) == 1 &&
  1453. (zend_hash_internal_pointer_reset(sdl_type->elements),
  1454. zend_hash_get_current_data(sdl_type->elements, (void**)&elementType) == SUCCESS) &&
  1455. (elementType = *(sdlTypePtr*)elementType) != NULL &&
  1456. elementType->encode && elementType->encode->details.type_str) {
  1457. element_type = elementType;
  1458. enc = elementType->encode;
  1459. get_type_str(xmlParam, elementType->encode->details.ns, elementType->encode->details.type_str, &array_type);
  1460. } else {
  1461. get_array_type(xmlParam, data, &array_type TSRMLS_CC);
  1462. enc = get_encoder_ex(SOAP_GLOBAL(sdl), array_type.c, array_type.len);
  1463. }
  1464. } else if (sdl_type && sdl_type->elements &&
  1465. zend_hash_num_elements(sdl_type->elements) == 1 &&
  1466. (zend_hash_internal_pointer_reset(sdl_type->elements),
  1467. zend_hash_get_current_data(sdl_type->elements, (void**)&elementType) == SUCCESS) &&
  1468. (elementType = *(sdlTypePtr*)elementType) != NULL &&
  1469. elementType->encode && elementType->encode->details.type_str) {
  1470. element_type = elementType;
  1471. enc = elementType->encode;
  1472. get_type_str(xmlParam, elementType->encode->details.ns, elementType->encode->details.type_str, &array_type);
  1473. smart_str_append_long(&array_size, i);
  1474. dims = safe_emalloc(sizeof(int), dimension, 0);
  1475. dims[0] = i;
  1476. } else {
  1477. get_array_type(xmlParam, data, &array_type TSRMLS_CC);
  1478. enc = get_encoder_ex(SOAP_GLOBAL(sdl), array_type.c, array_type.len);
  1479. smart_str_append_long(&array_size, i);
  1480. dims = safe_emalloc(sizeof(int), dimension, 0);
  1481. dims[0] = i;
  1482. }
  1483. if (style == SOAP_ENCODED) {
  1484. if (soap_version == SOAP_1_1) {
  1485. smart_str_0(&array_type);
  1486. if (strcmp(array_type.c,"xsd:anyType") == 0) {
  1487. smart_str_free(&array_type);
  1488. smart_str_appendl(&array_type,"xsd:ur-type",sizeof("xsd:ur-type")-1);
  1489. }
  1490. smart_str_appendc(&array_type, '[');
  1491. smart_str_append(&array_type, &array_size);
  1492. smart_str_appendc(&array_type, ']');
  1493. smart_str_0(&array_type);
  1494. xmlSetProp(xmlParam, SOAP_1_1_ENC_NS_PREFIX":arrayType", array_type.c);
  1495. } else {
  1496. int i = 0;
  1497. while (i < array_size.len) {
  1498. if (array_size.c[i] == ',') {array_size.c[i] = ' ';}
  1499. ++i;
  1500. }
  1501. smart_str_0(&array_type);
  1502. smart_str_0(&array_size);
  1503. xmlSetProp(xmlParam, SOAP_1_2_ENC_NS_PREFIX":itemType", array_type.c);
  1504. xmlSetProp(xmlParam, SOAP_1_2_ENC_NS_PREFIX":arraySize", array_size.c);
  1505. }
  1506. }
  1507. smart_str_free(&array_type);
  1508. smart_str_free(&array_size);
  1509. add_xml_array_elements(xmlParam, element_type, enc, enc?encode_add_ns(xmlParam,enc->details.ns):NULL, dimension, dims, data, style);
  1510. efree(dims);
  1511. }
  1512. if (style == SOAP_ENCODED) {
  1513. set_ns_and_type(xmlParam, type);
  1514. }
  1515. return xmlParam;
  1516. }
  1517. static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data)
  1518. {
  1519. zval *ret;
  1520. xmlNodePtr trav;
  1521. encodePtr enc = NULL;
  1522. int dimension = 1;
  1523. int* dims = NULL;
  1524. int* pos = NULL;
  1525. xmlAttrPtr attr;
  1526. sdlPtr sdl;
  1527. sdlAttributePtr *arrayType;
  1528. sdlExtraAttributePtr *ext;
  1529. sdlTypePtr elementType;
  1530. TSRMLS_FETCH();
  1531. MAKE_STD_ZVAL(ret);
  1532. FIND_XML_NULL(data, ret);
  1533. sdl = SOAP_GLOBAL(sdl);
  1534. if (data &&
  1535. (attr = get_attribute(data->properties,"arrayType")) &&
  1536. attr->children && attr->children->content) {
  1537. char *type, *end, *ns;
  1538. xmlNsPtr nsptr;
  1539. parse_namespace(attr->children->content, &type, &ns);
  1540. nsptr = xmlSearchNs(attr->doc, attr->parent, ns);
  1541. end = strrchr(type,'[');
  1542. if (end) {
  1543. *end = '\0';
  1544. dimension = calc_dimension(end+1);
  1545. dims = get_position(dimension, end+1);
  1546. }
  1547. if (nsptr != NULL) {
  1548. enc = get_encoder(SOAP_GLOBAL(sdl), nsptr->href, type);
  1549. }
  1550. efree(type);
  1551. if (ns) {efree(ns);}
  1552. } else if ((attr = get_attribute(data->properties,"itemType")) &&
  1553. attr->children &&
  1554. attr->children->content) {
  1555. char *type, *ns;
  1556. xmlNsPtr nsptr;
  1557. parse_namespace(attr->children->content, &type, &ns);
  1558. nsptr = xmlSearchNs(attr->doc, attr->parent, ns);
  1559. if (nsptr != NULL) {
  1560. enc = get_encoder(SOAP_GLOBAL(sdl), nsptr->href, type);
  1561. }
  1562. efree(type);
  1563. if (ns) {efree(ns);}
  1564. if ((attr = get_attribute(data->properties,"arraySize")) &&
  1565. attr->children && attr->children->content) {
  1566. dimension = calc_dimension_12(attr->children->content);
  1567. dims = get_position_12(dimension, attr->children->content);
  1568. } else {
  1569. dims = emalloc(sizeof(int));
  1570. *dims = 0;
  1571. }
  1572. } else if ((attr = get_attribute(data->properties,"arraySize")) &&
  1573. attr->children && attr->children->content) {
  1574. dimension = calc_dimension_12(attr->children->content);
  1575. dims = get_position_12(dimension, attr->children->content);
  1576. } else if (type->sdl_type != NULL &&
  1577. type->sdl_type->attributes != NULL &&
  1578. zend_hash_find(type->sdl_type->attributes, SOAP_1_1_ENC_NAMESPACE":arrayType",
  1579. sizeof(SOAP_1_1_ENC_NAMESPACE":arrayType"),
  1580. (void **)&arrayType) == SUCCESS &&
  1581. zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arrayType", sizeof(WSDL_NAMESPACE":arrayType"), (void **)&ext) == SUCCESS) {
  1582. char *type, *end;
  1583. type = estrdup((*ext)->val);
  1584. end = strrchr(type,'[');
  1585. if (end) {
  1586. *end = '\0';
  1587. }
  1588. if ((*ext)->ns != NULL) {
  1589. enc = get_encoder(SOAP_GLOBAL(sdl), (*ext)->ns, type);
  1590. }
  1591. efree(type);
  1592. dims = emalloc(sizeof(int));
  1593. *dims = 0;
  1594. } else if (type->sdl_type != NULL &&
  1595. type->sdl_type->attributes != NULL &&
  1596. zend_hash_find(type->sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":itemType",
  1597. sizeof(SOAP_1_2_ENC_NAMESPACE":itemType"),
  1598. (void **)&arrayType) == SUCCESS &&
  1599. zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":itemType", sizeof(WSDL_NAMESPACE":itemType"), (void **)&ext) == SUCCESS) {
  1600. if ((*ext)->ns != NULL) {
  1601. enc = get_encoder(SOAP_GLOBAL(sdl), (*ext)->ns, (*ext)->val);
  1602. }
  1603. if (zend_hash_find(type->sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
  1604. sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize"),
  1605. (void **)&arrayType) == SUCCESS &&
  1606. zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arraySize", sizeof(WSDL_NAMESPACE":arraysize"), (void **)&ext) == SUCCESS) {
  1607. dimension = calc_dimension_12((*ext)->val);
  1608. dims = get_position_12(dimension, (*ext)->val);
  1609. } else {
  1610. dims = emalloc(sizeof(int));
  1611. *dims = 0;
  1612. }
  1613. } else if (type->sdl_type != NULL &&
  1614. type->sdl_type->attributes != NULL &&
  1615. zend_hash_find(type->sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
  1616. sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize"),
  1617. (void **)&arrayType) == SUCCESS &&
  1618. zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arraySize", sizeof(WSDL_NAMESPACE":arraysize"), (void **)&ext) == SUCCESS) {
  1619. dimension = calc_dimension_12((*ext)->val);
  1620. dims = get_position_12(dimension, (*ext)->val);
  1621. if (type->sdl_type && type->sdl_type->elements &&
  1622. zend_hash_num_elements(type->sdl_type->elements) == 1 &&
  1623. (zend_hash_internal_pointer_reset(type->sdl_type->elements),
  1624. zend_hash_get_current_data(type->sdl_type->elements, (void**)&elementType) == SUCCESS) &&
  1625. (elementType = *(sdlTypePtr*)elementType) != NULL &&
  1626. elementType->encode) {
  1627. enc = elementType->encode;
  1628. }
  1629. } else if (type->sdl_type && type->sdl_type->elements &&
  1630. zend_hash_num_elements(type->sdl_type->elements) == 1 &&
  1631. (zend_hash_internal_pointer_reset(type->sdl_type->elements),
  1632. zend_hash_get_current_data(type->sdl_type->elements, (void**)&elementType) == SUCCESS) &&
  1633. (elementType = *(sdlTypePtr*)elementType) != NULL &&
  1634. elementType->encode) {
  1635. enc = elementType->encode;
  1636. }
  1637. if (dims == NULL) {
  1638. dimension = 1;
  1639. dims = emalloc(sizeof(int));
  1640. *dims = 0;
  1641. }
  1642. pos = safe_emalloc(sizeof(int), dimension, 0);
  1643. memset(pos,0,sizeof(int)*dimension);
  1644. if (data &&
  1645. (attr = get_attribute(data->properties,"offset")) &&
  1646. attr->children && attr->children->content) {
  1647. char* tmp = strrchr(attr->children->content,'[');
  1648. if (tmp == NULL) {
  1649. tmp = attr->children->content;
  1650. }
  1651. get_position_ex(dimension, tmp, &pos);
  1652. }
  1653. array_init(ret);
  1654. trav = data->children;
  1655. while (trav) {
  1656. if (trav->type == XML_ELEMENT_NODE) {
  1657. int i;
  1658. zval *tmpVal, *ar;
  1659. xmlAttrPtr position = get_attribute(trav->properties,"position");
  1660. tmpVal = master_to_zval(enc, trav);
  1661. if (position != NULL && position->children && position->children->content) {
  1662. char* tmp = strrchr(position->children->content,'[');
  1663. if (tmp == NULL) {
  1664. tmp = position->children->content;
  1665. }
  1666. get_position_ex(dimension, tmp, &pos);
  1667. }
  1668. /* Get/Create intermediate arrays for multidimensional arrays */
  1669. i = 0;
  1670. ar = ret;
  1671. while (i < dimension-1) {
  1672. zval** ar2;
  1673. if (zend_hash_index_find(Z_ARRVAL_P(ar), pos[i], (void**)&ar2) == SUCCESS) {
  1674. ar = *ar2;
  1675. } else {
  1676. zval *tmpAr;
  1677. MAKE_STD_ZVAL(tmpAr);
  1678. array_init(tmpAr);
  1679. zend_hash_index_update(Z_ARRVAL_P(ar), pos[i], &tmpAr, sizeof(zval*), (void**)&ar2);
  1680. ar = *ar2;
  1681. }
  1682. i++;
  1683. }
  1684. zend_hash_index_update(Z_ARRVAL_P(ar), pos[i], &tmpVal, sizeof(zval *), NULL);
  1685. /* Increment position */
  1686. i = dimension;
  1687. while (i > 0) {
  1688. i--;
  1689. pos[i]++;
  1690. if (pos[i] >= dims[i]) {
  1691. if (i > 0) {
  1692. pos[i] = 0;
  1693. } else {
  1694. /* TODO: Array index overflow */
  1695. }
  1696. } else {
  1697. break;
  1698. }
  1699. }
  1700. }
  1701. trav = trav->next;
  1702. }
  1703. efree(dims);
  1704. efree(pos);
  1705. return ret;
  1706. }
  1707. /* Map encode/decode */
  1708. static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  1709. {
  1710. xmlNodePtr xmlParam;
  1711. int i;
  1712. TSRMLS_FETCH();
  1713. xmlParam = xmlNewNode(NULL,"BOGUS");
  1714. xmlAddChild(parent, xmlParam);
  1715. FIND_ZVAL_NULL(data, xmlParam, style);
  1716. if (Z_TYPE_P(data) == IS_ARRAY) {
  1717. i = zend_hash_num_elements(Z_ARRVAL_P(data));
  1718. zend_hash_internal_pointer_reset(data->value.ht);
  1719. for (;i > 0;i--) {
  1720. xmlNodePtr xparam, item;
  1721. xmlNodePtr key;
  1722. zval **temp_data;
  1723. char *key_val;
  1724. int int_val;
  1725. zend_hash_get_current_data(data->value.ht, (void **)&temp_data);
  1726. if (Z_TYPE_PP(temp_data) != IS_NULL) {
  1727. item = xmlNewNode(NULL,"item");
  1728. xmlAddChild(xmlParam, item);
  1729. key = xmlNewNode(NULL,"key");
  1730. xmlAddChild(item,key);
  1731. if (zend_hash_get_current_key(data->value.ht, &key_val, (long *)&int_val, FALSE) == HASH_KEY_IS_STRING) {
  1732. if (style == SOAP_ENCODED) {
  1733. xmlSetProp(key, "xsi:type", "xsd:string");
  1734. }
  1735. xmlNodeSetContent(key, key_val);
  1736. } else {
  1737. smart_str tmp = {0};
  1738. smart_str_append_long(&tmp, int_val);
  1739. smart_str_0(&tmp);
  1740. if (style == SOAP_ENCODED) {
  1741. xmlSetProp(key, "xsi:type", "xsd:int");
  1742. }
  1743. xmlNodeSetContentLen(key, tmp.c, tmp.len);
  1744. smart_str_free(&tmp);
  1745. }
  1746. xparam = master_to_xml(get_conversion((*temp_data)->type), (*temp_data), style, item);
  1747. xmlNodeSetName(xparam, "value");
  1748. }
  1749. zend_hash_move_forward(data->value.ht);
  1750. }
  1751. }
  1752. if (style == SOAP_ENCODED) {
  1753. set_ns_and_type(xmlParam, type);
  1754. }
  1755. return xmlParam;
  1756. }
  1757. static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data)
  1758. {
  1759. zval *ret, *key, *value;
  1760. xmlNodePtr trav, item, xmlKey, xmlValue;
  1761. TSRMLS_FETCH();
  1762. MAKE_STD_ZVAL(ret);
  1763. FIND_XML_NULL(data, ret);
  1764. if (data && data->children) {
  1765. array_init(ret);
  1766. trav = data->children;
  1767. trav = data->children;
  1768. FOREACHNODE(trav, "item", item) {
  1769. xmlKey = get_node(item->children, "key");
  1770. if (!xmlKey) {
  1771. php_error(E_ERROR, "SOAP-ERROR: Encoding: Can't decode apache map, missing key");
  1772. }
  1773. xmlValue = get_node(item->children, "value");
  1774. if (!xmlKey) {
  1775. php_error(E_ERROR, "SOAP-ERROR: Encoding: Can't decode apache map, missing value");
  1776. }
  1777. key = master_to_zval(NULL, xmlKey);
  1778. value = master_to_zval(NULL, xmlValue);
  1779. if (Z_TYPE_P(key) == IS_STRING) {
  1780. zend_hash_update(Z_ARRVAL_P(ret), Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof(zval *), NULL);
  1781. } else if (Z_TYPE_P(key) == IS_LONG) {
  1782. zend_hash_index_update(Z_ARRVAL_P(ret), Z_LVAL_P(key), &value, sizeof(zval *), NULL);
  1783. } else {
  1784. php_error(E_ERROR, "SOAP-ERROR: Encoding: Can't decode apache map, only Strings or Longs are allowd as keys");
  1785. }
  1786. zval_ptr_dtor(&key);
  1787. }
  1788. ENDFOREACH(trav);
  1789. } else {
  1790. ZVAL_NULL(ret);
  1791. }
  1792. return ret;
  1793. }
  1794. /* Unknown encode/decode */
  1795. static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  1796. {
  1797. encodePtr enc;
  1798. xmlNodePtr ret;
  1799. TSRMLS_FETCH();
  1800. if (data) {
  1801. enc = get_conversion(data->type);
  1802. } else {
  1803. enc = get_conversion(IS_NULL);
  1804. }
  1805. ret = master_to_xml(enc, data, style, parent);
  1806. /*
  1807. if (style == SOAP_LITERAL && SOAP_GLOBAL(sdl)) {
  1808. encode_add_ns(node, XSI_NAMESPACE);
  1809. set_ns_and_type(ret, &enc->details);
  1810. }
  1811. */
  1812. return ret;
  1813. }
  1814. static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data)
  1815. {
  1816. encodePtr enc = NULL;
  1817. xmlAttrPtr tmpattr;
  1818. char *type_name = NULL;
  1819. zval *ret;
  1820. TSRMLS_FETCH();
  1821. data = check_and_resolve_href(data);
  1822. if (data == NULL) {
  1823. enc = get_conversion(IS_NULL);
  1824. } else if (data->properties && get_attribute_ex(data->properties, "nil", XSI_NAMESPACE)) {
  1825. enc = get_conversion(IS_NULL);
  1826. } else {
  1827. tmpattr = get_attribute_ex(data->properties,"type", XSI_NAMESPACE);
  1828. if (tmpattr != NULL) {
  1829. type_name = tmpattr->children->content;
  1830. enc = get_encoder_from_prefix(SOAP_GLOBAL(sdl), data, tmpattr->children->content);
  1831. if (enc != NULL) {
  1832. encodePtr tmp = enc;
  1833. while (tmp &&
  1834. tmp->details.sdl_type != NULL &&
  1835. tmp->details.sdl_type->kind != XSD_TYPEKIND_COMPLEX) {
  1836. if (tmp == enc) {
  1837. enc = NULL;
  1838. break;
  1839. }
  1840. tmp = tmp->details.sdl_type->encode;
  1841. }
  1842. }
  1843. }
  1844. if (enc == NULL) {
  1845. /* Didn't have a type, totally guess here */
  1846. /* Logic: has children = IS_OBJECT else IS_STRING */
  1847. xmlNodePtr trav;
  1848. if (get_attribute(data->properties, "arrayType") ||
  1849. get_attribute(data->properties, "itemType") ||
  1850. get_attribute(data->properties, "arraySize")) {
  1851. enc = get_conversion(SOAP_ENC_ARRAY);
  1852. } else {
  1853. enc = get_conversion(XSD_STRING);
  1854. trav = data->children;
  1855. while (trav != NULL) {
  1856. if (trav->type == XML_ELEMENT_NODE) {
  1857. enc = get_conversion(SOAP_ENC_OBJECT);
  1858. break;
  1859. }
  1860. trav = trav->next;
  1861. }
  1862. }
  1863. }
  1864. }
  1865. ret = master_to_zval(enc, data);
  1866. if (SOAP_GLOBAL(sdl) && type_name && enc->details.sdl_type) {
  1867. zval* soapvar;
  1868. char *ns, *cptype;
  1869. xmlNsPtr nsptr;
  1870. MAKE_STD_ZVAL(soapvar);
  1871. object_init_ex(soapvar, soap_var_class_entry);
  1872. add_property_long(soapvar, "enc_type", enc->details.type);
  1873. #ifdef ZEND_ENGINE_2
  1874. ret->refcount--;
  1875. #endif
  1876. add_property_zval(soapvar, "enc_value", ret);
  1877. parse_namespace(type_name, &cptype, &ns);
  1878. nsptr = xmlSearchNs(data->doc, data, ns);
  1879. add_property_string(soapvar, "enc_stype", cptype, 1);
  1880. if (nsptr) {
  1881. add_property_string(soapvar, "enc_ns", (char*)nsptr->href, 1);
  1882. }
  1883. efree(cptype);
  1884. if (ns) {efree(ns);}
  1885. ret = soapvar;
  1886. }
  1887. return ret;
  1888. }
  1889. /* Time encode/decode */
  1890. static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, int style, xmlNodePtr parent)
  1891. {
  1892. /* logic hacked from ext/standard/datetime.c */
  1893. struct tm *ta, tmbuf;
  1894. time_t timestamp;
  1895. int max_reallocs = 5;
  1896. size_t buf_len=64, real_len;
  1897. char *buf;
  1898. char tzbuf[6];
  1899. xmlNodePtr xmlParam;
  1900. xmlParam = xmlNewNode(NULL,"BOGUS");
  1901. xmlAddChild(parent, xmlParam);
  1902. FIND_ZVAL_NULL(data, xmlParam, style);
  1903. if (Z_TYPE_P(data) == IS_LONG) {
  1904. timestamp = Z_LVAL_P(data);
  1905. ta = php_localtime_r(&timestamp, &tmbuf);
  1906. /*ta = php_gmtime_r(&timestamp, &tmbuf);*/
  1907. buf = (char *) emalloc(buf_len);
  1908. while ((real_len = strftime(buf, buf_len, format, ta)) == buf_len || real_len == 0) {
  1909. buf_len *= 2;
  1910. buf = (char *) erealloc(buf, buf_len);
  1911. if (!--max_reallocs) break;
  1912. }
  1913. /* Time zone support */
  1914. #ifdef HAVE_TM_GMTOFF
  1915. sprintf(tzbuf, "%c%02d%02d", (ta->tm_gmtoff < 0) ? '-' : '+', abs(ta->tm_gmtoff / 3600), abs( (ta->tm_gmtoff % 3600) / 60 ));
  1916. #else
  1917. # ifdef ZEND_WIN32
  1918. sprintf(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));
  1919. # else
  1920. sprintf(tzbuf, "%c%02d%02d", ((ta->tm_isdst ? tzone - 3600:tzone)>0)?'-':'+', abs((ta->tm_isdst ? tzone - 3600 : tzone) / 3600), abs(((ta->tm_isdst ? tzone - 3600 : tzone) % 3600) / 60));
  1921. # endif
  1922. #endif
  1923. if (strcmp(tzbuf,"+0000") == 0) {
  1924. strcpy(tzbuf,"Z");
  1925. real_len++;
  1926. } else {
  1927. real_len += 5;
  1928. }
  1929. if (real_len >= buf_len) {
  1930. buf = (char *) erealloc(buf, real_len+1);
  1931. }
  1932. strcat(buf, tzbuf);
  1933. xmlNodeSetContent(xmlParam, buf);
  1934. efree(buf);
  1935. } else if (Z_TYPE_P(data) == IS_STRING) {
  1936. xmlNodeSetContentLen(xmlParam, Z_STRVAL_P(data), Z_STRLEN_P(data));
  1937. }
  1938. if (style == SOAP_ENCODED) {
  1939. set_ns_and_type(xmlParam, type);
  1940. }
  1941. return xmlParam;
  1942. }
  1943. static xmlNodePtr to_xml_duration(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  1944. {
  1945. /* TODO: '-'?P([0-9]+Y)?([0-9]+M)?([0-9]+D)?T([0-9]+H)?([0-9]+M)?([0-9]+S)? */
  1946. return to_xml_string(type, data, style, parent);
  1947. }
  1948. static xmlNodePtr to_xml_datetime(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  1949. {
  1950. return to_xml_datetime_ex(type, data, "%Y-%m-%dT%H:%M:%S", style, parent);
  1951. }
  1952. static xmlNodePtr to_xml_time(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  1953. {
  1954. /* TODO: microsecconds */
  1955. return to_xml_datetime_ex(type, data, "%H:%M:%S", style, parent);
  1956. }
  1957. static xmlNodePtr to_xml_date(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  1958. {
  1959. return to_xml_datetime_ex(type, data, "%Y-%m-%d", style, parent);
  1960. }
  1961. static xmlNodePtr to_xml_gyearmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  1962. {
  1963. return to_xml_datetime_ex(type, data, "%Y-%m", style, parent);
  1964. }
  1965. static xmlNodePtr to_xml_gyear(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  1966. {
  1967. return to_xml_datetime_ex(type, data, "%Y", style, parent);
  1968. }
  1969. static xmlNodePtr to_xml_gmonthday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  1970. {
  1971. return to_xml_datetime_ex(type, data, "--%m-%d", style, parent);
  1972. }
  1973. static xmlNodePtr to_xml_gday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  1974. {
  1975. return to_xml_datetime_ex(type, data, "---%d", style, parent);
  1976. }
  1977. static xmlNodePtr to_xml_gmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
  1978. {
  1979. return to_xml_datetime_ex(type, data, "--%m--", style, parent);
  1980. }
  1981. static zval* to_zval_list(encodeTypePtr enc, xmlNodePtr data) {
  1982. /*FIXME*/
  1983. return to_zval_stringc(enc, data);
  1984. }
  1985. static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent) {
  1986. xmlNodePtr ret;
  1987. encodePtr list_enc = NULL;
  1988. if (enc->sdl_type && enc->sdl_type->kind == XSD_TYPEKIND_LIST && enc->sdl_type->elements) {
  1989. sdlTypePtr *type;
  1990. zend_hash_internal_pointer_reset(enc->sdl_type->elements);
  1991. if (zend_hash_get_current_data(enc->sdl_type->elements, (void**)&type) == SUCCESS) {
  1992. list_enc = (*type)->encode;
  1993. }
  1994. }
  1995. ret = xmlNewNode(NULL,"BOGUS");
  1996. xmlAddChild(parent, ret);
  1997. FIND_ZVAL_NULL(data, ret, style);
  1998. if (Z_TYPE_P(data) == IS_ARRAY) {
  1999. zval **tmp;
  2000. smart_str list = {0};
  2001. HashTable *ht = Z_ARRVAL_P(data);
  2002. zend_hash_internal_pointer_reset(ht);
  2003. while (zend_hash_get_current_data(ht, (void**)&tmp) == SUCCESS) {
  2004. xmlNodePtr dummy = master_to_xml(list_enc, *tmp, SOAP_LITERAL, ret);
  2005. if (dummy && dummy->children && dummy->children->content) {
  2006. if (list.len != 0) {
  2007. smart_str_appendc(&list, ' ');
  2008. }
  2009. smart_str_appends(&list, dummy->children->content);
  2010. } else {
  2011. php_error(E_ERROR,"SOAP-ERROR: Encoding: Violation of encoding rules");
  2012. }
  2013. xmlUnlinkNode(dummy);
  2014. xmlFreeNode(dummy);
  2015. zend_hash_move_forward(ht);
  2016. }
  2017. smart_str_0(&list);
  2018. xmlNodeSetContentLen(ret, list.c, list.len);
  2019. smart_str_free(&list);
  2020. } else {
  2021. zval tmp = *data;
  2022. char *str, *start, *next;
  2023. smart_str list = {0};
  2024. if (Z_TYPE_P(data) != IS_STRING) {
  2025. zval_copy_ctor(&tmp);
  2026. convert_to_string(&tmp);
  2027. data = &tmp;
  2028. }
  2029. str = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
  2030. whiteSpace_collapse(str);
  2031. start = str;
  2032. while (start != NULL && *start != '\0') {
  2033. xmlNodePtr dummy;
  2034. zval dummy_zval;
  2035. next = strchr(start,' ');
  2036. if (next != NULL) {
  2037. *next = '\0';
  2038. next++;
  2039. }
  2040. ZVAL_STRING(&dummy_zval, start, 0);
  2041. dummy = master_to_xml(list_enc, &dummy_zval, SOAP_LITERAL, ret);
  2042. if (dummy && dummy->children && dummy->children->content) {
  2043. if (list.len != 0) {
  2044. smart_str_appendc(&list, ' ');
  2045. }
  2046. smart_str_appends(&list, dummy->children->content);
  2047. } else {
  2048. php_error(E_ERROR,"SOAP-ERROR: Encoding: Violation of encoding rules");
  2049. }
  2050. xmlUnlinkNode(dummy);
  2051. xmlFreeNode(dummy);
  2052. start = next;
  2053. }
  2054. smart_str_0(&list);
  2055. xmlNodeSetContentLen(ret, list.c, list.len);
  2056. smart_str_free(&list);
  2057. efree(str);
  2058. if (data == &tmp) {zval_dtor(&tmp);}
  2059. }
  2060. return ret;
  2061. }
  2062. static xmlNodePtr to_xml_list1(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent) {
  2063. /*FIXME: minLength=1 */
  2064. return to_xml_list(enc,data,style, parent);
  2065. }
  2066. static zval* to_zval_union(encodeTypePtr enc, xmlNodePtr data) {
  2067. /*FIXME*/
  2068. return to_zval_list(enc, data);
  2069. }
  2070. static xmlNodePtr to_xml_union(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent) {
  2071. /*FIXME*/
  2072. return to_xml_list(enc,data,style, parent);
  2073. }
  2074. zval *sdl_guess_convert_zval(encodeTypePtr enc, xmlNodePtr data)
  2075. {
  2076. sdlTypePtr type;
  2077. type = enc->sdl_type;
  2078. /*FIXME: restriction support
  2079. if (type && type->restrictions &&
  2080. data && data->children && data->children->content) {
  2081. if (type->restrictions->whiteSpace && type->restrictions->whiteSpace->value) {
  2082. if (strcmp(type->restrictions->whiteSpace->value,"replace") == 0) {
  2083. whiteSpace_replace(data->children->content);
  2084. } else if (strcmp(type->restrictions->whiteSpace->value,"collapse") == 0) {
  2085. whiteSpace_collapse(data->children->content);
  2086. }
  2087. }
  2088. if (type->restrictions->enumeration) {
  2089. if (!zend_hash_exists(type->restrictions->enumeration,data->children->content,strlen(data->children->content)+1)) {
  2090. php_error(E_WARNING,"SOAP-ERROR: Encoding: Restriction: invalid enumeration value \"%s\"",data->children->content);
  2091. }
  2092. }
  2093. if (type->restrictions->minLength &&
  2094. strlen(data->children->content) < type->restrictions->minLength->value) {
  2095. php_error(E_WARNING,"SOAP-ERROR: Encoding: Restriction: length less then 'minLength'");
  2096. }
  2097. if (type->restrictions->maxLength &&
  2098. strlen(data->children->content) > type->restrictions->maxLength->value) {
  2099. php_error(E_WARNING,"SOAP-ERROR: Encoding: Restriction: length greater then 'maxLength'");
  2100. }
  2101. if (type->restrictions->length &&
  2102. strlen(data->children->content) != type->restrictions->length->value) {
  2103. php_error(E_WARNING,"SOAP-ERROR: Encoding: Restriction: length is not equal to 'length'");
  2104. }
  2105. }
  2106. */
  2107. switch (type->kind) {
  2108. case XSD_TYPEKIND_SIMPLE:
  2109. if (type->encode && enc != &type->encode->details) {
  2110. return master_to_zval(type->encode, data);
  2111. } else {
  2112. return guess_zval_convert(enc, data);
  2113. }
  2114. break;
  2115. case XSD_TYPEKIND_LIST:
  2116. return to_zval_list(enc, data);
  2117. case XSD_TYPEKIND_UNION:
  2118. return to_zval_union(enc, data);
  2119. case XSD_TYPEKIND_COMPLEX:
  2120. case XSD_TYPEKIND_RESTRICTION:
  2121. case XSD_TYPEKIND_EXTENSION:
  2122. if (type->encode &&
  2123. (type->encode->details.type == IS_ARRAY ||
  2124. type->encode->details.type == SOAP_ENC_ARRAY)) {
  2125. return to_zval_array(enc, data);
  2126. }
  2127. return to_zval_object(enc, data);
  2128. default:
  2129. php_error(E_ERROR,"SOAP-ERROR: Encoding: Internal Error");
  2130. return guess_zval_convert(enc, data);
  2131. }
  2132. }
  2133. xmlNodePtr sdl_guess_convert_xml(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent)
  2134. {
  2135. sdlTypePtr type;
  2136. xmlNodePtr ret = NULL;
  2137. type = enc->sdl_type;
  2138. /*FIXME: restriction support
  2139. if (type) {
  2140. if (type->restrictions && Z_TYPE_P(data) == IS_STRING) {
  2141. if (type->restrictions->enumeration) {
  2142. if (!zend_hash_exists(type->restrictions->enumeration,Z_STRVAL_P(data),Z_STRLEN_P(data)+1)) {
  2143. php_error(E_WARNING,"SOAP-ERROR: Encoding: Restriction: invalid enumeration value \"%s\".",Z_STRVAL_P(data));
  2144. }
  2145. }
  2146. if (type->restrictions->minLength &&
  2147. Z_STRLEN_P(data) < type->restrictions->minLength->value) {
  2148. php_error(E_WARNING,"SOAP-ERROR: Encoding: Restriction: length less then 'minLength'");
  2149. }
  2150. if (type->restrictions->maxLength &&
  2151. Z_STRLEN_P(data) > type->restrictions->maxLength->value) {
  2152. php_error(E_WARNING,"SOAP-ERROR: Encoding: Restriction: length greater then 'maxLength'");
  2153. }
  2154. if (type->restrictions->length &&
  2155. Z_STRLEN_P(data) != type->restrictions->length->value) {
  2156. php_error(E_WARNING,"SOAP-ERROR: Encoding: Restriction: length is not equal to 'length'");
  2157. }
  2158. }
  2159. }
  2160. */
  2161. switch(type->kind) {
  2162. case XSD_TYPEKIND_SIMPLE:
  2163. if (type->encode && enc != &type->encode->details) {
  2164. ret = master_to_xml(type->encode, data, style, parent);
  2165. } else {
  2166. ret = guess_xml_convert(enc, data, style, parent);
  2167. }
  2168. break;
  2169. case XSD_TYPEKIND_LIST:
  2170. ret = to_xml_list(enc, data, style, parent);
  2171. break;
  2172. case XSD_TYPEKIND_UNION:
  2173. ret = to_xml_union(enc, data, style, parent);
  2174. break;
  2175. case XSD_TYPEKIND_COMPLEX:
  2176. case XSD_TYPEKIND_RESTRICTION:
  2177. case XSD_TYPEKIND_EXTENSION:
  2178. if (type->encode &&
  2179. (type->encode->details.type == IS_ARRAY ||
  2180. type->encode->details.type == SOAP_ENC_ARRAY)) {
  2181. ret = to_xml_array(enc, data, style, parent);
  2182. } else {
  2183. ret = to_xml_object(enc, data, style, parent);
  2184. }
  2185. break;
  2186. default:
  2187. php_error(E_ERROR,"SOAP-ERROR: Encoding: Internal Error");
  2188. break;
  2189. }
  2190. if (style == SOAP_ENCODED) {
  2191. set_ns_and_type(ret, enc);
  2192. }
  2193. return ret;
  2194. }
  2195. static xmlNodePtr check_and_resolve_href(xmlNodePtr data)
  2196. {
  2197. if (data && data->properties) {
  2198. xmlAttrPtr href;
  2199. href = data->properties;
  2200. while (1) {
  2201. href = get_attribute(href, "href");
  2202. if (href == NULL || href->ns == NULL) {break;}
  2203. href = href->next;
  2204. }
  2205. if (href) {
  2206. /* Internal href try and find node */
  2207. if (href->children->content[0] == '#') {
  2208. xmlNodePtr ret = get_node_with_attribute_recursive(data->doc->children, NULL, "id", &href->children->content[1]);
  2209. if (!ret) {
  2210. php_error(E_ERROR,"SOAP-ERROR: Encoding: Unresolved reference '%s'",href->children->content);
  2211. }
  2212. return ret;
  2213. } else {
  2214. /* TODO: External href....? */
  2215. php_error(E_ERROR,"SOAP-ERROR: Encoding: External reference '%s'",href->children->content);
  2216. }
  2217. }
  2218. /* SOAP 1.2 enc:id enc:ref */
  2219. href = get_attribute_ex(data->properties, "ref", SOAP_1_2_ENC_NAMESPACE);
  2220. if (href) {
  2221. char* id;
  2222. xmlNodePtr ret;
  2223. if (href->children->content[0] == '#') {
  2224. id = href->children->content+1;
  2225. } else {
  2226. id = href->children->content;
  2227. }
  2228. ret = get_node_with_attribute_recursive_ex(data->doc->children, NULL, NULL, "id", id, SOAP_1_2_ENC_NAMESPACE);
  2229. if (!ret) {
  2230. php_error(E_ERROR,"SOAP-ERROR: Encoding: Unresolved reference '%s'",href->children->content);
  2231. } else if (ret == data) {
  2232. php_error(E_ERROR,"SOAP-ERROR: Encoding: Violation of id and ref information items '%s'",href->children->content);
  2233. }
  2234. return ret;
  2235. }
  2236. }
  2237. return data;
  2238. }
  2239. static void set_ns_and_type(xmlNodePtr node, encodeTypePtr type)
  2240. {
  2241. set_ns_and_type_ex(node, type->ns, type->type_str);
  2242. }
  2243. static void set_ns_and_type_ex(xmlNodePtr node, char *ns, char *type)
  2244. {
  2245. smart_str nstype = {0};
  2246. get_type_str(node, ns, type, &nstype);
  2247. xmlSetProp(node, "xsi:type", nstype.c);
  2248. smart_str_free(&nstype);
  2249. }
  2250. xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns)
  2251. {
  2252. xmlNsPtr xmlns;
  2253. if (ns == NULL) {
  2254. return NULL;
  2255. }
  2256. xmlns = xmlSearchNsByHref(node->doc,node,ns);
  2257. if (xmlns == NULL) {
  2258. char* prefix;
  2259. TSRMLS_FETCH();
  2260. if (zend_hash_find(&SOAP_GLOBAL(defEncNs), (char*)ns, strlen(ns) + 1, (void **)&prefix) == SUCCESS) {
  2261. xmlns = xmlNewNs(node->doc->children,ns,prefix);
  2262. } else {
  2263. smart_str prefix = {0};
  2264. int num = ++SOAP_GLOBAL(cur_uniq_ns);
  2265. smart_str_appendl(&prefix, "ns", 2);
  2266. smart_str_append_long(&prefix, num);
  2267. smart_str_0(&prefix);
  2268. xmlns = xmlNewNs(node->doc->children,ns,prefix.c);
  2269. smart_str_free(&prefix);
  2270. }
  2271. }
  2272. return xmlns;
  2273. }
  2274. void encode_reset_ns()
  2275. {
  2276. TSRMLS_FETCH();
  2277. SOAP_GLOBAL(cur_uniq_ns) = 0;
  2278. }
  2279. static encodePtr get_conversion(int encode)
  2280. {
  2281. encodePtr *enc = NULL;
  2282. TSRMLS_FETCH();
  2283. if (zend_hash_index_find(&SOAP_GLOBAL(defEncIndex), encode, (void **)&enc) == FAILURE) {
  2284. if (SOAP_GLOBAL(overrides)) {
  2285. smart_str nscat = {0};
  2286. smart_str_appendl(&nscat, (*enc)->details.ns, strlen((*enc)->details.ns));
  2287. smart_str_appendc(&nscat, ':');
  2288. smart_str_appendl(&nscat, (*enc)->details.type_str, strlen((*enc)->details.type_str));
  2289. smart_str_0(&nscat);
  2290. if (zend_hash_find(SOAP_GLOBAL(overrides), nscat.c, nscat.len + 1, (void **)&enc) == FAILURE) {
  2291. smart_str_free(&nscat);
  2292. php_error(E_ERROR, "SOAP-ERROR: Encoding: Cannot find encoding");
  2293. return NULL;
  2294. } else {
  2295. smart_str_free(&nscat);
  2296. return *enc;
  2297. }
  2298. } else {
  2299. php_error(E_ERROR, "SOAP-ERROR: Encoding: Cannot find encoding");
  2300. return NULL;
  2301. }
  2302. } else {
  2303. return *enc;
  2304. }
  2305. }
  2306. static int is_map(zval *array)
  2307. {
  2308. int i, count = zend_hash_num_elements(Z_ARRVAL_P(array));
  2309. zend_hash_internal_pointer_reset(Z_ARRVAL_P(array));
  2310. for (i = 0;i < count;i++) {
  2311. if (zend_hash_get_current_key_type(Z_ARRVAL_P(array)) == HASH_KEY_IS_STRING) {
  2312. return TRUE;
  2313. }
  2314. zend_hash_move_forward(Z_ARRVAL_P(array));
  2315. }
  2316. return FALSE;
  2317. }
  2318. static void get_array_type(xmlNodePtr node, zval *array, smart_str *type TSRMLS_DC)
  2319. {
  2320. HashTable *ht = HASH_OF(array);
  2321. int i, count, cur_type, prev_type, different;
  2322. zval **tmp;
  2323. char *prev_stype = NULL, *cur_stype = NULL, *prev_ns = NULL, *cur_ns = NULL;
  2324. if (!array || Z_TYPE_P(array) != IS_ARRAY) {
  2325. smart_str_appendl(type, "xsd:anyType", 11);
  2326. }
  2327. different = FALSE;
  2328. cur_type = prev_type = 0;
  2329. count = zend_hash_num_elements(ht);
  2330. zend_hash_internal_pointer_reset(ht);
  2331. for (i = 0;i < count;i++) {
  2332. zend_hash_get_current_data(ht, (void **)&tmp);
  2333. if (Z_TYPE_PP(tmp) == IS_OBJECT &&
  2334. Z_OBJCE_PP(tmp) == soap_var_class_entry) {
  2335. zval **ztype;
  2336. if (zend_hash_find(Z_OBJPROP_PP(tmp), "enc_type", sizeof("enc_type"), (void **)&ztype) == FAILURE) {
  2337. php_error(E_ERROR, "SOAP-ERROR: Encoding: SoapVar hasn't 'enc_type' property");
  2338. }
  2339. cur_type = Z_LVAL_PP(ztype);
  2340. if (zend_hash_find(Z_OBJPROP_PP(tmp), "enc_stype", sizeof("enc_stype"), (void **)&ztype) == SUCCESS) {
  2341. cur_stype = Z_STRVAL_PP(ztype);
  2342. } else {
  2343. cur_stype = NULL;
  2344. }
  2345. if (zend_hash_find(Z_OBJPROP_PP(tmp), "enc_ns", sizeof("enc_ns"), (void **)&ztype) == SUCCESS) {
  2346. cur_ns = Z_STRVAL_PP(ztype);
  2347. } else {
  2348. cur_ns = NULL;
  2349. }
  2350. } else if (Z_TYPE_PP(tmp) == IS_ARRAY && is_map(*tmp)) {
  2351. cur_type = APACHE_MAP;
  2352. cur_stype = NULL;
  2353. cur_ns = NULL;
  2354. } else {
  2355. cur_type = Z_TYPE_PP(tmp);
  2356. cur_stype = NULL;
  2357. cur_ns = NULL;
  2358. }
  2359. if (i > 0) {
  2360. if ((cur_type != prev_type) ||
  2361. (cur_stype != NULL && prev_stype != NULL && strcmp(cur_stype,prev_stype) != 0) ||
  2362. (cur_stype == NULL && cur_stype != prev_stype) ||
  2363. (cur_ns != NULL && prev_ns != NULL && strcmp(cur_ns,prev_ns) != 0) ||
  2364. (cur_ns == NULL && cur_ns != prev_ns)) {
  2365. different = TRUE;
  2366. break;
  2367. }
  2368. }
  2369. prev_type = cur_type;
  2370. prev_stype = cur_stype;
  2371. prev_ns = cur_ns;
  2372. zend_hash_move_forward(ht);
  2373. }
  2374. if (different || count == 0) {
  2375. smart_str_appendl(type, "xsd:anyType", 11);
  2376. } else {
  2377. if (cur_stype != NULL) {
  2378. if (cur_ns) {
  2379. xmlNsPtr ns = encode_add_ns(node,cur_ns);
  2380. smart_str_appends(type,ns->prefix);
  2381. smart_str_appendc(type,':');
  2382. }
  2383. smart_str_appends(type,cur_stype);
  2384. smart_str_0(type);
  2385. } else {
  2386. encodePtr enc;
  2387. enc = get_conversion(cur_type);
  2388. get_type_str(node, enc->details.ns, enc->details.type_str, type);
  2389. }
  2390. }
  2391. }
  2392. static void get_type_str(xmlNodePtr node, const char* ns, const char* type, smart_str* ret)
  2393. {
  2394. TSRMLS_FETCH();
  2395. if (ns) {
  2396. xmlNsPtr xmlns;
  2397. if (SOAP_GLOBAL(soap_version) == SOAP_1_2 &&
  2398. strcmp(ns,SOAP_1_1_ENC_NAMESPACE) == 0) {
  2399. ns = SOAP_1_2_ENC_NAMESPACE;
  2400. } else if (SOAP_GLOBAL(soap_version) == SOAP_1_1 &&
  2401. strcmp(ns,SOAP_1_2_ENC_NAMESPACE) == 0) {
  2402. ns = SOAP_1_1_ENC_NAMESPACE;
  2403. }
  2404. xmlns = encode_add_ns(node,ns);
  2405. smart_str_appends(ret, xmlns->prefix);
  2406. smart_str_appendc(ret, ':');
  2407. }
  2408. smart_str_appendl(ret, type, strlen(type));
  2409. smart_str_0(ret);
  2410. }
  2411. static void delete_mapping(void *data)
  2412. {
  2413. soapMappingPtr map = (soapMappingPtr)data;
  2414. if (map->ns) {
  2415. efree(map->ns);
  2416. }
  2417. if (map->ctype) {
  2418. efree(map->ctype);
  2419. }
  2420. if (map->type == SOAP_MAP_FUNCTION) {
  2421. if (map->map_functions.to_xml_before) {
  2422. zval_ptr_dtor(&map->map_functions.to_xml_before);
  2423. }
  2424. if (map->map_functions.to_xml) {
  2425. zval_ptr_dtor(&map->map_functions.to_xml);
  2426. }
  2427. if (map->map_functions.to_xml_after) {
  2428. zval_ptr_dtor(&map->map_functions.to_xml_after);
  2429. }
  2430. if (map->map_functions.to_zval_before) {
  2431. zval_ptr_dtor(&map->map_functions.to_zval_before);
  2432. }
  2433. if (map->map_functions.to_zval) {
  2434. zval_ptr_dtor(&map->map_functions.to_zval);
  2435. }
  2436. if (map->map_functions.to_zval_after) {
  2437. zval_ptr_dtor(&map->map_functions.to_zval_after);
  2438. }
  2439. }
  2440. efree(map);
  2441. }
  2442. void delete_encoder(void *encode)
  2443. {
  2444. encodePtr t = *((encodePtr*)encode);
  2445. if (t->details.ns) {
  2446. efree(t->details.ns);
  2447. }
  2448. if (t->details.type_str) {
  2449. efree(t->details.type_str);
  2450. }
  2451. if (t->details.map) {
  2452. delete_mapping(t->details.map);
  2453. }
  2454. efree(t);
  2455. }