Annotation of embedaddon/php/ext/wddx/wddx.c, revision 1.1
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: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>