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

LTP GCOV extension - code coverage report
Current view: directory - wddx - wddx.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 590
Code covered: 89.5 % Executed lines: 528
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:24 +0000 (5 days ago)

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