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.

1125 lines
28 KiB

  1. #include <time.h>
  2. #include "php_soap.h"
  3. encode defaultEncoding[] = {
  4. {{UNKNOWN_TYPE, NULL, NULL, NULL}, guess_zval_convert, guess_xml_convert},
  5. {{IS_NULL, "null", "null", NULL}, to_zval_null, to_xml_null},
  6. {{IS_STRING, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
  7. {{IS_LONG, XSD_INT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  8. {{IS_DOUBLE, XSD_FLOAT_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_string},
  9. {{IS_BOOL, XSD_BOOLEAN_STRING, XSD_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
  10. {{IS_CONSTANT, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
  11. {{IS_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_ENC_NAMESPACE, NULL}, to_zval_array, guess_array_map},
  12. {{IS_CONSTANT_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
  13. {{IS_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
  14. {{XSD_STRING, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
  15. {{XSD_BOOLEAN, XSD_BOOLEAN_STRING, XSD_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
  16. {{XSD_DECIMAL, XSD_DECIMAL_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_string},
  17. {{XSD_FLOAT, XSD_FLOAT_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_string},
  18. {{XSD_DOUBLE, XSD_DOUBLE_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_string},
  19. {{XSD_DATETIME, XSD_DATETIME_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_datetime},
  20. {{XSD_TIME, XSD_TIME_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_time},
  21. {{XSD_DATE, XSD_DATE_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_date},
  22. {{XSD_GYEARMONTH, XSD_GYEARMONTH_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_gyearmonth},
  23. {{XSD_GYEAR, XSD_GYEAR_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_gyear},
  24. {{XSD_GMONTHDAY, XSD_GMONTHDAY_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_gmonthday},
  25. {{XSD_GDAY, XSD_GDAY_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_gday},
  26. {{XSD_GMONTH, XSD_GMONTH_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_gmonth},
  27. {{XSD_HEXBINARY, XSD_HEXBINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_stringl},
  28. {{XSD_BASE64BINARY, XSD_BASE64BINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_stringl},
  29. {{XSD_LONG, XSD_LONG_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  30. {{XSD_INT, XSD_INT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_string},
  31. {{XSD_SHORT, XSD_SHORT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_string},
  32. {{APACHE_MAP, APACHE_MAP_STRING, APACHE_NAMESPACE, NULL}, to_zval_map, to_xml_map},
  33. {{SOAP_ENC_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
  34. {{SOAP_ENC_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
  35. //support some of the 1999 data types
  36. {{XSD_STRING, XSD_STRING_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_string, to_xml_string},
  37. {{XSD_BOOLEAN, XSD_BOOLEAN_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
  38. {{XSD_DECIMAL, XSD_DECIMAL_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_string},
  39. {{XSD_FLOAT, XSD_FLOAT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_double, to_xml_string},
  40. {{XSD_DOUBLE, XSD_DOUBLE_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_double, to_xml_string},
  41. {{XSD_LONG, XSD_LONG_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
  42. {{XSD_INT, XSD_INT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_string},
  43. {{XSD_SHORT, XSD_SHORT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_string},
  44. {{XSD_1999_TIMEINSTANT, XSD_1999_TIMEINSTANT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_string, to_xml_string},
  45. {{END_KNOWN_TYPES, NULL, NULL, NULL}, guess_zval_convert, guess_xml_convert}
  46. //TODO: finish off encoding
  47. /*
  48. #define XSD_DURATION 107
  49. #define XSD_DURATION_STRING "duration"
  50. #define XSD_ANYURI 118
  51. #define XSD_ANYURI_STRING "anyURI"
  52. #define XSD_QNAME 119
  53. #define XSD_QNAME_STRING "QName"
  54. #define XSD_NOTATION 120
  55. #define XSD_NOTATION_STRING "NOTATION"
  56. */
  57. /*
  58. #define XSD_NORMALIZEDSTRING 121
  59. #define XSD_NORMALIZEDSTRING_STRING "normalizedString"
  60. #define XSD_TOKEN 122
  61. #define XSD_TOKEN_STRING "token"
  62. #define XSD_LANGUAGE 123
  63. #define XSD_LANGUAGE_STRING "language"
  64. #define XSD_NMTOKEN 124
  65. #define XSD_NMTOKEN_STRING "NMTOKEN"
  66. #define XSD_NAME 124
  67. #define XSD_NAME_STRING "Name"
  68. #define XSD_NCNAME 125
  69. #define XSD_NCNAME_STRING "NCName"
  70. #define XSD_ID 126
  71. #define XSD_ID_STRING "ID"
  72. #define XSD_IDREF 127
  73. #define XSD_IDREF_STRING "IDREF"
  74. #define XSD_IDREFS 127
  75. #define XSD_IDREFS_STRING "IDREFS"
  76. #define XSD_ENTITY 128
  77. #define XSD_ENTITY_STRING "ENTITY"
  78. #define XSD_ENTITYS 129
  79. #define XSD_ENTITYS_STRING "ENTITYS"
  80. #define XSD_INTEGER 130
  81. #define XSD_INTEGER_STRING "integer"
  82. #define XSD_NONPOSITIVEINTEGER 131
  83. #define XSD_NONPOSITIVEINTEGER_STRING "nonPositiveInteger"
  84. #define XSD_NEGATIVEINTEGER 132
  85. #define XSD_NEGATIVEINTEGER_STRING "negativeInteger"
  86. #define XSD_NONNEGATIVEINTEGER 137
  87. #define XSD_NONNEGATIVEINTEGER_STRING "nonNegativeInteger"
  88. #define XSD_UNSIGNEDLONG 138
  89. #define XSD_UNSIGNEDLONG_STRING "unsignedLong"
  90. #define XSD_UNSIGNEDINT 139
  91. #define XSD_UNSIGNEDINT_STRING "unsignedInt"
  92. #define XSD_UNSIGNEDSHORT 140
  93. #define XSD_UNSIGNEDSHORT_STRING "unsignedShort"
  94. #define XSD_UNSIGNEDBYTE 141
  95. #define XSD_UNSIGNEDBYTE_STRING "unsignedByte"
  96. #define XSD_POSITIVEINTEGER 142
  97. #define XSD_POSITIVEINTEGER_STRING "positiveInteger"
  98. */
  99. };
  100. xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style)
  101. {
  102. xmlNodePtr node;
  103. if(encode->to_xml_before)
  104. data = encode->to_xml_before(encode->details, data);
  105. if(encode->to_xml)
  106. node = encode->to_xml(encode->details, data, style);
  107. if(encode->to_xml_after)
  108. node = encode->to_xml_after(encode->details, node, style);
  109. return node;
  110. }
  111. zval *master_to_zval(encodePtr encode, xmlNodePtr data)
  112. {
  113. zval *ret;
  114. data = check_and_resolve_href(data);
  115. if(encode->to_zval_before)
  116. data = encode->to_zval_before(encode->details, data, 0);
  117. if(encode->to_zval)
  118. ret = encode->to_zval(encode->details, data);
  119. if(encode->to_zval_after)
  120. ret = encode->to_zval_after(encode->details, ret);
  121. return ret;
  122. }
  123. #ifdef HAVE_PHP_DOMXML
  124. zval *to_xml_before_user(encodeType type, zval *data)
  125. {
  126. TSRMLS_FETCH();
  127. if(type.map->map_functions.to_xml_before)
  128. {
  129. if(call_user_function(EG(function_table), NULL, type.map->map_functions.to_xml_before, data, 1, &data TSRMLS_CC) == FAILURE)
  130. php_error(E_ERROR, "Error calling to_xml_before");
  131. }
  132. return data;
  133. }
  134. xmlNodePtr to_xml_user(encodeType type, zval *data, int style)
  135. {
  136. zval *ret, **addr;
  137. xmlNodePtr node;
  138. TSRMLS_FETCH();
  139. if(type.map->map_functions.to_xml)
  140. {
  141. MAKE_STD_ZVAL(ret);
  142. if(call_user_function(EG(function_table), NULL, type.map->map_functions.to_xml, ret, 1, &data TSRMLS_CC) == FAILURE)
  143. php_error(E_ERROR, "Error calling to_xml");
  144. if(Z_TYPE_P(ret) != IS_OBJECT)
  145. php_error(E_ERROR, "Error serializing object from to_xml_user");
  146. if(zend_hash_index_find(Z_OBJPROP_P(ret), 1, (void **)&addr) == SUCCESS)
  147. {
  148. node = (xmlNodePtr)Z_LVAL_PP(addr);
  149. node = xmlCopyNode(node, 1);
  150. set_ns_and_type(node, type);
  151. }
  152. zval_ptr_dtor(&ret);
  153. }
  154. return node;
  155. }
  156. xmlNodePtr to_xml_after_user(encodeType type, xmlNodePtr node, int style)
  157. {
  158. zval *ret, *param, **addr;
  159. int found;
  160. TSRMLS_FETCH();
  161. if(type.map->map_functions.to_xml_after)
  162. {
  163. MAKE_STD_ZVAL(ret);
  164. MAKE_STD_ZVAL(param);
  165. param = php_domobject_new(node, &found, NULL TSRMLS_CC);
  166. if(call_user_function(EG(function_table), NULL, type.map->map_functions.to_xml_after, ret, 1, &param TSRMLS_CC) == FAILURE)
  167. php_error(E_ERROR, "Error calling to_xml_after");
  168. if(zend_hash_index_find(Z_OBJPROP_P(ret), 1, (void **)&addr) == SUCCESS)
  169. {
  170. node = (xmlNodePtr)Z_LVAL_PP(addr);
  171. set_ns_and_type(node, type);
  172. }
  173. zval_ptr_dtor(&ret);
  174. zval_ptr_dtor(&param);
  175. }
  176. return node;
  177. }
  178. xmlNodePtr to_zval_before_user(encodeType type, xmlNodePtr node, int style)
  179. {
  180. zval *ret, *param, **addr;
  181. int found;
  182. TSRMLS_FETCH();
  183. if(type.map->map_functions.to_zval_before)
  184. {
  185. MAKE_STD_ZVAL(ret);
  186. MAKE_STD_ZVAL(param);
  187. param = php_domobject_new(node, &found, NULL TSRMLS_CC);
  188. if(call_user_function(EG(function_table), NULL, type.map->map_functions.to_zval_before, ret, 1, &param TSRMLS_CC) == FAILURE)
  189. php_error(E_ERROR, "Error calling to_zval_before");
  190. if(zend_hash_index_find(Z_OBJPROP_P(ret), 1, (void **)&addr) == SUCCESS)
  191. {
  192. node = (xmlNodePtr)Z_LVAL_PP(addr);
  193. set_ns_and_type(node, type);
  194. }
  195. zval_ptr_dtor(&ret);
  196. zval_ptr_dtor(&param);
  197. }
  198. return node;
  199. }
  200. zval *to_zval_user(encodeType type, xmlNodePtr node)
  201. {
  202. zval *ret, *param;
  203. int found;
  204. TSRMLS_FETCH();
  205. if(type.map->map_functions.to_zval)
  206. {
  207. MAKE_STD_ZVAL(ret);
  208. MAKE_STD_ZVAL(param);
  209. param = php_domobject_new(node, &found, NULL TSRMLS_CC);
  210. if(call_user_function(EG(function_table), NULL, type.map->map_functions.to_zval, ret, 1, &param TSRMLS_CC) == FAILURE)
  211. php_error(E_ERROR, "Error calling to_zval");
  212. zval_ptr_dtor(&param);
  213. }
  214. return ret;
  215. }
  216. zval *to_zval_after_user(encodeType type, zval *data)
  217. {
  218. TSRMLS_FETCH();
  219. if(type.map->map_functions.to_zval_after)
  220. {
  221. if(call_user_function(EG(function_table), NULL, type.map->map_functions.to_zval_after, data, 1, &data TSRMLS_CC) == FAILURE)
  222. php_error(E_ERROR, "Error calling to_xml_before");
  223. }
  224. return data;
  225. }
  226. #endif
  227. //TODO: get rid of "bogus".. ither by passing in the already created xmlnode or passing in the node name
  228. //String encode/decode
  229. zval *to_zval_string(encodeType type, xmlNodePtr data)
  230. {
  231. zval *ret;
  232. MAKE_STD_ZVAL(ret);
  233. FIND_XML_NULL(data, ret);
  234. if(data && data->children)
  235. ZVAL_STRING(ret, data->children->content, 1);
  236. return ret;
  237. }
  238. zval *to_zval_stringl(encodeType type, xmlNodePtr data)
  239. {
  240. zval *ret;
  241. MAKE_STD_ZVAL(ret);
  242. FIND_XML_NULL(data, ret);
  243. if(data && data->children)
  244. ZVAL_STRINGL(ret, data->children->content, xmlStrlen(data->children->content), 1);
  245. return ret;
  246. }
  247. xmlNodePtr to_xml_string(encodeType type, zval *data, int style)
  248. {
  249. xmlNodePtr ret;
  250. char *str;
  251. int new_len;
  252. ret = xmlNewNode(NULL, "BOGUS");
  253. FIND_ZVAL_NULL(data, ret);
  254. convert_to_string(data);
  255. str = php_escape_html_entities(Z_STRVAL_P(data), Z_STRLEN_P(data), &new_len, 0, 0, NULL);
  256. xmlNodeSetContentLen(ret, str, new_len);
  257. if(style == SOAP_ENCODED)
  258. set_ns_and_type(ret, type);
  259. return ret;
  260. }
  261. xmlNodePtr to_xml_stringl(encodeType type, zval *data, int style)
  262. {
  263. xmlNodePtr ret;
  264. ret = xmlNewNode(NULL, "BOGUS");
  265. FIND_ZVAL_NULL(data, ret);
  266. convert_to_string(data);
  267. xmlNodeSetContentLen(ret, estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data)), Z_STRLEN_P(data));
  268. if(style == SOAP_ENCODED)
  269. set_ns_and_type(ret, type);
  270. return ret;
  271. }
  272. zval *to_zval_double(encodeType type, xmlNodePtr data)
  273. {
  274. zval *ret;
  275. MAKE_STD_ZVAL(ret);
  276. FIND_XML_NULL(data, ret);
  277. ZVAL_DOUBLE(ret, atof(data->children->content));
  278. return ret;
  279. }
  280. zval *to_zval_long(encodeType type, xmlNodePtr data)
  281. {
  282. zval *ret;
  283. MAKE_STD_ZVAL(ret);
  284. FIND_XML_NULL(data, ret);
  285. ZVAL_LONG(ret, atol(data->children->content));
  286. return ret;
  287. }
  288. xmlNodePtr to_xml_long(encodeType type, zval *data, int style)
  289. {
  290. xmlNodePtr ret;
  291. ret = xmlNewNode(NULL, "BOGUS");
  292. FIND_ZVAL_NULL(data, ret);
  293. convert_to_long(data);
  294. convert_to_string(data);
  295. xmlNodeSetContentLen(ret, Z_STRVAL_P(data), Z_STRLEN_P(data));
  296. if(style == SOAP_ENCODED)
  297. set_ns_and_type(ret, type);
  298. return ret;
  299. }
  300. zval *to_zval_bool(encodeType type, xmlNodePtr data)
  301. {
  302. zval *ret;
  303. MAKE_STD_ZVAL(ret);
  304. FIND_XML_NULL(data, ret);
  305. if(stricmp(data->children->content,"true") == 0 ||
  306. stricmp(data->children->content,"t") == 0 ||
  307. strcmp(data->children->content,"1") == 0)
  308. {
  309. ZVAL_BOOL(ret, 1);
  310. }
  311. else
  312. {
  313. ZVAL_BOOL(ret, 0);
  314. }
  315. return ret;
  316. }
  317. xmlNodePtr to_xml_bool(encodeType type, zval *data, int style)
  318. {
  319. xmlNodePtr ret;
  320. ret = xmlNewNode(NULL, "BOGUS");
  321. FIND_ZVAL_NULL(data, ret);
  322. convert_to_boolean(data);
  323. if(data->value.lval == 1)
  324. xmlNodeSetContent(ret, "1");
  325. else
  326. xmlNodeSetContent(ret, "0");
  327. if(style == SOAP_ENCODED)
  328. set_ns_and_type(ret, type);
  329. return ret;
  330. }
  331. //Null encode/decode
  332. zval *to_zval_null(encodeType type, xmlNodePtr data)
  333. {
  334. zval *ret;
  335. MAKE_STD_ZVAL(ret);
  336. ZVAL_NULL(ret);
  337. return ret;
  338. }
  339. xmlNodePtr to_xml_null(encodeType type, zval *data, int style)
  340. {
  341. xmlNodePtr ret;
  342. ret = xmlNewNode(NULL, "BOGUS");
  343. FIND_ZVAL_NULL(data, ret);
  344. if(style == SOAP_ENCODED)
  345. xmlSetProp(ret, "xsi:null", "1");
  346. return ret;
  347. }
  348. //Struct encode/decode
  349. zval *to_zval_object(encodeType type, xmlNodePtr data)
  350. {
  351. zval *ret;
  352. xmlNodePtr trav;
  353. encodePtr enc;
  354. TSRMLS_FETCH();
  355. MAKE_STD_ZVAL(ret);
  356. FIND_XML_NULL(data, ret);
  357. object_init(ret);
  358. trav = data->children;
  359. enc = get_conversion(UNKNOWN_TYPE);
  360. do
  361. {
  362. if(trav->type == XML_ELEMENT_NODE)
  363. {
  364. zval *tmpVal;
  365. tmpVal = master_to_zval(enc, trav);
  366. add_property_zval(ret, (char *)trav->name, tmpVal);
  367. }
  368. }
  369. while(trav = trav->next);
  370. return ret;
  371. }
  372. xmlNodePtr to_xml_object(encodeType type, zval *data, int style)
  373. {
  374. xmlNodePtr xmlParam;
  375. HashTable *prop;
  376. int i;
  377. TSRMLS_FETCH();
  378. //Special handling of class SoapVar
  379. if(data && Z_TYPE_P(data) == IS_OBJECT && !strcmp(Z_OBJCE_P(data)->name, soap_var_class_entry.name))
  380. {
  381. zval **ztype, **zdata, **zns, **zstype, **zname, **znamens;
  382. encodePtr enc;
  383. if(zend_hash_find(Z_OBJPROP_P(data), "enc_type", sizeof("enc_type"), (void **)&ztype) == FAILURE)
  384. php_error(E_ERROR, "error encoding SoapVar");
  385. if(zend_hash_find(Z_OBJPROP_P(data), "enc_value", sizeof("enc_value"), (void **)&zdata) == FAILURE)
  386. php_error(E_ERROR, "error encoding SoapVar");
  387. enc = get_conversion(Z_LVAL_P(*ztype));
  388. xmlParam = master_to_xml(enc, *zdata, style);
  389. if(zend_hash_find(Z_OBJPROP_P(data), "enc_stype", sizeof("enc_stype"), (void **)&zstype) == SUCCESS)
  390. {
  391. if(zend_hash_find(Z_OBJPROP_P(data), "enc_ns", sizeof("enc_ns"), (void **)&zns) == SUCCESS)
  392. set_ns_and_type_ex(xmlParam, Z_STRVAL_PP(zns), Z_STRVAL_PP(zstype));
  393. else
  394. set_ns_and_type_ex(xmlParam, NULL, Z_STRVAL_PP(zstype));
  395. }
  396. if(zend_hash_find(Z_OBJPROP_P(data), "enc_name", sizeof("enc_name"), (void **)&zname) == SUCCESS)
  397. xmlNodeSetName(xmlParam, Z_STRVAL_PP(zname));
  398. if(zend_hash_find(Z_OBJPROP_P(data), "enc_namens", sizeof("enc_namens"), (void **)&znamens) == SUCCESS)
  399. {
  400. smart_str *ns;
  401. xmlNsPtr nsp;
  402. ns = encode_new_ns();
  403. nsp = xmlNewNs(xmlParam, Z_STRVAL_PP(znamens), ns->c);
  404. xmlSetNs(xmlParam, nsp);
  405. smart_str_free(ns);
  406. efree(ns);
  407. }
  408. }
  409. else
  410. {
  411. xmlParam = xmlNewNode(NULL, "BOGUS");
  412. FIND_ZVAL_NULL(data, xmlParam);
  413. if(Z_TYPE_P(data) == IS_OBJECT)
  414. {
  415. prop = Z_OBJPROP_P(data);
  416. i = zend_hash_num_elements(prop);
  417. zend_hash_internal_pointer_reset(prop);
  418. for(;i > 0;i--)
  419. {
  420. xmlNodePtr property;
  421. encodePtr enc;
  422. zval **zprop;
  423. char *str_key;
  424. zend_hash_get_current_key(prop, &str_key, NULL, FALSE);
  425. zend_hash_get_current_data(prop, (void **)&zprop);
  426. enc = get_conversion((*zprop)->type);
  427. property = master_to_xml(enc, (*zprop), style);
  428. xmlNodeSetName(property, str_key);
  429. xmlAddChild(xmlParam, property);
  430. zend_hash_move_forward(prop);
  431. }
  432. }
  433. if(style == SOAP_ENCODED)
  434. set_ns_and_type(xmlParam, type);
  435. }
  436. return xmlParam;
  437. }
  438. //Array encode/decode
  439. xmlNodePtr guess_array_map(encodeType type, zval *data, int style)
  440. {
  441. encodePtr enc = NULL;
  442. TSRMLS_FETCH();
  443. if(data && Z_TYPE_P(data) == IS_ARRAY)
  444. {
  445. if(zend_hash_num_elements(Z_ARRVAL_P(data)) > 0)
  446. {
  447. if(is_map(data))
  448. enc = get_conversion(APACHE_MAP);
  449. else
  450. enc = get_conversion(SOAP_ENC_ARRAY);
  451. }
  452. }
  453. if(!enc)
  454. enc = get_conversion(IS_NULL);
  455. return master_to_xml(enc, data, style);
  456. }
  457. xmlNodePtr to_xml_array(encodeType type, zval *data, int style)
  458. {
  459. smart_str array_type_and_size = {0}, array_type = {0};
  460. int i;
  461. xmlNodePtr xmlParam;
  462. TSRMLS_FETCH();
  463. xmlParam = xmlNewNode(NULL,"BOGUS");
  464. FIND_ZVAL_NULL(data, xmlParam);
  465. if(Z_TYPE_P(data) == IS_ARRAY)
  466. {
  467. i = zend_hash_num_elements(Z_ARRVAL_P(data));
  468. if(style == SOAP_ENCODED)
  469. {
  470. get_array_type(data, &array_type);
  471. smart_str_append(&array_type_and_size, &array_type);
  472. smart_str_appendc(&array_type_and_size, '[');
  473. smart_str_append_long(&array_type_and_size, i);
  474. smart_str_appendc(&array_type_and_size, ']');
  475. smart_str_0(&array_type_and_size);
  476. xmlSetProp(xmlParam, "SOAP-ENC:arrayType", array_type_and_size.c);
  477. smart_str_free(&array_type_and_size);
  478. smart_str_free(&array_type);
  479. }
  480. zend_hash_internal_pointer_reset(data->value.ht);
  481. for(;i > 0;i--)
  482. {
  483. xmlNodePtr xparam;
  484. zval **zdata;
  485. encodePtr enc;
  486. zend_hash_get_current_data(data->value.ht, (void **)&zdata);
  487. enc = get_conversion((*zdata)->type);
  488. xparam = master_to_xml(enc, (*zdata), style);
  489. if(style == SOAP_LITERAL)
  490. xmlNodeSetName(xparam, enc->details.type_str);
  491. else
  492. xmlNodeSetName(xparam, "val");
  493. xmlAddChild(xmlParam, xparam);
  494. zend_hash_move_forward(data->value.ht);
  495. }
  496. }
  497. if(style == SOAP_ENCODED)
  498. set_ns_and_type(xmlParam, type);
  499. return xmlParam;
  500. }
  501. zval *to_zval_array(encodeType type, xmlNodePtr data)
  502. {
  503. zval *ret;
  504. xmlNodePtr trav;
  505. encodePtr enc;
  506. TSRMLS_FETCH();
  507. MAKE_STD_ZVAL(ret);
  508. FIND_XML_NULL(data, ret);
  509. array_init(ret);
  510. trav = data->children;
  511. enc = get_conversion(UNKNOWN_TYPE);
  512. while(trav)
  513. {
  514. if(trav->type == XML_ELEMENT_NODE)
  515. {
  516. zval *tmpVal;
  517. tmpVal = master_to_zval(enc, trav);
  518. zend_hash_next_index_insert(Z_ARRVAL_P(ret), &tmpVal, sizeof(zval *), NULL);
  519. }
  520. trav = trav->next;
  521. }
  522. return ret;
  523. }
  524. //Map encode/decode
  525. xmlNodePtr to_xml_map(encodeType type, zval *data, int style)
  526. {
  527. xmlNodePtr xmlParam;
  528. int i;
  529. TSRMLS_FETCH();
  530. xmlParam = xmlNewNode(NULL, "BOGUS");
  531. FIND_ZVAL_NULL(data, xmlParam);
  532. if(Z_TYPE_P(data) == IS_ARRAY)
  533. {
  534. i = zend_hash_num_elements(Z_ARRVAL_P(data));
  535. //TODO: Register namespace...???
  536. xmlSetProp(xmlParam, "xmlns:apache", "http://xml.apache.org/xml-soap");
  537. zend_hash_internal_pointer_reset(data->value.ht);
  538. for(;i > 0;i--)
  539. {
  540. xmlNodePtr xparam, item;
  541. xmlNodePtr key;
  542. zval **temp_data;
  543. char *key_val;
  544. int int_val;
  545. encodePtr enc;
  546. zend_hash_get_current_data(data->value.ht, (void **)&temp_data);
  547. if(Z_TYPE_PP(temp_data) != IS_NULL)
  548. {
  549. item = xmlNewNode(NULL, "item");
  550. key = xmlNewNode(NULL, "key");
  551. if(zend_hash_get_current_key(data->value.ht, &key_val, (long *)&int_val, FALSE) == HASH_KEY_IS_STRING)
  552. {
  553. if(style == SOAP_ENCODED)
  554. xmlSetProp(key, "xsi:type", "xsd:string");
  555. xmlNodeSetContent(key, key_val);
  556. }
  557. else
  558. {
  559. smart_str tmp = {0};
  560. smart_str_append_long(&tmp, int_val);
  561. smart_str_0(&tmp);
  562. if(style == SOAP_ENCODED)
  563. xmlSetProp(key, "xsi:type", "xsd:int");
  564. xmlNodeSetContentLen(key, tmp.c, tmp.len);
  565. smart_str_free(&tmp);
  566. }
  567. enc = get_conversion((*temp_data)->type);
  568. xparam = master_to_xml(enc, (*temp_data), style);
  569. xmlNodeSetName(xparam, "value");
  570. xmlAddChild(item, key);
  571. xmlAddChild(item, xparam);
  572. xmlAddChild(xmlParam, item);
  573. }
  574. zend_hash_move_forward(data->value.ht);
  575. }
  576. }
  577. if(style == SOAP_ENCODED)
  578. set_ns_and_type(xmlParam, type);
  579. return xmlParam;
  580. }
  581. zval *to_zval_map(encodeType type, xmlNodePtr data)
  582. {
  583. zval *ret, *key, *value;
  584. xmlNodePtr trav, item, xmlKey, xmlValue;
  585. encodePtr enc;
  586. TSRMLS_FETCH();
  587. MAKE_STD_ZVAL(ret);
  588. FIND_XML_NULL(data, ret);
  589. array_init(ret);
  590. trav = data->children;
  591. enc = get_conversion(UNKNOWN_TYPE);
  592. trav = data->children;
  593. FOREACHNODE(trav, "item", item)
  594. {
  595. xmlKey = get_node(item->children, "key");
  596. if(!xmlKey)
  597. php_error(E_ERROR, "Error encoding apache map, missing key");
  598. xmlValue = get_node(item->children, "value");
  599. if(!xmlKey)
  600. php_error(E_ERROR, "Error encoding apache map, missing value");
  601. key = master_to_zval(enc, xmlKey);
  602. value = master_to_zval(enc, xmlValue);
  603. if(Z_TYPE_P(key) == IS_STRING)
  604. zend_hash_update(Z_ARRVAL_P(ret), Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof(zval *), NULL);
  605. else if(Z_TYPE_P(key) == IS_LONG)
  606. zend_hash_index_update(Z_ARRVAL_P(ret), Z_LVAL_P(key), &value, sizeof(zval *), NULL);
  607. else
  608. php_error(E_ERROR, "Error encoding apache map, only Strings or Longs are allowd as keys");
  609. }
  610. ENDFOREACH(trav);
  611. return ret;
  612. }
  613. //Unknown encode/decode
  614. xmlNodePtr guess_xml_convert(encodeType type, zval *data, int style)
  615. {
  616. encodePtr enc;
  617. TSRMLS_FETCH();
  618. if(data)
  619. enc = get_conversion(data->type);
  620. else
  621. enc = get_conversion(IS_NULL);
  622. return master_to_xml(enc, data, style);
  623. }
  624. zval *guess_zval_convert(encodeType type, xmlNodePtr data)
  625. {
  626. encodePtr enc = NULL;
  627. xmlAttrPtr tmpattr;
  628. TSRMLS_FETCH();
  629. data = check_and_resolve_href(data);
  630. if(data == NULL || data->children == NULL)
  631. enc = get_conversion(IS_NULL);
  632. else
  633. {
  634. tmpattr = get_attribute(data->properties,"type");
  635. if(tmpattr != NULL)
  636. {
  637. enc = get_conversion_from_type(data, tmpattr->children->content);
  638. // if(enc == NULL)
  639. // php_error(E_ERROR, "Error (Don't know how to encode/decode \"%s\")", tmpattr->children->content);
  640. }
  641. if(enc == NULL)
  642. {
  643. //Didn't have a type, totally guess here
  644. //Logic: has children = IS_OBJECT else IS_STRING
  645. xmlNodePtr trav;
  646. if(get_attribute(data->properties, "arrayType"))
  647. enc = get_conversion(SOAP_ENC_ARRAY);
  648. else
  649. {
  650. enc = get_conversion(XSD_STRING);
  651. trav = data->children;
  652. do
  653. {
  654. if(trav->type == XML_ELEMENT_NODE)
  655. {
  656. enc = get_conversion(SOAP_ENC_OBJECT);
  657. break;
  658. }
  659. }
  660. while(trav = trav->next);
  661. }
  662. }
  663. }
  664. return master_to_zval(enc, data);
  665. }
  666. //Time encode/decode
  667. xmlNodePtr to_xml_datetime_ex(encodeType type, zval *data, char *format, int style)
  668. {
  669. //logic hacked from ext/standard/datetime.c
  670. struct tm *ta, tmbuf;
  671. time_t timestamp;
  672. int max_reallocs = 5;
  673. size_t buf_len=64, real_len;
  674. char *buf;
  675. xmlNodePtr xmlParam;
  676. xmlParam = xmlNewNode(NULL, "BOGUS");
  677. FIND_ZVAL_NULL(data, xmlParam);
  678. timestamp = Z_LVAL_P(data);
  679. time(&timestamp);
  680. ta = php_localtime_r(&timestamp, &tmbuf);
  681. buf = (char *) emalloc(buf_len);
  682. while ((real_len = strftime(buf, buf_len, format, ta)) == buf_len || real_len == 0)
  683. {
  684. buf_len *= 2;
  685. buf = (char *) erealloc(buf, buf_len);
  686. if(!--max_reallocs) break;
  687. }
  688. xmlNodeSetContent(xmlParam, buf);
  689. efree(buf);
  690. if(style == SOAP_ENCODED)
  691. set_ns_and_type(xmlParam, type);
  692. return xmlParam;
  693. }
  694. xmlNodePtr to_xml_datetime(encodeType type, zval *data, int style)
  695. {
  696. return to_xml_datetime_ex(type, data, "%Y-%m-%dT%H:%M:%S", style);
  697. }
  698. xmlNodePtr to_xml_time(encodeType type, zval *data, int style)
  699. {
  700. return to_xml_datetime_ex(type, data, "%H:%M:%S", style);
  701. }
  702. xmlNodePtr to_xml_date(encodeType type, zval *data, int style)
  703. {
  704. return to_xml_datetime_ex(type, data, "%Y-%m-%d", style);
  705. }
  706. xmlNodePtr to_xml_gyearmonth(encodeType type, zval *data, int style)
  707. {
  708. return to_xml_datetime_ex(type, data, "%Y-%m", style);
  709. }
  710. xmlNodePtr to_xml_gyear(encodeType type, zval *data, int style)
  711. {
  712. return to_xml_datetime_ex(type, data, "%Y", style);
  713. }
  714. xmlNodePtr to_xml_gmonthday(encodeType type, zval *data, int style)
  715. {
  716. return to_xml_datetime_ex(type, data, "--%m-%d", style);
  717. }
  718. xmlNodePtr to_xml_gday(encodeType type, zval *data, int style)
  719. {
  720. return to_xml_datetime_ex(type, data, "%d", style);
  721. }
  722. xmlNodePtr to_xml_gmonth(encodeType type, zval *data, int style)
  723. {
  724. return to_xml_datetime_ex(type, data, "%m", style);
  725. }
  726. void set_ns_and_type(xmlNodePtr node, encodeType type)
  727. {
  728. set_ns_and_type_ex(node, type.ns, type.type_str);
  729. }
  730. void set_ns_and_type_ex(xmlNodePtr node, char *ns, char *type)
  731. {
  732. if(ns != NULL)
  733. {
  734. char *sprefix;
  735. smart_str *prefix;
  736. smart_str xmlns = {0}, nstype = {0};
  737. TSRMLS_FETCH();
  738. if(zend_hash_find(SOAP_GLOBAL(defEncNs), ns, strlen(ns) + 1, (void **)&sprefix) == FAILURE)
  739. {
  740. prefix = encode_new_ns();
  741. smart_str_appendl(&xmlns, "xmlns:", 6);
  742. smart_str_append(&xmlns, prefix);
  743. smart_str_0(&xmlns);
  744. xmlSetProp(node, xmlns.c, ns);
  745. }
  746. else
  747. {
  748. prefix = emalloc(sizeof(smart_str));
  749. memset(prefix, 0, sizeof(smart_str));
  750. smart_str_appends(prefix, sprefix);
  751. }
  752. smart_str_append(&nstype, prefix);
  753. smart_str_appendc(&nstype, ':');
  754. smart_str_appends(&nstype, type);
  755. smart_str_0(&nstype);
  756. xmlSetProp(node, "xsi:type", nstype.c);
  757. smart_str_free(&nstype);
  758. smart_str_free(&xmlns);
  759. smart_str_free(prefix);
  760. efree(prefix);
  761. }
  762. else
  763. xmlSetProp(node, "xsi:type", type);
  764. }
  765. smart_str *encode_new_ns()
  766. {
  767. int num;
  768. smart_str *ns = emalloc(sizeof(smart_str));
  769. TSRMLS_FETCH();
  770. memset(ns, 0, sizeof(smart_str));
  771. num = ++SOAP_GLOBAL(cur_uniq_ns);
  772. smart_str_appendl(ns, "ns", 2);
  773. smart_str_append_long(ns, num);
  774. smart_str_0(ns);
  775. return ns;
  776. }
  777. void encode_reset_ns()
  778. {
  779. TSRMLS_FETCH();
  780. SOAP_GLOBAL(cur_uniq_ns) = 0;
  781. }
  782. encodePtr get_conversion_ex(HashTable *encoding, int encode)
  783. {
  784. encodePtr *enc;
  785. TSRMLS_FETCH();
  786. if(zend_hash_index_find(encoding, encode, (void **)&enc) == FAILURE)
  787. php_error(E_ERROR, "Cannot find encoding");
  788. if(SOAP_GLOBAL(overrides))
  789. {
  790. smart_str nscat = {0};
  791. smart_str_appendl(&nscat, (*enc)->details.ns, strlen((*enc)->details.ns));
  792. smart_str_appendc(&nscat, ':');
  793. smart_str_appendl(&nscat, (*enc)->details.type_str, strlen((*enc)->details.type_str));
  794. smart_str_0(&nscat);
  795. zend_hash_find(SOAP_GLOBAL(overrides), nscat.c, nscat.len + 1, (void **)&enc);
  796. smart_str_free(&nscat);
  797. }
  798. return *enc;
  799. }
  800. encodePtr get_conversion_from_href_type_ex(HashTable *encoding, char *type, int len)
  801. {
  802. encodePtr *enc = NULL;
  803. if(encoding == NULL)
  804. return NULL;
  805. if(zend_hash_find(encoding, type, len + 1, (void **)&enc) == FAILURE)
  806. return NULL;
  807. return (*enc);
  808. }
  809. encodePtr get_conversion_from_type_ex(HashTable *encoding, xmlNodePtr node, char *type)
  810. {
  811. encodePtr *enc = NULL;
  812. xmlNsPtr nsptr;
  813. char *ns, *cptype;
  814. smart_str nscat = {0};
  815. if(encoding == NULL)
  816. return NULL;
  817. parse_namespace(type, &cptype, &ns);
  818. nsptr = xmlSearchNs(node->doc, node, ns);
  819. if(nsptr != NULL)
  820. {
  821. smart_str_appends(&nscat, nsptr->href);
  822. smart_str_appendc(&nscat, ':');
  823. smart_str_appends(&nscat, cptype);
  824. smart_str_0(&nscat);
  825. if(zend_hash_find(encoding, nscat.c, nscat.len + 1, (void **)&enc) == FAILURE)
  826. {
  827. if(zend_hash_find(encoding, type, strlen(type) + 1, (void **)&enc) == FAILURE)
  828. enc = NULL;
  829. }
  830. smart_str_free(&nscat);
  831. }
  832. else
  833. {
  834. if(zend_hash_find(encoding, type, strlen(type) + 1, (void **)&enc) == FAILURE)
  835. enc = NULL;
  836. }
  837. if(cptype) efree(cptype);
  838. if(ns) efree(ns);
  839. if(enc == NULL)
  840. return NULL;
  841. else
  842. return (*enc);
  843. }
  844. int is_map(zval *array)
  845. {
  846. int i, count = zend_hash_num_elements(Z_ARRVAL_P(array));
  847. for(i = 0;i < count;i++)
  848. {
  849. if(zend_hash_get_current_key_type(Z_ARRVAL_P(array)) == HASH_KEY_IS_STRING)
  850. return TRUE;
  851. zend_hash_move_forward(Z_ARRVAL_P(array));
  852. }
  853. return FALSE;
  854. }
  855. void get_array_type(zval *array, smart_str *type)
  856. {
  857. HashTable *ht = array->value.ht;
  858. int i, count, cur_type, prev_type, different;
  859. char *name = NULL;
  860. zval **tmp;
  861. TSRMLS_FETCH();
  862. if(!array || Z_TYPE_P(array) != IS_ARRAY)
  863. smart_str_appendl(type, "xsd:ur-type", 11);
  864. different = FALSE;
  865. cur_type = prev_type = 0;
  866. count = zend_hash_num_elements(ht);
  867. zend_hash_internal_pointer_reset(ht);
  868. for(i = 0;i < count;i++)
  869. {
  870. zend_hash_get_current_data(ht, (void **)&tmp);
  871. if(Z_TYPE_PP(tmp) == IS_OBJECT && !strcmp(Z_OBJCE_PP(tmp)->name, soap_var_class_entry.name))
  872. {
  873. zval **ztype;
  874. if(zend_hash_find(Z_OBJPROP_PP(tmp), "enc_type", sizeof("enc_type"), (void **)&ztype) == FAILURE)
  875. php_error(E_ERROR, "error encoding SoapVar");
  876. cur_type = Z_LVAL_P(*ztype);
  877. }
  878. else if(Z_TYPE_PP(tmp) == IS_ARRAY && is_map(*tmp))
  879. cur_type = APACHE_MAP;
  880. else
  881. cur_type = Z_TYPE_PP(tmp);
  882. if(i > 0)
  883. {
  884. if(cur_type != prev_type)
  885. {
  886. different = TRUE;
  887. break;
  888. }
  889. }
  890. prev_type = cur_type;
  891. zend_hash_move_forward(ht);
  892. }
  893. if(different)
  894. smart_str_appendl(type, "xsd:ur-type", 11);
  895. else
  896. {
  897. encodePtr enc;
  898. char *prefix;
  899. enc = get_conversion(cur_type);
  900. if(enc->details.ns != NULL)
  901. {
  902. if(zend_hash_find(SOAP_GLOBAL(defEncNs), enc->details.ns, strlen(enc->details.ns) + 1, (void **)&prefix) == FAILURE)
  903. php_error(E_ERROR, "fix me");
  904. smart_str_appendl(type, prefix, strlen(prefix));
  905. smart_str_appendc(type, ':');
  906. smart_str_appendl(type, enc->details.type_str, strlen(enc->details.type_str));
  907. smart_str_0(type);
  908. }
  909. else
  910. smart_str_appendl(type, enc->details.type_str, strlen(enc->details.type_str));
  911. }
  912. }
  913. smart_str *build_soap_action(zval *this_ptr, char *soapaction)
  914. {
  915. zval **uri;
  916. smart_str *tmp;
  917. tmp = emalloc(sizeof(smart_str));
  918. memset(tmp, 0, sizeof(smart_str));
  919. if(zend_hash_find(Z_OBJPROP_P(this_ptr), "uri", sizeof("uri"), (void *)&uri) == FAILURE)
  920. php_error(E_ERROR, "Error finding uri");
  921. smart_str_appendl(tmp, Z_STRVAL_PP(uri), Z_STRLEN_PP(uri));
  922. smart_str_appends(tmp, "#");
  923. smart_str_appendl(tmp, soapaction, strlen(soapaction));
  924. smart_str_0(tmp);
  925. return tmp;
  926. }
  927. void delete_encoder(void *encode)
  928. {
  929. encodePtr t = *((encodePtr*)encode);
  930. if(t->details.ns)
  931. free(t->details.ns);
  932. if(t->details.type_str)
  933. free(t->details.type_str);
  934. if(t->details.map)
  935. delete_mapping(t->details.map);
  936. free(t);
  937. }