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: +----------------------------------------------------------------------+ ! 5: | Copyright (c) 1997-2012 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 321634 2012-01-01 13:15:04Z 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: /* {{{ 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; ! 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: */ ! 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: */