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