Annotation of embedaddon/php/ext/standard/var.c, revision 1.1.1.2
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: +----------------------------------------------------------------------+
1.1.1.2 ! misho 15: | Authors: Jani Lehtimäki <jkl@njet.net> |
1.1 misho 16: | Thies C. Arntzen <thies@thieso.net> |
17: | Sascha Schumann <sascha@schumann.cx> |
18: +----------------------------------------------------------------------+
19: */
20:
1.1.1.2 ! misho 21: /* $Id$ */
1.1 misho 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;
1.1.1.2 ! misho 59: const char *prop_name, *class_name;
1.1 misho 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;
1.1.1.2 ! misho 90: const char *class_name;
1.1 misho 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:
1.1.1.2 ! misho 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: }
1.1 misho 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: {
1.1.1.2 ! misho 159: const char *type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(struc) TSRMLS_CC);
1.1 misho 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;
1.1.1.2 ! misho 216: const char *prop_name, *class_name;
1.1 misho 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;
1.1.1.2 ! misho 245: const char *class_name;
1.1 misho 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: }
1.1.1.2 ! misho 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);
1.1 misho 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: {
1.1.1.2 ! misho 305: const char *type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(struc) TSRMLS_CC);
1.1 misho 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);
1.1.1.2 ! misho 356:
1.1 misho 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');
1.1.1.2 ! misho 376:
1.1 misho 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) {
1.1.1.2 ! misho 391: const char *class_name; /* ignored, but must be passed to unmangle */
! 392: const char *pname;
! 393: char *pname_esc;
1.1 misho 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 {
1.1.1.2 ! misho 406: smart_str_append_long(buf, (long) hash_key->h);
1.1 misho 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;
1.1.1.2 ! misho 421: const char *class_name;
1.1 misho 422: zend_uint class_name_len;
423:
424: switch (Z_TYPE_PP(struc)) {
425: case IS_BOOL:
1.1.1.2 ! misho 426: if (Z_LVAL_PP(struc)) {
! 427: smart_str_appendl(buf, "true", 4);
! 428: } else {
! 429: smart_str_appendl(buf, "false", 5);
! 430: }
1.1 misho 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", (int) EG(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 (level > 1) {
457: smart_str_appendc(buf, '\n');
458: buffer_append_spaces(buf, level - 1);
459: }
460: smart_str_appendl(buf, "array (\n", 8);
461: zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) php_array_element_export, 2, level, buf);
462:
463: if (level > 1) {
464: buffer_append_spaces(buf, level - 1);
465: }
466: smart_str_appendc(buf, ')');
1.1.1.2 ! misho 467:
1.1 misho 468: break;
1.1.1.2 ! misho 469:
1.1 misho 470: case IS_OBJECT:
471: myht = Z_OBJPROP_PP(struc);
472: if (level > 1) {
473: smart_str_appendc(buf, '\n');
474: buffer_append_spaces(buf, level - 1);
475: }
476: Z_OBJ_HANDLER(**struc, get_class_name)(*struc, &class_name, &class_name_len, 0 TSRMLS_CC);
477:
478: smart_str_appendl(buf, class_name, class_name_len);
479: smart_str_appendl(buf, "::__set_state(array(\n", 21);
480:
1.1.1.2 ! misho 481: efree((char*)class_name);
1.1 misho 482: if (myht) {
1.1.1.2 ! misho 483: zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) php_object_element_export, 1, level, buf);
1.1 misho 484: }
485: if (level > 1) {
486: buffer_append_spaces(buf, level - 1);
487: }
488: smart_str_appendl(buf, "))", 2);
489:
490: break;
491: default:
492: smart_str_appendl(buf, "NULL", 4);
493: break;
494: }
495: }
496: /* }}} */
497:
498: /* FOR BC reasons, this will always perform and then print */
499: PHPAPI void php_var_export(zval **struc, int level TSRMLS_DC) /* {{{ */
500: {
501: smart_str buf = {0};
502: php_var_export_ex(struc, level, &buf TSRMLS_CC);
503: smart_str_0 (&buf);
504: PHPWRITE(buf.c, buf.len);
505: smart_str_free(&buf);
506: }
507: /* }}} */
508:
1.1.1.2 ! misho 509:
1.1 misho 510: /* {{{ proto mixed var_export(mixed var [, bool return])
511: Outputs or returns a string representation of a variable */
512: PHP_FUNCTION(var_export)
513: {
514: zval *var;
515: zend_bool return_output = 0;
516: smart_str buf = {0};
517:
518: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &var, &return_output) == FAILURE) {
519: return;
520: }
521:
522: php_var_export_ex(&var, 1, &buf TSRMLS_CC);
523: smart_str_0 (&buf);
524:
525: if (return_output) {
526: RETVAL_STRINGL(buf.c, buf.len, 1);
527: } else {
528: PHPWRITE(buf.c, buf.len);
529: }
530: smart_str_free(&buf);
531: }
532: /* }}} */
533:
534: static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var_hash TSRMLS_DC);
535:
536: static inline int php_add_var_hash(HashTable *var_hash, zval *var, void *var_old TSRMLS_DC) /* {{{ */
537: {
538: ulong var_no;
539: char id[32], *p;
540: register int len;
541:
542: /* relies on "(long)" being a perfect hash function for data pointers,
543: * however the actual identity of an object has had to be determined
544: * by its object handle and the class entry since 5.0. */
545: if ((Z_TYPE_P(var) == IS_OBJECT) && Z_OBJ_HT_P(var)->get_class_entry) {
546: p = smart_str_print_long(id + sizeof(id) - 1,
547: (((size_t)Z_OBJCE_P(var) << 5)
548: | ((size_t)Z_OBJCE_P(var) >> (sizeof(long) * 8 - 5)))
549: + (long) Z_OBJ_HANDLE_P(var));
550: *(--p) = 'O';
551: len = id + sizeof(id) - 1 - p;
552: } else {
553: p = smart_str_print_long(id + sizeof(id) - 1, (long) var);
554: len = id + sizeof(id) - 1 - p;
555: }
556:
557: if (var_old && zend_hash_find(var_hash, p, len, var_old) == SUCCESS) {
558: if (!Z_ISREF_P(var)) {
559: /* we still need to bump up the counter, since non-refs will
560: * be counted separately by unserializer */
561: var_no = -1;
562: zend_hash_next_index_insert(var_hash, &var_no, sizeof(var_no), NULL);
563: }
1.1.1.2 ! misho 564: #if 0
! 565: fprintf(stderr, "- had var (%d): %lu\n", Z_TYPE_P(var), **(ulong**)var_old);
! 566: #endif
1.1 misho 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);
1.1.1.2 ! misho 573: #if 0
! 574: fprintf(stderr, "+ add var (%d): %lu\n", Z_TYPE_P(var), var_no);
! 575: #endif
1.1 misho 576: return SUCCESS;
577: }
578: /* }}} */
579:
580: static inline void php_var_serialize_long(smart_str *buf, long val) /* {{{ */
581: {
582: smart_str_appendl(buf, "i:", 2);
583: smart_str_append_long(buf, val);
584: smart_str_appendc(buf, ';');
585: }
586: /* }}} */
587:
588: static inline void php_var_serialize_string(smart_str *buf, char *str, int len) /* {{{ */
589: {
590: smart_str_appendl(buf, "s:", 2);
591: smart_str_append_long(buf, len);
592: smart_str_appendl(buf, ":\"", 2);
593: smart_str_appendl(buf, str, len);
594: smart_str_appendl(buf, "\";", 2);
595: }
596: /* }}} */
597:
598: static inline zend_bool php_var_serialize_class_name(smart_str *buf, zval *struc TSRMLS_DC) /* {{{ */
599: {
600: PHP_CLASS_ATTRIBUTES;
601:
602: PHP_SET_CLASS_ATTRIBUTES(struc);
603: smart_str_appendl(buf, "O:", 2);
604: smart_str_append_long(buf, (int)name_len);
605: smart_str_appendl(buf, ":\"", 2);
606: smart_str_appendl(buf, class_name, name_len);
607: smart_str_appendl(buf, "\":", 2);
608: PHP_CLEANUP_CLASS_ATTRIBUTES();
609: return incomplete_class;
610: }
611: /* }}} */
612:
613: static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_ptr, HashTable *var_hash TSRMLS_DC) /* {{{ */
614: {
615: int count;
616: zend_bool incomplete_class;
617:
618: incomplete_class = php_var_serialize_class_name(buf, struc TSRMLS_CC);
619: /* count after serializing name, since php_var_serialize_class_name
620: * changes the count if the variable is incomplete class */
621: count = zend_hash_num_elements(HASH_OF(retval_ptr));
622: if (incomplete_class) {
623: --count;
624: }
625: smart_str_append_long(buf, count);
626: smart_str_appendl(buf, ":{", 2);
627:
628: if (count > 0) {
629: char *key;
630: zval **d, **name;
631: ulong index;
632: HashPosition pos;
633: int i;
634: zval nval, *nvalp;
635:
636: ZVAL_NULL(&nval);
637: nvalp = &nval;
638:
639: zend_hash_internal_pointer_reset_ex(HASH_OF(retval_ptr), &pos);
640:
641: for (;; zend_hash_move_forward_ex(HASH_OF(retval_ptr), &pos)) {
642: i = zend_hash_get_current_key_ex(HASH_OF(retval_ptr), &key, NULL, &index, 0, &pos);
643:
644: if (i == HASH_KEY_NON_EXISTANT) {
645: break;
646: }
647:
648: if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) {
649: continue;
650: }
651: zend_hash_get_current_data_ex(HASH_OF(retval_ptr), (void **) &name, &pos);
652:
653: if (Z_TYPE_PP(name) != IS_STRING) {
654: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array only containing the names of instance-variables to serialize.");
655: /* we should still add element even if it's not OK,
656: * since we already wrote the length of the array before */
657: smart_str_appendl(buf,"N;", 2);
658: continue;
659: }
660: if (zend_hash_find(Z_OBJPROP_P(struc), Z_STRVAL_PP(name), Z_STRLEN_PP(name) + 1, (void *) &d) == SUCCESS) {
661: php_var_serialize_string(buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name));
662: php_var_serialize_intern(buf, *d, var_hash TSRMLS_CC);
663: } else {
664: zend_class_entry *ce;
665: ce = zend_get_class_entry(struc TSRMLS_CC);
666: if (ce) {
667: char *prot_name, *priv_name;
668: int prop_name_length;
669:
670: do {
671: 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);
672: if (zend_hash_find(Z_OBJPROP_P(struc), priv_name, prop_name_length + 1, (void *) &d) == SUCCESS) {
673: php_var_serialize_string(buf, priv_name, prop_name_length);
674: pefree(priv_name, ce->type & ZEND_INTERNAL_CLASS);
675: php_var_serialize_intern(buf, *d, var_hash TSRMLS_CC);
676: break;
677: }
678: pefree(priv_name, ce->type & ZEND_INTERNAL_CLASS);
679: zend_mangle_property_name(&prot_name, &prop_name_length, "*", 1, Z_STRVAL_PP(name), Z_STRLEN_PP(name), ce->type & ZEND_INTERNAL_CLASS);
680: if (zend_hash_find(Z_OBJPROP_P(struc), prot_name, prop_name_length + 1, (void *) &d) == SUCCESS) {
681: php_var_serialize_string(buf, prot_name, prop_name_length);
682: pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
683: php_var_serialize_intern(buf, *d, var_hash TSRMLS_CC);
684: break;
685: }
686: pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
687: php_var_serialize_string(buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name));
688: php_var_serialize_intern(buf, nvalp, var_hash TSRMLS_CC);
689: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "\"%s\" returned as member variable from __sleep() but does not exist", Z_STRVAL_PP(name));
690: } while (0);
691: } else {
692: php_var_serialize_string(buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name));
693: php_var_serialize_intern(buf, nvalp, var_hash TSRMLS_CC);
694: }
695: }
696: }
697: }
698: smart_str_appendc(buf, '}');
699: }
700: /* }}} */
701:
702: static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var_hash TSRMLS_DC) /* {{{ */
703: {
704: int i;
705: ulong *var_already;
706: HashTable *myht;
707:
708: if (var_hash && php_add_var_hash(var_hash, struc, (void *) &var_already TSRMLS_CC) == FAILURE) {
709: if (Z_ISREF_P(struc)) {
710: smart_str_appendl(buf, "R:", 2);
711: smart_str_append_long(buf, (long)*var_already);
712: smart_str_appendc(buf, ';');
713: return;
714: } else if (Z_TYPE_P(struc) == IS_OBJECT) {
715: smart_str_appendl(buf, "r:", 2);
716: smart_str_append_long(buf, (long)*var_already);
717: smart_str_appendc(buf, ';');
718: return;
719: }
720: }
721:
722: switch (Z_TYPE_P(struc)) {
723: case IS_BOOL:
724: smart_str_appendl(buf, "b:", 2);
725: smart_str_append_long(buf, Z_LVAL_P(struc));
726: smart_str_appendc(buf, ';');
727: return;
728:
729: case IS_NULL:
730: smart_str_appendl(buf, "N;", 2);
731: return;
732:
733: case IS_LONG:
734: php_var_serialize_long(buf, Z_LVAL_P(struc));
735: return;
736:
737: case IS_DOUBLE: {
738: char *s;
739:
740: smart_str_appendl(buf, "d:", 2);
741: s = (char *) safe_emalloc(PG(serialize_precision), 1, MAX_LENGTH_OF_DOUBLE + 1);
742: php_gcvt(Z_DVAL_P(struc), PG(serialize_precision), '.', 'E', s);
743: smart_str_appends(buf, s);
744: smart_str_appendc(buf, ';');
745: efree(s);
746: return;
747: }
748:
749: case IS_STRING:
750: php_var_serialize_string(buf, Z_STRVAL_P(struc), Z_STRLEN_P(struc));
751: return;
752:
753: case IS_OBJECT: {
754: zval *retval_ptr = NULL;
755: zval fname;
756: int res;
757: zend_class_entry *ce = NULL;
758:
759: if (Z_OBJ_HT_P(struc)->get_class_entry) {
760: ce = Z_OBJCE_P(struc);
761: }
762:
763: if (ce && ce->serialize != NULL) {
764: /* has custom handler */
765: unsigned char *serialized_data = NULL;
766: zend_uint serialized_length;
767:
768: if (ce->serialize(struc, &serialized_data, &serialized_length, (zend_serialize_data *)var_hash TSRMLS_CC) == SUCCESS) {
769: smart_str_appendl(buf, "C:", 2);
770: smart_str_append_long(buf, (int)Z_OBJCE_P(struc)->name_length);
771: smart_str_appendl(buf, ":\"", 2);
772: smart_str_appendl(buf, Z_OBJCE_P(struc)->name, Z_OBJCE_P(struc)->name_length);
773: smart_str_appendl(buf, "\":", 2);
774:
775: smart_str_append_long(buf, (int)serialized_length);
776: smart_str_appendl(buf, ":{", 2);
777: smart_str_appendl(buf, serialized_data, serialized_length);
778: smart_str_appendc(buf, '}');
779: } else {
780: smart_str_appendl(buf, "N;", 2);
781: }
782: if (serialized_data) {
783: efree(serialized_data);
784: }
785: return;
786: }
787:
788: if (ce && ce != PHP_IC_ENTRY && zend_hash_exists(&ce->function_table, "__sleep", sizeof("__sleep"))) {
789: INIT_PZVAL(&fname);
790: ZVAL_STRINGL(&fname, "__sleep", sizeof("__sleep") - 1, 0);
1.1.1.2 ! misho 791: BG(serialize_lock)++;
1.1 misho 792: res = call_user_function_ex(CG(function_table), &struc, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC);
1.1.1.2 ! misho 793: BG(serialize_lock)--;
1.1 misho 794:
795: if (res == SUCCESS && !EG(exception)) {
796: if (retval_ptr) {
797: if (HASH_OF(retval_ptr)) {
798: php_var_serialize_class(buf, struc, retval_ptr, var_hash TSRMLS_CC);
799: } else {
800: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array only containing the names of instance-variables to serialize");
801: /* we should still add element even if it's not OK,
802: * since we already wrote the length of the array before */
803: smart_str_appendl(buf,"N;", 2);
804: }
805: zval_ptr_dtor(&retval_ptr);
806: }
807: return;
808: }
809: }
810:
811: if (retval_ptr) {
812: zval_ptr_dtor(&retval_ptr);
813: }
814: /* fall-through */
815: }
816: case IS_ARRAY: {
817: zend_bool incomplete_class = 0;
818: if (Z_TYPE_P(struc) == IS_ARRAY) {
819: smart_str_appendl(buf, "a:", 2);
820: myht = HASH_OF(struc);
821: } else {
822: incomplete_class = php_var_serialize_class_name(buf, struc TSRMLS_CC);
823: myht = Z_OBJPROP_P(struc);
824: }
825: /* count after serializing name, since php_var_serialize_class_name
826: * changes the count if the variable is incomplete class */
827: i = myht ? zend_hash_num_elements(myht) : 0;
828: if (i > 0 && incomplete_class) {
829: --i;
830: }
831: smart_str_append_long(buf, i);
832: smart_str_appendl(buf, ":{", 2);
833: if (i > 0) {
834: char *key;
835: zval **data;
836: ulong index;
837: uint key_len;
838: HashPosition pos;
839:
840: zend_hash_internal_pointer_reset_ex(myht, &pos);
841: for (;; zend_hash_move_forward_ex(myht, &pos)) {
842: i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos);
843: if (i == HASH_KEY_NON_EXISTANT) {
844: break;
845: }
846: if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) {
847: continue;
848: }
849:
850: switch (i) {
851: case HASH_KEY_IS_LONG:
852: php_var_serialize_long(buf, index);
853: break;
854: case HASH_KEY_IS_STRING:
855: php_var_serialize_string(buf, key, key_len - 1);
856: break;
857: }
858:
859: /* we should still add element even if it's not OK,
860: * since we already wrote the length of the array before */
861: if (zend_hash_get_current_data_ex(myht, (void **) &data, &pos) != SUCCESS
862: || !data
863: || data == &struc
864: || (Z_TYPE_PP(data) == IS_ARRAY && Z_ARRVAL_PP(data)->nApplyCount > 1)
865: ) {
866: smart_str_appendl(buf, "N;", 2);
867: } else {
868: if (Z_TYPE_PP(data) == IS_ARRAY) {
869: Z_ARRVAL_PP(data)->nApplyCount++;
870: }
871: php_var_serialize_intern(buf, *data, var_hash TSRMLS_CC);
872: if (Z_TYPE_PP(data) == IS_ARRAY) {
873: Z_ARRVAL_PP(data)->nApplyCount--;
874: }
875: }
876: }
877: }
878: smart_str_appendc(buf, '}');
879: return;
880: }
881: default:
882: smart_str_appendl(buf, "i:0;", 4);
883: return;
884: }
885: }
886: /* }}} */
887:
1.1.1.2 ! misho 888: PHPAPI void php_var_serialize(smart_str *buf, zval **struc, php_serialize_data_t *var_hash TSRMLS_DC) /* {{{ */
1.1 misho 889: {
1.1.1.2 ! misho 890: php_var_serialize_intern(buf, *struc, *var_hash TSRMLS_CC);
1.1 misho 891: smart_str_0(buf);
892: }
893: /* }}} */
894:
895: /* {{{ proto string serialize(mixed variable)
896: Returns a string representation of variable (which can later be unserialized) */
897: PHP_FUNCTION(serialize)
898: {
899: zval **struc;
900: php_serialize_data_t var_hash;
901: smart_str buf = {0};
902:
903: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &struc) == FAILURE) {
904: return;
905: }
906:
907: Z_TYPE_P(return_value) = IS_STRING;
908: Z_STRVAL_P(return_value) = NULL;
909: Z_STRLEN_P(return_value) = 0;
910:
911: PHP_VAR_SERIALIZE_INIT(var_hash);
912: php_var_serialize(&buf, struc, &var_hash TSRMLS_CC);
913: PHP_VAR_SERIALIZE_DESTROY(var_hash);
914:
915: if (buf.c) {
916: RETURN_STRINGL(buf.c, buf.len, 0);
917: } else {
918: RETURN_NULL();
919: }
920: }
921: /* }}} */
922:
923: /* {{{ proto mixed unserialize(string variable_representation)
924: Takes a string representation of variable and recreates it */
925: PHP_FUNCTION(unserialize)
926: {
927: char *buf = NULL;
928: int buf_len;
929: const unsigned char *p;
930: php_unserialize_data_t var_hash;
931:
932: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
933: RETURN_FALSE;
934: }
935:
936: if (buf_len == 0) {
937: RETURN_FALSE;
938: }
939:
940: p = (const unsigned char*) buf;
941: PHP_VAR_UNSERIALIZE_INIT(var_hash);
942: if (!php_var_unserialize(&return_value, &p, p + buf_len, &var_hash TSRMLS_CC)) {
943: PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
944: zval_dtor(return_value);
945: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len);
946: RETURN_FALSE;
947: }
948: PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
949: }
950: /* }}} */
951:
952: /* {{{ proto int memory_get_usage([real_usage])
953: Returns the allocated by PHP memory */
954: PHP_FUNCTION(memory_get_usage) {
955: zend_bool real_usage = 0;
956:
957: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &real_usage) == FAILURE) {
958: RETURN_FALSE;
959: }
960:
961: RETURN_LONG(zend_memory_usage(real_usage TSRMLS_CC));
962: }
963: /* }}} */
964:
965: /* {{{ proto int memory_get_peak_usage([real_usage])
966: Returns the peak allocated by PHP memory */
967: PHP_FUNCTION(memory_get_peak_usage) {
968: zend_bool real_usage = 0;
969:
970: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &real_usage) == FAILURE) {
971: RETURN_FALSE;
972: }
973:
974: RETURN_LONG(zend_memory_peak_usage(real_usage TSRMLS_CC));
975: }
976: /* }}} */
977:
978: /*
979: * Local variables:
980: * tab-width: 4
981: * c-basic-offset: 4
982: * End:
983: * vim600: sw=4 ts=4 fdm=marker
984: * vim<600: sw=4 ts=4
985: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>