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>