Annotation of embedaddon/php/ext/standard/var.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2012 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: var.c 321634 2012-01-01 13:15:04Z felipe $ */
! 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 "php_smart_str.h"
! 32: #include "basic_functions.h"
! 33: #include "php_incomplete_class.h"
! 34:
! 35: #define COMMON (Z_ISREF_PP(struc) ? "&" : "")
! 36: /* }}} */
! 37:
! 38: static int php_array_element_dump(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
! 39: {
! 40: int level;
! 41:
! 42: level = va_arg(args, int);
! 43:
! 44: if (hash_key->nKeyLength == 0) { /* numeric key */
! 45: php_printf("%*c[%ld]=>\n", level + 1, ' ', hash_key->h);
! 46: } else { /* string key */
! 47: php_printf("%*c[\"", level + 1, ' ');
! 48: PHPWRITE(hash_key->arKey, hash_key->nKeyLength - 1);
! 49: php_printf("\"]=>\n");
! 50: }
! 51: php_var_dump(zv, level + 2 TSRMLS_CC);
! 52: return 0;
! 53: }
! 54: /* }}} */
! 55:
! 56: static int php_object_property_dump(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
! 57: {
! 58: int level;
! 59: char *prop_name, *class_name;
! 60:
! 61: level = va_arg(args, int);
! 62:
! 63: if (hash_key->nKeyLength == 0) { /* numeric key */
! 64: php_printf("%*c[%ld]=>\n", level + 1, ' ', hash_key->h);
! 65: } else { /* string key */
! 66: int unmangle = zend_unmangle_property_name(hash_key->arKey, hash_key->nKeyLength - 1, &class_name, &prop_name);
! 67: php_printf("%*c[", level + 1, ' ');
! 68:
! 69: if (class_name && unmangle == SUCCESS) {
! 70: if (class_name[0] == '*') {
! 71: php_printf("\"%s\":protected", prop_name);
! 72: } else {
! 73: php_printf("\"%s\":\"%s\":private", prop_name, class_name);
! 74: }
! 75: } else {
! 76: php_printf("\"");
! 77: PHPWRITE(hash_key->arKey, hash_key->nKeyLength - 1);
! 78: php_printf("\"");
! 79: }
! 80: ZEND_PUTS("]=>\n");
! 81: }
! 82: php_var_dump(zv, level + 2 TSRMLS_CC);
! 83: return 0;
! 84: }
! 85: /* }}} */
! 86:
! 87: PHPAPI void php_var_dump(zval **struc, int level TSRMLS_DC) /* {{{ */
! 88: {
! 89: HashTable *myht;
! 90: char *class_name;
! 91: zend_uint class_name_len;
! 92: int (*php_element_dump_func)(zval** TSRMLS_DC, int, va_list, zend_hash_key*);
! 93: int is_temp;
! 94:
! 95: if (level > 1) {
! 96: php_printf("%*c", level - 1, ' ');
! 97: }
! 98:
! 99: switch (Z_TYPE_PP(struc)) {
! 100: case IS_BOOL:
! 101: php_printf("%sbool(%s)\n", COMMON, Z_LVAL_PP(struc) ? "true" : "false");
! 102: break;
! 103: case IS_NULL:
! 104: php_printf("%sNULL\n", COMMON);
! 105: break;
! 106: case IS_LONG:
! 107: php_printf("%sint(%ld)\n", COMMON, Z_LVAL_PP(struc));
! 108: break;
! 109: case IS_DOUBLE:
! 110: php_printf("%sfloat(%.*G)\n", COMMON, (int) EG(precision), Z_DVAL_PP(struc));
! 111: break;
! 112: case IS_STRING:
! 113: php_printf("%sstring(%d) \"", COMMON, Z_STRLEN_PP(struc));
! 114: PHPWRITE(Z_STRVAL_PP(struc), Z_STRLEN_PP(struc));
! 115: PUTS("\"\n");
! 116: break;
! 117: case IS_ARRAY:
! 118: myht = Z_ARRVAL_PP(struc);
! 119: if (++myht->nApplyCount > 1) {
! 120: PUTS("*RECURSION*\n");
! 121: --myht->nApplyCount;
! 122: return;
! 123: }
! 124: php_printf("%sarray(%d) {\n", COMMON, zend_hash_num_elements(myht));
! 125: php_element_dump_func = php_array_element_dump;
! 126: is_temp = 0;
! 127: goto head_done;
! 128: case IS_OBJECT:
! 129: myht = Z_OBJDEBUG_PP(struc, is_temp);
! 130: if (myht && ++myht->nApplyCount > 1) {
! 131: PUTS("*RECURSION*\n");
! 132: --myht->nApplyCount;
! 133: return;
! 134: }
! 135:
! 136: Z_OBJ_HANDLER(**struc, get_class_name)(*struc, &class_name, &class_name_len, 0 TSRMLS_CC);
! 137: php_printf("%sobject(%s)#%d (%d) {\n", COMMON, class_name, Z_OBJ_HANDLE_PP(struc), myht ? zend_hash_num_elements(myht) : 0);
! 138: efree(class_name);
! 139: php_element_dump_func = php_object_property_dump;
! 140: head_done:
! 141: if (myht) {
! 142: zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) php_element_dump_func, 1, level);
! 143: --myht->nApplyCount;
! 144: if (is_temp) {
! 145: zend_hash_destroy(myht);
! 146: efree(myht);
! 147: }
! 148: }
! 149: if (level > 1) {
! 150: php_printf("%*c", level-1, ' ');
! 151: }
! 152: PUTS("}\n");
! 153: break;
! 154: case IS_RESOURCE: {
! 155: char *type_name;
! 156:
! 157: type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(struc) TSRMLS_CC);
! 158: php_printf("%sresource(%ld) of type (%s)\n", COMMON, Z_LVAL_PP(struc), type_name ? type_name : "Unknown");
! 159: break;
! 160: }
! 161: default:
! 162: php_printf("%sUNKNOWN:0\n", COMMON);
! 163: break;
! 164: }
! 165: }
! 166: /* }}} */
! 167:
! 168: /* {{{ proto void var_dump(mixed var)
! 169: Dumps a string representation of variable to output */
! 170: PHP_FUNCTION(var_dump)
! 171: {
! 172: zval ***args;
! 173: int argc;
! 174: int i;
! 175:
! 176: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
! 177: return;
! 178: }
! 179:
! 180: for (i = 0; i < argc; i++) {
! 181: php_var_dump(args[i], 1 TSRMLS_CC);
! 182: }
! 183: efree(args);
! 184: }
! 185: /* }}} */
! 186:
! 187: static int zval_array_element_dump(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
! 188: {
! 189: int level;
! 190:
! 191: level = va_arg(args, int);
! 192:
! 193: if (hash_key->nKeyLength == 0) { /* numeric key */
! 194: php_printf("%*c[%ld]=>\n", level + 1, ' ', hash_key->h);
! 195: } else { /* string key */
! 196: /* XXX: perphaps when we are inside the class we should permit access to
! 197: * private & protected values
! 198: */
! 199: if (va_arg(args, int) && hash_key->arKey[0] == '\0') {
! 200: return 0;
! 201: }
! 202: php_printf("%*c[\"", level + 1, ' ');
! 203: PHPWRITE(hash_key->arKey, hash_key->nKeyLength - 1);
! 204: php_printf("\"]=>\n");
! 205: }
! 206: php_debug_zval_dump(zv, level + 2 TSRMLS_CC);
! 207: return 0;
! 208: }
! 209: /* }}} */
! 210:
! 211: static int zval_object_property_dump(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
! 212: {
! 213: int level;
! 214: char *prop_name, *class_name;
! 215:
! 216: level = va_arg(args, int);
! 217:
! 218: if (hash_key->nKeyLength == 0) { /* numeric key */
! 219: php_printf("%*c[%ld]=>\n", level + 1, ' ', hash_key->h);
! 220: } else { /* string key */
! 221: zend_unmangle_property_name(hash_key->arKey, hash_key->nKeyLength - 1, &class_name, &prop_name);
! 222: php_printf("%*c[", level + 1, ' ');
! 223:
! 224: if (class_name) {
! 225: if (class_name[0] == '*') {
! 226: php_printf("\"%s\":protected", prop_name);
! 227: } else {
! 228: php_printf("\"%s\":\"%s\":private", prop_name, class_name);
! 229: }
! 230: } else {
! 231: php_printf("\"%s\"", prop_name);
! 232: }
! 233: ZEND_PUTS("]=>\n");
! 234: }
! 235: php_debug_zval_dump(zv, level + 2 TSRMLS_CC);
! 236: return 0;
! 237: }
! 238: /* }}} */
! 239:
! 240: PHPAPI void php_debug_zval_dump(zval **struc, int level TSRMLS_DC) /* {{{ */
! 241: {
! 242: HashTable *myht = NULL;
! 243: char *class_name;
! 244: zend_uint class_name_len;
! 245: int (*zval_element_dump_func)(zval** TSRMLS_DC, int, va_list, zend_hash_key*);
! 246: int is_temp = 0;
! 247:
! 248: if (level > 1) {
! 249: php_printf("%*c", level - 1, ' ');
! 250: }
! 251:
! 252: switch (Z_TYPE_PP(struc)) {
! 253: case IS_BOOL:
! 254: php_printf("%sbool(%s) refcount(%u)\n", COMMON, Z_LVAL_PP(struc)?"true":"false", Z_REFCOUNT_PP(struc));
! 255: break;
! 256: case IS_NULL:
! 257: php_printf("%sNULL refcount(%u)\n", COMMON, Z_REFCOUNT_PP(struc));
! 258: break;
! 259: case IS_LONG:
! 260: php_printf("%slong(%ld) refcount(%u)\n", COMMON, Z_LVAL_PP(struc), Z_REFCOUNT_PP(struc));
! 261: break;
! 262: case IS_DOUBLE:
! 263: php_printf("%sdouble(%.*G) refcount(%u)\n", COMMON, (int) EG(precision), Z_DVAL_PP(struc), Z_REFCOUNT_PP(struc));
! 264: break;
! 265: case IS_STRING:
! 266: php_printf("%sstring(%d) \"", COMMON, Z_STRLEN_PP(struc));
! 267: PHPWRITE(Z_STRVAL_PP(struc), Z_STRLEN_PP(struc));
! 268: php_printf("\" refcount(%u)\n", Z_REFCOUNT_PP(struc));
! 269: break;
! 270: case IS_ARRAY:
! 271: myht = Z_ARRVAL_PP(struc);
! 272: if (myht->nApplyCount > 1) {
! 273: PUTS("*RECURSION*\n");
! 274: return;
! 275: }
! 276: php_printf("%sarray(%d) refcount(%u){\n", COMMON, zend_hash_num_elements(myht), Z_REFCOUNT_PP(struc));
! 277: zval_element_dump_func = zval_array_element_dump;
! 278: goto head_done;
! 279: case IS_OBJECT:
! 280: myht = Z_OBJDEBUG_PP(struc, is_temp);
! 281: if (myht && myht->nApplyCount > 1) {
! 282: PUTS("*RECURSION*\n");
! 283: return;
! 284: }
! 285: if (Z_OBJ_HANDLER_PP(struc, get_class_name)) {
! 286: Z_OBJ_HANDLER_PP(struc, get_class_name)(*struc, &class_name, &class_name_len, 0 TSRMLS_CC);
! 287: php_printf("%sobject(%s)#%d (%d) refcount(%u){\n", COMMON, class_name, Z_OBJ_HANDLE_PP(struc), myht ? zend_hash_num_elements(myht) : 0, Z_REFCOUNT_PP(struc));
! 288: efree(class_name);
! 289: } else {
! 290: php_printf("%sobject(unknown class)#%d (%d) refcount(%u){\n", COMMON, Z_OBJ_HANDLE_PP(struc), myht ? zend_hash_num_elements(myht) : 0, Z_REFCOUNT_PP(struc));
! 291: }
! 292: zval_element_dump_func = zval_object_property_dump;
! 293: head_done:
! 294: if (myht) {
! 295: zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) zval_element_dump_func, 1, level, (Z_TYPE_PP(struc) == IS_ARRAY ? 0 : 1));
! 296: if (is_temp) {
! 297: zend_hash_destroy(myht);
! 298: efree(myht);
! 299: }
! 300: }
! 301: if (level > 1) {
! 302: php_printf("%*c", level - 1, ' ');
! 303: }
! 304: PUTS("}\n");
! 305: break;
! 306: case IS_RESOURCE: {
! 307: char *type_name;
! 308:
! 309: type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(struc) TSRMLS_CC);
! 310: php_printf("%sresource(%ld) of type (%s) refcount(%u)\n", COMMON, Z_LVAL_PP(struc), type_name ? type_name : "Unknown", Z_REFCOUNT_PP(struc));
! 311: break;
! 312: }
! 313: default:
! 314: php_printf("%sUNKNOWN:0\n", COMMON);
! 315: break;
! 316: }
! 317: }
! 318: /* }}} */
! 319:
! 320: /* {{{ proto void debug_zval_dump(mixed var)
! 321: Dumps a string representation of an internal zend value to output. */
! 322: PHP_FUNCTION(debug_zval_dump)
! 323: {
! 324: zval ***args;
! 325: int argc;
! 326: int i;
! 327:
! 328: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
! 329: return;
! 330: }
! 331:
! 332: for (i = 0; i < argc; i++) {
! 333: php_debug_zval_dump(args[i], 1 TSRMLS_CC);
! 334: }
! 335: efree(args);
! 336: }
! 337: /* }}} */
! 338:
! 339: #define buffer_append_spaces(buf, num_spaces) \
! 340: do { \
! 341: char *tmp_spaces; \
! 342: int tmp_spaces_len; \
! 343: tmp_spaces_len = spprintf(&tmp_spaces, 0,"%*c", num_spaces, ' '); \
! 344: smart_str_appendl(buf, tmp_spaces, tmp_spaces_len); \
! 345: efree(tmp_spaces); \
! 346: } while(0);
! 347:
! 348: static int php_array_element_export(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
! 349: {
! 350: int level;
! 351: smart_str *buf;
! 352:
! 353: level = va_arg(args, int);
! 354: buf = va_arg(args, smart_str *);
! 355:
! 356: if (hash_key->nKeyLength == 0) { /* numeric key */
! 357: buffer_append_spaces(buf, level+1);
! 358: smart_str_append_long(buf, (long) hash_key->h);
! 359: smart_str_appendl(buf, " => ", 4);
! 360: } else { /* string key */
! 361: char *key, *tmp_str;
! 362: int key_len, tmp_len;
! 363: key = php_addcslashes(hash_key->arKey, hash_key->nKeyLength - 1, &key_len, 0, "'\\", 2 TSRMLS_CC);
! 364: tmp_str = php_str_to_str_ex(key, key_len, "\0", 1, "' . \"\\0\" . '", 12, &tmp_len, 0, NULL);
! 365:
! 366: buffer_append_spaces(buf, level + 1);
! 367:
! 368: smart_str_appendc(buf, '\'');
! 369: smart_str_appendl(buf, tmp_str, tmp_len);
! 370: smart_str_appendl(buf, "' => ", 5);
! 371:
! 372: efree(key);
! 373: efree(tmp_str);
! 374: }
! 375: php_var_export_ex(zv, level + 2, buf TSRMLS_CC);
! 376:
! 377: smart_str_appendc(buf, ',');
! 378: smart_str_appendc(buf, '\n');
! 379:
! 380: return 0;
! 381: }
! 382: /* }}} */
! 383:
! 384: static int php_object_element_export(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
! 385: {
! 386: int level;
! 387: smart_str *buf;
! 388:
! 389: level = va_arg(args, int);
! 390: buf = va_arg(args, smart_str *);
! 391:
! 392: buffer_append_spaces(buf, level + 2);
! 393: if (hash_key->nKeyLength != 0) {
! 394: char *class_name, /* ignored, but must be passed to unmangle */
! 395: *pname,
! 396: *pname_esc;
! 397: int pname_esc_len;
! 398:
! 399: zend_unmangle_property_name(hash_key->arKey, hash_key->nKeyLength - 1,
! 400: &class_name, &pname);
! 401: pname_esc = php_addcslashes(pname, strlen(pname), &pname_esc_len, 0,
! 402: "'\\", 2 TSRMLS_CC);
! 403:
! 404: smart_str_appendc(buf, '\'');
! 405: smart_str_appendl(buf, pname_esc, pname_esc_len);
! 406: smart_str_appendc(buf, '\'');
! 407: efree(pname_esc);
! 408: } else {
! 409: smart_str_append_long(buf, hash_key->h);
! 410: }
! 411:
! 412: smart_str_appendl(buf, " => ", 4);
! 413: php_var_export_ex(zv, level + 2, buf TSRMLS_CC);
! 414: smart_str_appendc(buf, ',');
! 415: smart_str_appendc(buf, '\n');
! 416:
! 417: return 0;
! 418: }
! 419: /* }}} */
! 420:
! 421: PHPAPI void php_var_export_ex(zval **struc, int level, smart_str *buf TSRMLS_DC) /* {{{ */
! 422: {
! 423: HashTable *myht;
! 424: char *tmp_str, *tmp_str2;
! 425: int tmp_len, tmp_len2;
! 426: char *class_name;
! 427: zend_uint class_name_len;
! 428:
! 429: switch (Z_TYPE_PP(struc)) {
! 430: case IS_BOOL:
! 431: if (Z_LVAL_PP(struc)) {
! 432: smart_str_appendl(buf, "true", 4);
! 433: } else {
! 434: smart_str_appendl(buf, "false", 5);
! 435: }
! 436: break;
! 437: case IS_NULL:
! 438: smart_str_appendl(buf, "NULL", 4);
! 439: break;
! 440: case IS_LONG:
! 441: smart_str_append_long(buf, Z_LVAL_PP(struc));
! 442: break;
! 443: case IS_DOUBLE:
! 444: tmp_len = spprintf(&tmp_str, 0,"%.*H", (int) EG(precision), Z_DVAL_PP(struc));
! 445: smart_str_appendl(buf, tmp_str, tmp_len);
! 446: efree(tmp_str);
! 447: break;
! 448: case IS_STRING:
! 449: tmp_str = php_addcslashes(Z_STRVAL_PP(struc), Z_STRLEN_PP(struc), &tmp_len, 0, "'\\", 2 TSRMLS_CC);
! 450: tmp_str2 = php_str_to_str_ex(tmp_str, tmp_len, "\0", 1, "' . \"\\0\" . '", 12, &tmp_len2, 0, NULL);
! 451:
! 452: smart_str_appendc(buf, '\'');
! 453: smart_str_appendl(buf, tmp_str2, tmp_len2);
! 454: smart_str_appendc(buf, '\'');
! 455:
! 456: efree(tmp_str2);
! 457: efree(tmp_str);
! 458: break;
! 459: case IS_ARRAY:
! 460: myht = Z_ARRVAL_PP(struc);
! 461: if (level > 1) {
! 462: smart_str_appendc(buf, '\n');
! 463: buffer_append_spaces(buf, level - 1);
! 464: }
! 465: smart_str_appendl(buf, "array (\n", 8);
! 466: zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) php_array_element_export, 2, level, buf);
! 467:
! 468: if (level > 1) {
! 469: buffer_append_spaces(buf, level - 1);
! 470: }
! 471: smart_str_appendc(buf, ')');
! 472:
! 473: break;
! 474: case IS_OBJECT:
! 475: myht = Z_OBJPROP_PP(struc);
! 476: if (level > 1) {
! 477: smart_str_appendc(buf, '\n');
! 478: buffer_append_spaces(buf, level - 1);
! 479: }
! 480: Z_OBJ_HANDLER(**struc, get_class_name)(*struc, &class_name, &class_name_len, 0 TSRMLS_CC);
! 481:
! 482: smart_str_appendl(buf, class_name, class_name_len);
! 483: smart_str_appendl(buf, "::__set_state(array(\n", 21);
! 484:
! 485: efree(class_name);
! 486: if (myht) {
! 487: zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) php_object_element_export, 2, level, buf);
! 488: }
! 489: if (level > 1) {
! 490: buffer_append_spaces(buf, level - 1);
! 491: }
! 492: smart_str_appendl(buf, "))", 2);
! 493:
! 494: break;
! 495: default:
! 496: smart_str_appendl(buf, "NULL", 4);
! 497: break;
! 498: }
! 499: }
! 500: /* }}} */
! 501:
! 502: /* FOR BC reasons, this will always perform and then print */
! 503: PHPAPI void php_var_export(zval **struc, int level TSRMLS_DC) /* {{{ */
! 504: {
! 505: smart_str buf = {0};
! 506: php_var_export_ex(struc, level, &buf TSRMLS_CC);
! 507: smart_str_0 (&buf);
! 508: PHPWRITE(buf.c, buf.len);
! 509: smart_str_free(&buf);
! 510: }
! 511: /* }}} */
! 512:
! 513: /* {{{ proto mixed var_export(mixed var [, bool return])
! 514: Outputs or returns a string representation of a variable */
! 515: PHP_FUNCTION(var_export)
! 516: {
! 517: zval *var;
! 518: zend_bool return_output = 0;
! 519: smart_str buf = {0};
! 520:
! 521: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &var, &return_output) == FAILURE) {
! 522: return;
! 523: }
! 524:
! 525: php_var_export_ex(&var, 1, &buf TSRMLS_CC);
! 526: smart_str_0 (&buf);
! 527:
! 528: if (return_output) {
! 529: RETVAL_STRINGL(buf.c, buf.len, 1);
! 530: } else {
! 531: PHPWRITE(buf.c, buf.len);
! 532: }
! 533: smart_str_free(&buf);
! 534: }
! 535: /* }}} */
! 536:
! 537: static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var_hash TSRMLS_DC);
! 538:
! 539: static inline int php_add_var_hash(HashTable *var_hash, zval *var, void *var_old TSRMLS_DC) /* {{{ */
! 540: {
! 541: ulong var_no;
! 542: char id[32], *p;
! 543: register int len;
! 544:
! 545: /* relies on "(long)" being a perfect hash function for data pointers,
! 546: * however the actual identity of an object has had to be determined
! 547: * by its object handle and the class entry since 5.0. */
! 548: if ((Z_TYPE_P(var) == IS_OBJECT) && Z_OBJ_HT_P(var)->get_class_entry) {
! 549: p = smart_str_print_long(id + sizeof(id) - 1,
! 550: (((size_t)Z_OBJCE_P(var) << 5)
! 551: | ((size_t)Z_OBJCE_P(var) >> (sizeof(long) * 8 - 5)))
! 552: + (long) Z_OBJ_HANDLE_P(var));
! 553: *(--p) = 'O';
! 554: len = id + sizeof(id) - 1 - p;
! 555: } else {
! 556: p = smart_str_print_long(id + sizeof(id) - 1, (long) var);
! 557: len = id + sizeof(id) - 1 - p;
! 558: }
! 559:
! 560: if (var_old && zend_hash_find(var_hash, p, len, var_old) == SUCCESS) {
! 561: if (!Z_ISREF_P(var)) {
! 562: /* we still need to bump up the counter, since non-refs will
! 563: * be counted separately by unserializer */
! 564: var_no = -1;
! 565: zend_hash_next_index_insert(var_hash, &var_no, sizeof(var_no), NULL);
! 566: }
! 567: return FAILURE;
! 568: }
! 569:
! 570: /* +1 because otherwise hash will think we are trying to store NULL pointer */
! 571: var_no = zend_hash_num_elements(var_hash) + 1;
! 572: zend_hash_add(var_hash, p, len, &var_no, sizeof(var_no), NULL);
! 573: return SUCCESS;
! 574: }
! 575: /* }}} */
! 576:
! 577: static inline void php_var_serialize_long(smart_str *buf, long val) /* {{{ */
! 578: {
! 579: smart_str_appendl(buf, "i:", 2);
! 580: smart_str_append_long(buf, val);
! 581: smart_str_appendc(buf, ';');
! 582: }
! 583: /* }}} */
! 584:
! 585: static inline void php_var_serialize_string(smart_str *buf, char *str, int len) /* {{{ */
! 586: {
! 587: smart_str_appendl(buf, "s:", 2);
! 588: smart_str_append_long(buf, len);
! 589: smart_str_appendl(buf, ":\"", 2);
! 590: smart_str_appendl(buf, str, len);
! 591: smart_str_appendl(buf, "\";", 2);
! 592: }
! 593: /* }}} */
! 594:
! 595: static inline zend_bool php_var_serialize_class_name(smart_str *buf, zval *struc TSRMLS_DC) /* {{{ */
! 596: {
! 597: PHP_CLASS_ATTRIBUTES;
! 598:
! 599: PHP_SET_CLASS_ATTRIBUTES(struc);
! 600: smart_str_appendl(buf, "O:", 2);
! 601: smart_str_append_long(buf, (int)name_len);
! 602: smart_str_appendl(buf, ":\"", 2);
! 603: smart_str_appendl(buf, class_name, name_len);
! 604: smart_str_appendl(buf, "\":", 2);
! 605: PHP_CLEANUP_CLASS_ATTRIBUTES();
! 606: return incomplete_class;
! 607: }
! 608: /* }}} */
! 609:
! 610: static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_ptr, HashTable *var_hash TSRMLS_DC) /* {{{ */
! 611: {
! 612: int count;
! 613: zend_bool incomplete_class;
! 614:
! 615: incomplete_class = php_var_serialize_class_name(buf, struc TSRMLS_CC);
! 616: /* count after serializing name, since php_var_serialize_class_name
! 617: * changes the count if the variable is incomplete class */
! 618: count = zend_hash_num_elements(HASH_OF(retval_ptr));
! 619: if (incomplete_class) {
! 620: --count;
! 621: }
! 622: smart_str_append_long(buf, count);
! 623: smart_str_appendl(buf, ":{", 2);
! 624:
! 625: if (count > 0) {
! 626: char *key;
! 627: zval **d, **name;
! 628: ulong index;
! 629: HashPosition pos;
! 630: int i;
! 631: zval nval, *nvalp;
! 632:
! 633: ZVAL_NULL(&nval);
! 634: nvalp = &nval;
! 635:
! 636: zend_hash_internal_pointer_reset_ex(HASH_OF(retval_ptr), &pos);
! 637:
! 638: for (;; zend_hash_move_forward_ex(HASH_OF(retval_ptr), &pos)) {
! 639: i = zend_hash_get_current_key_ex(HASH_OF(retval_ptr), &key, NULL, &index, 0, &pos);
! 640:
! 641: if (i == HASH_KEY_NON_EXISTANT) {
! 642: break;
! 643: }
! 644:
! 645: if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) {
! 646: continue;
! 647: }
! 648: zend_hash_get_current_data_ex(HASH_OF(retval_ptr), (void **) &name, &pos);
! 649:
! 650: if (Z_TYPE_PP(name) != IS_STRING) {
! 651: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array only containing the names of instance-variables to serialize.");
! 652: /* we should still add element even if it's not OK,
! 653: * since we already wrote the length of the array before */
! 654: smart_str_appendl(buf,"N;", 2);
! 655: continue;
! 656: }
! 657: if (zend_hash_find(Z_OBJPROP_P(struc), Z_STRVAL_PP(name), Z_STRLEN_PP(name) + 1, (void *) &d) == SUCCESS) {
! 658: php_var_serialize_string(buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name));
! 659: php_var_serialize_intern(buf, *d, var_hash TSRMLS_CC);
! 660: } else {
! 661: zend_class_entry *ce;
! 662: ce = zend_get_class_entry(struc TSRMLS_CC);
! 663: if (ce) {
! 664: char *prot_name, *priv_name;
! 665: int prop_name_length;
! 666:
! 667: do {
! 668: zend_mangle_property_name(&priv_name, &prop_name_length, ce->name, ce->name_length, Z_STRVAL_PP(name), Z_STRLEN_PP(name), ce->type & ZEND_INTERNAL_CLASS);
! 669: if (zend_hash_find(Z_OBJPROP_P(struc), priv_name, prop_name_length + 1, (void *) &d) == SUCCESS) {
! 670: php_var_serialize_string(buf, priv_name, prop_name_length);
! 671: pefree(priv_name, ce->type & ZEND_INTERNAL_CLASS);
! 672: php_var_serialize_intern(buf, *d, var_hash TSRMLS_CC);
! 673: break;
! 674: }
! 675: pefree(priv_name, ce->type & ZEND_INTERNAL_CLASS);
! 676: zend_mangle_property_name(&prot_name, &prop_name_length, "*", 1, Z_STRVAL_PP(name), Z_STRLEN_PP(name), ce->type & ZEND_INTERNAL_CLASS);
! 677: if (zend_hash_find(Z_OBJPROP_P(struc), prot_name, prop_name_length + 1, (void *) &d) == SUCCESS) {
! 678: php_var_serialize_string(buf, prot_name, prop_name_length);
! 679: pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
! 680: php_var_serialize_intern(buf, *d, var_hash TSRMLS_CC);
! 681: break;
! 682: }
! 683: pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
! 684: php_var_serialize_string(buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name));
! 685: php_var_serialize_intern(buf, nvalp, var_hash TSRMLS_CC);
! 686: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "\"%s\" returned as member variable from __sleep() but does not exist", Z_STRVAL_PP(name));
! 687: } while (0);
! 688: } else {
! 689: php_var_serialize_string(buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name));
! 690: php_var_serialize_intern(buf, nvalp, var_hash TSRMLS_CC);
! 691: }
! 692: }
! 693: }
! 694: }
! 695: smart_str_appendc(buf, '}');
! 696: }
! 697: /* }}} */
! 698:
! 699: static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var_hash TSRMLS_DC) /* {{{ */
! 700: {
! 701: int i;
! 702: ulong *var_already;
! 703: HashTable *myht;
! 704:
! 705: if (var_hash && php_add_var_hash(var_hash, struc, (void *) &var_already TSRMLS_CC) == FAILURE) {
! 706: if (Z_ISREF_P(struc)) {
! 707: smart_str_appendl(buf, "R:", 2);
! 708: smart_str_append_long(buf, (long)*var_already);
! 709: smart_str_appendc(buf, ';');
! 710: return;
! 711: } else if (Z_TYPE_P(struc) == IS_OBJECT) {
! 712: smart_str_appendl(buf, "r:", 2);
! 713: smart_str_append_long(buf, (long)*var_already);
! 714: smart_str_appendc(buf, ';');
! 715: return;
! 716: }
! 717: }
! 718:
! 719: switch (Z_TYPE_P(struc)) {
! 720: case IS_BOOL:
! 721: smart_str_appendl(buf, "b:", 2);
! 722: smart_str_append_long(buf, Z_LVAL_P(struc));
! 723: smart_str_appendc(buf, ';');
! 724: return;
! 725:
! 726: case IS_NULL:
! 727: smart_str_appendl(buf, "N;", 2);
! 728: return;
! 729:
! 730: case IS_LONG:
! 731: php_var_serialize_long(buf, Z_LVAL_P(struc));
! 732: return;
! 733:
! 734: case IS_DOUBLE: {
! 735: char *s;
! 736:
! 737: smart_str_appendl(buf, "d:", 2);
! 738: s = (char *) safe_emalloc(PG(serialize_precision), 1, MAX_LENGTH_OF_DOUBLE + 1);
! 739: php_gcvt(Z_DVAL_P(struc), PG(serialize_precision), '.', 'E', s);
! 740: smart_str_appends(buf, s);
! 741: smart_str_appendc(buf, ';');
! 742: efree(s);
! 743: return;
! 744: }
! 745:
! 746: case IS_STRING:
! 747: php_var_serialize_string(buf, Z_STRVAL_P(struc), Z_STRLEN_P(struc));
! 748: return;
! 749:
! 750: case IS_OBJECT: {
! 751: zval *retval_ptr = NULL;
! 752: zval fname;
! 753: int res;
! 754: zend_class_entry *ce = NULL;
! 755:
! 756: if (Z_OBJ_HT_P(struc)->get_class_entry) {
! 757: ce = Z_OBJCE_P(struc);
! 758: }
! 759:
! 760: if (ce && ce->serialize != NULL) {
! 761: /* has custom handler */
! 762: unsigned char *serialized_data = NULL;
! 763: zend_uint serialized_length;
! 764:
! 765: if (ce->serialize(struc, &serialized_data, &serialized_length, (zend_serialize_data *)var_hash TSRMLS_CC) == SUCCESS) {
! 766: smart_str_appendl(buf, "C:", 2);
! 767: smart_str_append_long(buf, (int)Z_OBJCE_P(struc)->name_length);
! 768: smart_str_appendl(buf, ":\"", 2);
! 769: smart_str_appendl(buf, Z_OBJCE_P(struc)->name, Z_OBJCE_P(struc)->name_length);
! 770: smart_str_appendl(buf, "\":", 2);
! 771:
! 772: smart_str_append_long(buf, (int)serialized_length);
! 773: smart_str_appendl(buf, ":{", 2);
! 774: smart_str_appendl(buf, serialized_data, serialized_length);
! 775: smart_str_appendc(buf, '}');
! 776: } else {
! 777: smart_str_appendl(buf, "N;", 2);
! 778: }
! 779: if (serialized_data) {
! 780: efree(serialized_data);
! 781: }
! 782: return;
! 783: }
! 784:
! 785: if (ce && ce != PHP_IC_ENTRY && zend_hash_exists(&ce->function_table, "__sleep", sizeof("__sleep"))) {
! 786: INIT_PZVAL(&fname);
! 787: ZVAL_STRINGL(&fname, "__sleep", sizeof("__sleep") - 1, 0);
! 788: res = call_user_function_ex(CG(function_table), &struc, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC);
! 789:
! 790: if (res == SUCCESS && !EG(exception)) {
! 791: if (retval_ptr) {
! 792: if (HASH_OF(retval_ptr)) {
! 793: php_var_serialize_class(buf, struc, retval_ptr, var_hash TSRMLS_CC);
! 794: } else {
! 795: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array only containing the names of instance-variables to serialize");
! 796: /* we should still add element even if it's not OK,
! 797: * since we already wrote the length of the array before */
! 798: smart_str_appendl(buf,"N;", 2);
! 799: }
! 800: zval_ptr_dtor(&retval_ptr);
! 801: }
! 802: return;
! 803: }
! 804: }
! 805:
! 806: if (retval_ptr) {
! 807: zval_ptr_dtor(&retval_ptr);
! 808: }
! 809: /* fall-through */
! 810: }
! 811: case IS_ARRAY: {
! 812: zend_bool incomplete_class = 0;
! 813: if (Z_TYPE_P(struc) == IS_ARRAY) {
! 814: smart_str_appendl(buf, "a:", 2);
! 815: myht = HASH_OF(struc);
! 816: } else {
! 817: incomplete_class = php_var_serialize_class_name(buf, struc TSRMLS_CC);
! 818: myht = Z_OBJPROP_P(struc);
! 819: }
! 820: /* count after serializing name, since php_var_serialize_class_name
! 821: * changes the count if the variable is incomplete class */
! 822: i = myht ? zend_hash_num_elements(myht) : 0;
! 823: if (i > 0 && incomplete_class) {
! 824: --i;
! 825: }
! 826: smart_str_append_long(buf, i);
! 827: smart_str_appendl(buf, ":{", 2);
! 828: if (i > 0) {
! 829: char *key;
! 830: zval **data;
! 831: ulong index;
! 832: uint key_len;
! 833: HashPosition pos;
! 834:
! 835: zend_hash_internal_pointer_reset_ex(myht, &pos);
! 836: for (;; zend_hash_move_forward_ex(myht, &pos)) {
! 837: i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos);
! 838: if (i == HASH_KEY_NON_EXISTANT) {
! 839: break;
! 840: }
! 841: if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) {
! 842: continue;
! 843: }
! 844:
! 845: switch (i) {
! 846: case HASH_KEY_IS_LONG:
! 847: php_var_serialize_long(buf, index);
! 848: break;
! 849: case HASH_KEY_IS_STRING:
! 850: php_var_serialize_string(buf, key, key_len - 1);
! 851: break;
! 852: }
! 853:
! 854: /* we should still add element even if it's not OK,
! 855: * since we already wrote the length of the array before */
! 856: if (zend_hash_get_current_data_ex(myht, (void **) &data, &pos) != SUCCESS
! 857: || !data
! 858: || data == &struc
! 859: || (Z_TYPE_PP(data) == IS_ARRAY && Z_ARRVAL_PP(data)->nApplyCount > 1)
! 860: ) {
! 861: smart_str_appendl(buf, "N;", 2);
! 862: } else {
! 863: if (Z_TYPE_PP(data) == IS_ARRAY) {
! 864: Z_ARRVAL_PP(data)->nApplyCount++;
! 865: }
! 866: php_var_serialize_intern(buf, *data, var_hash TSRMLS_CC);
! 867: if (Z_TYPE_PP(data) == IS_ARRAY) {
! 868: Z_ARRVAL_PP(data)->nApplyCount--;
! 869: }
! 870: }
! 871: }
! 872: }
! 873: smart_str_appendc(buf, '}');
! 874: return;
! 875: }
! 876: default:
! 877: smart_str_appendl(buf, "i:0;", 4);
! 878: return;
! 879: }
! 880: }
! 881: /* }}} */
! 882:
! 883: PHPAPI void php_var_serialize(smart_str *buf, zval **struc, HashTable *var_hash TSRMLS_DC) /* {{{ */
! 884: {
! 885: php_var_serialize_intern(buf, *struc, var_hash TSRMLS_CC);
! 886: smart_str_0(buf);
! 887: }
! 888: /* }}} */
! 889:
! 890: /* {{{ proto string serialize(mixed variable)
! 891: Returns a string representation of variable (which can later be unserialized) */
! 892: PHP_FUNCTION(serialize)
! 893: {
! 894: zval **struc;
! 895: php_serialize_data_t var_hash;
! 896: smart_str buf = {0};
! 897:
! 898: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &struc) == FAILURE) {
! 899: return;
! 900: }
! 901:
! 902: Z_TYPE_P(return_value) = IS_STRING;
! 903: Z_STRVAL_P(return_value) = NULL;
! 904: Z_STRLEN_P(return_value) = 0;
! 905:
! 906: PHP_VAR_SERIALIZE_INIT(var_hash);
! 907: php_var_serialize(&buf, struc, &var_hash TSRMLS_CC);
! 908: PHP_VAR_SERIALIZE_DESTROY(var_hash);
! 909:
! 910: if (buf.c) {
! 911: RETURN_STRINGL(buf.c, buf.len, 0);
! 912: } else {
! 913: RETURN_NULL();
! 914: }
! 915: }
! 916: /* }}} */
! 917:
! 918: /* {{{ proto mixed unserialize(string variable_representation)
! 919: Takes a string representation of variable and recreates it */
! 920: PHP_FUNCTION(unserialize)
! 921: {
! 922: char *buf = NULL;
! 923: int buf_len;
! 924: const unsigned char *p;
! 925: php_unserialize_data_t var_hash;
! 926:
! 927: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
! 928: RETURN_FALSE;
! 929: }
! 930:
! 931: if (buf_len == 0) {
! 932: RETURN_FALSE;
! 933: }
! 934:
! 935: p = (const unsigned char*) buf;
! 936: PHP_VAR_UNSERIALIZE_INIT(var_hash);
! 937: if (!php_var_unserialize(&return_value, &p, p + buf_len, &var_hash TSRMLS_CC)) {
! 938: PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
! 939: zval_dtor(return_value);
! 940: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len);
! 941: RETURN_FALSE;
! 942: }
! 943: PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
! 944: }
! 945: /* }}} */
! 946:
! 947: /* {{{ proto int memory_get_usage([real_usage])
! 948: Returns the allocated by PHP memory */
! 949: PHP_FUNCTION(memory_get_usage) {
! 950: zend_bool real_usage = 0;
! 951:
! 952: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &real_usage) == FAILURE) {
! 953: RETURN_FALSE;
! 954: }
! 955:
! 956: RETURN_LONG(zend_memory_usage(real_usage TSRMLS_CC));
! 957: }
! 958: /* }}} */
! 959:
! 960: /* {{{ proto int memory_get_peak_usage([real_usage])
! 961: Returns the peak allocated by PHP memory */
! 962: PHP_FUNCTION(memory_get_peak_usage) {
! 963: zend_bool real_usage = 0;
! 964:
! 965: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &real_usage) == FAILURE) {
! 966: RETURN_FALSE;
! 967: }
! 968:
! 969: RETURN_LONG(zend_memory_peak_usage(real_usage TSRMLS_CC));
! 970: }
! 971: /* }}} */
! 972:
! 973: /*
! 974: * Local variables:
! 975: * tab-width: 4
! 976: * c-basic-offset: 4
! 977: * End:
! 978: * vim600: sw=4 ts=4 fdm=marker
! 979: * vim<600: sw=4 ts=4
! 980: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>