PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.13.3
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.13.3
5.12.0 5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / core / Session / SaveHandler / DbTable.php
matomo / app / core / Session / SaveHandler Last commit date
DbTable.php 4 years ago
DbTable.php
215 lines
1 <?php
2 /**
3 * Matomo - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 *
8 */
9
10 namespace Piwik\Session\SaveHandler;
11
12 use Piwik\Db;
13 use Piwik\DbHelper;
14 use Exception;
15 use Piwik\SettingsPiwik;
16 use Piwik\Updater\Migration;
17 use Zend_Session;
18 use Zend_Session_SaveHandler_Interface;
19
20 /**
21 * Database-backed session save handler
22 *
23 */
24 class DbTable implements Zend_Session_SaveHandler_Interface
25 {
26 public static $wasSessionToLargeToRead = false;
27
28 protected $config;
29 protected $maxLifetime;
30
31 const TABLE_NAME = 'session';
32 const TOKEN_HASH_ALGO = 'sha512';
33
34 /**
35 * @param array $config
36 */
37 public function __construct($config)
38 {
39 $this->config = $config;
40 $this->maxLifetime = ini_get('session.gc_maxlifetime');
41 }
42
43 private function hashSessionId($id)
44 {
45 $salt = SettingsPiwik::getSalt();
46 return hash(self::TOKEN_HASH_ALGO, $id . $salt);
47 }
48
49
50 /**
51 * Destructor
52 *
53 * @return void
54 */
55 public function __destruct()
56 {
57 Zend_Session::writeClose();
58 }
59
60 /**
61 * Open Session - retrieve resources
62 *
63 * @param string $save_path
64 * @param string $name
65 * @return boolean
66 */
67 public function open($save_path, $name)
68 {
69 Db::get()->getConnection();
70
71 return true;
72 }
73
74 /**
75 * Close Session - free resources
76 *
77 * @return boolean
78 */
79 public function close()
80 {
81 return true;
82 }
83
84 /**
85 * Read session data
86 *
87 * @param string $id
88 * @return string
89 */
90 public function read($id)
91 {
92 $id = $this->hashSessionId($id);
93 $sql = 'SELECT ' . $this->config['dataColumn'] . ' FROM ' . $this->config['name']
94 . ' WHERE ' . $this->config['primary'] . ' = ?'
95 . ' AND ' . $this->config['modifiedColumn'] . ' + ' . $this->config['lifetimeColumn'] . ' >= ?';
96
97 $result = $this->fetchOne($sql, array($id, time()));
98
99 if (!$result) {
100 $result = '';
101 }
102
103 return $result;
104 }
105
106 private function fetchOne($sql, $bind)
107 {
108 try {
109 $result = Db::get()->fetchOne($sql, $bind);
110 } catch (Exception $e) {
111 if (Db::get()->isErrNo($e, Migration\Db::ERROR_CODE_TABLE_NOT_EXISTS)) {
112 $this->migrateToDbSessionTable();
113 $result = Db::get()->fetchOne($sql, $bind);
114 } else {
115 throw $e;
116 }
117 }
118 return $result;
119 }
120
121 private function query($sql, $bind)
122 {
123 try {
124 $result = Db::get()->query($sql, $bind);
125 } catch (Exception $e) {
126 if (Db::get()->isErrNo($e, Migration\Db::ERROR_CODE_TABLE_NOT_EXISTS)) {
127 $this->migrateToDbSessionTable();
128 $result = Db::get()->query($sql, $bind);
129 } else {
130 throw $e;
131 }
132 }
133 return $result;
134 }
135
136 /**
137 * Write Session - commit data to resource
138 *
139 * @param string $id
140 * @param mixed $data
141 * @return boolean
142 */
143 public function write($id, $data)
144 {
145 $id = $this->hashSessionId($id);
146
147 $sql = 'INSERT INTO ' . $this->config['name']
148 . ' (' . $this->config['primary'] . ','
149 . $this->config['modifiedColumn'] . ','
150 . $this->config['lifetimeColumn'] . ','
151 . $this->config['dataColumn'] . ')'
152 . ' VALUES (?,?,?,?)'
153 . ' ON DUPLICATE KEY UPDATE '
154 . $this->config['modifiedColumn'] . ' = ?,'
155 . $this->config['lifetimeColumn'] . ' = ?,'
156 . $this->config['dataColumn'] . ' = ?';
157
158 $this->query($sql, array($id, time(), $this->maxLifetime, $data, time(), $this->maxLifetime, $data));
159
160 return true;
161 }
162
163 /**
164 * Destroy Session - remove data from resource for
165 * given session id
166 *
167 * @param string $id
168 * @return boolean
169 */
170 public function destroy($id)
171 {
172 $id = $this->hashSessionId($id);
173
174 $sql = 'DELETE FROM ' . $this->config['name'] . ' WHERE ' . $this->config['primary'] . ' = ?';
175
176 $this->query($sql, array($id));
177
178 return true;
179 }
180
181 /**
182 * Garbage Collection - remove old session data older
183 * than $maxlifetime (in seconds)
184 *
185 * @param int $maxlifetime timestamp in seconds
186 * @return bool always true
187 */
188 public function gc($maxlifetime)
189 {
190 $sql = 'DELETE FROM ' . $this->config['name']
191 . ' WHERE ' . $this->config['modifiedColumn'] . ' + ' . $this->config['lifetimeColumn'] . ' < ?';
192
193 $this->query($sql, array(time()));
194
195 return true;
196 }
197
198 private function migrateToDbSessionTable()
199 {
200 // happens when updating from Piwik 1.4 or earlier to Matomo 3.7+
201 // in this case on update it will change the session handler to dbtable, but it hasn't performed
202 // the DB updates just yet which means the session table won't be available as it was only added in
203 // Piwik 1.5 => results in a sql error the session table does not exist
204 try {
205 $sql = DbHelper::getTableCreateSql(self::TABLE_NAME);
206 Db::query($sql);
207 } catch (Exception $e) {
208 if (!Db::get()->isErrNo($e, Migration\Db::ERROR_CODE_TABLE_EXISTS)) {
209 throw $e;
210 }
211 }
212 }
213
214 }
215