1999-12-12 22:22:55 +08:00
/*
1999-06-06 03:52:58 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2001-12-11 23:32:16 +08:00
| PHP Version 4 |
1999-06-06 03:52:58 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2003-01-01 00:08:15 +08:00
| Copyright ( c ) 1997 - 2003 The PHP Group |
1999-06-06 03:52:58 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2000-05-18 23:34:45 +08:00
| This source file is subject to version 2.02 of the PHP license , |
1999-07-16 21:13:16 +08:00
| that is bundled with this package in the file LICENSE , and is |
| available at through the world - wide - web at |
2000-05-18 23:34:45 +08:00
| http : //www.php.net/license/2_02.txt. |
1999-07-16 21:13:16 +08:00
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
1999-06-06 03:52:58 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2000-07-10 18:09:15 +08:00
| Authors : Sascha Schumann < sascha @ schumann . cx > |
2002-05-14 01:28:38 +08:00
| Andrei Zmievski < andrei @ php . net > |
1999-06-06 03:52:58 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
2001-06-06 22:32:27 +08:00
/* $Id$ */
2001-05-24 18:07:29 +08:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
2000-02-11 21:41:30 +08:00
# include "php.h"
2000-02-11 23:59:30 +08:00
# ifdef PHP_WIN32
1999-06-07 03:53:59 +08:00
# include "win32/time.h"
2000-02-11 21:41:30 +08:00
# else
# include <sys/time.h>
1999-06-07 02:22:17 +08:00
# endif
1999-06-06 03:52:58 +08:00
1999-12-12 22:16:55 +08:00
# include <sys/stat.h>
1999-09-12 01:20:31 +08:00
# include <fcntl.h>
1999-06-06 03:52:58 +08:00
# include "php_ini.h"
# include "SAPI.h"
# include "php_session.h"
1999-06-07 03:53:59 +08:00
# include "ext/standard/md5.h"
2003-01-12 21:07:14 +08:00
# include "ext/standard/sha1.h"
1999-12-05 03:19:57 +08:00
# include "ext/standard/php_var.h"
1999-06-29 23:39:59 +08:00
# include "ext/standard/datetime.h"
1999-09-01 22:20:15 +08:00
# include "ext/standard/php_lcg.h"
2000-09-20 09:22:55 +08:00
# include "ext/standard/url_scanner_ex.h"
1999-12-19 07:28:43 +08:00
# include "ext/standard/php_rand.h" /* for RAND_MAX */
2000-04-07 05:07:44 +08:00
# include "ext/standard/info.h"
2001-03-14 00:53:34 +08:00
# include "ext/standard/php_smart_str.h"
2001-05-03 23:48:49 +08:00
# include "mod_files.h"
# include "mod_user.h"
2002-06-28 10:27:02 +08:00
# ifdef HAVE_LIBMM
# include "mod_mm.h"
# endif
2001-06-06 22:32:27 +08:00
/* {{{ session_functions[]
*/
1999-06-06 03:52:58 +08:00
function_entry session_functions [ ] = {
2002-07-03 10:16:46 +08:00
PHP_FE ( session_name , NULL )
PHP_FE ( session_module_name , NULL )
PHP_FE ( session_save_path , NULL )
PHP_FE ( session_id , NULL )
2003-02-19 02:50:44 +08:00
PHP_FE ( session_regenerate_id , NULL )
2002-07-03 10:16:46 +08:00
PHP_FE ( session_decode , NULL )
PHP_FE ( session_register , NULL )
PHP_FE ( session_unregister , NULL )
PHP_FE ( session_is_registered , NULL )
PHP_FE ( session_encode , NULL )
PHP_FE ( session_start , NULL )
PHP_FE ( session_destroy , NULL )
PHP_FE ( session_unset , NULL )
PHP_FE ( session_set_save_handler , NULL )
PHP_FE ( session_cache_limiter , NULL )
PHP_FE ( session_cache_expire , NULL )
2002-05-10 04:02:47 +08:00
PHP_FE ( session_set_cookie_params , NULL )
PHP_FE ( session_get_cookie_params , NULL )
2002-07-03 10:16:46 +08:00
PHP_FE ( session_write_close , NULL )
2002-05-10 04:02:47 +08:00
{ NULL , NULL , NULL }
1999-06-06 03:52:58 +08:00
} ;
2001-06-06 22:32:27 +08:00
/* }}} */
1999-06-06 03:52:58 +08:00
2002-02-08 06:00:21 +08:00
ZEND_DECLARE_MODULE_GLOBALS ( ps ) ;
2001-05-02 01:01:51 +08:00
2001-07-28 19:36:37 +08:00
static ps_module * _php_find_ps_module ( char * name TSRMLS_DC ) ;
static const ps_serializer * _php_find_ps_serializer ( char * name TSRMLS_DC ) ;
2001-08-26 09:09:20 +08:00
2000-05-26 21:02:11 +08:00
static PHP_INI_MH ( OnUpdateSaveHandler )
{
2002-11-21 01:15:00 +08:00
if ( PS ( session_status ) = = php_session_active ) {
2002-12-06 04:13:35 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " A session is active. You cannot change the session module's ini settings at this time. " ) ;
2002-11-21 01:15:00 +08:00
return FAILURE ;
}
2002-05-10 04:02:47 +08:00
PS ( mod ) = _php_find_ps_module ( new_value TSRMLS_CC ) ;
2002-05-12 20:51:42 +08:00
/*
* Following lines are commented out to prevent bogus error message at
* start up . i . e . Save handler modules are not initilzied before Session
* module .
*/
#if 0
if ( ! PS ( mod ) ) {
2002-12-06 04:41:55 +08:00
php_error_docref ( NULL TSRMLS_CC , E_ERROR , " Cannot find save handler %s " , new_value ) ;
2002-05-12 20:51:42 +08:00
}
# endif
2002-05-10 04:02:47 +08:00
return SUCCESS ;
2000-05-26 21:02:11 +08:00
}
static PHP_INI_MH ( OnUpdateSerializer )
{
2002-11-21 01:15:00 +08:00
if ( PS ( session_status ) = = php_session_active ) {
2002-12-06 04:13:35 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " A session is active. You cannot change the session module's ini settings at this time. " ) ;
2002-11-21 01:15:00 +08:00
return FAILURE ;
}
2002-05-10 04:02:47 +08:00
PS ( serializer ) = _php_find_ps_serializer ( new_value TSRMLS_CC ) ;
2002-05-12 20:51:42 +08:00
/*
* Following lines are commented out to prevent bogus error message at
* start up . i . e . Serializer modules are not initilzied before Session
* module .
*/
#if 0
if ( ! PS ( serializer ) ) {
2002-12-06 04:41:55 +08:00
php_error_docref ( NULL TSRMLS_CC , E_ERROR , " Cannot find serialization handler %s " , new_value ) ;
2002-05-12 20:51:42 +08:00
}
# endif
2002-05-10 04:02:47 +08:00
return SUCCESS ;
2000-05-26 21:02:11 +08:00
}
2001-06-06 22:32:27 +08:00
/* {{{ PHP_INI
*/
1999-06-06 03:52:58 +08:00
PHP_INI_BEGIN ( )
2002-10-03 11:23:02 +08:00
STD_PHP_INI_BOOLEAN ( " session.bug_compat_42 " , " 1 " , PHP_INI_ALL , OnUpdateBool , bug_compat , php_ps_globals , ps_globals )
STD_PHP_INI_BOOLEAN ( " session.bug_compat_warn " , " 1 " , PHP_INI_ALL , OnUpdateBool , bug_compat_warn , php_ps_globals , ps_globals )
2002-07-03 10:16:46 +08:00
STD_PHP_INI_ENTRY ( " session.save_path " , " /tmp " , PHP_INI_ALL , OnUpdateString , save_path , php_ps_globals , ps_globals )
STD_PHP_INI_ENTRY ( " session.name " , " PHPSESSID " , PHP_INI_ALL , OnUpdateString , session_name , php_ps_globals , ps_globals )
PHP_INI_ENTRY ( " session.save_handler " , " files " , PHP_INI_ALL , OnUpdateSaveHandler )
STD_PHP_INI_BOOLEAN ( " session.auto_start " , " 0 " , PHP_INI_ALL , OnUpdateBool , auto_start , php_ps_globals , ps_globals )
STD_PHP_INI_ENTRY ( " session.gc_probability " , " 1 " , PHP_INI_ALL , OnUpdateInt , gc_probability , php_ps_globals , ps_globals )
2002-10-03 14:45:15 +08:00
STD_PHP_INI_ENTRY ( " session.gc_dividend " , " 100 " , PHP_INI_ALL , OnUpdateInt , gc_dividend , php_ps_globals , ps_globals )
2002-07-03 10:16:46 +08:00
STD_PHP_INI_ENTRY ( " session.gc_maxlifetime " , " 1440 " , PHP_INI_ALL , OnUpdateInt , gc_maxlifetime , php_ps_globals , ps_globals )
PHP_INI_ENTRY ( " session.serialize_handler " , " php " , PHP_INI_ALL , OnUpdateSerializer )
STD_PHP_INI_ENTRY ( " session.cookie_lifetime " , " 0 " , PHP_INI_ALL , OnUpdateInt , cookie_lifetime , php_ps_globals , ps_globals )
STD_PHP_INI_ENTRY ( " session.cookie_path " , " / " , PHP_INI_ALL , OnUpdateString , cookie_path , php_ps_globals , ps_globals )
STD_PHP_INI_ENTRY ( " session.cookie_domain " , " " , PHP_INI_ALL , OnUpdateString , cookie_domain , php_ps_globals , ps_globals )
STD_PHP_INI_BOOLEAN ( " session.cookie_secure " , " " , PHP_INI_ALL , OnUpdateBool , cookie_secure , php_ps_globals , ps_globals )
STD_PHP_INI_BOOLEAN ( " session.use_cookies " , " 1 " , PHP_INI_ALL , OnUpdateBool , use_cookies , php_ps_globals , ps_globals )
STD_PHP_INI_BOOLEAN ( " session.use_only_cookies " , " 0 " , PHP_INI_ALL , OnUpdateBool , use_only_cookies , php_ps_globals , ps_globals )
STD_PHP_INI_ENTRY ( " session.referer_check " , " " , PHP_INI_ALL , OnUpdateString , extern_referer_chk , php_ps_globals , ps_globals )
STD_PHP_INI_ENTRY ( " session.entropy_file " , " " , PHP_INI_ALL , OnUpdateString , entropy_file , php_ps_globals , ps_globals )
STD_PHP_INI_ENTRY ( " session.entropy_length " , " 0 " , PHP_INI_ALL , OnUpdateInt , entropy_length , php_ps_globals , ps_globals )
STD_PHP_INI_ENTRY ( " session.cache_limiter " , " nocache " , PHP_INI_ALL , OnUpdateString , cache_limiter , php_ps_globals , ps_globals )
STD_PHP_INI_ENTRY ( " session.cache_expire " , " 180 " , PHP_INI_ALL , OnUpdateInt , cache_expire , php_ps_globals , ps_globals )
2002-09-27 00:46:21 +08:00
STD_PHP_INI_BOOLEAN ( " session.use_trans_sid " , " 0 " , PHP_INI_SYSTEM | PHP_INI_PERDIR , OnUpdateBool , use_trans_sid , php_ps_globals , ps_globals )
2003-01-12 21:07:14 +08:00
STD_PHP_INI_ENTRY ( " session.hash_function " , " 0 " , PHP_INI_ALL , OnUpdateInt , hash_func , php_ps_globals , ps_globals )
2003-01-16 15:21:49 +08:00
STD_PHP_INI_ENTRY ( " session.hash_bits_per_character " , " 4 " , PHP_INI_ALL , OnUpdateInt , hash_bits_per_character , php_ps_globals , ps_globals )
2002-05-10 04:02:47 +08:00
/* Commented out until future discussion */
/* PHP_INI_ENTRY("session.encode_sources", "globals,track", PHP_INI_ALL, NULL) */
1999-06-06 03:52:58 +08:00
PHP_INI_END ( )
2001-06-06 22:32:27 +08:00
/* }}} */
1999-06-06 03:52:58 +08:00
1999-07-01 13:45:48 +08:00
PS_SERIALIZER_FUNCS ( php ) ;
2000-09-01 23:24:58 +08:00
PS_SERIALIZER_FUNCS ( php_binary ) ;
1999-07-01 13:45:48 +08:00
2001-05-02 01:01:51 +08:00
# define MAX_SERIALIZERS 10
1999-09-17 13:40:59 +08:00
2001-05-02 01:01:51 +08:00
static ps_serializer ps_serializers [ MAX_SERIALIZERS + 1 ] = {
2002-05-10 04:02:47 +08:00
PS_SERIALIZER_ENTRY ( php ) ,
PS_SERIALIZER_ENTRY ( php_binary )
1999-07-01 13:45:48 +08:00
} ;
1999-06-07 03:53:59 +08:00
2001-05-03 23:48:49 +08:00
# define MAX_MODULES 10
static ps_module * ps_modules [ MAX_MODULES + 1 ] = {
2002-05-10 04:02:47 +08:00
ps_files_ptr ,
ps_user_ptr
2001-05-03 23:48:49 +08:00
} ;
2002-10-03 11:23:02 +08:00
# define IF_SESSION_VARS() \
if ( PS ( http_session_vars ) & & PS ( http_session_vars ) - > type = = IS_ARRAY )
2002-05-10 04:02:47 +08:00
PHPAPI int php_session_register_serializer ( const char * name ,
int ( * encode ) ( PS_SERIALIZER_ENCODE_ARGS ) ,
int ( * decode ) ( PS_SERIALIZER_DECODE_ARGS ) )
2001-05-02 01:01:51 +08:00
{
2002-05-10 04:02:47 +08:00
int ret = - 1 ;
int i ;
for ( i = 0 ; i < MAX_SERIALIZERS ; i + + ) {
if ( ps_serializers [ i ] . name = = NULL ) {
ps_serializers [ i ] . name = name ;
ps_serializers [ i ] . encode = encode ;
ps_serializers [ i ] . decode = decode ;
ps_serializers [ i + 1 ] . name = NULL ;
ret = 0 ;
break ;
}
}
return ret ;
2001-05-02 01:01:51 +08:00
}
2002-01-17 07:24:37 +08:00
PHPAPI int php_session_register_module ( ps_module * ptr )
2001-05-03 23:48:49 +08:00
{
2002-05-10 04:02:47 +08:00
int ret = - 1 ;
int i ;
for ( i = 0 ; i < MAX_MODULES ; i + + ) {
if ( ! ps_modules [ i ] ) {
ps_modules [ i ] = ptr ;
ret = 0 ;
break ;
}
}
return ret ;
2001-05-03 23:48:49 +08:00
}
2001-05-02 01:01:51 +08:00
1999-09-17 13:40:59 +08:00
PHP_MINIT_FUNCTION ( session ) ;
PHP_RINIT_FUNCTION ( session ) ;
PHP_MSHUTDOWN_FUNCTION ( session ) ;
2000-01-17 05:03:49 +08:00
PHP_RSHUTDOWN_FUNCTION ( session ) ;
1999-09-17 13:40:59 +08:00
PHP_MINFO_FUNCTION ( session ) ;
2001-07-28 19:36:37 +08:00
static void php_rinit_session_globals ( TSRMLS_D ) ;
static void php_rshutdown_session_globals ( TSRMLS_D ) ;
static zend_bool php_session_destroy ( TSRMLS_D ) ;
1999-06-06 03:52:58 +08:00
zend_module_entry session_module_entry = {
2002-05-10 04:02:47 +08:00
STANDARD_MODULE_HEADER ,
" session " ,
session_functions ,
PHP_MINIT ( session ) , PHP_MSHUTDOWN ( session ) ,
PHP_RINIT ( session ) , PHP_RSHUTDOWN ( session ) ,
PHP_MINFO ( session ) ,
2002-07-03 10:16:46 +08:00
NO_VERSION_YET ,
2002-05-10 04:02:47 +08:00
STANDARD_MODULE_PROPERTIES
1999-06-06 03:52:58 +08:00
} ;
2000-05-23 17:33:51 +08:00
# ifdef COMPILE_DL_SESSION
2000-05-02 08:30:36 +08:00
ZEND_GET_MODULE ( session )
2000-05-01 10:42:55 +08:00
# endif
1999-12-12 22:16:55 +08:00
typedef struct {
2002-05-10 04:02:47 +08:00
char * name ;
void ( * func ) ( TSRMLS_D ) ;
2000-09-06 22:16:12 +08:00
} php_session_cache_limiter_t ;
1999-12-12 22:16:55 +08:00
2002-05-12 20:51:42 +08:00
# define CACHE_LIMITER(name) _php_cache_limiter_##name
# define CACHE_LIMITER_FUNC(name) static void CACHE_LIMITER(name)(TSRMLS_D)
# define CACHE_LIMITER_ENTRY(name) { #name, CACHE_LIMITER(name) },
1999-12-12 22:16:55 +08:00
2000-04-28 21:03:13 +08:00
# define ADD_COOKIE(a) sapi_add_header(a, strlen(a), 1);
1999-12-12 22:16:55 +08:00
1999-06-06 03:52:58 +08:00
# define MAX_STR 512
2002-10-01 19:59:45 +08:00
void php_add_session_var ( char * name , size_t namelen TSRMLS_DC )
{
zval * * sym_track = NULL ;
zend_hash_find ( Z_ARRVAL_P ( PS ( http_session_vars ) ) , name , namelen + 1 ,
( void * ) & sym_track ) ;
/*
* Set up a proper reference between $ _SESSION [ " x " ] and $ x .
*/
if ( PG ( register_globals ) ) {
zval * * sym_global = NULL ;
zend_hash_find ( & EG ( symbol_table ) , name , namelen + 1 ,
( void * ) & sym_global ) ;
if ( sym_global = = NULL & & sym_track = = NULL ) {
zval * empty_var ;
2002-10-03 05:51:32 +08:00
ALLOC_INIT_ZVAL ( empty_var ) ; /* this sets refcount to 1 */
ZVAL_DELREF ( empty_var ) ; /* our module does not maintain a ref */
/* The next call will increase refcount by NR_OF_SYM_TABLES==2 */
2002-10-01 19:59:45 +08:00
zend_set_hash_symbol ( empty_var , name , namelen , 1 , 2 , Z_ARRVAL_P ( PS ( http_session_vars ) ) , & EG ( symbol_table ) ) ;
} else if ( sym_global = = NULL ) {
zend_set_hash_symbol ( * sym_track , name , namelen , 1 , 1 , & EG ( symbol_table ) ) ;
} else if ( sym_track = = NULL ) {
zend_set_hash_symbol ( * sym_global , name , namelen , 1 , 1 , Z_ARRVAL_P ( PS ( http_session_vars ) ) ) ;
}
} else {
if ( sym_track = = NULL ) {
zval * empty_var ;
ALLOC_INIT_ZVAL ( empty_var ) ;
2002-10-03 05:51:32 +08:00
ZEND_SET_SYMBOL_WITH_LENGTH ( Z_ARRVAL_P ( PS ( http_session_vars ) ) , name , namelen + 1 , empty_var , 1 , 0 ) ;
2002-10-01 19:59:45 +08:00
}
}
}
2001-11-11 05:18:34 +08:00
void php_set_session_var ( char * name , size_t namelen , zval * state_val , php_unserialize_data_t * var_hash TSRMLS_DC )
1999-12-05 01:02:04 +08:00
{
2002-05-10 04:02:47 +08:00
if ( PG ( register_globals ) ) {
zval * * old_symbol ;
if ( zend_hash_find ( & EG ( symbol_table ) , name , namelen + 1 , ( void * ) & old_symbol ) = = SUCCESS ) {
/*
2002-08-16 03:32:08 +08:00
There was an old one , we need to replace it accurately .
2002-05-10 04:02:47 +08:00
hash_update in zend_set_hash_symbol is not good , because
it will leave referenced variables ( such as local instances
of a global variable ) dangling .
BTW : if you use register_globals references between
session - vars won ' t work because of this very reason !
*/
REPLACE_ZVAL_VALUE ( old_symbol , state_val , 1 ) ;
/* the following line will muck with the reference-table used for
* unserialisation
*/
PHP_VAR_UNSERIALIZE_ZVAL_CHANGED ( var_hash , state_val , * old_symbol ) ;
zend_set_hash_symbol ( * old_symbol , name , namelen , 1 , 1 , Z_ARRVAL_P ( PS ( http_session_vars ) ) ) ;
} else {
zend_set_hash_symbol ( state_val , name , namelen , 1 , 2 , Z_ARRVAL_P ( PS ( http_session_vars ) ) , & EG ( symbol_table ) ) ;
}
2002-10-03 11:23:02 +08:00
} else IF_SESSION_VARS ( ) {
2002-05-10 04:02:47 +08:00
zend_set_hash_symbol ( state_val , name , namelen , 0 , 1 , Z_ARRVAL_P ( PS ( http_session_vars ) ) ) ;
}
1999-12-05 01:02:04 +08:00
}
2001-07-28 19:36:37 +08:00
int php_get_session_var ( char * name , size_t namelen , zval * * * state_var TSRMLS_DC )
1999-12-05 01:02:04 +08:00
{
2002-10-03 12:53:05 +08:00
int ret = FAILURE ;
2002-10-03 11:23:02 +08:00
IF_SESSION_VARS ( ) {
2002-10-03 12:53:05 +08:00
ret = zend_hash_find ( Z_ARRVAL_P ( PS ( http_session_vars ) ) , name ,
2002-10-01 19:59:45 +08:00
namelen + 1 , ( void * * ) state_var ) ;
2002-10-03 12:53:05 +08:00
/*
* If register_globals is enabled , and
* if there is an entry for the slot in $ _SESSION , and
* if that entry is still set to NULL , and
* if the global var exists , then
* we prefer the same key in the global sym table
*/
if ( PG ( register_globals ) & & ret = = SUCCESS
& & Z_TYPE_PP ( * state_var ) = = IS_NULL ) {
zval * * tmp ;
if ( zend_hash_find ( & EG ( symbol_table ) , name , namelen + 1 ,
( void * * ) & tmp ) = = SUCCESS ) {
* state_var = tmp ;
}
}
2002-09-23 22:04:50 +08:00
}
2002-10-03 12:53:05 +08:00
return ret ;
1999-12-05 01:02:04 +08:00
}
1999-11-30 07:07:20 +08:00
2000-09-01 23:24:58 +08:00
# define PS_BIN_NR_OF_BITS 8
# define PS_BIN_UNDEF (1<<(PS_BIN_NR_OF_BITS-1))
# define PS_BIN_MAX (PS_BIN_UNDEF-1)
PS_SERIALIZER_ENCODE_FUNC ( php_binary )
{
2002-05-10 04:02:47 +08:00
smart_str buf = { 0 } ;
php_serialize_data_t var_hash ;
PS_ENCODE_VARS ;
PHP_VAR_SERIALIZE_INIT ( var_hash ) ;
PS_ENCODE_LOOP (
if ( key_length > PS_BIN_MAX ) continue ;
smart_str_appendc ( & buf , ( unsigned char ) key_length ) ;
smart_str_appendl ( & buf , key , key_length ) ;
php_var_serialize ( & buf , struc , & var_hash TSRMLS_CC ) ;
} else {
if ( key_length > PS_BIN_MAX ) continue ;
smart_str_appendc ( & buf , ( unsigned char ) ( key_length & PS_BIN_UNDEF ) ) ;
smart_str_appendl ( & buf , key , key_length ) ;
) ;
if ( newlen ) * newlen = buf . len ;
* newstr = buf . c ;
PHP_VAR_SERIALIZE_DESTROY ( var_hash ) ;
2002-05-10 03:42:00 +08:00
2002-05-10 04:02:47 +08:00
return SUCCESS ;
2000-09-01 23:24:58 +08:00
}
PS_SERIALIZER_DECODE_FUNC ( php_binary )
{
2002-05-10 04:02:47 +08:00
const char * p ;
char * name ;
const char * endptr = val + vallen ;
zval * current ;
int namelen ;
int has_value ;
php_unserialize_data_t var_hash ;
PHP_VAR_UNSERIALIZE_INIT ( var_hash ) ;
for ( p = val ; p < endptr ; ) {
namelen = * p & ( ~ PS_BIN_UNDEF ) ;
has_value = * p & PS_BIN_UNDEF ? 0 : 1 ;
name = estrndup ( p + 1 , namelen ) ;
p + = namelen + 1 ;
if ( has_value ) {
MAKE_STD_ZVAL ( current ) ;
if ( php_var_unserialize ( & current , & p , endptr , & var_hash TSRMLS_CC ) ) {
php_set_session_var ( name , namelen , current , & var_hash TSRMLS_CC ) ;
}
zval_ptr_dtor ( & current ) ;
}
PS_ADD_VARL ( name , namelen ) ;
efree ( name ) ;
}
PHP_VAR_UNSERIALIZE_DESTROY ( var_hash ) ;
return SUCCESS ;
2000-09-01 23:24:58 +08:00
}
# define PS_DELIMITER '|'
# define PS_UNDEF_MARKER '!'
1999-07-01 13:45:48 +08:00
PS_SERIALIZER_ENCODE_FUNC ( php )
1999-06-06 03:52:58 +08:00
{
2002-05-10 04:02:47 +08:00
smart_str buf = { 0 } ;
php_serialize_data_t var_hash ;
PS_ENCODE_VARS ;
PHP_VAR_SERIALIZE_INIT ( var_hash ) ;
PS_ENCODE_LOOP (
smart_str_appendl ( & buf , key , ( unsigned char ) key_length ) ;
smart_str_appendc ( & buf , PS_DELIMITER ) ;
php_var_serialize ( & buf , struc , & var_hash TSRMLS_CC ) ;
} else {
smart_str_appendc ( & buf , PS_UNDEF_MARKER ) ;
smart_str_appendl ( & buf , key , key_length ) ;
smart_str_appendc ( & buf , PS_DELIMITER ) ;
) ;
if ( newlen ) * newlen = buf . len ;
* newstr = buf . c ;
PHP_VAR_SERIALIZE_DESTROY ( var_hash ) ;
return SUCCESS ;
1999-06-06 03:52:58 +08:00
}
2002-05-10 04:02:47 +08:00
PS_SERIALIZER_DECODE_FUNC ( php )
1999-06-06 03:52:58 +08:00
{
2002-05-10 04:02:47 +08:00
const char * p , * q ;
char * name ;
const char * endptr = val + vallen ;
zval * current ;
int namelen ;
int has_value ;
php_unserialize_data_t var_hash ;
PHP_VAR_UNSERIALIZE_INIT ( var_hash ) ;
p = val ;
while ( p < endptr ) {
q = p ;
while ( * q ! = PS_DELIMITER )
if ( + + q > = endptr ) goto break_outer_loop ;
if ( p [ 0 ] = = PS_UNDEF_MARKER ) {
p + + ;
has_value = 0 ;
} else {
has_value = 1 ;
}
namelen = q - p ;
name = estrndup ( p , namelen ) ;
q + + ;
if ( has_value ) {
MAKE_STD_ZVAL ( current ) ;
if ( php_var_unserialize ( & current , & q , endptr , & var_hash TSRMLS_CC ) ) {
php_set_session_var ( name , namelen , current , & var_hash TSRMLS_CC ) ;
}
zval_ptr_dtor ( & current ) ;
}
PS_ADD_VARL ( name , namelen ) ;
efree ( name ) ;
p = q ;
}
2001-07-26 03:02:13 +08:00
break_outer_loop :
2002-05-10 04:02:47 +08:00
PHP_VAR_UNSERIALIZE_DESTROY ( var_hash ) ;
2001-06-22 02:46:26 +08:00
2002-05-10 04:02:47 +08:00
return SUCCESS ;
1999-07-01 13:45:48 +08:00
}
2001-08-05 22:36:51 +08:00
static void php_session_track_init ( TSRMLS_D )
1999-12-05 01:02:04 +08:00
{
2002-10-03 05:51:32 +08:00
/* Unconditionally destroy existing arrays -- possible dirty data */
zend_hash_del ( & EG ( symbol_table ) , " HTTP_SESSION_VARS " ,
sizeof ( " HTTP_SESSION_VARS " ) ) ;
zend_hash_del ( & EG ( symbol_table ) , " _SESSION " , sizeof ( " _SESSION " ) ) ;
2002-05-10 04:02:47 +08:00
2002-10-03 05:51:32 +08:00
MAKE_STD_ZVAL ( PS ( http_session_vars ) ) ;
array_init ( PS ( http_session_vars ) ) ;
2002-10-03 13:53:45 +08:00
ZEND_SET_GLOBAL_VAR_WITH_LENGTH ( " HTTP_SESSION_VARS " , sizeof ( " HTTP_SESSION_VARS " ) , PS ( http_session_vars ) , 2 , 1 ) ;
ZEND_SET_GLOBAL_VAR_WITH_LENGTH ( " _SESSION " , sizeof ( " _SESSION " ) , PS ( http_session_vars ) , 2 , 1 ) ;
1999-12-05 01:02:04 +08:00
}
2001-07-28 19:36:37 +08:00
static char * php_session_encode ( int * newlen TSRMLS_DC )
1999-07-01 13:45:48 +08:00
{
2002-05-10 04:02:47 +08:00
char * ret = NULL ;
1999-07-01 13:45:48 +08:00
2002-10-03 11:23:02 +08:00
IF_SESSION_VARS ( ) {
if ( PS ( serializer ) - > encode ( & ret , newlen TSRMLS_CC ) = = FAILURE )
ret = NULL ;
} else {
2002-09-29 23:55:11 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Cannot encode non-existent session. " ) ;
}
2002-05-10 04:02:47 +08:00
return ret ;
1999-07-01 13:45:48 +08:00
}
2002-03-06 17:02:31 +08:00
static void php_session_decode ( const char * val , int vallen TSRMLS_DC )
1999-07-01 13:45:48 +08:00
{
2002-05-10 04:02:47 +08:00
if ( PS ( serializer ) - > decode ( val , vallen TSRMLS_CC ) = = FAILURE ) {
php_session_destroy ( TSRMLS_C ) ;
2002-12-06 04:13:35 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Failed to decode session object. Session has been destroyed. " ) ;
2002-05-10 04:02:47 +08:00
}
1999-06-06 03:52:58 +08:00
}
2003-01-16 15:21:49 +08:00
/*
* Note that we cannot use the BASE64 alphabet here , because
* it contains " / " and " + " : both are unacceptable for simple inclusion
* into URLs .
*/
static char hexconvtab [ ] = " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,- " ;
2003-01-12 21:07:14 +08:00
enum {
PS_HASH_FUNC_MD5 ,
PS_HASH_FUNC_SHA1
} ;
2001-05-19 17:58:31 +08:00
2003-01-16 15:21:49 +08:00
/* returns a pointer to the byte after the last valid character in out */
static char * bin_to_readable ( char * in , size_t inlen , char * out , char nbits )
{
unsigned char * p , * q ;
unsigned short w ;
int mask ;
int have ;
p = in ;
q = in + inlen ;
w = 0 ;
have = 0 ;
mask = ( 1 < < nbits ) - 1 ;
while ( 1 ) {
if ( have < nbits ) {
if ( p < q ) {
w | = * p + + < < have ;
have + = 8 ;
} else {
/* consumed everything? */
if ( have = = 0 ) break ;
/* No? We need a final round */
have = nbits ;
}
}
/* consume nbits */
* out + + = hexconvtab [ w & mask ] ;
w > > = nbits ;
have - = nbits ;
}
* out = ' \0 ' ;
return out ;
}
2002-03-31 00:29:15 +08:00
char * php_session_create_id ( PS_CREATE_SID_ARGS )
1999-06-06 03:52:58 +08:00
{
2003-01-12 21:07:14 +08:00
PHP_MD5_CTX md5_context ;
PHP_SHA1_CTX sha1_context ;
unsigned char digest [ 21 ] ;
int digest_len ;
2003-01-16 15:21:49 +08:00
int j ;
2003-01-12 21:07:14 +08:00
char * buf ;
2002-05-10 04:02:47 +08:00
struct timeval tv ;
2003-01-12 21:07:14 +08:00
zval * * array ;
zval * * token ;
char * remote_addr = NULL ;
2002-05-10 04:02:47 +08:00
gettimeofday ( & tv , NULL ) ;
2003-01-12 21:07:14 +08:00
if ( zend_hash_find ( & EG ( symbol_table ) , " _SERVER " ,
sizeof ( " _SERVER " ) , ( void * * ) & array ) = = SUCCESS & &
Z_TYPE_PP ( array ) = = IS_ARRAY & &
zend_hash_find ( Z_ARRVAL_PP ( array ) , " REMOTE_ADDR " ,
sizeof ( " REMOTE_ADDR " ) , ( void * * ) & token ) = = SUCCESS ) {
remote_addr = Z_STRVAL_PP ( token ) ;
}
buf = emalloc ( 100 ) ;
/* maximum 15+19+19+10 bytes */
sprintf ( buf , " %.15s%ld%ld%0.8f " , remote_addr ? remote_addr : " " ,
tv . tv_sec , tv . tv_usec , php_combined_lcg ( TSRMLS_C ) * 10 ) ;
switch ( PS ( hash_func ) ) {
case PS_HASH_FUNC_MD5 :
PHP_MD5Init ( & md5_context ) ;
PHP_MD5Update ( & md5_context , buf , strlen ( buf ) ) ;
digest_len = 16 ;
break ;
case PS_HASH_FUNC_SHA1 :
PHP_SHA1Init ( & sha1_context ) ;
PHP_SHA1Update ( & sha1_context , buf , strlen ( buf ) ) ;
digest_len = 20 ;
break ;
default :
2003-01-19 08:45:53 +08:00
php_error_docref ( NULL TSRMLS_CC , E_ERROR , " Invalid session hash function " ) ;
2003-01-12 21:07:14 +08:00
efree ( buf ) ;
return NULL ;
}
2002-05-10 04:02:47 +08:00
if ( PS ( entropy_length ) > 0 ) {
int fd ;
fd = VCWD_OPEN ( PS ( entropy_file ) , O_RDONLY ) ;
if ( fd > = 0 ) {
2003-01-12 21:07:14 +08:00
unsigned char rbuf [ 2048 ] ;
2002-05-10 04:02:47 +08:00
int n ;
int to_read = PS ( entropy_length ) ;
while ( to_read > 0 ) {
2003-01-12 21:07:14 +08:00
n = read ( fd , rbuf , MIN ( to_read , sizeof ( rbuf ) ) ) ;
2002-05-10 04:02:47 +08:00
if ( n < = 0 ) break ;
2003-01-12 21:07:14 +08:00
switch ( PS ( hash_func ) ) {
case PS_HASH_FUNC_MD5 :
PHP_MD5Update ( & md5_context , rbuf , n ) ;
break ;
case PS_HASH_FUNC_SHA1 :
PHP_SHA1Update ( & sha1_context , rbuf , n ) ;
break ;
}
2002-05-10 04:02:47 +08:00
to_read - = n ;
}
close ( fd ) ;
}
}
1999-06-06 03:52:58 +08:00
2003-01-12 21:07:14 +08:00
switch ( PS ( hash_func ) ) {
case PS_HASH_FUNC_MD5 :
PHP_MD5Final ( digest , & md5_context ) ;
break ;
case PS_HASH_FUNC_SHA1 :
PHP_SHA1Final ( digest , & sha1_context ) ;
break ;
}
2003-01-16 15:21:49 +08:00
if ( PS ( hash_bits_per_character ) < 4
| | PS ( hash_bits_per_character ) > 6 ) {
PS ( hash_bits_per_character ) = 4 ;
2003-01-12 21:07:14 +08:00
2003-01-19 08:45:53 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " The ini setting hash_bits_per_character is out of range (should be 4, 5, or 6) - using 4 for now " ) ;
2002-05-10 04:02:47 +08:00
}
2003-01-31 06:37:50 +08:00
j = ( int ) ( bin_to_readable ( digest , digest_len , buf , PS ( hash_bits_per_character ) ) - buf ) ;
2002-05-10 04:02:47 +08:00
if ( newlen )
* newlen = j ;
2003-01-12 21:07:14 +08:00
return buf ;
2002-05-10 04:02:47 +08:00
}
2002-05-10 03:42:00 +08:00
2002-02-03 13:40:19 +08:00
static void php_session_initialize ( TSRMLS_D )
1999-06-06 03:52:58 +08:00
{
2002-05-10 04:02:47 +08:00
char * val ;
int vallen ;
2002-09-30 02:33:14 +08:00
if ( ! PS ( mod ) ) {
php_error_docref ( NULL TSRMLS_CC , E_ERROR , " Failed to initialize session module. " ) ;
return ;
}
2002-05-10 04:02:47 +08:00
/* Open session handler first */
2003-02-11 08:42:14 +08:00
if ( PS ( mod ) - > s_open ( & PS ( mod_data ) , PS ( save_path ) , PS ( session_name ) TSRMLS_CC ) = = FAILURE ) {
2002-12-06 04:13:35 +08:00
php_error_docref ( NULL TSRMLS_CC , E_ERROR , " Failed to initialize session module " ) ;
2002-05-10 04:02:47 +08:00
return ;
}
/* If there is no ID, use session module to create one */
if ( ! PS ( id ) )
2003-02-11 08:42:14 +08:00
PS ( id ) = PS ( mod ) - > s_create_sid ( & PS ( mod_data ) , NULL TSRMLS_CC ) ;
2002-05-10 04:02:47 +08:00
/* Read data */
/* Question: if you create a SID here, should you also try to read data?
* I ' m not sure , but while not doing so will remove one session operation
* it could prove usefull for those sites which wish to have " default "
* session information
*/
php_session_track_init ( TSRMLS_C ) ;
2003-02-11 08:42:14 +08:00
if ( PS ( mod ) - > s_read ( & PS ( mod_data ) , PS ( id ) , & val , & vallen TSRMLS_CC ) = = SUCCESS ) {
2002-05-10 04:02:47 +08:00
php_session_decode ( val , vallen TSRMLS_CC ) ;
efree ( val ) ;
}
1999-06-06 03:52:58 +08:00
}
2002-10-07 10:37:50 +08:00
static int migrate_global ( HashTable * ht , HashPosition * pos TSRMLS_DC )
1999-06-06 03:52:58 +08:00
{
2002-10-03 11:23:02 +08:00
char * str ;
uint str_len ;
2002-05-10 04:02:47 +08:00
ulong num_key ;
2002-10-03 11:23:02 +08:00
int n ;
zval * * val = NULL ;
2002-10-07 10:37:50 +08:00
int ret = 0 ;
2002-05-10 04:02:47 +08:00
2002-10-03 11:23:02 +08:00
n = zend_hash_get_current_key_ex ( ht , & str , & str_len , & num_key , 0 , pos ) ;
switch ( n ) {
case HASH_KEY_IS_STRING :
zend_hash_find ( & EG ( symbol_table ) , str , str_len , ( void * * ) & val ) ;
if ( val ) {
2002-10-03 14:29:58 +08:00
ZEND_SET_SYMBOL_WITH_LENGTH ( ht , str , str_len , * val , ( * val ) - > refcount + 1 , 1 ) ;
2002-10-07 10:37:50 +08:00
ret = 1 ;
2002-10-03 11:23:02 +08:00
}
break ;
case HASH_KEY_IS_LONG :
2002-12-06 04:13:35 +08:00
php_error_docref ( NULL TSRMLS_CC , E_NOTICE , " The session bug compatibility code will not "
2002-10-03 11:23:02 +08:00
" try to locate the global variable $%d due to its "
" numeric nature. " , num_key ) ;
break ;
2002-09-29 23:26:50 +08:00
}
2002-10-07 10:37:50 +08:00
return ret ;
2002-10-03 11:23:02 +08:00
}
static void php_session_save_current_state ( TSRMLS_D )
{
int ret = FAILURE ;
IF_SESSION_VARS ( ) {
if ( PS ( bug_compat ) & & ! PG ( register_globals ) ) {
HashTable * ht = Z_ARRVAL_P ( PS ( http_session_vars ) ) ;
HashPosition pos ;
zval * * val ;
int do_warn = 0 ;
zend_hash_internal_pointer_reset_ex ( ht , & pos ) ;
while ( zend_hash_get_current_data_ex ( ht ,
( void * * ) & val , & pos ) ! = FAILURE ) {
if ( Z_TYPE_PP ( val ) = = IS_NULL ) {
2002-10-07 10:37:50 +08:00
if ( migrate_global ( ht , & pos TSRMLS_CC ) )
do_warn = 1 ;
2002-10-03 11:23:02 +08:00
}
zend_hash_move_forward_ex ( ht , & pos ) ;
}
if ( do_warn & & PS ( bug_compat_warn ) ) {
2002-12-06 04:13:35 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Your script possibly relies on a session side-effect which existed until PHP 4.2.3. Please be advised that the session extension does not consider global variables as a source of data, unless register_globals is enabled. You can disable this functionality and this warning by setting session.bug_compat_42 or session.bug_compat_warn to off, respectively. " ) ;
2002-10-03 11:23:02 +08:00
}
2002-05-10 04:02:47 +08:00
}
2002-10-03 13:53:45 +08:00
if ( PS ( mod_data ) ) {
char * val ;
int vallen ;
2002-10-03 11:23:02 +08:00
2002-10-03 13:53:45 +08:00
val = php_session_encode ( & vallen TSRMLS_CC ) ;
if ( val ) {
2003-02-11 08:42:14 +08:00
ret = PS ( mod ) - > s_write ( & PS ( mod_data ) , PS ( id ) , val , vallen TSRMLS_CC ) ;
2002-10-03 13:53:45 +08:00
efree ( val ) ;
} else {
2003-02-11 08:42:14 +08:00
ret = PS ( mod ) - > s_write ( & PS ( mod_data ) , PS ( id ) , " " , 0 TSRMLS_CC ) ;
2002-10-03 13:53:45 +08:00
}
2002-05-10 04:02:47 +08:00
}
2002-10-03 13:53:45 +08:00
if ( ret = = FAILURE )
2002-12-06 04:13:35 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Failed to write session data (%s). Please "
2002-10-03 13:53:45 +08:00
" verify that the current setting of session.save_path "
" is correct (%s) " ,
2003-02-11 08:42:14 +08:00
PS ( mod ) - > s_name ,
2002-10-03 13:53:45 +08:00
PS ( save_path ) ) ;
2002-05-10 04:02:47 +08:00
}
if ( PS ( mod_data ) )
2003-02-11 08:42:14 +08:00
PS ( mod ) - > s_close ( & PS ( mod_data ) TSRMLS_CC ) ;
1999-06-06 03:52:58 +08:00
}
1999-12-12 22:16:55 +08:00
static char * month_names [ ] = {
2002-05-10 04:02:47 +08:00
" Jan " , " Feb " , " Mar " , " Apr " , " May " , " Jun " ,
" Jul " , " Aug " , " Sep " , " Oct " , " Nov " , " Dec "
1999-12-12 22:16:55 +08:00
} ;
1999-12-12 22:22:55 +08:00
static char * week_days [ ] = {
2002-05-10 04:02:47 +08:00
" Sun " , " Mon " , " Tue " , " Wed " , " Thu " , " Fri " , " Sat " , " Sun "
1999-12-12 22:16:55 +08:00
} ;
2001-03-14 00:53:34 +08:00
static void strcpy_gmt ( char * ubuf , time_t * when )
1999-12-12 22:16:55 +08:00
{
2002-05-10 04:02:47 +08:00
char buf [ MAX_STR ] ;
struct tm tm ;
int n ;
php_gmtime_r ( when , & tm ) ;
2002-05-12 20:51:42 +08:00
n = sprintf ( buf , " %s, %d %s %d %02d:%02d:%02d GMT " , /* SAFE */
2002-05-10 04:02:47 +08:00
week_days [ tm . tm_wday ] , tm . tm_mday ,
month_names [ tm . tm_mon ] , tm . tm_year + 1900 ,
tm . tm_hour , tm . tm_min ,
tm . tm_sec ) ;
memcpy ( ubuf , buf , n ) ;
ubuf [ n ] = ' \0 ' ;
1999-12-12 22:16:55 +08:00
}
2001-08-05 22:36:51 +08:00
static void last_modified ( TSRMLS_D )
1999-12-12 22:16:55 +08:00
{
2002-05-10 04:02:47 +08:00
const char * path ;
struct stat sb ;
char buf [ MAX_STR + 1 ] ;
path = SG ( request_info ) . path_translated ;
if ( path ) {
if ( VCWD_STAT ( path , & sb ) = = - 1 ) {
return ;
}
1999-12-12 22:16:55 +08:00
2001-03-14 00:53:34 +08:00
# define LAST_MODIFIED "Last-Modified: "
2002-05-10 04:02:47 +08:00
memcpy ( buf , LAST_MODIFIED , sizeof ( LAST_MODIFIED ) - 1 ) ;
strcpy_gmt ( buf + sizeof ( LAST_MODIFIED ) - 1 , & sb . st_mtime ) ;
ADD_COOKIE ( buf ) ;
}
1999-12-12 22:16:55 +08:00
}
CACHE_LIMITER_FUNC ( public )
{
2002-05-10 04:02:47 +08:00
char buf [ MAX_STR + 1 ] ;
struct timeval tv ;
time_t now ;
gettimeofday ( & tv , NULL ) ;
now = tv . tv_sec + PS ( cache_expire ) * 60 ;
2001-03-14 00:53:34 +08:00
# define EXPIRES "Expires: "
2002-05-10 04:02:47 +08:00
memcpy ( buf , EXPIRES , sizeof ( EXPIRES ) - 1 ) ;
strcpy_gmt ( buf + sizeof ( EXPIRES ) - 1 , & now ) ;
ADD_COOKIE ( buf ) ;
2002-05-12 20:51:42 +08:00
sprintf ( buf , " Cache-Control: public, max-age=%ld " , PS ( cache_expire ) * 60 ) ; /* SAFE */
2002-05-10 04:02:47 +08:00
ADD_COOKIE ( buf ) ;
last_modified ( TSRMLS_C ) ;
1999-12-12 22:16:55 +08:00
}
2001-09-21 21:38:44 +08:00
2002-05-12 20:51:42 +08:00
CACHE_LIMITER_FUNC ( private_no_expire )
1999-12-12 22:16:55 +08:00
{
2002-05-10 04:02:47 +08:00
char buf [ MAX_STR + 1 ] ;
2002-05-12 20:51:42 +08:00
sprintf ( buf , " Cache-Control: private, max-age=%ld, pre-check=%ld " , PS ( cache_expire ) * 60 , PS ( cache_expire ) * 60 ) ; /* SAFE */
2002-05-10 04:02:47 +08:00
ADD_COOKIE ( buf ) ;
1999-12-12 22:16:55 +08:00
2002-05-10 04:02:47 +08:00
last_modified ( TSRMLS_C ) ;
1999-12-12 22:16:55 +08:00
}
2002-05-12 20:51:42 +08:00
CACHE_LIMITER_FUNC ( private )
2001-11-03 06:27:07 +08:00
{
2002-05-12 20:51:42 +08:00
ADD_COOKIE ( " Expires: Thu, 19 Nov 1981 08:52:00 GMT " ) ;
CACHE_LIMITER ( private_no_expire ) ( TSRMLS_C ) ;
2001-11-03 06:27:07 +08:00
}
1999-12-12 22:16:55 +08:00
CACHE_LIMITER_FUNC ( nocache )
{
2002-05-10 04:02:47 +08:00
ADD_COOKIE ( " Expires: Thu, 19 Nov 1981 08:52:00 GMT " ) ;
/* For HTTP/1.1 conforming clients and the rest (MSIE 5) */
ADD_COOKIE ( " Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 " ) ;
/* For HTTP/1.0 conforming clients */
ADD_COOKIE ( " Pragma: no-cache " ) ;
1999-12-12 22:16:55 +08:00
}
2000-09-06 22:16:12 +08:00
static php_session_cache_limiter_t php_session_cache_limiters [ ] = {
2002-05-12 20:51:42 +08:00
CACHE_LIMITER_ENTRY ( public )
CACHE_LIMITER_ENTRY ( private )
CACHE_LIMITER_ENTRY ( private_no_expire )
CACHE_LIMITER_ENTRY ( nocache )
2002-05-10 04:02:47 +08:00
{ 0 }
1999-12-12 22:16:55 +08:00
} ;
2001-07-28 19:36:37 +08:00
static int php_session_cache_limiter ( TSRMLS_D )
1999-12-12 22:16:55 +08:00
{
2002-05-10 04:02:47 +08:00
php_session_cache_limiter_t * lim ;
2002-10-03 23:10:36 +08:00
if ( PS ( cache_limiter ) [ 0 ] = = ' \0 ' ) return 0 ;
2002-05-10 04:02:47 +08:00
if ( SG ( headers_sent ) ) {
char * output_start_filename = php_get_output_start_filename ( TSRMLS_C ) ;
int output_start_lineno = php_get_output_start_lineno ( TSRMLS_C ) ;
if ( output_start_filename ) {
2002-12-06 04:13:35 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Cannot send session cache limiter - headers already sent (output started at %s:%d) " ,
2002-05-10 04:02:47 +08:00
output_start_filename , output_start_lineno ) ;
} else {
2002-12-06 04:13:35 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Cannot send session cache limiter - headers already sent " ) ;
2002-05-10 04:02:47 +08:00
}
2002-10-03 23:10:36 +08:00
return - 2 ;
2002-05-10 04:02:47 +08:00
}
for ( lim = php_session_cache_limiters ; lim - > name ; lim + + ) {
if ( ! strcasecmp ( lim - > name , PS ( cache_limiter ) ) ) {
lim - > func ( TSRMLS_C ) ;
2002-10-03 23:10:36 +08:00
return 0 ;
2002-05-10 04:02:47 +08:00
}
}
2002-10-03 23:10:36 +08:00
return - 1 ;
1999-12-12 22:16:55 +08:00
}
2001-03-14 00:53:34 +08:00
# define COOKIE_SET_COOKIE "Set-Cookie: "
2002-05-10 04:02:47 +08:00
# define COOKIE_EXPIRES "; expires="
# define COOKIE_PATH "; path="
# define COOKIE_DOMAIN "; domain="
# define COOKIE_SECURE "; secure"
1999-06-06 03:52:58 +08:00
2001-07-28 19:36:37 +08:00
static void php_session_send_cookie ( TSRMLS_D )
1999-06-06 03:52:58 +08:00
{
2002-05-10 04:02:47 +08:00
smart_str ncookie = { 0 } ;
char * date_fmt = NULL ;
if ( SG ( headers_sent ) ) {
char * output_start_filename = php_get_output_start_filename ( TSRMLS_C ) ;
int output_start_lineno = php_get_output_start_lineno ( TSRMLS_C ) ;
if ( output_start_filename ) {
2002-12-06 04:13:35 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Cannot send session cookie - headers already sent by (output started at %s:%d) " ,
2002-05-10 04:02:47 +08:00
output_start_filename , output_start_lineno ) ;
} else {
2002-12-06 04:13:35 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Cannot send session cookie - headers already sent " ) ;
2002-05-10 04:02:47 +08:00
}
return ;
}
smart_str_appends ( & ncookie , COOKIE_SET_COOKIE ) ;
smart_str_appends ( & ncookie , PS ( session_name ) ) ;
smart_str_appendc ( & ncookie , ' = ' ) ;
smart_str_appends ( & ncookie , PS ( id ) ) ;
if ( PS ( cookie_lifetime ) > 0 ) {
struct timeval tv ;
gettimeofday ( & tv , NULL ) ;
date_fmt = php_std_date ( tv . tv_sec + PS ( cookie_lifetime ) ) ;
smart_str_appends ( & ncookie , COOKIE_EXPIRES ) ;
smart_str_appends ( & ncookie , date_fmt ) ;
efree ( date_fmt ) ;
}
if ( PS ( cookie_path ) [ 0 ] ) {
smart_str_appends ( & ncookie , COOKIE_PATH ) ;
smart_str_appends ( & ncookie , PS ( cookie_path ) ) ;
}
if ( PS ( cookie_domain ) [ 0 ] ) {
smart_str_appends ( & ncookie , COOKIE_DOMAIN ) ;
smart_str_appends ( & ncookie , PS ( cookie_domain ) ) ;
}
if ( PS ( cookie_secure ) ) {
smart_str_appends ( & ncookie , COOKIE_SECURE ) ;
}
smart_str_0 ( & ncookie ) ;
sapi_add_header ( ncookie . c , ncookie . len , 0 ) ;
1999-06-06 03:52:58 +08:00
}
2001-07-28 19:36:37 +08:00
static ps_module * _php_find_ps_module ( char * name TSRMLS_DC )
1999-06-06 03:52:58 +08:00
{
2002-05-10 04:02:47 +08:00
ps_module * ret = NULL ;
ps_module * * mod ;
int i ;
for ( i = 0 , mod = ps_modules ; i < MAX_MODULES ; i + + , mod + + )
2003-02-11 08:42:14 +08:00
if ( * mod & & ! strcasecmp ( name , ( * mod ) - > s_name ) ) {
2002-05-10 04:02:47 +08:00
ret = * mod ;
break ;
}
return ret ;
1999-06-06 03:52:58 +08:00
}
2001-07-28 19:36:37 +08:00
static const ps_serializer * _php_find_ps_serializer ( char * name TSRMLS_DC )
1999-07-01 13:45:48 +08:00
{
2002-05-10 04:02:47 +08:00
const ps_serializer * ret = NULL ;
const ps_serializer * mod ;
1999-07-01 13:45:48 +08:00
2002-05-10 04:02:47 +08:00
for ( mod = ps_serializers ; mod - > name ; mod + + )
if ( ! strcasecmp ( name , mod - > name ) ) {
ret = mod ;
break ;
}
1999-07-01 13:45:48 +08:00
2002-05-10 04:02:47 +08:00
return ret ;
1999-07-01 13:45:48 +08:00
}
1999-12-22 08:38:04 +08:00
# define PPID2SID \
2002-05-10 04:02:47 +08:00
convert_to_string ( ( * ppid ) ) ; \
PS ( id ) = estrndup ( Z_STRVAL_PP ( ppid ) , Z_STRLEN_PP ( ppid ) )
1999-12-22 08:38:04 +08:00
2003-02-19 03:29:38 +08:00
static void php_session_reset_id ( TSRMLS_D )
{
int module_number = PS ( module_number ) ;
if ( PS ( send_cookie ) ) {
php_session_send_cookie ( TSRMLS_C ) ;
}
/* if the SID constant exists, destroy it. */
zend_hash_del ( EG ( zend_constants ) , " sid " , sizeof ( " sid " ) ) ;
if ( PS ( define_sid ) ) {
smart_str var = { 0 } ;
smart_str_appends ( & var , PS ( session_name ) ) ;
smart_str_appendc ( & var , ' = ' ) ;
smart_str_appends ( & var , PS ( id ) ) ;
smart_str_0 ( & var ) ;
REGISTER_STRINGL_CONSTANT ( " SID " , var . c , var . len , 0 ) ;
} else {
REGISTER_STRINGL_CONSTANT ( " SID " , empty_string , 0 , 0 ) ;
}
if ( PS ( apply_trans_sid ) ) {
php_url_scanner_reset_vars ( TSRMLS_C ) ;
php_url_scanner_add_var ( PS ( session_name ) , strlen ( PS ( session_name ) ) , PS ( id ) , strlen ( PS ( id ) ) , 0 TSRMLS_CC ) ;
}
}
2002-02-05 09:28:55 +08:00
PHPAPI void php_session_start ( TSRMLS_D )
1999-06-06 06:15:49 +08:00
{
2002-05-10 04:02:47 +08:00
zval * * ppid ;
zval * * data ;
char * p ;
int nrand ;
int lensess ;
PS ( apply_trans_sid ) = PS ( use_trans_sid ) ;
2003-02-19 03:29:38 +08:00
PS ( define_sid ) = 1 ;
2003-02-19 03:13:49 +08:00
PS ( send_cookie ) = 1 ;
2002-05-10 04:02:47 +08:00
if ( PS ( session_status ) ! = php_session_none )
return ;
lensess = strlen ( PS ( session_name ) ) ;
/*
* Cookies are preferred , because initially
* cookie and get variables will be available .
*/
if ( ! PS ( id ) ) {
if ( zend_hash_find ( & EG ( symbol_table ) , " _COOKIE " ,
sizeof ( " _COOKIE " ) , ( void * * ) & data ) = = SUCCESS & &
Z_TYPE_PP ( data ) = = IS_ARRAY & &
zend_hash_find ( Z_ARRVAL_PP ( data ) , PS ( session_name ) ,
lensess + 1 , ( void * * ) & ppid ) = = SUCCESS ) {
PPID2SID ;
PS ( apply_trans_sid ) = 0 ;
2003-02-19 03:13:49 +08:00
PS ( send_cookie ) = 0 ;
2003-02-19 03:29:38 +08:00
PS ( define_sid ) = 0 ;
2002-05-10 04:02:47 +08:00
}
2002-06-12 16:18:36 +08:00
if ( ! PS ( use_only_cookies ) & & ! PS ( id ) & &
2002-05-10 04:02:47 +08:00
zend_hash_find ( & EG ( symbol_table ) , " _GET " ,
sizeof ( " _GET " ) , ( void * * ) & data ) = = SUCCESS & &
Z_TYPE_PP ( data ) = = IS_ARRAY & &
zend_hash_find ( Z_ARRVAL_PP ( data ) , PS ( session_name ) ,
lensess + 1 , ( void * * ) & ppid ) = = SUCCESS ) {
PPID2SID ;
2003-02-19 03:13:49 +08:00
PS ( send_cookie ) = 0 ;
2002-05-10 04:02:47 +08:00
}
2002-06-12 16:18:36 +08:00
if ( ! PS ( use_only_cookies ) & & ! PS ( id ) & &
2002-05-10 04:02:47 +08:00
zend_hash_find ( & EG ( symbol_table ) , " _POST " ,
sizeof ( " _POST " ) , ( void * * ) & data ) = = SUCCESS & &
Z_TYPE_PP ( data ) = = IS_ARRAY & &
zend_hash_find ( Z_ARRVAL_PP ( data ) , PS ( session_name ) ,
lensess + 1 , ( void * * ) & ppid ) = = SUCCESS ) {
PPID2SID ;
2003-02-19 03:13:49 +08:00
PS ( send_cookie ) = 0 ;
2002-05-10 04:02:47 +08:00
}
}
/* check the REQUEST_URI symbol for a string of the form
' < session - name > = < session - id > ' to allow URLs of the form
2002-07-03 10:16:46 +08:00
http : //yoursite/<session-name>=<session-id>/script.php */
1999-08-22 04:48:40 +08:00
2002-06-12 16:18:36 +08:00
if ( ! PS ( use_only_cookies ) & & ! PS ( id ) & &
1999-12-12 22:22:55 +08:00
zend_hash_find ( & EG ( symbol_table ) , " REQUEST_URI " ,
1999-07-23 01:55:13 +08:00
sizeof ( " REQUEST_URI " ) , ( void * * ) & data ) = = SUCCESS & &
2000-09-06 22:13:31 +08:00
Z_TYPE_PP ( data ) = = IS_STRING & &
( p = strstr ( Z_STRVAL_PP ( data ) , PS ( session_name ) ) ) & &
1999-07-23 01:55:13 +08:00
p [ lensess ] = = ' = ' ) {
char * q ;
p + = lensess + 1 ;
2000-02-11 20:59:08 +08:00
if ( ( q = strpbrk ( p , " /? \\ " ) ) )
1999-07-23 01:55:13 +08:00
PS ( id ) = estrndup ( p , q - p ) ;
}
1999-08-22 04:48:40 +08:00
/* check whether the current request was referred to by
an external site which invalidates the previously found id */
2000-02-11 20:59:08 +08:00
if ( PS ( id ) & &
1999-08-22 04:48:40 +08:00
PS ( extern_referer_chk ) [ 0 ] ! = ' \0 ' & &
zend_hash_find ( & EG ( symbol_table ) , " HTTP_REFERER " ,
sizeof ( " HTTP_REFERER " ) , ( void * * ) & data ) = = SUCCESS & &
2000-09-06 22:13:31 +08:00
Z_TYPE_PP ( data ) = = IS_STRING & &
Z_STRLEN_PP ( data ) ! = 0 & &
strstr ( Z_STRVAL_PP ( data ) , PS ( extern_referer_chk ) ) = = NULL ) {
1999-08-22 04:48:40 +08:00
efree ( PS ( id ) ) ;
PS ( id ) = NULL ;
2003-02-19 03:13:49 +08:00
PS ( send_cookie ) = 1 ;
2001-10-18 17:05:16 +08:00
if ( PS ( use_trans_sid ) )
PS ( apply_trans_sid ) = 1 ;
1999-08-22 04:48:40 +08:00
}
1999-06-06 06:15:49 +08:00
2002-03-30 00:00:27 +08:00
php_session_initialize ( TSRMLS_C ) ;
1999-10-22 16:10:08 +08:00
2003-02-19 03:13:49 +08:00
if ( ! PS ( use_cookies ) & & PS ( send_cookie ) ) {
2001-10-18 17:05:16 +08:00
if ( PS ( use_trans_sid ) )
PS ( apply_trans_sid ) = 1 ;
2003-02-19 03:13:49 +08:00
PS ( send_cookie ) = 0 ;
1999-10-22 16:10:08 +08:00
}
2001-07-11 21:46:11 +08:00
2003-02-19 03:29:38 +08:00
php_session_reset_id ( TSRMLS_C ) ;
2002-09-27 02:12:27 +08:00
2001-08-26 19:49:43 +08:00
PS ( session_status ) = php_session_active ;
1999-06-06 06:15:49 +08:00
2001-07-28 19:36:37 +08:00
php_session_cache_limiter ( TSRMLS_C ) ;
2002-02-03 13:40:19 +08:00
2002-03-06 17:02:31 +08:00
if ( PS ( mod_data ) & & PS ( gc_probability ) > 0 ) {
2000-03-30 04:37:29 +08:00
int nrdels = - 1 ;
2002-03-06 17:02:31 +08:00
2002-10-03 14:45:15 +08:00
nrand = ( int ) ( ( float ) PS ( gc_dividend ) * php_combined_lcg ( TSRMLS_C ) ) ;
2001-07-26 03:02:13 +08:00
if ( nrand < PS ( gc_probability ) ) {
2003-02-11 08:42:14 +08:00
PS ( mod ) - > s_gc ( & PS ( mod_data ) , PS ( gc_maxlifetime ) , & nrdels TSRMLS_CC ) ;
2000-09-20 09:38:39 +08:00
#if 0
2002-05-10 04:02:47 +08:00
if ( nrdels ! = - 1 )
2002-12-06 04:13:35 +08:00
php_error_docref ( NULL TSRMLS_CC , E_NOTICE , " purged %d expired session objects \n " , nrdels ) ;
2000-09-20 09:38:39 +08:00
# endif
2002-05-10 04:02:47 +08:00
}
}
1999-06-08 00:43:24 +08:00
}
2001-07-28 19:36:37 +08:00
static zend_bool php_session_destroy ( TSRMLS_D )
1999-06-08 00:43:24 +08:00
{
2002-05-10 04:02:47 +08:00
zend_bool retval = SUCCESS ;
2000-07-05 09:26:22 +08:00
2002-05-10 04:02:47 +08:00
if ( PS ( session_status ) ! = php_session_active ) {
2002-12-06 04:13:35 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Trying to destroy uninitialized session " ) ;
2002-05-10 04:02:47 +08:00
return FAILURE ;
}
2002-05-10 03:42:00 +08:00
2003-02-11 08:42:14 +08:00
if ( PS ( mod ) - > s_destroy ( & PS ( mod_data ) , PS ( id ) TSRMLS_CC ) = = FAILURE ) {
2002-05-10 04:02:47 +08:00
retval = FAILURE ;
2002-12-06 04:13:35 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Session object destruction failed " ) ;
2002-05-10 04:02:47 +08:00
}
php_rshutdown_session_globals ( TSRMLS_C ) ;
php_rinit_session_globals ( TSRMLS_C ) ;
2000-07-05 09:26:22 +08:00
2002-05-10 04:02:47 +08:00
return retval ;
1999-06-06 06:15:49 +08:00
}
2001-09-11 18:16:01 +08:00
2000-10-29 01:13:28 +08:00
/* {{{ proto void session_set_cookie_params(int lifetime [, string path [, string domain [, bool secure]]])
2000-02-05 07:34:24 +08:00
Set session cookie parameters */
PHP_FUNCTION ( session_set_cookie_params )
{
2002-07-03 10:16:46 +08:00
zval * * lifetime , * * path , * * domain , * * secure ;
2000-02-05 07:34:24 +08:00
2002-05-10 04:02:47 +08:00
if ( ! PS ( use_cookies ) )
return ;
2000-02-05 07:34:24 +08:00
2002-07-03 10:16:46 +08:00
if ( ZEND_NUM_ARGS ( ) < 1 | | ZEND_NUM_ARGS ( ) > 4 | |
2002-05-10 04:02:47 +08:00
zend_get_parameters_ex ( ZEND_NUM_ARGS ( ) , & lifetime , & path , & domain , & secure ) = = FAILURE )
WRONG_PARAM_COUNT ;
convert_to_long_ex ( lifetime ) ;
PS ( cookie_lifetime ) = Z_LVAL_PP ( lifetime ) ;
if ( ZEND_NUM_ARGS ( ) > 1 ) {
convert_to_string_ex ( path ) ;
zend_alter_ini_entry ( " session.cookie_path " , sizeof ( " session.cookie_path " ) , Z_STRVAL_PP ( path ) , Z_STRLEN_PP ( path ) , PHP_INI_USER , PHP_INI_STAGE_RUNTIME ) ;
if ( ZEND_NUM_ARGS ( ) > 2 ) {
convert_to_string_ex ( domain ) ;
zend_alter_ini_entry ( " session.cookie_domain " , sizeof ( " session.cookie_domain " ) , Z_STRVAL_PP ( domain ) , Z_STRLEN_PP ( domain ) , PHP_INI_USER , PHP_INI_STAGE_RUNTIME ) ;
if ( ZEND_NUM_ARGS ( ) > 3 ) {
convert_to_long_ex ( secure ) ;
zend_alter_ini_entry ( " session.cookie_secure " , sizeof ( " session.cookie_secure " ) , Z_BVAL_PP ( secure ) ? " 1 " : " 0 " , 1 , PHP_INI_USER , PHP_INI_STAGE_RUNTIME ) ;
}
}
}
2000-02-05 07:34:24 +08:00
}
/* }}} */
2000-06-24 01:37:49 +08:00
/* {{{ proto array session_get_cookie_params(void)
2002-05-10 04:02:47 +08:00
Return the session cookie parameters */
2000-03-31 04:02:21 +08:00
PHP_FUNCTION ( session_get_cookie_params )
{
2002-05-10 04:02:47 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 0 ) {
WRONG_PARAM_COUNT ;
}
2003-01-19 03:28:10 +08:00
array_init ( return_value ) ;
2002-05-10 04:02:47 +08:00
add_assoc_long ( return_value , " lifetime " , PS ( cookie_lifetime ) ) ;
add_assoc_string ( return_value , " path " , PS ( cookie_path ) , 1 ) ;
add_assoc_string ( return_value , " domain " , PS ( cookie_domain ) , 1 ) ;
add_assoc_bool ( return_value , " secure " , PS ( cookie_secure ) ) ;
2000-03-31 02:50:09 +08:00
}
/* }}} */
2000-02-05 07:34:24 +08:00
1999-06-06 22:19:55 +08:00
/* {{{ proto string session_name([string newname])
2000-06-24 01:37:49 +08:00
Return the current session name . If newname is given , the session name is replaced with newname */
1999-06-06 03:52:58 +08:00
PHP_FUNCTION ( session_name )
{
2002-05-10 04:02:47 +08:00
zval * * p_name ;
int ac = ZEND_NUM_ARGS ( ) ;
char * old ;
1999-06-06 03:52:58 +08:00
2002-05-10 04:02:47 +08:00
if ( ac < 0 | | ac > 1 | | zend_get_parameters_ex ( ac , & p_name ) = = FAILURE )
WRONG_PARAM_COUNT ;
old = estrdup ( PS ( session_name ) ) ;
2002-05-10 03:42:00 +08:00
2002-05-10 04:02:47 +08:00
if ( ac = = 1 ) {
convert_to_string_ex ( p_name ) ;
zend_alter_ini_entry ( " session.name " , sizeof ( " session.name " ) , Z_STRVAL_PP ( p_name ) , Z_STRLEN_PP ( p_name ) , PHP_INI_USER , PHP_INI_STAGE_RUNTIME ) ;
}
RETVAL_STRING ( old , 0 ) ;
1999-06-06 03:52:58 +08:00
}
1999-06-06 22:19:55 +08:00
/* }}} */
1999-06-06 03:52:58 +08:00
1999-06-06 22:19:55 +08:00
/* {{{ proto string session_module_name([string newname])
2000-06-24 01:37:49 +08:00
Return the current module name used for accessing session data . If newname is given , the module name is replaced with newname */
1999-06-06 03:52:58 +08:00
PHP_FUNCTION ( session_module_name )
{
2002-05-10 04:02:47 +08:00
zval * * p_name ;
int ac = ZEND_NUM_ARGS ( ) ;
char * old ;
if ( ac < 0 | | ac > 1 | | zend_get_parameters_ex ( ac , & p_name ) = = FAILURE )
WRONG_PARAM_COUNT ;
2003-02-11 08:42:14 +08:00
old = safe_estrdup ( PS ( mod ) - > s_name ) ;
2002-05-10 04:02:47 +08:00
if ( ac = = 1 ) {
ps_module * tempmod ;
convert_to_string_ex ( p_name ) ;
tempmod = _php_find_ps_module ( Z_STRVAL_PP ( p_name ) TSRMLS_CC ) ;
if ( tempmod ) {
if ( PS ( mod_data ) )
2003-02-11 08:42:14 +08:00
PS ( mod ) - > s_close ( & PS ( mod_data ) TSRMLS_CC ) ;
2002-05-10 04:02:47 +08:00
PS ( mod ) = tempmod ;
PS ( mod_data ) = NULL ;
} else {
efree ( old ) ;
2002-12-06 04:13:35 +08:00
php_error_docref ( NULL TSRMLS_CC , E_ERROR , " Cannot find named PHP session module (%s) " ,
2002-05-10 04:02:47 +08:00
Z_STRVAL_PP ( p_name ) ) ;
RETURN_FALSE ;
}
}
RETVAL_STRING ( old , 0 ) ;
1999-06-06 03:52:58 +08:00
}
1999-06-06 22:19:55 +08:00
/* }}} */
1999-06-06 03:52:58 +08:00
2002-03-06 17:02:31 +08:00
/* {{{ proto void session_set_save_handler(string open, string close, string read, string write, string destroy, string gc)
2000-02-24 23:11:09 +08:00
Sets user - level functions */
1999-09-17 13:40:59 +08:00
PHP_FUNCTION ( session_set_save_handler )
{
2002-05-10 04:02:47 +08:00
zval * * args [ 6 ] ;
int i ;
ps_user * mdata ;
2002-05-10 03:42:00 +08:00
2002-05-10 04:02:47 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 6 | | zend_get_parameters_array_ex ( 6 , args ) = = FAILURE )
WRONG_PARAM_COUNT ;
if ( PS ( session_status ) ! = php_session_none )
RETURN_FALSE ;
zend_alter_ini_entry ( " session.save_handler " , sizeof ( " session.save_handler " ) , " user " , sizeof ( " user " ) - 1 , PHP_INI_USER , PHP_INI_STAGE_RUNTIME ) ;
2002-05-10 03:42:00 +08:00
2002-05-10 04:02:47 +08:00
mdata = emalloc ( sizeof ( * mdata ) ) ;
for ( i = 0 ; i < 6 ; i + + ) {
ZVAL_ADDREF ( * args [ i ] ) ;
mdata - > names [ i ] = * args [ i ] ;
}
2002-05-10 03:42:00 +08:00
2002-05-10 04:02:47 +08:00
PS ( mod_data ) = ( void * ) mdata ;
RETURN_TRUE ;
1999-09-17 13:40:59 +08:00
}
/* }}} */
1999-06-06 22:19:55 +08:00
/* {{{ proto string session_save_path([string newname])
2000-06-24 01:37:49 +08:00
Return the current save path passed to module_name . If newname is given , the save path is replaced with newname */
1999-06-06 03:52:58 +08:00
PHP_FUNCTION ( session_save_path )
{
2002-05-10 04:02:47 +08:00
zval * * p_name ;
int ac = ZEND_NUM_ARGS ( ) ;
char * old ;
2002-05-10 03:42:00 +08:00
2002-05-10 04:02:47 +08:00
if ( ac < 0 | | ac > 1 | | zend_get_parameters_ex ( ac , & p_name ) = = FAILURE )
WRONG_PARAM_COUNT ;
old = estrdup ( PS ( save_path ) ) ;
2002-05-10 03:42:00 +08:00
2002-05-10 04:02:47 +08:00
if ( ac = = 1 ) {
convert_to_string_ex ( p_name ) ;
zend_alter_ini_entry ( " session.save_path " , sizeof ( " session.save_path " ) , Z_STRVAL_PP ( p_name ) , Z_STRLEN_PP ( p_name ) , PHP_INI_USER , PHP_INI_STAGE_RUNTIME ) ;
}
RETVAL_STRING ( old , 0 ) ;
1999-06-06 03:52:58 +08:00
}
1999-06-06 22:19:55 +08:00
/* }}} */
1999-06-06 03:52:58 +08:00
1999-06-06 22:19:55 +08:00
/* {{{ proto string session_id([string newid])
2000-06-24 01:37:49 +08:00
Return the current session id . If newid is given , the session id is replaced with newid */
1999-06-06 03:52:58 +08:00
PHP_FUNCTION ( session_id )
{
2002-05-10 04:02:47 +08:00
zval * * p_name ;
int ac = ZEND_NUM_ARGS ( ) ;
char * old = empty_string ;
2002-03-06 17:02:31 +08:00
2002-05-10 04:02:47 +08:00
if ( ac < 0 | | ac > 1 | | zend_get_parameters_ex ( ac , & p_name ) = = FAILURE )
WRONG_PARAM_COUNT ;
2002-03-06 20:34:47 +08:00
2002-05-10 04:02:47 +08:00
if ( PS ( id ) )
old = estrdup ( PS ( id ) ) ;
2002-05-10 03:42:00 +08:00
2002-05-10 04:02:47 +08:00
if ( ac = = 1 ) {
convert_to_string_ex ( p_name ) ;
if ( PS ( id ) ) efree ( PS ( id ) ) ;
PS ( id ) = estrndup ( Z_STRVAL_PP ( p_name ) , Z_STRLEN_PP ( p_name ) ) ;
}
RETVAL_STRING ( old , 0 ) ;
1999-06-06 03:52:58 +08:00
}
1999-06-06 22:19:55 +08:00
/* }}} */
1999-06-06 03:52:58 +08:00
2003-02-19 02:50:44 +08:00
/* {{{ proto string session_regenerate_id()
Update the current session id with a newly generated one . */
PHP_FUNCTION ( session_regenerate_id )
{
2003-02-19 03:13:49 +08:00
if ( PS ( session_status ) = = php_session_active ) {
2003-02-19 02:50:44 +08:00
if ( PS ( id ) ) efree ( PS ( id ) ) ;
PS ( id ) = PS ( mod ) - > s_create_sid ( & PS ( mod_data ) , NULL TSRMLS_CC ) ;
2003-02-19 03:13:49 +08:00
2003-02-19 03:29:38 +08:00
php_session_reset_id ( TSRMLS_C ) ;
2003-02-19 02:50:44 +08:00
RETURN_TRUE ;
}
RETURN_FALSE ;
}
/* }}} */
2000-09-01 23:56:26 +08:00
/* {{{ proto string session_cache_limiter([string new_cache_limiter])
Return the current cache limiter . If new_cache_limited is given , the current cache_limiter is replaced with new_cache_limiter */
PHP_FUNCTION ( session_cache_limiter )
{
2002-05-10 04:02:47 +08:00
zval * * p_cache_limiter ;
int ac = ZEND_NUM_ARGS ( ) ;
char * old ;
2000-09-01 23:56:26 +08:00
2002-05-10 04:02:47 +08:00
if ( ac < 0 | | ac > 1 | | zend_get_parameters_ex ( ac , & p_cache_limiter ) = = FAILURE )
WRONG_PARAM_COUNT ;
old = estrdup ( PS ( cache_limiter ) ) ;
2002-05-10 03:42:00 +08:00
2002-05-10 04:02:47 +08:00
if ( ac = = 1 ) {
convert_to_string_ex ( p_cache_limiter ) ;
zend_alter_ini_entry ( " session.cache_limiter " , sizeof ( " session.cache_limiter " ) , Z_STRVAL_PP ( p_cache_limiter ) , Z_STRLEN_PP ( p_cache_limiter ) , PHP_INI_USER , PHP_INI_STAGE_RUNTIME ) ;
}
RETVAL_STRING ( old , 0 ) ;
2000-09-01 23:56:26 +08:00
}
/* }}} */
2001-10-22 23:18:06 +08:00
/* {{{ proto int session_cache_expire([int new_cache_expire])
Return the current cache expire . If new_cache_expire is given , the current cache_expire is replaced with new_cache_expire */
PHP_FUNCTION ( session_cache_expire )
{
2002-05-10 04:02:47 +08:00
zval * * p_cache_expire ;
int ac = ZEND_NUM_ARGS ( ) ;
long old ;
2002-03-06 17:02:31 +08:00
2002-05-10 04:02:47 +08:00
old = PS ( cache_expire ) ;
2001-10-22 23:18:06 +08:00
2002-05-10 04:02:47 +08:00
if ( ac < 0 | | ac > 1 | | zend_get_parameters_ex ( ac , & p_cache_expire ) = = FAILURE )
WRONG_PARAM_COUNT ;
2001-10-22 23:18:06 +08:00
2002-05-10 04:02:47 +08:00
if ( ac = = 1 ) {
convert_to_long_ex ( p_cache_expire ) ;
PS ( cache_expire ) = Z_LVAL_PP ( p_cache_expire ) ;
}
2001-10-22 23:18:06 +08:00
2002-05-10 04:02:47 +08:00
RETVAL_LONG ( old ) ;
2001-10-22 23:18:06 +08:00
}
/* }}} */
2001-07-28 19:36:37 +08:00
/* {{{ static void php_register_var(zval** entry TSRMLS_DC) */
static void php_register_var ( zval * * entry TSRMLS_DC )
1999-11-28 05:18:41 +08:00
{
2002-05-10 04:02:47 +08:00
zval * * value ;
if ( Z_TYPE_PP ( entry ) = = IS_ARRAY ) {
zend_hash_internal_pointer_reset ( Z_ARRVAL_PP ( entry ) ) ;
while ( zend_hash_get_current_data ( Z_ARRVAL_PP ( entry ) , ( void * * ) & value ) = = SUCCESS ) {
php_register_var ( value TSRMLS_CC ) ;
zend_hash_move_forward ( Z_ARRVAL_PP ( entry ) ) ;
}
} else {
convert_to_string_ex ( entry ) ;
if ( ( strcmp ( Z_STRVAL_PP ( entry ) , " HTTP_SESSION_VARS " ) ! = 0 ) | |
( strcmp ( Z_STRVAL_PP ( entry ) , " _SESSION " ) ! = 0 ) ) {
PS_ADD_VARL ( Z_STRVAL_PP ( entry ) , Z_STRLEN_PP ( entry ) ) ;
}
}
1999-11-28 05:18:41 +08:00
}
/* }}} */
2000-06-24 01:37:49 +08:00
/* {{{ proto bool session_register(mixed var_names [, mixed ...])
2000-02-24 23:11:09 +08:00
Adds varname ( s ) to the list of variables which are freezed at the session end */
1999-06-06 03:52:58 +08:00
PHP_FUNCTION ( session_register )
{
2002-05-10 04:02:47 +08:00
zval * * * args ;
int argc = ZEND_NUM_ARGS ( ) ;
int i ;
if ( argc < = 0 )
RETURN_FALSE
else
args = ( zval * * * ) emalloc ( argc * sizeof ( zval * * ) ) ;
if ( zend_get_parameters_array_ex ( argc , args ) = = FAILURE ) {
efree ( args ) ;
WRONG_PARAM_COUNT ;
}
2002-05-10 03:42:00 +08:00
2002-05-10 04:02:47 +08:00
if ( PS ( session_status ) = = php_session_none )
php_session_start ( TSRMLS_C ) ;
2002-05-10 03:42:00 +08:00
2002-05-10 04:02:47 +08:00
for ( i = 0 ; i < argc ; i + + ) {
if ( Z_TYPE_PP ( args [ i ] ) = = IS_ARRAY )
SEPARATE_ZVAL ( args [ i ] ) ;
php_register_var ( args [ i ] TSRMLS_CC ) ;
}
efree ( args ) ;
RETURN_TRUE ;
1999-06-06 03:52:58 +08:00
}
1999-06-06 22:19:55 +08:00
/* }}} */
1999-06-06 03:52:58 +08:00
1999-10-25 00:17:45 +08:00
/* {{{ proto bool session_unregister(string varname)
2000-02-24 23:11:09 +08:00
Removes varname from the list of variables which are freezed at the session end */
1999-06-06 03:52:58 +08:00
PHP_FUNCTION ( session_unregister )
{
2002-05-10 04:02:47 +08:00
zval * * p_name ;
int ac = ZEND_NUM_ARGS ( ) ;
2002-05-10 03:42:00 +08:00
2002-05-10 04:02:47 +08:00
if ( ac ! = 1 | | zend_get_parameters_ex ( ac , & p_name ) = = FAILURE )
WRONG_PARAM_COUNT ;
convert_to_string_ex ( p_name ) ;
PS_DEL_VARL ( Z_STRVAL_PP ( p_name ) , Z_STRLEN_PP ( p_name ) ) ;
1999-10-25 00:17:45 +08:00
2002-05-10 04:02:47 +08:00
RETURN_TRUE ;
1999-06-06 03:52:58 +08:00
}
1999-06-06 22:19:55 +08:00
/* }}} */
1999-06-06 03:52:58 +08:00
1999-06-28 23:46:56 +08:00
/* {{{ proto bool session_is_registered(string varname)
2000-02-24 23:11:09 +08:00
Checks if a variable is registered in session */
1999-06-28 23:46:56 +08:00
PHP_FUNCTION ( session_is_registered )
{
2002-05-10 04:02:47 +08:00
zval * * p_name ;
zval * p_var ;
int ac = ZEND_NUM_ARGS ( ) ;
1999-06-28 23:46:56 +08:00
2002-05-10 04:02:47 +08:00
if ( ac ! = 1 | | zend_get_parameters_ex ( ac , & p_name ) = = FAILURE )
WRONG_PARAM_COUNT ;
convert_to_string_ex ( p_name ) ;
2002-10-03 11:23:02 +08:00
if ( PS ( session_status ) = = php_session_none )
2002-05-10 04:02:47 +08:00
RETURN_FALSE ;
2002-10-03 11:23:02 +08:00
IF_SESSION_VARS ( ) {
if ( zend_hash_find ( Z_ARRVAL_P ( PS ( http_session_vars ) ) ,
Z_STRVAL_PP ( p_name ) , Z_STRLEN_PP ( p_name ) + 1 ,
( void * * ) & p_var ) = = SUCCESS ) {
RETURN_TRUE ;
}
}
RETURN_FALSE ;
1999-06-28 23:46:56 +08:00
}
/* }}} */
2000-02-24 23:11:09 +08:00
/* {{{ proto string session_encode(void)
Serializes the current setup and returns the serialized representation */
1999-06-06 23:18:51 +08:00
PHP_FUNCTION ( session_encode )
1999-06-06 03:52:58 +08:00
{
2002-05-10 04:02:47 +08:00
int len ;
char * enc ;
1999-06-06 03:52:58 +08:00
2002-05-10 04:02:47 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 0 ) {
WRONG_PARAM_COUNT ;
}
2001-08-13 14:43:47 +08:00
2002-05-10 04:02:47 +08:00
enc = php_session_encode ( & len TSRMLS_CC ) ;
2002-09-29 23:55:11 +08:00
if ( enc = = NULL ) {
RETURN_FALSE ;
}
2002-05-10 04:02:47 +08:00
RETVAL_STRINGL ( enc , len , 0 ) ;
1999-06-06 03:52:58 +08:00
}
1999-06-06 22:19:55 +08:00
/* }}} */
1999-06-06 03:52:58 +08:00
2000-05-24 07:13:02 +08:00
/* {{{ proto bool session_decode(string data)
2000-02-24 23:11:09 +08:00
Deserializes data and reinitializes the variables */
1999-06-06 03:52:58 +08:00
PHP_FUNCTION ( session_decode )
{
2002-05-10 04:02:47 +08:00
zval * * str ;
1999-06-06 03:52:58 +08:00
2002-12-30 02:50:55 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 1 | | zend_get_parameters_ex ( 1 , & str ) = = FAILURE ) {
2002-05-10 04:02:47 +08:00
WRONG_PARAM_COUNT ;
2002-12-30 02:50:55 +08:00
}
1999-06-06 03:52:58 +08:00
2002-12-30 02:50:55 +08:00
if ( PS ( session_status ) = = php_session_none ) {
2002-10-03 23:33:00 +08:00
RETURN_FALSE ;
2002-12-30 02:50:55 +08:00
}
2002-10-03 23:33:00 +08:00
2002-05-10 04:02:47 +08:00
convert_to_string_ex ( str ) ;
1999-09-17 17:26:03 +08:00
2002-05-10 04:02:47 +08:00
php_session_decode ( Z_STRVAL_PP ( str ) , Z_STRLEN_PP ( str ) TSRMLS_CC ) ;
2002-12-30 02:50:55 +08:00
RETURN_TRUE ;
1999-06-06 03:52:58 +08:00
}
1999-06-06 22:19:55 +08:00
/* }}} */
1999-06-06 03:52:58 +08:00
2000-05-24 07:13:02 +08:00
/* {{{ proto bool session_start(void)
1999-06-06 22:19:55 +08:00
Begin session - reinitializes freezed variables , registers browsers etc */
1999-06-06 03:52:58 +08:00
PHP_FUNCTION ( session_start )
{
2002-05-10 04:02:47 +08:00
/* skipping check for non-zero args for performance reasons here ?*/
php_session_start ( TSRMLS_C ) ;
RETURN_TRUE ;
1999-06-06 03:52:58 +08:00
}
1999-06-06 22:19:55 +08:00
/* }}} */
1999-06-06 03:52:58 +08:00
2000-07-05 09:26:22 +08:00
/* {{{ proto bool session_destroy(void)
1999-06-08 00:43:24 +08:00
Destroy the current session and all data associated with it */
PHP_FUNCTION ( session_destroy )
{
2002-05-10 04:02:47 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 0 ) {
WRONG_PARAM_COUNT ;
}
if ( php_session_destroy ( TSRMLS_C ) = = SUCCESS ) {
RETURN_TRUE ;
} else {
RETURN_FALSE ;
}
1999-06-08 00:43:24 +08:00
}
/* }}} */
2001-07-04 23:30:21 +08:00
2000-05-24 07:13:02 +08:00
/* {{{ proto void session_unset(void)
1999-09-12 06:31:04 +08:00
Unset all registered variables */
PHP_FUNCTION ( session_unset )
{
2002-05-10 04:02:47 +08:00
if ( PS ( session_status ) = = php_session_none )
RETURN_FALSE ;
2002-10-03 11:23:02 +08:00
IF_SESSION_VARS ( ) {
HashTable * ht = Z_ARRVAL_P ( PS ( http_session_vars ) ) ;
if ( PG ( register_globals ) ) {
uint str_len ;
char * str ;
ulong num_key ;
HashPosition pos ;
zend_hash_internal_pointer_reset_ex ( ht , & pos ) ;
while ( zend_hash_get_current_key_ex ( ht , & str , & str_len , & num_key ,
0 , & pos ) = = HASH_KEY_IS_STRING ) {
zend_hash_del ( & EG ( symbol_table ) , str , str_len ) ;
zend_hash_move_forward_ex ( ht , & pos ) ;
}
2002-05-10 04:02:47 +08:00
}
2002-10-03 11:23:02 +08:00
/* Clean $_SESSION. */
zend_hash_clean ( ht ) ;
2002-05-10 04:02:47 +08:00
}
1999-09-12 06:31:04 +08:00
}
/* }}} */
2002-05-06 00:39:49 +08:00
PHPAPI void session_adapt_url ( const char * url , size_t urllen , char * * new , size_t * newlen TSRMLS_DC )
{
if ( PS ( apply_trans_sid ) & & ( PS ( session_status ) = = php_session_active ) ) {
* new = php_url_scanner_adapt_single_url ( url , urllen , PS ( session_name ) , PS ( id ) , newlen TSRMLS_CC ) ;
}
}
2001-09-01 04:03:09 +08:00
2001-07-28 19:36:37 +08:00
static void php_rinit_session_globals ( TSRMLS_D )
2000-05-26 21:02:11 +08:00
{
1999-06-07 02:39:48 +08:00
PS ( id ) = NULL ;
2001-07-11 21:27:27 +08:00
PS ( session_status ) = php_session_none ;
1999-06-07 02:39:48 +08:00
PS ( mod_data ) = NULL ;
2002-03-02 23:59:16 +08:00
PS ( http_session_vars ) = NULL ;
1999-06-06 03:52:58 +08:00
}
2001-07-28 19:36:37 +08:00
static void php_rshutdown_session_globals ( TSRMLS_D )
1999-06-06 03:52:58 +08:00
{
2002-05-10 04:02:47 +08:00
if ( PS ( mod_data ) ) {
2003-02-11 08:42:14 +08:00
PS ( mod ) - > s_close ( & PS ( mod_data ) TSRMLS_CC ) ;
2002-05-10 04:02:47 +08:00
}
if ( PS ( id ) ) {
efree ( PS ( id ) ) ;
}
1999-06-06 03:52:58 +08:00
}
1999-11-18 06:59:27 +08:00
1999-09-17 13:40:59 +08:00
PHP_RINIT_FUNCTION ( session )
1999-06-06 03:52:58 +08:00
{
2002-05-10 04:02:47 +08:00
php_rinit_session_globals ( TSRMLS_C ) ;
1999-06-07 02:22:17 +08:00
2002-05-10 04:02:47 +08:00
if ( PS ( mod ) = = NULL ) {
char * value ;
2001-05-24 07:18:51 +08:00
2002-05-10 04:02:47 +08:00
value = zend_ini_string ( " session.save_handler " , sizeof ( " session.save_handler " ) , 0 ) ;
if ( value ) {
PS ( mod ) = _php_find_ps_module ( value TSRMLS_CC ) ;
}
2001-05-24 07:18:51 +08:00
2002-05-10 04:02:47 +08:00
if ( ! PS ( mod ) ) {
/* current status is unusable */
PS ( session_status ) = php_session_disabled ;
return SUCCESS ;
}
}
1999-08-28 05:03:22 +08:00
2002-05-10 04:02:47 +08:00
if ( PS ( auto_start ) ) {
php_session_start ( TSRMLS_C ) ;
}
1999-06-06 03:52:58 +08:00
2002-05-10 04:02:47 +08:00
return SUCCESS ;
2000-01-17 05:03:49 +08:00
}
2000-01-15 21:09:32 +08:00
2001-07-28 19:36:37 +08:00
static void php_session_flush ( TSRMLS_D )
2000-01-17 05:03:49 +08:00
{
2002-05-10 04:02:47 +08:00
if ( PS ( session_status ) = = php_session_active ) {
php_session_save_current_state ( TSRMLS_C ) ;
PS ( session_status ) = php_session_none ;
}
2000-10-12 03:47:15 +08:00
}
2001-12-05 06:57:16 +08:00
/* {{{ proto void session_write_close(void)
Write session data and end session */
2000-10-12 03:47:15 +08:00
PHP_FUNCTION ( session_write_close )
{
2002-05-10 04:02:47 +08:00
php_session_flush ( TSRMLS_C ) ;
2000-10-12 03:47:15 +08:00
}
PHP_RSHUTDOWN_FUNCTION ( session )
{
2001-07-28 19:36:37 +08:00
php_session_flush ( TSRMLS_C ) ;
php_rshutdown_session_globals ( TSRMLS_C ) ;
1999-06-06 03:52:58 +08:00
return SUCCESS ;
}
2001-12-05 06:57:16 +08:00
/* }}} */
2000-01-17 05:03:49 +08:00
1999-09-17 13:40:59 +08:00
PHP_MINIT_FUNCTION ( session )
1999-06-06 03:52:58 +08:00
{
1999-06-07 02:56:11 +08:00
# ifdef ZTS
2002-05-10 04:02:47 +08:00
php_ps_globals * ps_globals ;
1999-07-17 00:09:01 +08:00
2002-05-10 04:02:47 +08:00
ts_allocate_id ( & ps_globals_id , sizeof ( php_ps_globals ) , NULL , NULL ) ;
ps_globals = ts_resource ( ps_globals_id ) ;
1999-06-07 02:56:11 +08:00
# endif
1999-07-17 00:09:01 +08:00
2002-05-10 04:02:47 +08:00
zend_register_auto_global ( " _SESSION " , sizeof ( " _SESSION " ) - 1 TSRMLS_CC ) ;
2001-08-11 18:49:03 +08:00
2002-05-06 00:39:49 +08:00
PS ( module_number ) = module_number ; /* if we really need this var we need to init it in zts mode as well! */
2002-06-28 10:27:02 +08:00
2003-01-08 21:28:16 +08:00
PS ( session_status ) = php_session_none ;
1999-06-06 03:52:58 +08:00
REGISTER_INI_ENTRIES ( ) ;
2002-06-28 10:27:02 +08:00
# ifdef HAVE_LIBMM
PHP_MINIT ( ps_mm ) ( INIT_FUNC_ARGS_PASSTHRU ) ;
# endif
1999-06-06 03:52:58 +08:00
return SUCCESS ;
}
1999-09-17 13:40:59 +08:00
PHP_MSHUTDOWN_FUNCTION ( session )
1999-06-06 03:52:58 +08:00
{
2002-05-10 04:02:47 +08:00
UNREGISTER_INI_ENTRIES ( ) ;
2002-06-28 10:27:02 +08:00
# ifdef HAVE_LIBMM
PHP_MSHUTDOWN ( ps_mm ) ( SHUTDOWN_FUNC_ARGS_PASSTHRU ) ;
# endif
2002-05-10 04:02:47 +08:00
return SUCCESS ;
1999-06-06 03:52:58 +08:00
}
1999-06-07 03:53:59 +08:00
1999-09-17 13:40:59 +08:00
PHP_MINFO_FUNCTION ( session )
1999-06-07 03:53:59 +08:00
{
2002-06-28 10:27:02 +08:00
ps_module * * mod ;
smart_str handlers = { 0 } ;
int i ;
for ( i = 0 , mod = ps_modules ; i < MAX_MODULES ; i + + , mod + + ) {
2003-02-11 08:42:14 +08:00
if ( * mod & & ( * mod ) - > s_name ) {
smart_str_appends ( & handlers , ( * mod ) - > s_name ) ;
2002-06-28 10:27:02 +08:00
smart_str_appendc ( & handlers , ' ' ) ;
}
}
2002-05-10 04:02:47 +08:00
php_info_print_table_start ( ) ;
php_info_print_table_row ( 2 , " Session Support " , " enabled " ) ;
2002-06-28 10:27:02 +08:00
if ( handlers . c ) {
smart_str_0 ( & handlers ) ;
php_info_print_table_row ( 2 , " Registered save handlers " , handlers . c ) ;
smart_str_free ( & handlers ) ;
} else {
php_info_print_table_row ( 2 , " Registered save handlers " , " none " ) ;
}
2002-05-10 04:02:47 +08:00
php_info_print_table_end ( ) ;
2000-04-07 05:07:44 +08:00
2002-05-10 04:02:47 +08:00
DISPLAY_INI_ENTRIES ( ) ;
1999-06-07 03:53:59 +08:00
}
2001-06-06 22:32:27 +08:00
2001-08-25 23:57:42 +08:00
2001-06-06 22:32:27 +08:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* End :
2001-09-09 21:29:31 +08:00
* vim600 : sw = 4 ts = 4 fdm = marker
* vim < 600 : sw = 4 ts = 4
2001-06-06 22:32:27 +08:00
*/