PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/wddx - wddx.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 504 547 92.1 %
Date: 2022-01-18 Functions: 32 32 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Wed, 19 Jan 2022 00:14:26 +0000 (3 days ago)

Copyright © 2005-2022 The PHP Group
All rights reserved.