2006-02-21 08:00:39 +00:00
/*
2003-02-01 01:49:15 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Zend Engine |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2008-12-31 11:12:40 +00:00
| Copyright ( c ) 1998 - 2009 Zend Technologies Ltd . ( http : //www.zend.com) |
2003-02-01 01:49:15 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| This source file is subject to version 2.00 of the Zend license , |
| that is bundled with this package in the file LICENSE , and is |
2003-06-10 20:04:29 +00:00
| available through the world - wide - web at the following url : |
2003-02-01 01:49:15 +00:00
| http : //www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ zend . com so we can mail you a copy immediately . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Authors : Andi Gutmans < andi @ zend . com > |
| Zeev Suraski < zeev @ zend . com > |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
/* $Id$ */
2002-02-07 14:08:43 +00:00
# include "zend.h"
# include "zend_globals.h"
# include "zend_variables.h"
# include "zend_API.h"
# include "zend_objects.h"
2002-05-31 12:09:19 +00:00
# include "zend_objects_API.h"
2002-02-07 14:08:43 +00:00
# include "zend_object_handlers.h"
2003-11-24 20:57:54 +00:00
# include "zend_interfaces.h"
2008-08-14 21:26:05 +00:00
# include "zend_closures.h"
2002-02-07 14:08:43 +00:00
2002-02-21 11:50:44 +00:00
# define DEBUG_OBJECT_HANDLERS 0
2002-02-07 14:08:43 +00:00
2003-03-26 06:32:53 +00:00
# define Z_OBJ_P(zval_p) zend_objects_get_address(zval_p TSRMLS_CC)
2003-01-12 14:39:45 +00:00
2002-09-04 09:07:58 +00:00
/*
__X accessors explanation :
if we have __get and property that is not part of the properties array is
requested , we call __get handler . If it fails , we return uninitialized .
if we have __set and property that is not part of the properties array is
set , we call __set handler . If it fails , we do not change the array .
for both handlers above , when we are inside __get / __set , no further calls for
2007-03-23 17:39:19 +00:00
__get / __set for this property of this object will be made , to prevent endless
recursion and enable accessors to change properties array .
2002-09-04 09:07:58 +00:00
if we have __call and method which is not part of the class function table is
2006-02-21 08:00:39 +00:00
called , we cal __call handler .
2002-09-04 09:07:58 +00:00
*/
2007-07-11 11:19:58 +00:00
ZEND_API HashTable * zend_std_get_properties ( zval * object TSRMLS_DC ) /* { { { */
2002-02-07 14:08:43 +00:00
{
zend_object * zobj ;
2002-04-22 14:22:27 +00:00
zobj = Z_OBJ_P ( object ) ;
2002-02-07 14:08:43 +00:00
return zobj - > properties ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2002-02-07 14:08:43 +00:00
2007-07-11 11:19:58 +00:00
ZEND_API HashTable * zend_std_get_debug_info ( zval * object , int * is_temp TSRMLS_DC ) /* { { { */
2007-01-18 23:23:13 +00:00
{
* is_temp = 0 ;
return zend_std_get_properties ( object TSRMLS_CC ) ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2007-01-18 23:23:13 +00:00
2007-07-11 11:19:58 +00:00
static zval * zend_std_call_getter ( zval * object , zval * member TSRMLS_DC ) /* { { { */
2002-09-04 09:07:58 +00:00
{
zval * retval = NULL ;
2004-09-28 22:55:22 +00:00
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2006-02-21 08:00:39 +00:00
2004-09-28 22:55:22 +00:00
/* __get handler is called with one argument:
property name
2002-09-04 09:07:58 +00:00
it should return whether the call was successfull or not
*/
2006-02-21 08:00:39 +00:00
2005-02-02 07:19:22 +00:00
SEPARATE_ARG_IF_REF ( member ) ;
2004-09-28 22:55:22 +00:00
zend_call_method_with_1_params ( & object , ce , & ce - > __get , ZEND_GET_FUNC_NAME , & retval , member ) ;
2002-09-04 09:07:58 +00:00
2005-02-02 07:19:22 +00:00
zval_ptr_dtor ( & member ) ;
2003-06-29 23:41:49 +00:00
if ( retval ) {
2007-10-07 05:15:07 +00:00
Z_DELREF_P ( retval ) ;
2003-06-29 23:41:49 +00:00
}
2002-09-04 09:07:58 +00:00
return retval ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2002-09-04 09:07:58 +00:00
2007-07-11 11:19:58 +00:00
static int zend_std_call_setter ( zval * object , zval * member , zval * value TSRMLS_DC ) /* { { { */
2002-09-04 09:07:58 +00:00
{
zval * retval = NULL ;
2005-03-19 15:32:18 +00:00
int result ;
2004-09-28 22:55:22 +00:00
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2005-02-02 07:19:22 +00:00
SEPARATE_ARG_IF_REF ( member ) ;
2007-10-07 05:15:07 +00:00
Z_ADDREF_P ( value ) ;
2004-09-28 22:55:22 +00:00
2002-09-04 09:07:58 +00:00
/* __set handler is called with two arguments:
2004-09-28 22:55:22 +00:00
property name
value to be set
2002-09-04 09:07:58 +00:00
it should return whether the call was successfull or not
*/
2004-09-28 22:55:22 +00:00
zend_call_method_with_2_params ( & object , ce , & ce - > __set , ZEND_SET_FUNC_NAME , & retval , member , value ) ;
2002-09-04 09:07:58 +00:00
2005-02-02 07:19:22 +00:00
zval_ptr_dtor ( & member ) ;
2002-09-04 09:07:58 +00:00
zval_ptr_dtor ( & value ) ;
2002-09-15 07:45:26 +00:00
if ( retval ) {
2005-03-19 15:32:18 +00:00
result = i_zend_is_true ( retval ) ? SUCCESS : FAILURE ;
2002-09-04 09:07:58 +00:00
zval_ptr_dtor ( & retval ) ;
2005-03-19 15:32:18 +00:00
return result ;
} else {
return FAILURE ;
2002-09-04 09:07:58 +00:00
}
}
2007-07-11 11:19:58 +00:00
/* }}} */
2002-09-04 09:07:58 +00:00
2007-07-11 11:19:58 +00:00
static void zend_std_call_unsetter ( zval * object , zval * member TSRMLS_DC ) /* { { { */
2005-07-07 16:07:09 +00:00
{
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2006-02-21 08:00:39 +00:00
2005-07-07 16:07:09 +00:00
/* __unset handler is called with one argument:
property name
*/
2006-02-21 08:00:39 +00:00
2005-07-07 16:07:09 +00:00
SEPARATE_ARG_IF_REF ( member ) ;
zend_call_method_with_1_params ( & object , ce , & ce - > __unset , ZEND_UNSET_FUNC_NAME , NULL , member ) ;
zval_ptr_dtor ( & member ) ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2005-07-07 16:07:09 +00:00
2007-07-11 11:19:58 +00:00
static zval * zend_std_call_issetter ( zval * object , zval * member TSRMLS_DC ) /* { { { */
2005-07-07 16:07:09 +00:00
{
zval * retval = NULL ;
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2006-02-21 08:00:39 +00:00
2005-07-07 16:07:09 +00:00
/* __isset handler is called with one argument:
property name
it should return whether the property is set or not
*/
2006-02-21 08:00:39 +00:00
2005-07-07 16:07:09 +00:00
SEPARATE_ARG_IF_REF ( member ) ;
zend_call_method_with_1_params ( & object , ce , & ce - > __isset , ZEND_ISSET_FUNC_NAME , & retval , member ) ;
zval_ptr_dtor ( & member ) ;
return retval ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-02-04 12:12:34 +00:00
2007-07-11 11:19:58 +00:00
static int zend_verify_property_access ( zend_property_info * property_info , zend_class_entry * ce TSRMLS_DC ) /* { { { */
2003-02-04 12:12:34 +00:00
{
switch ( property_info - > flags & ZEND_ACC_PPP_MASK ) {
case ZEND_ACC_PUBLIC :
return 1 ;
2003-02-05 13:35:52 +00:00
case ZEND_ACC_PROTECTED :
2006-05-27 02:12:43 +00:00
return zend_check_protected ( property_info - > ce , EG ( scope ) ) ;
2003-02-10 10:03:19 +00:00
case ZEND_ACC_PRIVATE :
2007-07-24 11:40:07 +00:00
if ( ( ce = = EG ( scope ) | | property_info - > ce = = EG ( scope ) ) & & EG ( scope ) ) {
2003-02-10 10:03:19 +00:00
return 1 ;
} else {
return 0 ;
}
break ;
2003-02-04 12:12:34 +00:00
}
return 0 ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-02-04 12:12:34 +00:00
2007-07-11 11:19:58 +00:00
static inline zend_bool is_derived_class ( zend_class_entry * child_class , zend_class_entry * parent_class ) /* { { { */
2003-07-21 12:13:16 +00:00
{
child_class = child_class - > parent ;
while ( child_class ) {
if ( child_class = = parent_class ) {
return 1 ;
}
child_class = child_class - > parent ;
}
return 0 ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-07-21 12:13:16 +00:00
2007-07-11 11:19:58 +00:00
ZEND_API struct _zend_property_info * zend_get_property_info ( zend_class_entry * ce , zval * member , int silent TSRMLS_DC ) /* { { { */
2003-02-07 10:05:36 +00:00
{
2003-03-18 16:30:23 +00:00
zend_property_info * property_info = NULL ;
zend_property_info * scope_property_info ;
zend_bool denied_access = 0 ;
2005-04-29 10:40:01 +00:00
ulong h ;
2003-03-18 16:30:23 +00:00
2005-08-12 12:58:41 +00:00
if ( ( Z_TYPE_P ( member ) = = IS_UNICODE & & Z_USTRVAL_P ( member ) [ 0 ] = = 0 ) | |
Z_STRVAL_P ( member ) [ 0 ] = = ' \0 ' ) {
2005-04-28 17:40:11 +00:00
if ( ! silent ) {
2005-08-12 12:58:41 +00:00
if ( Z_UNILEN_P ( member ) = = 0 ) {
2005-04-28 17:40:11 +00:00
zend_error ( E_ERROR , " Cannot access empty property " ) ;
} else {
zend_error ( E_ERROR , " Cannot access property started with ' \\ 0' " ) ;
}
}
2006-02-21 08:00:39 +00:00
return NULL ;
2005-04-28 17:40:11 +00:00
}
2005-08-12 12:58:41 +00:00
h = zend_u_get_hash_value ( Z_TYPE_P ( member ) , Z_UNIVAL_P ( member ) , Z_UNILEN_P ( member ) + 1 ) ;
if ( zend_u_hash_quick_find ( & ce - > properties_info , Z_TYPE_P ( member ) , Z_UNIVAL_P ( member ) , Z_UNILEN_P ( member ) + 1 , h , ( void * * ) & property_info ) = = SUCCESS ) {
2005-06-09 17:20:44 +00:00
if ( property_info - > flags & ZEND_ACC_SHADOW ) {
/* if it's a shadow - go to access it's private */
property_info = NULL ;
} else {
if ( zend_verify_property_access ( property_info , ce TSRMLS_CC ) ) {
if ( property_info - > flags & ZEND_ACC_CHANGED
& & ! ( property_info - > flags & ZEND_ACC_PRIVATE ) ) {
/* We still need to make sure that we're not in a context
* where the right property is a different ' statically linked ' private
* continue checking below . . .
*/
} else {
if ( ! silent & & ( property_info - > flags & ZEND_ACC_STATIC ) ) {
2005-08-12 11:29:33 +00:00
zend_error ( E_STRICT , " Accessing static property %v::$%R as non static " , ce - > name , Z_TYPE_P ( member ) , Z_UNIVAL_P ( member ) ) ;
2005-06-09 17:20:44 +00:00
}
return property_info ;
2005-06-08 08:08:18 +00:00
}
2005-06-09 17:20:44 +00:00
} else {
/* Try to look in the scope instead */
denied_access = 1 ;
2003-03-18 16:30:23 +00:00
}
2003-02-07 10:05:36 +00:00
}
2003-02-13 22:47:25 +00:00
}
2005-04-08 11:35:11 +00:00
if ( EG ( scope ) ! = ce
& & is_derived_class ( ce , EG ( scope ) )
2003-03-18 16:30:23 +00:00
& & EG ( scope )
2006-05-27 19:04:16 +00:00
& & zend_u_hash_quick_find ( & EG ( scope ) - > properties_info , Z_TYPE_P ( member ) , Z_UNIVAL_P ( member ) , Z_UNILEN_P ( member ) + 1 , h , ( void * * ) & scope_property_info ) = = SUCCESS
2003-03-18 16:30:23 +00:00
& & scope_property_info - > flags & ZEND_ACC_PRIVATE ) {
return scope_property_info ;
} else if ( property_info ) {
if ( denied_access ) {
/* Information was available, but we were denied access. Error out. */
2003-12-18 20:07:30 +00:00
if ( silent ) {
return NULL ;
}
2005-08-12 11:29:33 +00:00
zend_error ( E_ERROR , " Cannot access %s property %v::$%R " , zend_visibility_string ( property_info - > flags ) , ce - > name , Z_TYPE_P ( member ) , Z_STRVAL_P ( member ) ) ;
2003-03-18 16:30:23 +00:00
} else {
/* fall through, return property_info... */
}
2003-02-07 10:05:36 +00:00
} else {
EG ( std_property_info ) . flags = ZEND_ACC_PUBLIC ;
2005-08-11 23:35:03 +00:00
EG ( std_property_info ) . name = Z_UNIVAL_P ( member ) ;
EG ( std_property_info ) . name_length = Z_UNILEN_P ( member ) ;
2005-11-15 15:21:47 +00:00
EG ( std_property_info ) . h = h ;
2006-05-27 19:04:16 +00:00
EG ( std_property_info ) . ce = ce ;
2003-02-07 10:05:36 +00:00
property_info = & EG ( std_property_info ) ;
}
return property_info ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-02-07 10:05:36 +00:00
2007-07-11 11:19:58 +00:00
ZEND_API int zend_check_property_access ( zend_object * zobj , zend_uchar utype , zstr prop_info_name , int prop_info_name_len TSRMLS_DC ) /* { { { */
2003-12-18 20:07:30 +00:00
{
zend_property_info * property_info ;
2006-02-21 20:12:43 +00:00
zstr class_name , prop_name ;
2003-12-18 20:07:30 +00:00
zval member ;
2006-07-24 17:51:41 +00:00
zend_u_unmangle_property_name ( utype , prop_info_name , prop_info_name_len , & class_name , & prop_name ) ;
2005-08-11 23:35:03 +00:00
if ( utype = = IS_UNICODE ) {
2006-02-21 20:12:43 +00:00
ZVAL_UNICODE ( & member , prop_name . u , 0 ) ;
2005-08-11 23:35:03 +00:00
} else {
2006-02-21 20:12:43 +00:00
ZVAL_STRING ( & member , prop_name . s , 0 ) ;
2005-08-11 23:35:03 +00:00
}
2005-04-08 11:35:11 +00:00
property_info = zend_get_property_info ( zobj - > ce , & member , 1 TSRMLS_CC ) ;
2003-12-18 20:07:30 +00:00
if ( ! property_info ) {
return FAILURE ;
}
2006-02-21 20:12:43 +00:00
if ( class_name . s & & class_name . s [ 0 ] ! = ' * ' ) {
2005-06-06 07:52:08 +00:00
if ( ! ( property_info - > flags & ZEND_ACC_PRIVATE ) ) {
/* we we're looking for a private prop but found a non private one of the same name */
return FAILURE ;
2009-03-26 20:02:53 +00:00
} else if ( u_strcmp ( prop_info_name . u + 1 , property_info - > name . u + 1 ) ) {
2005-06-06 07:52:08 +00:00
/* we we're looking for a private prop but found a private one of the same name but another class */
return FAILURE ;
}
2003-12-18 20:07:30 +00:00
}
return zend_verify_property_access ( property_info , zobj - > ce TSRMLS_CC ) ? SUCCESS : FAILURE ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-12-18 20:07:30 +00:00
2007-07-11 11:19:58 +00:00
static int zend_get_property_guard ( zend_object * zobj , zend_property_info * property_info , zval * member , zend_guard * * pguard TSRMLS_DC ) /* { { { */
2005-11-15 15:21:47 +00:00
{
zend_property_info info ;
zend_guard stub ;
if ( ! property_info ) {
property_info = & info ;
info . name = Z_UNIVAL_P ( member ) ;
info . name_length = Z_UNILEN_P ( member ) ;
2006-02-21 20:12:43 +00:00
info . h = zend_u_get_hash_value ( Z_TYPE_P ( member ) , Z_UNIVAL_P ( member ) , Z_UNILEN_P ( member ) + 1 ) ;
2005-11-15 15:21:47 +00:00
}
if ( ! zobj - > guards ) {
ALLOC_HASHTABLE ( zobj - > guards ) ;
zend_u_hash_init ( zobj - > guards , 0 , NULL , NULL , 0 , UG ( unicode ) ) ;
2009-03-26 20:02:53 +00:00
} else if ( zend_u_hash_quick_find ( zobj - > guards , IS_UNICODE , property_info - > name , property_info - > name_length + 1 , property_info - > h , ( void * * ) pguard ) = = SUCCESS ) {
2005-11-15 15:21:47 +00:00
return SUCCESS ;
}
stub . in_get = 0 ;
stub . in_set = 0 ;
stub . in_unset = 0 ;
stub . in_isset = 0 ;
2009-03-26 20:02:53 +00:00
return zend_u_hash_quick_add ( zobj - > guards , IS_UNICODE , property_info - > name , property_info - > name_length + 1 , property_info - > h , ( void * * ) & stub , sizeof ( stub ) , ( void * * ) pguard ) ;
2005-11-15 15:21:47 +00:00
}
2007-07-11 11:19:58 +00:00
/* }}} */
2005-11-15 15:21:47 +00:00
2007-07-11 11:19:58 +00:00
zval * zend_std_read_property ( zval * object , zval * member , int type TSRMLS_DC ) /* { { { */
2002-02-07 14:08:43 +00:00
{
zend_object * zobj ;
2005-06-03 11:16:19 +00:00
zval * tmp_member = NULL ;
2002-02-07 14:08:43 +00:00
zval * * retval ;
2002-09-04 09:07:58 +00:00
zval * rv = NULL ;
2003-02-04 12:12:34 +00:00
zend_property_info * property_info ;
2004-03-21 18:07:27 +00:00
int silent ;
silent = ( type = = BP_VAR_IS ) ;
2002-04-22 14:22:27 +00:00
zobj = Z_OBJ_P ( object ) ;
2002-02-07 14:08:43 +00:00
2009-03-26 20:02:53 +00:00
if ( Z_TYPE_P ( member ) ! = IS_UNICODE ) {
2005-06-03 11:16:19 +00:00
ALLOC_ZVAL ( tmp_member ) ;
* tmp_member = * member ;
INIT_PZVAL ( tmp_member ) ;
zval_copy_ctor ( tmp_member ) ;
2009-03-26 20:02:53 +00:00
convert_to_unicode ( tmp_member ) ;
2005-06-03 11:16:19 +00:00
member = tmp_member ;
2002-02-07 14:08:43 +00:00
}
# if DEBUG_OBJECT_HANDLERS
2005-08-12 11:29:33 +00:00
fprintf ( stderr , " Read object #%d property: %R \n " , Z_OBJ_HANDLE_P ( object ) , Z_TYPE_P ( member ) , Z_STRVAL_P ( member ) ) ;
2006-02-21 08:00:39 +00:00
# endif
2003-02-04 12:12:34 +00:00
2004-07-19 14:26:53 +00:00
/* make zend_get_property_info silent if we have getter - we may want to use it */
2005-11-15 15:21:47 +00:00
property_info = zend_get_property_info ( zobj - > ce , member , ( zobj - > ce - > __get ! = NULL ) TSRMLS_CC ) ;
2003-02-04 12:12:34 +00:00
2005-08-11 23:35:03 +00:00
if ( ! property_info | | zend_u_hash_quick_find ( zobj - > properties , Z_TYPE_P ( member ) , property_info - > name , property_info - > name_length + 1 , property_info - > h , ( void * * ) & retval ) = = FAILURE ) {
2005-11-15 15:21:47 +00:00
zend_guard * guard ;
if ( zobj - > ce - > __get & &
zend_get_property_guard ( zobj , property_info , member , & guard TSRMLS_CC ) = = SUCCESS & &
! guard - > in_get ) {
2002-09-04 09:07:58 +00:00
/* have getter - try with it! */
2008-10-17 10:26:16 +00:00
Z_ADDREF_P ( object ) ;
2005-11-15 15:21:47 +00:00
guard - > in_get = 1 ; /* prevent circular getting */
2002-09-04 09:07:58 +00:00
rv = zend_std_call_getter ( object , member TSRMLS_CC ) ;
2005-11-15 15:21:47 +00:00
guard - > in_get = 0 ;
2002-09-04 09:07:58 +00:00
2002-09-15 07:45:26 +00:00
if ( rv ) {
2002-09-04 09:07:58 +00:00
retval = & rv ;
2007-10-07 05:15:07 +00:00
if ( ! Z_ISREF_P ( rv ) & &
2007-01-10 15:59:56 +00:00
( type = = BP_VAR_W | | type = = BP_VAR_RW | | type = = BP_VAR_UNSET ) ) {
2007-10-07 05:15:07 +00:00
if ( Z_REFCOUNT_P ( rv ) > 0 ) {
2006-12-08 16:23:04 +00:00
zval * tmp = rv ;
ALLOC_ZVAL ( rv ) ;
* rv = * tmp ;
zval_copy_ctor ( rv ) ;
2007-10-07 05:15:07 +00:00
Z_UNSET_ISREF_P ( rv ) ;
Z_SET_REFCOUNT_P ( rv , 0 ) ;
2006-12-08 16:23:04 +00:00
}
2006-07-21 10:32:41 +00:00
if ( Z_TYPE_P ( rv ) ! = IS_OBJECT ) {
zend_error ( E_NOTICE , " Indirect modification of overloaded property %v::$%R has no effect " , zobj - > ce - > name , Z_TYPE_P ( member ) , Z_UNIVAL_P ( member ) ) ;
}
}
2002-09-04 09:07:58 +00:00
} else {
2006-02-21 08:00:39 +00:00
retval = & EG ( uninitialized_zval_ptr ) ;
2002-09-04 09:07:58 +00:00
}
2008-10-17 10:26:16 +00:00
zval_ptr_dtor ( & object ) ;
2002-09-04 09:07:58 +00:00
} else {
2003-07-22 13:49:33 +00:00
if ( ! silent ) {
2007-11-17 21:51:40 +00:00
zend_error ( E_NOTICE , " Undefined property: %v::$%R " , zobj - > ce - > name , Z_TYPE_P ( member ) , Z_STRVAL_P ( member ) ) ;
2003-07-22 13:49:33 +00:00
}
2003-02-07 10:05:36 +00:00
retval = & EG ( uninitialized_zval_ptr ) ;
2002-02-07 14:08:43 +00:00
}
}
2005-06-03 11:16:19 +00:00
if ( tmp_member ) {
2007-10-07 05:15:07 +00:00
Z_ADDREF_PP ( retval ) ;
2005-06-03 11:16:19 +00:00
zval_ptr_dtor ( & tmp_member ) ;
2007-10-07 05:15:07 +00:00
Z_DELREF_PP ( retval ) ;
2002-02-07 14:08:43 +00:00
}
return * retval ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2002-02-07 14:08:43 +00:00
2007-07-11 11:19:58 +00:00
static void zend_std_write_property ( zval * object , zval * member , zval * value TSRMLS_DC ) /* { { { */
2002-02-07 14:08:43 +00:00
{
zend_object * zobj ;
2005-06-03 11:16:19 +00:00
zval * tmp_member = NULL ;
2002-03-10 13:42:37 +00:00
zval * * variable_ptr ;
2003-02-04 12:12:34 +00:00
zend_property_info * property_info ;
2004-07-19 14:26:53 +00:00
2002-04-22 14:22:27 +00:00
zobj = Z_OBJ_P ( object ) ;
2002-02-07 14:08:43 +00:00
2009-03-26 20:02:53 +00:00
if ( Z_TYPE_P ( member ) ! = IS_UNICODE ) {
2005-06-03 11:16:19 +00:00
ALLOC_ZVAL ( tmp_member ) ;
* tmp_member = * member ;
INIT_PZVAL ( tmp_member ) ;
zval_copy_ctor ( tmp_member ) ;
2009-03-26 20:02:53 +00:00
convert_to_unicode ( tmp_member ) ;
2005-06-03 11:16:19 +00:00
member = tmp_member ;
2002-02-07 14:08:43 +00:00
}
2005-11-15 15:21:47 +00:00
property_info = zend_get_property_info ( zobj - > ce , member , ( zobj - > ce - > __set ! = NULL ) TSRMLS_CC ) ;
2003-02-04 12:12:34 +00:00
2005-08-11 23:35:03 +00:00
if ( property_info & & zend_u_hash_quick_find ( zobj - > properties , Z_TYPE_P ( member ) , property_info - > name , property_info - > name_length + 1 , property_info - > h , ( void * * ) & variable_ptr ) = = SUCCESS ) {
2006-07-26 15:29:39 +00:00
/* if we already have this value there, we don't actually need to do anything */
if ( * variable_ptr ! = value ) {
2002-10-09 17:14:25 +00:00
/* if we are assigning reference, we shouldn't move it, but instead assign variable
to the same pointer */
if ( PZVAL_IS_REF ( * variable_ptr ) ) {
2005-11-16 11:52:53 +00:00
zval garbage = * * variable_ptr ; /* old value should be destroyed */
2002-10-10 10:07:22 +00:00
/* To check: can't *variable_ptr be some system variable like error_zval here? */
2006-02-20 19:03:43 +00:00
Z_TYPE_PP ( variable_ptr ) = Z_TYPE_P ( value ) ;
2002-10-09 17:14:25 +00:00
( * variable_ptr ) - > value = value - > value ;
2007-10-07 05:15:07 +00:00
if ( Z_REFCOUNT_P ( value ) > 0 ) {
2003-01-29 08:55:12 +00:00
zval_copy_ctor ( * variable_ptr ) ;
}
2005-11-16 11:52:53 +00:00
zval_dtor ( & garbage ) ;
2006-07-26 15:29:39 +00:00
} else {
zval * garbage = * variable_ptr ;
/* if we assign referenced variable, we should separate it */
2007-10-07 05:15:07 +00:00
Z_ADDREF_P ( value ) ;
2006-07-26 15:29:39 +00:00
if ( PZVAL_IS_REF ( value ) ) {
SEPARATE_ZVAL ( & value ) ;
}
* variable_ptr = value ;
zval_ptr_dtor ( & garbage ) ;
2002-02-07 14:08:43 +00:00
}
}
2006-08-15 20:30:26 +00:00
} else {
2006-07-26 15:29:39 +00:00
int setter_done = 0 ;
2005-11-15 15:21:47 +00:00
zend_guard * guard ;
if ( zobj - > ce - > __set & &
zend_get_property_guard ( zobj , property_info , member , & guard TSRMLS_CC ) = = SUCCESS & &
! guard - > in_set ) {
2008-10-17 10:26:16 +00:00
Z_ADDREF_P ( object ) ;
2005-11-15 15:21:47 +00:00
guard - > in_set = 1 ; /* prevent circular setting */
2002-09-15 07:45:26 +00:00
if ( zend_std_call_setter ( object , member , value TSRMLS_CC ) ! = SUCCESS ) {
2002-09-09 08:59:18 +00:00
/* for now, just ignore it - __set should take care of warnings, etc. */
2002-09-04 09:07:58 +00:00
}
setter_done = 1 ;
2005-11-15 15:21:47 +00:00
guard - > in_set = 0 ;
2008-10-17 10:26:16 +00:00
zval_ptr_dtor ( & object ) ;
2002-09-04 09:07:58 +00:00
}
2006-08-15 20:30:26 +00:00
if ( ! setter_done & & property_info ) {
2006-07-26 15:29:39 +00:00
zval * * foo ;
2003-02-07 10:05:36 +00:00
2006-07-26 15:29:39 +00:00
/* if we assign referenced variable, we should separate it */
2007-10-07 05:15:07 +00:00
Z_ADDREF_P ( value ) ;
2006-07-26 15:29:39 +00:00
if ( PZVAL_IS_REF ( value ) ) {
SEPARATE_ZVAL ( & value ) ;
}
zend_u_hash_quick_update ( zobj - > properties , Z_TYPE_P ( member ) , property_info - > name , property_info - > name_length + 1 , property_info - > h , & value , sizeof ( zval * ) , ( void * * ) & foo ) ;
2002-10-09 17:14:25 +00:00
}
2002-09-04 09:07:58 +00:00
}
2006-07-26 15:29:39 +00:00
2005-06-03 11:16:19 +00:00
if ( tmp_member ) {
zval_ptr_dtor ( & tmp_member ) ;
2002-02-07 14:08:43 +00:00
}
}
2007-07-11 11:19:58 +00:00
/* }}} */
2002-02-07 14:08:43 +00:00
2007-07-11 11:19:58 +00:00
zval * zend_std_read_dimension ( zval * object , zval * offset , int type TSRMLS_DC ) /* { { { */
2003-07-07 10:53:27 +00:00
{
2003-11-24 20:57:54 +00:00
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
zval * retval ;
2006-02-21 08:00:39 +00:00
2006-02-13 10:23:59 +00:00
if ( instanceof_function_ex ( ce , zend_ce_arrayaccess , 1 TSRMLS_CC ) ) {
2004-07-14 09:01:58 +00:00
if ( offset = = NULL ) {
/* [] construct */
2005-02-02 07:19:22 +00:00
ALLOC_INIT_ZVAL ( offset ) ;
} else {
SEPARATE_ARG_IF_REF ( offset ) ;
2004-07-14 09:01:58 +00:00
}
2004-07-14 09:04:13 +00:00
zend_call_method_with_1_params ( & object , ce , NULL , " offsetget " , & retval , offset ) ;
2005-02-02 07:19:22 +00:00
zval_ptr_dtor ( & offset ) ;
2003-12-11 09:56:06 +00:00
if ( ! retval ) {
if ( ! EG ( exception ) ) {
2005-08-11 23:35:03 +00:00
zend_error ( E_ERROR , " Undefined offset for object of type %v used as array " , ce - > name ) ;
2003-12-11 09:56:06 +00:00
}
return 0 ;
}
2004-02-12 13:49:55 +00:00
/* Undo PZVAL_LOCK() */
2007-10-07 05:15:07 +00:00
Z_DELREF_P ( retval ) ;
2004-02-12 13:49:55 +00:00
2003-11-24 20:57:54 +00:00
return retval ;
} else {
2005-08-11 23:35:03 +00:00
zend_error ( E_ERROR , " Cannot use object of type %v as array " , ce - > name ) ;
2003-11-24 20:57:54 +00:00
return 0 ;
}
2003-07-07 10:53:27 +00:00
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-07-07 10:53:27 +00:00
2007-07-11 11:19:58 +00:00
static void zend_std_write_dimension ( zval * object , zval * offset , zval * value TSRMLS_DC ) /* { { { */
2003-07-07 09:00:36 +00:00
{
2003-11-24 20:57:54 +00:00
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2005-02-02 07:19:22 +00:00
2006-02-13 10:23:59 +00:00
if ( instanceof_function_ex ( ce , zend_ce_arrayaccess , 1 TSRMLS_CC ) ) {
2003-12-22 16:27:14 +00:00
if ( ! offset ) {
2005-02-02 07:19:22 +00:00
ALLOC_INIT_ZVAL ( offset ) ;
} else {
SEPARATE_ARG_IF_REF ( offset ) ;
2003-12-22 16:27:14 +00:00
}
2003-11-24 20:57:54 +00:00
zend_call_method_with_2_params ( & object , ce , NULL , " offsetset " , NULL , offset , value ) ;
2005-02-02 07:19:22 +00:00
zval_ptr_dtor ( & offset ) ;
2003-11-24 20:57:54 +00:00
} else {
2005-08-11 23:35:03 +00:00
zend_error ( E_ERROR , " Cannot use object of type %v as array " , ce - > name ) ;
2003-11-24 20:57:54 +00:00
}
2003-07-07 09:00:36 +00:00
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-07-07 09:00:36 +00:00
2007-07-11 11:19:58 +00:00
static int zend_std_has_dimension ( zval * object , zval * offset , int check_empty TSRMLS_DC ) /* { { { */
2003-11-10 16:14:44 +00:00
{
2003-11-24 20:57:54 +00:00
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
zval * retval ;
int result ;
2006-02-21 08:00:39 +00:00
2006-02-13 10:23:59 +00:00
if ( instanceof_function_ex ( ce , zend_ce_arrayaccess , 1 TSRMLS_CC ) ) {
2005-02-02 07:19:22 +00:00
SEPARATE_ARG_IF_REF ( offset ) ;
2003-11-24 20:57:54 +00:00
zend_call_method_with_1_params ( & object , ce , NULL , " offsetexists " , & retval , offset ) ;
2005-03-19 15:32:18 +00:00
if ( retval ) {
result = i_zend_is_true ( retval ) ;
zval_ptr_dtor ( & retval ) ;
2005-07-07 16:07:09 +00:00
if ( check_empty & & result & & ! EG ( exception ) ) {
zend_call_method_with_1_params ( & object , ce , NULL , " offsetget " , & retval , offset ) ;
if ( retval ) {
result = i_zend_is_true ( retval ) ;
zval_ptr_dtor ( & retval ) ;
}
}
2005-03-19 15:32:18 +00:00
} else {
2005-07-07 16:07:09 +00:00
result = 0 ;
2005-03-19 15:32:18 +00:00
}
2005-07-07 16:07:09 +00:00
zval_ptr_dtor ( & offset ) ;
2003-11-24 20:57:54 +00:00
} else {
2005-08-11 23:35:03 +00:00
zend_error ( E_ERROR , " Cannot use object of type %v as array " , ce - > name ) ;
2003-11-24 20:57:54 +00:00
return 0 ;
}
2005-07-07 16:07:09 +00:00
return result ;
2003-11-10 16:14:44 +00:00
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-11-10 16:14:44 +00:00
2007-07-11 11:19:58 +00:00
static zval * * zend_std_get_property_ptr_ptr ( zval * object , zval * member TSRMLS_DC ) /* { { { */
2002-02-07 14:08:43 +00:00
{
zend_object * zobj ;
zval tmp_member ;
zval * * retval ;
2003-02-05 09:41:31 +00:00
zend_property_info * property_info ;
2006-02-21 08:00:39 +00:00
2002-04-22 14:22:27 +00:00
zobj = Z_OBJ_P ( object ) ;
2002-02-07 14:08:43 +00:00
2009-03-26 20:02:53 +00:00
if ( Z_TYPE_P ( member ) ! = IS_UNICODE ) {
2002-02-07 14:08:43 +00:00
tmp_member = * member ;
zval_copy_ctor ( & tmp_member ) ;
2009-03-26 20:02:53 +00:00
convert_to_unicode ( & tmp_member ) ;
2002-02-07 14:08:43 +00:00
member = & tmp_member ;
}
# if DEBUG_OBJECT_HANDLERS
2005-08-12 11:29:33 +00:00
fprintf ( stderr , " Ptr object #%d property: %R \n " , Z_OBJ_HANDLE_P ( object ) , Z_TYPE_P ( member ) , Z_STRVAL_P ( member ) ) ;
2006-02-21 08:00:39 +00:00
# endif
2002-02-07 14:08:43 +00:00
2005-11-15 15:21:47 +00:00
property_info = zend_get_property_info ( zobj - > ce , member , ( zobj - > ce - > __get ! = NULL ) TSRMLS_CC ) ;
2003-02-05 09:41:31 +00:00
2005-10-20 09:47:31 +00:00
if ( ! property_info | | zend_u_hash_quick_find ( zobj - > properties , Z_TYPE_P ( member ) , property_info - > name , property_info - > name_length + 1 , property_info - > h , ( void * * ) & retval ) = = FAILURE ) {
2002-09-04 09:07:58 +00:00
zval * new_zval ;
2005-11-15 15:21:47 +00:00
zend_guard * guard ;
2002-09-04 09:07:58 +00:00
2005-11-15 15:21:47 +00:00
if ( ! zobj - > ce - > __get | |
2009-05-12 22:50:56 +00:00
zend_get_property_guard ( zobj , property_info , member , & guard TSRMLS_CC ) ! = SUCCESS | |
( property_info & & guard - > in_get ) ) {
2004-01-05 11:45:46 +00:00
/* we don't have access controls - will just add it */
2002-09-04 09:07:58 +00:00
new_zval = & EG ( uninitialized_zval ) ;
2002-02-07 14:08:43 +00:00
2005-08-12 11:29:33 +00:00
/* zend_error(E_NOTICE, "Undefined property: %R", Z_TYPE_P(member), Z_STRVAL_P(member)); */
2007-10-07 05:15:07 +00:00
Z_ADDREF_P ( new_zval ) ;
2005-08-11 23:35:03 +00:00
zend_u_hash_quick_update ( zobj - > properties , Z_TYPE_P ( member ) , property_info - > name , property_info - > name_length + 1 , property_info - > h , & new_zval , sizeof ( zval * ) , ( void * * ) & retval ) ;
2002-09-04 09:07:58 +00:00
} else {
/* we do have getter - fail and let it try again with usual get/set */
retval = NULL ;
}
2002-02-07 14:08:43 +00:00
}
if ( member = = & tmp_member ) {
zval_dtor ( member ) ;
}
return retval ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2002-02-07 14:08:43 +00:00
2007-07-11 11:19:58 +00:00
static void zend_std_unset_property ( zval * object , zval * member TSRMLS_DC ) /* { { { */
2002-02-07 14:08:43 +00:00
{
zend_object * zobj ;
2005-07-07 16:07:09 +00:00
zval * tmp_member = NULL ;
2003-02-05 14:27:30 +00:00
zend_property_info * property_info ;
2006-02-21 08:00:39 +00:00
2002-04-22 14:22:27 +00:00
zobj = Z_OBJ_P ( object ) ;
2002-02-07 14:08:43 +00:00
2009-03-26 20:02:53 +00:00
if ( Z_TYPE_P ( member ) ! = IS_UNICODE ) {
2005-07-07 16:07:09 +00:00
ALLOC_ZVAL ( tmp_member ) ;
* tmp_member = * member ;
INIT_PZVAL ( tmp_member ) ;
zval_copy_ctor ( tmp_member ) ;
2009-03-26 20:02:53 +00:00
convert_to_unicode ( tmp_member ) ;
2005-07-07 16:07:09 +00:00
member = tmp_member ;
2002-02-07 14:08:43 +00:00
}
2003-02-05 14:27:30 +00:00
2005-11-15 15:21:47 +00:00
property_info = zend_get_property_info ( zobj - > ce , member , ( zobj - > ce - > __unset ! = NULL ) TSRMLS_CC ) ;
2006-02-21 08:00:39 +00:00
2008-04-29 08:15:49 +00:00
if ( ! property_info | | zend_u_hash_quick_del ( zobj - > properties , Z_TYPE_P ( member ) , property_info - > name , property_info - > name_length + 1 , property_info - > h ) ) {
2005-11-15 15:21:47 +00:00
zend_guard * guard ;
if ( zobj - > ce - > __unset & &
zend_get_property_guard ( zobj , property_info , member , & guard TSRMLS_CC ) = = SUCCESS & &
! guard - > in_unset ) {
2005-07-07 16:07:09 +00:00
/* have unseter - try with it! */
2008-10-17 10:26:16 +00:00
Z_ADDREF_P ( object ) ;
2005-11-15 15:21:47 +00:00
guard - > in_unset = 1 ; /* prevent circular unsetting */
2005-07-07 16:07:09 +00:00
zend_std_call_unsetter ( object , member TSRMLS_CC ) ;
2005-11-15 15:21:47 +00:00
guard - > in_unset = 0 ;
2008-10-17 10:26:16 +00:00
zval_ptr_dtor ( & object ) ;
2005-07-07 16:07:09 +00:00
}
}
if ( tmp_member ) {
zval_ptr_dtor ( & tmp_member ) ;
2002-02-07 14:08:43 +00:00
}
}
2007-07-11 11:19:58 +00:00
/* }}} */
2002-02-07 14:08:43 +00:00
2007-07-11 11:19:58 +00:00
static void zend_std_unset_dimension ( zval * object , zval * offset TSRMLS_DC ) /* { { { */
2003-07-30 17:12:06 +00:00
{
2003-11-24 20:57:54 +00:00
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2006-02-21 08:00:39 +00:00
2006-02-13 10:23:59 +00:00
if ( instanceof_function_ex ( ce , zend_ce_arrayaccess , 1 TSRMLS_CC ) ) {
2005-02-02 07:19:22 +00:00
SEPARATE_ARG_IF_REF ( offset ) ;
2005-03-19 15:06:39 +00:00
zend_call_method_with_1_params ( & object , ce , NULL , " offsetunset " , NULL , offset ) ;
2005-02-02 07:19:22 +00:00
zval_ptr_dtor ( & offset ) ;
2003-11-24 20:57:54 +00:00
} else {
2005-08-11 23:35:03 +00:00
zend_error ( E_ERROR , " Cannot use object of type %v as array " , ce - > name ) ;
2003-11-24 20:57:54 +00:00
}
2003-07-30 17:12:06 +00:00
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-07-30 17:12:06 +00:00
2007-07-11 11:19:58 +00:00
ZEND_API void zend_std_call_user_call ( INTERNAL_FUNCTION_PARAMETERS ) /* { { { */
2002-09-04 09:07:58 +00:00
{
2007-11-20 09:51:44 +00:00
zend_internal_function * func = ( zend_internal_function * ) EG ( current_execute_data ) - > function_state . function ;
2002-09-04 15:03:41 +00:00
zval * method_name_ptr , * method_args_ptr ;
zval * method_result_ptr = NULL ;
2004-09-28 22:55:22 +00:00
zend_class_entry * ce = Z_OBJCE_P ( this_ptr ) ;
2006-02-21 08:00:39 +00:00
2004-12-17 22:24:51 +00:00
ALLOC_ZVAL ( method_args_ptr ) ;
2004-09-28 22:55:22 +00:00
INIT_PZVAL ( method_args_ptr ) ;
2008-05-27 10:28:25 +00:00
array_init_size ( method_args_ptr , ZEND_NUM_ARGS ( ) ) ;
2002-09-04 09:07:58 +00:00
2004-09-28 22:55:22 +00:00
if ( zend_copy_parameters_array ( ZEND_NUM_ARGS ( ) , method_args_ptr TSRMLS_CC ) = = FAILURE ) {
zval_dtor ( method_args_ptr ) ;
2002-09-04 09:07:58 +00:00
zend_error ( E_ERROR , " Cannot get arguments for __call " ) ;
RETURN_FALSE ;
}
2004-12-17 22:24:51 +00:00
ALLOC_ZVAL ( method_name_ptr ) ;
2002-09-04 09:07:58 +00:00
INIT_PZVAL ( method_name_ptr ) ;
2009-05-25 14:32:15 +00:00
ZVAL_UNICODE ( method_name_ptr , func - > function_name . u , 0 ) ; /* no dup - it's a copy */
2002-09-04 09:07:58 +00:00
2002-09-04 15:03:41 +00:00
/* __call handler is called with two arguments:
2002-09-04 09:07:58 +00:00
method name
array of method parameters
*/
2004-09-28 22:55:22 +00:00
zend_call_method_with_2_params ( & this_ptr , ce , & ce - > __call , ZEND_CALL_FUNC_NAME , & method_result_ptr , method_name_ptr , method_args_ptr ) ;
2002-09-15 07:45:26 +00:00
if ( method_result_ptr ) {
2007-10-07 05:15:07 +00:00
if ( Z_ISREF_P ( method_result_ptr ) | | Z_REFCOUNT_P ( method_result_ptr ) > 1 ) {
2005-05-03 12:47:27 +00:00
RETVAL_ZVAL ( method_result_ptr , 1 , 1 ) ;
} else {
RETVAL_ZVAL ( method_result_ptr , 0 , 1 ) ;
}
2002-09-04 15:03:41 +00:00
}
2006-02-21 08:00:39 +00:00
2002-09-04 09:07:58 +00:00
/* now destruct all auxiliaries */
2004-12-17 22:24:51 +00:00
zval_ptr_dtor ( & method_args_ptr ) ;
zval_ptr_dtor ( & method_name_ptr ) ;
2002-09-04 09:07:58 +00:00
/* destruct the function also, then - we have allocated it in get_method */
efree ( func ) ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2002-09-04 09:07:58 +00:00
2003-02-02 16:17:25 +00:00
/* Ensures that we're allowed to call a private method.
* Returns the function address that should be called , or NULL
* if no such function exists .
*/
2007-07-11 11:19:58 +00:00
static inline zend_function * zend_check_private_int ( zend_function * fbc , zend_class_entry * ce , zstr function_name_strval , int function_name_strlen TSRMLS_DC ) /* { { { */
2003-02-02 16:17:25 +00:00
{
if ( ! ce ) {
return 0 ;
}
/* We may call a private function if:
* 1. The class of our object is the same as the scope , and the private
* function ( EX ( fbc ) ) has the same scope .
* 2. One of our parent classes are the same as the scope , and it contains
* a private function with the same name that has the same scope .
*/
if ( fbc - > common . scope = = ce & & EG ( scope ) = = ce ) {
/* rule #1 checks out ok, allow the function call */
return fbc ;
}
/* Check rule #2 */
ce = ce - > parent ;
while ( ce ) {
if ( ce = = EG ( scope ) ) {
2009-03-26 20:02:53 +00:00
if ( zend_u_hash_find ( & ce - > function_table , IS_UNICODE , function_name_strval , function_name_strlen + 1 , ( void * * ) & fbc ) = = SUCCESS
2003-02-02 16:17:25 +00:00
& & fbc - > op_array . fn_flags & ZEND_ACC_PRIVATE
& & fbc - > common . scope = = EG ( scope ) ) {
return fbc ;
}
break ;
}
ce = ce - > parent ;
}
return NULL ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-02-02 16:17:25 +00:00
2007-07-11 11:19:58 +00:00
ZEND_API int zend_check_private ( zend_function * fbc , zend_class_entry * ce , zstr function_name_strval , int function_name_strlen TSRMLS_DC ) /* { { { */
2005-04-27 15:45:36 +00:00
{
return zend_check_private_int ( fbc , ce , function_name_strval , function_name_strlen TSRMLS_CC ) ! = NULL ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2005-04-27 15:45:36 +00:00
2003-02-02 16:17:25 +00:00
/* Ensures that we're allowed to call a protected method.
*/
2007-07-11 11:19:58 +00:00
ZEND_API int zend_check_protected ( zend_class_entry * ce , zend_class_entry * scope ) /* { { { */
2003-02-02 16:17:25 +00:00
{
zend_class_entry * fbc_scope = ce ;
/* Is the context that's calling the function, the same as one of
* the function ' s parents ?
*/
while ( fbc_scope ) {
if ( fbc_scope = = scope ) {
return 1 ;
}
fbc_scope = fbc_scope - > parent ;
}
/* Is the function's scope the same as our current object context,
* or any of the parents of our context ?
*/
while ( scope ) {
if ( scope = = ce ) {
return 1 ;
}
scope = scope - > parent ;
}
return 0 ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-02-02 16:17:25 +00:00
2007-07-11 11:19:58 +00:00
static inline zend_class_entry * zend_get_function_root_class ( zend_function * fbc ) /* { { { */
2006-05-29 19:57:43 +00:00
{
return fbc - > common . prototype ? fbc - > common . prototype - > common . scope : fbc - > common . scope ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2006-05-29 19:57:43 +00:00
2009-06-12 21:43:22 +00:00
static inline union _zend_function * zend_get_user_call_function ( zend_class_entry * ce , const zstr method_name , int method_len ) /* { { { */
2009-01-07 22:13:07 +00:00
{
zend_internal_function * call_user_call = emalloc ( sizeof ( zend_internal_function ) ) ;
2009-01-08 18:37:59 +00:00
2009-01-07 22:13:07 +00:00
call_user_call - > type = ZEND_INTERNAL_FUNCTION ;
2009-06-12 01:00:30 +00:00
call_user_call - > module = ce - > module ;
2009-01-07 22:13:07 +00:00
call_user_call - > handler = zend_std_call_user_call ;
call_user_call - > arg_info = NULL ;
call_user_call - > num_args = 0 ;
2009-06-12 01:00:30 +00:00
call_user_call - > scope = ce ;
2009-01-07 22:13:07 +00:00
call_user_call - > fn_flags = ZEND_ACC_CALL_VIA_HANDLER ;
2009-03-26 20:02:53 +00:00
call_user_call - > function_name . u = eustrndup ( method_name . u , method_len ) ;
2009-01-07 22:13:07 +00:00
call_user_call - > pass_rest_by_reference = 0 ;
call_user_call - > return_reference = ZEND_RETURN_VALUE ;
return ( union _zend_function * ) call_user_call ;
}
/* }}} */
2007-07-11 11:19:58 +00:00
static union _zend_function * zend_std_get_method ( zval * * object_ptr , zstr method_name , int method_len TSRMLS_DC ) /* { { { */
2002-02-07 14:08:43 +00:00
{
zend_object * zobj ;
2003-02-02 16:17:25 +00:00
zend_function * fbc ;
2005-08-11 23:35:03 +00:00
unsigned int lc_method_name_len ;
2006-02-21 20:12:43 +00:00
zstr lc_method_name ;
2004-10-30 19:11:37 +00:00
zval * object = * object_ptr ;
2006-02-21 08:00:39 +00:00
2005-08-11 23:35:03 +00:00
/* FIXME: type is default */
2009-03-26 20:02:53 +00:00
zend_uchar type = IS_UNICODE ;
2005-08-11 23:35:03 +00:00
2002-06-05 17:34:56 +00:00
/* Create a zend_copy_str_tolower(dest, src, src_length); */
2005-08-11 23:35:03 +00:00
lc_method_name = zend_u_str_case_fold ( type , method_name , method_len , 1 , & lc_method_name_len ) ;
2006-02-21 08:00:39 +00:00
2002-04-22 14:22:27 +00:00
zobj = Z_OBJ_P ( object ) ;
2005-08-11 23:35:03 +00:00
if ( zend_u_hash_find ( & zobj - > ce - > function_table , type , lc_method_name , lc_method_name_len + 1 , ( void * * ) & fbc ) = = FAILURE ) {
2006-02-21 20:12:43 +00:00
efree ( lc_method_name . v ) ;
2003-01-29 15:02:57 +00:00
if ( zobj - > ce - > __call ) {
2009-06-12 01:00:30 +00:00
return zend_get_user_call_function ( zobj - > ce , method_name , method_len ) ;
2003-01-29 15:02:57 +00:00
} else {
return NULL ;
2002-09-04 09:07:58 +00:00
}
2002-02-07 14:08:43 +00:00
}
2002-06-05 17:34:56 +00:00
2003-02-02 16:17:25 +00:00
/* Check access level */
2006-09-12 11:01:31 +00:00
if ( fbc - > op_array . fn_flags & ZEND_ACC_PRIVATE ) {
zend_function * updated_fbc ;
/* Ensure that if we're calling a private function, we're allowed to do so.
2009-01-07 22:13:07 +00:00
* If we ' re not and __call ( ) handler exists , invoke it , otherwise error out .
2006-09-12 11:01:31 +00:00
*/
updated_fbc = zend_check_private_int ( fbc , Z_OBJ_HANDLER_P ( object , get_class_entry ) ( object TSRMLS_CC ) , lc_method_name , method_len TSRMLS_CC ) ;
2009-01-07 22:13:07 +00:00
if ( updated_fbc ) {
fbc = updated_fbc ;
} else {
if ( zobj - > ce - > __call ) {
2009-06-12 01:00:30 +00:00
fbc = zend_get_user_call_function ( zobj - > ce , method_name , method_len ) ;
2009-01-07 22:13:07 +00:00
} else {
zend_error ( E_ERROR , " Call to %s method %v::%v() from context '%v' " , zend_visibility_string ( fbc - > common . fn_flags ) , ZEND_FN_SCOPE_NAME ( fbc ) , method_name , EG ( scope ) ? EG ( scope ) - > name : EMPTY_ZSTR ) ;
}
2006-09-12 11:01:31 +00:00
}
} else {
2003-02-02 16:17:25 +00:00
/* Ensure that we haven't overridden a private function and end up calling
* the overriding public function . . .
*/
2007-07-12 10:32:26 +00:00
if ( EG ( scope ) & &
is_derived_class ( fbc - > common . scope , EG ( scope ) ) & &
fbc - > op_array . fn_flags & ZEND_ACC_CHANGED ) {
2003-02-02 16:17:25 +00:00
zend_function * priv_fbc ;
2005-08-11 23:35:03 +00:00
if ( zend_u_hash_find ( & EG ( scope ) - > function_table , type , lc_method_name , lc_method_name_len + 1 , ( void * * ) & priv_fbc ) = = SUCCESS
2005-06-17 10:50:45 +00:00
& & priv_fbc - > common . fn_flags & ZEND_ACC_PRIVATE
& & priv_fbc - > common . scope = = EG ( scope ) ) {
2003-02-02 16:17:25 +00:00
fbc = priv_fbc ;
}
}
2006-09-12 11:01:31 +00:00
if ( ( fbc - > common . fn_flags & ZEND_ACC_PROTECTED ) ) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
2009-01-07 22:13:07 +00:00
* If we ' re not and __call ( ) handler exists , invoke it , otherwise error out .
2006-09-12 11:01:31 +00:00
*/
if ( ! zend_check_protected ( zend_get_function_root_class ( fbc ) , EG ( scope ) ) ) {
2009-01-07 22:13:07 +00:00
if ( zobj - > ce - > __call ) {
2009-06-12 01:00:30 +00:00
fbc = zend_get_user_call_function ( zobj - > ce , method_name , method_len ) ;
2009-01-07 22:13:07 +00:00
} else {
zend_error ( E_ERROR , " Call to %s method %v::%v() from context '%v' " , zend_visibility_string ( fbc - > common . fn_flags ) , ZEND_FN_SCOPE_NAME ( fbc ) , method_name , EG ( scope ) ? EG ( scope ) - > name : EMPTY_ZSTR ) ;
}
2006-09-12 11:01:31 +00:00
}
2003-02-02 16:17:25 +00:00
}
}
2006-02-21 20:12:43 +00:00
efree ( lc_method_name . v ) ;
2003-02-02 16:17:25 +00:00
return fbc ;
2002-02-07 14:08:43 +00:00
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-02-02 16:17:25 +00:00
2007-07-21 05:27:07 +00:00
ZEND_API void zend_std_callstatic_user_call ( INTERNAL_FUNCTION_PARAMETERS ) /* { { { */
{
2007-11-20 09:51:44 +00:00
zend_internal_function * func = ( zend_internal_function * ) EG ( current_execute_data ) - > function_state . function ;
2007-07-21 05:27:07 +00:00
zval * method_name_ptr , * method_args_ptr ;
zval * method_result_ptr = NULL ;
zend_class_entry * ce = EG ( scope ) ;
ALLOC_ZVAL ( method_args_ptr ) ;
INIT_PZVAL ( method_args_ptr ) ;
2008-05-27 10:28:25 +00:00
array_init_size ( method_args_ptr , ZEND_NUM_ARGS ( ) ) ;
2007-07-21 05:27:07 +00:00
if ( zend_copy_parameters_array ( ZEND_NUM_ARGS ( ) , method_args_ptr TSRMLS_CC ) = = FAILURE ) {
zval_dtor ( method_args_ptr ) ;
zend_error ( E_ERROR , " Cannot get arguments for " ZEND_CALLSTATIC_FUNC_NAME ) ;
RETURN_FALSE ;
}
ALLOC_ZVAL ( method_name_ptr ) ;
INIT_PZVAL ( method_name_ptr ) ;
2009-05-25 14:32:15 +00:00
ZVAL_UNICODE ( method_name_ptr , func - > function_name . u , 0 ) ; /* no dup - it's a copy */
2007-07-21 05:27:07 +00:00
/* __callStatic handler is called with two arguments:
method name
array of method parameters
*/
zend_call_method_with_2_params ( NULL , ce , & ce - > __callstatic , ZEND_CALLSTATIC_FUNC_NAME , & method_result_ptr , method_name_ptr , method_args_ptr ) ;
if ( method_result_ptr ) {
2007-10-07 05:15:07 +00:00
if ( Z_ISREF_P ( method_result_ptr ) | | Z_REFCOUNT_P ( method_result_ptr ) > 1 ) {
2007-07-21 05:27:07 +00:00
RETVAL_ZVAL ( method_result_ptr , 1 , 1 ) ;
} else {
RETVAL_ZVAL ( method_result_ptr , 0 , 1 ) ;
}
}
/* now destruct all auxiliaries */
zval_ptr_dtor ( & method_args_ptr ) ;
zval_ptr_dtor ( & method_name_ptr ) ;
/* destruct the function also, then - we have allocated it in get_method */
efree ( func ) ;
}
/* }}} */
2009-06-12 21:43:22 +00:00
static inline union _zend_function * zend_get_user_callstatic_function ( zend_class_entry * ce , const zstr method_name , int method_len ) /* { { { */
2009-06-12 01:00:30 +00:00
{
zend_internal_function * callstatic_user_call = emalloc ( sizeof ( zend_internal_function ) ) ;
callstatic_user_call - > type = ZEND_INTERNAL_FUNCTION ;
callstatic_user_call - > module = ce - > module ;
callstatic_user_call - > handler = zend_std_callstatic_user_call ;
callstatic_user_call - > arg_info = NULL ;
callstatic_user_call - > num_args = 0 ;
callstatic_user_call - > scope = ce ;
callstatic_user_call - > fn_flags = ZEND_ACC_STATIC | ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER ;
callstatic_user_call - > function_name . u = eustrndup ( method_name . u , method_len ) ;
callstatic_user_call - > pass_rest_by_reference = 0 ;
callstatic_user_call - > return_reference = ZEND_RETURN_VALUE ;
return ( union _zend_function * ) callstatic_user_call ;
}
/* }}} */
2007-07-21 05:27:07 +00:00
2007-08-30 14:48:39 +00:00
ZEND_API zend_function * zend_std_get_static_method ( zend_class_entry * ce , zend_uchar type , zstr function_name_strval , int function_name_strlen TSRMLS_DC ) /* { { { */
2003-02-02 16:17:25 +00:00
{
2008-03-17 14:53:43 +00:00
zend_function * fbc = NULL ;
2008-06-03 19:01:26 +00:00
zstr lc_function_name ;
unsigned int lc_function_name_len ;
lc_function_name = zend_u_str_case_fold ( type , function_name_strval , function_name_strlen , 0 , & lc_function_name_len ) ;
2008-03-17 14:53:43 +00:00
if ( function_name_strlen = = ce - > name_length & & ce - > constructor ) {
zstr lc_class_name ;
unsigned int lc_class_name_len , real_len ;
lc_class_name = zend_u_str_case_fold ( type , ce - > name , ce - > name_length , 0 , & lc_class_name_len ) ;
real_len = USTR_BYTES ( type , lc_class_name_len ) ;
if ( ! memcmp ( lc_class_name . s , function_name_strval . s , real_len ) ) {
fbc = ce - > constructor ;
}
efree ( lc_class_name . v ) ;
}
2003-02-02 16:17:25 +00:00
2008-06-03 19:01:26 +00:00
if ( ! fbc & & zend_u_hash_find ( & ce - > function_table , type , lc_function_name , function_name_strlen + 1 , ( void * * ) & fbc ) = = FAILURE ) {
efree ( lc_function_name . v ) ;
2007-11-12 09:12:20 +00:00
if ( ce - > __call & &
EG ( This ) & &
Z_OBJ_HT_P ( EG ( This ) ) - > get_class_entry & &
instanceof_function ( Z_OBJCE_P ( EG ( This ) ) , ce TSRMLS_CC ) ) {
2009-06-12 01:00:30 +00:00
return zend_get_user_call_function ( ce , function_name_strval , function_name_strlen ) ;
2007-11-12 09:12:20 +00:00
} else if ( ce - > __callstatic ) {
2009-06-12 01:00:30 +00:00
return zend_get_user_callstatic_function ( ce , function_name_strval , function_name_strlen ) ;
2007-07-21 05:27:07 +00:00
} else {
2008-07-26 13:14:56 +00:00
return NULL ;
2003-03-11 23:19:45 +00:00
}
2003-02-02 16:17:25 +00:00
}
2008-06-03 19:01:26 +00:00
efree ( lc_function_name . v ) ;
2007-07-21 05:27:07 +00:00
2006-01-22 18:55:02 +00:00
# if MBO_0
/* right now this function is used for non static method lookup too */
/* Is the function static */
if ( ! ( fbc - > common . fn_flags & ZEND_ACC_STATIC ) ) {
zend_error ( E_ERROR , " Cannot call non static method %v::%v() without object " , ZEND_FN_SCOPE_NAME ( fbc ) , fbc - > common . function_name ) ;
}
# endif
2003-02-02 16:17:25 +00:00
if ( fbc - > op_array . fn_flags & ZEND_ACC_PUBLIC ) {
/* No further checks necessary, most common case */
} else if ( fbc - > op_array . fn_flags & ZEND_ACC_PRIVATE ) {
zend_function * updated_fbc ;
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
2006-02-21 08:00:39 +00:00
updated_fbc = zend_check_private_int ( fbc , EG ( scope ) , function_name_strval , function_name_strlen TSRMLS_CC ) ;
2009-06-12 01:00:30 +00:00
if ( updated_fbc ) {
fbc = updated_fbc ;
} else {
if ( ce - > __callstatic ) {
return zend_get_user_callstatic_function ( ce , function_name_strval , function_name_strlen ) ;
}
2006-02-26 11:57:14 +00:00
zend_error ( E_ERROR , " Call to %s method %v::%v() from context '%v' " , zend_visibility_string ( fbc - > common . fn_flags ) , ZEND_FN_SCOPE_NAME ( fbc ) , fbc - > common . function_name , EG ( scope ) ? EG ( scope ) - > name : EMPTY_ZSTR ) ;
2009-06-12 01:00:30 +00:00
}
2003-02-02 16:17:25 +00:00
} else if ( ( fbc - > common . fn_flags & ZEND_ACC_PROTECTED ) ) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
2006-05-29 19:57:43 +00:00
if ( ! zend_check_protected ( zend_get_function_root_class ( fbc ) , EG ( scope ) ) ) {
2009-06-12 01:00:30 +00:00
if ( ce - > __callstatic ) {
return zend_get_user_callstatic_function ( ce , function_name_strval , function_name_strlen ) ;
}
2006-02-26 11:57:14 +00:00
zend_error ( E_ERROR , " Call to %s method %v::%v() from context '%v' " , zend_visibility_string ( fbc - > common . fn_flags ) , ZEND_FN_SCOPE_NAME ( fbc ) , fbc - > common . function_name , EG ( scope ) ? EG ( scope ) - > name : EMPTY_ZSTR ) ;
2003-02-02 16:17:25 +00:00
}
}
return fbc ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-02-02 16:17:25 +00:00
2007-07-11 11:19:58 +00:00
ZEND_API zval * * zend_std_get_static_property ( zend_class_entry * ce , zend_uchar type , zstr property_name , int property_name_len , zend_bool silent TSRMLS_DC ) /* { { { */
2003-02-05 13:35:52 +00:00
{
zval * * retval = NULL ;
zend_class_entry * tmp_ce = ce ;
zend_property_info * property_info ;
zend_property_info std_property_info ;
2005-08-11 23:35:03 +00:00
if ( zend_u_hash_find ( & ce - > properties_info , type , property_name , property_name_len + 1 , ( void * * ) & property_info ) = = FAILURE ) {
2003-06-02 12:13:11 +00:00
std_property_info . flags = ZEND_ACC_PUBLIC ;
std_property_info . name = property_name ;
std_property_info . name_length = property_name_len ;
2009-03-26 20:02:53 +00:00
std_property_info . h = zend_u_get_hash_value ( IS_UNICODE , std_property_info . name , std_property_info . name_length + 1 ) ;
2006-05-27 02:12:43 +00:00
std_property_info . ce = ce ;
2003-06-02 12:13:11 +00:00
property_info = & std_property_info ;
}
2003-02-05 13:35:52 +00:00
2005-05-18 15:14:36 +00:00
# if DEBUG_OBJECT_HANDLERS
2005-08-19 13:20:16 +00:00
zend_printf ( " Access type for %v::%R is %s \n " , ce - > name , type , property_name , zend_visibility_string ( property_info - > flags ) ) ;
2003-02-05 13:35:52 +00:00
# endif
2005-05-18 15:30:35 +00:00
if ( ! zend_verify_property_access ( property_info , ce TSRMLS_CC ) ) {
2005-02-27 22:22:26 +00:00
if ( ! silent ) {
2005-08-19 13:20:16 +00:00
zend_error ( E_ERROR , " Cannot access %s property %v::$%R " , zend_visibility_string ( property_info - > flags ) , ce - > name , type , property_name ) ;
2005-02-27 22:22:26 +00:00
}
return NULL ;
2003-06-02 12:13:11 +00:00
}
2003-02-05 13:35:52 +00:00
2005-09-01 10:05:01 +00:00
zend_update_class_constants ( tmp_ce TSRMLS_CC ) ;
2009-03-26 20:02:53 +00:00
zend_u_hash_quick_find ( CE_STATIC_MEMBERS ( tmp_ce ) , IS_UNICODE , property_info - > name , property_info - > name_length + 1 , property_info - > h , ( void * * ) & retval ) ;
2003-02-05 13:35:52 +00:00
if ( ! retval ) {
2003-02-17 14:06:39 +00:00
if ( silent ) {
return NULL ;
} else {
2007-11-17 21:51:40 +00:00
zend_error ( E_ERROR , " Access to undeclared static property: %v::$%R " , ce - > name , type , property_name ) ;
2003-02-05 13:35:52 +00:00
}
}
2006-02-21 08:00:39 +00:00
2003-02-05 13:35:52 +00:00
return retval ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-02-05 13:35:52 +00:00
2007-07-11 11:19:58 +00:00
ZEND_API zend_bool zend_std_unset_static_property ( zend_class_entry * ce , zend_uchar type , zstr property_name , int property_name_len TSRMLS_DC ) /* { { { */
2003-02-17 14:06:39 +00:00
{
2005-08-19 13:20:16 +00:00
zend_error ( E_ERROR , " Attempt to unset static property %v::$%R " , ce - > name , type , property_name ) ;
2003-02-17 14:06:39 +00:00
return 0 ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-02-17 14:06:39 +00:00
2007-07-11 11:19:58 +00:00
ZEND_API union _zend_function * zend_std_get_constructor ( zval * object TSRMLS_DC ) /* { { { */
2002-02-07 14:08:43 +00:00
{
2003-02-02 16:17:25 +00:00
zend_object * zobj = Z_OBJ_P ( object ) ;
zend_function * constructor = zobj - > ce - > constructor ;
if ( constructor ) {
if ( constructor - > op_array . fn_flags & ZEND_ACC_PUBLIC ) {
/* No further checks necessary */
} else if ( constructor - > op_array . fn_flags & ZEND_ACC_PRIVATE ) {
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
2008-02-21 13:55:55 +00:00
if ( constructor - > common . scope ! = EG ( scope ) ) {
2006-07-05 11:38:13 +00:00
if ( EG ( scope ) ) {
zend_error ( E_ERROR , " Call to private %v::%v() from context '%v' " , constructor - > common . scope - > name , constructor - > common . function_name , EG ( scope ) - > name ) ;
} else {
zend_error ( E_ERROR , " Call to private %v::%v() from invalid context " , constructor - > common . scope - > name , constructor - > common . function_name ) ;
}
2003-02-02 16:17:25 +00:00
}
} else if ( ( constructor - > common . fn_flags & ZEND_ACC_PROTECTED ) ) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
2006-05-29 19:57:43 +00:00
* Constructors only have prototype if they are defined by an interface but
* it is the compilers responsibility to take care of the prototype .
2003-02-02 16:17:25 +00:00
*/
2006-05-29 19:57:43 +00:00
if ( ! zend_check_protected ( zend_get_function_root_class ( constructor ) , EG ( scope ) ) ) {
2006-07-05 11:38:13 +00:00
if ( EG ( scope ) ) {
zend_error ( E_ERROR , " Call to protected %v::%v() from context '%v' " , constructor - > common . scope - > name , constructor - > common . function_name , EG ( scope ) - > name ) ;
} else {
zend_error ( E_ERROR , " Call to protected %v::%v() from invalid context " , constructor - > common . scope - > name , constructor - > common . function_name ) ;
}
2003-02-02 16:17:25 +00:00
}
}
}
return constructor ;
2002-02-07 14:08:43 +00:00
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-02-05 14:27:30 +00:00
2002-02-07 14:08:43 +00:00
int zend_compare_symbol_tables_i ( HashTable * ht1 , HashTable * ht2 TSRMLS_DC ) ;
2007-07-11 11:19:58 +00:00
static int zend_std_compare_objects ( zval * o1 , zval * o2 TSRMLS_DC ) /* { { { */
2002-02-07 14:08:43 +00:00
{
zend_object * zobj1 , * zobj2 ;
2006-02-21 08:00:39 +00:00
2002-04-22 14:22:27 +00:00
zobj1 = Z_OBJ_P ( o1 ) ;
zobj2 = Z_OBJ_P ( o2 ) ;
2002-02-07 14:08:43 +00:00
2002-09-15 07:45:26 +00:00
if ( zobj1 - > ce ! = zobj2 - > ce ) {
2002-02-07 14:08:43 +00:00
return 1 ; /* different classes */
}
return zend_compare_symbol_tables_i ( zobj1 - > properties , zobj2 - > properties TSRMLS_CC ) ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2002-02-07 14:08:43 +00:00
2007-07-11 11:19:58 +00:00
static int zend_std_has_property ( zval * object , zval * member , int has_set_exists TSRMLS_DC ) /* { { { */
2002-02-07 14:08:43 +00:00
{
zend_object * zobj ;
int result ;
zval * * value ;
2005-07-07 16:07:09 +00:00
zval * tmp_member = NULL ;
2003-02-05 14:27:30 +00:00
zend_property_info * property_info ;
2006-02-21 08:00:39 +00:00
2003-02-05 14:27:30 +00:00
zobj = Z_OBJ_P ( object ) ;
2009-03-26 20:02:53 +00:00
if ( Z_TYPE_P ( member ) ! = IS_UNICODE ) {
2006-05-09 21:26:39 +00:00
ALLOC_ZVAL ( tmp_member ) ;
2005-07-07 16:07:09 +00:00
* tmp_member = * member ;
INIT_PZVAL ( tmp_member ) ;
zval_copy_ctor ( tmp_member ) ;
2009-03-26 20:02:53 +00:00
convert_to_unicode ( tmp_member ) ;
2005-07-07 16:07:09 +00:00
member = tmp_member ;
2002-02-07 14:08:43 +00:00
}
2003-02-05 14:27:30 +00:00
# if DEBUG_OBJECT_HANDLERS
2005-08-12 11:29:33 +00:00
fprintf ( stderr , " Read object #%d property: %R \n " , Z_OBJ_HANDLE_P ( object ) , Z_TYPE_P ( member ) , Z_STRVAL_P ( member ) ) ;
2006-02-21 08:00:39 +00:00
# endif
2003-02-05 14:27:30 +00:00
2005-07-07 16:07:09 +00:00
property_info = zend_get_property_info ( zobj - > ce , member , 1 TSRMLS_CC ) ;
2005-08-11 23:35:03 +00:00
if ( ! property_info | | zend_u_hash_quick_find ( zobj - > properties , Z_TYPE_P ( member ) , property_info - > name , property_info - > name_length + 1 , property_info - > h , ( void * * ) & value ) = = FAILURE ) {
2005-11-15 15:21:47 +00:00
zend_guard * guard ;
2005-07-07 16:07:09 +00:00
result = 0 ;
2005-11-15 15:21:47 +00:00
if ( ( has_set_exists ! = 2 ) & &
zobj - > ce - > __isset & &
zend_get_property_guard ( zobj , property_info , member , & guard TSRMLS_CC ) = = SUCCESS & &
! guard - > in_isset ) {
2005-07-07 16:07:09 +00:00
zval * rv ;
2003-02-05 14:27:30 +00:00
2005-07-07 16:07:09 +00:00
/* have issetter - try with it! */
2008-10-17 10:26:16 +00:00
Z_ADDREF_P ( object ) ;
2005-11-15 15:21:47 +00:00
guard - > in_isset = 1 ; /* prevent circular getting */
2005-07-07 16:07:09 +00:00
rv = zend_std_call_issetter ( object , member TSRMLS_CC ) ;
if ( rv ) {
result = zend_is_true ( rv ) ;
zval_ptr_dtor ( & rv ) ;
2008-05-03 00:36:54 +00:00
if ( has_set_exists & & result ) {
if ( ! EG ( exception ) & & zobj - > ce - > __get & & ! guard - > in_get ) {
guard - > in_get = 1 ;
rv = zend_std_call_getter ( object , member TSRMLS_CC ) ;
guard - > in_get = 0 ;
if ( rv ) {
Z_ADDREF_P ( rv ) ;
result = i_zend_is_true ( rv ) ;
zval_ptr_dtor ( & rv ) ;
} else {
result = 0 ;
}
} else {
result = 0 ;
2005-07-07 16:07:09 +00:00
}
}
}
2005-11-15 15:21:47 +00:00
guard - > in_isset = 0 ;
2008-10-17 10:26:16 +00:00
zval_ptr_dtor ( & object ) ;
2005-07-07 16:07:09 +00:00
}
} else {
2005-05-02 16:18:02 +00:00
switch ( has_set_exists ) {
case 0 :
2005-04-25 20:41:26 +00:00
result = ( Z_TYPE_PP ( value ) ! = IS_NULL ) ;
2005-05-02 16:18:02 +00:00
break ;
default :
result = zend_is_true ( * value ) ;
break ;
case 2 :
result = 1 ;
break ;
2002-02-07 14:08:43 +00:00
}
}
2005-07-07 16:07:09 +00:00
if ( tmp_member ) {
zval_ptr_dtor ( & tmp_member ) ;
2002-02-07 14:08:43 +00:00
}
return result ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2002-02-07 14:08:43 +00:00
2008-08-12 17:15:59 +00:00
zend_class_entry * zend_std_object_get_class ( const zval * object TSRMLS_DC ) /* { { { */
2002-04-30 09:56:48 +00:00
{
zend_object * zobj ;
zobj = Z_OBJ_P ( object ) ;
return zobj - > ce ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2002-04-30 09:56:48 +00:00
2008-08-12 17:15:59 +00:00
int zend_std_object_get_class_name ( const zval * object , zstr * class_name , zend_uint * class_name_len , int parent TSRMLS_DC ) /* { { { */
2003-01-12 13:56:51 +00:00
{
zend_object * zobj ;
2003-04-21 17:01:34 +00:00
zend_class_entry * ce ;
2003-01-12 13:56:51 +00:00
zobj = Z_OBJ_P ( object ) ;
2003-01-14 12:13:51 +00:00
if ( parent ) {
if ( ! zobj - > ce - > parent ) {
2003-01-12 13:56:51 +00:00
return FAILURE ;
}
2003-04-21 17:01:34 +00:00
ce = zobj - > ce - > parent ;
2003-01-12 13:56:51 +00:00
} else {
2003-04-21 17:01:34 +00:00
ce = zobj - > ce ;
2003-01-12 13:56:51 +00:00
}
2003-04-21 17:01:34 +00:00
2003-06-04 08:16:55 +00:00
* class_name_len = ce - > name_length ;
2009-03-26 20:02:53 +00:00
class_name - > u = eustrndup ( ce - > name . u , ce - > name_length ) ;
2003-01-12 13:56:51 +00:00
return SUCCESS ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-01-12 13:56:51 +00:00
2007-07-11 11:19:58 +00:00
ZEND_API int zend_std_cast_object_tostring ( zval * readobj , zval * writeobj , int type , void * extra TSRMLS_DC ) /* { { { */
2003-12-15 16:59:21 +00:00
{
2005-09-27 07:59:18 +00:00
zval * retval ;
zend_class_entry * ce ;
2006-10-13 14:52:19 +00:00
UConverter * conv ;
2005-10-05 19:02:27 +00:00
2003-12-15 16:59:21 +00:00
switch ( type ) {
case IS_STRING :
2005-08-11 23:35:03 +00:00
case IS_UNICODE :
2006-10-13 14:52:19 +00:00
if ( extra ) {
conv = ( UConverter * ) extra ;
} else {
conv = ZEND_U_CONVERTER ( UG ( runtime_encoding_conv ) ) ;
}
2005-09-27 07:59:18 +00:00
ce = Z_OBJCE_P ( readobj ) ;
if ( ce - > __tostring & &
2006-05-10 21:11:48 +00:00
( zend_call_method_with_0_params ( & readobj , ce , & ce - > __tostring , " __tostring " , & retval ) | | EG ( exception ) ) ) {
2005-10-05 19:02:27 +00:00
if ( EG ( exception ) ) {
2006-05-10 21:11:48 +00:00
if ( retval ) {
zval_ptr_dtor ( & retval ) ;
}
2006-05-18 21:14:40 +00:00
zend_error ( E_ERROR , " Method %v::__toString() must not throw an exception " , ce - > name ) ;
2005-10-05 19:02:27 +00:00
return FAILURE ;
}
2009-03-26 20:02:53 +00:00
if ( Z_TYPE_P ( retval ) = = IS_UNICODE ) {
2005-09-27 07:59:18 +00:00
INIT_PZVAL ( writeobj ) ;
2007-12-21 20:56:10 +00:00
if ( readobj = = writeobj ) {
zval_dtor ( readobj ) ;
}
2005-10-05 19:02:27 +00:00
ZVAL_ZVAL ( writeobj , retval , 1 , 1 ) ;
2005-09-27 07:59:18 +00:00
if ( Z_TYPE_P ( writeobj ) ! = type ) {
2006-10-13 14:52:19 +00:00
if ( type = = IS_UNICODE ) {
convert_to_unicode_with_converter ( writeobj , conv ) ;
} else {
convert_to_string_with_converter ( writeobj , conv ) ;
}
2003-12-15 16:59:21 +00:00
}
2005-09-27 07:59:18 +00:00
return SUCCESS ;
2003-12-15 16:59:21 +00:00
} else {
2005-09-27 07:59:18 +00:00
zval_ptr_dtor ( & retval ) ;
2005-10-05 19:02:27 +00:00
INIT_PZVAL ( writeobj ) ;
2007-12-21 20:56:10 +00:00
if ( readobj = = writeobj ) {
zval_dtor ( readobj ) ;
}
2008-03-17 15:05:28 +00:00
if ( type = = IS_UNICODE ) {
ZVAL_EMPTY_UNICODE ( writeobj ) ;
} else {
ZVAL_EMPTY_STRING ( writeobj ) ;
}
2005-09-27 07:59:18 +00:00
zend_error ( E_RECOVERABLE_ERROR , " Method %v::__toString() must return a string value " , ce - > name ) ;
2005-10-05 19:02:27 +00:00
return SUCCESS ;
2003-12-15 16:59:21 +00:00
}
2005-08-11 23:35:03 +00:00
}
2005-09-27 07:59:18 +00:00
return FAILURE ;
2005-10-06 18:46:01 +00:00
case IS_BOOL :
INIT_PZVAL ( writeobj ) ;
ZVAL_BOOL ( writeobj , 1 ) ;
return SUCCESS ;
2005-10-06 19:11:01 +00:00
case IS_LONG :
ce = Z_OBJCE_P ( readobj ) ;
zend_error ( E_NOTICE , " Object of class %v could not be converted to int " , ce - > name ) ;
INIT_PZVAL ( writeobj ) ;
2007-12-21 20:56:10 +00:00
if ( readobj = = writeobj ) {
zval_dtor ( readobj ) ;
}
2005-10-06 19:11:01 +00:00
ZVAL_LONG ( writeobj , 1 ) ;
return SUCCESS ;
case IS_DOUBLE :
ce = Z_OBJCE_P ( readobj ) ;
zend_error ( E_NOTICE , " Object of class %v could not be converted to double " , ce - > name ) ;
INIT_PZVAL ( writeobj ) ;
2007-12-21 20:56:10 +00:00
if ( readobj = = writeobj ) {
zval_dtor ( writeobj ) ;
}
2005-10-06 19:11:01 +00:00
ZVAL_DOUBLE ( writeobj , 1 ) ;
return SUCCESS ;
2003-12-15 16:59:21 +00:00
default :
2007-12-21 20:56:10 +00:00
INIT_PZVAL ( writeobj ) ;
Z_TYPE_P ( writeobj ) = IS_NULL ;
2003-12-15 16:59:21 +00:00
break ;
}
return FAILURE ;
}
2007-07-11 11:19:58 +00:00
/* }}} */
2003-09-18 11:38:33 +00:00
2008-11-27 19:02:45 +00:00
int zend_std_get_closure ( zval * obj , zend_class_entry * * ce_ptr , zend_function * * fptr_ptr , zval * * zobj_ptr TSRMLS_DC ) /* { { { */
2008-08-14 21:26:05 +00:00
{
zstr key ;
2009-03-26 20:02:53 +00:00
zend_uchar utype = IS_UNICODE ;
2008-08-14 21:26:05 +00:00
zend_class_entry * ce ;
if ( Z_TYPE_P ( obj ) ! = IS_OBJECT ) {
return FAILURE ;
}
ce = Z_OBJCE_P ( obj ) ;
if ( utype = = IS_UNICODE ) {
key . u = USTR_MAKE ( ZEND_INVOKE_FUNC_NAME ) ;
} else {
key . s = ZEND_INVOKE_FUNC_NAME ;
}
if ( zend_u_hash_find ( & ce - > function_table , utype , key , sizeof ( ZEND_INVOKE_FUNC_NAME ) , ( void * * ) fptr_ptr ) = = FAILURE ) {
if ( utype = = IS_UNICODE ) {
efree ( key . u ) ;
}
return FAILURE ;
}
* ce_ptr = ce ;
if ( ( * fptr_ptr ) - > common . fn_flags & ZEND_ACC_STATIC ) {
if ( zobj_ptr ) {
* zobj_ptr = NULL ;
}
} else {
if ( zobj_ptr ) {
* zobj_ptr = obj ;
}
}
if ( utype = = IS_UNICODE ) {
efree ( key . u ) ;
}
return SUCCESS ;
}
/* }}} */
2003-12-22 13:09:15 +00:00
ZEND_API zend_object_handlers std_object_handlers = {
2003-07-07 09:12:15 +00:00
zend_objects_store_add_ref , /* add_ref */
zend_objects_store_del_ref , /* del_ref */
zend_objects_clone_obj , /* clone_obj */
2006-02-21 08:00:39 +00:00
2003-07-07 09:12:15 +00:00
zend_std_read_property , /* read_property */
zend_std_write_property , /* write_property */
2003-07-07 10:53:27 +00:00
zend_std_read_dimension , /* read_dimension */
2003-07-07 09:12:15 +00:00
zend_std_write_dimension , /* write_dimension */
2003-10-05 07:52:28 +00:00
zend_std_get_property_ptr_ptr , /* get_property_ptr_ptr */
2003-07-07 09:12:15 +00:00
NULL , /* get */
NULL , /* set */
zend_std_has_property , /* has_property */
zend_std_unset_property , /* unset_property */
2003-11-10 16:14:44 +00:00
zend_std_has_dimension , /* has_dimension */
2003-07-30 17:12:06 +00:00
zend_std_unset_dimension , /* unset_dimension */
2003-07-07 09:12:15 +00:00
zend_std_get_properties , /* get_properties */
zend_std_get_method , /* get_method */
NULL , /* call_method */
zend_std_get_constructor , /* get_constructor */
zend_std_object_get_class , /* get_class_entry */
zend_std_object_get_class_name , /* get_class_name */
zend_std_compare_objects , /* compare_objects */
2005-09-27 07:59:18 +00:00
zend_std_cast_object_tostring , /* cast_object */
2004-05-04 15:03:28 +00:00
NULL , /* count_elements */
2008-08-14 21:26:05 +00:00
NULL , /* get_debug_info */
zend_std_get_closure , /* get_closure */
2002-02-07 14:08:43 +00:00
} ;
2003-02-01 01:49:15 +00:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* indent - tabs - mode : t
* End :
*/