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