📄 session.c
字号:
/* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | 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. | +----------------------------------------------------------------------+ | Authors: Sascha Schumann <sascha@schumann.cx> | | Andrei Zmievski <andrei@php.net> | +----------------------------------------------------------------------+ *//* $Id: session.c,v 1.336.2.53.2.17 2007/04/04 19:52:26 tony2001 Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "php.h"#ifdef PHP_WIN32#include "win32/time.h"#else#include <sys/time.h>#endif#include <sys/stat.h>#include <fcntl.h>#include "php_ini.h"#include "SAPI.h"#include "php_session.h"#include "ext/standard/md5.h"#include "ext/standard/php_var.h"#include "ext/standard/datetime.h"#include "ext/standard/php_lcg.h"#include "ext/standard/url_scanner_ex.h"#include "ext/standard/php_rand.h" /* for RAND_MAX */#include "ext/standard/info.h"#include "ext/standard/php_smart_str.h"#include "mod_files.h"#include "mod_user.h"#ifdef HAVE_LIBMM#include "mod_mm.h"#endif/* {{{ session_functions[] */function_entry session_functions[] = { PHP_FE(session_name, NULL) PHP_FE(session_module_name, NULL) PHP_FE(session_save_path, NULL) PHP_FE(session_id, NULL) PHP_FE(session_regenerate_id, NULL) 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) PHP_FE(session_set_cookie_params, NULL) PHP_FE(session_get_cookie_params, NULL) PHP_FE(session_write_close, NULL) PHP_FALIAS(session_commit, session_write_close, NULL) {NULL, NULL, NULL} };/* }}} */PHPAPI ZEND_DECLARE_MODULE_GLOBALS(ps);static ps_module *_php_find_ps_module(char *name TSRMLS_DC);static const ps_serializer *_php_find_ps_serializer(char *name TSRMLS_DC);#define SESSION_CHECK_ACTIVE_STATE \ if (PS(session_status) == php_session_active) { \ php_error_docref(NULL TSRMLS_CC, E_WARNING, "A session is active. You cannot change the session module's ini settings at this time."); \ return FAILURE; \ }static PHP_INI_MH(OnUpdateSaveHandler){ SESSION_CHECK_ACTIVE_STATE; PS(mod) = _php_find_ps_module(new_value TSRMLS_CC); if (PG(modules_activated) && !PS(mod)) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "Cannot find save handler %s", new_value); } return SUCCESS;}static PHP_INI_MH(OnUpdateSerializer){ SESSION_CHECK_ACTIVE_STATE; PS(serializer) = _php_find_ps_serializer(new_value TSRMLS_CC); if (PG(modules_activated) && !PS(serializer)) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "Cannot find serialization handler %s", new_value); } return SUCCESS;}static PHP_INI_MH(OnUpdateSaveDir) { /* Only do the safemode/open_basedir check at runtime */ if(stage == PHP_INI_STAGE_RUNTIME) { if (memchr(new_value, '\0', new_value_length) != NULL) { return FAILURE; } if (PG(safe_mode) && (!php_checkuid(new_value, NULL, CHECKUID_ALLOW_ONLY_DIR))) { return FAILURE; } if (php_check_open_basedir(new_value TSRMLS_CC)) { return FAILURE; } } OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); return SUCCESS;}/* {{{ PHP_INI */PHP_INI_BEGIN() 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)#ifdef PHP_WIN32 STD_PHP_INI_ENTRY("session.save_path", "", PHP_INI_ALL, OnUpdateSaveDir,save_path, php_ps_globals, ps_globals)#else STD_PHP_INI_ENTRY("session.save_path", "/tmp", PHP_INI_ALL, OnUpdateSaveDir,save_path, php_ps_globals, ps_globals)#endif 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) STD_PHP_INI_ENTRY("session.gc_divisor", "100", PHP_INI_ALL, OnUpdateInt, gc_divisor, php_ps_globals, ps_globals) 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) STD_PHP_INI_BOOLEAN("session.use_trans_sid", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, use_trans_sid, php_ps_globals, ps_globals) /* Commented out until future discussion */ /* PHP_INI_ENTRY("session.encode_sources", "globals,track", PHP_INI_ALL, NULL) */PHP_INI_END()/* }}} */PS_SERIALIZER_FUNCS(php);PS_SERIALIZER_FUNCS(php_binary);#define MAX_SERIALIZERS 10static ps_serializer ps_serializers[MAX_SERIALIZERS + 1] = { PS_SERIALIZER_ENTRY(php), PS_SERIALIZER_ENTRY(php_binary)};#define MAX_MODULES 10#define PREDEFINED_MODULES 2static ps_module *ps_modules[MAX_MODULES + 1] = { ps_files_ptr, ps_user_ptr};#define IF_SESSION_VARS() \ if (PS(http_session_vars) && PS(http_session_vars)->type == IS_ARRAY)PHPAPI int php_session_register_serializer(const char *name, int (*encode)(PS_SERIALIZER_ENCODE_ARGS), int (*decode)(PS_SERIALIZER_DECODE_ARGS)){ 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;}PHPAPI int php_session_register_module(ps_module *ptr){ 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;}PHP_MINIT_FUNCTION(session);PHP_RINIT_FUNCTION(session);PHP_MSHUTDOWN_FUNCTION(session);PHP_RSHUTDOWN_FUNCTION(session);PHP_MINFO_FUNCTION(session);static void php_rinit_session_globals(TSRMLS_D);static void php_rshutdown_session_globals(TSRMLS_D);static zend_bool php_session_destroy(TSRMLS_D);zend_module_entry session_module_entry = { STANDARD_MODULE_HEADER, "session", session_functions, PHP_MINIT(session), PHP_MSHUTDOWN(session), PHP_RINIT(session), PHP_RSHUTDOWN(session), PHP_MINFO(session), NO_VERSION_YET, STANDARD_MODULE_PROPERTIES};#ifdef COMPILE_DL_SESSIONZEND_GET_MODULE(session)#endiftypedef struct { char *name; void (*func)(TSRMLS_D);} php_session_cache_limiter_t;#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) },#define ADD_HEADER(a) sapi_add_header(a, strlen(a), 1);#define MAX_STR 512void php_add_session_var(char *name, size_t namelen TSRMLS_DC){ zval **sym_track = NULL; IF_SESSION_VARS() { zend_hash_find(Z_ARRVAL_P(PS(http_session_vars)), name, namelen + 1, (void *) &sym_track); } else { return; } /* * Set up a proper reference between $_SESSION["x"] and $x. */ if (PG(register_globals)) { zval **sym_global = NULL; if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void *) &sym_global) == SUCCESS) { if ((Z_TYPE_PP(sym_global) == IS_ARRAY && Z_ARRVAL_PP(sym_global) == &EG(symbol_table)) || *sym_global == PS(http_session_vars)) { return; } } if (sym_global == NULL && sym_track == NULL) { zval *empty_var; 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 */ 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) { SEPARATE_ZVAL_IF_NOT_REF(sym_track); zend_set_hash_symbol(*sym_track, name, namelen, 1, 1, &EG(symbol_table)); } else if (sym_track == NULL) { SEPARATE_ZVAL_IF_NOT_REF(sym_global); 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); ZEND_SET_SYMBOL_WITH_LENGTH(Z_ARRVAL_P(PS(http_session_vars)), name, namelen+1, empty_var, 1, 0); } }}void php_set_session_var(char *name, size_t namelen, zval *state_val, php_unserialize_data_t *var_hash TSRMLS_DC){ if (PG(register_globals)) { zval **old_symbol; if (zend_hash_find(&EG(symbol_table),name,namelen+1,(void *)&old_symbol) == SUCCESS) { if ((Z_TYPE_PP(old_symbol) == IS_ARRAY && Z_ARRVAL_PP(old_symbol) == &EG(symbol_table)) || *old_symbol == PS(http_session_vars)) { return; } /* * A global symbol with the same name exists already. That * symbol might have been created by other means (e.g. $_GET). * * 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 update the reference table used for * unserialization. It is optional, because some storage * formats may not be able to represent references. */ if (var_hash) { 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)); } } else IF_SESSION_VARS() { zend_set_hash_symbol(state_val, name, namelen, PZVAL_IS_REF(state_val), 1, Z_ARRVAL_P(PS(http_session_vars))); }}int php_get_session_var(char *name, size_t namelen, zval ***state_var TSRMLS_DC){ int ret = FAILURE; IF_SESSION_VARS() { ret = zend_hash_find(Z_ARRVAL_P(PS(http_session_vars)), name, namelen+1, (void **) state_var); /* * 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; } } } return ret;}#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){ 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); return SUCCESS;}PS_SERIALIZER_DECODE_FUNC(php_binary){ 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; ) { zval **tmp; namelen = *p & (~PS_BIN_UNDEF); if (namelen > PS_BIN_MAX || (p + namelen) >= endptr) { return FAILURE; } has_value = *p & PS_BIN_UNDEF ? 0 : 1; name = estrndup(p + 1, namelen); p += namelen + 1; if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void **) &tmp) == SUCCESS) { if ((Z_TYPE_PP(tmp) == IS_ARRAY && Z_ARRVAL_PP(tmp) == &EG(symbol_table)) || *tmp == PS(http_session_vars)) { efree(name); continue; } } if (has_value) { ALLOC_INIT_ZVAL(current); if (php_var_unserialize(¤t, (const unsigned char **)&p, endptr, &var_hash TSRMLS_CC)) { php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC); } zval_ptr_dtor(¤t);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -