1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2007 Zend Technologies Ltd. (http://www.zend.com) |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt. |
11 : | If you did not receive a copy of the Zend license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@zend.com so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Andi Gutmans <andi@zend.com> |
16 : | Zeev Suraski <zeev@zend.com> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: zend_builtin_functions.c,v 1.277.2.12.2.16 2007/02/24 02:17:23 helly Exp $ */
21 :
22 : #include "zend.h"
23 : #include "zend_API.h"
24 : #include "zend_builtin_functions.h"
25 : #include "zend_constants.h"
26 : #include "zend_ini.h"
27 : #include "zend_exceptions.h"
28 :
29 : #undef ZEND_TEST_EXCEPTIONS
30 :
31 : static ZEND_FUNCTION(zend_version);
32 : static ZEND_FUNCTION(func_num_args);
33 : static ZEND_FUNCTION(func_get_arg);
34 : static ZEND_FUNCTION(func_get_args);
35 : static ZEND_NAMED_FUNCTION(zend_if_strlen);
36 : static ZEND_FUNCTION(strcmp);
37 : static ZEND_FUNCTION(strncmp);
38 : static ZEND_FUNCTION(strcasecmp);
39 : static ZEND_FUNCTION(strncasecmp);
40 : static ZEND_FUNCTION(each);
41 : static ZEND_FUNCTION(error_reporting);
42 : static ZEND_FUNCTION(define);
43 : static ZEND_FUNCTION(defined);
44 : static ZEND_FUNCTION(get_class);
45 : static ZEND_FUNCTION(get_parent_class);
46 : static ZEND_FUNCTION(method_exists);
47 : static ZEND_FUNCTION(property_exists);
48 : static ZEND_FUNCTION(class_exists);
49 : static ZEND_FUNCTION(interface_exists);
50 : static ZEND_FUNCTION(function_exists);
51 : #if ZEND_DEBUG
52 : static ZEND_FUNCTION(leak);
53 : #ifdef ZEND_TEST_EXCEPTIONS
54 : static ZEND_FUNCTION(crash);
55 : #endif
56 : #endif
57 : static ZEND_FUNCTION(get_included_files);
58 : static ZEND_FUNCTION(is_subclass_of);
59 : static ZEND_FUNCTION(is_a);
60 : static ZEND_FUNCTION(get_class_vars);
61 : static ZEND_FUNCTION(get_object_vars);
62 : static ZEND_FUNCTION(get_class_methods);
63 : static ZEND_FUNCTION(trigger_error);
64 : static ZEND_FUNCTION(set_error_handler);
65 : static ZEND_FUNCTION(restore_error_handler);
66 : static ZEND_FUNCTION(set_exception_handler);
67 : static ZEND_FUNCTION(restore_exception_handler);
68 : static ZEND_FUNCTION(get_declared_classes);
69 : static ZEND_FUNCTION(get_declared_interfaces);
70 : static ZEND_FUNCTION(get_defined_functions);
71 : static ZEND_FUNCTION(get_defined_vars);
72 : static ZEND_FUNCTION(create_function);
73 : static ZEND_FUNCTION(get_resource_type);
74 : static ZEND_FUNCTION(get_loaded_extensions);
75 : static ZEND_FUNCTION(extension_loaded);
76 : static ZEND_FUNCTION(get_extension_funcs);
77 : static ZEND_FUNCTION(get_defined_constants);
78 : static ZEND_FUNCTION(debug_backtrace);
79 : static ZEND_FUNCTION(debug_print_backtrace);
80 : #if ZEND_DEBUG
81 : static ZEND_FUNCTION(zend_test_func);
82 : #ifdef ZTS
83 : static ZEND_FUNCTION(zend_thread_id);
84 : #endif
85 : #endif
86 :
87 : #include "zend_arg_defs.c"
88 :
89 :
90 : static zend_function_entry builtin_functions[] = {
91 : ZEND_FE(zend_version, NULL)
92 : ZEND_FE(func_num_args, NULL)
93 : ZEND_FE(func_get_arg, NULL)
94 : ZEND_FE(func_get_args, NULL)
95 : { "strlen", zend_if_strlen, NULL },
96 : ZEND_FE(strcmp, NULL)
97 : ZEND_FE(strncmp, NULL)
98 : ZEND_FE(strcasecmp, NULL)
99 : ZEND_FE(strncasecmp, NULL)
100 : ZEND_FE(each, first_arg_force_ref)
101 : ZEND_FE(error_reporting, NULL)
102 : ZEND_FE(define, NULL)
103 : ZEND_FE(defined, NULL)
104 : ZEND_FE(get_class, NULL)
105 : ZEND_FE(get_parent_class, NULL)
106 : ZEND_FE(method_exists, NULL)
107 : ZEND_FE(property_exists, NULL)
108 : ZEND_FE(class_exists, NULL)
109 : ZEND_FE(interface_exists, NULL)
110 : ZEND_FE(function_exists, NULL)
111 : #if ZEND_DEBUG
112 : ZEND_FE(leak, NULL)
113 : #ifdef ZEND_TEST_EXCEPTIONS
114 : ZEND_FE(crash, NULL)
115 : #endif
116 : #endif
117 : ZEND_FE(get_included_files, NULL)
118 : ZEND_FALIAS(get_required_files, get_included_files, NULL)
119 : ZEND_FE(is_subclass_of, NULL)
120 : ZEND_FE(is_a, NULL)
121 : ZEND_FE(get_class_vars, NULL)
122 : ZEND_FE(get_object_vars, NULL)
123 : ZEND_FE(get_class_methods, NULL)
124 : ZEND_FE(trigger_error, NULL)
125 : ZEND_FALIAS(user_error, trigger_error, NULL)
126 : ZEND_FE(set_error_handler, NULL)
127 : ZEND_FE(restore_error_handler, NULL)
128 : ZEND_FE(set_exception_handler, NULL)
129 : ZEND_FE(restore_exception_handler, NULL)
130 : ZEND_FE(get_declared_classes, NULL)
131 : ZEND_FE(get_declared_interfaces, NULL)
132 : ZEND_FE(get_defined_functions, NULL)
133 : ZEND_FE(get_defined_vars, NULL)
134 : ZEND_FE(create_function, NULL)
135 : ZEND_FE(get_resource_type, NULL)
136 : ZEND_FE(get_loaded_extensions, NULL)
137 : ZEND_FE(extension_loaded, NULL)
138 : ZEND_FE(get_extension_funcs, NULL)
139 : ZEND_FE(get_defined_constants, NULL)
140 : ZEND_FE(debug_backtrace, NULL)
141 : ZEND_FE(debug_print_backtrace, NULL)
142 : #if ZEND_DEBUG
143 : ZEND_FE(zend_test_func, NULL)
144 : #ifdef ZTS
145 : ZEND_FE(zend_thread_id, NULL)
146 : #endif
147 : #endif
148 : { NULL, NULL, NULL }
149 : };
150 :
151 :
152 : int zend_startup_builtin_functions(TSRMLS_D)
153 220 : {
154 220 : return zend_register_functions(NULL, builtin_functions, NULL, MODULE_PERSISTENT TSRMLS_CC);
155 : }
156 :
157 :
158 : /* {{{ proto string zend_version(void)
159 : Get the version of the Zend Engine */
160 : ZEND_FUNCTION(zend_version)
161 1 : {
162 1 : RETURN_STRINGL(ZEND_VERSION, sizeof(ZEND_VERSION)-1, 1);
163 : }
164 : /* }}} */
165 :
166 :
167 : /* {{{ proto int func_num_args(void)
168 : Get the number of arguments that were passed to the function */
169 : ZEND_FUNCTION(func_num_args)
170 0 : {
171 : void **p;
172 : int arg_count;
173 :
174 0 : p = EG(argument_stack).top_element-1-1;
175 0 : arg_count = (ulong) *p; /* this is the amount of arguments passed to func_num_args(); */
176 0 : p -= 1+arg_count;
177 0 : if (*p) {
178 0 : zend_error(E_ERROR, "func_num_args(): Can't be used as a function parameter");
179 : }
180 0 : --p;
181 0 : if (p>=EG(argument_stack).elements) {
182 0 : RETURN_LONG((ulong) *p);
183 : } else {
184 0 : zend_error(E_WARNING, "func_num_args(): Called from the global scope - no function context");
185 0 : RETURN_LONG(-1);
186 : }
187 : }
188 : /* }}} */
189 :
190 :
191 : /* {{{ proto mixed func_get_arg(int arg_num)
192 : Get the $arg_num'th argument that was passed to the function */
193 : ZEND_FUNCTION(func_get_arg)
194 0 : {
195 : void **p;
196 : int arg_count;
197 : zval **z_requested_offset;
198 : zval *arg;
199 : long requested_offset;
200 :
201 0 : if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &z_requested_offset)==FAILURE) {
202 0 : RETURN_FALSE;
203 : }
204 0 : convert_to_long_ex(z_requested_offset);
205 0 : requested_offset = Z_LVAL_PP(z_requested_offset);
206 :
207 0 : if (requested_offset < 0) {
208 0 : zend_error(E_WARNING, "func_get_arg(): The argument number should be >= 0");
209 0 : RETURN_FALSE;
210 : }
211 :
212 0 : p = EG(argument_stack).top_element-1-1;
213 0 : arg_count = (ulong) *p; /* this is the amount of arguments passed to func_get_arg(); */
214 0 : p -= 1+arg_count;
215 0 : if (*p) {
216 0 : zend_error(E_ERROR, "func_get_arg(): Can't be used as a function parameter");
217 : }
218 0 : --p;
219 0 : if (p<EG(argument_stack).elements) {
220 0 : zend_error(E_WARNING, "func_get_arg(): Called from the global scope - no function context");
221 0 : RETURN_FALSE;
222 : }
223 0 : arg_count = (ulong) *p;
224 :
225 0 : if (requested_offset>=arg_count) {
226 0 : zend_error(E_WARNING, "func_get_arg(): Argument %ld not passed to function", requested_offset);
227 0 : RETURN_FALSE;
228 : }
229 :
230 0 : arg = *(p-(arg_count-requested_offset));
231 0 : *return_value = *arg;
232 0 : zval_copy_ctor(return_value);
233 0 : INIT_PZVAL(return_value);
234 : }
235 : /* }}} */
236 :
237 :
238 : /* {{{ proto array func_get_args()
239 : Get an array of the arguments that were passed to the function */
240 : ZEND_FUNCTION(func_get_args)
241 0 : {
242 : void **p;
243 : int arg_count;
244 : int i;
245 :
246 0 : p = EG(argument_stack).top_element-1-1;
247 0 : arg_count = (ulong) *p; /* this is the amount of arguments passed to func_get_args(); */
248 0 : p -= 1+arg_count;
249 0 : if (*p) {
250 0 : zend_error(E_ERROR, "func_get_args(): Can't be used as a function parameter");
251 : }
252 0 : --p;
253 :
254 0 : if (p<EG(argument_stack).elements) {
255 0 : zend_error(E_WARNING, "func_get_args(): Called from the global scope - no function context");
256 0 : RETURN_FALSE;
257 : }
258 0 : arg_count = (ulong) *p;
259 :
260 :
261 0 : array_init(return_value);
262 0 : for (i=0; i<arg_count; i++) {
263 : zval *element;
264 :
265 0 : ALLOC_ZVAL(element);
266 0 : *element = **((zval **) (p-(arg_count-i)));
267 0 : zval_copy_ctor(element);
268 0 : INIT_PZVAL(element);
269 0 : zend_hash_next_index_insert(return_value->value.ht, &element, sizeof(zval *), NULL);
270 : }
271 : }
272 : /* }}} */
273 :
274 :
275 : /* {{{ proto int strlen(string str)
276 : Get string length */
277 : ZEND_NAMED_FUNCTION(zend_if_strlen)
278 1914 : {
279 : zval **str;
280 :
281 1914 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) {
282 0 : ZEND_WRONG_PARAM_COUNT();
283 : }
284 1914 : convert_to_string_ex(str);
285 1914 : RETVAL_LONG(Z_STRLEN_PP(str));
286 : }
287 : /* }}} */
288 :
289 :
290 : /* {{{ proto int strcmp(string str1, string str2)
291 : Binary safe string comparison */
292 : ZEND_FUNCTION(strcmp)
293 758 : {
294 : zval **s1, **s2;
295 :
296 758 : if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &s1, &s2) == FAILURE) {
297 0 : ZEND_WRONG_PARAM_COUNT();
298 : }
299 758 : convert_to_string_ex(s1);
300 758 : convert_to_string_ex(s2);
301 758 : RETURN_LONG(zend_binary_zval_strcmp(*s1, *s2));
302 : }
303 : /* }}} */
304 :
305 :
306 : /* {{{ proto int strncmp(string str1, string str2, int len)
307 : Binary safe string comparison */
308 : ZEND_FUNCTION(strncmp)
309 110 : {
310 : zval **s1, **s2, **s3;
311 :
312 110 : if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &s1, &s2, &s3) == FAILURE) {
313 0 : ZEND_WRONG_PARAM_COUNT();
314 : }
315 110 : convert_to_string_ex(s1);
316 110 : convert_to_string_ex(s2);
317 110 : convert_to_long_ex(s3);
318 :
319 110 : if (Z_LVAL_PP(s3) < 0) {
320 0 : zend_error(E_WARNING, "Length must be greater than or equal to 0");
321 0 : RETURN_FALSE;
322 : }
323 :
324 110 : RETURN_LONG(zend_binary_zval_strncmp(*s1, *s2, *s3));
325 : }
326 : /* }}} */
327 :
328 :
329 : /* {{{ proto int strcasecmp(string str1, string str2)
330 : Binary safe case-insensitive string comparison */
331 : ZEND_FUNCTION(strcasecmp)
332 0 : {
333 : zval **s1, **s2;
334 :
335 0 : if (ZEND_NUM_ARGS()!=2 || zend_get_parameters_ex(2, &s1, &s2) == FAILURE) {
336 0 : ZEND_WRONG_PARAM_COUNT();
337 : }
338 0 : convert_to_string_ex(s1);
339 0 : convert_to_string_ex(s2);
340 0 : RETURN_LONG(zend_binary_zval_strcasecmp(*s1, *s2));
341 : }
342 : /* }}} */
343 :
344 :
345 : /* {{{ proto int strncasecmp(string str1, string str2, int len)
346 : Binary safe string comparison */
347 : ZEND_FUNCTION(strncasecmp)
348 368 : {
349 : zval **s1, **s2, **s3;
350 :
351 368 : if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &s1, &s2, &s3) == FAILURE) {
352 0 : ZEND_WRONG_PARAM_COUNT();
353 : }
354 368 : convert_to_string_ex(s1);
355 368 : convert_to_string_ex(s2);
356 368 : convert_to_long_ex(s3);
357 :
358 368 : if (Z_LVAL_PP(s3) < 0) {
359 0 : zend_error(E_WARNING, "Length must be greater than or equal to 0");
360 0 : RETURN_FALSE;
361 : }
362 :
363 368 : RETURN_LONG(zend_binary_zval_strncasecmp(*s1, *s2, *s3));
364 : }
365 : /* }}} */
366 :
367 :
368 : /* {{{ proto array each(array arr)
369 : Return the currently pointed key..value pair in the passed array, and advance the pointer to the next element */
370 : ZEND_FUNCTION(each)
371 56 : {
372 : zval **array, *entry, **entry_ptr, *tmp;
373 : char *string_key;
374 : uint string_key_len;
375 : ulong num_key;
376 : zval **inserted_pointer;
377 : HashTable *target_hash;
378 :
379 56 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &array) == FAILURE) {
380 0 : ZEND_WRONG_PARAM_COUNT();
381 : }
382 :
383 56 : target_hash = HASH_OF(*array);
384 56 : if (!target_hash) {
385 0 : zend_error(E_WARNING,"Variable passed to each() is not an array or object");
386 0 : return;
387 : }
388 56 : if (zend_hash_get_current_data(target_hash, (void **) &entry_ptr)==FAILURE) {
389 11 : RETURN_FALSE;
390 : }
391 45 : array_init(return_value);
392 45 : entry = *entry_ptr;
393 :
394 : /* add value elements */
395 45 : if (entry->is_ref) {
396 0 : ALLOC_ZVAL(tmp);
397 0 : *tmp = *entry;
398 0 : zval_copy_ctor(tmp);
399 0 : tmp->is_ref=0;
400 0 : tmp->refcount=0;
401 0 : entry=tmp;
402 : }
403 45 : zend_hash_index_update(return_value->value.ht, 1, &entry, sizeof(zval *), NULL);
404 45 : entry->refcount++;
405 45 : zend_hash_update(return_value->value.ht, "value", sizeof("value"), &entry, sizeof(zval *), NULL);
406 45 : entry->refcount++;
407 :
408 : /* add the key elements */
409 45 : switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_key_len, &num_key, 1, NULL)) {
410 : case HASH_KEY_IS_STRING:
411 45 : add_get_index_stringl(return_value, 0, string_key, string_key_len-1, (void **) &inserted_pointer, 0);
412 45 : break;
413 : case HASH_KEY_IS_LONG:
414 0 : add_get_index_long(return_value, 0, num_key, (void **) &inserted_pointer);
415 : break;
416 : }
417 45 : zend_hash_update(return_value->value.ht, "key", sizeof("key"), inserted_pointer, sizeof(zval *), NULL);
418 45 : (*inserted_pointer)->refcount++;
419 45 : zend_hash_move_forward(target_hash);
420 : }
421 : /* }}} */
422 :
423 :
424 : /* {{{ proto int error_reporting(int new_error_level=null)
425 : Return the current error_reporting level, and if an argument was passed - change to the new level */
426 : ZEND_FUNCTION(error_reporting)
427 4 : {
428 : zval **arg;
429 : int old_error_reporting;
430 :
431 4 : old_error_reporting = EG(error_reporting);
432 4 : switch (ZEND_NUM_ARGS()) {
433 : case 0:
434 0 : break;
435 : case 1:
436 4 : if (zend_get_parameters_ex(1, &arg) == FAILURE) {
437 0 : RETURN_FALSE;
438 : }
439 4 : convert_to_string_ex(arg);
440 4 : zend_alter_ini_entry("error_reporting", sizeof("error_reporting"), Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
441 4 : break;
442 : default:
443 0 : ZEND_WRONG_PARAM_COUNT();
444 : break;
445 : }
446 :
447 4 : RETVAL_LONG(old_error_reporting);
448 : }
449 : /* }}} */
450 :
451 :
452 : /* {{{ proto bool define(string constant_name, mixed value, boolean case_sensitive=true)
453 : Define a new constant */
454 : ZEND_FUNCTION(define)
455 146 : {
456 146 : zval **var, **val, **non_cs, *val_free = NULL;
457 : int case_sensitive;
458 : zend_constant c;
459 :
460 146 : switch (ZEND_NUM_ARGS()) {
461 : case 2:
462 146 : if (zend_get_parameters_ex(2, &var, &val)==FAILURE) {
463 0 : RETURN_FALSE;
464 : }
465 146 : case_sensitive = CONST_CS;
466 146 : break;
467 : case 3:
468 0 : if (zend_get_parameters_ex(3, &var, &val, &non_cs)==FAILURE) {
469 0 : RETURN_FALSE;
470 : }
471 0 : convert_to_long_ex(non_cs);
472 0 : if (Z_LVAL_PP(non_cs)) {
473 0 : case_sensitive = 0;
474 : } else {
475 0 : case_sensitive = CONST_CS;
476 : }
477 0 : break;
478 : default:
479 0 : ZEND_WRONG_PARAM_COUNT();
480 : break;
481 : }
482 :
483 146 : repeat:
484 146 : switch (Z_TYPE_PP(val)) {
485 : case IS_LONG:
486 : case IS_DOUBLE:
487 : case IS_STRING:
488 : case IS_BOOL:
489 : case IS_RESOURCE:
490 : case IS_NULL:
491 146 : break;
492 : case IS_OBJECT:
493 0 : if (!val_free) {
494 0 : if (Z_OBJ_HT_PP(val)->get) {
495 0 : val_free = *val = Z_OBJ_HT_PP(val)->get(*val TSRMLS_CC);
496 0 : goto repeat;
497 0 : } else if (Z_OBJ_HT_PP(val)->cast_object) {
498 0 : ALLOC_INIT_ZVAL(val_free);
499 0 : if (Z_OBJ_HT_PP(val)->cast_object(*val, val_free, IS_STRING TSRMLS_CC) == SUCCESS) {
500 0 : val = &val_free;
501 0 : break;
502 : }
503 : }
504 : }
505 : /* no break */
506 : default:
507 0 : zend_error(E_WARNING,"Constants may only evaluate to scalar values");
508 0 : if (val_free) {
509 0 : zval_ptr_dtor(&val_free);
510 : }
511 0 : RETURN_FALSE;
512 : }
513 146 : convert_to_string_ex(var);
514 :
515 146 : c.value = **val;
516 146 : zval_copy_ctor(&c.value);
517 146 : if (val_free) {
518 0 : zval_ptr_dtor(&val_free);
519 : }
520 146 : c.flags = case_sensitive; /* non persistent */
521 146 : c.name = zend_strndup(Z_STRVAL_PP(var), Z_STRLEN_PP(var));
522 146 : c.name_len = Z_STRLEN_PP(var)+1;
523 146 : c.module_number = PHP_USER_CONSTANT;
524 146 : if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {
525 146 : RETURN_TRUE;
526 : } else {
527 0 : RETURN_FALSE;
528 : }
529 : }
530 : /* }}} */
531 :
532 :
533 : /* {{{ proto bool defined(string constant_name)
534 : Check whether a constant exists */
535 : ZEND_FUNCTION(defined)
536 108 : {
537 : zval **var;
538 : zval c;
539 :
540 108 : if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &var)==FAILURE) {
541 0 : ZEND_WRONG_PARAM_COUNT();
542 : }
543 :
544 108 : convert_to_string_ex(var);
545 108 : if (zend_get_constant(Z_STRVAL_PP(var), Z_STRLEN_PP(var), &c TSRMLS_CC)) {
546 0 : zval_dtor(&c);
547 0 : RETURN_TRUE;
548 : } else {
549 108 : RETURN_FALSE;
550 : }
551 : }
552 : /* }}} */
553 :
554 :
555 : /* {{{ proto string get_class([object object])
556 : Retrieves the class name */
557 : ZEND_FUNCTION(get_class)
558 20 : {
559 : zval **arg;
560 20 : char *name = "";
561 20 : zend_uint name_len = 0;
562 : int dup;
563 :
564 20 : if (!ZEND_NUM_ARGS()) {
565 0 : if (EG(scope)) {
566 0 : RETURN_STRINGL(EG(scope)->name, EG(scope)->name_length, 1);
567 : } else {
568 0 : zend_error(E_WARNING, "get_class() called without object from outside a class");
569 0 : RETURN_FALSE;
570 : }
571 : }
572 20 : if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &arg)==FAILURE) {
573 0 : ZEND_WRONG_PARAM_COUNT();
574 : }
575 20 : if (Z_TYPE_PP(arg) != IS_OBJECT) {
576 0 : RETURN_FALSE;
577 : }
578 :
579 20 : dup = zend_get_object_classname(*arg, &name, &name_len TSRMLS_CC);
580 :
581 20 : RETURN_STRINGL(name, name_len, dup);
582 : }
583 : /* }}} */
584 :
585 :
586 : /* {{{ proto string get_parent_class([mixed object])
587 : Retrieves the parent class name for object or class or current scope. */
588 : ZEND_FUNCTION(get_parent_class)
589 0 : {
590 : zval **arg;
591 0 : zend_class_entry *ce = NULL;
592 : char *name;
593 : zend_uint name_length;
594 :
595 0 : if (!ZEND_NUM_ARGS()) {
596 0 : ce = EG(scope);
597 0 : if (ce && ce->parent) {
598 0 : RETURN_STRINGL(ce->parent->name, ce->parent->name_length, 1);
599 : } else {
600 0 : RETURN_FALSE;
601 : }
602 : }
603 0 : if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &arg)==FAILURE) {
604 0 : ZEND_WRONG_PARAM_COUNT();
605 : }
606 :
607 0 : if (Z_TYPE_PP(arg) == IS_OBJECT) {
608 0 : if (Z_OBJ_HT_PP(arg)->get_class_name
609 : && Z_OBJ_HT_PP(arg)->get_class_name(*arg, &name, &name_length, 1 TSRMLS_CC) == SUCCESS) {
610 0 : RETURN_STRINGL(name, name_length, 0);
611 : } else {
612 0 : ce = zend_get_class_entry(*arg TSRMLS_CC);
613 : }
614 0 : } else if (Z_TYPE_PP(arg) == IS_STRING) {
615 : zend_class_entry **pce;
616 :
617 0 : if (zend_lookup_class(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &pce TSRMLS_CC) == SUCCESS) {
618 0 : ce = *pce;
619 : }
620 : }
621 :
622 0 : if (ce && ce->parent) {
623 0 : RETURN_STRINGL(ce->parent->name, ce->parent->name_length, 1);
624 : } else {
625 0 : RETURN_FALSE;
626 : }
627 : }
628 : /* }}} */
629 :
630 :
631 : static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass)
632 0 : {
633 : zval **obj, **class_name;
634 : zend_class_entry *instance_ce;
635 : zend_class_entry **ce;
636 : zend_bool retval;
637 :
638 0 : if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &obj, &class_name)==FAILURE) {
639 0 : ZEND_WRONG_PARAM_COUNT();
640 : }
641 :
642 0 : if (only_subclass && Z_TYPE_PP(obj) == IS_STRING) {
643 : zend_class_entry **the_ce;
644 0 : if (zend_lookup_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), &the_ce TSRMLS_CC) == FAILURE) {
645 0 : zend_error(E_WARNING, "Unknown class passed as parameter");
646 0 : RETURN_FALSE;
647 : }
648 0 : instance_ce = *the_ce;
649 0 : } else if (Z_TYPE_PP(obj) != IS_OBJECT) {
650 0 : RETURN_FALSE;
651 : } else {
652 0 : instance_ce = NULL;
653 : }
654 :
655 : /* TBI!! new object handlers */
656 0 : if (Z_TYPE_PP(obj) == IS_OBJECT && !HAS_CLASS_ENTRY(**obj)) {
657 0 : RETURN_FALSE;
658 : }
659 :
660 0 : convert_to_string_ex(class_name);
661 :
662 0 : if (zend_lookup_class_ex(Z_STRVAL_PP(class_name), Z_STRLEN_PP(class_name), (instance_ce != NULL), &ce TSRMLS_CC) == FAILURE) {
663 0 : retval = 0;
664 : } else {
665 0 : if (only_subclass) {
666 0 : if (!instance_ce) {
667 0 : instance_ce = Z_OBJCE_PP(obj)->parent;
668 : } else {
669 0 : instance_ce = instance_ce->parent;
670 : }
671 : } else {
672 0 : instance_ce = Z_OBJCE_PP(obj);
673 : }
674 :
675 0 : if (!instance_ce) {
676 0 : RETURN_FALSE;
677 : }
678 :
679 0 : if (instanceof_function(instance_ce, *ce TSRMLS_CC)) {
680 0 : retval = 1;
681 : } else {
682 0 : retval = 0;
683 : }
684 : }
685 :
686 0 : RETURN_BOOL(retval);
687 : }
688 :
689 :
690 : /* {{{ proto bool is_subclass_of(object object, string class_name)
691 : Returns true if the object has this class as one of its parents */
692 : ZEND_FUNCTION(is_subclass_of)
693 0 : {
694 0 : is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
695 0 : }
696 : /* }}} */
697 :
698 :
699 : /* {{{ proto bool is_a(object object, string class_name)
700 : Returns true if the object is of this class or has this class as one of its parents */
701 : ZEND_FUNCTION(is_a)
702 0 : {
703 0 : zend_error(E_STRICT, "is_a(): Deprecated. Please use the instanceof operator");
704 0 : is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
705 0 : }
706 : /* }}} */
707 :
708 :
709 : /* {{{ add_class_vars */
710 : static void add_class_vars(zend_class_entry *ce, HashTable *properties, zval *return_value TSRMLS_DC)
711 0 : {
712 0 : int instanceof = EG(scope) && instanceof_function(EG(scope), ce TSRMLS_CC);
713 :
714 0 : if (zend_hash_num_elements(properties) > 0) {
715 : HashPosition pos;
716 : zval **prop;
717 :
718 0 : zend_hash_internal_pointer_reset_ex(properties, &pos);
719 0 : while (zend_hash_get_current_data_ex(properties, (void **) &prop, &pos) == SUCCESS) {
720 : char *key, *class_name, *prop_name;
721 : uint key_len;
722 : ulong num_index;
723 : zval *prop_copy;
724 :
725 0 : zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos);
726 0 : zend_hash_move_forward_ex(properties, &pos);
727 0 : zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
728 0 : if (class_name) {
729 0 : if (class_name[0] != '*' && strcmp(class_name, ce->name)) {
730 : /* filter privates from base classes */
731 : continue;
732 0 : } else if (!instanceof) {
733 : /* filter protected if not inside class */
734 0 : continue;
735 : }
736 : }
737 :
738 : /* copy: enforce read only access */
739 0 : ALLOC_ZVAL(prop_copy);
740 0 : *prop_copy = **prop;
741 0 : zval_copy_ctor(prop_copy);
742 0 : INIT_PZVAL(prop_copy);
743 :
744 : /* this is necessary to make it able to work with default array
745 : * properties, returned to user */
746 0 : if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || Z_TYPE_P(prop_copy) == IS_CONSTANT) {
747 0 : zval_update_constant(&prop_copy, 0 TSRMLS_CC);
748 : }
749 :
750 0 : add_assoc_zval(return_value, prop_name, prop_copy);
751 : }
752 : }
753 0 : }
754 : /* }}} */
755 :
756 :
757 : /* {{{ proto array get_class_vars(string class_name)
758 : Returns an array of default properties of the class. */
759 : ZEND_FUNCTION(get_class_vars)
760 0 : {
761 : char *class_name;
762 : int class_name_len;
763 : zend_class_entry **pce;
764 :
765 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &class_name, &class_name_len) == FAILURE) {
766 0 : return;
767 : }
768 :
769 0 : if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC) == FAILURE) {
770 0 : RETURN_FALSE;
771 : } else {
772 0 : array_init(return_value);
773 0 : add_class_vars(*pce, &(*pce)->default_properties, return_value TSRMLS_CC);
774 0 : zend_update_class_constants(*pce TSRMLS_CC);
775 0 : add_class_vars(*pce, CE_STATIC_MEMBERS(*pce), return_value TSRMLS_CC);
776 : }
777 : }
778 : /* }}} */
779 :
780 :
781 : /* {{{ proto array get_object_vars(object obj)
782 : Returns an array of object properties */
783 : ZEND_FUNCTION(get_object_vars)
784 0 : {
785 : zval **obj;
786 : zval **value;
787 : HashTable *properties;
788 : HashPosition pos;
789 : char *key, *prop_name, *class_name;
790 : uint key_len;
791 : ulong num_index;
792 : int instanceof;
793 :
794 0 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &obj) == FAILURE) {
795 0 : ZEND_WRONG_PARAM_COUNT();
796 : }
797 :
798 0 : if (Z_TYPE_PP(obj) != IS_OBJECT) {
799 0 : RETURN_FALSE;
800 : }
801 0 : if (Z_OBJ_HT_PP(obj)->get_properties == NULL) {
802 0 : RETURN_FALSE;
803 : }
804 :
805 0 : properties = Z_OBJ_HT_PP(obj)->get_properties(*obj TSRMLS_CC);
806 :
807 0 : if (properties == NULL) {
808 0 : RETURN_FALSE;
809 : }
810 :
811 0 : instanceof = EG(This) && instanceof_function(Z_OBJCE_P(EG(This)), Z_OBJCE_PP(obj) TSRMLS_CC);
812 :
813 0 : array_init(return_value);
814 :
815 0 : zend_hash_internal_pointer_reset_ex(properties, &pos);
816 :
817 0 : while (zend_hash_get_current_data_ex(properties, (void **) &value, &pos) == SUCCESS) {
818 0 : if (zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos) == HASH_KEY_IS_STRING) {
819 0 : if (key[0]) {
820 : /* Not separating references */
821 0 : (*value)->refcount++;
822 0 : add_assoc_zval_ex(return_value, key, key_len, *value);
823 0 : } else if (instanceof) {
824 0 : zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
825 0 : if (!memcmp(class_name, "*", 2) || (Z_OBJCE_P(EG(This)) == Z_OBJCE_PP(obj) && !strcmp(Z_OBJCE_P(EG(This))->name, class_name))) {
826 : /* Not separating references */
827 0 : (*value)->refcount++;
828 0 : add_assoc_zval_ex(return_value, prop_name, strlen(prop_name)+1, *value);
829 : }
830 : }
831 : }
832 0 : zend_hash_move_forward_ex(properties, &pos);
833 : }
834 : }
835 : /* }}} */
836 :
837 :
838 : /* {{{ proto array get_class_methods(mixed class)
839 : Returns an array of method names for class or class instance. */
840 : ZEND_FUNCTION(get_class_methods)
841 1 : {
842 : zval **class;
843 : zval *method_name;
844 1 : zend_class_entry *ce = NULL, **pce;
845 : HashPosition pos;
846 : zend_function *mptr;
847 :
848 1 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &class)==FAILURE) {
849 0 : ZEND_WRONG_PARAM_COUNT();
850 : }
851 :
852 1 : if (Z_TYPE_PP(class) == IS_OBJECT) {
853 : /* TBI!! new object handlers */
854 0 : if (!HAS_CLASS_ENTRY(**class)) {
855 0 : RETURN_FALSE;
856 : }
857 0 : ce = Z_OBJCE_PP(class);
858 1 : } else if (Z_TYPE_PP(class) == IS_STRING) {
859 1 : if (zend_lookup_class(Z_STRVAL_PP(class), Z_STRLEN_PP(class), &pce TSRMLS_CC) == SUCCESS) {
860 1 : ce = *pce;
861 : }
862 : }
863 :
864 1 : if (!ce) {
865 0 : RETURN_NULL();
866 : }
867 :
868 1 : array_init(return_value);
869 1 : zend_hash_internal_pointer_reset_ex(&ce->function_table, &pos);
870 :
871 68 : while (zend_hash_get_current_data_ex(&ce->function_table, (void **) &mptr, &pos) == SUCCESS) {
872 66 : if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC)
873 : || (EG(scope) &&
874 : (((mptr->common.fn_flags & ZEND_ACC_PROTECTED) &&
875 : instanceof_function(EG(scope), mptr->common.scope TSRMLS_CC))
876 : || ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) &&
877 : EG(scope) == mptr->common.scope)))) {
878 : char *key;
879 : uint key_len;
880 : ulong num_index;
881 66 : uint len = strlen(mptr->common.function_name);
882 :
883 : /* Do not display old-style inherited constructors */
884 66 : if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0 ||
885 : mptr->common.scope == ce ||
886 : zend_hash_get_current_key_ex(&ce->function_table, &key, &key_len, &num_index, 0, &pos) != HASH_KEY_IS_STRING ||
887 : zend_binary_strcasecmp(key, key_len-1, mptr->common.function_name, len) == 0) {
888 :
889 66 : MAKE_STD_ZVAL(method_name);
890 66 : ZVAL_STRINGL(method_name, mptr->common.function_name, len, 1);
891 66 : zend_hash_next_index_insert(return_value->value.ht, &method_name, sizeof(zval *), NULL);
892 : }
893 : }
894 66 : zend_hash_move_forward_ex(&ce->function_table, &pos);
895 : }
896 : }
897 : /* }}} */
898 :
899 :
900 : /* {{{ proto bool method_exists(object object, string method)
901 : Checks if the class method exists */
902 : ZEND_FUNCTION(method_exists)
903 0 : {
904 : zval **klass, **method_name;
905 : char *lcname;
906 : zend_class_entry * ce, **pce;
907 :
908 0 : if (ZEND_NUM_ARGS()!=2 || zend_get_parameters_ex(2, &klass, &method_name)==FAILURE) {
909 0 : ZEND_WRONG_PARAM_COUNT();
910 : }
911 0 : if (Z_TYPE_PP(klass) == IS_OBJECT) {
912 0 : ce = Z_OBJCE_PP(klass);
913 0 : } else if (Z_TYPE_PP(klass) == IS_STRING) {
914 0 : if (zend_lookup_class(Z_STRVAL_PP(klass), Z_STRLEN_PP(klass), &pce TSRMLS_CC) == FAILURE) {
915 0 : RETURN_FALSE;
916 : }
917 0 : ce = *pce;
918 : } else {
919 0 : RETURN_FALSE;
920 : }
921 :
922 0 : convert_to_string_ex(method_name);
923 0 : lcname = zend_str_tolower_dup(Z_STRVAL_PP(method_name), Z_STRLEN_PP(method_name));
924 0 : if (zend_hash_exists(&ce->function_table, lcname, Z_STRLEN_PP(method_name)+1)) {
925 0 : efree(lcname);
926 0 : RETURN_TRUE;
927 : } else {
928 0 : union _zend_function *func = NULL;
929 0 : efree(lcname);
930 :
931 0 : if (Z_TYPE_PP(klass) == IS_OBJECT
932 : && Z_OBJ_HT_PP(klass)->get_method != NULL
933 : && (func = Z_OBJ_HT_PP(klass)->get_method(klass, Z_STRVAL_PP(method_name), Z_STRLEN_PP(method_name) TSRMLS_CC)) != NULL
934 : ) {
935 0 : if (func->type == ZEND_INTERNAL_FUNCTION
936 : && ((zend_internal_function*)func)->handler == zend_std_call_user_call
937 : ) {
938 0 : efree(((zend_internal_function*)func)->function_name);
939 0 : efree(func);
940 0 : RETURN_FALSE;
941 : }
942 0 : RETURN_TRUE;
943 : }
944 : }
945 0 : RETURN_FALSE;
946 : }
947 : /* }}} */
948 :
949 : /* {{{ proto bool property_exists(mixed object_or_class, string property_name)
950 : Checks if the object or class has a property */
951 : ZEND_FUNCTION(property_exists)
952 0 : {
953 : zval **object, **property;
954 : zend_class_entry *ce, **pce;
955 : zend_property_info *property_info;
956 : char *prop_name, *class_name;
957 :
958 0 : if (ZEND_NUM_ARGS()!= 2 || zend_get_parameters_ex(2, &object, &property)==FAILURE) {
959 0 : ZEND_WRONG_PARAM_COUNT();
960 : }
961 0 : convert_to_string_ex(property);
962 0 : if (!Z_STRLEN_PP(property)) {
963 0 : RETURN_FALSE;
964 : }
965 :
966 0 : switch((*object)->type) {
967 : case IS_STRING:
968 0 : if (!Z_STRLEN_PP(object)) {
969 0 : RETURN_FALSE;
970 : }
971 0 : if (zend_lookup_class(Z_STRVAL_PP(object), Z_STRLEN_PP(object), &pce TSRMLS_CC) == SUCCESS) {
972 0 : ce = *pce;
973 : } else {
974 0 : RETURN_FALSE;
975 : }
976 0 : if (!ce) {
977 0 : RETURN_NULL();
978 : }
979 0 : if (!(property_info = zend_get_property_info(ce, *property, 1 TSRMLS_CC)) || property_info == &EG(std_property_info)) {
980 0 : RETURN_FALSE;
981 : }
982 0 : if (property_info->flags & ZEND_ACC_PUBLIC) {
983 0 : RETURN_TRUE;
984 : }
985 0 : zend_unmangle_property_name(property_info->name, property_info->name_length, &class_name, &prop_name);
986 0 : if (!strncmp(class_name, "*", 1)) {
987 0 : if (instanceof_function(EG(scope), ce TSRMLS_CC)) {
988 0 : RETURN_TRUE;
989 : }
990 0 : RETURN_FALSE;
991 : }
992 0 : if (zend_lookup_class(Z_STRVAL_PP(object), Z_STRLEN_PP(object), &pce TSRMLS_CC) == SUCCESS) {
993 0 : ce = *pce;
994 : } else {
995 0 : RETURN_FALSE; /* shouldn't happen */
996 : }
997 0 : RETURN_BOOL(EG(scope) == ce);
998 :
999 : case IS_OBJECT:
1000 0 : if (Z_OBJ_HANDLER_PP(object, has_property) && Z_OBJ_HANDLER_PP(object, has_property)(*object, *property, 2 TSRMLS_CC)) {
1001 0 : RETURN_TRUE;
1002 : }
1003 0 : RETURN_FALSE;
1004 :
1005 : default:
1006 0 : zend_error(E_WARNING, "First parameter must either be an object or the name of an existing class");
1007 0 : RETURN_NULL();
1008 : }
1009 : }
1010 : /* }}} */
1011 :
1012 :
1013 : /* {{{ proto bool class_exists(string classname [, bool autoload])
1014 : Checks if the class exists */
1015 : ZEND_FUNCTION(class_exists)
1016 20 : {
1017 : char *class_name, *lc_name;
1018 : zend_class_entry **ce;
1019 : int class_name_len;
1020 20 : zend_bool autoload = 1;
1021 : int found;
1022 :
1023 20 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &class_name, &class_name_len, &autoload) == FAILURE) {
1024 0 : return;
1025 : }
1026 :
1027 20 : if (!autoload) {
1028 0 : lc_name = do_alloca(class_name_len + 1);
1029 0 : zend_str_tolower_copy(lc_name, class_name, class_name_len);
1030 :
1031 0 : found = zend_hash_find(EG(class_table), lc_name, class_name_len+1, (void **) &ce);
1032 : free_alloca(lc_name);
1033 0 : RETURN_BOOL(found == SUCCESS && !((*ce)->ce_flags & ZEND_ACC_INTERFACE));
1034 : }
1035 :
1036 20 : if (zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC) == SUCCESS) {
1037 20 : RETURN_BOOL(((*ce)->ce_flags & ZEND_ACC_INTERFACE) == 0);
1038 : } else {
1039 0 : RETURN_FALSE;
1040 : }
1041 : }
1042 : /* }}} */
1043 :
1044 : /* {{{ proto bool interface_exists(string classname [, bool autoload])
1045 : Checks if the class exists */
1046 : ZEND_FUNCTION(interface_exists)
1047 0 : {
1048 : char *iface_name, *lc_name;
1049 : zend_class_entry **ce;
1050 : int iface_name_len;
1051 0 : zend_bool autoload = 1;
1052 : int found;
1053 :
1054 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &iface_name, &iface_name_len, &autoload) == FAILURE) {
1055 0 : return;
1056 : }
1057 :
1058 0 : if (!autoload) {
1059 0 : lc_name = do_alloca(iface_name_len + 1);
1060 0 : zend_str_tolower_copy(lc_name, iface_name, iface_name_len);
1061 :
1062 0 : found = zend_hash_find(EG(class_table), lc_name, iface_name_len+1, (void **) &ce);
1063 : free_alloca(lc_name);
1064 0 : RETURN_BOOL(found == SUCCESS && (*ce)->ce_flags & ZEND_ACC_INTERFACE);
1065 : }
1066 :
1067 0 : if (zend_lookup_class(iface_name, iface_name_len, &ce TSRMLS_CC) == SUCCESS) {
1068 0 : RETURN_BOOL(((*ce)->ce_flags & ZEND_ACC_INTERFACE) > 0);
1069 : } else {
1070 0 : RETURN_FALSE;
1071 : }
1072 : }
1073 : /* }}} */
1074 :
1075 :
1076 : /* {{{ proto bool function_exists(string function_name)
1077 : Checks if the function exists */
1078 : ZEND_FUNCTION(function_exists)
1079 4 : {
1080 : zval **function_name;
1081 : zend_function *func;
1082 : char *lcname;
1083 : zend_bool retval;
1084 :
1085 4 : if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &function_name)==FAILURE) {
1086 0 : ZEND_WRONG_PARAM_COUNT();
1087 : }
1088 4 : convert_to_string_ex(function_name);
1089 4 : lcname = zend_str_tolower_dup(Z_STRVAL_PP(function_name), Z_STRLEN_PP(function_name));
1090 :
1091 4 : retval = (zend_hash_find(EG(function_table), lcname, Z_STRLEN_PP(function_name)+1, (void **)&func) == SUCCESS);
1092 :
1093 4 : efree(lcname);
1094 :
1095 : /*
1096 : * A bit of a hack, but not a bad one: we see if the handler of the function
1097 : * is actually one that displays "function is disabled" message.
1098 : */
1099 4 : if (retval && func->type == ZEND_INTERNAL_FUNCTION &&
1100 : func->internal_function.handler == zif_display_disabled_function) {
1101 0 : retval = 0;
1102 : }
1103 :
1104 4 : RETURN_BOOL(retval);
1105 : }
1106 : /* }}} */
1107 :
1108 : #if ZEND_DEBUG
1109 : /* {{{ proto void leak(int num_bytes=3)
1110 : Cause an intentional memory leak, for testing/debugging purposes */
1111 : ZEND_FUNCTION(leak)
1112 : {
1113 : int leakbytes=3;
1114 : zval **leak;
1115 :
1116 : if (ZEND_NUM_ARGS()>=1) {
1117 : if (zend_get_parameters_ex(1, &leak)==SUCCESS) {
1118 : convert_to_long_ex(leak);
1119 : leakbytes = Z_LVAL_PP(leak);
1120 : }
1121 : }
1122 :
1123 : emalloc(leakbytes);
1124 : }
1125 : /* }}} */
1126 :
1127 :
1128 : #ifdef ZEND_TEST_EXCEPTIONS
1129 : ZEND_FUNCTION(crash)
1130 : {
1131 : char *nowhere=NULL;
1132 :
1133 : memcpy(nowhere, "something", sizeof("something"));
1134 : }
1135 : #endif
1136 :
1137 : #endif /* ZEND_DEBUG */
1138 :
1139 : /* {{{ proto array get_included_files(void)
1140 : Returns an array with the file names that were include_once()'d */
1141 : ZEND_FUNCTION(get_included_files)
1142 0 : {
1143 : char *entry;
1144 0 : if (ZEND_NUM_ARGS() != 0) {
1145 0 : ZEND_WRONG_PARAM_COUNT();
1146 : }
1147 :
1148 0 : array_init(return_value);
1149 0 : zend_hash_internal_pointer_reset(&EG(included_files));
1150 0 : while (zend_hash_get_current_key(&EG(included_files), &entry, NULL, 1) == HASH_KEY_IS_STRING) {
1151 0 : add_next_index_string(return_value, entry, 0);
1152 0 : zend_hash_move_forward(&EG(included_files));
1153 : }
1154 : }
1155 : /* }}} */
1156 :
1157 :
1158 : /* {{{ proto void trigger_error(string messsage [, int error_type])
1159 : Generates a user-level error/warning/notice message */
1160 : ZEND_FUNCTION(trigger_error)
1161 0 : {
1162 0 : int error_type = E_USER_NOTICE;
1163 : zval **z_error_type, **z_error_message;
1164 :
1165 0 : switch (ZEND_NUM_ARGS()) {
1166 : case 1:
1167 0 : if (zend_get_parameters_ex(1, &z_error_message)==FAILURE) {
1168 0 : ZEND_WRONG_PARAM_COUNT();
1169 : }
1170 0 : break;
1171 : case 2:
1172 0 : if (zend_get_parameters_ex(2, &z_error_message, &z_error_type)==FAILURE) {
1173 0 : ZEND_WRONG_PARAM_COUNT();
1174 : }
1175 0 : convert_to_long_ex(z_error_type);
1176 0 : error_type = Z_LVAL_PP(z_error_type);
1177 0 : switch (error_type) {
1178 : case E_USER_ERROR:
1179 : case E_USER_WARNING:
1180 : case E_USER_NOTICE:
1181 : break;
1182 : default:
1183 0 : zend_error(E_WARNING, "Invalid error type specified");
1184 0 : RETURN_FALSE;
1185 : break;
1186 : }
1187 0 : break;
1188 : default:
1189 0 : ZEND_WRONG_PARAM_COUNT();
1190 : }
1191 0 : convert_to_string_ex(z_error_message);
1192 0 : zend_error(error_type, "%s", Z_STRVAL_PP(z_error_message));
1193 0 : RETURN_TRUE;
1194 : }
1195 : /* }}} */
1196 :
1197 :
1198 : /* {{{ proto string set_error_handler(string error_handler [, int error_types])
1199 : Sets a user-defined error handler function. Returns the previously defined error handler, or false on error */
1200 : ZEND_FUNCTION(set_error_handler)
1201 0 : {
1202 : zval *error_handler;
1203 0 : zend_bool had_orig_error_handler=0;
1204 0 : char *error_handler_name = NULL;
1205 0 : long error_type = E_ALL | E_STRICT;
1206 :
1207 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &error_handler, &error_type) == FAILURE) {
1208 0 : return;
1209 : }
1210 :
1211 0 : if (!zend_is_callable(error_handler, 0, &error_handler_name)) {
1212 0 : zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback",
1213 : get_active_function_name(TSRMLS_C), error_handler_name?error_handler_name:"unknown");
1214 0 : efree(error_handler_name);
1215 0 : return;
1216 : }
1217 0 : efree(error_handler_name);
1218 :
1219 0 : if (EG(user_error_handler)) {
1220 0 : had_orig_error_handler = 1;
1221 0 : *return_value = *EG(user_error_handler);
1222 0 : zval_copy_ctor(return_value);
1223 0 : zend_stack_push(&EG(user_error_handlers_error_reporting), &EG(user_error_handler_error_reporting), sizeof(EG(user_error_handler_error_reporting)));
1224 0 : zend_ptr_stack_push(&EG(user_error_handlers), EG(user_error_handler));
1225 : }
1226 0 : ALLOC_ZVAL(EG(user_error_handler));
1227 :
1228 0 : if (!zend_is_true(error_handler)) { /* unset user-defined handler */
1229 0 : FREE_ZVAL(EG(user_error_handler));
1230 0 : EG(user_error_handler) = NULL;
1231 0 : RETURN_TRUE;
1232 : }
1233 :
1234 0 : EG(user_error_handler_error_reporting) = (int)error_type;
1235 0 : *EG(user_error_handler) = *error_handler;
1236 0 : zval_copy_ctor(EG(user_error_handler));
1237 :
1238 0 : if (!had_orig_error_handler) {
1239 0 : RETURN_NULL();
1240 : }
1241 : }
1242 : /* }}} */
1243 :
1244 :
1245 : /* {{{ proto void restore_error_handler(void)
1246 : Restores the previously defined error handler function */
1247 : ZEND_FUNCTION(restore_error_handler)
1248 0 : {
1249 0 : if (EG(user_error_handler)) {
1250 0 : zval *zeh = EG(user_error_handler);
1251 :
1252 0 : EG(user_error_handler) = NULL;
1253 0 : zval_ptr_dtor(&zeh);
1254 : }
1255 :
1256 0 : if (zend_ptr_stack_num_elements(&EG(user_error_handlers))==0) {
1257 0 : EG(user_error_handler) = NULL;
1258 : } else {
1259 0 : EG(user_error_handler_error_reporting) = zend_stack_int_top(&EG(user_error_handlers_error_reporting));
1260 0 : zend_stack_del_top(&EG(user_error_handlers_error_reporting));
1261 0 : EG(user_error_handler) = zend_ptr_stack_pop(&EG(user_error_handlers));
1262 : }
1263 0 : RETURN_TRUE;
1264 : }
1265 : /* }}} */
1266 :
1267 :
1268 : /* {{{ proto string set_exception_handler(callable exception_handler)
1269 : Sets a user-defined exception handler function. Returns the previously defined exception handler, or false on error */
1270 : ZEND_FUNCTION(set_exception_handler)
1271 0 : {
1272 : zval **exception_handler;
1273 0 : char *exception_handler_name = NULL;
1274 0 : zend_bool had_orig_exception_handler=0;
1275 :
1276 0 : if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &exception_handler)==FAILURE) {
1277 0 : ZEND_WRONG_PARAM_COUNT();
1278 : }
1279 :
1280 0 : if (Z_TYPE_PP(exception_handler) != IS_NULL) { /* NULL == unset */
1281 0 : if (!zend_is_callable(*exception_handler, 0, &exception_handler_name)) {
1282 0 : zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback",
1283 : get_active_function_name(TSRMLS_C), exception_handler_name?exception_handler_name:"unknown");
1284 0 : efree(exception_handler_name);
1285 0 : return;
1286 : }
1287 0 : efree(exception_handler_name);
1288 : }
1289 :
1290 0 : if (EG(user_exception_handler)) {
1291 0 : had_orig_exception_handler = 1;
1292 0 : *return_value = *EG(user_exception_handler);
1293 0 : zval_copy_ctor(return_value);
1294 0 : zend_ptr_stack_push(&EG(user_exception_handlers), EG(user_exception_handler));
1295 : }
1296 0 : ALLOC_ZVAL(EG(user_exception_handler));
1297 :
1298 0 : if (Z_TYPE_PP(exception_handler) == IS_NULL) { /* unset user-defined handler */
1299 0 : FREE_ZVAL(EG(user_exception_handler));
1300 0 : EG(user_exception_handler) = NULL;
1301 0 : RETURN_TRUE;
1302 : }
1303 :
1304 0 : *EG(user_exception_handler) = **exception_handler;
1305 0 : zval_copy_ctor(EG(user_exception_handler));
1306 :
1307 0 : if (!had_orig_exception_handler) {
1308 0 : RETURN_NULL();
1309 : }
1310 : }
1311 : /* }}} */
1312 :
1313 :
1314 : /* {{{ proto void restore_exception_handler(void)
1315 : Restores the previously defined exception handler function */
1316 : ZEND_FUNCTION(restore_exception_handler)
1317 0 : {
1318 0 : if (EG(user_exception_handler)) {
1319 0 : zval_ptr_dtor(&EG(user_exception_handler));
1320 : }
1321 0 : if (zend_ptr_stack_num_elements(&EG(user_exception_handlers))==0) {
1322 0 : EG(user_exception_handler) = NULL;
1323 : } else {
1324 0 : EG(user_exception_handler) = zend_ptr_stack_pop(&EG(user_exception_handlers));
1325 : }
1326 0 : RETURN_TRUE;
1327 : }
1328 : /* }}} */
1329 :
1330 :
1331 : static int copy_class_or_interface_name(zend_class_entry **pce, int num_args, va_list args, zend_hash_key *hash_key)
1332 0 : {
1333 0 : zval *array = va_arg(args, zval *);
1334 0 : zend_uint mask = va_arg(args, zend_uint);
1335 0 : zend_uint comply = va_arg(args, zend_uint);
1336 0 : zend_uint comply_mask = (comply)? mask:0;
1337 0 : zend_class_entry *ce = *pce;
1338 :
1339 0 : if ((hash_key->nKeyLength==0 || hash_key->arKey[0]!=0)
1340 : && (comply_mask == (ce->ce_flags & mask))) {
1341 0 : add_next_index_stringl(array, ce->name, ce->name_length, 1);
1342 : }
1343 0 : return ZEND_HASH_APPLY_KEEP;
1344 : }
1345 :
1346 :
1347 : /* {{{ proto array get_declared_classes()
1348 : Returns an array of all declared classes. */
1349 : ZEND_FUNCTION(get_declared_classes)
1350 0 : {
1351 0 : zend_uint mask = ZEND_ACC_INTERFACE;
1352 0 : zend_uint comply = 0;
1353 :
1354 0 : if (ZEND_NUM_ARGS() != 0) {
1355 0 : ZEND_WRONG_PARAM_COUNT();
1356 : }
1357 :
1358 0 : array_init(return_value);
1359 0 : zend_hash_apply_with_arguments(EG(class_table), (apply_func_args_t) copy_class_or_interface_name, 3, return_value, mask, comply);
1360 : }
1361 : /* }}} */
1362 :
1363 : /* {{{ proto array get_declared_interfaces()
1364 : Returns an array of all declared interfaces. */
1365 : ZEND_FUNCTION(get_declared_interfaces)
1366 0 : {
1367 0 : zend_uint mask = ZEND_ACC_INTERFACE;
1368 0 : zend_uint comply = 1;
1369 :
1370 0 : if (ZEND_NUM_ARGS() != 0) {
1371 0 : ZEND_WRONG_PARAM_COUNT();
1372 : }
1373 :
1374 0 : array_init(return_value);
1375 0 : zend_hash_apply_with_arguments(EG(class_table), (apply_func_args_t) copy_class_or_interface_name, 3, return_value, mask, comply);
1376 : }
1377 : /* }}} */
1378 :
1379 :
1380 : static int copy_function_name(zend_function *func, int num_args, va_list args, zend_hash_key *hash_key)
1381 0 : {
1382 0 : zval *internal_ar = va_arg(args, zval *),
1383 0 : *user_ar = va_arg(args, zval *);
1384 :
1385 0 : if (hash_key->nKeyLength == 0 || hash_key->arKey[0] == 0) {
1386 0 : return 0;
1387 : }
1388 :
1389 0 : if (func->type == ZEND_INTERNAL_FUNCTION) {
1390 0 : add_next_index_stringl(internal_ar, hash_key->arKey, hash_key->nKeyLength-1, 1);
1391 0 : } else if (func->type == ZEND_USER_FUNCTION) {
1392 0 : add_next_index_stringl(user_ar, hash_key->arKey, hash_key->nKeyLength-1, 1);
1393 : }
1394 :
1395 0 : return 0;
1396 : }
1397 :
1398 :
1399 : /* {{{ proto array get_defined_functions(void)
1400 : Returns an array of all defined functions */
1401 : ZEND_FUNCTION(get_defined_functions)
1402 0 : {
1403 : zval *internal;
1404 : zval *user;
1405 :
1406 0 : if (ZEND_NUM_ARGS() != 0) {
1407 0 : ZEND_WRONG_PARAM_COUNT();
1408 : }
1409 :
1410 0 : MAKE_STD_ZVAL(internal);
1411 0 : MAKE_STD_ZVAL(user);
1412 :
1413 0 : array_init(internal);
1414 0 : array_init(user);
1415 0 : array_init(return_value);
1416 :
1417 0 : zend_hash_apply_with_arguments(EG(function_table), (apply_func_args_t) copy_function_name, 2, internal, user);
1418 :
1419 0 : if (zend_hash_add(Z_ARRVAL_P(return_value), "internal", sizeof("internal"), (void **)&internal, sizeof(zval *), NULL) == FAILURE) {
1420 0 : zval_ptr_dtor(&internal);
1421 0 : zval_ptr_dtor(&user);
1422 0 : zval_dtor(return_value);
1423 0 : zend_error(E_WARNING, "Cannot add internal functions to return value from get_defined_functions()");
1424 0 : RETURN_FALSE;
1425 : }
1426 :
1427 0 : if (zend_hash_add(Z_ARRVAL_P(return_value), "user", sizeof("user"), (void **)&user, sizeof(zval *), NULL) == FAILURE) {
1428 0 : zval_ptr_dtor(&user);
1429 0 : zval_dtor(return_value);
1430 0 : zend_error(E_WARNING, "Cannot add user functions to return value from get_defined_functions()");
1431 0 : RETURN_FALSE;
1432 : }
1433 : }
1434 : /* }}} */
1435 :
1436 :
1437 : /* {{{ proto array get_defined_vars(void)
1438 : Returns an associative array of names and values of all currently defined variable names (variables in the current scope) */
1439 : ZEND_FUNCTION(get_defined_vars)
1440 0 : {
1441 : zval *tmp;
1442 :
1443 0 : array_init(return_value);
1444 :
1445 0 : zend_hash_copy(Z_ARRVAL_P(return_value), EG(active_symbol_table),
1446 : (copy_ctor_func_t)zval_add_ref, &tmp, sizeof(zval *));
1447 0 : }
1448 : /* }}} */
1449 :
1450 :
1451 : #define LAMBDA_TEMP_FUNCNAME "__lambda_func"
1452 : /* {{{ proto string create_function(string args, string code)
1453 : Creates an anonymous function, and returns its name (funny, eh?) */
1454 : ZEND_FUNCTION(create_function)
1455 0 : {
1456 : char *eval_code, *function_name;
1457 : int eval_code_length, function_name_length;
1458 : zval **z_function_args, **z_function_code;
1459 : int retval;
1460 : char *eval_name;
1461 :
1462 0 : if (ZEND_NUM_ARGS()!=2 || zend_get_parameters_ex(2, &z_function_args, &z_function_code)==FAILURE) {
1463 0 : ZEND_WRONG_PARAM_COUNT();
1464 : }
1465 :
1466 0 : convert_to_string_ex(z_function_args);
1467 0 : convert_to_string_ex(z_function_code);
1468 :
1469 0 : eval_code_length = sizeof("function " LAMBDA_TEMP_FUNCNAME)
1470 : +Z_STRLEN_PP(z_function_args)
1471 : +2 /* for the args parentheses */
1472 : +2 /* for the curly braces */
1473 : +Z_STRLEN_PP(z_function_code);
1474 :
1475 0 : zend_spprintf(&eval_code, 0, "function " LAMBDA_TEMP_FUNCNAME "(%s){%s}", Z_STRVAL_PP(z_function_args), Z_STRVAL_PP(z_function_code));
1476 :
1477 0 : eval_name = zend_make_compiled_string_description("runtime-created function" TSRMLS_CC);
1478 0 : retval = zend_eval_string(eval_code, NULL, eval_name TSRMLS_CC);
1479 0 : efree(eval_code);
1480 0 : efree(eval_name);
1481 :
1482 0 : if (retval==SUCCESS) {
1483 : zend_function new_function, *func;
1484 :
1485 0 : if (zend_hash_find(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME), (void **) &func)==FAILURE) {
1486 0 : zend_error(E_ERROR, "Unexpected inconsistency in create_function()");
1487 0 : RETURN_FALSE;
1488 : }
1489 0 : new_function = *func;
1490 0 : function_add_ref(&new_function);
1491 :
1492 0 : function_name = (char *) emalloc(sizeof("0lambda_")+MAX_LENGTH_OF_LONG);
1493 :
1494 : do {
1495 0 : sprintf(function_name, "%clambda_%d", 0, ++EG(lambda_count));
1496 0 : function_name_length = strlen(function_name+1)+1;
1497 0 : } while (zend_hash_add(EG(function_table), function_name, function_name_length+1, &new_function, sizeof(zend_function), NULL)==FAILURE);
1498 0 : zend_hash_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME));
1499 0 : RETURN_STRINGL(function_name, function_name_length, 0);
1500 : } else {
1501 0 : RETURN_FALSE;
1502 : }
1503 : }
1504 : /* }}} */
1505 :
1506 :
1507 : #if ZEND_DEBUG
1508 : ZEND_FUNCTION(zend_test_func)
1509 : {
1510 : zval *arg1, *arg2;
1511 :
1512 : zend_get_parameters(ht, 2, &arg1, &arg2);
1513 : }
1514 :
1515 :
1516 : #ifdef ZTS
1517 : ZEND_FUNCTION(zend_thread_id)
1518 : {
1519 : RETURN_LONG(tsrm_thread_id());
1520 : }
1521 : #endif
1522 : #endif
1523 :
1524 : /* {{{ proto string get_resource_type(resource res)
1525 : Get the resource type name for a given resource */
1526 : ZEND_FUNCTION(get_resource_type)
1527 0 : {
1528 : char *resource_type;
1529 : zval **z_resource_type;
1530 :
1531 0 : if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &z_resource_type)==FAILURE) {
1532 0 : ZEND_WRONG_PARAM_COUNT();
1533 : }
1534 :
1535 0 : if (Z_TYPE_PP(z_resource_type) != IS_RESOURCE) {
1536 0 : zend_error(E_WARNING, "Supplied argument is not a valid resource handle");
1537 0 : RETURN_FALSE;
1538 : }
1539 :
1540 0 : resource_type = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(z_resource_type) TSRMLS_CC);
1541 0 : if (resource_type) {
1542 0 : RETURN_STRING(resource_type, 1);
1543 : } else {
1544 0 : RETURN_STRING("Unknown", 1);
1545 : }
1546 : }
1547 : /* }}} */
1548 :
1549 :
1550 : static int add_extension_info(zend_module_entry *module, void *arg TSRMLS_DC)
1551 10 : {
1552 10 : zval *name_array = (zval *)arg;
1553 10 : add_next_index_string(name_array, module->name, 1);
1554 10 : return 0;
1555 : }
1556 :
1557 : static int add_constant_info(zend_constant *constant, void *arg TSRMLS_DC)
1558 0 : {
1559 0 : zval *name_array = (zval *)arg;
1560 : zval *const_val;
1561 :
1562 0 : MAKE_STD_ZVAL(const_val);
1563 0 : *const_val = constant->value;
1564 0 : zval_copy_ctor(const_val);
1565 0 : INIT_PZVAL(const_val);
1566 0 : add_assoc_zval_ex(name_array, constant->name, constant->name_len, const_val);
1567 0 : return 0;
1568 : }
1569 :
1570 :
1571 : /* {{{ proto array get_loaded_extensions(void)
1572 : Return an array containing names of loaded extensions */
1573 : ZEND_FUNCTION(get_loaded_extensions)
1574 1 : {
1575 1 : if (ZEND_NUM_ARGS() != 0) {
1576 0 : ZEND_WRONG_PARAM_COUNT();
1577 : }
1578 :
1579 1 : array_init(return_value);
1580 1 : zend_hash_apply_with_argument(&module_registry, (apply_func_arg_t) add_extension_info, return_value TSRMLS_CC);
1581 : }
1582 : /* }}} */
1583 :
1584 :
1585 : /* {{{ proto array get_defined_constants([mixed categorize])
1586 : Return an array containing the names and values of all defined constants */
1587 : ZEND_FUNCTION(get_defined_constants)
1588 0 : {
1589 0 : int argc = ZEND_NUM_ARGS();
1590 :
1591 0 : if (argc != 0 && argc != 1) {
1592 0 : ZEND_WRONG_PARAM_COUNT();
1593 : }
1594 :
1595 0 : array_init(return_value);
1596 :
1597 0 : if (argc) {
1598 : HashPosition pos;
1599 : zend_constant *val;
1600 : int module_number;
1601 : zval **modules;
1602 : char **module_names;
1603 : zend_module_entry *module;
1604 0 : int i = 1;
1605 :
1606 0 : modules = ecalloc(zend_hash_num_elements(&module_registry) + 2, sizeof(zval *));
1607 0 : module_names = emalloc((zend_hash_num_elements(&module_registry) + 2) * sizeof(char *));
1608 :
1609 0 : module_names[0] = "internal";
1610 0 : zend_hash_internal_pointer_reset_ex(&module_registry, &pos);
1611 0 : while (zend_hash_get_current_data_ex(&module_registry, (void *) &module, &pos) != FAILURE) {
1612 0 : module_names[i++] = module->name;
1613 0 : zend_hash_move_forward_ex(&module_registry, &pos);
1614 : }
1615 0 : module_names[i] = "user";
1616 :
1617 0 : zend_hash_internal_pointer_reset_ex(EG(zend_constants), &pos);
1618 0 : while (zend_hash_get_current_data_ex(EG(zend_constants), (void **) &val, &pos) != FAILURE) {
1619 : zval *const_val;
1620 :
1621 0 : if (val->module_number == PHP_USER_CONSTANT) {
1622 0 : module_number = i;
1623 0 : } else if (val->module_number > i || val->module_number < 0) {
1624 : /* should not happen */
1625 : goto bad_module_id;
1626 : } else {
1627 0 : module_number = val->module_number;
1628 : }
1629 :
1630 0 : if (!modules[module_number]) {
1631 0 : MAKE_STD_ZVAL(modules[module_number]);
1632 0 : array_init(modules[module_number]);
1633 0 : add_assoc_zval(return_value, module_names[module_number], modules[module_number]);
1634 : }
1635 :
1636 0 : MAKE_STD_ZVAL(const_val);
1637 0 : *const_val = val->value;
1638 0 : zval_copy_ctor(const_val);
1639 0 : INIT_PZVAL(const_val);
1640 :
1641 0 : add_assoc_zval_ex(modules[module_number], val->name, val->name_len, const_val);
1642 0 : bad_module_id:
1643 0 : zend_hash_move_forward_ex(EG(zend_constants), &pos);
1644 : }
1645 0 : efree(module_names);
1646 0 : efree(modules);
1647 : } else {
1648 0 : zend_hash_apply_with_argument(EG(zend_constants), (apply_func_arg_t) add_constant_info, return_value TSRMLS_CC);
1649 : }
1650 : }
1651 : /* }}} */
1652 :
1653 :
1654 : static zval *debug_backtrace_get_args(void ***curpos TSRMLS_DC)
1655 16 : {
1656 16 : void **p = *curpos - 2;
1657 : zval *arg_array, **arg;
1658 16 : int arg_count = (ulong) *p;
1659 :
1660 16 : *curpos -= (arg_count+2);
1661 :
1662 16 : MAKE_STD_ZVAL(arg_array);
1663 16 : array_init(arg_array);
1664 16 : p -= arg_count;
1665 :
1666 40 : while (--arg_count >= 0) {
1667 8 : arg = (zval **) p++;
1668 8 : if (*arg) {
1669 8 : if (Z_TYPE_PP(arg) != IS_OBJECT) {
1670 2 : SEPARATE_ZVAL_TO_MAKE_IS_REF(arg);
1671 : }
1672 8 : (*arg)->refcount++;
1673 8 : add_next_index_zval(arg_array, *arg);
1674 : } else {
1675 0 : add_next_index_null(arg_array);
1676 : }
1677 : }
1678 :
1679 : /* skip args from incomplete frames */
1680 32 : while ((((*curpos)-1) > EG(argument_stack).elements) && *((*curpos)-1)) {
1681 0 : (*curpos)--;
1682 : }
1683 :
1684 16 : return arg_array;
1685 : }
1686 :
1687 : void debug_print_backtrace_args(zval *arg_array TSRMLS_DC)
1688 0 : {
1689 : zval **tmp;
1690 : HashPosition iterator;
1691 0 : int i = 0;
1692 :
1693 0 : zend_hash_internal_pointer_reset_ex(arg_array->value.ht, &iterator);
1694 0 : while (zend_hash_get_current_data_ex(arg_array->value.ht, (void **) &tmp, &iterator) == SUCCESS) {
1695 0 : if (i++) {
1696 0 : ZEND_PUTS(", ");
1697 : }
1698 0 : zend_print_flat_zval_r(*tmp TSRMLS_CC);
1699 0 : zend_hash_move_forward_ex(arg_array->value.ht, &iterator);
1700 : }
1701 0 : }
1702 :
1703 : /* {{{ proto void debug_print_backtrace(void) */
1704 : ZEND_FUNCTION(debug_print_backtrace)
1705 0 : {
1706 : zend_execute_data *ptr, *skip;
1707 : int lineno;
1708 : char *function_name;
1709 : char *filename;
1710 0 : char *class_name = NULL;
1711 : char *call_type;
1712 0 : char *include_filename = NULL;
1713 0 : zval *arg_array = NULL;
1714 0 : void **cur_arg_pos = EG(argument_stack).top_element;
1715 0 : void **args = cur_arg_pos;
1716 0 : int arg_stack_consistent = 0;
1717 0 : int frames_on_stack = 0;
1718 0 : int indent = 0;
1719 :
1720 0 : if (ZEND_NUM_ARGS()) {
1721 0 : ZEND_WRONG_PARAM_COUNT();
1722 : }
1723 :
1724 0 : while (--args > EG(argument_stack).elements) {
1725 0 : if (*args--) {
1726 0 : break;
1727 : }
1728 0 : args -= *(ulong*)args;
1729 0 : frames_on_stack++;
1730 :
1731 : /* skip args from incomplete frames */
1732 0 : while (((args-1) > EG(argument_stack).elements) && *(args-1)) {
1733 0 : args--;
1734 : }
1735 :
1736 0 : if ((args-1) == EG(argument_stack).elements) {
1737 0 : arg_stack_consistent = 1;
1738 0 : break;
1739 : }
1740 : }
1741 :
1742 0 : ptr = EG(current_execute_data);
1743 :
1744 : /* skip debug_backtrace() */
1745 0 : ptr = ptr->prev_execute_data;
1746 0 : cur_arg_pos -= 2;
1747 0 : frames_on_stack--;
1748 :
1749 0 : if (arg_stack_consistent) {
1750 : /* skip args from incomplete frames */
1751 0 : while (((cur_arg_pos-1) > EG(argument_stack).elements) && *(cur_arg_pos-1)) {
1752 0 : cur_arg_pos--;
1753 : }
1754 : }
1755 :
1756 0 : while (ptr) {
1757 0 : char *free_class_name = NULL;
1758 :
1759 0 : class_name = call_type = NULL;
1760 0 : arg_array = NULL;
1761 :
1762 0 : skip = ptr;
1763 : /* skip internal handler */
1764 0 : if (!skip->op_array &&
1765 : skip->prev_execute_data &&
1766 : skip->prev_execute_data->opline &&
1767 : skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
1768 : skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
1769 : skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
1770 0 : skip = skip->prev_execute_data;
1771 : }
1772 :
1773 0 : if (skip->op_array) {
1774 0 : filename = skip->op_array->filename;
1775 0 : lineno = skip->opline->lineno;
1776 : } else {
1777 0 : filename = NULL;
1778 0 : lineno = 0;
1779 : }
1780 :
1781 0 : function_name = ptr->function_state.function->common.function_name;
1782 :
1783 0 : if (function_name) {
1784 0 : if (ptr->object) {
1785 0 : if (ptr->function_state.function->common.scope) {
1786 0 : class_name = ptr->function_state.function->common.scope->name;
1787 : } else {
1788 : zend_uint class_name_len;
1789 : int dup;
1790 :
1791 0 : dup = zend_get_object_classname(ptr->object, &class_name, &class_name_len TSRMLS_CC);
1792 0 : if(!dup) {
1793 0 : free_class_name = class_name;
1794 : }
1795 : }
1796 :
1797 0 : call_type = "->";
1798 0 : } else if (ptr->function_state.function->common.scope) {
1799 0 : class_name = ptr->function_state.function->common.scope->name;
1800 0 : call_type = "::";
1801 : } else {
1802 0 : class_name = NULL;
1803 0 : call_type = NULL;
1804 : }
1805 0 : if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) {
1806 0 : if (arg_stack_consistent && (frames_on_stack > 0)) {
1807 0 : arg_array = debug_backtrace_get_args(&cur_arg_pos TSRMLS_CC);
1808 0 : frames_on_stack--;
1809 : }
1810 : }
1811 : } else {
1812 : /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
1813 0 : zend_bool build_filename_arg = 1;
1814 :
1815 0 : if (!ptr->opline || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
1816 : /* can happen when calling eval from a custom sapi */
1817 0 : function_name = "unknown";
1818 0 : build_filename_arg = 0;
1819 : } else
1820 0 : switch (Z_LVAL(ptr->opline->op2.u.constant)) {
1821 : case ZEND_EVAL:
1822 0 : function_name = "eval";
1823 0 : build_filename_arg = 0;
1824 0 : break;
1825 : case ZEND_INCLUDE:
1826 0 : function_name = "include";
1827 0 : break;
1828 : case ZEND_REQUIRE:
1829 0 : function_name = "require";
1830 0 : break;
1831 : case ZEND_INCLUDE_ONCE:
1832 0 : function_name = "include_once";
1833 0 : break;
1834 : case ZEND_REQUIRE_ONCE:
1835 0 : function_name = "require_once";
1836 0 : break;
1837 : default:
1838 : /* this can actually happen if you use debug_backtrace() in your error_handler and
1839 : * you're in the top-scope */
1840 0 : function_name = "unknown";
1841 0 : build_filename_arg = 0;
1842 : break;
1843 : }
1844 :
1845 0 : if (build_filename_arg && include_filename) {
1846 0 : MAKE_STD_ZVAL(arg_array);
1847 0 : array_init(arg_array);
1848 0 : add_next_index_string(arg_array, include_filename, 1);
1849 : }
1850 0 : call_type = NULL;
1851 : }
1852 0 : zend_printf("#%-2d ", indent);
1853 0 : if (class_name) {
1854 0 : ZEND_PUTS(class_name);
1855 0 : ZEND_PUTS(call_type);
1856 : }
1857 0 : zend_printf("%s(", function_name?function_name:"main");
1858 0 : if (arg_array) {
1859 0 : debug_print_backtrace_args(arg_array TSRMLS_CC);
1860 0 : zval_ptr_dtor(&arg_array);
1861 : }
1862 0 : if (filename) {
1863 0 : zend_printf(") called at [%s:%d]\n", filename, lineno);
1864 : } else {
1865 0 : zend_execute_data *prev = skip->prev_execute_data;
1866 :
1867 0 : while (prev) {
1868 0 : if (prev->function_state.function &&
1869 : prev->function_state.function->common.type != ZEND_USER_FUNCTION) {
1870 0 : prev = NULL;
1871 0 : break;
1872 : }
1873 0 : if (prev->op_array) {
1874 0 : zend_printf(") called at [%s:%d]\n", prev->op_array->filename, prev->opline->lineno);
1875 0 : break;
1876 : }
1877 0 : prev = prev->prev_execute_data;
1878 : }
1879 0 : if (!prev) {
1880 0 : ZEND_PUTS(")\n");
1881 : }
1882 : }
1883 0 : include_filename = filename;
1884 0 : ptr = skip->prev_execute_data;
1885 0 : ++indent;
1886 0 : if (free_class_name) {
1887 0 : efree(free_class_name);
1888 : }
1889 : }
1890 : }
1891 :
1892 : /* }}} */
1893 :
1894 : ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int provide_object TSRMLS_DC)
1895 30 : {
1896 : zend_execute_data *ptr, *skip;
1897 : int lineno;
1898 : char *function_name;
1899 : char *filename;
1900 : char *class_name;
1901 30 : char *include_filename = NULL;
1902 : zval *stack_frame;
1903 30 : void **cur_arg_pos = EG(argument_stack).top_element;
1904 30 : void **args = cur_arg_pos;
1905 30 : int arg_stack_consistent = 0;
1906 30 : int frames_on_stack = 0;
1907 :
1908 64 : while (--args > EG(argument_stack).elements) {
1909 22 : if (*args--) {
1910 0 : break;
1911 : }
1912 22 : args -= *(ulong*)args;
1913 22 : frames_on_stack++;
1914 :
1915 : /* skip args from incomplete frames */
1916 44 : while (((args-1) > EG(argument_stack).elements) && *(args-1)) {
1917 0 : args--;
1918 : }
1919 :
1920 22 : if ((args-1) == EG(argument_stack).elements) {
1921 18 : arg_stack_consistent = 1;
1922 18 : break;
1923 : }
1924 : }
1925 :
1926 30 : ptr = EG(current_execute_data);
1927 :
1928 : /* skip "new Exception()" */
1929 30 : if (ptr && (skip_last == 0) && ptr->opline && (ptr->opline->opcode == ZEND_NEW)) {
1930 12 : ptr = ptr->prev_execute_data;
1931 : }
1932 :
1933 : /* skip debug_backtrace() */
1934 30 : if (skip_last-- && ptr) {
1935 0 : int arg_count = *((ulong*)(cur_arg_pos - 2));
1936 0 : cur_arg_pos -= (arg_count + 2);
1937 0 : frames_on_stack--;
1938 0 : ptr = ptr->prev_execute_data;
1939 :
1940 0 : if (arg_stack_consistent) {
1941 : /* skip args from incomplete frames */
1942 0 : while (((cur_arg_pos-1) > EG(argument_stack).elements) && *(cur_arg_pos-1)) {
1943 0 : cur_arg_pos--;
1944 : }
1945 : }
1946 : }
1947 :
1948 30 : array_init(return_value);
1949 :
1950 82 : while (ptr) {
1951 22 : MAKE_STD_ZVAL(stack_frame);
1952 22 : array_init(stack_frame);
1953 :
1954 22 : skip = ptr;
1955 : /* skip internal handler */
1956 22 : if (!skip->op_array &&
1957 : skip->prev_execute_data &&
1958 : skip->prev_execute_data->opline &&
1959 : skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
1960 : skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
1961 : skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
1962 0 : skip = skip->prev_execute_data;
1963 : }
1964 :
1965 22 : if (skip->op_array) {
1966 20 : filename = skip->op_array->filename;
1967 20 : lineno = skip->opline->lineno;
1968 20 : add_assoc_string_ex(stack_frame, "file", sizeof("file"), filename, 1);
1969 20 : add_assoc_long_ex(stack_frame, "line", sizeof("line"), lineno);
1970 :
1971 : /* try to fetch args only if an FCALL was just made - elsewise we're in the middle of a function
1972 : * and debug_baktrace() might have been called by the error_handler. in this case we don't
1973 : * want to pop anything of the argument-stack */
1974 : } else {
1975 2 : zend_execute_data *prev = skip->prev_execute_data;
1976 :
1977 4 : while (prev) {
1978 2 : if (prev->function_state.function &&
1979 : prev->function_state.function->common.type != ZEND_USER_FUNCTION) {
1980 2 : break;
1981 : }
1982 0 : if (prev->op_array) {
1983 0 : add_assoc_string_ex(stack_frame, "file", sizeof("file"), prev->op_array->filename, 1);
1984 0 : add_assoc_long_ex(stack_frame, "line", sizeof("line"), prev->opline->lineno);
1985 0 : break;
1986 : }
1987 0 : prev = prev->prev_execute_data;
1988 : }
1989 2 : filename = NULL;
1990 : }
1991 :
1992 22 : function_name = ptr->function_state.function->common.function_name;
1993 :
1994 22 : if (function_name) {
1995 22 : add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1);
1996 :
1997 44 : if (ptr->object && Z_TYPE_P(ptr->object) == IS_OBJECT) {
1998 22 : if (ptr->function_state.function->common.scope) {
1999 22 : add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
2000 : } else {
2001 : zend_uint class_name_len;
2002 : int dup;
2003 :
2004 0 : dup = zend_get_object_classname(ptr->object, &class_name, &class_name_len TSRMLS_CC);
2005 0 : add_assoc_string_ex(stack_frame, "class", sizeof("class"), class_name, dup);
2006 :
2007 : }
2008 22 : if (provide_object) {
2009 0 : add_assoc_zval_ex(stack_frame, "object", sizeof("object"), ptr->object);
2010 0 : ptr->object->refcount++;
2011 : }
2012 :
2013 22 : add_assoc_string_ex(stack_frame, "type", sizeof("type"), "->", 1);
2014 0 : } else if (ptr->function_state.function->common.scope) {
2015 0 : add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
2016 0 : add_assoc_string_ex(stack_frame, "type", sizeof("type"), "::", 1);
2017 : }
2018 :
2019 22 : if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) {
2020 16 : if (arg_stack_consistent && (frames_on_stack > 0)) {
2021 16 : add_assoc_zval_ex(stack_frame, "args", sizeof("args"), debug_backtrace_get_args(&cur_arg_pos TSRMLS_CC));
2022 16 : frames_on_stack--;
2023 : }
2024 : }
2025 : } else {
2026 : /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
2027 0 : zend_bool build_filename_arg = 1;
2028 :
2029 0 : if (!ptr->opline || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
2030 : /* can happen when calling eval from a custom sapi */
2031 0 : function_name = "unknown";
2032 0 : build_filename_arg = 0;
2033 : } else
2034 0 : switch (ptr->opline->op2.u.constant.value.lval) {
2035 : case ZEND_EVAL:
2036 0 : function_name = "eval";
2037 0 : build_filename_arg = 0;
2038 0 : break;
2039 : case ZEND_INCLUDE:
2040 0 : function_name = "include";
2041 0 : break;
2042 : case ZEND_REQUIRE:
2043 0 : function_name = "require";
2044 0 : break;
2045 : case ZEND_INCLUDE_ONCE:
2046 0 : function_name = "include_once";
2047 0 : break;
2048 : case ZEND_REQUIRE_ONCE:
2049 0 : function_name = "require_once";
2050 0 : break;
2051 : default:
2052 : /* this can actually happen if you use debug_backtrace() in your error_handler and
2053 : * you're in the top-scope */
2054 0 : function_name = "unknown";
2055 0 : build_filename_arg = 0;
2056 : break;
2057 : }
2058 :
2059 0 : if (build_filename_arg && include_filename) {
2060 : zval *arg_array;
2061 :
2062 0 : MAKE_STD_ZVAL(arg_array);
2063 0 : array_init(arg_array);
2064 :
2065 : /* include_filename always points to the last filename of the last last called-fuction.
2066 : if we have called include in the frame above - this is the file we have included.
2067 : */
2068 :
2069 0 : add_next_index_string(arg_array, include_filename, 1);
2070 0 : add_assoc_zval_ex(stack_frame, "args", sizeof("args"), arg_array);
2071 : }
2072 :
2073 0 : add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1);
2074 : }
2075 :
2076 22 : add_next_index_zval(return_value, stack_frame);
2077 :
2078 22 : include_filename = filename;
2079 :
2080 22 : ptr = skip->prev_execute_data;
2081 : }
2082 30 : }
2083 : /* }}} */
2084 :
2085 :
2086 : /* {{{ proto array debug_backtrace(void)
2087 : Return backtrace as array */
2088 : ZEND_FUNCTION(debug_backtrace)
2089 0 : {
2090 0 : if (ZEND_NUM_ARGS()) {
2091 0 : ZEND_WRONG_PARAM_COUNT();
2092 : }
2093 :
2094 0 : zend_fetch_debug_backtrace(return_value, 1, 1 TSRMLS_CC);
2095 : }
2096 : /* }}} */
2097 :
2098 : /* {{{ proto bool extension_loaded(string extension_name)
2099 : Returns true if the named extension is loaded */
2100 : ZEND_FUNCTION(extension_loaded)
2101 117 : {
2102 : zval **extension_name;
2103 : char *lcname;
2104 :
2105 117 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &extension_name)) {
2106 0 : ZEND_WRONG_PARAM_COUNT();
2107 : }
2108 :
2109 117 : convert_to_string_ex(extension_name);
2110 117 : lcname = zend_str_tolower_dup(Z_STRVAL_PP(extension_name), Z_STRLEN_PP(extension_name));
2111 117 : if (zend_hash_exists(&module_registry, lcname, Z_STRLEN_PP(extension_name)+1)) {
2112 115 : RETVAL_TRUE;
2113 : } else {
2114 2 : RETVAL_FALSE;
2115 : }
2116 117 : efree(lcname);
2117 : }
2118 : /* }}} */
2119 :
2120 :
2121 : /* {{{ proto array get_extension_funcs(string extension_name)
2122 : Returns an array with the names of functions belonging to the named extension */
2123 : ZEND_FUNCTION(get_extension_funcs)
2124 0 : {
2125 : zval **extension_name;
2126 : zend_module_entry *module;
2127 : zend_function_entry *func;
2128 :
2129 0 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &extension_name)) {
2130 0 : ZEND_WRONG_PARAM_COUNT();
2131 : }
2132 :
2133 0 : convert_to_string_ex(extension_name);
2134 0 : if (strncasecmp(Z_STRVAL_PP(extension_name), "zend", sizeof("zend"))) {
2135 0 : char *lcname = zend_str_tolower_dup(Z_STRVAL_PP(extension_name), Z_STRLEN_PP(extension_name));
2136 0 : if (zend_hash_find(&module_registry, lcname,
2137 : Z_STRLEN_PP(extension_name)+1, (void**)&module) == FAILURE) {
2138 0 : efree(lcname);
2139 0 : RETURN_FALSE;
2140 : }
2141 0 : efree(lcname);
2142 :
2143 0 : if (!(func = module->functions)) {
2144 0 : RETURN_FALSE;
2145 : }
2146 : } else {
2147 0 : func = builtin_functions;
2148 : }
2149 :
2150 0 : array_init(return_value);
2151 :
2152 0 : while (func->fname) {
2153 0 : add_next_index_string(return_value, func->fname, 1);
2154 0 : func++;
2155 : }
2156 : }
2157 : /* }}} */
2158 :
2159 : /*
2160 : * Local variables:
2161 : * tab-width: 4
2162 : * c-basic-offset: 4
2163 : * indent-tabs-mode: t
2164 : * End:
2165 : */
|