@@ -1924,18 +1924,18 @@ PHP_FUNCTION(session_module_name)
1924
1924
}
1925
1925
/* }}} */
1926
1926
1927
- static zend_result save_handler_check_session (void ) {
1927
+ static bool can_session_handler_be_changed (void ) {
1928
1928
if (PS (session_status ) == php_session_active ) {
1929
1929
php_error_docref (NULL , E_WARNING , "Session save handler cannot be changed when a session is active" );
1930
- return FAILURE ;
1930
+ return false ;
1931
1931
}
1932
1932
1933
1933
if (SG (headers_sent )) {
1934
1934
php_error_docref (NULL , E_WARNING , "Session save handler cannot be changed after headers have already been sent" );
1935
- return FAILURE ;
1935
+ return false ;
1936
1936
}
1937
1937
1938
- return SUCCESS ;
1938
+ return true ;
1939
1939
}
1940
1940
1941
1941
static inline void set_user_save_handler_ini (void ) {
@@ -1950,91 +1950,107 @@ static inline void set_user_save_handler_ini(void) {
1950
1950
zend_string_release_ex (ini_name , 0 );
1951
1951
}
1952
1952
1953
+ #define SESSION_RELEASE_USER_HANDLER_OO (struct_name ) \
1954
+ if (!Z_ISUNDEF(PS(mod_user_names).name.struct_name)) { \
1955
+ zval_ptr_dtor(&PS(mod_user_names).name.struct_name); \
1956
+ ZVAL_UNDEF(&PS(mod_user_names).name.struct_name); \
1957
+ }
1958
+
1959
+ #define SESSION_SET_USER_HANDLER_OO (struct_name , zstr_method_name ) \
1960
+ array_init_size(&PS(mod_user_names).name.struct_name, 2); \
1961
+ Z_ADDREF_P(obj); \
1962
+ add_next_index_zval(&PS(mod_user_names).name.struct_name, obj); \
1963
+ add_next_index_str(&PS(mod_user_names).name.struct_name, zstr_method_name);
1964
+
1965
+ #define SESSION_SET_USER_HANDLER_OO_MANDATORY (struct_name , method_name ) \
1966
+ if (!Z_ISUNDEF(PS(mod_user_names).name.struct_name)) { \
1967
+ zval_ptr_dtor(&PS(mod_user_names).name.struct_name); \
1968
+ } \
1969
+ array_init_size(&PS(mod_user_names).name.struct_name, 2); \
1970
+ Z_ADDREF_P(obj); \
1971
+ add_next_index_zval(&PS(mod_user_names).name.struct_name, obj); \
1972
+ add_next_index_str(&PS(mod_user_names).name.struct_name, zend_string_init(method_name, strlen(method_name), false));
1973
+
1974
+ #define SESSION_SET_USER_HANDLER_PROCEDURAL (struct_name , fci ) \
1975
+ if (!Z_ISUNDEF(PS(mod_user_names).name.struct_name)) { \
1976
+ zval_ptr_dtor(&PS(mod_user_names).name.struct_name); \
1977
+ } \
1978
+ ZVAL_COPY(&PS(mod_user_names).name.struct_name, &fci.function_name);
1979
+
1980
+ #define SESSION_SET_USER_HANDLER_PROCEDURAL_OPTIONAL (struct_name , fci ) \
1981
+ if (ZEND_FCI_INITIALIZED(fci)) { \
1982
+ SESSION_SET_USER_HANDLER_PROCEDURAL(struct_name, fci); \
1983
+ }
1984
+
1953
1985
/* {{{ Sets user-level functions */
1954
1986
PHP_FUNCTION (session_set_save_handler )
1955
1987
{
1956
- zval * args = NULL ;
1957
- int i , num_args , argc = ZEND_NUM_ARGS ();
1958
-
1959
- if (argc > 0 && argc <= 2 ) {
1988
+ /* OOP Version */
1989
+ if (ZEND_NUM_ARGS () <= 2 ) {
1960
1990
zval * obj = NULL ;
1961
- zend_string * func_name ;
1962
- zend_function * current_mptr ;
1963
1991
bool register_shutdown = 1 ;
1964
1992
1965
1993
if (zend_parse_parameters (ZEND_NUM_ARGS (), "O|b" , & obj , php_session_iface_entry , & register_shutdown ) == FAILURE ) {
1966
1994
RETURN_THROWS ();
1967
1995
}
1968
1996
1969
- if (save_handler_check_session () == FAILURE ) {
1997
+ if (! can_session_handler_be_changed () ) {
1970
1998
RETURN_FALSE ;
1971
1999
}
1972
2000
1973
- /* For compatibility reason, implemented interface is not checked */
1974
- /* Find implemented methods - SessionHandlerInterface */
1975
- i = 0 ;
1976
- ZEND_HASH_MAP_FOREACH_STR_KEY (& php_session_iface_entry -> function_table , func_name ) {
1977
- if ((current_mptr = zend_hash_find_ptr (& Z_OBJCE_P (obj )-> function_table , func_name ))) {
1978
- if (!Z_ISUNDEF (PS (mod_user_names ).names [i ])) {
1979
- zval_ptr_dtor (& PS (mod_user_names ).names [i ]);
1980
- }
2001
+ if (PS (mod_user_class_name )) {
2002
+ zend_string_release (PS (mod_user_class_name ));
2003
+ }
2004
+ PS (mod_user_class_name ) = zend_string_copy (Z_OBJCE_P (obj )-> name );
1981
2005
1982
- array_init_size (& PS (mod_user_names ).names [i ], 2 );
1983
- Z_ADDREF_P (obj );
1984
- add_next_index_zval (& PS (mod_user_names ).names [i ], obj );
1985
- add_next_index_str (& PS (mod_user_names ).names [i ], zend_string_copy (func_name ));
1986
- } else {
1987
- php_error_docref (NULL , E_ERROR , "Session save handler function table is corrupt" );
1988
- RETURN_FALSE ;
1989
- }
2006
+ /* Define mandatory handlers */
2007
+ SESSION_SET_USER_HANDLER_OO_MANDATORY (ps_open , "open" );
2008
+ SESSION_SET_USER_HANDLER_OO_MANDATORY (ps_close , "close" );
2009
+ SESSION_SET_USER_HANDLER_OO_MANDATORY (ps_read , "read" );
2010
+ SESSION_SET_USER_HANDLER_OO_MANDATORY (ps_write , "write" );
2011
+ SESSION_SET_USER_HANDLER_OO_MANDATORY (ps_destroy , "destroy" );
2012
+ SESSION_SET_USER_HANDLER_OO_MANDATORY (ps_gc , "gc" );
1990
2013
1991
- ++ i ;
1992
- } ZEND_HASH_FOREACH_END () ;
2014
+ /* Elements of object_methods HashTable are zend_function *method */
2015
+ HashTable * object_methods = & Z_OBJCE_P ( obj ) -> function_table ;
1993
2016
1994
2017
/* Find implemented methods - SessionIdInterface (optional) */
1995
- ZEND_HASH_MAP_FOREACH_STR_KEY (& php_session_id_iface_entry -> function_table , func_name ) {
1996
- if ((current_mptr = zend_hash_find_ptr (& Z_OBJCE_P (obj )-> function_table , func_name ))) {
1997
- if (!Z_ISUNDEF (PS (mod_user_names ).names [i ])) {
1998
- zval_ptr_dtor (& PS (mod_user_names ).names [i ]);
1999
- }
2000
- array_init_size (& PS (mod_user_names ).names [i ], 2 );
2001
- Z_ADDREF_P (obj );
2002
- add_next_index_zval (& PS (mod_user_names ).names [i ], obj );
2003
- add_next_index_str (& PS (mod_user_names ).names [i ], zend_string_copy (func_name ));
2004
- } else {
2005
- if (!Z_ISUNDEF (PS (mod_user_names ).names [i ])) {
2006
- zval_ptr_dtor (& PS (mod_user_names ).names [i ]);
2007
- ZVAL_UNDEF (& PS (mod_user_names ).names [i ]);
2008
- }
2009
- }
2010
-
2011
- ++ i ;
2012
- } ZEND_HASH_FOREACH_END ();
2018
+ /* First release old handlers */
2019
+ SESSION_RELEASE_USER_HANDLER_OO (ps_create_sid );
2020
+ zend_string * create_sid_name = zend_string_init ("create_sid" , strlen ("create_sid" ), false);
2021
+ if (instanceof_function (Z_OBJCE_P (obj ), php_session_id_iface_entry )) {
2022
+ SESSION_SET_USER_HANDLER_OO (ps_create_sid , zend_string_copy (create_sid_name ));
2023
+ } else if (zend_hash_find_ptr (object_methods , create_sid_name )) {
2024
+ /* For BC reasons we accept methods even if the class does not implement the interface */
2025
+ SESSION_SET_USER_HANDLER_OO (ps_create_sid , zend_string_copy (create_sid_name ));
2026
+ }
2027
+ zend_string_release_ex (create_sid_name , false);
2013
2028
2014
2029
/* Find implemented methods - SessionUpdateTimestampInterface (optional) */
2015
- ZEND_HASH_MAP_FOREACH_STR_KEY (& php_session_update_timestamp_iface_entry -> function_table , func_name ) {
2016
- if ((current_mptr = zend_hash_find_ptr (& Z_OBJCE_P (obj )-> function_table , func_name ))) {
2017
- if (!Z_ISUNDEF (PS (mod_user_names ).names [i ])) {
2018
- zval_ptr_dtor (& PS (mod_user_names ).names [i ]);
2019
- }
2020
- array_init_size (& PS (mod_user_names ).names [i ], 2 );
2021
- Z_ADDREF_P (obj );
2022
- add_next_index_zval (& PS (mod_user_names ).names [i ], obj );
2023
- add_next_index_str (& PS (mod_user_names ).names [i ], zend_string_copy (func_name ));
2024
- } else {
2025
- if (!Z_ISUNDEF (PS (mod_user_names ).names [i ])) {
2026
- zval_ptr_dtor (& PS (mod_user_names ).names [i ]);
2027
- ZVAL_UNDEF (& PS (mod_user_names ).names [i ]);
2028
- }
2030
+ /* First release old handlers */
2031
+ SESSION_RELEASE_USER_HANDLER_OO (ps_validate_sid );
2032
+ SESSION_RELEASE_USER_HANDLER_OO (ps_update_timestamp );
2033
+ /* Method names need to be lowercase */
2034
+ zend_string * validate_sid_name = zend_string_init ("validateid" , strlen ("validateid" ), false);
2035
+ zend_string * update_timestamp_name = zend_string_init ("updatetimestamp" , strlen ("updatetimestamp" ), false);
2036
+ if (instanceof_function (Z_OBJCE_P (obj ), php_session_update_timestamp_iface_entry )) {
2037
+ /* Validate ID handler */
2038
+ SESSION_SET_USER_HANDLER_OO (ps_validate_sid , zend_string_copy (validate_sid_name ));
2039
+ /* Update Timestamp handler */
2040
+ SESSION_SET_USER_HANDLER_OO (ps_update_timestamp , zend_string_copy (update_timestamp_name ));
2041
+ } else {
2042
+ /* For BC reasons we accept methods even if the class does not implement the interface */
2043
+ if (zend_hash_find_ptr (object_methods , validate_sid_name )) {
2044
+ /* For BC reasons we accept methods even if the class does not implement the interface */
2045
+ SESSION_SET_USER_HANDLER_OO (ps_validate_sid , zend_string_copy (validate_sid_name ));
2046
+ }
2047
+ if (zend_hash_find_ptr (object_methods , update_timestamp_name )) {
2048
+ /* For BC reasons we accept methods even if the class does not implement the interface */
2049
+ SESSION_SET_USER_HANDLER_OO (ps_update_timestamp , zend_string_copy (update_timestamp_name ));
2029
2050
}
2030
- ++ i ;
2031
- } ZEND_HASH_FOREACH_END ();
2032
-
2033
-
2034
- if (PS (mod_user_class_name )) {
2035
- zend_string_release (PS (mod_user_class_name ));
2036
2051
}
2037
- PS (mod_user_class_name ) = zend_string_copy (Z_OBJCE_P (obj )-> name );
2052
+ zend_string_release_ex (validate_sid_name , false);
2053
+ zend_string_release_ex (update_timestamp_name , false);
2038
2054
2039
2055
if (register_shutdown ) {
2040
2056
/* create shutdown function */
@@ -2049,14 +2065,14 @@ PHP_FUNCTION(session_set_save_handler)
2049
2065
ZEND_ASSERT (result == SUCCESS );
2050
2066
2051
2067
/* add shutdown function, removing the old one if it exists */
2052
- if (!register_user_shutdown_function ("session_shutdown" , sizeof ("session_shutdown" ) - 1 , & shutdown_function_entry )) {
2068
+ if (!register_user_shutdown_function ("session_shutdown" , strlen ("session_shutdown" ), & shutdown_function_entry )) {
2053
2069
zval_ptr_dtor (& callable );
2054
2070
php_error_docref (NULL , E_WARNING , "Unable to register session shutdown function" );
2055
2071
RETURN_FALSE ;
2056
2072
}
2057
2073
} else {
2058
2074
/* remove shutdown function */
2059
- remove_user_shutdown_function ("session_shutdown" , sizeof ("session_shutdown" ) - 1 );
2075
+ remove_user_shutdown_function ("session_shutdown" , strlen ("session_shutdown" ));
2060
2076
}
2061
2077
2062
2078
if (PS (session_status ) != php_session_active && (!PS (mod ) || PS (mod ) != & ps_mod_user )) {
@@ -2066,47 +2082,69 @@ PHP_FUNCTION(session_set_save_handler)
2066
2082
RETURN_TRUE ;
2067
2083
}
2068
2084
2069
- /* Set procedural save handler functions */
2070
- if (argc < 6 || PS_NUM_APIS < argc ) {
2071
- WRONG_PARAM_COUNT ;
2072
- }
2073
-
2074
- if (zend_parse_parameters (argc , "+" , & args , & num_args ) == FAILURE ) {
2085
+ /* Procedural version */
2086
+ zend_fcall_info open_fci = {0 };
2087
+ zend_fcall_info_cache open_fcc ;
2088
+ zend_fcall_info close_fci = {0 };
2089
+ zend_fcall_info_cache close_fcc ;
2090
+ zend_fcall_info read_fci = {0 };
2091
+ zend_fcall_info_cache read_fcc ;
2092
+ zend_fcall_info write_fci = {0 };
2093
+ zend_fcall_info_cache write_fcc ;
2094
+ zend_fcall_info destroy_fci = {0 };
2095
+ zend_fcall_info_cache destroy_fcc ;
2096
+ zend_fcall_info gc_fci = {0 };
2097
+ zend_fcall_info_cache gc_fcc ;
2098
+ zend_fcall_info create_id_fci = {0 };
2099
+ zend_fcall_info_cache create_id_fcc ;
2100
+ zend_fcall_info validate_id_fci = {0 };
2101
+ zend_fcall_info_cache validate_id_fcc ;
2102
+ zend_fcall_info update_timestamp_fci = {0 };
2103
+ zend_fcall_info_cache update_timestamp_fcc ;
2104
+
2105
+ if (zend_parse_parameters (ZEND_NUM_ARGS (),
2106
+ "ffffff|f!f!f!" ,
2107
+ & open_fci , & open_fcc ,
2108
+ & close_fci , & close_fcc ,
2109
+ & read_fci , & read_fcc ,
2110
+ & write_fci , & write_fcc ,
2111
+ & destroy_fci , & destroy_fcc ,
2112
+ & gc_fci , & gc_fcc ,
2113
+ & create_id_fci , & create_id_fcc ,
2114
+ & validate_id_fci , & validate_id_fcc ,
2115
+ & update_timestamp_fci , & update_timestamp_fcc ) == FAILURE
2116
+ ) {
2075
2117
RETURN_THROWS ();
2076
2118
}
2077
-
2078
- /* At this point argc can only be between 6 and PS_NUM_APIS */
2079
- for (i = 0 ; i < argc ; i ++ ) {
2080
- if (!zend_is_callable (& args [i ], IS_CALLABLE_SUPPRESS_DEPRECATIONS , NULL )) {
2081
- zend_string * name = zend_get_callable_name (& args [i ]);
2082
- zend_argument_type_error (i + 1 , "must be a valid callback, function \"%s\" not found or invalid function name" , ZSTR_VAL (name ));
2083
- zend_string_release (name );
2084
- RETURN_THROWS ();
2085
- }
2086
- }
2087
-
2088
- if (save_handler_check_session () == FAILURE ) {
2119
+ if (!can_session_handler_be_changed ()) {
2089
2120
RETURN_FALSE ;
2090
2121
}
2091
2122
2123
+ /* If a custom session handler is already set, release relevant info */
2092
2124
if (PS (mod_user_class_name )) {
2093
2125
zend_string_release (PS (mod_user_class_name ));
2094
2126
PS (mod_user_class_name ) = NULL ;
2095
2127
}
2096
2128
2097
2129
/* remove shutdown function */
2098
- remove_user_shutdown_function ("session_shutdown" , sizeof ("session_shutdown" ) - 1 );
2130
+ remove_user_shutdown_function ("session_shutdown" , strlen ("session_shutdown" ));
2099
2131
2100
2132
if (!PS (mod ) || PS (mod ) != & ps_mod_user ) {
2101
2133
set_user_save_handler_ini ();
2102
2134
}
2103
2135
2104
- for (i = 0 ; i < argc ; i ++ ) {
2105
- if (!Z_ISUNDEF (PS (mod_user_names ).names [i ])) {
2106
- zval_ptr_dtor (& PS (mod_user_names ).names [i ]);
2107
- }
2108
- ZVAL_COPY (& PS (mod_user_names ).names [i ], & args [i ]);
2109
- }
2136
+ /* Define mandatory handlers */
2137
+ SESSION_SET_USER_HANDLER_PROCEDURAL (ps_open , open_fci );
2138
+ SESSION_SET_USER_HANDLER_PROCEDURAL (ps_close , close_fci );
2139
+ SESSION_SET_USER_HANDLER_PROCEDURAL (ps_read , read_fci );
2140
+ SESSION_SET_USER_HANDLER_PROCEDURAL (ps_write , write_fci );
2141
+ SESSION_SET_USER_HANDLER_PROCEDURAL (ps_destroy , destroy_fci );
2142
+ SESSION_SET_USER_HANDLER_PROCEDURAL (ps_gc , gc_fci );
2143
+
2144
+ /* Check for optional handlers */
2145
+ SESSION_SET_USER_HANDLER_PROCEDURAL_OPTIONAL (ps_create_sid , create_id_fci );
2146
+ SESSION_SET_USER_HANDLER_PROCEDURAL_OPTIONAL (ps_validate_sid , validate_id_fci );
2147
+ SESSION_SET_USER_HANDLER_PROCEDURAL_OPTIONAL (ps_update_timestamp , update_timestamp_fci );
2110
2148
2111
2149
RETURN_TRUE ;
2112
2150
}
0 commit comments