PageRenderTime 63ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/ext/wddx/wddx.c

http://github.com/infusion/PHP
C | 1367 lines | 996 code | 223 blank | 148 comment | 233 complexity | 4da4774146b6e8725d91ede7deb06201 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2011 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Andrei Zmievski <andrei@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id: wddx.c 306939 2011-01-01 02:19:59Z felipe $ */
  19. #ifdef HAVE_CONFIG_H
  20. #include "config.h"
  21. #endif
  22. #include "php.h"
  23. #if HAVE_WDDX
  24. #include "ext/xml/expat_compat.h"
  25. #include "php_wddx.h"
  26. #include "php_wddx_api.h"
  27. #define PHP_XML_INTERNAL
  28. #include "ext/xml/php_xml.h"
  29. #include "ext/standard/php_incomplete_class.h"
  30. #include "ext/standard/base64.h"
  31. #include "ext/standard/info.h"
  32. #include "ext/standard/php_smart_str.h"
  33. #include "ext/standard/html.h"
  34. #include "ext/standard/php_string.h"
  35. #include "ext/date/php_date.h"
  36. #include "zend_globals.h"
  37. #define WDDX_BUF_LEN 256
  38. #define PHP_CLASS_NAME_VAR "php_class_name"
  39. #define EL_ARRAY "array"
  40. #define EL_BINARY "binary"
  41. #define EL_BOOLEAN "boolean"
  42. #define EL_CHAR "char"
  43. #define EL_CHAR_CODE "code"
  44. #define EL_NULL "null"
  45. #define EL_NUMBER "number"
  46. #define EL_PACKET "wddxPacket"
  47. #define EL_STRING "string"
  48. #define EL_STRUCT "struct"
  49. #define EL_VALUE "value"
  50. #define EL_VAR "var"
  51. #define EL_NAME "name"
  52. #define EL_VERSION "version"
  53. #define EL_RECORDSET "recordset"
  54. #define EL_FIELD "field"
  55. #define EL_DATETIME "dateTime"
  56. #define php_wddx_deserialize(a,b) \
  57. php_wddx_deserialize_ex((a)->value.str.val, (a)->value.str.len, (b))
  58. #define SET_STACK_VARNAME \
  59. if (stack->varname) { \
  60. ent.varname = estrdup(stack->varname); \
  61. efree(stack->varname); \
  62. stack->varname = NULL; \
  63. } else \
  64. ent.varname = NULL; \
  65. static int le_wddx;
  66. typedef struct {
  67. zval *data;
  68. enum {
  69. ST_ARRAY,
  70. ST_BOOLEAN,
  71. ST_NULL,
  72. ST_NUMBER,
  73. ST_STRING,
  74. ST_BINARY,
  75. ST_STRUCT,
  76. ST_RECORDSET,
  77. ST_FIELD,
  78. ST_DATETIME
  79. } type;
  80. char *varname;
  81. } st_entry;
  82. typedef struct {
  83. int top, max;
  84. char *varname;
  85. zend_bool done;
  86. void **elements;
  87. } wddx_stack;
  88. static void php_wddx_process_data(void *user_data, const XML_Char *s, int len);
  89. /* {{{ arginfo */
  90. ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_serialize_value, 0, 0, 1)
  91. ZEND_ARG_INFO(0, var)
  92. ZEND_ARG_INFO(0, comment)
  93. ZEND_END_ARG_INFO()
  94. ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_serialize_vars, 0, 0, 1)
  95. ZEND_ARG_INFO(0, var_name)
  96. ZEND_ARG_INFO(0, ...)
  97. ZEND_END_ARG_INFO()
  98. ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_serialize_start, 0, 0, 0)
  99. ZEND_ARG_INFO(0, comment)
  100. ZEND_END_ARG_INFO()
  101. ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_packet_end, 0, 0, 1)
  102. ZEND_ARG_INFO(0, packet_id)
  103. ZEND_END_ARG_INFO()
  104. ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_add_vars, 0, 0, 2)
  105. ZEND_ARG_INFO(0, packet_id)
  106. ZEND_ARG_INFO(0, var_name)
  107. ZEND_ARG_INFO(0, ...)
  108. ZEND_END_ARG_INFO()
  109. ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_deserialize, 0, 0, 1)
  110. ZEND_ARG_INFO(0, packet)
  111. ZEND_END_ARG_INFO()
  112. /* }}} */
  113. /* {{{ wddx_functions[]
  114. */
  115. const zend_function_entry wddx_functions[] = {
  116. PHP_FE(wddx_serialize_value, arginfo_wddx_serialize_value)
  117. PHP_FE(wddx_serialize_vars, arginfo_wddx_serialize_vars)
  118. PHP_FE(wddx_packet_start, arginfo_wddx_serialize_start)
  119. PHP_FE(wddx_packet_end, arginfo_wddx_packet_end)
  120. PHP_FE(wddx_add_vars, arginfo_wddx_add_vars)
  121. PHP_FE(wddx_deserialize, arginfo_wddx_deserialize)
  122. {NULL, NULL, NULL}
  123. };
  124. /* }}} */
  125. PHP_MINIT_FUNCTION(wddx);
  126. PHP_MINFO_FUNCTION(wddx);
  127. /* {{{ dynamically loadable module stuff */
  128. #ifdef COMPILE_DL_WDDX
  129. ZEND_GET_MODULE(wddx)
  130. #endif /* COMPILE_DL_WDDX */
  131. /* }}} */
  132. /* {{{ wddx_module_entry
  133. */
  134. zend_module_entry wddx_module_entry = {
  135. STANDARD_MODULE_HEADER,
  136. "wddx",
  137. wddx_functions,
  138. PHP_MINIT(wddx),
  139. NULL,
  140. NULL,
  141. NULL,
  142. PHP_MINFO(wddx),
  143. NO_VERSION_YET,
  144. STANDARD_MODULE_PROPERTIES
  145. };
  146. /* }}} */
  147. /* {{{ wddx_stack_init
  148. */
  149. static int wddx_stack_init(wddx_stack *stack)
  150. {
  151. stack->top = 0;
  152. stack->elements = (void **) safe_emalloc(sizeof(void **), STACK_BLOCK_SIZE, 0);
  153. stack->max = STACK_BLOCK_SIZE;
  154. stack->varname = NULL;
  155. stack->done = 0;
  156. return SUCCESS;
  157. }
  158. /* }}} */
  159. /* {{{ wddx_stack_push
  160. */
  161. static int wddx_stack_push(wddx_stack *stack, void *element, int size)
  162. {
  163. if (stack->top >= stack->max) { /* we need to allocate more memory */
  164. stack->elements = (void **) erealloc(stack->elements,
  165. (sizeof(void **) * (stack->max += STACK_BLOCK_SIZE)));
  166. }
  167. stack->elements[stack->top] = (void *) emalloc(size);
  168. memcpy(stack->elements[stack->top], element, size);
  169. return stack->top++;
  170. }
  171. /* }}} */
  172. /* {{{ wddx_stack_top
  173. */
  174. static int wddx_stack_top(wddx_stack *stack, void **element)
  175. {
  176. if (stack->top > 0) {
  177. *element = stack->elements[stack->top - 1];
  178. return SUCCESS;
  179. } else {
  180. *element = NULL;
  181. return FAILURE;
  182. }
  183. }
  184. /* }}} */
  185. /* {{{ wddx_stack_is_empty
  186. */
  187. static int wddx_stack_is_empty(wddx_stack *stack)
  188. {
  189. if (stack->top == 0) {
  190. return 1;
  191. } else {
  192. return 0;
  193. }
  194. }
  195. /* }}} */
  196. /* {{{ wddx_stack_destroy
  197. */
  198. static int wddx_stack_destroy(wddx_stack *stack)
  199. {
  200. register int i;
  201. if (stack->elements) {
  202. for (i = 0; i < stack->top; i++) {
  203. if (((st_entry *)stack->elements[i])->data) {
  204. zval_ptr_dtor(&((st_entry *)stack->elements[i])->data);
  205. }
  206. if (((st_entry *)stack->elements[i])->varname) {
  207. efree(((st_entry *)stack->elements[i])->varname);
  208. }
  209. efree(stack->elements[i]);
  210. }
  211. efree(stack->elements);
  212. }
  213. return SUCCESS;
  214. }
  215. /* }}} */
  216. /* {{{ release_wddx_packet_rsrc
  217. */
  218. static void release_wddx_packet_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC)
  219. {
  220. smart_str *str = (smart_str *)rsrc->ptr;
  221. smart_str_free(str);
  222. efree(str);
  223. }
  224. /* }}} */
  225. #include "ext/session/php_session.h"
  226. #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
  227. /* {{{ PS_SERIALIZER_ENCODE_FUNC
  228. */
  229. PS_SERIALIZER_ENCODE_FUNC(wddx)
  230. {
  231. wddx_packet *packet;
  232. PS_ENCODE_VARS;
  233. packet = php_wddx_constructor();
  234. php_wddx_packet_start(packet, NULL, 0);
  235. php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
  236. PS_ENCODE_LOOP(
  237. php_wddx_serialize_var(packet, *struc, key, key_length TSRMLS_CC);
  238. );
  239. php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
  240. php_wddx_packet_end(packet);
  241. *newstr = php_wddx_gather(packet);
  242. php_wddx_destructor(packet);
  243. if (newlen) {
  244. *newlen = strlen(*newstr);
  245. }
  246. return SUCCESS;
  247. }
  248. /* }}} */
  249. /* {{{ PS_SERIALIZER_DECODE_FUNC
  250. */
  251. PS_SERIALIZER_DECODE_FUNC(wddx)
  252. {
  253. zval *retval;
  254. zval **ent;
  255. char *key;
  256. uint key_length;
  257. char tmp[128];
  258. ulong idx;
  259. int hash_type;
  260. int ret;
  261. if (vallen == 0) {
  262. return SUCCESS;
  263. }
  264. MAKE_STD_ZVAL(retval);
  265. if ((ret = php_wddx_deserialize_ex((char *)val, vallen, retval)) == SUCCESS) {
  266. for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(retval));
  267. zend_hash_get_current_data(Z_ARRVAL_P(retval), (void **) &ent) == SUCCESS;
  268. zend_hash_move_forward(Z_ARRVAL_P(retval))) {
  269. hash_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(retval), &key, &key_length, &idx, 0, NULL);
  270. switch (hash_type) {
  271. case HASH_KEY_IS_LONG:
  272. key_length = slprintf(tmp, sizeof(tmp), "%ld", idx) + 1;
  273. key = tmp;
  274. /* fallthru */
  275. case HASH_KEY_IS_STRING:
  276. php_set_session_var(key, key_length-1, *ent, NULL TSRMLS_CC);
  277. PS_ADD_VAR(key);
  278. }
  279. }
  280. }
  281. zval_ptr_dtor(&retval);
  282. return ret;
  283. }
  284. /* }}} */
  285. #endif
  286. /* {{{ PHP_MINIT_FUNCTION
  287. */
  288. PHP_MINIT_FUNCTION(wddx)
  289. {
  290. le_wddx = zend_register_list_destructors_ex(release_wddx_packet_rsrc, NULL, "wddx", module_number);
  291. #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
  292. php_session_register_serializer("wddx",
  293. PS_SERIALIZER_ENCODE_NAME(wddx),
  294. PS_SERIALIZER_DECODE_NAME(wddx));
  295. #endif
  296. return SUCCESS;
  297. }
  298. /* }}} */
  299. /* {{{ PHP_MINFO_FUNCTION
  300. */
  301. PHP_MINFO_FUNCTION(wddx)
  302. {
  303. php_info_print_table_start();
  304. #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
  305. php_info_print_table_header(2, "WDDX Support", "enabled" );
  306. php_info_print_table_row(2, "WDDX Session Serializer", "enabled" );
  307. #else
  308. php_info_print_table_row(2, "WDDX Support", "enabled" );
  309. #endif
  310. php_info_print_table_end();
  311. }
  312. /* }}} */
  313. /* {{{ php_wddx_packet_start
  314. */
  315. void php_wddx_packet_start(wddx_packet *packet, char *comment, int comment_len)
  316. {
  317. php_wddx_add_chunk_static(packet, WDDX_PACKET_S);
  318. if (comment) {
  319. php_wddx_add_chunk_static(packet, WDDX_HEADER_S);
  320. php_wddx_add_chunk_static(packet, WDDX_COMMENT_S);
  321. php_wddx_add_chunk_ex(packet, comment, comment_len);
  322. php_wddx_add_chunk_static(packet, WDDX_COMMENT_E);
  323. php_wddx_add_chunk_static(packet, WDDX_HEADER_E);
  324. } else {
  325. php_wddx_add_chunk_static(packet, WDDX_HEADER);
  326. }
  327. php_wddx_add_chunk_static(packet, WDDX_DATA_S);
  328. }
  329. /* }}} */
  330. /* {{{ php_wddx_packet_end
  331. */
  332. void php_wddx_packet_end(wddx_packet *packet)
  333. {
  334. php_wddx_add_chunk_static(packet, WDDX_DATA_E);
  335. php_wddx_add_chunk_static(packet, WDDX_PACKET_E);
  336. }
  337. /* }}} */
  338. #define FLUSH_BUF() \
  339. if (l > 0) { \
  340. php_wddx_add_chunk_ex(packet, buf, l); \
  341. l = 0; \
  342. }
  343. /* {{{ php_wddx_serialize_string
  344. */
  345. static void php_wddx_serialize_string(wddx_packet *packet, zval *var TSRMLS_DC)
  346. {
  347. php_wddx_add_chunk_static(packet, WDDX_STRING_S);
  348. if (Z_STRLEN_P(var) > 0) {
  349. char *buf;
  350. int buf_len;
  351. buf = php_escape_html_entities(Z_STRVAL_P(var), Z_STRLEN_P(var), &buf_len, 0, ENT_QUOTES, NULL TSRMLS_CC);
  352. php_wddx_add_chunk_ex(packet, buf, buf_len);
  353. efree(buf);
  354. }
  355. php_wddx_add_chunk_static(packet, WDDX_STRING_E);
  356. }
  357. /* }}} */
  358. /* {{{ php_wddx_serialize_number
  359. */
  360. static void php_wddx_serialize_number(wddx_packet *packet, zval *var)
  361. {
  362. char tmp_buf[WDDX_BUF_LEN];
  363. zval tmp;
  364. tmp = *var;
  365. zval_copy_ctor(&tmp);
  366. convert_to_string(&tmp);
  367. snprintf(tmp_buf, sizeof(tmp_buf), WDDX_NUMBER, Z_STRVAL(tmp));
  368. zval_dtor(&tmp);
  369. php_wddx_add_chunk(packet, tmp_buf);
  370. }
  371. /* }}} */
  372. /* {{{ php_wddx_serialize_boolean
  373. */
  374. static void php_wddx_serialize_boolean(wddx_packet *packet, zval *var)
  375. {
  376. php_wddx_add_chunk(packet, Z_LVAL_P(var) ? WDDX_BOOLEAN_TRUE : WDDX_BOOLEAN_FALSE);
  377. }
  378. /* }}} */
  379. /* {{{ php_wddx_serialize_unset
  380. */
  381. static void php_wddx_serialize_unset(wddx_packet *packet)
  382. {
  383. php_wddx_add_chunk_static(packet, WDDX_NULL);
  384. }
  385. /* }}} */
  386. /* {{{ php_wddx_serialize_object
  387. */
  388. static void php_wddx_serialize_object(wddx_packet *packet, zval *obj)
  389. {
  390. /* OBJECTS_FIXME */
  391. zval **ent, *fname, **varname;
  392. zval *retval = NULL;
  393. char *key;
  394. ulong idx;
  395. char tmp_buf[WDDX_BUF_LEN];
  396. HashTable *objhash, *sleephash;
  397. TSRMLS_FETCH();
  398. MAKE_STD_ZVAL(fname);
  399. ZVAL_STRING(fname, "__sleep", 1);
  400. /*
  401. * We try to call __sleep() method on object. It's supposed to return an
  402. * array of property names to be serialized.
  403. */
  404. if (call_user_function_ex(CG(function_table), &obj, fname, &retval, 0, 0, 1, NULL TSRMLS_CC) == SUCCESS) {
  405. if (retval && (sleephash = HASH_OF(retval))) {
  406. PHP_CLASS_ATTRIBUTES;
  407. PHP_SET_CLASS_ATTRIBUTES(obj);
  408. php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
  409. snprintf(tmp_buf, WDDX_BUF_LEN, WDDX_VAR_S, PHP_CLASS_NAME_VAR);
  410. php_wddx_add_chunk(packet, tmp_buf);
  411. php_wddx_add_chunk_static(packet, WDDX_STRING_S);
  412. php_wddx_add_chunk_ex(packet, class_name, name_len);
  413. php_wddx_add_chunk_static(packet, WDDX_STRING_E);
  414. php_wddx_add_chunk_static(packet, WDDX_VAR_E);
  415. PHP_CLEANUP_CLASS_ATTRIBUTES();
  416. objhash = HASH_OF(obj);
  417. for (zend_hash_internal_pointer_reset(sleephash);
  418. zend_hash_get_current_data(sleephash, (void **)&varname) == SUCCESS;
  419. zend_hash_move_forward(sleephash)) {
  420. if (Z_TYPE_PP(varname) != IS_STRING) {
  421. php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array only containing the names of instance-variables to serialize.");
  422. continue;
  423. }
  424. if (zend_hash_find(objhash, Z_STRVAL_PP(varname), Z_STRLEN_PP(varname)+1, (void **)&ent) == SUCCESS) {
  425. php_wddx_serialize_var(packet, *ent, Z_STRVAL_PP(varname), Z_STRLEN_PP(varname) TSRMLS_CC);
  426. }
  427. }
  428. php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
  429. }
  430. } else {
  431. uint key_len;
  432. PHP_CLASS_ATTRIBUTES;
  433. PHP_SET_CLASS_ATTRIBUTES(obj);
  434. php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
  435. snprintf(tmp_buf, WDDX_BUF_LEN, WDDX_VAR_S, PHP_CLASS_NAME_VAR);
  436. php_wddx_add_chunk(packet, tmp_buf);
  437. php_wddx_add_chunk_static(packet, WDDX_STRING_S);
  438. php_wddx_add_chunk_ex(packet, class_name, name_len);
  439. php_wddx_add_chunk_static(packet, WDDX_STRING_E);
  440. php_wddx_add_chunk_static(packet, WDDX_VAR_E);
  441. PHP_CLEANUP_CLASS_ATTRIBUTES();
  442. objhash = HASH_OF(obj);
  443. for (zend_hash_internal_pointer_reset(objhash);
  444. zend_hash_get_current_data(objhash, (void**)&ent) == SUCCESS;
  445. zend_hash_move_forward(objhash)) {
  446. if (*ent == obj) {
  447. continue;
  448. }
  449. if (zend_hash_get_current_key_ex(objhash, &key, &key_len, &idx, 0, NULL) == HASH_KEY_IS_STRING) {
  450. char *class_name, *prop_name;
  451. zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
  452. php_wddx_serialize_var(packet, *ent, prop_name, strlen(prop_name)+1 TSRMLS_CC);
  453. } else {
  454. key_len = slprintf(tmp_buf, sizeof(tmp_buf), "%ld", idx);
  455. php_wddx_serialize_var(packet, *ent, tmp_buf, key_len TSRMLS_CC);
  456. }
  457. }
  458. php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
  459. }
  460. zval_dtor(fname);
  461. FREE_ZVAL(fname);
  462. if (retval) {
  463. zval_ptr_dtor(&retval);
  464. }
  465. }
  466. /* }}} */
  467. /* {{{ php_wddx_serialize_array
  468. */
  469. static void php_wddx_serialize_array(wddx_packet *packet, zval *arr)
  470. {
  471. zval **ent;
  472. char *key;
  473. uint key_len;
  474. int is_struct = 0, ent_type;
  475. ulong idx;
  476. HashTable *target_hash;
  477. char tmp_buf[WDDX_BUF_LEN];
  478. ulong ind = 0;
  479. int type;
  480. TSRMLS_FETCH();
  481. target_hash = HASH_OF(arr);
  482. for (zend_hash_internal_pointer_reset(target_hash);
  483. zend_hash_get_current_data(target_hash, (void**)&ent) == SUCCESS;
  484. zend_hash_move_forward(target_hash)) {
  485. type = zend_hash_get_current_key(target_hash, &key, &idx, 0);
  486. if (type == HASH_KEY_IS_STRING) {
  487. is_struct = 1;
  488. break;
  489. }
  490. if (idx != ind) {
  491. is_struct = 1;
  492. break;
  493. }
  494. ind++;
  495. }
  496. if (is_struct) {
  497. php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
  498. } else {
  499. snprintf(tmp_buf, sizeof(tmp_buf), WDDX_ARRAY_S, zend_hash_num_elements(target_hash));
  500. php_wddx_add_chunk(packet, tmp_buf);
  501. }
  502. for (zend_hash_internal_pointer_reset(target_hash);
  503. zend_hash_get_current_data(target_hash, (void**)&ent) == SUCCESS;
  504. zend_hash_move_forward(target_hash)) {
  505. if (*ent == arr) {
  506. continue;
  507. }
  508. if (is_struct) {
  509. ent_type = zend_hash_get_current_key_ex(target_hash, &key, &key_len, &idx, 0, NULL);
  510. if (ent_type == HASH_KEY_IS_STRING) {
  511. php_wddx_serialize_var(packet, *ent, key, key_len TSRMLS_CC);
  512. } else {
  513. key_len = slprintf(tmp_buf, sizeof(tmp_buf), "%ld", idx);
  514. php_wddx_serialize_var(packet, *ent, tmp_buf, key_len TSRMLS_CC);
  515. }
  516. } else {
  517. php_wddx_serialize_var(packet, *ent, NULL, 0 TSRMLS_CC);
  518. }
  519. }
  520. if (is_struct) {
  521. php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
  522. } else {
  523. php_wddx_add_chunk_static(packet, WDDX_ARRAY_E);
  524. }
  525. }
  526. /* }}} */
  527. /* {{{ php_wddx_serialize_var
  528. */
  529. void php_wddx_serialize_var(wddx_packet *packet, zval *var, char *name, int name_len TSRMLS_DC)
  530. {
  531. char *tmp_buf;
  532. char *name_esc;
  533. int name_esc_len;
  534. HashTable *ht;
  535. if (name) {
  536. name_esc = php_escape_html_entities(name, name_len, &name_esc_len, 0, ENT_QUOTES, NULL TSRMLS_CC);
  537. tmp_buf = emalloc(name_esc_len + sizeof(WDDX_VAR_S));
  538. snprintf(tmp_buf, name_esc_len + sizeof(WDDX_VAR_S), WDDX_VAR_S, name_esc);
  539. php_wddx_add_chunk(packet, tmp_buf);
  540. efree(tmp_buf);
  541. efree(name_esc);
  542. }
  543. switch(Z_TYPE_P(var)) {
  544. case IS_STRING:
  545. php_wddx_serialize_string(packet, var TSRMLS_CC);
  546. break;
  547. case IS_LONG:
  548. case IS_DOUBLE:
  549. php_wddx_serialize_number(packet, var);
  550. break;
  551. case IS_BOOL:
  552. php_wddx_serialize_boolean(packet, var);
  553. break;
  554. case IS_NULL:
  555. php_wddx_serialize_unset(packet);
  556. break;
  557. case IS_ARRAY:
  558. ht = Z_ARRVAL_P(var);
  559. if (ht->nApplyCount > 1) {
  560. php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "WDDX doesn't support circular references");
  561. return;
  562. }
  563. ht->nApplyCount++;
  564. php_wddx_serialize_array(packet, var);
  565. ht->nApplyCount--;
  566. break;
  567. case IS_OBJECT:
  568. ht = Z_OBJPROP_P(var);
  569. if (ht->nApplyCount > 1) {
  570. php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "WDDX doesn't support circular references");
  571. return;
  572. }
  573. ht->nApplyCount++;
  574. php_wddx_serialize_object(packet, var);
  575. ht->nApplyCount--;
  576. break;
  577. }
  578. if (name) {
  579. php_wddx_add_chunk_static(packet, WDDX_VAR_E);
  580. }
  581. }
  582. /* }}} */
  583. /* {{{ php_wddx_add_var
  584. */
  585. static void php_wddx_add_var(wddx_packet *packet, zval *name_var)
  586. {
  587. zval **val;
  588. HashTable *target_hash;
  589. TSRMLS_FETCH();
  590. if (Z_TYPE_P(name_var) == IS_STRING) {
  591. if (!EG(active_symbol_table)) {
  592. zend_rebuild_symbol_table(TSRMLS_C);
  593. }
  594. if (zend_hash_find(EG(active_symbol_table), Z_STRVAL_P(name_var),
  595. Z_STRLEN_P(name_var)+1, (void**)&val) != FAILURE) {
  596. php_wddx_serialize_var(packet, *val, Z_STRVAL_P(name_var), Z_STRLEN_P(name_var) TSRMLS_CC);
  597. }
  598. } else if (Z_TYPE_P(name_var) == IS_ARRAY || Z_TYPE_P(name_var) == IS_OBJECT) {
  599. int is_array = Z_TYPE_P(name_var) == IS_ARRAY;
  600. target_hash = HASH_OF(name_var);
  601. if (is_array && target_hash->nApplyCount > 1) {
  602. php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
  603. return;
  604. }
  605. zend_hash_internal_pointer_reset(target_hash);
  606. while(zend_hash_get_current_data(target_hash, (void**)&val) == SUCCESS) {
  607. if (is_array) {
  608. target_hash->nApplyCount++;
  609. }
  610. php_wddx_add_var(packet, *val);
  611. if (is_array) {
  612. target_hash->nApplyCount--;
  613. }
  614. zend_hash_move_forward(target_hash);
  615. }
  616. }
  617. }
  618. /* }}} */
  619. /* {{{ php_wddx_push_element
  620. */
  621. static void php_wddx_push_element(void *user_data, const XML_Char *name, const XML_Char **atts)
  622. {
  623. st_entry ent;
  624. wddx_stack *stack = (wddx_stack *)user_data;
  625. if (!strcmp(name, EL_PACKET)) {
  626. int i;
  627. if (atts) for (i=0; atts[i]; i++) {
  628. if (!strcmp(atts[i], EL_VERSION)) {
  629. /* nothing for now */
  630. }
  631. }
  632. } else if (!strcmp(name, EL_STRING)) {
  633. ent.type = ST_STRING;
  634. SET_STACK_VARNAME;
  635. ALLOC_ZVAL(ent.data);
  636. INIT_PZVAL(ent.data);
  637. Z_TYPE_P(ent.data) = IS_STRING;
  638. Z_STRVAL_P(ent.data) = STR_EMPTY_ALLOC();
  639. Z_STRLEN_P(ent.data) = 0;
  640. wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
  641. } else if (!strcmp(name, EL_BINARY)) {
  642. ent.type = ST_BINARY;
  643. SET_STACK_VARNAME;
  644. ALLOC_ZVAL(ent.data);
  645. INIT_PZVAL(ent.data);
  646. Z_TYPE_P(ent.data) = IS_STRING;
  647. Z_STRVAL_P(ent.data) = STR_EMPTY_ALLOC();
  648. Z_STRLEN_P(ent.data) = 0;
  649. wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
  650. } else if (!strcmp(name, EL_CHAR)) {
  651. int i;
  652. if (atts) for (i = 0; atts[i]; i++) {
  653. if (!strcmp(atts[i], EL_CHAR_CODE) && atts[++i] && atts[i][0]) {
  654. char tmp_buf[2];
  655. snprintf(tmp_buf, sizeof(tmp_buf), "%c", (char)strtol(atts[i], NULL, 16));
  656. php_wddx_process_data(user_data, tmp_buf, strlen(tmp_buf));
  657. break;
  658. }
  659. }
  660. } else if (!strcmp(name, EL_NUMBER)) {
  661. ent.type = ST_NUMBER;
  662. SET_STACK_VARNAME;
  663. ALLOC_ZVAL(ent.data);
  664. INIT_PZVAL(ent.data);
  665. Z_TYPE_P(ent.data) = IS_LONG;
  666. Z_LVAL_P(ent.data) = 0;
  667. wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
  668. } else if (!strcmp(name, EL_BOOLEAN)) {
  669. int i;
  670. if (atts) for (i = 0; atts[i]; i++) {
  671. if (!strcmp(atts[i], EL_VALUE) && atts[++i] && atts[i][0]) {
  672. ent.type = ST_BOOLEAN;
  673. SET_STACK_VARNAME;
  674. ALLOC_ZVAL(ent.data);
  675. INIT_PZVAL(ent.data);
  676. Z_TYPE_P(ent.data) = IS_BOOL;
  677. wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
  678. php_wddx_process_data(user_data, atts[i], strlen(atts[i]));
  679. break;
  680. }
  681. }
  682. } else if (!strcmp(name, EL_NULL)) {
  683. ent.type = ST_NULL;
  684. SET_STACK_VARNAME;
  685. ALLOC_ZVAL(ent.data);
  686. INIT_PZVAL(ent.data);
  687. ZVAL_NULL(ent.data);
  688. wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
  689. } else if (!strcmp(name, EL_ARRAY)) {
  690. ent.type = ST_ARRAY;
  691. SET_STACK_VARNAME;
  692. ALLOC_ZVAL(ent.data);
  693. array_init(ent.data);
  694. INIT_PZVAL(ent.data);
  695. wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
  696. } else if (!strcmp(name, EL_STRUCT)) {
  697. ent.type = ST_STRUCT;
  698. SET_STACK_VARNAME;
  699. ALLOC_ZVAL(ent.data);
  700. array_init(ent.data);
  701. INIT_PZVAL(ent.data);
  702. wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
  703. } else if (!strcmp(name, EL_VAR)) {
  704. int i;
  705. if (atts) for (i = 0; atts[i]; i++) {
  706. if (!strcmp(atts[i], EL_NAME) && atts[++i] && atts[i][0]) {
  707. stack->varname = estrdup(atts[i]);
  708. break;
  709. }
  710. }
  711. } else if (!strcmp(name, EL_RECORDSET)) {
  712. int i;
  713. ent.type = ST_RECORDSET;
  714. SET_STACK_VARNAME;
  715. MAKE_STD_ZVAL(ent.data);
  716. array_init(ent.data);
  717. if (atts) for (i = 0; atts[i]; i++) {
  718. if (!strcmp(atts[i], "fieldNames") && atts[++i] && atts[i][0]) {
  719. zval *tmp;
  720. char *key;
  721. char *p1, *p2, *endp;
  722. endp = (char *)atts[i] + strlen(atts[i]);
  723. p1 = (char *)atts[i];
  724. while ((p2 = php_memnstr(p1, ",", sizeof(",")-1, endp)) != NULL) {
  725. key = estrndup(p1, p2 - p1);
  726. MAKE_STD_ZVAL(tmp);
  727. array_init(tmp);
  728. add_assoc_zval_ex(ent.data, key, p2 - p1 + 1, tmp);
  729. p1 = p2 + sizeof(",")-1;
  730. efree(key);
  731. }
  732. if (p1 <= endp) {
  733. MAKE_STD_ZVAL(tmp);
  734. array_init(tmp);
  735. add_assoc_zval_ex(ent.data, p1, endp - p1 + 1, tmp);
  736. }
  737. break;
  738. }
  739. }
  740. wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
  741. } else if (!strcmp(name, EL_FIELD)) {
  742. int i;
  743. st_entry ent;
  744. ent.type = ST_FIELD;
  745. ent.varname = NULL;
  746. ent.data = NULL;
  747. if (atts) for (i = 0; atts[i]; i++) {
  748. if (!strcmp(atts[i], EL_NAME) && atts[++i] && atts[i][0]) {
  749. st_entry *recordset;
  750. zval **field;
  751. if (wddx_stack_top(stack, (void**)&recordset) == SUCCESS &&
  752. recordset->type == ST_RECORDSET &&
  753. zend_hash_find(Z_ARRVAL_P(recordset->data), (char*)atts[i], strlen(atts[i])+1, (void**)&field) == SUCCESS) {
  754. ent.data = *field;
  755. }
  756. break;
  757. }
  758. }
  759. wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
  760. } else if (!strcmp(name, EL_DATETIME)) {
  761. ent.type = ST_DATETIME;
  762. SET_STACK_VARNAME;
  763. ALLOC_ZVAL(ent.data);
  764. INIT_PZVAL(ent.data);
  765. Z_TYPE_P(ent.data) = IS_LONG;
  766. wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
  767. }
  768. }
  769. /* }}} */
  770. /* {{{ php_wddx_pop_element
  771. */
  772. static void php_wddx_pop_element(void *user_data, const XML_Char *name)
  773. {
  774. st_entry *ent1, *ent2;
  775. wddx_stack *stack = (wddx_stack *)user_data;
  776. HashTable *target_hash;
  777. zend_class_entry **pce;
  778. zval *obj;
  779. zval *tmp;
  780. TSRMLS_FETCH();
  781. /* OBJECTS_FIXME */
  782. if (stack->top == 0) {
  783. return;
  784. }
  785. if (!strcmp(name, EL_STRING) || !strcmp(name, EL_NUMBER) ||
  786. !strcmp(name, EL_BOOLEAN) || !strcmp(name, EL_NULL) ||
  787. !strcmp(name, EL_ARRAY) || !strcmp(name, EL_STRUCT) ||
  788. !strcmp(name, EL_RECORDSET) || !strcmp(name, EL_BINARY) ||
  789. !strcmp(name, EL_DATETIME)) {
  790. wddx_stack_top(stack, (void**)&ent1);
  791. if (!strcmp(name, EL_BINARY)) {
  792. int new_len=0;
  793. unsigned char *new_str;
  794. new_str = php_base64_decode(Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data), &new_len);
  795. STR_FREE(Z_STRVAL_P(ent1->data));
  796. Z_STRVAL_P(ent1->data) = new_str;
  797. Z_STRLEN_P(ent1->data) = new_len;
  798. }
  799. /* Call __wakeup() method on the object. */
  800. if (Z_TYPE_P(ent1->data) == IS_OBJECT) {
  801. zval *fname, *retval = NULL;
  802. MAKE_STD_ZVAL(fname);
  803. ZVAL_STRING(fname, "__wakeup", 1);
  804. call_user_function_ex(NULL, &ent1->data, fname, &retval, 0, 0, 0, NULL TSRMLS_CC);
  805. zval_dtor(fname);
  806. FREE_ZVAL(fname);
  807. if (retval) {
  808. zval_ptr_dtor(&retval);
  809. }
  810. }
  811. if (stack->top > 1) {
  812. stack->top--;
  813. wddx_stack_top(stack, (void**)&ent2);
  814. /* if non-existent field */
  815. if (ent2->type == ST_FIELD && ent2->data == NULL) {
  816. zval_ptr_dtor(&ent1->data);
  817. efree(ent1);
  818. return;
  819. }
  820. if (Z_TYPE_P(ent2->data) == IS_ARRAY || Z_TYPE_P(ent2->data) == IS_OBJECT) {
  821. target_hash = HASH_OF(ent2->data);
  822. if (ent1->varname) {
  823. if (!strcmp(ent1->varname, PHP_CLASS_NAME_VAR) &&
  824. Z_TYPE_P(ent1->data) == IS_STRING && Z_STRLEN_P(ent1->data)) {
  825. zend_bool incomplete_class = 0;
  826. zend_str_tolower(Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data));
  827. if (zend_hash_find(EG(class_table), Z_STRVAL_P(ent1->data),
  828. Z_STRLEN_P(ent1->data)+1, (void **) &pce)==FAILURE) {
  829. incomplete_class = 1;
  830. pce = &PHP_IC_ENTRY;
  831. }
  832. /* Initialize target object */
  833. MAKE_STD_ZVAL(obj);
  834. object_init_ex(obj, *pce);
  835. /* Merge current hashtable with object's default properties */
  836. zend_hash_merge(Z_OBJPROP_P(obj),
  837. Z_ARRVAL_P(ent2->data),
  838. (void (*)(void *)) zval_add_ref,
  839. (void *) &tmp, sizeof(zval *), 0);
  840. if (incomplete_class) {
  841. php_store_class_name(obj, Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data));
  842. }
  843. /* Clean up old array entry */
  844. zval_ptr_dtor(&ent2->data);
  845. /* Set stack entry to point to the newly created object */
  846. ent2->data = obj;
  847. /* Clean up class name var entry */
  848. zval_ptr_dtor(&ent1->data);
  849. } else if (Z_TYPE_P(ent2->data) == IS_OBJECT) {
  850. zend_class_entry *old_scope = EG(scope);
  851. EG(scope) = Z_OBJCE_P(ent2->data);
  852. Z_DELREF_P(ent1->data);
  853. add_property_zval(ent2->data, ent1->varname, ent1->data);
  854. EG(scope) = old_scope;
  855. } else {
  856. zend_symtable_update(target_hash, ent1->varname, strlen(ent1->varname)+1, &ent1->data, sizeof(zval *), NULL);
  857. }
  858. efree(ent1->varname);
  859. } else {
  860. zend_hash_next_index_insert(target_hash, &ent1->data, sizeof(zval *), NULL);
  861. }
  862. }
  863. efree(ent1);
  864. } else {
  865. stack->done = 1;
  866. }
  867. } else if (!strcmp(name, EL_VAR) && stack->varname) {
  868. efree(stack->varname);
  869. } else if (!strcmp(name, EL_FIELD)) {
  870. st_entry *ent;
  871. wddx_stack_top(stack, (void **)&ent);
  872. efree(ent);
  873. stack->top--;
  874. }
  875. }
  876. /* }}} */
  877. /* {{{ php_wddx_process_data
  878. */
  879. static void php_wddx_process_data(void *user_data, const XML_Char *s, int len)
  880. {
  881. st_entry *ent;
  882. wddx_stack *stack = (wddx_stack *)user_data;
  883. TSRMLS_FETCH();
  884. if (!wddx_stack_is_empty(stack) && !stack->done) {
  885. wddx_stack_top(stack, (void**)&ent);
  886. switch (Z_TYPE_P(ent)) {
  887. case ST_STRING:
  888. if (Z_STRLEN_P(ent->data) == 0) {
  889. STR_FREE(Z_STRVAL_P(ent->data));
  890. Z_STRVAL_P(ent->data) = estrndup(s, len);
  891. Z_STRLEN_P(ent->data) = len;
  892. } else {
  893. Z_STRVAL_P(ent->data) = erealloc(Z_STRVAL_P(ent->data), Z_STRLEN_P(ent->data) + len + 1);
  894. memcpy(Z_STRVAL_P(ent->data) + Z_STRLEN_P(ent->data), s, len);
  895. Z_STRLEN_P(ent->data) += len;
  896. Z_STRVAL_P(ent->data)[Z_STRLEN_P(ent->data)] = '\0';
  897. }
  898. break;
  899. case ST_BINARY:
  900. if (Z_STRLEN_P(ent->data) == 0) {
  901. STR_FREE(Z_STRVAL_P(ent->data));
  902. Z_STRVAL_P(ent->data) = estrndup(s, len + 1);
  903. } else {
  904. Z_STRVAL_P(ent->data) = erealloc(Z_STRVAL_P(ent->data), Z_STRLEN_P(ent->data) + len + 1);
  905. memcpy(Z_STRVAL_P(ent->data) + Z_STRLEN_P(ent->data), s, len);
  906. }
  907. Z_STRLEN_P(ent->data) += len;
  908. Z_STRVAL_P(ent->data)[Z_STRLEN_P(ent->data)] = '\0';
  909. break;
  910. case ST_NUMBER:
  911. Z_TYPE_P(ent->data) = IS_STRING;
  912. Z_STRLEN_P(ent->data) = len;
  913. Z_STRVAL_P(ent->data) = estrndup(s, len);
  914. convert_scalar_to_number(ent->data TSRMLS_CC);
  915. break;
  916. case ST_BOOLEAN:
  917. if (!strcmp(s, "true")) {
  918. Z_LVAL_P(ent->data) = 1;
  919. } else if (!strcmp(s, "false")) {
  920. Z_LVAL_P(ent->data) = 0;
  921. } else {
  922. stack->top--;
  923. zval_ptr_dtor(&ent->data);
  924. if (ent->varname)
  925. efree(ent->varname);
  926. efree(ent);
  927. }
  928. break;
  929. case ST_DATETIME: {
  930. char *tmp;
  931. tmp = emalloc(len + 1);
  932. memcpy(tmp, s, len);
  933. tmp[len] = '\0';
  934. Z_LVAL_P(ent->data) = php_parse_date(tmp, NULL);
  935. /* date out of range < 1969 or > 2038 */
  936. if (Z_LVAL_P(ent->data) == -1) {
  937. Z_TYPE_P(ent->data) = IS_STRING;
  938. Z_STRLEN_P(ent->data) = len;
  939. Z_STRVAL_P(ent->data) = estrndup(s, len);
  940. }
  941. efree(tmp);
  942. }
  943. break;
  944. default:
  945. break;
  946. }
  947. }
  948. }
  949. /* }}} */
  950. /* {{{ php_wddx_deserialize_ex
  951. */
  952. int php_wddx_deserialize_ex(char *value, int vallen, zval *return_value)
  953. {
  954. wddx_stack stack;
  955. XML_Parser parser;
  956. st_entry *ent;
  957. int retval;
  958. wddx_stack_init(&stack);
  959. parser = XML_ParserCreate("UTF-8");
  960. XML_SetUserData(parser, &stack);
  961. XML_SetElementHandler(parser, php_wddx_push_element, php_wddx_pop_element);
  962. XML_SetCharacterDataHandler(parser, php_wddx_process_data);
  963. XML_Parse(parser, value, vallen, 1);
  964. XML_ParserFree(parser);
  965. if (stack.top == 1) {
  966. wddx_stack_top(&stack, (void**)&ent);
  967. *return_value = *(ent->data);
  968. zval_copy_ctor(return_value);
  969. retval = SUCCESS;
  970. } else {
  971. retval = FAILURE;
  972. }
  973. wddx_stack_destroy(&stack);
  974. return retval;
  975. }
  976. /* }}} */
  977. /* {{{ proto string wddx_serialize_value(mixed var [, string comment])
  978. Creates a new packet and serializes the given value */
  979. PHP_FUNCTION(wddx_serialize_value)
  980. {
  981. zval *var;
  982. char *comment = NULL;
  983. int comment_len = 0;
  984. wddx_packet *packet;
  985. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|s", &var, &comment, &comment_len) == FAILURE) {
  986. return;
  987. }
  988. packet = php_wddx_constructor();
  989. php_wddx_packet_start(packet, comment, comment_len);
  990. php_wddx_serialize_var(packet, var, NULL, 0 TSRMLS_CC);
  991. php_wddx_packet_end(packet);
  992. ZVAL_STRINGL(return_value, packet->c, packet->len, 1);
  993. smart_str_free(packet);
  994. efree(packet);
  995. }
  996. /* }}} */
  997. /* {{{ proto string wddx_serialize_vars(mixed var_name [, mixed ...])
  998. Creates a new packet and serializes given variables into a struct */
  999. PHP_FUNCTION(wddx_serialize_vars)
  1000. {
  1001. int num_args, i;
  1002. wddx_packet *packet;
  1003. zval ***args = NULL;
  1004. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &num_args) == FAILURE) {
  1005. return;
  1006. }
  1007. packet = php_wddx_constructor();
  1008. php_wddx_packet_start(packet, NULL, 0);
  1009. php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
  1010. for (i=0; i<num_args; i++) {
  1011. if (Z_TYPE_PP(args[i]) != IS_ARRAY && Z_TYPE_PP(args[i]) != IS_OBJECT) {
  1012. convert_to_string_ex(args[i]);
  1013. }
  1014. php_wddx_add_var(packet, *args[i]);
  1015. }
  1016. php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
  1017. php_wddx_packet_end(packet);
  1018. efree(args);
  1019. ZVAL_STRINGL(return_value, packet->c, packet->len, 1);
  1020. smart_str_free(packet);
  1021. efree(packet);
  1022. }
  1023. /* }}} */
  1024. /* {{{ php_wddx_constructor
  1025. */
  1026. wddx_packet *php_wddx_constructor(void)
  1027. {
  1028. smart_str *packet;
  1029. packet = (smart_str *)emalloc(sizeof(smart_str));
  1030. packet->c = NULL;
  1031. return packet;
  1032. }
  1033. /* }}} */
  1034. /* {{{ php_wddx_destructor
  1035. */
  1036. void php_wddx_destructor(wddx_packet *packet)
  1037. {
  1038. smart_str_free(packet);
  1039. efree(packet);
  1040. }
  1041. /* }}} */
  1042. /* {{{ proto resource wddx_packet_start([string comment])
  1043. Starts a WDDX packet with optional comment and returns the packet id */
  1044. PHP_FUNCTION(wddx_packet_start)
  1045. {
  1046. char *comment = NULL;
  1047. int comment_len = 0;
  1048. wddx_packet *packet;
  1049. comment = NULL;
  1050. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &comment, &comment_len) == FAILURE) {
  1051. return;
  1052. }
  1053. packet = php_wddx_constructor();
  1054. php_wddx_packet_start(packet, comment, comment_len);
  1055. php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
  1056. ZEND_REGISTER_RESOURCE(return_value, packet, le_wddx);
  1057. }
  1058. /* }}} */
  1059. /* {{{ proto string wddx_packet_end(resource packet_id)
  1060. Ends specified WDDX packet and returns the string containing the packet */
  1061. PHP_FUNCTION(wddx_packet_end)
  1062. {
  1063. zval *packet_id;
  1064. wddx_packet *packet = NULL;
  1065. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &packet_id) == FAILURE) {
  1066. return;
  1067. }
  1068. ZEND_FETCH_RESOURCE(packet, wddx_packet *, &packet_id, -1, "WDDX packet ID", le_wddx);
  1069. php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
  1070. php_wddx_packet_end(packet);
  1071. ZVAL_STRINGL(return_value, packet->c, packet->len, 1);
  1072. zend_list_delete(Z_LVAL_P(packet_id));
  1073. }
  1074. /* }}} */
  1075. /* {{{ proto int wddx_add_vars(resource packet_id, mixed var_names [, mixed ...])
  1076. Serializes given variables and adds them to packet given by packet_id */
  1077. PHP_FUNCTION(wddx_add_vars)
  1078. {
  1079. int num_args, i;
  1080. zval ***args = NULL;
  1081. zval *packet_id;
  1082. wddx_packet *packet = NULL;
  1083. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r+", &packet_id, &args, &num_args) == FAILURE) {
  1084. return;
  1085. }
  1086. if (!ZEND_FETCH_RESOURCE_NO_RETURN(packet, wddx_packet *, &packet_id, -1, "WDDX packet ID", le_wddx)) {
  1087. efree(args);
  1088. RETURN_FALSE;
  1089. }
  1090. if (!packet) {
  1091. efree(args);
  1092. RETURN_FALSE;
  1093. }
  1094. for (i=0; i<num_args; i++) {
  1095. if (Z_TYPE_PP(args[i]) != IS_ARRAY && Z_TYPE_PP(args[i]) != IS_OBJECT) {
  1096. convert_to_string_ex(args[i]);
  1097. }
  1098. php_wddx_add_var(packet, (*args[i]));
  1099. }
  1100. efree(args);
  1101. RETURN_TRUE;
  1102. }
  1103. /* }}} */
  1104. /* {{{ proto mixed wddx_deserialize(mixed packet)
  1105. Deserializes given packet and returns a PHP value */
  1106. PHP_FUNCTION(wddx_deserialize)
  1107. {
  1108. zval *packet;
  1109. char *payload;
  1110. int payload_len;
  1111. php_stream *stream = NULL;
  1112. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &packet) == FAILURE) {
  1113. return;
  1114. }
  1115. if (Z_TYPE_P(packet) == IS_STRING) {
  1116. payload = Z_STRVAL_P(packet);
  1117. payload_len = Z_STRLEN_P(packet);
  1118. } else if (Z_TYPE_P(packet) == IS_RESOURCE) {
  1119. php_stream_from_zval(stream, &packet);
  1120. if (stream) {
  1121. payload_len = php_stream_copy_to_mem(stream, &payload, PHP_STREAM_COPY_ALL, 0);
  1122. }
  1123. } else {
  1124. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expecting parameter 1 to be a string or a stream");
  1125. return;
  1126. }
  1127. if (payload_len == 0) {
  1128. return;
  1129. }
  1130. php_wddx_deserialize_ex(payload, payload_len, return_value);
  1131. if (stream) {
  1132. pefree(payload, 0);
  1133. }
  1134. }
  1135. /* }}} */
  1136. #endif /* HAVE_LIBEXPAT */
  1137. /*
  1138. * Local variables:
  1139. * tab-width: 4
  1140. * c-basic-offset: 4
  1141. * End:
  1142. * vim600: sw=4 ts=4 fdm=marker
  1143. * vim<600: sw=4 ts=4
  1144. */