Instantly share code, notes, and snippets.
Created
July 15, 2009 14:07
-
Save hiroy/147730 to your computer and use it in GitHub Desktop.
a cookie-stored session class.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Cookie-Stored session class. | |
*/ | |
class cookie_stored_session | |
{ | |
const cookie_max_length = 4096; | |
protected $_secret_key; | |
protected $_vars = array(); | |
protected $_available = false; | |
protected $_cookie_name; | |
protected $_cookie_params; | |
public function __construct($secret_key) | |
{ | |
$this->_secret_key = $secret_key; | |
$this->_available = true; | |
// use session settings | |
$this->_cookie_name = session_name(); | |
$this->_cookie_params = session_get_cookie_params(); | |
$this->_restore(); | |
} | |
public function __destruct() | |
{ | |
if ($this->_available) { | |
$this->_save(); | |
} | |
} | |
public function __set($name, $value) | |
{ | |
$this->_vars[$name] = $value; | |
} | |
public function __get($name) | |
{ | |
if (isset($this->_vars[$name])) { | |
return $this->_vars[$name]; | |
} | |
return null; | |
} | |
public function __isset($name) | |
{ | |
return isset($this->_vars[$name]); | |
} | |
public function __unset($name) | |
{ | |
if (isset($this->_vars[$name])) { | |
unset($this->_vars[$name]); | |
} | |
} | |
public function lifetime($seconds) | |
{ | |
$this->_cookie_params['lifetime'] = $seconds; | |
} | |
public function destroy() | |
{ | |
$this->_available = false; | |
$this->_vars = array(); | |
$this->_cookie('', time() - 3600); | |
} | |
protected function _restore() | |
{ | |
if (!isset($_COOKIE[$this->_cookie_name])) { | |
// cookie not exists | |
return; | |
} | |
$cookie_data = $_COOKIE[$this->_cookie_name]; | |
$data_list = explode('--', $cookie_data); | |
if (count($data_list) !== 2) { | |
// invalid cookie value | |
$this->destroy(); | |
return; | |
} | |
$vars = @unserialize(base64_decode($data_list[0])); | |
if ($vars === false || !is_array($vars)) { | |
// broken cookie value | |
$this->destroy(); | |
return; | |
} | |
if ($this->_digest($vars) !== $data_list[1]) { | |
// tampered | |
$this->destroy(); | |
return; | |
} | |
$this->_vars = $vars; | |
} | |
protected function _save() | |
{ | |
$expire = time() + $this->_cookie_params['lifetime']; | |
$digest = $this->_digest($this->_vars); | |
$cookie_data = base64_encode(serialize($this->_vars)) . '--' . $digest; | |
if (strlen($cookie_data) > self::cookie_max_length) { | |
throw new Exception('session data is too large'); | |
} | |
$this->_cookie($cookie_data, $expire); | |
} | |
protected function _digest($data) | |
{ | |
$serialized_data = serialize($data); | |
return hash_hmac('sha1', $serialized_data, $this->_secret_key); | |
} | |
protected function _cookie($value, $expire) | |
{ | |
$name = $this->_cookie_name; | |
$params = $this->_cookie_params; | |
if (empty($params['domain']) && empty($params['secure'])) { | |
setcookie($name, $value, $expire, $params['path']); | |
} else if (empty($params['secure'])) { | |
setcookie($name, $value, $expire, | |
$params['path'], $params['domain']); | |
} else { | |
setcookie($name, $value, $expire, | |
$params['path'], $params['domain'], $params['secure']); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment