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