1/* 2 +----------------------------------------------------------------------+ 3 | PHP Version 5 | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1997-2013 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$ */ 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 76static int le_wddx; 77 78typedef 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 95typedef struct { 96 int top, max; 97 char *varname; 98 zend_bool done; 99 void **elements; 100} wddx_stack; 101 102 103static void php_wddx_process_data(void *user_data, const XML_Char *s, int len); 104 105/* {{{ arginfo */ 106ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_serialize_value, 0, 0, 1) 107 ZEND_ARG_INFO(0, var) 108 ZEND_ARG_INFO(0, comment) 109ZEND_END_ARG_INFO() 110 111ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_serialize_vars, 0, 0, 1) 112 ZEND_ARG_INFO(0, var_name) 113 ZEND_ARG_INFO(0, ...) 114ZEND_END_ARG_INFO() 115 116ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_serialize_start, 0, 0, 0) 117 ZEND_ARG_INFO(0, comment) 118ZEND_END_ARG_INFO() 119 120ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_packet_end, 0, 0, 1) 121 ZEND_ARG_INFO(0, packet_id) 122ZEND_END_ARG_INFO() 123 124ZEND_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, ...) 128ZEND_END_ARG_INFO() 129 130ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_deserialize, 0, 0, 1) 131 ZEND_ARG_INFO(0, packet) 132ZEND_END_ARG_INFO() 133/* }}} */ 134 135/* {{{ wddx_functions[] 136 */ 137const 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 148PHP_MINIT_FUNCTION(wddx); 149PHP_MINFO_FUNCTION(wddx); 150 151/* {{{ dynamically loadable module stuff */ 152#ifdef COMPILE_DL_WDDX 153ZEND_GET_MODULE(wddx) 154#endif /* COMPILE_DL_WDDX */ 155/* }}} */ 156 157/* {{{ wddx_module_entry 158 */ 159zend_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 */ 175static 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 */ 189static 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 */ 203static 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 */ 217static 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 */ 229static 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 */ 251static 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 */ 264PS_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 */ 293PS_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 */ 338PHP_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 */ 354PHP_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 */ 369void 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 */ 387void 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 */ 402static 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 */ 422static 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 */ 439static 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 */ 447static 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 */ 455static void php_wddx_serialize_object(wddx_packet *packet, zval *obj) 456{ 457/* OBJECTS_FIXME */ 458 zval **ent, *fname, **varname; 459 zval *retval = NULL; 460 char *key; 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) { 532 char *class_name, *prop_name; 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 */ 555static 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 */ 627void 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 */ 692static 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 */ 736static 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 */ 914static 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 */ 1042static 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 */ 1124int 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 */ 1159PHP_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 */ 1184PHP_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 */ 1219wddx_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 */ 1232void 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 */ 1241PHP_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 */ 1264PHP_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 */ 1287PHP_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 */ 1322PHP_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 */ 1368