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