예제 #1
0
파일: fcall.c 프로젝트: andont/zephir
/**
 * Checks if a method is callable
 */
static int zephir_alt_is_callable_check_method(zend_class_entry *ce, int check_flags, char *method_name, unsigned int method_len, zend_fcall_info_cache *fcc, char **error, unsigned long method_key TSRMLS_DC)
{
	int retval = 0;

	#ifndef ZEPHIR_RELEASE
	int call_via_handler = 0;
	#endif

	if (error) {
		*error = NULL;
	}

	if (!method_key) {
		method_key = zend_inline_hash_func(method_name, method_len + 1);
	}

	/* Try to fetch find static method of given class. */
	if (likely(zephir_hash_quick_find(&ce->function_table, method_name, method_len + 1, method_key, (void**) &fcc->function_handler) == SUCCESS)) {
		retval = 1;
		if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) && ZEPHIR_EG(scope) && instanceof_function(fcc->function_handler->common.scope, EG(scope) TSRMLS_CC)) {
			zend_function *priv_fbc;
			if (zephir_hash_quick_find(&ZEPHIR_EG(scope)->function_table, method_name, method_len + 1, method_key, (void **) &priv_fbc)==SUCCESS && (priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE) && priv_fbc->common.scope == EG(scope)) {
				fcc->function_handler = priv_fbc;
			}
		}
		#ifndef ZEPHIR_RELEASE
		if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0 && (fcc->calling_scope && (fcc->calling_scope->__call || fcc->calling_scope->__callstatic))) {
			if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
				if (!zend_check_private(fcc->function_handler, ce, method_name, method_len TSRMLS_CC)) {
					retval = 0;
					fcc->function_handler = NULL;
					goto get_function_via_handler;
				}
			} else {
				if (fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED) {
					if (!zend_check_protected(fcc->function_handler->common.scope, ZEPHIR_EG(scope))) {
						retval = 0;
						fcc->function_handler = NULL;
						goto get_function_via_handler;
					}
				}
			}
		}
		#endif
	} else {
		#ifndef ZEPHIR_RELEASE
		get_function_via_handler:
		if (Z_OBJ_HT_P(fcc->object_ptr)->get_method) {
			#if PHP_VERSION_ID < 50400
			fcc->function_handler = Z_OBJ_HT_P(fcc->object_ptr)->get_method(&fcc->object_ptr, method_name, method_len TSRMLS_CC);
			#else
			fcc->function_handler = Z_OBJ_HT_P(fcc->object_ptr)->get_method(&fcc->object_ptr, method_name, method_len, NULL TSRMLS_CC);
			#endif
			if (fcc->function_handler) {
				retval = 1;
				call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
			}
		}
		#endif
	}

	if (retval) {
		#ifndef ZEPHIR_RELEASE
		if (fcc->calling_scope && !call_via_handler) {
			if (!fcc->object_ptr && (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT)) {
				if (error) {
					zephir_spprintf(error, 0, "cannot call abstract method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
					retval = 0;
				} else {
					zend_error(E_ERROR, "Cannot call abstract method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
				}
			}
			if (retval && (check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) {
				if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
					if (!zend_check_private(fcc->function_handler, ce, method_name, method_len TSRMLS_CC)) {
						if (error) {
							if (*error) {
								efree(*error);
							}
							zephir_spprintf(error, 0, "cannot access private method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
						}
						retval = 0;
					}
				} else {
					if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED)) {
						if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
							if (error) {
								if (*error) {
									efree(*error);
								}
								zephir_spprintf(error, 0, "cannot access protected method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
							}
							retval = 0;
						}
					}
				}
			}
		}
		#endif
	} else {
		if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
			if (fcc->calling_scope) {
				if (error) {
					zephir_spprintf(error, 0, "class '%s' does not have a method '%s'", fcc->calling_scope->name, method_name);
				}
			} else {
				if (error) {
					zephir_spprintf(error, 0, "function '%s' does not exist", method_name);
				}
			}
		}
	}

	if (retval) {
		fcc->initialized = 1;
	}
	return retval;
}
예제 #2
0
파일: fcall.c 프로젝트: Mrhjx2/zephir
static int zephir_is_callable_check_class(const char *name, int name_len, zend_fcall_info_cache *fcc, int *strict_class, char **error) /* {{{ */
{
	int ret = 0;
	zend_class_entry *pce;
	char *lcname = zend_str_tolower_dup(name, name_len);

	*strict_class = 0;
	if (name_len == sizeof("self") - 1 &&
		!memcmp(lcname, "self", sizeof("self") - 1)) {
		if (!EG(scope)) {
			if (error) *error = estrdup("cannot access self:: when no class scope is active");
		} else {
			fcc->called_scope = EG(current_execute_data)->called_scope;
			if (!fcc->object) {
				fcc->object = Z_OBJ(EG(current_execute_data)->This);
			}
			ret = 1;
		}
	} else if (name_len == sizeof("parent") - 1 &&
			   !memcmp(lcname, "parent", sizeof("parent") - 1)) {
		if (!EG(scope)) {
			if (error) *error = estrdup("cannot access parent:: when no class scope is active");
		} else if (!EG(scope)->parent) {
			if (error) *error = estrdup("cannot access parent:: when current class scope has no parent");
		} else {
			fcc->called_scope = EG(current_execute_data)->called_scope;
			if (!fcc->object) {
				fcc->object = Z_OBJ(EG(current_execute_data)->This);
			}
			*strict_class = 1;
			ret = 1;
		}
	} else if (name_len == sizeof("static") - 1 &&
			   !memcmp(lcname, "static", sizeof("static") - 1)) {
		if (!EG(current_execute_data)->called_scope) {
			if (error) *error = estrdup("cannot access static:: when no class scope is active");
		} else {
			fcc->called_scope = EG(current_execute_data)->called_scope;
			if (!fcc->object) {
				fcc->object = Z_OBJ(EG(current_execute_data)->This);
			}
			*strict_class = 1;
			ret = 1;
		}
	} else {
		zend_string *class_name;
		class_name = zend_string_init(name, name_len, 0);
		if ((pce = zend_lookup_class_ex(class_name, NULL, 1)) != NULL) {
			zend_class_entry *scope = EG(current_execute_data) ? EG(current_execute_data)->func->common.scope : NULL;
			fcc->calling_scope = pce;
			if (scope && !fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This) &&
				instanceof_function(Z_OBJCE(EG(current_execute_data)->This), scope TSRMLS_CC) &&
				instanceof_function(scope, fcc->calling_scope TSRMLS_CC)) {
				fcc->object = Z_OBJ(EG(current_execute_data)->This);
				fcc->called_scope = fcc->object->ce;
			} else {
				fcc->called_scope = fcc->object ? fcc->object->ce : fcc->calling_scope;
			}
			*strict_class = 1;
			ret = 1;
		} else {
			if (error) zephir_spprintf(error, 0, "class '%.*s' not found", name_len, name);
		}
		zend_string_free(class_name);
	}
	efree(lcname);
	return ret;
}