File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / standard / var.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:03:57 2014 UTC (10 years, 1 month ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>