· 7 years ago · Mar 09, 2018, 09:20 PM
1<?php
2/**
3 * Cookie-Stored session class.
4 */
5class cookie_stored_session
6{
7 const cookie_max_length = 4096;
8 protected $_secret_key;
9 protected $_vars = array();
10 protected $_available = false;
11 protected $_cookie_name;
12 protected $_cookie_params;
13
14 public function __construct($secret_key)
15 {
16 $this->_secret_key = $secret_key;
17 $this->_available = true;
18 // use session settings
19 $this->_cookie_name = session_name();
20 $this->_cookie_params = session_get_cookie_params();
21 $this->_restore();
22 }
23
24 public function __destruct()
25 {
26 if ($this->_available) {
27 $this->_save();
28 }
29 }
30
31 public function __set($name, $value)
32 {
33 $this->_vars[$name] = $value;
34 }
35
36 public function __get($name)
37 {
38 if (isset($this->_vars[$name])) {
39 return $this->_vars[$name];
40 }
41 return null;
42 }
43
44 public function __isset($name)
45 {
46 return isset($this->_vars[$name]);
47 }
48
49 public function __unset($name)
50 {
51 if (isset($this->_vars[$name])) {
52 unset($this->_vars[$name]);
53 }
54 }
55
56 public function lifetime($seconds)
57 {
58 $this->_cookie_params['lifetime'] = $seconds;
59 }
60
61 public function destroy()
62 {
63 $this->_available = false;
64 $this->_vars = array();
65 $this->_cookie('', time() - 3600);
66 }
67
68 protected function _restore()
69 {
70 if (!isset($_COOKIE[$this->_cookie_name])) {
71 // cookie not exists
72 return;
73 }
74 $cookie_data = $_COOKIE[$this->_cookie_name];
75 $data_list = explode('--', $cookie_data);
76 if (count($data_list) !== 2) {
77 // invalid cookie value
78 $this->destroy();
79 return;
80 }
81 $vars = @unserialize(base64_decode($data_list[0]));
82 if ($vars === false || !is_array($vars)) {
83 // broken cookie value
84 $this->destroy();
85 return;
86 }
87 if ($this->_digest($vars) !== $data_list[1]) {
88 // tampered
89 $this->destroy();
90 return;
91 }
92 $this->_vars = $vars;
93 }
94
95 protected function _save()
96 {
97 $expire = time() + $this->_cookie_params['lifetime'];
98 $digest = $this->_digest($this->_vars);
99 $cookie_data = base64_encode(serialize($this->_vars)) . '--' . $digest;
100
101 if (strlen($cookie_data) > self::cookie_max_length) {
102 throw new Exception('session data is too large');
103 }
104
105 $this->_cookie($cookie_data, $expire);
106 }
107
108 protected function _digest($data)
109 {
110 $serialized_data = serialize($data);
111 return hash_hmac('sha1', $serialized_data, $this->_secret_key);
112 }
113
114 protected function _cookie($value, $expire)
115 {
116 $name = $this->_cookie_name;
117 $params = $this->_cookie_params;
118
119 if (empty($params['domain']) && empty($params['secure'])) {
120 setcookie($name, $value, $expire, $params['path']);
121 } else if (empty($params['secure'])) {
122 setcookie($name, $value, $expire,
123 $params['path'], $params['domain']);
124 } else {
125 setcookie($name, $value, $expire,
126 $params['path'], $params['domain'], $params['secure']);
127 }
128 }
129}