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 | Andrei Zmievski <andrei@php.net> | 18 +----------------------------------------------------------------------+ 19*/ 20 21/* $Id$ */ 22 23#include "zend.h" 24#include "zend_execute.h" 25#include "zend_API.h" 26#include "zend_modules.h" 27#include "zend_constants.h" 28#include "zend_exceptions.h" 29#include "zend_closures.h" 30 31#ifdef HAVE_STDARG_H 32#include <stdarg.h> 33#endif 34 35/* these variables are true statics/globals, and have to be mutex'ed on every access */ 36ZEND_API HashTable module_registry; 37 38/* this function doesn't check for too many parameters */ 39ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */ 40{ 41 void **p; 42 int arg_count; 43 va_list ptr; 44 zval **param, *param_ptr; 45 TSRMLS_FETCH(); 46 47 p = zend_vm_stack_top(TSRMLS_C) - 1; 48 arg_count = (int)(zend_uintptr_t) *p; 49 50 if (param_count>arg_count) { 51 return FAILURE; 52 } 53 54 va_start(ptr, param_count); 55 56 while (param_count-->0) { 57 param = va_arg(ptr, zval **); 58 param_ptr = *(p-arg_count); 59 if (!PZVAL_IS_REF(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) { 60 zval *new_tmp; 61 62 ALLOC_ZVAL(new_tmp); 63 *new_tmp = *param_ptr; 64 zval_copy_ctor(new_tmp); 65 INIT_PZVAL(new_tmp); 66 param_ptr = new_tmp; 67 Z_DELREF_P((zval *) *(p-arg_count)); 68 *(p-arg_count) = param_ptr; 69 } 70 *param = param_ptr; 71 arg_count--; 72 } 73 va_end(ptr); 74 75 return SUCCESS; 76} 77/* }}} */ 78 79ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval **argument_array TSRMLS_DC) /* {{{ */ 80{ 81 void **p; 82 int arg_count; 83 zval *param_ptr; 84 85 p = zend_vm_stack_top(TSRMLS_C) - 1; 86 arg_count = (int)(zend_uintptr_t) *p; 87 88 if (param_count>arg_count) { 89 return FAILURE; 90 } 91 92 while (param_count-->0) { 93 param_ptr = *(p-arg_count); 94 if (!PZVAL_IS_REF(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) { 95 zval *new_tmp; 96 97 ALLOC_ZVAL(new_tmp); 98 *new_tmp = *param_ptr; 99 zval_copy_ctor(new_tmp); 100 INIT_PZVAL(new_tmp); 101 param_ptr = new_tmp; 102 Z_DELREF_P((zval *) *(p-arg_count)); 103 *(p-arg_count) = param_ptr; 104 } 105 *(argument_array++) = param_ptr; 106 arg_count--; 107 } 108 109 return SUCCESS; 110} 111/* }}} */ 112 113/* Zend-optimized Extended functions */ 114/* this function doesn't check for too many parameters */ 115ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */ 116{ 117 void **p; 118 int arg_count; 119 va_list ptr; 120 zval ***param; 121 TSRMLS_FETCH(); 122 123 p = zend_vm_stack_top(TSRMLS_C) - 1; 124 arg_count = (int)(zend_uintptr_t) *p; 125 126 if (param_count>arg_count) { 127 return FAILURE; 128 } 129 130 va_start(ptr, param_count); 131 while (param_count-->0) { 132 param = va_arg(ptr, zval ***); 133 *param = (zval **) p-(arg_count--); 134 } 135 va_end(ptr); 136 137 return SUCCESS; 138} 139/* }}} */ 140 141ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_array TSRMLS_DC) /* {{{ */ 142{ 143 void **p; 144 int arg_count; 145 146 p = zend_vm_stack_top(TSRMLS_C) - 1; 147 arg_count = (int)(zend_uintptr_t) *p; 148 149 if (param_count>arg_count) { 150 return FAILURE; 151 } 152 153 while (param_count-->0) { 154 zval **value = (zval**)(p-arg_count); 155 156 *(argument_array++) = value; 157 arg_count--; 158 } 159 160 return SUCCESS; 161} 162/* }}} */ 163 164ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TSRMLS_DC) /* {{{ */ 165{ 166 void **p; 167 int arg_count; 168 169 p = zend_vm_stack_top(TSRMLS_C) - 1; 170 arg_count = (int)(zend_uintptr_t) *p; 171 172 if (param_count>arg_count) { 173 return FAILURE; 174 } 175 176 while (param_count-->0) { 177 zval **param = (zval **) p-(arg_count--); 178 zval_add_ref(param); 179 add_next_index_zval(argument_array, *param); 180 } 181 182 return SUCCESS; 183} 184/* }}} */ 185 186ZEND_API void zend_wrong_param_count(TSRMLS_D) /* {{{ */ 187{ 188 char *space; 189 char *class_name = get_active_class_name(&space TSRMLS_CC); 190 191 zend_error(E_WARNING, "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name(TSRMLS_C)); 192} 193/* }}} */ 194 195/* Argument parsing API -- andrei */ 196ZEND_API char *zend_get_type_by_const(int type) /* {{{ */ 197{ 198 switch(type) { 199 case IS_BOOL: 200 return "boolean"; 201 case IS_LONG: 202 return "integer"; 203 case IS_DOUBLE: 204 return "double"; 205 case IS_STRING: 206 return "string"; 207 case IS_OBJECT: 208 return "object"; 209 case IS_RESOURCE: 210 return "resource"; 211 case IS_NULL: 212 return "null"; 213 case IS_ARRAY: 214 return "array"; 215 default: 216 return "unknown"; 217 } 218} 219/* }}} */ 220 221ZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */ 222{ 223 return zend_get_type_by_const(Z_TYPE_P(arg)); 224} 225/* }}} */ 226 227ZEND_API zend_class_entry *zend_get_class_entry(const zval *zobject TSRMLS_DC) /* {{{ */ 228{ 229 if (Z_OBJ_HT_P(zobject)->get_class_entry) { 230 return Z_OBJ_HT_P(zobject)->get_class_entry(zobject TSRMLS_CC); 231 } else { 232 zend_error(E_ERROR, "Class entry requested for an object without PHP class"); 233 return NULL; 234 } 235} 236/* }}} */ 237 238/* returns 1 if you need to copy result, 0 if it's already a copy */ 239ZEND_API int zend_get_object_classname(const zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC) /* {{{ */ 240{ 241 if (Z_OBJ_HT_P(object)->get_class_name == NULL || 242 Z_OBJ_HT_P(object)->get_class_name(object, class_name, class_name_len, 0 TSRMLS_CC) != SUCCESS) { 243 zend_class_entry *ce = Z_OBJCE_P(object); 244 245 *class_name = ce->name; 246 *class_name_len = ce->name_length; 247 return 1; 248 } 249 return 0; 250} 251/* }}} */ 252 253static int parse_arg_object_to_string(zval **arg TSRMLS_DC) /* {{{ */ 254{ 255 if (Z_OBJ_HANDLER_PP(arg, cast_object)) { 256 zval *obj; 257 MAKE_STD_ZVAL(obj); 258 if (Z_OBJ_HANDLER_P(*arg, cast_object)(*arg, obj, IS_STRING TSRMLS_CC) == SUCCESS) { 259 zval_ptr_dtor(arg); 260 *arg = obj; 261 return SUCCESS; 262 } 263 efree(obj); 264 } 265 /* Standard PHP objects */ 266 if (Z_OBJ_HT_PP(arg) == &std_object_handlers || !Z_OBJ_HANDLER_PP(arg, cast_object)) { 267 SEPARATE_ZVAL_IF_NOT_REF(arg); 268 if (zend_std_cast_object_tostring(*arg, *arg, IS_STRING TSRMLS_CC) == SUCCESS) { 269 return SUCCESS; 270 } 271 } 272 if (!Z_OBJ_HANDLER_PP(arg, cast_object) && Z_OBJ_HANDLER_PP(arg, get)) { 273 int use_copy; 274 zval *z = Z_OBJ_HANDLER_PP(arg, get)(*arg TSRMLS_CC); 275 Z_ADDREF_P(z); 276 if(Z_TYPE_P(z) != IS_OBJECT) { 277 zval_dtor(*arg); 278 Z_TYPE_P(*arg) = IS_NULL; 279 zend_make_printable_zval(z, *arg, &use_copy); 280 if (!use_copy) { 281 ZVAL_ZVAL(*arg, z, 1, 1); 282 } 283 return SUCCESS; 284 } 285 zval_ptr_dtor(&z); 286 } 287 return FAILURE; 288} 289/* }}} */ 290 291static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **spec, char **error, int *severity TSRMLS_DC) /* {{{ */ 292{ 293 char *spec_walk = *spec; 294 char c = *spec_walk++; 295 int return_null = 0; 296 297 /* scan through modifiers */ 298 while (1) { 299 if (*spec_walk == '/') { 300 SEPARATE_ZVAL_IF_NOT_REF(arg); 301 } else if (*spec_walk == '!') { 302 if (Z_TYPE_PP(arg) == IS_NULL) { 303 return_null = 1; 304 } 305 } else { 306 break; 307 } 308 spec_walk++; 309 } 310 311 switch (c) { 312 case 'l': 313 case 'L': 314 { 315 long *p = va_arg(*va, long *); 316 switch (Z_TYPE_PP(arg)) { 317 case IS_STRING: 318 { 319 double d; 320 int type; 321 322 if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), p, &d, -1)) == 0) { 323 return "long"; 324 } else if (type == IS_DOUBLE) { 325 if (c == 'L') { 326 if (d > LONG_MAX) { 327 *p = LONG_MAX; 328 break; 329 } else if (d < LONG_MIN) { 330 *p = LONG_MIN; 331 break; 332 } 333 } 334 335 *p = zend_dval_to_lval(d); 336 } 337 } 338 break; 339 340 case IS_DOUBLE: 341 if (c == 'L') { 342 if (Z_DVAL_PP(arg) > LONG_MAX) { 343 *p = LONG_MAX; 344 break; 345 } else if (Z_DVAL_PP(arg) < LONG_MIN) { 346 *p = LONG_MIN; 347 break; 348 } 349 } 350 case IS_NULL: 351 case IS_LONG: 352 case IS_BOOL: 353 convert_to_long_ex(arg); 354 *p = Z_LVAL_PP(arg); 355 break; 356 357 case IS_ARRAY: 358 case IS_OBJECT: 359 case IS_RESOURCE: 360 default: 361 return "long"; 362 } 363 } 364 break; 365 366 case 'd': 367 { 368 double *p = va_arg(*va, double *); 369 switch (Z_TYPE_PP(arg)) { 370 case IS_STRING: 371 { 372 long l; 373 int type; 374 375 if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &l, p, -1)) == 0) { 376 return "double"; 377 } else if (type == IS_LONG) { 378 *p = (double) l; 379 } 380 } 381 break; 382 383 case IS_NULL: 384 case IS_LONG: 385 case IS_DOUBLE: 386 case IS_BOOL: 387 convert_to_double_ex(arg); 388 *p = Z_DVAL_PP(arg); 389 break; 390 391 case IS_ARRAY: 392 case IS_OBJECT: 393 case IS_RESOURCE: 394 default: 395 return "double"; 396 } 397 } 398 break; 399 400 case 's': 401 { 402 char **p = va_arg(*va, char **); 403 int *pl = va_arg(*va, int *); 404 switch (Z_TYPE_PP(arg)) { 405 case IS_NULL: 406 if (return_null) { 407 *p = NULL; 408 *pl = 0; 409 break; 410 } 411 /* break omitted intentionally */ 412 413 case IS_STRING: 414 case IS_LONG: 415 case IS_DOUBLE: 416 case IS_BOOL: 417 convert_to_string_ex(arg); 418 if (UNEXPECTED(Z_ISREF_PP(arg) != 0)) { 419 /* it's dangerous to return pointers to string 420 buffer of referenced variable, because it can 421 be clobbered throug magic callbacks */ 422 SEPARATE_ZVAL(arg); 423 } 424 *p = Z_STRVAL_PP(arg); 425 *pl = Z_STRLEN_PP(arg); 426 break; 427 428 case IS_OBJECT: 429 case IS_ARRAY: 430 case IS_RESOURCE: 431 default: 432 return "string"; 433 } 434 } 435 break; 436 437 case 'b': 438 { 439 zend_bool *p = va_arg(*va, zend_bool *); 440 switch (Z_TYPE_PP(arg)) { 441 case IS_NULL: 442 case IS_STRING: 443 case IS_LONG: 444 case IS_DOUBLE: 445 case IS_BOOL: 446 convert_to_boolean_ex(arg); 447 *p = Z_BVAL_PP(arg); 448 break; 449 450 case IS_ARRAY: 451 case IS_OBJECT: 452 case IS_RESOURCE: 453 default: 454 return "boolean"; 455 } 456 } 457 break; 458 459 case 'r': 460 { 461 zval **p = va_arg(*va, zval **); 462 if (return_null) { 463 *p = NULL; 464 break; 465 } 466 if (Z_TYPE_PP(arg) == IS_RESOURCE) { 467 *p = *arg; 468 } else { 469 return "resource"; 470 } 471 } 472 break; 473 case 'A': 474 case 'a': 475 { 476 zval **p = va_arg(*va, zval **); 477 if (return_null) { 478 *p = NULL; 479 break; 480 } 481 if (Z_TYPE_PP(arg) == IS_ARRAY || (c == 'A' && Z_TYPE_PP(arg) == IS_OBJECT)) { 482 *p = *arg; 483 } else { 484 return "array"; 485 } 486 } 487 break; 488 case 'H': 489 case 'h': 490 { 491 HashTable **p = va_arg(*va, HashTable **); 492 if (return_null) { 493 *p = NULL; 494 break; 495 } 496 if (Z_TYPE_PP(arg) == IS_ARRAY) { 497 *p = Z_ARRVAL_PP(arg); 498 } else if(c == 'H' && Z_TYPE_PP(arg) == IS_OBJECT) { 499 *p = HASH_OF(*arg); 500 if(*p == NULL) { 501 return "array"; 502 } 503 } else { 504 return "array"; 505 } 506 } 507 break; 508 509 case 'o': 510 { 511 zval **p = va_arg(*va, zval **); 512 if (return_null) { 513 *p = NULL; 514 break; 515 } 516 if (Z_TYPE_PP(arg) == IS_OBJECT) { 517 *p = *arg; 518 } else { 519 return "object"; 520 } 521 } 522 break; 523 524 case 'O': 525 { 526 zval **p = va_arg(*va, zval **); 527 zend_class_entry *ce = va_arg(*va, zend_class_entry *); 528 529 if (return_null) { 530 *p = NULL; 531 break; 532 } 533 if (Z_TYPE_PP(arg) == IS_OBJECT && 534 (!ce || instanceof_function(Z_OBJCE_PP(arg), ce TSRMLS_CC))) { 535 *p = *arg; 536 } else { 537 if (ce) { 538 return ce->name; 539 } else { 540 return "object"; 541 } 542 } 543 } 544 break; 545 546 case 'C': 547 { 548 zend_class_entry **lookup, **pce = va_arg(*va, zend_class_entry **); 549 zend_class_entry *ce_base = *pce; 550 551 if (return_null) { 552 *pce = NULL; 553 break; 554 } 555 convert_to_string_ex(arg); 556 if (zend_lookup_class(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &lookup TSRMLS_CC) == FAILURE) { 557 *pce = NULL; 558 } else { 559 *pce = *lookup; 560 } 561 if (ce_base) { 562 if ((!*pce || !instanceof_function(*pce, ce_base TSRMLS_CC))) { 563 zend_spprintf(error, 0, "to be a class name derived from %s, '%s' given", 564 ce_base->name, Z_STRVAL_PP(arg)); 565 *pce = NULL; 566 return ""; 567 } 568 } 569 if (!*pce) { 570 zend_spprintf(error, 0, "to be a valid class name, '%s' given", 571 Z_STRVAL_PP(arg)); 572 return ""; 573 } 574 break; 575 576 } 577 break; 578 579 case 'f': 580 { 581 zend_fcall_info *fci = va_arg(*va, zend_fcall_info *); 582 zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *); 583 char *is_callable_error = NULL; 584 585 if (return_null) { 586 fci->size = 0; 587 fcc->initialized = 0; 588 break; 589 } 590 591 if (zend_fcall_info_init(*arg, 0, fci, fcc, NULL, &is_callable_error TSRMLS_CC) == SUCCESS) { 592 if (is_callable_error) { 593 *severity = E_STRICT; 594 zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error); 595 efree(is_callable_error); 596 *spec = spec_walk; 597 return ""; 598 } 599 break; 600 } else { 601 if (is_callable_error) { 602 *severity = E_WARNING; 603 zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error); 604 efree(is_callable_error); 605 return ""; 606 } else { 607 return "valid callback"; 608 } 609 } 610 } 611 612 case 'z': 613 { 614 zval **p = va_arg(*va, zval **); 615 if (return_null) { 616 *p = NULL; 617 } else { 618 *p = *arg; 619 } 620 } 621 break; 622 623 case 'Z': 624 { 625 zval ***p = va_arg(*va, zval ***); 626 if (return_null) { 627 *p = NULL; 628 } else { 629 *p = arg; 630 } 631 } 632 break; 633 634 default: 635 return "unknown"; 636 } 637 638 *spec = spec_walk; 639 640 return NULL; 641} 642/* }}} */ 643 644static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int quiet TSRMLS_DC) /* {{{ */ 645{ 646 char *expected_type = NULL, *error = NULL; 647 int severity = E_WARNING; 648 649 expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity TSRMLS_CC); 650 if (expected_type) { 651 if (!quiet && (*expected_type || error)) { 652 char *space; 653 char *class_name = get_active_class_name(&space TSRMLS_CC); 654 655 if (error) { 656 zend_error(severity, "%s%s%s() expects parameter %d %s", 657 class_name, space, get_active_function_name(TSRMLS_C), arg_num, error); 658 efree(error); 659 } else { 660 zend_error(severity, "%s%s%s() expects parameter %d to be %s, %s given", 661 class_name, space, get_active_function_name(TSRMLS_C), arg_num, expected_type, 662 zend_zval_type_name(*arg)); 663 } 664 } 665 if (severity != E_STRICT) { 666 return FAILURE; 667 } 668 } 669 670 return SUCCESS; 671} 672/* }}} */ 673 674static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int flags TSRMLS_DC) /* {{{ */ 675{ 676 char *spec_walk; 677 int c, i; 678 int min_num_args = -1; 679 int max_num_args = 0; 680 int post_varargs = 0; 681 zval **arg; 682 int arg_count = (int)(zend_uintptr_t) *(zend_vm_stack_top(TSRMLS_C) - 1); 683 int quiet = flags & ZEND_PARSE_PARAMS_QUIET; 684 zend_bool have_varargs = 0; 685 zval ****varargs = NULL; 686 int *n_varargs = NULL; 687 688 for (spec_walk = type_spec; *spec_walk; spec_walk++) { 689 c = *spec_walk; 690 switch (c) { 691 case 's': 692 if (max_num_args < arg_count) { 693 arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - max_num_args)); 694 if (Z_TYPE_PP(arg) == IS_OBJECT) { 695 parse_arg_object_to_string(arg TSRMLS_CC); 696 } 697 } 698 /* break missing intentionally */ 699 case 'l': case 'd': 700 case 'H': case 'b': 701 case 'r': case 'a': 702 case 'o': case 'O': 703 case 'z': case 'Z': 704 case 'C': case 'h': 705 case 'f': case 'A': 706 max_num_args++; 707 break; 708 709 case '|': 710 min_num_args = max_num_args; 711 break; 712 713 case '/': 714 case '!': 715 /* Pass */ 716 break; 717 718 case '*': 719 case '+': 720 if (have_varargs) { 721 if (!quiet) { 722 zend_function *active_function = EG(current_execute_data)->function_state.function; 723 char *class_name = active_function->common.scope ? active_function->common.scope->name : ""; 724 zend_error(E_WARNING, "%s%s%s(): only one varargs specifier (* or +) is permitted", 725 class_name, 726 class_name[0] ? "::" : "", 727 active_function->common.function_name); 728 } 729 return FAILURE; 730 } 731 have_varargs = 1; 732 /* we expect at least one parameter in varargs */ 733 if (c == '+') { 734 max_num_args++; 735 } 736 /* mark the beginning of varargs */ 737 post_varargs = max_num_args; 738 break; 739 740 default: 741 if (!quiet) { 742 zend_function *active_function = EG(current_execute_data)->function_state.function; 743 char *class_name = active_function->common.scope ? active_function->common.scope->name : ""; 744 zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters", 745 class_name, 746 class_name[0] ? "::" : "", 747 active_function->common.function_name); 748 } 749 return FAILURE; 750 } 751 } 752 753 if (min_num_args < 0) { 754 min_num_args = max_num_args; 755 } 756 757 if (have_varargs) { 758 /* calculate how many required args are at the end of the specifier list */ 759 post_varargs = max_num_args - post_varargs; 760 max_num_args = -1; 761 } 762 763 if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) { 764 if (!quiet) { 765 zend_function *active_function = EG(current_execute_data)->function_state.function; 766 char *class_name = active_function->common.scope ? active_function->common.scope->name : ""; 767 zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given", 768 class_name, 769 class_name[0] ? "::" : "", 770 active_function->common.function_name, 771 min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most", 772 num_args < min_num_args ? min_num_args : max_num_args, 773 (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s", 774 num_args); 775 } 776 return FAILURE; 777 } 778 779 if (num_args > arg_count) { 780 zend_error(E_WARNING, "%s(): could not obtain parameters for parsing", 781 get_active_function_name(TSRMLS_C)); 782 return FAILURE; 783 } 784 785 i = 0; 786 while (num_args-- > 0) { 787 if (*type_spec == '|') { 788 type_spec++; 789 } 790 791 if (*type_spec == '*' || *type_spec == '+') { 792 int num_varargs = num_args + 1 - post_varargs; 793 794 /* eat up the passed in storage even if it won't be filled in with varargs */ 795 varargs = va_arg(*va, zval ****); 796 n_varargs = va_arg(*va, int *); 797 type_spec++; 798 799 if (num_varargs > 0) { 800 int iv = 0; 801 zval **p = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - i)); 802 803 *n_varargs = num_varargs; 804 805 /* allocate space for array and store args */ 806 *varargs = safe_emalloc(num_varargs, sizeof(zval **), 0); 807 while (num_varargs-- > 0) { 808 (*varargs)[iv++] = p++; 809 } 810 811 /* adjust how many args we have left and restart loop */ 812 num_args = num_args + 1 - iv; 813 i += iv; 814 continue; 815 } else { 816 *varargs = NULL; 817 *n_varargs = 0; 818 } 819 } 820 821 arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count-i)); 822 823 if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) { 824 /* clean up varargs array if it was used */ 825 if (varargs && *varargs) { 826 efree(*varargs); 827 *varargs = NULL; 828 } 829 return FAILURE; 830 } 831 i++; 832 } 833 834 return SUCCESS; 835} 836/* }}} */ 837 838#define RETURN_IF_ZERO_ARGS(num_args, type_spec, quiet) { \ 839 int __num_args = (num_args); \ 840 \ 841 if (0 == (type_spec)[0] && 0 != __num_args && !(quiet)) { \ 842 char *__space; \ 843 char * __class_name = get_active_class_name(&__space TSRMLS_CC); \ 844 zend_error(E_WARNING, "%s%s%s() expects exactly 0 parameters, %d given", \ 845 __class_name, __space, \ 846 get_active_function_name(TSRMLS_C), __num_args); \ 847 return FAILURE; \ 848 }\ 849} 850 851ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...) /* {{{ */ 852{ 853 va_list va; 854 int retval; 855 856 RETURN_IF_ZERO_ARGS(num_args, type_spec, flags & ZEND_PARSE_PARAMS_QUIET); 857 858 va_start(va, type_spec); 859 retval = zend_parse_va_args(num_args, type_spec, &va, flags TSRMLS_CC); 860 va_end(va); 861 862 return retval; 863} 864/* }}} */ 865 866ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...) /* {{{ */ 867{ 868 va_list va; 869 int retval; 870 871 RETURN_IF_ZERO_ARGS(num_args, type_spec, 0); 872 873 va_start(va, type_spec); 874 retval = zend_parse_va_args(num_args, type_spec, &va, 0 TSRMLS_CC); 875 va_end(va); 876 877 return retval; 878} 879/* }}} */ 880 881ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...) /* {{{ */ 882{ 883 va_list va; 884 int retval; 885 char *p = type_spec; 886 zval **object; 887 zend_class_entry *ce; 888 889 if (!this_ptr) { 890 RETURN_IF_ZERO_ARGS(num_args, p, 0); 891 892 va_start(va, type_spec); 893 retval = zend_parse_va_args(num_args, type_spec, &va, 0 TSRMLS_CC); 894 va_end(va); 895 } else { 896 p++; 897 RETURN_IF_ZERO_ARGS(num_args, p, 0); 898 899 va_start(va, type_spec); 900 901 object = va_arg(va, zval **); 902 ce = va_arg(va, zend_class_entry *); 903 *object = this_ptr; 904 905 if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) { 906 zend_error(E_CORE_ERROR, "%s::%s() must be derived from %s::%s", 907 ce->name, get_active_function_name(TSRMLS_C), Z_OBJCE_P(this_ptr)->name, get_active_function_name(TSRMLS_C)); 908 } 909 910 retval = zend_parse_va_args(num_args, p, &va, 0 TSRMLS_CC); 911 va_end(va); 912 } 913 return retval; 914} 915/* }}} */ 916 917ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...) /* {{{ */ 918{ 919 va_list va; 920 int retval; 921 char *p = type_spec; 922 zval **object; 923 zend_class_entry *ce; 924 int quiet = flags & ZEND_PARSE_PARAMS_QUIET; 925 926 if (!this_ptr) { 927 RETURN_IF_ZERO_ARGS(num_args, p, quiet); 928 929 va_start(va, type_spec); 930 retval = zend_parse_va_args(num_args, type_spec, &va, flags TSRMLS_CC); 931 va_end(va); 932 } else { 933 p++; 934 RETURN_IF_ZERO_ARGS(num_args, p, quiet); 935 936 va_start(va, type_spec); 937 938 object = va_arg(va, zval **); 939 ce = va_arg(va, zend_class_entry *); 940 *object = this_ptr; 941 942 if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) { 943 if (!quiet) { 944 zend_error(E_CORE_ERROR, "%s::%s() must be derived from %s::%s", 945 ce->name, get_active_function_name(TSRMLS_C), Z_OBJCE_P(this_ptr)->name, get_active_function_name(TSRMLS_C)); 946 } 947 va_end(va); 948 return FAILURE; 949 } 950 951 retval = zend_parse_va_args(num_args, p, &va, flags TSRMLS_CC); 952 va_end(va); 953 } 954 return retval; 955} 956/* }}} */ 957 958/* Argument parsing API -- andrei */ 959ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC) /* {{{ */ 960{ 961 ALLOC_HASHTABLE_REL(Z_ARRVAL_P(arg)); 962 963 _zend_hash_init(Z_ARRVAL_P(arg), size, NULL, ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC); 964 Z_TYPE_P(arg) = IS_ARRAY; 965 return SUCCESS; 966} 967/* }}} */ 968 969static int zend_merge_property(zval **value TSRMLS_DC, int num_args, va_list args, const zend_hash_key *hash_key) /* {{{ */ 970{ 971 /* which name should a numeric property have ? */ 972 if (hash_key->nKeyLength) { 973 zval *obj = va_arg(args, zval *); 974 zend_object_handlers *obj_ht = va_arg(args, zend_object_handlers *); 975 zval *member; 976 977 MAKE_STD_ZVAL(member); 978 ZVAL_STRINGL(member, hash_key->arKey, hash_key->nKeyLength-1, 1); 979 obj_ht->write_property(obj, member, *value TSRMLS_CC); 980 zval_ptr_dtor(&member); 981 } 982 return ZEND_HASH_APPLY_KEEP; 983} 984/* }}} */ 985 986/* This function should be called after the constructor has been called 987 * because it may call __set from the uninitialized object otherwise. */ 988ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC) /* {{{ */ 989{ 990 zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj); 991 zend_class_entry *old_scope = EG(scope); 992 993 EG(scope) = Z_OBJCE_P(obj); 994 zend_hash_apply_with_arguments(properties TSRMLS_CC, (apply_func_args_t)zend_merge_property, 2, obj, obj_ht); 995 EG(scope) = old_scope; 996 997 if (destroy_ht) { 998 zend_hash_destroy(properties); 999 FREE_HASHTABLE(properties); 1000 } 1001} 1002/* }}} */ 1003 1004ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ 1005{ 1006 if (!class_type->constants_updated || !CE_STATIC_MEMBERS(class_type)) { 1007 zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry); 1008 zend_class_entry *old_scope = *scope; 1009 1010 *scope = class_type; 1011 zend_hash_apply_with_argument(&class_type->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC); 1012 zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); 1013 1014 if (!CE_STATIC_MEMBERS(class_type)) { 1015 HashPosition pos; 1016 zval **p; 1017 1018 if (class_type->parent) { 1019 zend_update_class_constants(class_type->parent TSRMLS_CC); 1020 } 1021#if ZTS 1022 ALLOC_HASHTABLE(CG(static_members)[(zend_intptr_t)(class_type->static_members)]); 1023#else 1024 ALLOC_HASHTABLE(class_type->static_members); 1025#endif 1026 zend_hash_init(CE_STATIC_MEMBERS(class_type), zend_hash_num_elements(&class_type->default_static_members), NULL, ZVAL_PTR_DTOR, 0); 1027 1028 zend_hash_internal_pointer_reset_ex(&class_type->default_static_members, &pos); 1029 while (zend_hash_get_current_data_ex(&class_type->default_static_members, (void**)&p, &pos) == SUCCESS) { 1030 char *str_index; 1031 uint str_length; 1032 ulong num_index; 1033 zval **q; 1034 1035 zend_hash_get_current_key_ex(&class_type->default_static_members, &str_index, &str_length, &num_index, 0, &pos); 1036 if (Z_ISREF_PP(p) && 1037 class_type->parent && 1038 zend_hash_find(&class_type->parent->default_static_members, str_index, str_length, (void**)&q) == SUCCESS && 1039 *p == *q && 1040 zend_hash_find(CE_STATIC_MEMBERS(class_type->parent), str_index, str_length, (void**)&q) == SUCCESS 1041 ) { 1042 Z_ADDREF_PP(q); 1043 Z_SET_ISREF_PP(q); 1044 zend_hash_add(CE_STATIC_MEMBERS(class_type), str_index, str_length, (void**)q, sizeof(zval*), NULL); 1045 } else { 1046 zval *r; 1047 1048 ALLOC_ZVAL(r); 1049 *r = **p; 1050 INIT_PZVAL(r); 1051 zval_copy_ctor(r); 1052 zend_hash_add(CE_STATIC_MEMBERS(class_type), str_index, str_length, (void**)&r, sizeof(zval*), NULL); 1053 } 1054 zend_hash_move_forward_ex(&class_type->default_static_members, &pos); 1055 } 1056 } 1057 zend_hash_apply_with_argument(CE_STATIC_MEMBERS(class_type), (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); 1058 1059 *scope = old_scope; 1060 class_type->constants_updated = 1; 1061 } 1062} 1063/* }}} */ 1064 1065/* This function requires 'properties' to contain all props declared in the 1066 * class and all props being public. If only a subset is given or the class 1067 * has protected members then you need to merge the properties seperately by 1068 * calling zend_merge_properties(). */ 1069ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */ 1070{ 1071 zval *tmp; 1072 zend_object *object; 1073 1074 if (class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { 1075 char *what = class_type->ce_flags & ZEND_ACC_INTERFACE ? "interface" : "abstract class"; 1076 zend_error(E_ERROR, "Cannot instantiate %s %s", what, class_type->name); 1077 } 1078 1079 zend_update_class_constants(class_type TSRMLS_CC); 1080 1081 Z_TYPE_P(arg) = IS_OBJECT; 1082 if (class_type->create_object == NULL) { 1083 Z_OBJVAL_P(arg) = zend_objects_new(&object, class_type TSRMLS_CC); 1084 if (properties) { 1085 object->properties = properties; 1086 } else { 1087 ALLOC_HASHTABLE_REL(object->properties); 1088 zend_hash_init(object->properties, zend_hash_num_elements(&class_type->default_properties), NULL, ZVAL_PTR_DTOR, 0); 1089 zend_hash_copy(object->properties, &class_type->default_properties, zval_copy_property_ctor(class_type), (void *) &tmp, sizeof(zval *)); 1090 } 1091 } else { 1092 Z_OBJVAL_P(arg) = class_type->create_object(class_type TSRMLS_CC); 1093 } 1094 return SUCCESS; 1095} 1096/* }}} */ 1097 1098ZEND_API int _object_init_ex(zval *arg, zend_class_entry *class_type ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */ 1099{ 1100 return _object_and_properties_init(arg, class_type, 0 ZEND_FILE_LINE_RELAY_CC TSRMLS_CC); 1101} 1102/* }}} */ 1103 1104ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */ 1105{ 1106 return _object_init_ex(arg, zend_standard_class_def ZEND_FILE_LINE_RELAY_CC TSRMLS_CC); 1107} 1108/* }}} */ 1109 1110ZEND_API int add_assoc_function(zval *arg, const char *key, void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS)) /* {{{ */ 1111{ 1112 zend_error(E_WARNING, "add_assoc_function() is no longer supported"); 1113 return FAILURE; 1114} 1115/* }}} */ 1116 1117ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, long n) /* {{{ */ 1118{ 1119 zval *tmp; 1120 1121 MAKE_STD_ZVAL(tmp); 1122 ZVAL_LONG(tmp, n); 1123 1124 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); 1125} 1126/* }}} */ 1127 1128ZEND_API int add_assoc_null_ex(zval *arg, const char *key, uint key_len) /* {{{ */ 1129{ 1130 zval *tmp; 1131 1132 MAKE_STD_ZVAL(tmp); 1133 ZVAL_NULL(tmp); 1134 1135 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); 1136} 1137/* }}} */ 1138 1139ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, uint key_len, int b) /* {{{ */ 1140{ 1141 zval *tmp; 1142 1143 MAKE_STD_ZVAL(tmp); 1144 ZVAL_BOOL(tmp, b); 1145 1146 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); 1147} 1148/* }}} */ 1149 1150ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, uint key_len, int r) /* {{{ */ 1151{ 1152 zval *tmp; 1153 1154 MAKE_STD_ZVAL(tmp); 1155 ZVAL_RESOURCE(tmp, r); 1156 1157 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); 1158} 1159/* }}} */ 1160 1161ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, double d) /* {{{ */ 1162{ 1163 zval *tmp; 1164 1165 MAKE_STD_ZVAL(tmp); 1166 ZVAL_DOUBLE(tmp, d); 1167 1168 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); 1169} 1170/* }}} */ 1171 1172ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate) /* {{{ */ 1173{ 1174 zval *tmp; 1175 1176 MAKE_STD_ZVAL(tmp); 1177 ZVAL_STRING(tmp, str, duplicate); 1178 1179 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); 1180} 1181/* }}} */ 1182 1183ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length, int duplicate) /* {{{ */ 1184{ 1185 zval *tmp; 1186 1187 MAKE_STD_ZVAL(tmp); 1188 ZVAL_STRINGL(tmp, str, length, duplicate); 1189 1190 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); 1191} 1192/* }}} */ 1193 1194ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, uint key_len, zval *value) /* {{{ */ 1195{ 1196 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &value, sizeof(zval *), NULL); 1197} 1198/* }}} */ 1199 1200ZEND_API int add_index_long(zval *arg, ulong index, long n) /* {{{ */ 1201{ 1202 zval *tmp; 1203 1204 MAKE_STD_ZVAL(tmp); 1205 ZVAL_LONG(tmp, n); 1206 1207 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL); 1208} 1209/* }}} */ 1210 1211ZEND_API int add_index_null(zval *arg, ulong index) /* {{{ */ 1212{ 1213 zval *tmp; 1214 1215 MAKE_STD_ZVAL(tmp); 1216 ZVAL_NULL(tmp); 1217 1218 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL); 1219} 1220/* }}} */ 1221 1222ZEND_API int add_index_bool(zval *arg, ulong index, int b) /* {{{ */ 1223{ 1224 zval *tmp; 1225 1226 MAKE_STD_ZVAL(tmp); 1227 ZVAL_BOOL(tmp, b); 1228 1229 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL); 1230} 1231/* }}} */ 1232 1233ZEND_API int add_index_resource(zval *arg, ulong index, int r) /* {{{ */ 1234{ 1235 zval *tmp; 1236 1237 MAKE_STD_ZVAL(tmp); 1238 ZVAL_RESOURCE(tmp, r); 1239 1240 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL); 1241} 1242/* }}} */ 1243 1244ZEND_API int add_index_double(zval *arg, ulong index, double d) /* {{{ */ 1245{ 1246 zval *tmp; 1247 1248 MAKE_STD_ZVAL(tmp); 1249 ZVAL_DOUBLE(tmp, d); 1250 1251 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL); 1252} 1253/* }}} */ 1254 1255ZEND_API int add_index_string(zval *arg, ulong index, const char *str, int duplicate) /* {{{ */ 1256{ 1257 zval *tmp; 1258 1259 MAKE_STD_ZVAL(tmp); 1260 ZVAL_STRING(tmp, str, duplicate); 1261 1262 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL); 1263} 1264/* }}} */ 1265 1266ZEND_API int add_index_stringl(zval *arg, ulong index, const char *str, uint length, int duplicate) /* {{{ */ 1267{ 1268 zval *tmp; 1269 1270 MAKE_STD_ZVAL(tmp); 1271 ZVAL_STRINGL(tmp, str, length, duplicate); 1272 1273 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL); 1274} 1275/* }}} */ 1276 1277ZEND_API int add_index_zval(zval *arg, ulong index, zval *value) /* {{{ */ 1278{ 1279 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &value, sizeof(zval *), NULL); 1280} 1281/* }}} */ 1282 1283ZEND_API int add_next_index_long(zval *arg, long n) /* {{{ */ 1284{ 1285 zval *tmp; 1286 1287 MAKE_STD_ZVAL(tmp); 1288 ZVAL_LONG(tmp, n); 1289 1290 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL); 1291} 1292/* }}} */ 1293 1294ZEND_API int add_next_index_null(zval *arg) /* {{{ */ 1295{ 1296 zval *tmp; 1297 1298 MAKE_STD_ZVAL(tmp); 1299 ZVAL_NULL(tmp); 1300 1301 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL); 1302} 1303/* }}} */ 1304 1305ZEND_API int add_next_index_bool(zval *arg, int b) /* {{{ */ 1306{ 1307 zval *tmp; 1308 1309 MAKE_STD_ZVAL(tmp); 1310 ZVAL_BOOL(tmp, b); 1311 1312 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL); 1313} 1314/* }}} */ 1315 1316ZEND_API int add_next_index_resource(zval *arg, int r) /* {{{ */ 1317{ 1318 zval *tmp; 1319 1320 MAKE_STD_ZVAL(tmp); 1321 ZVAL_RESOURCE(tmp, r); 1322 1323 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL); 1324} 1325/* }}} */ 1326 1327ZEND_API int add_next_index_double(zval *arg, double d) /* {{{ */ 1328{ 1329 zval *tmp; 1330 1331 MAKE_STD_ZVAL(tmp); 1332 ZVAL_DOUBLE(tmp, d); 1333 1334 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL); 1335} 1336/* }}} */ 1337 1338ZEND_API int add_next_index_string(zval *arg, const char *str, int duplicate) /* {{{ */ 1339{ 1340 zval *tmp; 1341 1342 MAKE_STD_ZVAL(tmp); 1343 ZVAL_STRING(tmp, str, duplicate); 1344 1345 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL); 1346} 1347/* }}} */ 1348 1349ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length, int duplicate) /* {{{ */ 1350{ 1351 zval *tmp; 1352 1353 MAKE_STD_ZVAL(tmp); 1354 ZVAL_STRINGL(tmp, str, length, duplicate); 1355 1356 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL); 1357} 1358/* }}} */ 1359 1360ZEND_API int add_next_index_zval(zval *arg, zval *value) /* {{{ */ 1361{ 1362 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &value, sizeof(zval *), NULL); 1363} 1364/* }}} */ 1365 1366ZEND_API int add_get_assoc_string_ex(zval *arg, const char *key, uint key_len, const char *str, void **dest, int duplicate) /* {{{ */ 1367{ 1368 zval *tmp; 1369 1370 MAKE_STD_ZVAL(tmp); 1371 ZVAL_STRING(tmp, str, duplicate); 1372 1373 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest); 1374} 1375/* }}} */ 1376 1377ZEND_API int add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length, void **dest, int duplicate) /* {{{ */ 1378{ 1379 zval *tmp; 1380 1381 MAKE_STD_ZVAL(tmp); 1382 ZVAL_STRINGL(tmp, str, length, duplicate); 1383 1384 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest); 1385} 1386/* }}} */ 1387 1388ZEND_API int add_get_index_long(zval *arg, ulong index, long l, void **dest) /* {{{ */ 1389{ 1390 zval *tmp; 1391 1392 MAKE_STD_ZVAL(tmp); 1393 ZVAL_LONG(tmp, l); 1394 1395 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest); 1396} 1397/* }}} */ 1398 1399ZEND_API int add_get_index_double(zval *arg, ulong index, double d, void **dest) /* {{{ */ 1400{ 1401 zval *tmp; 1402 1403 MAKE_STD_ZVAL(tmp); 1404 ZVAL_DOUBLE(tmp, d); 1405 1406 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest); 1407} 1408/* }}} */ 1409 1410ZEND_API int add_get_index_string(zval *arg, ulong index, const char *str, void **dest, int duplicate) /* {{{ */ 1411{ 1412 zval *tmp; 1413 1414 MAKE_STD_ZVAL(tmp); 1415 ZVAL_STRING(tmp, str, duplicate); 1416 1417 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest); 1418} 1419/* }}} */ 1420 1421ZEND_API int add_get_index_stringl(zval *arg, ulong index, const char *str, uint length, void **dest, int duplicate) /* {{{ */ 1422{ 1423 zval *tmp; 1424 1425 MAKE_STD_ZVAL(tmp); 1426 ZVAL_STRINGL(tmp, str, length, duplicate); 1427 1428 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest); 1429} 1430/* }}} */ 1431 1432ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long n TSRMLS_DC) /* {{{ */ 1433{ 1434 zval *tmp; 1435 zval *z_key; 1436 1437 MAKE_STD_ZVAL(tmp); 1438 ZVAL_LONG(tmp, n); 1439 1440 MAKE_STD_ZVAL(z_key); 1441 ZVAL_STRINGL(z_key, key, key_len-1, 1); 1442 1443 Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC); 1444 zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */ 1445 zval_ptr_dtor(&z_key); 1446 return SUCCESS; 1447} 1448/* }}} */ 1449 1450ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, int b TSRMLS_DC) /* {{{ */ 1451{ 1452 zval *tmp; 1453 zval *z_key; 1454 1455 MAKE_STD_ZVAL(tmp); 1456 ZVAL_BOOL(tmp, b); 1457 1458 MAKE_STD_ZVAL(z_key); 1459 ZVAL_STRINGL(z_key, key, key_len-1, 1); 1460 1461 Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC); 1462 zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */ 1463 zval_ptr_dtor(&z_key); 1464 return SUCCESS; 1465} 1466/* }}} */ 1467 1468ZEND_API int add_property_null_ex(zval *arg, const char *key, uint key_len TSRMLS_DC) /* {{{ */ 1469{ 1470 zval *tmp; 1471 zval *z_key; 1472 1473 MAKE_STD_ZVAL(tmp); 1474 ZVAL_NULL(tmp); 1475 1476 MAKE_STD_ZVAL(z_key); 1477 ZVAL_STRINGL(z_key, key, key_len-1, 1); 1478 1479 Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC); 1480 zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */ 1481 zval_ptr_dtor(&z_key); 1482 return SUCCESS; 1483} 1484/* }}} */ 1485 1486ZEND_API int add_property_resource_ex(zval *arg, const char *key, uint key_len, long n TSRMLS_DC) /* {{{ */ 1487{ 1488 zval *tmp; 1489 zval *z_key; 1490 1491 MAKE_STD_ZVAL(tmp); 1492 ZVAL_RESOURCE(tmp, n); 1493 1494 MAKE_STD_ZVAL(z_key); 1495 ZVAL_STRINGL(z_key, key, key_len-1, 1); 1496 1497 Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC); 1498 zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */ 1499 zval_ptr_dtor(&z_key); 1500 return SUCCESS; 1501} 1502/* }}} */ 1503 1504ZEND_API int add_property_double_ex(zval *arg, const char *key, uint key_len, double d TSRMLS_DC) /* {{{ */ 1505{ 1506 zval *tmp; 1507 zval *z_key; 1508 1509 MAKE_STD_ZVAL(tmp); 1510 ZVAL_DOUBLE(tmp, d); 1511 1512 MAKE_STD_ZVAL(z_key); 1513 ZVAL_STRINGL(z_key, key, key_len-1, 1); 1514 1515 Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC); 1516 zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */ 1517 zval_ptr_dtor(&z_key); 1518 return SUCCESS; 1519} 1520/* }}} */ 1521 1522ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate TSRMLS_DC) /* {{{ */ 1523{ 1524 zval *tmp; 1525 zval *z_key; 1526 1527 MAKE_STD_ZVAL(tmp); 1528 ZVAL_STRING(tmp, str, duplicate); 1529 1530 MAKE_STD_ZVAL(z_key); 1531 ZVAL_STRINGL(z_key, key, key_len-1, 1); 1532 1533 Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC); 1534 zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */ 1535 zval_ptr_dtor(&z_key); 1536 return SUCCESS; 1537} 1538/* }}} */ 1539 1540ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length, int duplicate TSRMLS_DC) /* {{{ */ 1541{ 1542 zval *tmp; 1543 zval *z_key; 1544 1545 MAKE_STD_ZVAL(tmp); 1546 ZVAL_STRINGL(tmp, str, length, duplicate); 1547 1548 MAKE_STD_ZVAL(z_key); 1549 ZVAL_STRINGL(z_key, key, key_len-1, 1); 1550 1551 Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC); 1552 zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */ 1553 zval_ptr_dtor(&z_key); 1554 return SUCCESS; 1555} 1556/* }}} */ 1557 1558ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval *value TSRMLS_DC) /* {{{ */ 1559{ 1560 zval *z_key; 1561 1562 MAKE_STD_ZVAL(z_key); 1563 ZVAL_STRINGL(z_key, key, key_len-1, 1); 1564 1565 Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, value TSRMLS_CC); 1566 zval_ptr_dtor(&z_key); 1567 return SUCCESS; 1568} 1569/* }}} */ 1570 1571ZEND_API int zend_startup_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */ 1572{ 1573 int name_len; 1574 char *lcname; 1575 1576 if (module->module_started) { 1577 return SUCCESS; 1578 } 1579 module->module_started = 1; 1580 1581 /* Check module dependencies */ 1582 if (module->deps) { 1583 const zend_module_dep *dep = module->deps; 1584 1585 while (dep->name) { 1586 if (dep->type == MODULE_DEP_REQUIRED) { 1587 zend_module_entry *req_mod; 1588 1589 name_len = strlen(dep->name); 1590 lcname = zend_str_tolower_dup(dep->name, name_len); 1591 1592 if (zend_hash_find(&module_registry, lcname, name_len+1, (void**)&req_mod) == FAILURE || !req_mod->module_started) { 1593 efree(lcname); 1594 /* TODO: Check version relationship */ 1595 zend_error(E_CORE_WARNING, "Cannot load module '%s' because required module '%s' is not loaded", module->name, dep->name); 1596 module->module_started = 0; 1597 return FAILURE; 1598 } 1599 efree(lcname); 1600 } 1601 ++dep; 1602 } 1603 } 1604 1605 /* Initialize module globals */ 1606 if (module->globals_size) { 1607#ifdef ZTS 1608 ts_allocate_id(module->globals_id_ptr, module->globals_size, (ts_allocate_ctor) module->globals_ctor, (ts_allocate_dtor) module->globals_dtor); 1609#else 1610 if (module->globals_ctor) { 1611 module->globals_ctor(module->globals_ptr TSRMLS_CC); 1612 } 1613#endif 1614 } 1615 if (module->module_startup_func) { 1616 EG(current_module) = module; 1617 if (module->module_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) { 1618 zend_error(E_CORE_ERROR,"Unable to start %s module", module->name); 1619 EG(current_module) = NULL; 1620 return FAILURE; 1621 } 1622 EG(current_module) = NULL; 1623 } 1624 return SUCCESS; 1625} 1626/* }}} */ 1627 1628static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare TSRMLS_DC) /* {{{ */ 1629{ 1630 Bucket **b1 = base; 1631 Bucket **b2; 1632 Bucket **end = b1 + count; 1633 Bucket *tmp; 1634 zend_module_entry *m, *r; 1635 1636 while (b1 < end) { 1637try_again: 1638 m = (zend_module_entry*)(*b1)->pData; 1639 if (!m->module_started && m->deps) { 1640 const zend_module_dep *dep = m->deps; 1641 while (dep->name) { 1642 if (dep->type == MODULE_DEP_REQUIRED || dep->type == MODULE_DEP_OPTIONAL) { 1643 b2 = b1 + 1; 1644 while (b2 < end) { 1645 r = (zend_module_entry*)(*b2)->pData; 1646 if (strcasecmp(dep->name, r->name) == 0) { 1647 tmp = *b1; 1648 *b1 = *b2; 1649 *b2 = tmp; 1650 goto try_again; 1651 } 1652 b2++; 1653 } 1654 } 1655 dep++; 1656 } 1657 } 1658 b1++; 1659 } 1660} 1661/* }}} */ 1662 1663ZEND_API int zend_startup_modules(TSRMLS_D) /* {{{ */ 1664{ 1665 zend_hash_sort(&module_registry, zend_sort_modules, NULL, 0 TSRMLS_CC); 1666 zend_hash_apply(&module_registry, (apply_func_t)zend_startup_module_ex TSRMLS_CC); 1667 return SUCCESS; 1668} 1669/* }}} */ 1670 1671ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */ 1672{ 1673 int name_len; 1674 char *lcname; 1675 zend_module_entry *module_ptr; 1676 1677 if (!module) { 1678 return NULL; 1679 } 1680 1681#if 0 1682 zend_printf("%s: Registering module %d\n", module->name, module->module_number); 1683#endif 1684 1685 /* Check module dependencies */ 1686 if (module->deps) { 1687 const zend_module_dep *dep = module->deps; 1688 1689 while (dep->name) { 1690 if (dep->type == MODULE_DEP_CONFLICTS) { 1691 name_len = strlen(dep->name); 1692 lcname = zend_str_tolower_dup(dep->name, name_len); 1693 1694 if (zend_hash_exists(&module_registry, lcname, name_len+1)) { 1695 efree(lcname); 1696 /* TODO: Check version relationship */ 1697 zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded", module->name, dep->name); 1698 return NULL; 1699 } 1700 efree(lcname); 1701 } 1702 ++dep; 1703 } 1704 } 1705 1706 name_len = strlen(module->name); 1707 lcname = zend_str_tolower_dup(module->name, name_len); 1708 1709 if (zend_hash_add(&module_registry, lcname, name_len+1, (void *)module, sizeof(zend_module_entry), (void**)&module_ptr)==FAILURE) { 1710 zend_error(E_CORE_WARNING, "Module '%s' already loaded", module->name); 1711 efree(lcname); 1712 return NULL; 1713 } 1714 efree(lcname); 1715 module = module_ptr; 1716 EG(current_module) = module; 1717 1718 if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)==FAILURE) { 1719 EG(current_module) = NULL; 1720 zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name); 1721 return NULL; 1722 } 1723 1724 EG(current_module) = NULL; 1725 return module; 1726} 1727/* }}} */ 1728 1729ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module TSRMLS_DC) /* {{{ */ 1730{ 1731 module->module_number = zend_next_free_module(); 1732 module->type = MODULE_PERSISTENT; 1733 return zend_register_module_ex(module TSRMLS_CC); 1734} 1735/* }}} */ 1736 1737ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, int error_type TSRMLS_DC) /* {{{ */ 1738{ 1739 char lcname[16]; 1740 int name_len; 1741 1742 /* we don't care if the function name is longer, in fact lowercasing only 1743 * the beginning of the name speeds up the check process */ 1744 name_len = strlen(fptr->common.function_name); 1745 zend_str_tolower_copy(lcname, fptr->common.function_name, MIN(name_len, sizeof(lcname)-1)); 1746 lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */ 1747 1748 if (name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)) && fptr->common.num_args != 0) { 1749 zend_error(error_type, "Destructor %s::%s() cannot take arguments", ce->name, ZEND_DESTRUCTOR_FUNC_NAME); 1750 } else if (name_len == sizeof(ZEND_CLONE_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)) && fptr->common.num_args != 0) { 1751 zend_error(error_type, "Method %s::%s() cannot accept any arguments", ce->name, ZEND_CLONE_FUNC_NAME); 1752 } else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME))) { 1753 if (fptr->common.num_args != 1) { 1754 zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_GET_FUNC_NAME); 1755 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) { 1756 zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_GET_FUNC_NAME); 1757 } 1758 } else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME))) { 1759 if (fptr->common.num_args != 2) { 1760 zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_SET_FUNC_NAME); 1761 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) { 1762 zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_SET_FUNC_NAME); 1763 } 1764 } else if (name_len == sizeof(ZEND_UNSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME))) { 1765 if (fptr->common.num_args != 1) { 1766 zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_UNSET_FUNC_NAME); 1767 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) { 1768 zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_UNSET_FUNC_NAME); 1769 } 1770 } else if (name_len == sizeof(ZEND_ISSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME))) { 1771 if (fptr->common.num_args != 1) { 1772 zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_ISSET_FUNC_NAME); 1773 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) { 1774 zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_ISSET_FUNC_NAME); 1775 } 1776 } else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) { 1777 if (fptr->common.num_args != 2) { 1778 zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALL_FUNC_NAME); 1779 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) { 1780 zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_CALL_FUNC_NAME); 1781 } 1782 } else if (name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1 && 1783 !memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) 1784 ) { 1785 if (fptr->common.num_args != 2) { 1786 zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALLSTATIC_FUNC_NAME); 1787 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) { 1788 zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_CALLSTATIC_FUNC_NAME); 1789 } 1790 } else if (name_len == sizeof(ZEND_TOSTRING_FUNC_NAME) - 1 && 1791 !memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && fptr->common.num_args != 0 1792 ) { 1793 zend_error(error_type, "Method %s::%s() cannot take arguments", ce->name, ZEND_TOSTRING_FUNC_NAME); 1794 } 1795} 1796/* }}} */ 1797 1798/* registers all functions in *library_functions in the function hash */ 1799ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) /* {{{ */ 1800{ 1801 const zend_function_entry *ptr = functions; 1802 zend_function function, *reg_function; 1803 zend_internal_function *internal_function = (zend_internal_function *)&function; 1804 int count=0, unload=0; 1805 HashTable *target_function_table = function_table; 1806 int error_type; 1807 zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL; 1808 char *lowercase_name; 1809 int fname_len; 1810 char *lc_class_name = NULL; 1811 int class_name_len = 0; 1812 1813 if (type==MODULE_PERSISTENT) { 1814 error_type = E_CORE_WARNING; 1815 } else { 1816 error_type = E_WARNING; 1817 } 1818 1819 if (!target_function_table) { 1820 target_function_table = CG(function_table); 1821 } 1822 internal_function->type = ZEND_INTERNAL_FUNCTION; 1823 internal_function->module = EG(current_module); 1824 1825 if (scope) { 1826 class_name_len = strlen(scope->name); 1827 if ((lc_class_name = zend_memrchr(scope->name, '\\', class_name_len))) { 1828 ++lc_class_name; 1829 class_name_len -= (lc_class_name - scope->name); 1830 lc_class_name = zend_str_tolower_dup(lc_class_name, class_name_len); 1831 } else { 1832 lc_class_name = zend_str_tolower_dup(scope->name, class_name_len); 1833 } 1834 } 1835 1836 while (ptr->fname) { 1837 internal_function->handler = ptr->handler; 1838 internal_function->function_name = (char*)ptr->fname; 1839 internal_function->scope = scope; 1840 internal_function->prototype = NULL; 1841 if (ptr->arg_info) { 1842 internal_function->arg_info = (zend_arg_info*)ptr->arg_info+1; 1843 internal_function->num_args = ptr->num_args; 1844 /* Currently you cannot denote that the function can accept less arguments than num_args */ 1845 if (ptr->arg_info[0].required_num_args == -1) { 1846 internal_function->required_num_args = ptr->num_args; 1847 } else { 1848 internal_function->required_num_args = ptr->arg_info[0].required_num_args; 1849 } 1850 internal_function->pass_rest_by_reference = ptr->arg_info[0].pass_by_reference; 1851 internal_function->return_reference = ptr->arg_info[0].return_reference; 1852 } else { 1853 internal_function->arg_info = NULL; 1854 internal_function->num_args = 0; 1855 internal_function->required_num_args = 0; 1856 internal_function->pass_rest_by_reference = 0; 1857 internal_function->return_reference = 0; 1858 } 1859 if (ptr->flags) { 1860 if (!(ptr->flags & ZEND_ACC_PPP_MASK)) { 1861 if (ptr->flags != ZEND_ACC_DEPRECATED || scope) { 1862 zend_error(error_type, "Invalid access level for %s%s%s() - access must be exactly one of public, protected or private", scope ? scope->name : "", scope ? "::" : "", ptr->fname); 1863 } 1864 internal_function->fn_flags = ZEND_ACC_PUBLIC | ptr->flags; 1865 } else { 1866 internal_function->fn_flags = ptr->flags; 1867 } 1868 } else { 1869 internal_function->fn_flags = ZEND_ACC_PUBLIC; 1870 } 1871 if (ptr->flags & ZEND_ACC_ABSTRACT) { 1872 if (scope) { 1873 /* This is a class that must be abstract itself. Here we set the check info. */ 1874 scope->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS; 1875 if (!(scope->ce_flags & ZEND_ACC_INTERFACE)) { 1876 /* Since the class is not an interface it needs to be declared as a abstract class. */ 1877 /* Since here we are handling internal functions only we can add the keyword flag. */ 1878 /* This time we set the flag for the keyword 'abstract'. */ 1879 scope->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; 1880 } 1881 } 1882 if (ptr->flags & ZEND_ACC_STATIC && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) { 1883 zend_error(error_type, "Static function %s%s%s() cannot be abstract", scope ? scope->name : "", scope ? "::" : "", ptr->fname); 1884 } 1885 } else { 1886 if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) { 1887 efree(lc_class_name); 1888 zend_error(error_type, "Interface %s cannot contain non abstract method %s()", scope->name, ptr->fname); 1889 return FAILURE; 1890 } 1891 if (!internal_function->handler) { 1892 if (scope) { 1893 efree(lc_class_name); 1894 } 1895 zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? scope->name : "", scope ? "::" : "", ptr->fname); 1896 zend_unregister_functions(functions, count, target_function_table TSRMLS_CC); 1897 return FAILURE; 1898 } 1899 } 1900 fname_len = strlen(ptr->fname); 1901 lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len); 1902 if (zend_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)®_function) == FAILURE) { 1903 unload=1; 1904 efree(lowercase_name); 1905 break; 1906 } 1907 if (scope) { 1908 /* Look for ctor, dtor, clone 1909 * If it's an old-style constructor, store it only if we don't have 1910 * a constructor already. 1911 */ 1912 if ((fname_len == class_name_len) && !memcmp(lowercase_name, lc_class_name, class_name_len+1) && !ctor) { 1913 ctor = reg_function; 1914 } else if ((fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) { 1915 ctor = reg_function; 1916 } else if ((fname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME))) { 1917 dtor = reg_function; 1918 if (internal_function->num_args) { 1919 zend_error(error_type, "Destructor %s::%s() cannot take arguments", scope->name, ptr->fname); 1920 } 1921 } else if ((fname_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME))) { 1922 clone = reg_function; 1923 } else if ((fname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) { 1924 __call = reg_function; 1925 } else if ((fname_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME))) { 1926 __callstatic = reg_function; 1927 } else if ((fname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME))) { 1928 __tostring = reg_function; 1929 } else if ((fname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME))) { 1930 __get = reg_function; 1931 } else if ((fname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME))) { 1932 __set = reg_function; 1933 } else if ((fname_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME))) { 1934 __unset = reg_function; 1935 } else if ((fname_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME))) { 1936 __isset = reg_function; 1937 } else { 1938 reg_function = NULL; 1939 } 1940 if (reg_function) { 1941 zend_check_magic_method_implementation(scope, reg_function, error_type TSRMLS_CC); 1942 } 1943 } 1944 ptr++; 1945 count++; 1946 efree(lowercase_name); 1947 } 1948 if (unload) { /* before unloading, display all remaining bad function in the module */ 1949 if (scope) { 1950 efree(lc_class_name); 1951 } 1952 while (ptr->fname) { 1953 fname_len = strlen(ptr->fname); 1954 lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len); 1955 if (zend_hash_exists(target_function_table, lowercase_name, fname_len+1)) { 1956 zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? scope->name : "", scope ? "::" : "", ptr->fname); 1957 } 1958 efree(lowercase_name); 1959 ptr++; 1960 } 1961 zend_unregister_functions(functions, count, target_function_table TSRMLS_CC); 1962 return FAILURE; 1963 } 1964 if (scope) { 1965 scope->constructor = ctor; 1966 scope->destructor = dtor; 1967 scope->clone = clone; 1968 scope->__call = __call; 1969 scope->__callstatic = __callstatic; 1970 scope->__tostring = __tostring; 1971 scope->__get = __get; 1972 scope->__set = __set; 1973 scope->__unset = __unset; 1974 scope->__isset = __isset; 1975 if (ctor) { 1976 ctor->common.fn_flags |= ZEND_ACC_CTOR; 1977 if (ctor->common.fn_flags & ZEND_ACC_STATIC) { 1978 zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, ctor->common.function_name); 1979 } 1980 ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; 1981 } 1982 if (dtor) { 1983 dtor->common.fn_flags |= ZEND_ACC_DTOR; 1984 if (dtor->common.fn_flags & ZEND_ACC_STATIC) { 1985 zend_error(error_type, "Destructor %s::%s() cannot be static", scope->name, dtor->common.function_name); 1986 } 1987 dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; 1988 } 1989 if (clone) { 1990 clone->common.fn_flags |= ZEND_ACC_CLONE; 1991 if (clone->common.fn_flags & ZEND_ACC_STATIC) { 1992 zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, clone->common.function_name); 1993 } 1994 clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; 1995 } 1996 if (__call) { 1997 if (__call->common.fn_flags & ZEND_ACC_STATIC) { 1998 zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __call->common.function_name); 1999 } 2000 __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; 2001 } 2002 if (__callstatic) { 2003 if (!(__callstatic->common.fn_flags & ZEND_ACC_STATIC)) { 2004 zend_error(error_type, "Method %s::%s() must be static", scope->name, __callstatic->common.function_name); 2005 } 2006 __callstatic->common.fn_flags |= ZEND_ACC_STATIC; 2007 } 2008 if (__tostring) { 2009 if (__tostring->common.fn_flags & ZEND_ACC_STATIC) { 2010 zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __tostring->common.function_name); 2011 } 2012 __tostring->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; 2013 } 2014 if (__get) { 2015 if (__get->common.fn_flags & ZEND_ACC_STATIC) { 2016 zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __get->common.function_name); 2017 } 2018 __get->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; 2019 } 2020 if (__set) { 2021 if (__set->common.fn_flags & ZEND_ACC_STATIC) { 2022 zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __set->common.function_name); 2023 } 2024 __set->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; 2025 } 2026 if (__unset) { 2027 if (__unset->common.fn_flags & ZEND_ACC_STATIC) { 2028 zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __unset->common.function_name); 2029 } 2030 __unset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; 2031 } 2032 if (__isset) { 2033 if (__isset->common.fn_flags & ZEND_ACC_STATIC) { 2034 zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __isset->common.function_name); 2035 } 2036 __isset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; 2037 } 2038 efree(lc_class_name); 2039 } 2040 return SUCCESS; 2041} 2042/* }}} */ 2043 2044/* count=-1 means erase all functions, otherwise, 2045 * erase the first count functions 2046 */ 2047ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC) /* {{{ */ 2048{ 2049 const zend_function_entry *ptr = functions; 2050 int i=0; 2051 HashTable *target_function_table = function_table; 2052 2053 if (!target_function_table) { 2054 target_function_table = CG(function_table); 2055 } 2056 while (ptr->fname) { 2057 if (count!=-1 && i>=count) { 2058 break; 2059 } 2060#if 0 2061 zend_printf("Unregistering %s()\n", ptr->fname); 2062#endif 2063 zend_hash_del(target_function_table, ptr->fname, strlen(ptr->fname)+1); 2064 ptr++; 2065 i++; 2066 } 2067} 2068/* }}} */ 2069 2070ZEND_API int zend_startup_module(zend_module_entry *module) /* {{{ */ 2071{ 2072 TSRMLS_FETCH(); 2073 2074 if ((module = zend_register_internal_module(module TSRMLS_CC)) != NULL && zend_startup_module_ex(module TSRMLS_CC) == SUCCESS) { 2075 return SUCCESS; 2076 } 2077 return FAILURE; 2078} 2079/* }}} */ 2080 2081ZEND_API int zend_get_module_started(const char *module_name) /* {{{ */ 2082{ 2083 zend_module_entry *module; 2084 2085 return (zend_hash_find(&module_registry, module_name, strlen(module_name)+1, (void**)&module) == SUCCESS && module->module_started) ? SUCCESS : FAILURE; 2086} 2087/* }}} */ 2088 2089static int clean_module_class(const zend_class_entry **ce, int *module_number TSRMLS_DC) /* {{{ */ 2090{ 2091 if ((*ce)->type == ZEND_INTERNAL_CLASS && (*ce)->module->module_number == *module_number) { 2092 return ZEND_HASH_APPLY_REMOVE; 2093 } else { 2094 return ZEND_HASH_APPLY_KEEP; 2095 } 2096} 2097/* }}} */ 2098 2099static void clean_module_classes(int module_number TSRMLS_DC) /* {{{ */ 2100{ 2101 zend_hash_apply_with_argument(EG(class_table), (apply_func_arg_t) clean_module_class, (void *) &module_number TSRMLS_CC); 2102} 2103/* }}} */ 2104 2105void module_destructor(zend_module_entry *module) /* {{{ */ 2106{ 2107 TSRMLS_FETCH(); 2108 2109 if (module->type == MODULE_TEMPORARY) { 2110 zend_clean_module_rsrc_dtors(module->module_number TSRMLS_CC); 2111 clean_module_constants(module->module_number TSRMLS_CC); 2112 clean_module_classes(module->module_number TSRMLS_CC); 2113 } 2114 2115 if (module->module_started && module->module_shutdown_func) { 2116#if 0 2117 zend_printf("%s: Module shutdown\n", module->name); 2118#endif 2119 module->module_shutdown_func(module->type, module->module_number TSRMLS_CC); 2120 } 2121 2122 /* Deinitilaise module globals */ 2123 if (module->globals_size) { 2124#ifdef ZTS 2125 if (*module->globals_id_ptr) { 2126 ts_free_id(*module->globals_id_ptr); 2127 } 2128#else 2129 if (module->globals_dtor) { 2130 module->globals_dtor(module->globals_ptr TSRMLS_CC); 2131 } 2132#endif 2133 } 2134 2135 module->module_started=0; 2136 if (module->functions) { 2137 zend_unregister_functions(module->functions, -1, NULL TSRMLS_CC); 2138 } 2139 2140#if HAVE_LIBDL 2141#if !(defined(NETWARE) && defined(APACHE_1_BUILD)) 2142 if (module->handle && !getenv("ZEND_DONT_UNLOAD_MODULES")) { 2143 DL_UNLOAD(module->handle); 2144 } 2145#endif 2146#endif 2147} 2148/* }}} */ 2149 2150/* call request startup for all modules */ 2151int module_registry_request_startup(zend_module_entry *module TSRMLS_DC) /* {{{ */ 2152{ 2153 if (module->request_startup_func) { 2154#if 0 2155 zend_printf("%s: Request startup\n", module->name); 2156#endif 2157 if (module->request_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) { 2158 zend_error(E_WARNING, "request_startup() for %s module failed", module->name); 2159 exit(1); 2160 } 2161 } 2162 return 0; 2163} 2164/* }}} */ 2165 2166/* call request shutdown for all modules */ 2167int module_registry_cleanup(zend_module_entry *module TSRMLS_DC) /* {{{ */ 2168{ 2169 if (module->request_shutdown_func) { 2170#if 0 2171 zend_printf("%s: Request shutdown\n", module->name); 2172#endif 2173 module->request_shutdown_func(module->type, module->module_number TSRMLS_CC); 2174 } 2175 return 0; 2176} 2177/* }}} */ 2178 2179int module_registry_unload_temp(const zend_module_entry *module TSRMLS_DC) /* {{{ */ 2180{ 2181 return (module->type == MODULE_TEMPORARY) ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_STOP; 2182} 2183/* }}} */ 2184 2185/* return the next free module number */ 2186int zend_next_free_module(void) /* {{{ */ 2187{ 2188 return zend_hash_num_elements(&module_registry) + 1; 2189} 2190/* }}} */ 2191 2192static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, zend_uint ce_flags TSRMLS_DC) /* {{{ */ 2193{ 2194 zend_class_entry *class_entry = malloc(sizeof(zend_class_entry)); 2195 char *lowercase_name = malloc(orig_class_entry->name_length + 1); 2196 *class_entry = *orig_class_entry; 2197 2198 class_entry->type = ZEND_INTERNAL_CLASS; 2199 zend_initialize_class_data(class_entry, 0 TSRMLS_CC); 2200 class_entry->ce_flags = ce_flags; 2201 class_entry->module = EG(current_module); 2202 2203 if (class_entry->builtin_functions) { 2204 zend_register_functions(class_entry, class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC); 2205 } 2206 2207 zend_str_tolower_copy(lowercase_name, orig_class_entry->name, class_entry->name_length); 2208 zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL); 2209 free(lowercase_name); 2210 return class_entry; 2211} 2212/* }}} */ 2213 2214/* If parent_ce is not NULL then it inherits from parent_ce 2215 * If parent_ce is NULL and parent_name isn't then it looks for the parent and inherits from it 2216 * If both parent_ce and parent_name are NULL it does a regular class registration 2217 * If parent_name is specified but not found NULL is returned 2218 */ 2219ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce, char *parent_name TSRMLS_DC) /* {{{ */ 2220{ 2221 zend_class_entry *register_class; 2222 2223 if (!parent_ce && parent_name) { 2224 zend_class_entry **pce; 2225 if (zend_hash_find(CG(class_table), parent_name, strlen(parent_name)+1, (void **) &pce)==FAILURE) { 2226 return NULL; 2227 } else { 2228 parent_ce = *pce; 2229 } 2230 } 2231 2232 register_class = zend_register_internal_class(class_entry TSRMLS_CC); 2233 2234 if (parent_ce) { 2235 zend_do_inheritance(register_class, parent_ce TSRMLS_CC); 2236 } 2237 return register_class; 2238} 2239/* }}} */ 2240 2241ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int num_interfaces, ...) /* {{{ */ 2242{ 2243 zend_class_entry *interface_entry; 2244 va_list interface_list; 2245 va_start(interface_list, num_interfaces); 2246 2247 while (num_interfaces--) { 2248 interface_entry = va_arg(interface_list, zend_class_entry *); 2249 zend_do_implement_interface(class_entry, interface_entry TSRMLS_CC); 2250 } 2251 2252 va_end(interface_list); 2253} 2254/* }}} */ 2255 2256/* A class that contains at least one abstract method automatically becomes an abstract class. 2257 */ 2258ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry TSRMLS_DC) /* {{{ */ 2259{ 2260 return do_register_internal_class(orig_class_entry, 0 TSRMLS_CC); 2261} 2262/* }}} */ 2263 2264ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry TSRMLS_DC) /* {{{ */ 2265{ 2266 return do_register_internal_class(orig_class_entry, ZEND_ACC_INTERFACE TSRMLS_CC); 2267} 2268/* }}} */ 2269 2270ZEND_API int zend_register_class_alias_ex(const char *name, int name_len, zend_class_entry *ce TSRMLS_DC) /* {{{ */ 2271{ 2272 char *lcname = zend_str_tolower_dup(name, name_len); 2273 int ret; 2274 2275 ret = zend_hash_add(CG(class_table), lcname, name_len+1, &ce, sizeof(zend_class_entry *), NULL); 2276 efree(lcname); 2277 if (ret == SUCCESS) { 2278 ce->refcount++; 2279 } 2280 return ret; 2281} 2282/* }}} */ 2283 2284ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...) /* {{{ */ 2285{ 2286 HashTable *symbol_table; 2287 va_list symbol_table_list; 2288 2289 if (num_symbol_tables <= 0) return FAILURE; 2290 2291 Z_SET_ISREF_TO_P(symbol, is_ref); 2292 2293 va_start(symbol_table_list, num_symbol_tables); 2294 while (num_symbol_tables-- > 0) { 2295 symbol_table = va_arg(symbol_table_list, HashTable *); 2296 zend_hash_update(symbol_table, name, name_length + 1, &symbol, sizeof(zval *), NULL); 2297 zval_add_ref(&symbol); 2298 } 2299 va_end(symbol_table_list); 2300 return SUCCESS; 2301} 2302/* }}} */ 2303 2304/* Disabled functions support */ 2305 2306/* {{{ proto void display_disabled_function(void) 2307Dummy function which displays an error when a disabled function is called. */ 2308ZEND_API ZEND_FUNCTION(display_disabled_function) 2309{ 2310 zend_error(E_WARNING, "%s() has been disabled for security reasons", get_active_function_name(TSRMLS_C)); 2311} 2312/* }}} */ 2313 2314static zend_function_entry disabled_function[] = { 2315 ZEND_FE(display_disabled_function, NULL) 2316 ZEND_FE_END 2317}; 2318 2319ZEND_API int zend_disable_function(char *function_name, uint function_name_length TSRMLS_DC) /* {{{ */ 2320{ 2321 if (zend_hash_del(CG(function_table), function_name, function_name_length+1)==FAILURE) { 2322 return FAILURE; 2323 } 2324 disabled_function[0].fname = function_name; 2325 return zend_register_functions(NULL, disabled_function, CG(function_table), MODULE_PERSISTENT TSRMLS_CC); 2326} 2327/* }}} */ 2328 2329static zend_object_value display_disabled_class(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ 2330{ 2331 zend_object_value retval; 2332 zend_object *intern; 2333 retval = zend_objects_new(&intern, class_type TSRMLS_CC); 2334 ALLOC_HASHTABLE(intern->properties); 2335 zend_hash_init(intern->properties, 0, NULL, ZVAL_PTR_DTOR, 0); 2336 zend_error(E_WARNING, "%s() has been disabled for security reasons", class_type->name); 2337 return retval; 2338} 2339/* }}} */ 2340 2341static const zend_function_entry disabled_class_new[] = { 2342 ZEND_FE_END 2343}; 2344 2345ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_DC) /* {{{ */ 2346{ 2347 zend_class_entry **disabled_class; 2348 2349 zend_str_tolower(class_name, class_name_length); 2350 if (zend_hash_find(CG(class_table), class_name, class_name_length+1, (void **)&disabled_class)==FAILURE) { 2351 return FAILURE; 2352 } 2353 INIT_CLASS_ENTRY_INIT_METHODS((**disabled_class), disabled_class_new, NULL, NULL, NULL, NULL, NULL); 2354 (*disabled_class)->create_object = display_disabled_class; 2355 zend_hash_clean(&((*disabled_class)->function_table)); 2356 return SUCCESS; 2357} 2358/* }}} */ 2359 2360static int zend_is_callable_check_class(const char *name, int name_len, zend_fcall_info_cache *fcc, int *strict_class, char **error TSRMLS_DC) /* {{{ */ 2361{ 2362 int ret = 0; 2363 zend_class_entry **pce; 2364 char *lcname = zend_str_tolower_dup(name, name_len); 2365 2366 *strict_class = 0; 2367 if (name_len == sizeof("self") - 1 && 2368 !memcmp(lcname, "self", sizeof("self") - 1)) { 2369 if (!EG(scope)) { 2370 if (error) *error = estrdup("cannot access self:: when no class scope is active"); 2371 } else { 2372 fcc->called_scope = EG(called_scope); 2373 fcc->calling_scope = EG(scope); 2374 if (!fcc->object_ptr) { 2375 fcc->object_ptr = EG(This); 2376 } 2377 ret = 1; 2378 } 2379 } else if (name_len == sizeof("parent") - 1 && 2380 !memcmp(lcname, "parent", sizeof("parent") - 1)) { 2381 if (!EG(scope)) { 2382 if (error) *error = estrdup("cannot access parent:: when no class scope is active"); 2383 } else if (!EG(scope)->parent) { 2384 if (error) *error = estrdup("cannot access parent:: when current class scope has no parent"); 2385 } else { 2386 fcc->called_scope = EG(called_scope); 2387 fcc->calling_scope = EG(scope)->parent; 2388 if (!fcc->object_ptr) { 2389 fcc->object_ptr = EG(This); 2390 } 2391 *strict_class = 1; 2392 ret = 1; 2393 } 2394 } else if (name_len == sizeof("static") - 1 && 2395 !memcmp(lcname, "static", sizeof("static") - 1)) { 2396 if (!EG(called_scope)) { 2397 if (error) *error = estrdup("cannot access static:: when no class scope is active"); 2398 } else { 2399 fcc->called_scope = EG(called_scope); 2400 fcc->calling_scope = EG(called_scope); 2401 if (!fcc->object_ptr) { 2402 fcc->object_ptr = EG(This); 2403 } 2404 *strict_class = 1; 2405 ret = 1; 2406 } 2407 } else if (zend_lookup_class_ex(name, name_len, 1, &pce TSRMLS_CC) == SUCCESS) { 2408 zend_class_entry *scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL; 2409 2410 fcc->calling_scope = *pce; 2411 if (scope && !fcc->object_ptr && EG(This) && 2412 instanceof_function(Z_OBJCE_P(EG(This)), scope TSRMLS_CC) && 2413 instanceof_function(scope, fcc->calling_scope TSRMLS_CC)) { 2414 fcc->object_ptr = EG(This); 2415 fcc->called_scope = Z_OBJCE_P(fcc->object_ptr); 2416 } else { 2417 fcc->called_scope = fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : fcc->calling_scope; 2418 } 2419 *strict_class = 1; 2420 ret = 1; 2421 } else { 2422 if (error) zend_spprintf(error, 0, "class '%.*s' not found", name_len, name); 2423 } 2424 efree(lcname); 2425 return ret; 2426} 2427/* }}} */ 2428 2429static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fcall_info_cache *fcc, int strict_class, char **error TSRMLS_DC) /* {{{ */ 2430{ 2431 zend_class_entry *ce_org = fcc->calling_scope; 2432 int retval = 0; 2433 char *mname, *lmname, *colon; 2434 int clen, mlen; 2435 zend_class_entry *last_scope; 2436 HashTable *ftable; 2437 int call_via_handler = 0; 2438 2439 if (error) { 2440 *error = NULL; 2441 } 2442 2443 fcc->calling_scope = NULL; 2444 fcc->function_handler = NULL; 2445 2446 if (!ce_org) { 2447 /* Skip leading \ */ 2448 if (Z_STRVAL_P(callable)[0] == '\\') { 2449 mlen = Z_STRLEN_P(callable) - 1; 2450 lmname = zend_str_tolower_dup(Z_STRVAL_P(callable) + 1, mlen); 2451 } else { 2452 mlen = Z_STRLEN_P(callable); 2453 lmname = zend_str_tolower_dup(Z_STRVAL_P(callable), mlen); 2454 } 2455 /* Check if function with given name exists. 2456 * This may be a compound name that includes namespace name */ 2457 if (zend_hash_find(EG(function_table), lmname, mlen+1, (void**)&fcc->function_handler) == SUCCESS) { 2458 efree(lmname); 2459 return 1; 2460 } 2461 efree(lmname); 2462 } 2463 2464 /* Split name into class/namespace and method/function names */ 2465 if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL && 2466 colon > Z_STRVAL_P(callable) && 2467 *(colon-1) == ':' 2468 ) { 2469 colon--; 2470 clen = colon - Z_STRVAL_P(callable); 2471 mlen = Z_STRLEN_P(callable) - clen - 2; 2472 2473 if (colon == Z_STRVAL_P(callable)) { 2474 if (error) zend_spprintf(error, 0, "invalid function name"); 2475 return 0; 2476 } 2477 2478 /* This is a compound name. 2479 * Try to fetch class and then find static method. */ 2480 last_scope = EG(scope); 2481 if (ce_org) { 2482 EG(scope) = ce_org; 2483 } 2484 2485 if (!zend_is_callable_check_class(Z_STRVAL_P(callable), clen, fcc, &strict_class, error TSRMLS_CC)) { 2486 EG(scope) = last_scope; 2487 return 0; 2488 } 2489 EG(scope) = last_scope; 2490 2491 ftable = &fcc->calling_scope->function_table; 2492 if (ce_org && !instanceof_function(ce_org, fcc->calling_scope TSRMLS_CC)) { 2493 if (error) zend_spprintf(error, 0, "class '%s' is not a subclass of '%s'", ce_org->name, fcc->calling_scope->name); 2494 return 0; 2495 } 2496 mname = Z_STRVAL_P(callable) + clen + 2; 2497 } else if (ce_org) { 2498 /* Try to fetch find static method of given class. */ 2499 mlen = Z_STRLEN_P(callable); 2500 mname = Z_STRVAL_P(callable); 2501 ftable = &ce_org->function_table; 2502 fcc->calling_scope = ce_org; 2503 } else { 2504 /* We already checked for plain function before. */ 2505 if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) { 2506 zend_spprintf(error, 0, "function '%s' not found or invalid function name", Z_STRVAL_P(callable)); 2507 } 2508 return 0; 2509 } 2510 2511 lmname = zend_str_tolower_dup(mname, mlen); 2512 if (strict_class && 2513 fcc->calling_scope && 2514 mlen == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1 && 2515 !memcmp(lmname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) { 2516 fcc->function_handler = fcc->calling_scope->constructor; 2517 if (fcc->function_handler) { 2518 retval = 1; 2519 } 2520 } else if (zend_hash_find(ftable, lmname, mlen+1, (void**)&fcc->function_handler) == SUCCESS) { 2521 retval = 1; 2522 if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) && 2523 !strict_class && EG(scope) && 2524 instanceof_function(fcc->function_handler->common.scope, EG(scope) TSRMLS_CC)) { 2525 zend_function *priv_fbc; 2526 2527 if (zend_hash_find(&EG(scope)->function_table, lmname, mlen+1, (void **) &priv_fbc)==SUCCESS 2528 && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE 2529 && priv_fbc->common.scope == EG(scope)) { 2530 fcc->function_handler = priv_fbc; 2531 } 2532 } 2533 if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0 && 2534 (fcc->calling_scope && 2535 (fcc->calling_scope->__call || 2536 fcc->calling_scope->__callstatic))) { 2537 if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) { 2538 if (!zend_check_private(fcc->function_handler, fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : EG(scope), lmname, mlen TSRMLS_CC)) { 2539 retval = 0; 2540 fcc->function_handler = NULL; 2541 goto get_function_via_handler; 2542 } 2543 } else if (fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED) { 2544 if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) { 2545 retval = 0; 2546 fcc->function_handler = NULL; 2547 goto get_function_via_handler; 2548 } 2549 } 2550 } 2551 } else { 2552get_function_via_handler: 2553 if (fcc->object_ptr && fcc->calling_scope == ce_org) { 2554 if (strict_class && ce_org->__call) { 2555 fcc->function_handler = emalloc(sizeof(zend_internal_function)); 2556 fcc->function_handler->internal_function.type = ZEND_INTERNAL_FUNCTION; 2557 fcc->function_handler->internal_function.module = ce_org->module; 2558 fcc->function_handler->internal_function.handler = zend_std_call_user_call; 2559 fcc->function_handler->internal_function.arg_info = NULL; 2560 fcc->function_handler->internal_function.num_args = 0; 2561 fcc->function_handler->internal_function.scope = ce_org; 2562 fcc->function_handler->internal_function.fn_flags = ZEND_ACC_CALL_VIA_HANDLER; 2563 fcc->function_handler->internal_function.function_name = estrndup(mname, mlen); 2564 fcc->function_handler->internal_function.pass_rest_by_reference = 0; 2565 fcc->function_handler->internal_function.return_reference = ZEND_RETURN_VALUE; 2566 call_via_handler = 1; 2567 retval = 1; 2568 } else if (Z_OBJ_HT_P(fcc->object_ptr)->get_method) { 2569 fcc->function_handler = Z_OBJ_HT_P(fcc->object_ptr)->get_method(&fcc->object_ptr, mname, mlen TSRMLS_CC); 2570 if (fcc->function_handler) { 2571 if (strict_class && 2572 (!fcc->function_handler->common.scope || 2573 !instanceof_function(ce_org, fcc->function_handler->common.scope TSRMLS_CC))) { 2574 if ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) { 2575 if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) { 2576 efree(fcc->function_handler->common.function_name); 2577 } 2578 efree(fcc->function_handler); 2579 } 2580 } else { 2581 retval = 1; 2582 call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0; 2583 } 2584 } 2585 } 2586 } else if (fcc->calling_scope) { 2587 if (fcc->calling_scope->get_static_method) { 2588 fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, mname, mlen TSRMLS_CC); 2589 } else { 2590 fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, mname, mlen TSRMLS_CC); 2591 } 2592 if (fcc->function_handler) { 2593 retval = 1; 2594 call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0; 2595 if (call_via_handler && !fcc->object_ptr && EG(This) && 2596 Z_OBJ_HT_P(EG(This))->get_class_entry && 2597 instanceof_function(Z_OBJCE_P(EG(This)), fcc->calling_scope TSRMLS_CC)) { 2598 fcc->object_ptr = EG(This); 2599 } 2600 } 2601 } 2602 } 2603 2604 if (retval) { 2605 if (fcc->calling_scope && !call_via_handler) { 2606 if (!fcc->object_ptr && (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT)) { 2607 if (error) { 2608 zend_spprintf(error, 0, "cannot call abstract method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name); 2609 retval = 0; 2610 } else { 2611 zend_error(E_ERROR, "Cannot call abstract method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name); 2612 } 2613 } else if (!fcc->object_ptr && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) { 2614 int severity; 2615 char *verb; 2616 if (fcc->function_handler->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { 2617 severity = E_STRICT; 2618 verb = "should not"; 2619 } else { 2620 /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ 2621 severity = E_ERROR; 2622 verb = "cannot"; 2623 } 2624 if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0) { 2625 retval = 0; 2626 } 2627 if (EG(This) && instanceof_function(Z_OBJCE_P(EG(This)), fcc->calling_scope TSRMLS_CC)) { 2628 fcc->object_ptr = EG(This); 2629 if (error) { 2630 zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb, Z_OBJCE_P(EG(This))->name); 2631 if (severity == E_ERROR) { 2632 retval = 0; 2633 } 2634 } else if (retval) { 2635 zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb, Z_OBJCE_P(EG(This))->name); 2636 } 2637 } else { 2638 if (error) { 2639 zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb); 2640 if (severity == E_ERROR) { 2641 retval = 0; 2642 } 2643 } else if (retval) { 2644 zend_error(severity, "Non-static method %s::%s() %s be called statically", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb); 2645 } 2646 } 2647 } 2648 if (retval && (check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) { 2649 if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) { 2650 if (!zend_check_private(fcc->function_handler, fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : EG(scope), lmname, mlen TSRMLS_CC)) { 2651 if (error) { 2652 if (*error) { 2653 efree(*error); 2654 } 2655 zend_spprintf(error, 0, "cannot access private method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name); 2656 } 2657 retval = 0; 2658 } 2659 } else if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED)) { 2660 if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) { 2661 if (error) { 2662 if (*error) { 2663 efree(*error); 2664 } 2665 zend_spprintf(error, 0, "cannot access protected method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name); 2666 } 2667 retval = 0; 2668 } 2669 } 2670 } 2671 } 2672 } else if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) { 2673 if (fcc->calling_scope) { 2674 if (error) zend_spprintf(error, 0, "class '%s' does not have a method '%s'", fcc->calling_scope->name, mname); 2675 } else { 2676 if (error) zend_spprintf(error, 0, "function '%s' does not exist", mname); 2677 } 2678 } 2679 efree(lmname); 2680 2681 if (fcc->object_ptr) { 2682 fcc->called_scope = Z_OBJCE_P(fcc->object_ptr); 2683 } 2684 if (retval) { 2685 fcc->initialized = 1; 2686 } 2687 return retval; 2688} 2689/* }}} */ 2690 2691ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint check_flags, char **callable_name, int *callable_name_len, zend_fcall_info_cache *fcc, char **error TSRMLS_DC) /* {{{ */ 2692{ 2693 zend_bool ret; 2694 int callable_name_len_local; 2695 zend_fcall_info_cache fcc_local; 2696 2697 if (callable_name) { 2698 *callable_name = NULL; 2699 } 2700 if (callable_name_len == NULL) { 2701 callable_name_len = &callable_name_len_local; 2702 } 2703 if (fcc == NULL) { 2704 fcc = &fcc_local; 2705 } 2706 if (error) { 2707 *error = NULL; 2708 } 2709 2710 fcc->initialized = 0; 2711 fcc->calling_scope = NULL; 2712 fcc->called_scope = NULL; 2713 fcc->function_handler = NULL; 2714 fcc->calling_scope = NULL; 2715 fcc->object_ptr = NULL; 2716 2717 if (object_ptr && Z_TYPE_P(object_ptr) != IS_OBJECT) { 2718 object_ptr = NULL; 2719 } 2720 if (object_ptr && 2721 (!EG(objects_store).object_buckets || 2722 !EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(object_ptr)].valid)) { 2723 return 0; 2724 } 2725 2726 switch (Z_TYPE_P(callable)) { 2727 case IS_STRING: 2728 if (object_ptr) { 2729 fcc->object_ptr = object_ptr; 2730 fcc->calling_scope = Z_OBJCE_P(object_ptr); 2731 if (callable_name) { 2732 char *ptr; 2733 2734 *callable_name_len = fcc->calling_scope->name_length + Z_STRLEN_P(callable) + sizeof("::") - 1; 2735 ptr = *callable_name = emalloc(*callable_name_len + 1); 2736 memcpy(ptr, fcc->calling_scope->name, fcc->calling_scope->name_length); 2737 ptr += fcc->calling_scope->name_length; 2738 memcpy(ptr, "::", sizeof("::") - 1); 2739 ptr += sizeof("::") - 1; 2740 memcpy(ptr, Z_STRVAL_P(callable), Z_STRLEN_P(callable) + 1); 2741 } 2742 } else if (callable_name) { 2743 *callable_name = estrndup(Z_STRVAL_P(callable), Z_STRLEN_P(callable)); 2744 *callable_name_len = Z_STRLEN_P(callable); 2745 } 2746 if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) { 2747 fcc->called_scope = fcc->calling_scope; 2748 return 1; 2749 } 2750 2751 ret = zend_is_callable_check_func(check_flags, callable, fcc, 0, error TSRMLS_CC); 2752 if (fcc == &fcc_local && 2753 fcc->function_handler && 2754 ((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION && 2755 (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) || 2756 fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY || 2757 fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) { 2758 if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) { 2759 efree(fcc->function_handler->common.function_name); 2760 } 2761 efree(fcc->function_handler); 2762 } 2763 return ret; 2764 2765 case IS_ARRAY: 2766 { 2767 zval **method = NULL; 2768 zval **obj = NULL; 2769 int strict_class = 0; 2770 2771 if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) { 2772 zend_hash_index_find(Z_ARRVAL_P(callable), 0, (void **) &obj); 2773 zend_hash_index_find(Z_ARRVAL_P(callable), 1, (void **) &method); 2774 } 2775 if (obj && method && 2776 (Z_TYPE_PP(obj) == IS_OBJECT || 2777 Z_TYPE_PP(obj) == IS_STRING) && 2778 Z_TYPE_PP(method) == IS_STRING) { 2779 2780 if (Z_TYPE_PP(obj) == IS_STRING) { 2781 if (callable_name) { 2782 char *ptr; 2783 2784 *callable_name_len = Z_STRLEN_PP(obj) + Z_STRLEN_PP(method) + sizeof("::") - 1; 2785 ptr = *callable_name = emalloc(*callable_name_len + 1); 2786 memcpy(ptr, Z_STRVAL_PP(obj), Z_STRLEN_PP(obj)); 2787 ptr += Z_STRLEN_PP(obj); 2788 memcpy(ptr, "::", sizeof("::") - 1); 2789 ptr += sizeof("::") - 1; 2790 memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1); 2791 } 2792 2793 if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) { 2794 return 1; 2795 } 2796 2797 if (!zend_is_callable_check_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), fcc, &strict_class, error TSRMLS_CC)) { 2798 return 0; 2799 } 2800 2801 } else { 2802 if (!EG(objects_store).object_buckets || 2803 !EG(objects_store).object_buckets[Z_OBJ_HANDLE_PP(obj)].valid) { 2804 return 0; 2805 } 2806 2807 fcc->calling_scope = Z_OBJCE_PP(obj); /* TBFixed: what if it's overloaded? */ 2808 2809 fcc->object_ptr = *obj; 2810 2811 if (callable_name) { 2812 char *ptr; 2813 2814 *callable_name_len = fcc->calling_scope->name_length + Z_STRLEN_PP(method) + sizeof("::") - 1; 2815 ptr = *callable_name = emalloc(*callable_name_len + 1); 2816 memcpy(ptr, fcc->calling_scope->name, fcc->calling_scope->name_length); 2817 ptr += fcc->calling_scope->name_length; 2818 memcpy(ptr, "::", sizeof("::") - 1); 2819 ptr += sizeof("::") - 1; 2820 memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1); 2821 } 2822 2823 if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) { 2824 fcc->called_scope = fcc->calling_scope; 2825 return 1; 2826 } 2827 } 2828 2829 ret = zend_is_callable_check_func(check_flags, *method, fcc, strict_class, error TSRMLS_CC); 2830 if (fcc == &fcc_local && 2831 fcc->function_handler && 2832 ((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION && 2833 (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) || 2834 fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY || 2835 fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) { 2836 if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) { 2837 efree(fcc->function_handler->common.function_name); 2838 } 2839 efree(fcc->function_handler); 2840 } 2841 return ret; 2842 2843 } else { 2844 if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) { 2845 if (!obj || (Z_TYPE_PP(obj) != IS_STRING && Z_TYPE_PP(obj) != IS_OBJECT)) { 2846 if (error) zend_spprintf(error, 0, "first array member is not a valid class name or object"); 2847 } else { 2848 if (error) zend_spprintf(error, 0, "second array member is not a valid method"); 2849 } 2850 } else { 2851 if (error) zend_spprintf(error, 0, "array must have exactly two members"); 2852 } 2853 if (callable_name) { 2854 *callable_name = estrndup("Array", sizeof("Array")-1); 2855 *callable_name_len = sizeof("Array") - 1; 2856 } 2857 } 2858 } 2859 return 0; 2860 2861 case IS_OBJECT: 2862 if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(callable, &fcc->calling_scope, &fcc->function_handler, &fcc->object_ptr TSRMLS_CC) == SUCCESS) { 2863 fcc->called_scope = fcc->calling_scope; 2864 if (callable_name) { 2865 zend_class_entry *ce = Z_OBJCE_P(callable); /* TBFixed: what if it's overloaded? */ 2866 2867 *callable_name_len = ce->name_length + sizeof("::__invoke") - 1; 2868 *callable_name = emalloc(*callable_name_len + 1); 2869 memcpy(*callable_name, ce->name, ce->name_length); 2870 memcpy((*callable_name) + ce->name_length, "::__invoke", sizeof("::__invoke")); 2871 } 2872 return 1; 2873 } 2874 /* break missing intentionally */ 2875 2876 default: 2877 if (callable_name) { 2878 zval expr_copy; 2879 int use_copy; 2880 2881 zend_make_printable_zval(callable, &expr_copy, &use_copy); 2882 *callable_name = estrndup(Z_STRVAL(expr_copy), Z_STRLEN(expr_copy)); 2883 *callable_name_len = Z_STRLEN(expr_copy); 2884 zval_dtor(&expr_copy); 2885 } 2886 if (error) zend_spprintf(error, 0, "no array or string given"); 2887 return 0; 2888 } 2889} 2890/* }}} */ 2891 2892ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name TSRMLS_DC) /* {{{ */ 2893{ 2894 return zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, NULL, NULL TSRMLS_CC); 2895} 2896/* }}} */ 2897 2898ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC) /* {{{ */ 2899{ 2900 zend_fcall_info_cache fcc; 2901 2902 if (zend_is_callable_ex(callable, NULL, IS_CALLABLE_STRICT, callable_name, NULL, &fcc, NULL TSRMLS_CC)) { 2903 if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) { 2904 zval_dtor(callable); 2905 array_init(callable); 2906 add_next_index_string(callable, fcc.calling_scope->name, 1); 2907 add_next_index_string(callable, fcc.function_handler->common.function_name, 1); 2908 } 2909 if (fcc.function_handler && 2910 ((fcc.function_handler->type == ZEND_INTERNAL_FUNCTION && 2911 (fcc.function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) || 2912 fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY || 2913 fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION)) { 2914 if (fcc.function_handler->type != ZEND_OVERLOADED_FUNCTION) { 2915 efree(fcc.function_handler->common.function_name); 2916 } 2917 efree(fcc.function_handler); 2918 } 2919 return 1; 2920 } 2921 return 0; 2922} 2923/* }}} */ 2924 2925ZEND_API int zend_fcall_info_init(zval *callable, uint check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, char **callable_name, char **error TSRMLS_DC) /* {{{ */ 2926{ 2927 if (!zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, fcc, error TSRMLS_CC)) { 2928 return FAILURE; 2929 } 2930 2931 fci->size = sizeof(*fci); 2932 fci->function_table = fcc->calling_scope ? &fcc->calling_scope->function_table : EG(function_table); 2933 fci->object_ptr = fcc->object_ptr; 2934 fci->function_name = callable; 2935 fci->retval_ptr_ptr = NULL; 2936 fci->param_count = 0; 2937 fci->params = NULL; 2938 fci->no_separation = 1; 2939 fci->symbol_table = NULL; 2940 2941 return SUCCESS; 2942} 2943/* }}} */ 2944 2945ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) /* {{{ */ 2946{ 2947 if (fci->params) { 2948 if (free_mem) { 2949 efree(fci->params); 2950 fci->params = NULL; 2951 } 2952 } 2953 fci->param_count = 0; 2954} 2955/* }}} */ 2956 2957ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, int *param_count, zval ****params) /* {{{ */ 2958{ 2959 *param_count = fci->param_count; 2960 *params = fci->params; 2961 fci->param_count = 0; 2962 fci->params = NULL; 2963} 2964/* }}} */ 2965 2966ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count, zval ***params) /* {{{ */ 2967{ 2968 zend_fcall_info_args_clear(fci, 1); 2969 fci->param_count = param_count; 2970 fci->params = params; 2971} 2972/* }}} */ 2973 2974ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) /* {{{ */ 2975{ 2976 HashPosition pos; 2977 zval **arg, ***params; 2978 2979 zend_fcall_info_args_clear(fci, !args); 2980 2981 if (!args) { 2982 return SUCCESS; 2983 } 2984 2985 if (Z_TYPE_P(args) != IS_ARRAY) { 2986 return FAILURE; 2987 } 2988 2989 fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args)); 2990 fci->params = params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **)); 2991 2992 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos); 2993 while (zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void *) &arg, &pos) == SUCCESS) { 2994 *params++ = arg; 2995 zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos); 2996 } 2997 2998 return SUCCESS; 2999} 3000/* }}} */ 3001 3002ZEND_API int zend_fcall_info_argp(zend_fcall_info *fci TSRMLS_DC, int argc, zval ***argv) /* {{{ */ 3003{ 3004 int i; 3005 3006 if (argc < 0) { 3007 return FAILURE; 3008 } 3009 3010 zend_fcall_info_args_clear(fci, !argc); 3011 3012 if (argc) { 3013 fci->param_count = argc; 3014 fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **)); 3015 3016 for (i = 0; i < argc; ++i) { 3017 fci->params[i] = argv[i]; 3018 } 3019 } 3020 3021 return SUCCESS; 3022} 3023/* }}} */ 3024 3025ZEND_API int zend_fcall_info_argv(zend_fcall_info *fci TSRMLS_DC, int argc, va_list *argv) /* {{{ */ 3026{ 3027 int i; 3028 zval **arg; 3029 3030 if (argc < 0) { 3031 return FAILURE; 3032 } 3033 3034 zend_fcall_info_args_clear(fci, !argc); 3035 3036 if (argc) { 3037 fci->param_count = argc; 3038 fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **)); 3039 3040 for (i = 0; i < argc; ++i) { 3041 arg = va_arg(*argv, zval **); 3042 fci->params[i] = arg; 3043 } 3044 } 3045 3046 return SUCCESS; 3047} 3048/* }}} */ 3049 3050ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci TSRMLS_DC, int argc, ...) /* {{{ */ 3051{ 3052 int ret; 3053 va_list argv; 3054 3055 va_start(argv, argc); 3056 ret = zend_fcall_info_argv(fci TSRMLS_CC, argc, &argv); 3057 va_end(argv); 3058 3059 return ret; 3060} 3061/* }}} */ 3062 3063ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval **retval_ptr_ptr, zval *args TSRMLS_DC) /* {{{ */ 3064{ 3065 zval *retval, ***org_params = NULL; 3066 int result, org_count = 0; 3067 3068 fci->retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval; 3069 if (args) { 3070 zend_fcall_info_args_save(fci, &org_count, &org_params); 3071 zend_fcall_info_args(fci, args TSRMLS_CC); 3072 } 3073 result = zend_call_function(fci, fcc TSRMLS_CC); 3074 3075 if (!retval_ptr_ptr && retval) { 3076 zval_ptr_dtor(&retval); 3077 } 3078 if (args) { 3079 zend_fcall_info_args_restore(fci, org_count, org_params); 3080 } 3081 return result; 3082} 3083/* }}} */ 3084 3085ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */ 3086{ 3087 char *lname; 3088 int name_len = strlen(module_name); 3089 zend_module_entry *module; 3090 3091 lname = zend_str_tolower_dup(module_name, name_len); 3092 if (zend_hash_find(&module_registry, lname, name_len + 1, (void**)&module) == FAILURE) { 3093 efree(lname); 3094 return NULL; 3095 } 3096 efree(lname); 3097 return module->version; 3098} 3099/* }}} */ 3100 3101ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC) /* {{{ */ 3102{ 3103 zend_property_info property_info; 3104 HashTable *target_symbol_table; 3105 3106 if (!(access_type & ZEND_ACC_PPP_MASK)) { 3107 access_type |= ZEND_ACC_PUBLIC; 3108 } 3109 if (access_type & ZEND_ACC_STATIC) { 3110 target_symbol_table = &ce->default_static_members; 3111 } else { 3112 target_symbol_table = &ce->default_properties; 3113 } 3114 if (ce->type & ZEND_INTERNAL_CLASS) { 3115 switch(Z_TYPE_P(property)) { 3116 case IS_ARRAY: 3117 case IS_CONSTANT_ARRAY: 3118 case IS_OBJECT: 3119 case IS_RESOURCE: 3120 zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources"); 3121 break; 3122 default: 3123 break; 3124 } 3125 } 3126 switch (access_type & ZEND_ACC_PPP_MASK) { 3127 case ZEND_ACC_PRIVATE: { 3128 char *priv_name; 3129 int priv_name_length; 3130 3131 zend_mangle_property_name(&priv_name, &priv_name_length, ce->name, ce->name_length, name, name_length, ce->type & ZEND_INTERNAL_CLASS); 3132 zend_hash_update(target_symbol_table, priv_name, priv_name_length+1, &property, sizeof(zval *), NULL); 3133 property_info.name = priv_name; 3134 property_info.name_length = priv_name_length; 3135 } 3136 break; 3137 case ZEND_ACC_PROTECTED: { 3138 char *prot_name; 3139 int prot_name_length; 3140 3141 zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS); 3142 zend_hash_update(target_symbol_table, prot_name, prot_name_length+1, &property, sizeof(zval *), NULL); 3143 property_info.name = prot_name; 3144 property_info.name_length = prot_name_length; 3145 } 3146 break; 3147 case ZEND_ACC_PUBLIC: 3148 if (ce->parent) { 3149 char *prot_name; 3150 int prot_name_length; 3151 3152 zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS); 3153 zend_hash_del(target_symbol_table, prot_name, prot_name_length+1); 3154 pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS); 3155 } 3156 zend_hash_update(target_symbol_table, name, name_length+1, &property, sizeof(zval *), NULL); 3157 property_info.name = ce->type & ZEND_INTERNAL_CLASS ? zend_strndup(name, name_length) : estrndup(name, name_length); 3158 property_info.name_length = name_length; 3159 break; 3160 } 3161 property_info.flags = access_type; 3162 property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1); 3163 3164 property_info.doc_comment = doc_comment; 3165 property_info.doc_comment_len = doc_comment_len; 3166 3167 property_info.ce = ce; 3168 3169 zend_hash_update(&ce->properties_info, name, name_length + 1, &property_info, sizeof(zend_property_info), NULL); 3170 3171 return SUCCESS; 3172} 3173/* }}} */ 3174 3175ZEND_API int zend_declare_property(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type TSRMLS_DC) /* {{{ */ 3176{ 3177 return zend_declare_property_ex(ce, name, name_length, property, access_type, NULL, 0 TSRMLS_CC); 3178} 3179/* }}} */ 3180 3181ZEND_API int zend_declare_property_null(zend_class_entry *ce, char *name, int name_length, int access_type TSRMLS_DC) /* {{{ */ 3182{ 3183 zval *property; 3184 3185 if (ce->type & ZEND_INTERNAL_CLASS) { 3186 ALLOC_PERMANENT_ZVAL(property); 3187 } else { 3188 ALLOC_ZVAL(property); 3189 } 3190 INIT_ZVAL(*property); 3191 return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC); 3192} 3193/* }}} */ 3194 3195ZEND_API int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */ 3196{ 3197 zval *property; 3198 3199 if (ce->type & ZEND_INTERNAL_CLASS) { 3200 ALLOC_PERMANENT_ZVAL(property); 3201 } else { 3202 ALLOC_ZVAL(property); 3203 } 3204 INIT_PZVAL(property); 3205 ZVAL_BOOL(property, value); 3206 return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC); 3207} 3208/* }}} */ 3209 3210ZEND_API int zend_declare_property_long(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */ 3211{ 3212 zval *property; 3213 3214 if (ce->type & ZEND_INTERNAL_CLASS) { 3215 ALLOC_PERMANENT_ZVAL(property); 3216 } else { 3217 ALLOC_ZVAL(property); 3218 } 3219 INIT_PZVAL(property); 3220 ZVAL_LONG(property, value); 3221 return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC); 3222} 3223/* }}} */ 3224 3225ZEND_API int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC) /* {{{ */ 3226{ 3227 zval *property; 3228 3229 if (ce->type & ZEND_INTERNAL_CLASS) { 3230 ALLOC_PERMANENT_ZVAL(property); 3231 } else { 3232 ALLOC_ZVAL(property); 3233 } 3234 INIT_PZVAL(property); 3235 ZVAL_DOUBLE(property, value); 3236 return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC); 3237} 3238/* }}} */ 3239 3240ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int name_length, char *value, int access_type TSRMLS_DC) /* {{{ */ 3241{ 3242 zval *property; 3243 int len = strlen(value); 3244 3245 if (ce->type & ZEND_INTERNAL_CLASS) { 3246 ALLOC_PERMANENT_ZVAL(property); 3247 ZVAL_STRINGL(property, zend_strndup(value, len), len, 0); 3248 } else { 3249 ALLOC_ZVAL(property); 3250 ZVAL_STRINGL(property, value, len, 1); 3251 } 3252 INIT_PZVAL(property); 3253 return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC); 3254} 3255/* }}} */ 3256 3257ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, char *name, int name_length, char *value, int value_len, int access_type TSRMLS_DC) /* {{{ */ 3258{ 3259 zval *property; 3260 3261 if (ce->type & ZEND_INTERNAL_CLASS) { 3262 ALLOC_PERMANENT_ZVAL(property); 3263 ZVAL_STRINGL(property, zend_strndup(value, value_len), value_len, 0); 3264 } else { 3265 ALLOC_ZVAL(property); 3266 ZVAL_STRINGL(property, value, value_len, 1); 3267 } 3268 INIT_PZVAL(property); 3269 return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC); 3270} 3271/* }}} */ 3272 3273ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value TSRMLS_DC) /* {{{ */ 3274{ 3275 return zend_hash_update(&ce->constants_table, name, name_length+1, &value, sizeof(zval *), NULL); 3276} 3277/* }}} */ 3278 3279ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length TSRMLS_DC) /* {{{ */ 3280{ 3281 zval *constant; 3282 3283 if (ce->type & ZEND_INTERNAL_CLASS) { 3284 ALLOC_PERMANENT_ZVAL(constant); 3285 } else { 3286 ALLOC_ZVAL(constant); 3287 } 3288 ZVAL_NULL(constant); 3289 INIT_PZVAL(constant); 3290 return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC); 3291} 3292/* }}} */ 3293 3294ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, long value TSRMLS_DC) /* {{{ */ 3295{ 3296 zval *constant; 3297 3298 if (ce->type & ZEND_INTERNAL_CLASS) { 3299 ALLOC_PERMANENT_ZVAL(constant); 3300 } else { 3301 ALLOC_ZVAL(constant); 3302 } 3303 ZVAL_LONG(constant, value); 3304 INIT_PZVAL(constant); 3305 return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC); 3306} 3307/* }}} */ 3308 3309ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_bool value TSRMLS_DC) /* {{{ */ 3310{ 3311 zval *constant; 3312 3313 if (ce->type & ZEND_INTERNAL_CLASS) { 3314 ALLOC_PERMANENT_ZVAL(constant); 3315 } else { 3316 ALLOC_ZVAL(constant); 3317 } 3318 ZVAL_BOOL(constant, value); 3319 INIT_PZVAL(constant); 3320 return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC); 3321} 3322/* }}} */ 3323 3324ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value TSRMLS_DC) /* {{{ */ 3325{ 3326 zval *constant; 3327 3328 if (ce->type & ZEND_INTERNAL_CLASS) { 3329 ALLOC_PERMANENT_ZVAL(constant); 3330 } else { 3331 ALLOC_ZVAL(constant); 3332 } 3333 ZVAL_DOUBLE(constant, value); 3334 INIT_PZVAL(constant); 3335 return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC); 3336} 3337/* }}} */ 3338 3339ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length TSRMLS_DC) /* {{{ */ 3340{ 3341 zval *constant; 3342 3343 if (ce->type & ZEND_INTERNAL_CLASS) { 3344 ALLOC_PERMANENT_ZVAL(constant); 3345 ZVAL_STRINGL(constant, zend_strndup(value, value_length), value_length, 0); 3346 } else { 3347 ALLOC_ZVAL(constant); 3348 ZVAL_STRINGL(constant, value, value_length, 1); 3349 } 3350 INIT_PZVAL(constant); 3351 return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC); 3352} 3353/* }}} */ 3354 3355ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value TSRMLS_DC) /* {{{ */ 3356{ 3357 return zend_declare_class_constant_stringl(ce, name, name_length, value, strlen(value) TSRMLS_CC); 3358} 3359/* }}} */ 3360 3361ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */ 3362{ 3363 zval *property; 3364 zend_class_entry *old_scope = EG(scope); 3365 3366 EG(scope) = scope; 3367 3368 if (!Z_OBJ_HT_P(object)->write_property) { 3369 char *class_name; 3370 zend_uint class_name_len; 3371 3372 zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC); 3373 3374 zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, class_name); 3375 } 3376 MAKE_STD_ZVAL(property); 3377 ZVAL_STRINGL(property, name, name_length, 1); 3378 Z_OBJ_HT_P(object)->write_property(object, property, value TSRMLS_CC); 3379 zval_ptr_dtor(&property); 3380 3381 EG(scope) = old_scope; 3382} 3383/* }}} */ 3384 3385ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, char *name, int name_length TSRMLS_DC) /* {{{ */ 3386{ 3387 zval *tmp; 3388 3389 ALLOC_ZVAL(tmp); 3390 Z_UNSET_ISREF_P(tmp); 3391 Z_SET_REFCOUNT_P(tmp, 0); 3392 ZVAL_NULL(tmp); 3393 zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC); 3394} 3395/* }}} */ 3396 3397ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC) /* {{{ */ 3398{ 3399 zval *tmp; 3400 3401 ALLOC_ZVAL(tmp); 3402 Z_UNSET_ISREF_P(tmp); 3403 Z_SET_REFCOUNT_P(tmp, 0); 3404 ZVAL_BOOL(tmp, value); 3405 zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC); 3406} 3407/* }}} */ 3408 3409ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC) /* {{{ */ 3410{ 3411 zval *tmp; 3412 3413 ALLOC_ZVAL(tmp); 3414 Z_UNSET_ISREF_P(tmp); 3415 Z_SET_REFCOUNT_P(tmp, 0); 3416 ZVAL_LONG(tmp, value); 3417 zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC); 3418} 3419/* }}} */ 3420 3421ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC) /* {{{ */ 3422{ 3423 zval *tmp; 3424 3425 ALLOC_ZVAL(tmp); 3426 Z_UNSET_ISREF_P(tmp); 3427 Z_SET_REFCOUNT_P(tmp, 0); 3428 ZVAL_DOUBLE(tmp, value); 3429 zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC); 3430} 3431/* }}} */ 3432 3433ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */ 3434{ 3435 zval *tmp; 3436 3437 ALLOC_ZVAL(tmp); 3438 Z_UNSET_ISREF_P(tmp); 3439 Z_SET_REFCOUNT_P(tmp, 0); 3440 ZVAL_STRING(tmp, value, 1); 3441 zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC); 3442} 3443/* }}} */ 3444 3445ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */ 3446{ 3447 zval *tmp; 3448 3449 ALLOC_ZVAL(tmp); 3450 Z_UNSET_ISREF_P(tmp); 3451 Z_SET_REFCOUNT_P(tmp, 0); 3452 ZVAL_STRINGL(tmp, value, value_len, 1); 3453 zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC); 3454} 3455/* }}} */ 3456 3457ZEND_API int zend_update_static_property(zend_class_entry *scope, char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */ 3458{ 3459 zval **property; 3460 zend_class_entry *old_scope = EG(scope); 3461 3462 EG(scope) = scope; 3463 property = zend_std_get_static_property(scope, name, name_length, 0 TSRMLS_CC); 3464 EG(scope) = old_scope; 3465 if (!property) { 3466 return FAILURE; 3467 } else { 3468 if (*property != value) { 3469 if (PZVAL_IS_REF(*property)) { 3470 zval_dtor(*property); 3471 Z_TYPE_PP(property) = Z_TYPE_P(value); 3472 (*property)->value = value->value; 3473 if (Z_REFCOUNT_P(value) > 0) { 3474 zval_copy_ctor(*property); 3475 } else { 3476 efree(value); 3477 } 3478 } else { 3479 zval *garbage = *property; 3480 3481 Z_ADDREF_P(value); 3482 if (PZVAL_IS_REF(value)) { 3483 SEPARATE_ZVAL(&value); 3484 } 3485 *property = value; 3486 zval_ptr_dtor(&garbage); 3487 } 3488 } 3489 return SUCCESS; 3490 } 3491} 3492/* }}} */ 3493 3494ZEND_API int zend_update_static_property_null(zend_class_entry *scope, char *name, int name_length TSRMLS_DC) /* {{{ */ 3495{ 3496 zval *tmp; 3497 3498 ALLOC_ZVAL(tmp); 3499 Z_UNSET_ISREF_P(tmp); 3500 Z_SET_REFCOUNT_P(tmp, 0); 3501 ZVAL_NULL(tmp); 3502 return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC); 3503} 3504/* }}} */ 3505 3506ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC) /* {{{ */ 3507{ 3508 zval *tmp; 3509 3510 ALLOC_ZVAL(tmp); 3511 Z_UNSET_ISREF_P(tmp); 3512 Z_SET_REFCOUNT_P(tmp, 0); 3513 ZVAL_BOOL(tmp, value); 3514 return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC); 3515} 3516/* }}} */ 3517 3518ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC) /* {{{ */ 3519{ 3520 zval *tmp; 3521 3522 ALLOC_ZVAL(tmp); 3523 Z_UNSET_ISREF_P(tmp); 3524 Z_SET_REFCOUNT_P(tmp, 0); 3525 ZVAL_LONG(tmp, value); 3526 return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC); 3527} 3528/* }}} */ 3529 3530ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *name, int name_length, double value TSRMLS_DC) /* {{{ */ 3531{ 3532 zval *tmp; 3533 3534 ALLOC_ZVAL(tmp); 3535 Z_UNSET_ISREF_P(tmp); 3536 Z_SET_REFCOUNT_P(tmp, 0); 3537 ZVAL_DOUBLE(tmp, value); 3538 return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC); 3539} 3540/* }}} */ 3541 3542ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */ 3543{ 3544 zval *tmp; 3545 3546 ALLOC_ZVAL(tmp); 3547 Z_UNSET_ISREF_P(tmp); 3548 Z_SET_REFCOUNT_P(tmp, 0); 3549 ZVAL_STRING(tmp, value, 1); 3550 return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC); 3551} 3552/* }}} */ 3553 3554ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */ 3555{ 3556 zval *tmp; 3557 3558 ALLOC_ZVAL(tmp); 3559 Z_UNSET_ISREF_P(tmp); 3560 Z_SET_REFCOUNT_P(tmp, 0); 3561 ZVAL_STRINGL(tmp, value, value_len, 1); 3562 return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC); 3563} 3564/* }}} */ 3565 3566ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */ 3567{ 3568 zval *property, *value; 3569 zend_class_entry *old_scope = EG(scope); 3570 3571 EG(scope) = scope; 3572 3573 if (!Z_OBJ_HT_P(object)->read_property) { 3574 char *class_name; 3575 zend_uint class_name_len; 3576 3577 zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC); 3578 zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", name, class_name); 3579 } 3580 3581 MAKE_STD_ZVAL(property); 3582 ZVAL_STRINGL(property, name, name_length, 1); 3583 value = Z_OBJ_HT_P(object)->read_property(object, property, silent?BP_VAR_IS:BP_VAR_R TSRMLS_CC); 3584 zval_ptr_dtor(&property); 3585 3586 EG(scope) = old_scope; 3587 return value; 3588} 3589/* }}} */ 3590 3591ZEND_API zval *zend_read_static_property(zend_class_entry *scope, char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */ 3592{ 3593 zval **property; 3594 zend_class_entry *old_scope = EG(scope); 3595 3596 EG(scope) = scope; 3597 property = zend_std_get_static_property(scope, name, name_length, silent TSRMLS_CC); 3598 EG(scope) = old_scope; 3599 3600 return property?*property:NULL; 3601} 3602/* }}} */ 3603 3604ZEND_API void zend_save_error_handling(zend_error_handling *current TSRMLS_DC) /* {{{ */ 3605{ 3606 current->handling = EG(error_handling); 3607 current->exception = EG(exception_class); 3608 current->user_handler = EG(user_error_handler); 3609 if (current->user_handler) { 3610 Z_ADDREF_P(current->user_handler); 3611 } 3612} 3613/* }}} */ 3614 3615ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current TSRMLS_DC) /* {{{ */ 3616{ 3617 if (current) { 3618 zend_save_error_handling(current TSRMLS_CC); 3619 if (error_handling != EH_NORMAL && EG(user_error_handler)) { 3620 zval_ptr_dtor(&EG(user_error_handler)); 3621 EG(user_error_handler) = NULL; 3622 } 3623 } 3624 EG(error_handling) = error_handling; 3625 EG(exception_class) = error_handling == EH_THROW ? exception_class : NULL; 3626} 3627/* }}} */ 3628 3629ZEND_API void zend_restore_error_handling(zend_error_handling *saved TSRMLS_DC) /* {{{ */ 3630{ 3631 EG(error_handling) = saved->handling; 3632 EG(exception_class) = saved->handling == EH_THROW ? saved->exception : NULL; 3633 if (saved->user_handler && saved->user_handler != EG(user_error_handler)) { 3634 if (EG(user_error_handler)) { 3635 zval_ptr_dtor(&EG(user_error_handler)); 3636 } 3637 EG(user_error_handler) = saved->user_handler; 3638 } else if (saved->user_handler) { 3639 zval_ptr_dtor(&saved->user_handler); 3640 } 3641 saved->user_handler = NULL; 3642} 3643/* }}} */ 3644 3645/* 3646 * Local variables: 3647 * tab-width: 4 3648 * c-basic-offset: 4 3649 * indent-tabs-mode: t 3650 * End: 3651 */ 3652