root/ext/standard/var.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. php_array_element_dump
  2. php_object_property_dump
  3. php_var_dump
  4. PHP_FUNCTION
  5. zval_array_element_dump
  6. zval_object_property_dump
  7. php_debug_zval_dump
  8. PHP_FUNCTION
  9. php_array_element_export
  10. php_object_element_export
  11. php_var_export_ex
  12. php_var_export
  13. PHP_FUNCTION
  14. php_add_var_hash
  15. php_var_serialize_long
  16. php_var_serialize_string
  17. php_var_serialize_class_name
  18. php_var_serialize_class
  19. php_var_serialize_intern
  20. php_var_serialize
  21. PHP_FUNCTION
  22. PHP_FUNCTION
  23. PHP_FUNCTION
  24. PHP_FUNCTION

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 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    | Authors: Jani Lehtimäki <jkl@njet.net>                               |
  16    |          Thies C. Arntzen <thies@thieso.net>                         |
  17    |          Sascha Schumann <sascha@schumann.cx>                        |
  18    +----------------------------------------------------------------------+
  19 */
  20 
  21 /* $Id$ */
  22 
  23 /* {{{ includes
  24 */
  25 #include <stdio.h>
  26 #include <stdlib.h>
  27 #include <errno.h>
  28 #include "php.h"
  29 #include "php_string.h"
  30 #include "php_var.h"
  31 #include "zend_smart_str.h"
  32 #include "basic_functions.h"
  33 #include "php_incomplete_class.h"
  34 
  35 #define COMMON (is_ref ? "&" : "")
  36 /* }}} */
  37 
  38 static void php_array_element_dump(zval *zv, zend_ulong index, zend_string *key, int level) /* {{{ */
  39 {
  40         if (key == NULL) { /* numeric key */
  41                 php_printf("%*c[" ZEND_LONG_FMT "]=>\n", level + 1, ' ', index);
  42         } else { /* string key */
  43                 php_printf("%*c[\"", level + 1, ' ');
  44                 PHPWRITE(ZSTR_VAL(key), ZSTR_LEN(key));
  45                 php_printf("\"]=>\n");
  46         }
  47         php_var_dump(zv, level + 2);
  48 }
  49 /* }}} */
  50 
  51 static void php_object_property_dump(zval *zv, zend_ulong index, zend_string *key, int level) /* {{{ */
  52 {
  53         const char *prop_name, *class_name;
  54 
  55         if (key == NULL) { /* numeric key */
  56                 php_printf("%*c[" ZEND_LONG_FMT "]=>\n", level + 1, ' ', index);
  57         } else { /* string key */
  58                 int unmangle = zend_unmangle_property_name(key, &class_name, &prop_name);
  59                 php_printf("%*c[", level + 1, ' ');
  60 
  61                 if (class_name && unmangle == SUCCESS) {
  62                         if (class_name[0] == '*') {
  63                                 php_printf("\"%s\":protected", prop_name);
  64                         } else {
  65                                 php_printf("\"%s\":\"%s\":private", prop_name, class_name);
  66                         }
  67                 } else {
  68                         php_printf("\"");
  69                         PHPWRITE(ZSTR_VAL(key), ZSTR_LEN(key));
  70                         php_printf("\"");
  71                 }
  72                 ZEND_PUTS("]=>\n");
  73         }
  74         php_var_dump(zv, level + 2);
  75 }
  76 /* }}} */
  77 
  78 PHPAPI void php_var_dump(zval *struc, int level) /* {{{ */
  79 {
  80         HashTable *myht;
  81         zend_string *class_name;
  82         int is_temp;
  83         int is_ref = 0;
  84         zend_ulong num;
  85         zend_string *key;
  86         zval *val;
  87         uint32_t count;
  88 
  89         if (level > 1) {
  90                 php_printf("%*c", level - 1, ' ');
  91         }
  92 
  93 again:
  94         switch (Z_TYPE_P(struc)) {
  95                 case IS_FALSE:
  96                         php_printf("%sbool(false)\n", COMMON);
  97                         break;
  98                 case IS_TRUE:
  99                         php_printf("%sbool(true)\n", COMMON);
 100                         break;
 101                 case IS_NULL:
 102                         php_printf("%sNULL\n", COMMON);
 103                         break;
 104                 case IS_LONG:
 105                         php_printf("%sint(" ZEND_LONG_FMT ")\n", COMMON, Z_LVAL_P(struc));
 106                         break;
 107                 case IS_DOUBLE:
 108                         php_printf("%sfloat(%.*G)\n", COMMON, (int) EG(precision), Z_DVAL_P(struc));
 109                         break;
 110                 case IS_STRING:
 111                         php_printf("%sstring(%zd) \"", COMMON, Z_STRLEN_P(struc));
 112                         PHPWRITE(Z_STRVAL_P(struc), Z_STRLEN_P(struc));
 113                         PUTS("\"\n");
 114                         break;
 115                 case IS_ARRAY:
 116                         myht = Z_ARRVAL_P(struc);
 117                         if (level > 1 && ZEND_HASH_APPLY_PROTECTION(myht) && ++myht->u.v.nApplyCount > 1) {
 118                                 PUTS("*RECURSION*\n");
 119                                 --myht->u.v.nApplyCount;
 120                                 return;
 121                         }
 122                         count = zend_array_count(myht);
 123                         php_printf("%sarray(%d) {\n", COMMON, count);
 124                         is_temp = 0;
 125 
 126                         ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) {
 127                                 php_array_element_dump(val, num, key, level);
 128                         } ZEND_HASH_FOREACH_END();
 129                         if (level > 1 && ZEND_HASH_APPLY_PROTECTION(myht)) {
 130                                 --myht->u.v.nApplyCount;
 131                         }
 132                         if (is_temp) {
 133                                 zend_hash_destroy(myht);
 134                                 efree(myht);
 135                         }
 136                         if (level > 1) {
 137                                 php_printf("%*c", level-1, ' ');
 138                         }
 139                         PUTS("}\n");
 140                         break;
 141                 case IS_OBJECT:
 142                         if (Z_OBJ_APPLY_COUNT_P(struc) > 0) {
 143                                 PUTS("*RECURSION*\n");
 144                                 return;
 145                         }
 146                         Z_OBJ_INC_APPLY_COUNT_P(struc);
 147 
 148                         myht = Z_OBJDEBUG_P(struc, is_temp);
 149                         class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc));
 150                         php_printf("%sobject(%s)#%d (%d) {\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? zend_array_count(myht) : 0);
 151                         zend_string_release(class_name);
 152 
 153                         if (myht) {
 154                                 zend_ulong num;
 155                                 zend_string *key;
 156                                 zval *val;
 157 
 158                                 ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) {
 159                                         php_object_property_dump(val, num, key, level);
 160                                 } ZEND_HASH_FOREACH_END();
 161                                 if (is_temp) {
 162                                         zend_hash_destroy(myht);
 163                                         efree(myht);
 164                                 }
 165                         }
 166                         if (level > 1) {
 167                                 php_printf("%*c", level-1, ' ');
 168                         }
 169                         PUTS("}\n");
 170                         Z_OBJ_DEC_APPLY_COUNT_P(struc);
 171                         break;
 172                 case IS_RESOURCE: {
 173                         const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(struc));
 174                         php_printf("%sresource(%pd) of type (%s)\n", COMMON, Z_RES_P(struc)->handle, type_name ? type_name : "Unknown");
 175                         break;
 176                 }
 177                 case IS_REFERENCE:
 178                         //??? hide references with refcount==1 (for compatibility)
 179                         if (Z_REFCOUNT_P(struc) > 1) {
 180                                 is_ref = 1;
 181                         }
 182                         struc = Z_REFVAL_P(struc);
 183                         goto again;
 184                         break;
 185                 default:
 186                         php_printf("%sUNKNOWN:0\n", COMMON);
 187                         break;
 188         }
 189 }
 190 /* }}} */
 191 
 192 /* {{{ proto void var_dump(mixed var)
 193    Dumps a string representation of variable to output */
 194 PHP_FUNCTION(var_dump)
 195 {
 196         zval *args;
 197         int argc;
 198         int     i;
 199 
 200         if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
 201                 return;
 202         }
 203 
 204         for (i = 0; i < argc; i++) {
 205                 php_var_dump(&args[i], 1);
 206         }
 207 }
 208 /* }}} */
 209 
 210 static void zval_array_element_dump(zval *zv, zend_ulong index, zend_string *key, int level) /* {{{ */
 211 {
 212         if (key == NULL) { /* numeric key */
 213                 php_printf("%*c[" ZEND_LONG_FMT "]=>\n", level + 1, ' ', index);
 214         } else { /* string key */
 215                 php_printf("%*c[\"", level + 1, ' ');
 216                 PHPWRITE(ZSTR_VAL(key), ZSTR_LEN(key));
 217                 php_printf("\"]=>\n");
 218         }
 219         php_debug_zval_dump(zv, level + 2);
 220 }
 221 /* }}} */
 222 
 223 static void zval_object_property_dump(zval *zv, zend_ulong index, zend_string *key, int level) /* {{{ */
 224 {
 225         const char *prop_name, *class_name;
 226 
 227         if (key == NULL) { /* numeric key */
 228                 php_printf("%*c[" ZEND_LONG_FMT "]=>\n", level + 1, ' ', index);
 229         } else { /* string key */
 230                 zend_unmangle_property_name(key, &class_name, &prop_name);
 231                 php_printf("%*c[", level + 1, ' ');
 232 
 233                 if (class_name) {
 234                         if (class_name[0] == '*') {
 235                                 php_printf("\"%s\":protected", prop_name);
 236                         } else {
 237                                 php_printf("\"%s\":\"%s\":private", prop_name, class_name);
 238                         }
 239                 } else {
 240                         php_printf("\"%s\"", prop_name);
 241                 }
 242                 ZEND_PUTS("]=>\n");
 243         }
 244         php_debug_zval_dump(zv, level + 2);
 245 }
 246 /* }}} */
 247 
 248 PHPAPI void php_debug_zval_dump(zval *struc, int level) /* {{{ */
 249 {
 250         HashTable *myht = NULL;
 251         zend_string *class_name;
 252         int is_temp = 0;
 253         int is_ref = 0;
 254         zend_ulong index;
 255         zend_string *key;
 256         zval *val;
 257         uint32_t count;
 258 
 259         if (level > 1) {
 260                 php_printf("%*c", level - 1, ' ');
 261         }
 262 
 263 again:
 264         switch (Z_TYPE_P(struc)) {
 265         case IS_FALSE:
 266                 php_printf("%sbool(false)\n", COMMON);
 267                 break;
 268         case IS_TRUE:
 269                 php_printf("%sbool(true)\n", COMMON);
 270                 break;
 271         case IS_NULL:
 272                 php_printf("%sNULL\n", COMMON);
 273                 break;
 274         case IS_LONG:
 275                 php_printf("%sint(" ZEND_LONG_FMT ")\n", COMMON, Z_LVAL_P(struc));
 276                 break;
 277         case IS_DOUBLE:
 278                 php_printf("%sfloat(%.*G)\n", COMMON, (int) EG(precision), Z_DVAL_P(struc));
 279                 break;
 280         case IS_STRING:
 281                 php_printf("%sstring(%zd) \"", COMMON, Z_STRLEN_P(struc));
 282                 PHPWRITE(Z_STRVAL_P(struc), Z_STRLEN_P(struc));
 283                 php_printf("\" refcount(%u)\n", Z_REFCOUNTED_P(struc) ? Z_REFCOUNT_P(struc) : 1);
 284                 break;
 285         case IS_ARRAY:
 286                 myht = Z_ARRVAL_P(struc);
 287                 if (level > 1 && ZEND_HASH_APPLY_PROTECTION(myht) && myht->u.v.nApplyCount++ > 1) {
 288                         myht->u.v.nApplyCount--;
 289                         PUTS("*RECURSION*\n");
 290                         return;
 291                 }
 292                 count = zend_array_count(myht);
 293                 php_printf("%sarray(%d) refcount(%u){\n", COMMON, count, Z_REFCOUNTED_P(struc) ? Z_REFCOUNT_P(struc) : 1);
 294                 ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) {
 295                         zval_array_element_dump(val, index, key, level);
 296                 } ZEND_HASH_FOREACH_END();
 297                 if (level > 1 && ZEND_HASH_APPLY_PROTECTION(myht)) {
 298                         myht->u.v.nApplyCount--;
 299                 }
 300                 if (is_temp) {
 301                         zend_hash_destroy(myht);
 302                         efree(myht);
 303                 }
 304                 if (level > 1) {
 305                         php_printf("%*c", level - 1, ' ');
 306                 }
 307                 PUTS("}\n");
 308                 break;
 309         case IS_OBJECT:
 310                 myht = Z_OBJDEBUG_P(struc, is_temp);
 311                 if (myht) {
 312                         if (myht->u.v.nApplyCount > 1) {
 313                                 PUTS("*RECURSION*\n");
 314                                 return;
 315                         } else {
 316                                 myht->u.v.nApplyCount++;
 317                         }
 318                 }
 319                 class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc));
 320                 php_printf("%sobject(%s)#%d (%d) refcount(%u){\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? zend_array_count(myht) : 0, Z_REFCOUNT_P(struc));
 321                 zend_string_release(class_name);
 322                 if (myht) {
 323                         ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) {
 324                                 zval_object_property_dump(val, index, key, level);
 325                         } ZEND_HASH_FOREACH_END();
 326                         myht->u.v.nApplyCount--;
 327                         if (is_temp) {
 328                                 zend_hash_destroy(myht);
 329                                 efree(myht);
 330                         }
 331                 }
 332                 if (level > 1) {
 333                         php_printf("%*c", level - 1, ' ');
 334                 }
 335                 PUTS("}\n");
 336                 break;
 337         case IS_RESOURCE: {
 338                 const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(struc));
 339                 php_printf("%sresource(%d) of type (%s) refcount(%u)\n", COMMON, Z_RES_P(struc)->handle, type_name ? type_name : "Unknown", Z_REFCOUNT_P(struc));
 340                 break;
 341         }
 342         case IS_REFERENCE:
 343                 //??? hide references with refcount==1 (for compatibility)
 344                 if (Z_REFCOUNT_P(struc) > 1) {
 345                         is_ref = 1;
 346                 }
 347                 struc = Z_REFVAL_P(struc);
 348                 goto again;
 349         default:
 350                 php_printf("%sUNKNOWN:0\n", COMMON);
 351                 break;
 352         }
 353 }
 354 /* }}} */
 355 
 356 /* {{{ proto void debug_zval_dump(mixed var)
 357    Dumps a string representation of an internal zend value to output. */
 358 PHP_FUNCTION(debug_zval_dump)
 359 {
 360         zval *args;
 361         int argc;
 362         int     i;
 363 
 364         if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
 365                 return;
 366         }
 367 
 368         for (i = 0; i < argc; i++) {
 369                 php_debug_zval_dump(&args[i], 1);
 370         }
 371 }
 372 /* }}} */
 373 
 374 #define buffer_append_spaces(buf, num_spaces) \
 375         do { \
 376                 char *tmp_spaces; \
 377                 size_t tmp_spaces_len; \
 378                 tmp_spaces_len = spprintf(&tmp_spaces, 0,"%*c", num_spaces, ' '); \
 379                 smart_str_appendl(buf, tmp_spaces, tmp_spaces_len); \
 380                 efree(tmp_spaces); \
 381         } while(0);
 382 
 383 static void php_array_element_export(zval *zv, zend_ulong index, zend_string *key, int level, smart_str *buf) /* {{{ */
 384 {
 385         if (key == NULL) { /* numeric key */
 386                 buffer_append_spaces(buf, level+1);
 387                 smart_str_append_long(buf, (zend_long) index);
 388                 smart_str_appendl(buf, " => ", 4);
 389 
 390         } else { /* string key */
 391                 zend_string *tmp_str;
 392                 zend_string *ckey = php_addcslashes(key, 0, "'\\", 2);
 393                 tmp_str = php_str_to_str(ZSTR_VAL(ckey), ZSTR_LEN(ckey), "\0", 1, "' . \"\\0\" . '", 12);
 394 
 395                 buffer_append_spaces(buf, level + 1);
 396 
 397                 smart_str_appendc(buf, '\'');
 398                 smart_str_append(buf, tmp_str);
 399                 smart_str_appendl(buf, "' => ", 5);
 400 
 401                 zend_string_free(ckey);
 402                 zend_string_free(tmp_str);
 403         }
 404         php_var_export_ex(zv, level + 2, buf);
 405 
 406         smart_str_appendc(buf, ',');
 407         smart_str_appendc(buf, '\n');
 408 }
 409 /* }}} */
 410 
 411 static void php_object_element_export(zval *zv, zend_ulong index, zend_string *key, int level, smart_str *buf) /* {{{ */
 412 {
 413         buffer_append_spaces(buf, level + 2);
 414         if (key != NULL) {
 415                 const char *class_name, *prop_name;
 416                 size_t prop_name_len;
 417                 zend_string *pname_esc;
 418 
 419                 zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_name_len);
 420                 pname_esc = php_addcslashes(zend_string_init(prop_name, prop_name_len, 0), 1, "'\\", 2);
 421 
 422                 smart_str_appendc(buf, '\'');
 423                 smart_str_append(buf, pname_esc);
 424                 smart_str_appendc(buf, '\'');
 425                 zend_string_release(pname_esc);
 426         } else {
 427                 smart_str_append_long(buf, (zend_long) index);
 428         }
 429         smart_str_appendl(buf, " => ", 4);
 430         php_var_export_ex(zv, level + 2, buf);
 431         smart_str_appendc(buf, ',');
 432         smart_str_appendc(buf, '\n');
 433 }
 434 /* }}} */
 435 
 436 PHPAPI void php_var_export_ex(zval *struc, int level, smart_str *buf) /* {{{ */
 437 {
 438         HashTable *myht;
 439         char *tmp_str;
 440         size_t tmp_len;
 441         zend_string *ztmp, *ztmp2;
 442         zend_ulong index;
 443         zend_string *key;
 444         zval *val;
 445 
 446 again:
 447         switch (Z_TYPE_P(struc)) {
 448                 case IS_FALSE:
 449                         smart_str_appendl(buf, "false", 5);
 450                         break;
 451                 case IS_TRUE:
 452                         smart_str_appendl(buf, "true", 4);
 453                         break;
 454                 case IS_NULL:
 455                         smart_str_appendl(buf, "NULL", 4);
 456                         break;
 457                 case IS_LONG:
 458                         smart_str_append_long(buf, Z_LVAL_P(struc));
 459                         break;
 460                 case IS_DOUBLE:
 461                         tmp_len = spprintf(&tmp_str, 0,"%.*H", PG(serialize_precision), Z_DVAL_P(struc));
 462                         smart_str_appendl(buf, tmp_str, tmp_len);
 463                         /* Without a decimal point, PHP treats a number literal as an int.
 464                          * This check even works for scientific notation, because the
 465                          * mantissa always contains a decimal point.
 466                          * We need to check for finiteness, because INF, -INF and NAN
 467                          * must not have a decimal point added.
 468                          */
 469                         if (zend_finite(Z_DVAL_P(struc)) && NULL == strchr(tmp_str, '.')) {
 470                                 smart_str_appendl(buf, ".0", 2);
 471                         }
 472                         efree(tmp_str);
 473                         break;
 474                 case IS_STRING:
 475                         ztmp = php_addcslashes(Z_STR_P(struc), 0, "'\\", 2);
 476                         ztmp2 = php_str_to_str(ZSTR_VAL(ztmp), ZSTR_LEN(ztmp), "\0", 1, "' . \"\\0\" . '", 12);
 477 
 478                         smart_str_appendc(buf, '\'');
 479                         smart_str_append(buf, ztmp2);
 480                         smart_str_appendc(buf, '\'');
 481 
 482                         zend_string_free(ztmp);
 483                         zend_string_free(ztmp2);
 484                         break;
 485                 case IS_ARRAY:
 486                         myht = Z_ARRVAL_P(struc);
 487                         if (ZEND_HASH_APPLY_PROTECTION(myht) && myht->u.v.nApplyCount++ > 0) {
 488                                 myht->u.v.nApplyCount--;
 489                                 smart_str_appendl(buf, "NULL", 4);
 490                                 zend_error(E_WARNING, "var_export does not handle circular references");
 491                                 return;
 492                         }
 493                         if (level > 1) {
 494                                 smart_str_appendc(buf, '\n');
 495                                 buffer_append_spaces(buf, level - 1);
 496                         }
 497                         smart_str_appendl(buf, "array (\n", 8);
 498                         ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) {
 499                                 php_array_element_export(val, index, key, level, buf);
 500                         } ZEND_HASH_FOREACH_END();
 501                         if (ZEND_HASH_APPLY_PROTECTION(myht)) {
 502                                 myht->u.v.nApplyCount--;
 503                         }
 504                         if (level > 1) {
 505                                 buffer_append_spaces(buf, level - 1);
 506                         }
 507                         smart_str_appendc(buf, ')');
 508 
 509                         break;
 510 
 511                 case IS_OBJECT:
 512                         myht = Z_OBJPROP_P(struc);
 513                         if (myht) {
 514                                 if (myht->u.v.nApplyCount > 0) {
 515                                         smart_str_appendl(buf, "NULL", 4);
 516                                         zend_error(E_WARNING, "var_export does not handle circular references");
 517                                         return;
 518                                 } else {
 519                                         myht->u.v.nApplyCount++;
 520                                 }
 521                         }
 522                         if (level > 1) {
 523                                 smart_str_appendc(buf, '\n');
 524                                 buffer_append_spaces(buf, level - 1);
 525                         }
 526 
 527                         smart_str_append(buf, Z_OBJCE_P(struc)->name);
 528                         smart_str_appendl(buf, "::__set_state(array(\n", 21);
 529 
 530                         if (myht) {
 531                                 ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) {
 532                                         php_object_element_export(val, index, key, level, buf);
 533                                 } ZEND_HASH_FOREACH_END();
 534                                 myht->u.v.nApplyCount--;
 535                         }
 536                         if (level > 1) {
 537                                 buffer_append_spaces(buf, level - 1);
 538                         }
 539                         smart_str_appendl(buf, "))", 2);
 540 
 541                         break;
 542                 case IS_REFERENCE:
 543                         struc = Z_REFVAL_P(struc);
 544                         goto again;
 545                         break;
 546                 default:
 547                         smart_str_appendl(buf, "NULL", 4);
 548                         break;
 549         }
 550 }
 551 /* }}} */
 552 
 553 /* FOR BC reasons, this will always perform and then print */
 554 PHPAPI void php_var_export(zval *struc, int level) /* {{{ */
 555 {
 556         smart_str buf = {0};
 557         php_var_export_ex(struc, level, &buf);
 558         smart_str_0(&buf);
 559         PHPWRITE(ZSTR_VAL(buf.s), ZSTR_LEN(buf.s));
 560         smart_str_free(&buf);
 561 }
 562 /* }}} */
 563 
 564 /* {{{ proto mixed var_export(mixed var [, bool return])
 565    Outputs or returns a string representation of a variable */
 566 PHP_FUNCTION(var_export)
 567 {
 568         zval *var;
 569         zend_bool return_output = 0;
 570         smart_str buf = {0};
 571 
 572         if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &var, &return_output) == FAILURE) {
 573                 return;
 574         }
 575 
 576         php_var_export_ex(var, 1, &buf);
 577         smart_str_0 (&buf);
 578 
 579         if (return_output) {
 580                 RETURN_NEW_STR(buf.s);
 581         } else {
 582                 PHPWRITE(ZSTR_VAL(buf.s), ZSTR_LEN(buf.s));
 583                 smart_str_free(&buf);
 584         }
 585 }
 586 /* }}} */
 587 
 588 static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_data_t var_hash);
 589 
 590 static inline zend_long php_add_var_hash(php_serialize_data_t data, zval *var) /* {{{ */
 591 {
 592         zval *zv;
 593         zend_ulong key;
 594         zend_bool is_ref = Z_ISREF_P(var);
 595 
 596         data->n += 1;
 597 
 598         if (!is_ref && Z_TYPE_P(var) != IS_OBJECT) {
 599                 return 0;
 600         }
 601 
 602         /* References to objects are treated as if the reference didn't exist */
 603         if (is_ref && Z_TYPE_P(Z_REFVAL_P(var)) == IS_OBJECT) {
 604                 var = Z_REFVAL_P(var);
 605         }
 606 
 607         /* Index for the variable is stored using the numeric value of the pointer to
 608          * the zend_refcounted struct */
 609         key = (zend_ulong) (zend_uintptr_t) Z_COUNTED_P(var);
 610         zv = zend_hash_index_find(&data->ht, key);
 611 
 612         if (zv) {
 613                 /* References are only counted once, undo the data->n increment above */
 614                 if (is_ref) {
 615                         data->n -= 1;
 616                 }
 617 
 618                 return Z_LVAL_P(zv);
 619         } else {
 620                 zval zv_n;
 621                 ZVAL_LONG(&zv_n, data->n);
 622                 zend_hash_index_add_new(&data->ht, key, &zv_n);
 623 
 624                 /* Additionally to the index, we also store the variable, to ensure that it is
 625                  * not destroyed during serialization and its pointer reused. The variable is
 626                  * stored at the numeric value of the pointer + 1, which cannot be the location
 627                  * of another zend_refcounted structure. */
 628                 zend_hash_index_add_new(&data->ht, key + 1, var);
 629                 Z_ADDREF_P(var);
 630 
 631                 return 0;
 632         }
 633 }
 634 /* }}} */
 635 
 636 static inline void php_var_serialize_long(smart_str *buf, zend_long val) /* {{{ */
 637 {
 638         smart_str_appendl(buf, "i:", 2);
 639         smart_str_append_long(buf, val);
 640         smart_str_appendc(buf, ';');
 641 }
 642 /* }}} */
 643 
 644 static inline void php_var_serialize_string(smart_str *buf, char *str, size_t len) /* {{{ */
 645 {
 646         smart_str_appendl(buf, "s:", 2);
 647         smart_str_append_unsigned(buf, len);
 648         smart_str_appendl(buf, ":\"", 2);
 649         smart_str_appendl(buf, str, len);
 650         smart_str_appendl(buf, "\";", 2);
 651 }
 652 /* }}} */
 653 
 654 static inline zend_bool php_var_serialize_class_name(smart_str *buf, zval *struc) /* {{{ */
 655 {
 656         PHP_CLASS_ATTRIBUTES;
 657 
 658         PHP_SET_CLASS_ATTRIBUTES(struc);
 659         smart_str_appendl(buf, "O:", 2);
 660         smart_str_append_unsigned(buf, ZSTR_LEN(class_name));
 661         smart_str_appendl(buf, ":\"", 2);
 662         smart_str_append(buf, class_name);
 663         smart_str_appendl(buf, "\":", 2);
 664         PHP_CLEANUP_CLASS_ATTRIBUTES();
 665         return incomplete_class;
 666 }
 667 /* }}} */
 668 
 669 static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_ptr, php_serialize_data_t var_hash) /* {{{ */
 670 {
 671         uint32_t count;
 672         zend_bool incomplete_class;
 673         HashTable *ht;
 674 
 675         incomplete_class = php_var_serialize_class_name(buf, struc);
 676         /* count after serializing name, since php_var_serialize_class_name
 677          * changes the count if the variable is incomplete class */
 678         if (Z_TYPE_P(retval_ptr) == IS_ARRAY) {
 679                 ht = Z_ARRVAL_P(retval_ptr);
 680                 count = zend_array_count(ht);
 681         } else if (Z_TYPE_P(retval_ptr) == IS_OBJECT) {
 682                 ht = Z_OBJPROP_P(retval_ptr);
 683                 count = zend_array_count(ht);
 684                 if (incomplete_class) {
 685                         --count;
 686                 }
 687         } else {
 688                 count = 0;
 689         }
 690 
 691         smart_str_append_unsigned(buf, count);
 692         smart_str_appendl(buf, ":{", 2);
 693 
 694         if (count > 0) {
 695                 zend_string *key;
 696                 zval *d, *val;
 697                 zval nval, *nvalp;
 698                 zend_string *name;
 699                 HashTable *propers;
 700 
 701                 ZVAL_NULL(&nval);
 702                 nvalp = &nval;
 703 
 704                 ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
 705                         if (incomplete_class && strcmp(ZSTR_VAL(key), MAGIC_MEMBER) == 0) {
 706                                 continue;
 707                         }
 708 
 709                         if (Z_TYPE_P(val) != IS_STRING) {
 710                                 php_error_docref(NULL, E_NOTICE,
 711                                                 "__sleep should return an array only containing the names of instance-variables to serialize.");
 712                         }
 713                         name = zval_get_string(val);
 714                         propers = Z_OBJPROP_P(struc);
 715                         if ((d = zend_hash_find(propers, name)) != NULL) {
 716                                 if (Z_TYPE_P(d) == IS_INDIRECT) {
 717                                         d = Z_INDIRECT_P(d);
 718                                         if (Z_TYPE_P(d) == IS_UNDEF) {
 719                                                 zend_string_release(name);
 720                                                 continue;
 721                                         }
 722                                 }
 723                                 php_var_serialize_string(buf, ZSTR_VAL(name), ZSTR_LEN(name));
 724                                 php_var_serialize_intern(buf, d, var_hash);
 725                         } else {
 726                                 zend_class_entry *ce = Z_OBJ_P(struc)->ce;
 727                                 if (ce) {
 728                                         zend_string *prot_name, *priv_name;
 729 
 730                                         do {
 731                                                 priv_name = zend_mangle_property_name(
 732                                                                 ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), ZSTR_VAL(name), ZSTR_LEN(name), ce->type & ZEND_INTERNAL_CLASS);
 733                                                 if ((d = zend_hash_find(propers, priv_name)) != NULL) {
 734                                                         if (Z_TYPE_P(d) == IS_INDIRECT) {
 735                                                                 d = Z_INDIRECT_P(d);
 736                                                                 if (Z_ISUNDEF_P(d)) {
 737                                                                         break;
 738                                                                 }
 739                                                         }
 740                                                         php_var_serialize_string(buf, ZSTR_VAL(priv_name), ZSTR_LEN(priv_name));
 741                                                         zend_string_free(priv_name);
 742                                                         php_var_serialize_intern(buf, d, var_hash);
 743                                                         break;
 744                                                 }
 745                                                 zend_string_free(priv_name);
 746                                                 prot_name = zend_mangle_property_name(
 747                                                                 "*", 1, ZSTR_VAL(name), ZSTR_LEN(name), ce->type & ZEND_INTERNAL_CLASS);
 748                                                 if ((d = zend_hash_find(propers, prot_name)) != NULL) {
 749                                                         if (Z_TYPE_P(d) == IS_INDIRECT) {
 750                                                                 d = Z_INDIRECT_P(d);
 751                                                                 if (Z_TYPE_P(d) == IS_UNDEF) {
 752                                                                         zend_string_free(prot_name);
 753                                                                         break;
 754                                                                 }
 755                                                         }
 756                                                         php_var_serialize_string(buf, ZSTR_VAL(prot_name), ZSTR_LEN(prot_name));
 757                                                         zend_string_free(prot_name);
 758                                                         php_var_serialize_intern(buf, d, var_hash);
 759                                                         break;
 760                                                 }
 761                                                 zend_string_free(prot_name);
 762                                                 php_var_serialize_string(buf, ZSTR_VAL(name), ZSTR_LEN(name));
 763                                                 php_var_serialize_intern(buf, nvalp, var_hash);
 764                                                 php_error_docref(NULL, E_NOTICE,
 765                                                                 "\"%s\" returned as member variable from __sleep() but does not exist", ZSTR_VAL(name));
 766                                         } while (0);
 767                                 } else {
 768                                         php_var_serialize_string(buf, ZSTR_VAL(name), ZSTR_LEN(name));
 769                                         php_var_serialize_intern(buf, nvalp, var_hash);
 770                                 }
 771                         }
 772                         zend_string_release(name);
 773                 } ZEND_HASH_FOREACH_END();
 774         }
 775         smart_str_appendc(buf, '}');
 776 }
 777 /* }}} */
 778 
 779 static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_data_t var_hash) /* {{{ */
 780 {
 781         zend_long var_already;
 782         HashTable *myht;
 783 
 784         if (EG(exception)) {
 785                 return;
 786         }
 787 
 788         if (var_hash && (var_already = php_add_var_hash(var_hash, struc))) {
 789                 if (Z_ISREF_P(struc)) {
 790                         smart_str_appendl(buf, "R:", 2);
 791                         smart_str_append_long(buf, var_already);
 792                         smart_str_appendc(buf, ';');
 793                         return;
 794                 } else if (Z_TYPE_P(struc) == IS_OBJECT) {
 795                         smart_str_appendl(buf, "r:", 2);
 796                         smart_str_append_long(buf, var_already);
 797                         smart_str_appendc(buf, ';');
 798                         return;
 799                 }
 800         }
 801 
 802 again:
 803         switch (Z_TYPE_P(struc)) {
 804                 case IS_FALSE:
 805                         smart_str_appendl(buf, "b:0;", 4);
 806                         return;
 807 
 808                 case IS_TRUE:
 809                         smart_str_appendl(buf, "b:1;", 4);
 810                         return;
 811 
 812                 case IS_NULL:
 813                         smart_str_appendl(buf, "N;", 2);
 814                         return;
 815 
 816                 case IS_LONG:
 817                         php_var_serialize_long(buf, Z_LVAL_P(struc));
 818                         return;
 819 
 820                 case IS_DOUBLE: {
 821                                 char *s;
 822 
 823                                 smart_str_appendl(buf, "d:", 2);
 824                                 s = (char *) safe_emalloc(PG(serialize_precision), 1, MAX_LENGTH_OF_DOUBLE + 1);
 825                                 php_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', s);
 826                                 smart_str_appends(buf, s);
 827                                 smart_str_appendc(buf, ';');
 828                                 efree(s);
 829                                 return;
 830                         }
 831 
 832                 case IS_STRING:
 833                         php_var_serialize_string(buf, Z_STRVAL_P(struc), Z_STRLEN_P(struc));
 834                         return;
 835 
 836                 case IS_OBJECT: {
 837                                 zval retval;
 838                                 zval fname;
 839                                 int res;
 840                                 zend_class_entry *ce = Z_OBJCE_P(struc);
 841 
 842                                 if (ce->serialize != NULL) {
 843                                         /* has custom handler */
 844                                         unsigned char *serialized_data = NULL;
 845                                         size_t serialized_length;
 846 
 847                                         if (ce->serialize(struc, &serialized_data, &serialized_length, (zend_serialize_data *)var_hash) == SUCCESS) {
 848                                                 smart_str_appendl(buf, "C:", 2);
 849                                                 smart_str_append_unsigned(buf, ZSTR_LEN(Z_OBJCE_P(struc)->name));
 850                                                 smart_str_appendl(buf, ":\"", 2);
 851                                                 smart_str_append(buf, Z_OBJCE_P(struc)->name);
 852                                                 smart_str_appendl(buf, "\":", 2);
 853 
 854                                                 smart_str_append_unsigned(buf, serialized_length);
 855                                                 smart_str_appendl(buf, ":{", 2);
 856                                                 smart_str_appendl(buf, (char *) serialized_data, serialized_length);
 857                                                 smart_str_appendc(buf, '}');
 858                                         } else {
 859                                                 smart_str_appendl(buf, "N;", 2);
 860                                         }
 861                                         if (serialized_data) {
 862                                                 efree(serialized_data);
 863                                         }
 864                                         return;
 865                                 }
 866 
 867                                 if (ce != PHP_IC_ENTRY && zend_hash_str_exists(&ce->function_table, "__sleep", sizeof("__sleep")-1)) {
 868                                         ZVAL_STRINGL(&fname, "__sleep", sizeof("__sleep") - 1);
 869                                         BG(serialize_lock)++;
 870                                         res = call_user_function_ex(CG(function_table), struc, &fname, &retval, 0, 0, 1, NULL);
 871                                         BG(serialize_lock)--;
 872                                         zval_dtor(&fname);
 873 
 874                                         if (EG(exception)) {
 875                                                 zval_ptr_dtor(&retval);
 876                                                 return;
 877                                         }
 878 
 879                                         if (res == SUCCESS) {
 880                                                 if (Z_TYPE(retval) != IS_UNDEF) {
 881                                                         if (HASH_OF(&retval)) {
 882                                                                 php_var_serialize_class(buf, struc, &retval, var_hash);
 883                                                         } else {
 884                                                                 php_error_docref(NULL, E_NOTICE, "__sleep should return an array only containing the names of instance-variables to serialize");
 885                                                                 /* we should still add element even if it's not OK,
 886                                                                  * since we already wrote the length of the array before */
 887                                                                 smart_str_appendl(buf,"N;", 2);
 888                                                         }
 889                                                         zval_ptr_dtor(&retval);
 890                                                 }
 891                                                 return;
 892                                         }
 893                                         zval_ptr_dtor(&retval);
 894                                 }
 895 
 896                                 /* fall-through */
 897                         }
 898                 case IS_ARRAY: {
 899                         uint32_t i;
 900                         zend_bool incomplete_class = 0;
 901                         if (Z_TYPE_P(struc) == IS_ARRAY) {
 902                                 smart_str_appendl(buf, "a:", 2);
 903                                 myht = Z_ARRVAL_P(struc);
 904                                 i = zend_array_count(myht);
 905                         } else {
 906                                 incomplete_class = php_var_serialize_class_name(buf, struc);
 907                                 myht = Z_OBJPROP_P(struc);
 908                                 /* count after serializing name, since php_var_serialize_class_name
 909                                  * changes the count if the variable is incomplete class */
 910                                 i = zend_array_count(myht);
 911                                 if (i > 0 && incomplete_class) {
 912                                         --i;
 913                                 }
 914                         }
 915                         smart_str_append_unsigned(buf, i);
 916                         smart_str_appendl(buf, ":{", 2);
 917                         if (i > 0) {
 918                                 zend_string *key;
 919                                 zval *data;
 920                                 zend_ulong index;
 921 
 922                                 ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, data) {
 923 
 924                                         if (incomplete_class && strcmp(ZSTR_VAL(key), MAGIC_MEMBER) == 0) {
 925                                                 continue;
 926                                         }
 927 
 928                                         if (!key) {
 929                                                 php_var_serialize_long(buf, index);
 930                                         } else {
 931                                                 php_var_serialize_string(buf, ZSTR_VAL(key), ZSTR_LEN(key));
 932                                         }
 933 
 934                                         /* we should still add element even if it's not OK,
 935                                          * since we already wrote the length of the array before */
 936                                         if ((Z_TYPE_P(data) == IS_ARRAY && Z_TYPE_P(struc) == IS_ARRAY && Z_ARR_P(data) == Z_ARR_P(struc))
 937                                                 || (Z_TYPE_P(data) == IS_ARRAY && Z_ARRVAL_P(data)->u.v.nApplyCount > 1)
 938                                         ) {
 939                                                 smart_str_appendl(buf, "N;", 2);
 940                                         } else {
 941                                                 if (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data))) {
 942                                                         Z_ARRVAL_P(data)->u.v.nApplyCount++;
 943                                                 }
 944                                                 php_var_serialize_intern(buf, data, var_hash);
 945                                                 if (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data))) {
 946                                                         Z_ARRVAL_P(data)->u.v.nApplyCount--;
 947                                                 }
 948                                         }
 949                                 } ZEND_HASH_FOREACH_END();
 950                         }
 951                         smart_str_appendc(buf, '}');
 952                         return;
 953                 }
 954                 case IS_REFERENCE:
 955                         struc = Z_REFVAL_P(struc);
 956                         goto again;
 957                 default:
 958                         smart_str_appendl(buf, "i:0;", 4);
 959                         return;
 960         }
 961 }
 962 /* }}} */
 963 
 964 PHPAPI void php_var_serialize(smart_str *buf, zval *struc, php_serialize_data_t *data) /* {{{ */
 965 {
 966         php_var_serialize_intern(buf, struc, *data);
 967         smart_str_0(buf);
 968 }
 969 /* }}} */
 970 
 971 /* {{{ proto string serialize(mixed variable)
 972    Returns a string representation of variable (which can later be unserialized) */
 973 PHP_FUNCTION(serialize)
 974 {
 975         zval *struc;
 976         php_serialize_data_t var_hash;
 977         smart_str buf = {0};
 978 
 979         if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &struc) == FAILURE) {
 980                 return;
 981         }
 982 
 983         PHP_VAR_SERIALIZE_INIT(var_hash);
 984         php_var_serialize(&buf, struc, &var_hash);
 985         PHP_VAR_SERIALIZE_DESTROY(var_hash);
 986 
 987         if (EG(exception)) {
 988                 smart_str_free(&buf);
 989                 RETURN_FALSE;
 990         }
 991 
 992         if (buf.s) {
 993                 RETURN_NEW_STR(buf.s);
 994         } else {
 995                 RETURN_NULL();
 996         }
 997 }
 998 /* }}} */
 999 
1000 /* {{{ proto mixed unserialize(string variable_representation[, array allowed_classes])
1001    Takes a string representation of variable and recreates it */
1002 PHP_FUNCTION(unserialize)
1003 {
1004         char *buf = NULL;
1005         size_t buf_len;
1006         const unsigned char *p;
1007         php_unserialize_data_t var_hash;
1008         zval *options = NULL, *classes = NULL;
1009         HashTable *class_hash = NULL;
1010 
1011         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a", &buf, &buf_len, &options) == FAILURE) {
1012                 RETURN_FALSE;
1013         }
1014 
1015         if (buf_len == 0) {
1016                 RETURN_FALSE;
1017         }
1018 
1019         p = (const unsigned char*) buf;
1020         PHP_VAR_UNSERIALIZE_INIT(var_hash);
1021         if(options != NULL) {
1022                 classes = zend_hash_str_find(Z_ARRVAL_P(options), "allowed_classes", sizeof("allowed_classes")-1);
1023                 if(classes && (Z_TYPE_P(classes) == IS_ARRAY || !zend_is_true(classes))) {
1024                         ALLOC_HASHTABLE(class_hash);
1025                         zend_hash_init(class_hash, (Z_TYPE_P(classes) == IS_ARRAY)?zend_hash_num_elements(Z_ARRVAL_P(classes)):0, NULL, NULL, 0);
1026                 }
1027                 if(class_hash && Z_TYPE_P(classes) == IS_ARRAY) {
1028                         zval *entry;
1029                         zend_string *lcname;
1030 
1031                         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(classes), entry) {
1032                                 convert_to_string_ex(entry);
1033                                 lcname = zend_string_tolower(Z_STR_P(entry));
1034                                 zend_hash_add_empty_element(class_hash, lcname);
1035                         zend_string_release(lcname);
1036                         } ZEND_HASH_FOREACH_END();
1037                 }
1038         }
1039 
1040         if (!php_var_unserialize_ex(return_value, &p, p + buf_len, &var_hash, class_hash)) {
1041                 PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
1042                 if(class_hash) {
1043                         zend_hash_destroy(class_hash);
1044                         FREE_HASHTABLE(class_hash);
1045                 }
1046                 zval_ptr_dtor(return_value);
1047                 if (!EG(exception)) {
1048                         php_error_docref(NULL, E_NOTICE, "Error at offset " ZEND_LONG_FMT " of %zd bytes",
1049                                 (zend_long)((char*)p - buf), buf_len);
1050                 }
1051                 RETURN_FALSE;
1052         }
1053         PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
1054         if(class_hash) {
1055                 zend_hash_destroy(class_hash);
1056                 FREE_HASHTABLE(class_hash);
1057         }
1058 }
1059 /* }}} */
1060 
1061 /* {{{ proto int memory_get_usage([bool real_usage])
1062    Returns the allocated by PHP memory */
1063 PHP_FUNCTION(memory_get_usage) {
1064         zend_bool real_usage = 0;
1065 
1066         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &real_usage) == FAILURE) {
1067                 RETURN_FALSE;
1068         }
1069 
1070         RETURN_LONG(zend_memory_usage(real_usage));
1071 }
1072 /* }}} */
1073 
1074 /* {{{ proto int memory_get_peak_usage([bool real_usage])
1075    Returns the peak allocated by PHP memory */
1076 PHP_FUNCTION(memory_get_peak_usage) {
1077         zend_bool real_usage = 0;
1078 
1079         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &real_usage) == FAILURE) {
1080                 RETURN_FALSE;
1081         }
1082 
1083         RETURN_LONG(zend_memory_peak_usage(real_usage));
1084 }
1085 /* }}} */
1086 
1087 /*
1088  * Local variables:
1089  * tab-width: 4
1090  * c-basic-offset: 4
1091  * End:
1092  * vim600: sw=4 ts=4 fdm=marker
1093  * vim<600: sw=4 ts=4
1094  */

/* [<][>][^][v][top][bottom][index][help] */