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-23 Instrumented lines: 584
Code covered: 83.7 % Executed lines: 489
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:43 +0000 (36 hours ago)

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