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: 525 589 89.1 %
Date: 2014-04-10 Functions: 32 32 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2014 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Author: Andrei Zmievski <andrei@php.net>                             |
      16             :    +----------------------------------------------------------------------+
      17             :  */
      18             : 
      19             : /* $Id$ */
      20             : 
      21             : #ifdef HAVE_CONFIG_H
      22             : #include "config.h"
      23             : #endif
      24             : 
      25             : #include "php.h"
      26             : 
      27             : #if HAVE_WDDX
      28             : 
      29             : #include "ext/xml/expat_compat.h"
      30             : #include "php_wddx.h"
      31             : #include "php_wddx_api.h"
      32             : 
      33             : #define PHP_XML_INTERNAL
      34             : #include "ext/xml/php_xml.h"
      35             : #include "ext/standard/php_incomplete_class.h"
      36             : #include "ext/standard/base64.h"
      37             : #include "ext/standard/info.h"
      38             : #include "ext/standard/php_smart_str.h"
      39             : #include "ext/standard/html.h"
      40             : #include "ext/standard/php_string.h"
      41             : #include "ext/date/php_date.h"
      42             : #include "zend_globals.h"
      43             : 
      44             : #define WDDX_BUF_LEN                    256
      45             : #define PHP_CLASS_NAME_VAR              "php_class_name"
      46             : 
      47             : #define EL_ARRAY                                "array"
      48             : #define EL_BINARY                               "binary"
      49             : #define EL_BOOLEAN                              "boolean"
      50             : #define EL_CHAR                                 "char"
      51             : #define EL_CHAR_CODE                    "code"
      52             : #define EL_NULL                                 "null"
      53             : #define EL_NUMBER                               "number"
      54             : #define EL_PACKET                               "wddxPacket"
      55             : #define EL_STRING                               "string"
      56             : #define EL_STRUCT                               "struct"
      57             : #define EL_VALUE                                "value"
      58             : #define EL_VAR                                  "var"
      59             : #define EL_NAME                         "name"
      60             : #define EL_VERSION                              "version"
      61             : #define EL_RECORDSET                    "recordset"
      62             : #define EL_FIELD                                "field"
      63             : #define EL_DATETIME                             "dateTime"
      64             : 
      65             : #define php_wddx_deserialize(a,b) \
      66             :         php_wddx_deserialize_ex((a)->value.str.val, (a)->value.str.len, (b))
      67             : 
      68             : #define SET_STACK_VARNAME                                                       \
      69             :                 if (stack->varname) {                                                \
      70             :                         ent.varname = estrdup(stack->varname);       \
      71             :                         efree(stack->varname);                                       \
      72             :                         stack->varname = NULL;                                       \
      73             :                 } else                                                                          \
      74             :                         ent.varname = NULL;                                             \
      75             :                         
      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         392 : static int wddx_stack_init(wddx_stack *stack)
     176             : {
     177         392 :         stack->top = 0;
     178         392 :         stack->elements = (void **) safe_emalloc(sizeof(void **), STACK_BLOCK_SIZE, 0);
     179         392 :         stack->max = STACK_BLOCK_SIZE;
     180         392 :         stack->varname = NULL;
     181         392 :         stack->done = 0;
     182             : 
     183         392 :         return SUCCESS;
     184             : }
     185             : /* }}} */
     186             : 
     187             : /* {{{ wddx_stack_push
     188             :  */
     189         452 : static int wddx_stack_push(wddx_stack *stack, void *element, int size)
     190             : {
     191         452 :         if (stack->top >= stack->max) {                /* we need to allocate more memory */
     192           0 :                 stack->elements = (void **) erealloc(stack->elements,
     193             :                                    (sizeof(void **) * (stack->max += STACK_BLOCK_SIZE)));
     194             :         }
     195         452 :         stack->elements[stack->top] = (void *) emalloc(size);
     196         452 :         memcpy(stack->elements[stack->top], element, size);
     197         452 :         return stack->top++;
     198             : }
     199             : /* }}} */
     200             : 
     201             : /* {{{ wddx_stack_top
     202             :  */
     203        1411 : static int wddx_stack_top(wddx_stack *stack, void **element)
     204             : {
     205        1411 :         if (stack->top > 0) {
     206        1411 :                 *element = stack->elements[stack->top - 1];
     207        1411 :                 return SUCCESS;
     208             :         } else {
     209           0 :                 *element = NULL;
     210           0 :                 return FAILURE;
     211             :         }
     212             : }
     213             : /* }}} */
     214             : 
     215             : /* {{{ wddx_stack_is_empty
     216             :  */
     217         527 : static int wddx_stack_is_empty(wddx_stack *stack)
     218             : {
     219         527 :         if (stack->top == 0) {
     220          15 :                 return 1;
     221             :         } else {
     222         512 :                 return 0;
     223             :         }
     224             : }
     225             : /* }}} */
     226             : 
     227             : /* {{{ wddx_stack_destroy
     228             :  */
     229         392 : static int wddx_stack_destroy(wddx_stack *stack)
     230             : {
     231             :         register int i;
     232             : 
     233         392 :         if (stack->elements) {
     234         784 :                 for (i = 0; i < stack->top; i++) {
     235         392 :                         if (((st_entry *)stack->elements[i])->data)       {
     236         392 :                                 zval_ptr_dtor(&((st_entry *)stack->elements[i])->data);
     237             :                         }
     238         392 :                         if (((st_entry *)stack->elements[i])->varname) {
     239           0 :                                 efree(((st_entry *)stack->elements[i])->varname);
     240             :                         }
     241         392 :                         efree(stack->elements[i]);
     242             :                 }               
     243         392 :                 efree(stack->elements);
     244             :         }
     245         392 :         return SUCCESS;
     246             : }
     247             : /* }}} */
     248             : 
     249             : /* {{{ release_wddx_packet_rsrc
     250             :  */
     251           1 : static void release_wddx_packet_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC)
     252             : {
     253           1 :         smart_str *str = (smart_str *)rsrc->ptr;
     254           1 :         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             :         PS_ENCODE_VARS;
     268             : 
     269           1 :         packet = php_wddx_constructor();
     270             : 
     271           1 :         php_wddx_packet_start(packet, NULL, 0);
     272           1 :         php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
     273             :         
     274           1 :         PS_ENCODE_LOOP(
     275             :                 php_wddx_serialize_var(packet, *struc, key, key_length TSRMLS_CC);
     276             :         );
     277             :         
     278           1 :         php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
     279           1 :         php_wddx_packet_end(packet);
     280           1 :         *newstr = php_wddx_gather(packet);
     281           1 :         php_wddx_destructor(packet);
     282             :         
     283           1 :         if (newlen) {
     284           1 :                 *newlen = strlen(*newstr);
     285             :         }
     286             : 
     287           1 :         return SUCCESS;
     288             : }
     289             : /* }}} */
     290             : 
     291             : /* {{{ PS_SERIALIZER_DECODE_FUNC
     292             :  */
     293           3 : 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           3 :         if (vallen == 0) {
     305           2 :                 return SUCCESS;
     306             :         }
     307             :         
     308           1 :         MAKE_STD_ZVAL(retval);
     309             : 
     310           1 :         if ((ret = php_wddx_deserialize_ex((char *)val, vallen, retval)) == SUCCESS) {
     311             : 
     312           4 :                 for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(retval));
     313           3 :                          zend_hash_get_current_data(Z_ARRVAL_P(retval), (void **) &ent) == SUCCESS;
     314           2 :                          zend_hash_move_forward(Z_ARRVAL_P(retval))) {
     315           2 :                         hash_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(retval), &key, &key_length, &idx, 0, NULL);
     316             : 
     317           2 :                         switch (hash_type) {
     318             :                                 case HASH_KEY_IS_LONG:
     319           0 :                                         key_length = slprintf(tmp, sizeof(tmp), "%ld", idx) + 1;
     320           0 :                                         key = tmp;
     321             :                                         /* fallthru */
     322             :                                 case HASH_KEY_IS_STRING:
     323           2 :                                         php_set_session_var(key, key_length-1, *ent, NULL TSRMLS_CC);
     324           2 :                                         PS_ADD_VAR(key);
     325             :                         }
     326             :                 }
     327             :         }
     328             : 
     329           1 :         zval_ptr_dtor(&retval);
     330             : 
     331           1 :         return ret;
     332             : }
     333             : /* }}} */
     334             : #endif
     335             : 
     336             : /* {{{ PHP_MINIT_FUNCTION
     337             :  */
     338       20105 : PHP_MINIT_FUNCTION(wddx)
     339             : {
     340       20105 :         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       20105 :         php_session_register_serializer("wddx",
     344             :                                                                         PS_SERIALIZER_ENCODE_NAME(wddx),
     345             :                                                                         PS_SERIALIZER_DECODE_NAME(wddx));
     346             : #endif  
     347             : 
     348       20105 :         return SUCCESS;
     349             : }
     350             : /* }}} */
     351             : 
     352             : /* {{{ PHP_MINFO_FUNCTION
     353             :  */
     354         148 : PHP_MINFO_FUNCTION(wddx)
     355             : {
     356         148 :         php_info_print_table_start();
     357             : #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
     358         148 :         php_info_print_table_header(2, "WDDX Support", "enabled" );
     359         148 :         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         148 :         php_info_print_table_end();
     364         148 : }
     365             : /* }}} */
     366             : 
     367             : /* {{{ php_wddx_packet_start
     368             :  */
     369         200 : void php_wddx_packet_start(wddx_packet *packet, char *comment, int comment_len)
     370             : {
     371         200 :         php_wddx_add_chunk_static(packet, WDDX_PACKET_S);
     372         200 :         if (comment) {
     373           3 :                 php_wddx_add_chunk_static(packet, WDDX_HEADER_S);
     374           3 :                 php_wddx_add_chunk_static(packet, WDDX_COMMENT_S);
     375           3 :                 php_wddx_add_chunk_ex(packet, comment, comment_len);
     376           3 :                 php_wddx_add_chunk_static(packet, WDDX_COMMENT_E);
     377           3 :                 php_wddx_add_chunk_static(packet, WDDX_HEADER_E);
     378             :         } else {
     379         197 :                 php_wddx_add_chunk_static(packet, WDDX_HEADER);
     380             :         }
     381         200 :         php_wddx_add_chunk_static(packet, WDDX_DATA_S);
     382         200 : }
     383             : /* }}} */
     384             : 
     385             : /* {{{ php_wddx_packet_end
     386             :  */
     387         200 : void php_wddx_packet_end(wddx_packet *packet)
     388             : {
     389         200 :         php_wddx_add_chunk_static(packet, WDDX_DATA_E);
     390         200 :         php_wddx_add_chunk_static(packet, WDDX_PACKET_E);       
     391         200 : }
     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         204 : static void php_wddx_serialize_string(wddx_packet *packet, zval *var TSRMLS_DC)
     403             : {
     404         204 :         php_wddx_add_chunk_static(packet, WDDX_STRING_S);
     405             : 
     406         204 :         if (Z_STRLEN_P(var) > 0) {
     407             :                 char *buf;
     408             :                 int buf_len;
     409             : 
     410         204 :                 buf = php_escape_html_entities(Z_STRVAL_P(var), Z_STRLEN_P(var), &buf_len, 0, ENT_QUOTES, NULL TSRMLS_CC);
     411             : 
     412         204 :                 php_wddx_add_chunk_ex(packet, buf, buf_len);
     413             : 
     414         204 :                 efree(buf);
     415             :         }
     416         204 :         php_wddx_add_chunk_static(packet, WDDX_STRING_E);
     417         204 : }
     418             : /* }}} */
     419             : 
     420             : /* {{{ php_wddx_serialize_number
     421             :  */
     422           3 : static void php_wddx_serialize_number(wddx_packet *packet, zval *var)
     423             : {
     424             :         char tmp_buf[WDDX_BUF_LEN];
     425             :         zval tmp;
     426             :         
     427           3 :         tmp = *var;
     428             :         zval_copy_ctor(&tmp);
     429           3 :         convert_to_string(&tmp);
     430           3 :         snprintf(tmp_buf, sizeof(tmp_buf), WDDX_NUMBER, Z_STRVAL(tmp));
     431             :         zval_dtor(&tmp);
     432             : 
     433           3 :         php_wddx_add_chunk(packet, tmp_buf);    
     434           3 : }
     435             : /* }}} */
     436             : 
     437             : /* {{{ php_wddx_serialize_boolean
     438             :  */
     439           3 : static void php_wddx_serialize_boolean(wddx_packet *packet, zval *var)
     440             : {
     441           3 :         php_wddx_add_chunk(packet, Z_LVAL_P(var) ? WDDX_BOOLEAN_TRUE : WDDX_BOOLEAN_FALSE);
     442           3 : }
     443             : /* }}} */
     444             : 
     445             : /* {{{ php_wddx_serialize_unset
     446             :  */
     447           2 : static void php_wddx_serialize_unset(wddx_packet *packet)
     448             : {
     449           2 :         php_wddx_add_chunk_static(packet, WDDX_NULL);
     450           2 : }
     451             : /* }}} */
     452             : 
     453             : /* {{{ php_wddx_serialize_object
     454             :  */
     455           4 : static void php_wddx_serialize_object(wddx_packet *packet, zval *obj)
     456             : {
     457             : /* OBJECTS_FIXME */
     458             :         zval **ent, *fname, **varname;
     459           4 :         zval *retval = NULL;
     460             :         const char *key;
     461             :         ulong idx;
     462             :         char tmp_buf[WDDX_BUF_LEN];
     463             :         HashTable *objhash, *sleephash;
     464             :         TSRMLS_FETCH();
     465             : 
     466           4 :         MAKE_STD_ZVAL(fname);
     467           4 :         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           4 :         if (call_user_function_ex(CG(function_table), &obj, fname, &retval, 0, 0, 1, NULL TSRMLS_CC) == SUCCESS) {
     474           1 :                 if (retval && (sleephash = HASH_OF(retval))) {
     475           1 :                         PHP_CLASS_ATTRIBUTES;
     476             :                         
     477           1 :                         PHP_SET_CLASS_ATTRIBUTES(obj);
     478             : 
     479           1 :                         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           1 :                         php_wddx_add_chunk_static(packet, WDDX_STRING_S);
     483           1 :                         php_wddx_add_chunk_ex(packet, class_name, name_len);
     484           1 :                         php_wddx_add_chunk_static(packet, WDDX_STRING_E);
     485           1 :                         php_wddx_add_chunk_static(packet, WDDX_VAR_E);
     486             : 
     487           1 :                         PHP_CLEANUP_CLASS_ATTRIBUTES();
     488             : 
     489           1 :                         objhash = HASH_OF(obj);
     490             :                         
     491           4 :                         for (zend_hash_internal_pointer_reset(sleephash);
     492           3 :                                  zend_hash_get_current_data(sleephash, (void **)&varname) == SUCCESS;
     493           2 :                                  zend_hash_move_forward(sleephash)) {
     494           2 :                                 if (Z_TYPE_PP(varname) != IS_STRING) {
     495           0 :                                         php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array only containing the names of instance-variables to serialize.");
     496           0 :                                         continue;
     497             :                                 }
     498             : 
     499           2 :                                 if (zend_hash_find(objhash, Z_STRVAL_PP(varname), Z_STRLEN_PP(varname)+1, (void **)&ent) == SUCCESS) {
     500           2 :                                         php_wddx_serialize_var(packet, *ent, Z_STRVAL_PP(varname), Z_STRLEN_PP(varname) TSRMLS_CC);
     501             :                                 }
     502             :                         }
     503             :                         
     504           1 :                         php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
     505             :                 }
     506             :         } else {
     507             :                 uint key_len;
     508             : 
     509           3 :                 PHP_CLASS_ATTRIBUTES;
     510             : 
     511           3 :                 PHP_SET_CLASS_ATTRIBUTES(obj);
     512             : 
     513           3 :                 php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
     514           3 :                 snprintf(tmp_buf, WDDX_BUF_LEN, WDDX_VAR_S, PHP_CLASS_NAME_VAR);
     515           3 :                 php_wddx_add_chunk(packet, tmp_buf);
     516           3 :                 php_wddx_add_chunk_static(packet, WDDX_STRING_S);
     517           3 :                 php_wddx_add_chunk_ex(packet, class_name, name_len);
     518           3 :                 php_wddx_add_chunk_static(packet, WDDX_STRING_E);
     519           3 :                 php_wddx_add_chunk_static(packet, WDDX_VAR_E);
     520             : 
     521           3 :                 PHP_CLEANUP_CLASS_ATTRIBUTES();
     522             :                 
     523           3 :                 objhash = HASH_OF(obj);
     524           8 :                 for (zend_hash_internal_pointer_reset(objhash);
     525           5 :                          zend_hash_get_current_data(objhash, (void**)&ent) == SUCCESS;
     526           2 :                          zend_hash_move_forward(objhash)) {
     527           2 :                         if (*ent == obj) {
     528           0 :                                 continue;
     529             :                         }
     530             : 
     531           2 :                         if (zend_hash_get_current_key_ex(objhash, &key, &key_len, &idx, 0, NULL) == HASH_KEY_IS_STRING) {
     532             :                                 const char *class_name, *prop_name;
     533             :                                 
     534           2 :                                 zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
     535           2 :                                 php_wddx_serialize_var(packet, *ent, prop_name, strlen(prop_name)+1 TSRMLS_CC);
     536             :                         } else {
     537           0 :                                 key_len = slprintf(tmp_buf, sizeof(tmp_buf), "%ld", idx);
     538           0 :                                 php_wddx_serialize_var(packet, *ent, tmp_buf, key_len TSRMLS_CC);
     539             :                         }
     540             :                 }
     541           3 :                 php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
     542             :         }
     543             : 
     544             :         zval_dtor(fname);
     545           4 :         FREE_ZVAL(fname);
     546             : 
     547           4 :         if (retval) {
     548           1 :                 zval_ptr_dtor(&retval);
     549             :         }
     550           4 : }
     551             : /* }}} */
     552             : 
     553             : /* {{{ php_wddx_serialize_array
     554             :  */
     555           6 : static void php_wddx_serialize_array(wddx_packet *packet, zval *arr)
     556             : {
     557             :         zval **ent;
     558             :         char *key;
     559             :         uint key_len;
     560           6 :         int is_struct = 0, ent_type;
     561             :         ulong idx;
     562             :         HashTable *target_hash;
     563             :         char tmp_buf[WDDX_BUF_LEN];
     564           6 :         ulong ind = 0;
     565             :         int type;
     566             :         TSRMLS_FETCH();
     567             : 
     568           6 :         target_hash = HASH_OF(arr);
     569             : 
     570          15 :         for (zend_hash_internal_pointer_reset(target_hash);
     571           9 :                  zend_hash_get_current_data(target_hash, (void**)&ent) == SUCCESS;
     572           3 :                  zend_hash_move_forward(target_hash)) {
     573             : 
     574           8 :                 type = zend_hash_get_current_key(target_hash, &key, &idx, 0);
     575             : 
     576           8 :                 if (type == HASH_KEY_IS_STRING) {
     577           5 :                         is_struct = 1;
     578           5 :                         break;
     579             :                 }
     580             : 
     581           3 :                 if (idx != ind) {
     582           0 :                         is_struct = 1;
     583           0 :                         break;
     584             :                 }
     585             : 
     586           3 :                 ind++;
     587             :         }
     588             : 
     589           6 :         if (is_struct) {
     590           5 :                 php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
     591             :         } else {
     592           1 :                 snprintf(tmp_buf, sizeof(tmp_buf), WDDX_ARRAY_S, zend_hash_num_elements(target_hash));
     593           1 :                 php_wddx_add_chunk(packet, tmp_buf);
     594             :         }
     595             : 
     596          27 :         for (zend_hash_internal_pointer_reset(target_hash);
     597          21 :                  zend_hash_get_current_data(target_hash, (void**)&ent) == SUCCESS;
     598          15 :                  zend_hash_move_forward(target_hash)) {
     599          15 :                 if (*ent == arr) {
     600           0 :                         continue;
     601             :                 }
     602             : 
     603          15 :                 if (is_struct) {
     604          12 :                         ent_type = zend_hash_get_current_key_ex(target_hash, &key, &key_len, &idx, 0, NULL);
     605             : 
     606          12 :                         if (ent_type == HASH_KEY_IS_STRING) {
     607          12 :                                 php_wddx_serialize_var(packet, *ent, key, key_len TSRMLS_CC);
     608             :                         } else {
     609           0 :                                 key_len = slprintf(tmp_buf, sizeof(tmp_buf), "%ld", idx);
     610           0 :                                 php_wddx_serialize_var(packet, *ent, tmp_buf, key_len TSRMLS_CC);
     611             :                         }
     612             :                 } else {
     613           3 :                         php_wddx_serialize_var(packet, *ent, NULL, 0 TSRMLS_CC);
     614             :                 }
     615             :         }
     616             :         
     617           6 :         if (is_struct) {
     618           5 :                 php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
     619             :         } else {
     620           1 :                 php_wddx_add_chunk_static(packet, WDDX_ARRAY_E);
     621             :         }
     622           6 : }
     623             : /* }}} */
     624             : 
     625             : /* {{{ php_wddx_serialize_var
     626             :  */
     627         222 : 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         222 :         if (name) {
     635          25 :                 name_esc = php_escape_html_entities(name, name_len, &name_esc_len, 0, ENT_QUOTES, NULL TSRMLS_CC);
     636          25 :                 tmp_buf = emalloc(name_esc_len + sizeof(WDDX_VAR_S));
     637          25 :                 snprintf(tmp_buf, name_esc_len + sizeof(WDDX_VAR_S), WDDX_VAR_S, name_esc);
     638          25 :                 php_wddx_add_chunk(packet, tmp_buf);
     639          25 :                 efree(tmp_buf);
     640          25 :                 efree(name_esc);
     641             :         }
     642             :         
     643         222 :         switch(Z_TYPE_P(var)) {
     644             :                 case IS_STRING:
     645         204 :                         php_wddx_serialize_string(packet, var TSRMLS_CC);
     646         204 :                         break;
     647             :                         
     648             :                 case IS_LONG:
     649             :                 case IS_DOUBLE:
     650           3 :                         php_wddx_serialize_number(packet, var);
     651           3 :                         break;
     652             : 
     653             :                 case IS_BOOL:
     654           3 :                         php_wddx_serialize_boolean(packet, var);
     655           3 :                         break;
     656             : 
     657             :                 case IS_NULL:
     658           2 :                         php_wddx_serialize_unset(packet);
     659           2 :                         break;
     660             :                 
     661             :                 case IS_ARRAY:
     662           6 :                         ht = Z_ARRVAL_P(var);
     663           6 :                         if (ht->nApplyCount > 1) {
     664           0 :                                 php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "WDDX doesn't support circular references");
     665           0 :                                 return;
     666             :                         }
     667           6 :                         ht->nApplyCount++;                                                                                                                   
     668           6 :                         php_wddx_serialize_array(packet, var);
     669           6 :                         ht->nApplyCount--;
     670           6 :                         break;
     671             : 
     672             :                 case IS_OBJECT:
     673           4 :                         ht = Z_OBJPROP_P(var);
     674           4 :                         if (ht->nApplyCount > 1) {
     675           0 :                                 php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "WDDX doesn't support circular references");
     676           0 :                                 return;
     677             :                         }
     678           4 :                         ht->nApplyCount++;
     679           4 :                         php_wddx_serialize_object(packet, var);
     680           4 :                         ht->nApplyCount--;
     681             :                         break;
     682             :         }
     683             :         
     684         222 :         if (name) {
     685          25 :                 php_wddx_add_chunk_static(packet, WDDX_VAR_E);
     686             :         }
     687             : }
     688             : /* }}} */
     689             : 
     690             : /* {{{ php_wddx_add_var
     691             :  */
     692          14 : 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          14 :         if (Z_TYPE_P(name_var) == IS_STRING) {
     699           7 :                 if (!EG(active_symbol_table)) {
     700           0 :                         zend_rebuild_symbol_table(TSRMLS_C);
     701             :                 }
     702          14 :                 if (zend_hash_find(EG(active_symbol_table), Z_STRVAL_P(name_var),
     703           7 :                                                         Z_STRLEN_P(name_var)+1, (void**)&val) != FAILURE) {
     704           7 :                         php_wddx_serialize_var(packet, *val, Z_STRVAL_P(name_var), Z_STRLEN_P(name_var) TSRMLS_CC);
     705             :                 }               
     706           7 :         } else if (Z_TYPE_P(name_var) == IS_ARRAY || Z_TYPE_P(name_var) == IS_OBJECT)   {
     707           7 :                 int is_array = Z_TYPE_P(name_var) == IS_ARRAY;
     708             :                 
     709           7 :                 target_hash = HASH_OF(name_var);
     710             :                 
     711           7 :                 if (is_array && target_hash->nApplyCount > 1) {
     712           1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
     713           1 :                         return;
     714             :                 }
     715             : 
     716           6 :                 zend_hash_internal_pointer_reset(target_hash);
     717             : 
     718          19 :                 while(zend_hash_get_current_data(target_hash, (void**)&val) == SUCCESS) {
     719           7 :                         if (is_array) {
     720           7 :                                 target_hash->nApplyCount++;
     721             :                         }
     722             : 
     723           7 :                         php_wddx_add_var(packet, *val);
     724             : 
     725           7 :                         if (is_array) {
     726           7 :                                 target_hash->nApplyCount--;
     727             :                         }
     728           7 :                         zend_hash_move_forward(target_hash);
     729             :                 }
     730             :         }
     731             : }
     732             : /* }}} */
     733             : 
     734             : /* {{{ php_wddx_push_element
     735             :  */
     736        1681 : static void php_wddx_push_element(void *user_data, const XML_Char *name, const XML_Char **atts)
     737             : {
     738             :         st_entry ent;
     739        1681 :         wddx_stack *stack = (wddx_stack *)user_data;
     740             :         
     741        1681 :         if (!strcmp(name, EL_PACKET)) {
     742             :                 int i;
     743             :                 
     744        1173 :                 if (atts) for (i=0; atts[i]; i++) {
     745         782 :                         if (!strcmp(atts[i], EL_VERSION)) {
     746             :                                 /* nothing for now */
     747             :                         }
     748             :                 }
     749        1290 :         } else if (!strcmp(name, EL_STRING)) {
     750         403 :                 ent.type = ST_STRING;
     751         403 :                 SET_STACK_VARNAME;
     752             :                 
     753         403 :                 ALLOC_ZVAL(ent.data);
     754         403 :                 INIT_PZVAL(ent.data);
     755         403 :                 Z_TYPE_P(ent.data) = IS_STRING;
     756         403 :                 Z_STRVAL_P(ent.data) = STR_EMPTY_ALLOC();
     757         403 :                 Z_STRLEN_P(ent.data) = 0;
     758         403 :                 wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
     759         887 :         } else if (!strcmp(name, EL_BINARY)) {
     760           1 :                 ent.type = ST_BINARY;
     761           1 :                 SET_STACK_VARNAME;
     762             :                 
     763           1 :                 ALLOC_ZVAL(ent.data);
     764           1 :                 INIT_PZVAL(ent.data);
     765           1 :                 Z_TYPE_P(ent.data) = IS_STRING;
     766           1 :                 Z_STRVAL_P(ent.data) = STR_EMPTY_ALLOC();
     767           1 :                 Z_STRLEN_P(ent.data) = 0;
     768           1 :                 wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
     769         886 :         } else if (!strcmp(name, EL_CHAR)) {
     770             :                 int i;
     771             :                 
     772           0 :                 if (atts) for (i = 0; atts[i]; i++) {
     773           0 :                         if (!strcmp(atts[i], EL_CHAR_CODE) && atts[++i] && atts[i][0]) {
     774             :                                 char tmp_buf[2];
     775             : 
     776           0 :                                 snprintf(tmp_buf, sizeof(tmp_buf), "%c", (char)strtol(atts[i], NULL, 16));
     777           0 :                                 php_wddx_process_data(user_data, tmp_buf, strlen(tmp_buf));
     778           0 :                                 break;
     779             :                         }
     780             :                 }
     781         886 :         } else if (!strcmp(name, EL_NUMBER)) {
     782          11 :                 ent.type = ST_NUMBER;
     783          11 :                 SET_STACK_VARNAME;
     784             :                 
     785          11 :                 ALLOC_ZVAL(ent.data);
     786          11 :                 INIT_PZVAL(ent.data);
     787          11 :                 Z_TYPE_P(ent.data) = IS_LONG;
     788          11 :                 Z_LVAL_P(ent.data) = 0;
     789          11 :                 wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
     790         875 :         } else if (!strcmp(name, EL_BOOLEAN)) {
     791             :                 int i;
     792             : 
     793           4 :                 if (atts) for (i = 0; atts[i]; i++) {
     794           4 :                         if (!strcmp(atts[i], EL_VALUE) && atts[++i] && atts[i][0]) {
     795           4 :                                 ent.type = ST_BOOLEAN;
     796           4 :                                 SET_STACK_VARNAME;
     797             : 
     798           4 :                                 ALLOC_ZVAL(ent.data);
     799           4 :                                 INIT_PZVAL(ent.data);
     800           4 :                                 Z_TYPE_P(ent.data) = IS_BOOL;
     801           4 :                                 wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
     802           4 :                                 php_wddx_process_data(user_data, atts[i], strlen(atts[i]));
     803           4 :                                 break;
     804             :                         }
     805             :                 }
     806         871 :         } else if (!strcmp(name, EL_NULL)) {
     807           3 :                 ent.type = ST_NULL;
     808           3 :                 SET_STACK_VARNAME;
     809             : 
     810           3 :                 ALLOC_ZVAL(ent.data);
     811           3 :                 INIT_PZVAL(ent.data);
     812           3 :                 ZVAL_NULL(ent.data);
     813             :                 
     814           3 :                 wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
     815         868 :         } else if (!strcmp(name, EL_ARRAY)) {
     816           3 :                 ent.type = ST_ARRAY;
     817           3 :                 SET_STACK_VARNAME;
     818             :                 
     819           3 :                 ALLOC_ZVAL(ent.data);
     820           3 :                 array_init(ent.data);
     821           3 :                 INIT_PZVAL(ent.data);
     822           3 :                 wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
     823         865 :         } else if (!strcmp(name, EL_STRUCT)) {
     824          21 :                 ent.type = ST_STRUCT;
     825          21 :                 SET_STACK_VARNAME;
     826             :                 
     827          21 :                 ALLOC_ZVAL(ent.data);
     828          21 :                 array_init(ent.data);
     829          21 :                 INIT_PZVAL(ent.data);
     830          21 :                 wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
     831         844 :         } else if (!strcmp(name, EL_VAR)) {
     832             :                 int i;
     833             :                 
     834          49 :                 if (atts) for (i = 0; atts[i]; i++) {
     835          48 :                         if (!strcmp(atts[i], EL_NAME) && atts[++i] && atts[i][0]) {
     836          48 :                                 stack->varname = estrdup(atts[i]);
     837          48 :                                 break;
     838             :                         }
     839             :                 }
     840         795 :         } else if (!strcmp(name, EL_RECORDSET)) {
     841             :                 int i;
     842             : 
     843           1 :                 ent.type = ST_RECORDSET;
     844           1 :                 SET_STACK_VARNAME;
     845           1 :                 MAKE_STD_ZVAL(ent.data);
     846           1 :                 array_init(ent.data);
     847             : 
     848           3 :                 if (atts) for (i = 0; atts[i]; i++) {
     849           3 :                         if (!strcmp(atts[i], "fieldNames") && atts[++i] && atts[i][0]) {
     850             :                                 zval *tmp;
     851             :                                 char *key;
     852             :                                 char *p1, *p2, *endp;
     853             : 
     854           1 :                                 endp = (char *)atts[i] + strlen(atts[i]);
     855           1 :                                 p1 = (char *)atts[i];
     856           3 :                                 while ((p2 = php_memnstr(p1, ",", sizeof(",")-1, endp)) != NULL) {
     857           1 :                                         key = estrndup(p1, p2 - p1);
     858           1 :                                         MAKE_STD_ZVAL(tmp);
     859           1 :                                         array_init(tmp);
     860           1 :                                         add_assoc_zval_ex(ent.data, key, p2 - p1 + 1, tmp);
     861           1 :                                         p1 = p2 + sizeof(",")-1;
     862           1 :                                         efree(key);
     863             :                                 }
     864             : 
     865           1 :                                 if (p1 <= endp) {
     866           1 :                                         MAKE_STD_ZVAL(tmp);
     867           1 :                                         array_init(tmp);
     868           1 :                                         add_assoc_zval_ex(ent.data, p1, endp - p1 + 1, tmp);
     869             :                                 }
     870             : 
     871           1 :                                 break;
     872             :                         }
     873             :                 }
     874             : 
     875           1 :                 wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
     876         794 :         } else if (!strcmp(name, EL_FIELD)) {
     877             :                 int i;
     878             :                 st_entry ent;
     879             : 
     880           2 :                 ent.type = ST_FIELD;
     881           2 :                 ent.varname = NULL;
     882           2 :                 ent.data = NULL;
     883             : 
     884           2 :                 if (atts) for (i = 0; atts[i]; i++) {
     885           2 :                         if (!strcmp(atts[i], EL_NAME) && atts[++i] && atts[i][0]) {
     886             :                                 st_entry *recordset;
     887             :                                 zval **field;
     888             :  
     889           6 :                                 if (wddx_stack_top(stack, (void**)&recordset) == SUCCESS &&
     890           2 :                                         recordset->type == ST_RECORDSET &&
     891           2 :                                         zend_hash_find(Z_ARRVAL_P(recordset->data), (char*)atts[i], strlen(atts[i])+1, (void**)&field) == SUCCESS) {
     892           2 :                                         ent.data = *field;
     893             :                                 }
     894             :                                 
     895           2 :                                 break;
     896             :                         }
     897             :                 }
     898             : 
     899           2 :                 wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
     900         792 :         } else if (!strcmp(name, EL_DATETIME)) {
     901           3 :                 ent.type = ST_DATETIME;
     902           3 :                 SET_STACK_VARNAME;
     903             :                 
     904           3 :                 ALLOC_ZVAL(ent.data);
     905           3 :                 INIT_PZVAL(ent.data);
     906           3 :                 Z_TYPE_P(ent.data) = IS_LONG;
     907           3 :                 wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
     908             :         }
     909        1681 : }
     910             : /* }}} */
     911             : 
     912             : /* {{{ php_wddx_pop_element
     913             :  */
     914        1677 : static void php_wddx_pop_element(void *user_data, const XML_Char *name)
     915             : {
     916             :         st_entry                        *ent1, *ent2;
     917        1677 :         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        1677 :         if (stack->top == 0) {
     926         396 :                 return;
     927             :         }
     928             : 
     929        7685 :         if (!strcmp(name, EL_STRING) || !strcmp(name, EL_NUMBER) ||
     930        1730 :                 !strcmp(name, EL_BOOLEAN) || !strcmp(name, EL_NULL) ||
     931        1717 :                 !strcmp(name, EL_ARRAY) || !strcmp(name, EL_STRUCT) ||
     932        1673 :                 !strcmp(name, EL_RECORDSET) || !strcmp(name, EL_BINARY) ||
     933         835 :                 !strcmp(name, EL_DATETIME)) {
     934         449 :                 wddx_stack_top(stack, (void**)&ent1);
     935             : 
     936         449 :                 if (!strcmp(name, EL_BINARY)) {
     937           1 :                         int new_len=0;
     938             :                         unsigned char *new_str;
     939             : 
     940           1 :                         new_str = php_base64_decode(Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data), &new_len);
     941           1 :                         STR_FREE(Z_STRVAL_P(ent1->data));
     942           1 :                         Z_STRVAL_P(ent1->data) = new_str;
     943           1 :                         Z_STRLEN_P(ent1->data) = new_len;
     944             :                 }
     945             : 
     946             :                 /* Call __wakeup() method on the object. */
     947         449 :                 if (Z_TYPE_P(ent1->data) == IS_OBJECT) {
     948           2 :                         zval *fname, *retval = NULL;
     949             : 
     950           2 :                         MAKE_STD_ZVAL(fname);
     951           2 :                         ZVAL_STRING(fname, "__wakeup", 1);
     952             : 
     953           2 :                         call_user_function_ex(NULL, &ent1->data, fname, &retval, 0, 0, 0, NULL TSRMLS_CC);
     954             : 
     955             :                         zval_dtor(fname);
     956           2 :                         FREE_ZVAL(fname);
     957           2 :                         if (retval) {
     958           0 :                                 zval_ptr_dtor(&retval);
     959             :                         }
     960             :                 }
     961             : 
     962         449 :                 if (stack->top > 1) {
     963          58 :                         stack->top--;
     964          58 :                         wddx_stack_top(stack, (void**)&ent2);
     965             :                         
     966             :                         /* if non-existent field */
     967          58 :                         if (ent2->type == ST_FIELD && ent2->data == NULL) {
     968           0 :                                 zval_ptr_dtor(&ent1->data);
     969           0 :                                 efree(ent1);
     970           0 :                                 return;
     971             :                         }
     972             :                         
     973          58 :                         if (Z_TYPE_P(ent2->data) == IS_ARRAY || Z_TYPE_P(ent2->data) == IS_OBJECT) {
     974          58 :                                 target_hash = HASH_OF(ent2->data);
     975             : 
     976          58 :                                 if (ent1->varname) {
     977          54 :                                         if (!strcmp(ent1->varname, PHP_CLASS_NAME_VAR) &&
     978           4 :                                                 Z_TYPE_P(ent1->data) == IS_STRING && Z_STRLEN_P(ent1->data)) {
     979           2 :                                                 zend_bool incomplete_class = 0;
     980             : 
     981           2 :                                                 zend_str_tolower(Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data));
     982           4 :                                                 if (zend_hash_find(EG(class_table), Z_STRVAL_P(ent1->data),
     983           2 :                                                                                    Z_STRLEN_P(ent1->data)+1, (void **) &pce)==FAILURE) {
     984           0 :                                                         incomplete_class = 1;
     985           0 :                                                         pce = &PHP_IC_ENTRY;
     986             :                                                 }
     987             : 
     988             :                                                 /* Initialize target object */
     989           2 :                                                 MAKE_STD_ZVAL(obj);
     990           2 :                                                 object_init_ex(obj, *pce);
     991             :                                                 
     992             :                                                 /* Merge current hashtable with object's default properties */
     993           2 :                                                 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           2 :                                                 if (incomplete_class) {
     999           0 :                                                         php_store_class_name(obj, Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data));
    1000             :                                                 }
    1001             : 
    1002             :                                                 /* Clean up old array entry */
    1003           2 :                                                 zval_ptr_dtor(&ent2->data);
    1004             :                                                 
    1005             :                                                 /* Set stack entry to point to the newly created object */
    1006           2 :                                                 ent2->data = obj;
    1007             :                                                 
    1008             :                                                 /* Clean up class name var entry */
    1009           2 :                                                 zval_ptr_dtor(&ent1->data);
    1010          46 :                                         } else if (Z_TYPE_P(ent2->data) == IS_OBJECT) {
    1011           3 :                                                 zend_class_entry *old_scope = EG(scope);
    1012             :         
    1013           3 :                                                 EG(scope) = Z_OBJCE_P(ent2->data);
    1014           3 :                                                 Z_DELREF_P(ent1->data);
    1015           3 :                                                 add_property_zval(ent2->data, ent1->varname, ent1->data);
    1016           3 :                                                 EG(scope) = old_scope;
    1017             :                                         } else {
    1018          43 :                                                 zend_symtable_update(target_hash, ent1->varname, strlen(ent1->varname)+1, &ent1->data, sizeof(zval *), NULL);
    1019             :                                         }
    1020          48 :                                         efree(ent1->varname);
    1021             :                                 } else  {
    1022          10 :                                         zend_hash_next_index_insert(target_hash, &ent1->data, sizeof(zval *), NULL);
    1023             :                                 }
    1024             :                         }
    1025          58 :                         efree(ent1);
    1026             :                 } else {
    1027         391 :                         stack->done = 1;
    1028             :                 }
    1029         832 :         } else if (!strcmp(name, EL_VAR) && stack->varname) {
    1030           0 :                 efree(stack->varname);
    1031         832 :         } else if (!strcmp(name, EL_FIELD)) {
    1032             :                 st_entry *ent;
    1033           2 :                 wddx_stack_top(stack, (void **)&ent);
    1034           2 :                 efree(ent);
    1035           2 :                 stack->top--;
    1036             :         }
    1037             : }
    1038             : /* }}} */
    1039             : 
    1040             : /* {{{ php_wddx_process_data
    1041             :  */
    1042         527 : static void php_wddx_process_data(void *user_data, const XML_Char *s, int len)
    1043             : {
    1044             :         st_entry *ent;
    1045         527 :         wddx_stack *stack = (wddx_stack *)user_data;
    1046             :         TSRMLS_FETCH();
    1047             : 
    1048         527 :         if (!wddx_stack_is_empty(stack) && !stack->done) {
    1049         508 :                 wddx_stack_top(stack, (void**)&ent);
    1050         508 :                 switch (Z_TYPE_P(ent)) {
    1051             :                         case ST_STRING: 
    1052         403 :                                 if (Z_STRLEN_P(ent->data) == 0) {
    1053         403 :                                         STR_FREE(Z_STRVAL_P(ent->data));
    1054         403 :                                         Z_STRVAL_P(ent->data) = estrndup(s, len);
    1055         403 :                                         Z_STRLEN_P(ent->data) = len;
    1056             :                                 } else {
    1057           0 :                                         Z_STRVAL_P(ent->data) = erealloc(Z_STRVAL_P(ent->data), Z_STRLEN_P(ent->data) + len + 1);
    1058           0 :                                         memcpy(Z_STRVAL_P(ent->data) + Z_STRLEN_P(ent->data), s, len);
    1059           0 :                                         Z_STRLEN_P(ent->data) += len;
    1060           0 :                                         Z_STRVAL_P(ent->data)[Z_STRLEN_P(ent->data)] = '\0';
    1061             :                                 }
    1062         403 :                                 break;
    1063             : 
    1064             :                         case ST_BINARY:
    1065           1 :                                 if (Z_STRLEN_P(ent->data) == 0) {
    1066           1 :                                         STR_FREE(Z_STRVAL_P(ent->data));
    1067           1 :                                         Z_STRVAL_P(ent->data) = estrndup(s, len + 1);
    1068             :                                 } else {
    1069           0 :                                         Z_STRVAL_P(ent->data) = erealloc(Z_STRVAL_P(ent->data), Z_STRLEN_P(ent->data) + len + 1);
    1070           0 :                                         memcpy(Z_STRVAL_P(ent->data) + Z_STRLEN_P(ent->data), s, len);
    1071             :                                 }
    1072           1 :                                 Z_STRLEN_P(ent->data) += len;
    1073           1 :                                 Z_STRVAL_P(ent->data)[Z_STRLEN_P(ent->data)] = '\0';
    1074           1 :                                 break;
    1075             : 
    1076             :                         case ST_NUMBER:
    1077           9 :                                 Z_TYPE_P(ent->data) = IS_STRING;
    1078           9 :                                 Z_STRLEN_P(ent->data) = len;
    1079           9 :                                 Z_STRVAL_P(ent->data) = estrndup(s, len);
    1080           9 :                                 convert_scalar_to_number(ent->data TSRMLS_CC);
    1081           9 :                                 break;
    1082             : 
    1083             :                         case ST_BOOLEAN:
    1084           4 :                                 if (!strcmp(s, "true")) {
    1085           4 :                                         Z_LVAL_P(ent->data) = 1;
    1086           0 :                                 } else if (!strcmp(s, "false")) {
    1087           0 :                                         Z_LVAL_P(ent->data) = 0;
    1088             :                                 } else {
    1089           0 :                                         stack->top--;
    1090           0 :                                         zval_ptr_dtor(&ent->data);
    1091           0 :                                         if (ent->varname)
    1092           0 :                                                 efree(ent->varname);
    1093           0 :                                         efree(ent);
    1094             :                                 }
    1095           4 :                                 break;
    1096             : 
    1097             :                         case ST_DATETIME: {
    1098             :                                 char *tmp;
    1099             : 
    1100           3 :                                 tmp = emalloc(len + 1);
    1101           3 :                                 memcpy(tmp, s, len);
    1102           3 :                                 tmp[len] = '\0';
    1103             : 
    1104           3 :                                 Z_LVAL_P(ent->data) = php_parse_date(tmp, NULL);
    1105             :                                 /* date out of range < 1969 or > 2038 */
    1106           3 :                                 if (Z_LVAL_P(ent->data) == -1) {
    1107           0 :                                         Z_TYPE_P(ent->data) = IS_STRING;
    1108           0 :                                         Z_STRLEN_P(ent->data) = len;
    1109           0 :                                         Z_STRVAL_P(ent->data) = estrndup(s, len);
    1110             :                                 }
    1111           3 :                                 efree(tmp);
    1112             :                         }
    1113             :                                 break;
    1114             : 
    1115             :                         default:
    1116             :                                 break;
    1117             :                 }
    1118             :         }
    1119         527 : }
    1120             : /* }}} */
    1121             : 
    1122             : /* {{{ php_wddx_deserialize_ex
    1123             :  */
    1124         392 : 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         392 :         wddx_stack_init(&stack);
    1132         392 :         parser = XML_ParserCreate("UTF-8");
    1133             : 
    1134         392 :         XML_SetUserData(parser, &stack);
    1135         392 :         XML_SetElementHandler(parser, php_wddx_push_element, php_wddx_pop_element);
    1136         392 :         XML_SetCharacterDataHandler(parser, php_wddx_process_data);
    1137             :         
    1138         392 :         XML_Parse(parser, value, vallen, 1);
    1139             :         
    1140         392 :         XML_ParserFree(parser);
    1141             : 
    1142         392 :         if (stack.top == 1) {
    1143         392 :                 wddx_stack_top(&stack, (void**)&ent);
    1144         392 :                 *return_value = *(ent->data);
    1145             :                 zval_copy_ctor(return_value);
    1146         392 :                 retval = SUCCESS;
    1147             :         } else {
    1148           0 :                 retval = FAILURE;
    1149             :         }
    1150             :                 
    1151         392 :         wddx_stack_destroy(&stack);
    1152             : 
    1153         392 :         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         194 : PHP_FUNCTION(wddx_serialize_value)
    1160             : {
    1161             :         zval *var;
    1162         194 :         char *comment = NULL;
    1163         194 :         int comment_len = 0;
    1164             :         wddx_packet *packet;
    1165             :         
    1166         194 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|s", &var, &comment, &comment_len) == FAILURE) {
    1167           0 :                 return;
    1168             :         }
    1169             :         
    1170         194 :         packet = php_wddx_constructor();
    1171             : 
    1172         194 :         php_wddx_packet_start(packet, comment, comment_len);
    1173         194 :         php_wddx_serialize_var(packet, var, NULL, 0 TSRMLS_CC);
    1174         194 :         php_wddx_packet_end(packet);
    1175             :                                         
    1176         194 :         ZVAL_STRINGL(return_value, packet->c, packet->len, 1);
    1177         194 :         smart_str_free(packet);
    1178         194 :         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           4 : PHP_FUNCTION(wddx_serialize_vars)
    1185             : {
    1186             :         int num_args, i;
    1187             :         wddx_packet *packet;
    1188           4 :         zval ***args = NULL;
    1189             : 
    1190           4 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &num_args) == FAILURE) {
    1191           0 :                 return;
    1192             :         }
    1193             :                 
    1194           4 :         packet = php_wddx_constructor();
    1195             : 
    1196           4 :         php_wddx_packet_start(packet, NULL, 0);
    1197           4 :         php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
    1198             :         
    1199           8 :         for (i=0; i<num_args; i++) {
    1200           4 :                 if (Z_TYPE_PP(args[i]) != IS_ARRAY && Z_TYPE_PP(args[i]) != IS_OBJECT) {
    1201           2 :                         convert_to_string_ex(args[i]);
    1202             :                 }
    1203           4 :                 php_wddx_add_var(packet, *args[i]);
    1204             :         }       
    1205             :         
    1206           4 :         php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
    1207           4 :         php_wddx_packet_end(packet);
    1208             : 
    1209           4 :         efree(args);
    1210             : 
    1211           4 :         ZVAL_STRINGL(return_value, packet->c, packet->len, 1);
    1212           4 :         smart_str_free(packet);
    1213           4 :         efree(packet);
    1214             : }
    1215             : /* }}} */
    1216             : 
    1217             : /* {{{ php_wddx_constructor
    1218             :  */
    1219         200 : wddx_packet *php_wddx_constructor(void)
    1220             : {
    1221             :         smart_str *packet;
    1222             : 
    1223         200 :         packet = (smart_str *)emalloc(sizeof(smart_str));
    1224         200 :         packet->c = NULL;
    1225             : 
    1226         200 :         return packet;
    1227             : }
    1228             : /* }}} */
    1229             : 
    1230             : /* {{{ php_wddx_destructor
    1231             :  */
    1232           1 : void php_wddx_destructor(wddx_packet *packet)
    1233             : {
    1234           1 :         smart_str_free(packet);
    1235           1 :         efree(packet);
    1236           1 : }
    1237             : /* }}} */
    1238             : 
    1239             : /* {{{ proto resource wddx_packet_start([string comment])
    1240             :    Starts a WDDX packet with optional comment and returns the packet id */
    1241           1 : PHP_FUNCTION(wddx_packet_start)
    1242             : {
    1243           1 :         char *comment = NULL;
    1244           1 :         int comment_len = 0;
    1245             :         wddx_packet *packet;
    1246             : 
    1247           1 :         comment = NULL;
    1248             : 
    1249           1 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &comment, &comment_len) == FAILURE) {
    1250           0 :                 return;
    1251             :         }
    1252             : 
    1253           1 :         packet = php_wddx_constructor();
    1254             :         
    1255           1 :         php_wddx_packet_start(packet, comment, comment_len);
    1256           1 :         php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
    1257             : 
    1258           1 :         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           1 : PHP_FUNCTION(wddx_packet_end)
    1265             : {
    1266             :         zval *packet_id;
    1267           1 :         wddx_packet *packet = NULL;
    1268             :         
    1269           1 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &packet_id) == FAILURE) {
    1270           0 :                 return;
    1271             :         }
    1272             : 
    1273           1 :         ZEND_FETCH_RESOURCE(packet, wddx_packet *, &packet_id, -1, "WDDX packet ID", le_wddx);
    1274             :                         
    1275           1 :         php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);       
    1276             :         
    1277           1 :         php_wddx_packet_end(packet);
    1278             : 
    1279           1 :         ZVAL_STRINGL(return_value, packet->c, packet->len, 1);
    1280             : 
    1281           1 :         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           1 : PHP_FUNCTION(wddx_add_vars)
    1288             : {
    1289             :         int num_args, i;
    1290           1 :         zval ***args = NULL;
    1291             :         zval *packet_id;
    1292           1 :         wddx_packet *packet = NULL;
    1293             :         
    1294           1 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r+", &packet_id, &args, &num_args) == FAILURE) {
    1295           0 :                 return;
    1296             :         }
    1297             : 
    1298           1 :         if (!ZEND_FETCH_RESOURCE_NO_RETURN(packet, wddx_packet *, &packet_id, -1, "WDDX packet ID", le_wddx)) {
    1299           0 :                 efree(args);
    1300           0 :                 RETURN_FALSE;
    1301             :         }
    1302             :         
    1303           1 :         if (!packet) {
    1304           0 :                 efree(args);
    1305           0 :                 RETURN_FALSE;
    1306             :         }
    1307             :                 
    1308           4 :         for (i=0; i<num_args; i++) {
    1309           3 :                 if (Z_TYPE_PP(args[i]) != IS_ARRAY && Z_TYPE_PP(args[i]) != IS_OBJECT) {
    1310           2 :                         convert_to_string_ex(args[i]);
    1311             :                 }
    1312           3 :                 php_wddx_add_var(packet, (*args[i]));
    1313             :         }
    1314             : 
    1315           1 :         efree(args);
    1316           1 :         RETURN_TRUE;
    1317             : }
    1318             : /* }}} */
    1319             : 
    1320             : /* {{{ proto mixed wddx_deserialize(mixed packet) 
    1321             :    Deserializes given packet and returns a PHP value */
    1322         391 : PHP_FUNCTION(wddx_deserialize)
    1323             : {
    1324             :         zval *packet;
    1325             :         char *payload;
    1326             :         int payload_len;
    1327         391 :         php_stream *stream = NULL;
    1328             :         
    1329         391 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &packet) == FAILURE) {
    1330           0 :                 return;
    1331             :         }
    1332             : 
    1333         391 :         if (Z_TYPE_P(packet) == IS_STRING) {
    1334         390 :                 payload         = Z_STRVAL_P(packet);
    1335         390 :                 payload_len = Z_STRLEN_P(packet);
    1336           1 :         } else if (Z_TYPE_P(packet) == IS_RESOURCE) {
    1337           1 :                 php_stream_from_zval(stream, &packet);
    1338           1 :                 if (stream) {
    1339           1 :                         payload_len = php_stream_copy_to_mem(stream, &payload, PHP_STREAM_COPY_ALL, 0);
    1340             :                 }
    1341             :         } else {
    1342           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expecting parameter 1 to be a string or a stream");
    1343           0 :                 return;
    1344             :         }
    1345             : 
    1346         391 :         if (payload_len == 0) {
    1347           0 :                 return;
    1348             :         }
    1349             : 
    1350         391 :         php_wddx_deserialize_ex(payload, payload_len, return_value);
    1351             :                 
    1352         391 :         if (stream) {
    1353           1 :                 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             :  */

Generated by: LCOV version 1.10

Generated at Thu, 10 Apr 2014 08:54:00 +0000 (8 days ago)

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