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