PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.8.2
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.8.2
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 3 months ago
DbTable.php
179 lines
1 <?php
2
3 /**
4 * Matomo - free/libre analytics platform
5 *
6 * @link https://matomo.org
7 * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
8 */
9 namespace Piwik\Session\SaveHandler;
10
11 use Piwik\Db;
12 use Piwik\DbHelper;
13 use Exception;
14 use Piwik\SettingsPiwik;
15 use Piwik\Updater\Migration;
16 use Zend_Session;
17 /**
18 * Database-backed session save handler
19 *
20 */
21 class DbTable implements \SessionHandlerInterface
22 {
23 public static $wasSessionToLargeToRead = \false;
24 protected $config;
25 protected $maxLifetime;
26 public const TABLE_NAME = 'session';
27 public const TOKEN_HASH_ALGO = 'sha512';
28 /**
29 * @param array $config
30 */
31 public function __construct($config)
32 {
33 $this->config = $config;
34 $this->maxLifetime = ini_get('session.gc_maxlifetime');
35 }
36 private function hashSessionId($id)
37 {
38 $salt = SettingsPiwik::getSalt();
39 return hash(self::TOKEN_HASH_ALGO, $id . $salt);
40 }
41 /**
42 * Destructor
43 *
44 * @return void
45 */
46 public function __destruct()
47 {
48 Zend_Session::writeClose();
49 }
50 /**
51 * Open Session - retrieve resources
52 *
53 * @param string $save_path
54 * @param string $name
55 */
56 public function open($save_path, $name) : bool
57 {
58 Db::get()->getConnection();
59 return \true;
60 }
61 /**
62 * Close Session - free resources
63 *
64 */
65 public function close() : bool
66 {
67 return \true;
68 }
69 /**
70 * Read session data
71 *
72 * @param string $id
73 * @return string
74 */
75 #[\ReturnTypeWillChange]
76 public function read($id)
77 {
78 $id = $this->hashSessionId($id);
79 $sql = 'SELECT ' . $this->config['dataColumn'] . ' FROM `' . $this->config['name'] . '`' . ' WHERE ' . $this->config['primary'] . ' = ?' . ' AND ' . $this->config['modifiedColumn'] . ' + ' . $this->config['lifetimeColumn'] . ' >= ?';
80 $result = $this->fetchOne($sql, [$id, time()]);
81 if (!$result) {
82 $result = '';
83 }
84 return $result;
85 }
86 private function fetchOne($sql, $bind)
87 {
88 try {
89 $result = Db::get()->fetchOne($sql, $bind);
90 } catch (Exception $e) {
91 if (Db::get()->isErrNo($e, Migration\Db::ERROR_CODE_TABLE_NOT_EXISTS)) {
92 $this->migrateToDbSessionTable();
93 $result = Db::get()->fetchOne($sql, $bind);
94 } else {
95 throw $e;
96 }
97 }
98 return $result;
99 }
100 private function query($sql, $bind)
101 {
102 try {
103 $result = Db::get()->query($sql, $bind);
104 } catch (Exception $e) {
105 if (Db::get()->isErrNo($e, Migration\Db::ERROR_CODE_TABLE_NOT_EXISTS)) {
106 $this->migrateToDbSessionTable();
107 $result = Db::get()->query($sql, $bind);
108 } else {
109 throw $e;
110 }
111 }
112 return $result;
113 }
114 /**
115 * Write Session - commit data to resource
116 *
117 * @param string $id
118 * @param mixed $data
119 */
120 public function write($id, $data) : bool
121 {
122 $id = $this->hashSessionId($id);
123 $sql = 'INSERT INTO ' . $this->config['name'] . ' (' . $this->config['primary'] . ',' . $this->config['modifiedColumn'] . ',' . $this->config['lifetimeColumn'] . ',' . $this->config['dataColumn'] . ')' . ' VALUES (?,?,?,?)' . ' ON DUPLICATE KEY UPDATE ' . $this->config['modifiedColumn'] . ' = ?,' . $this->config['lifetimeColumn'] . ' = ?,' . $this->config['dataColumn'] . ' = ?';
124 $this->query($sql, [$id, time(), $this->maxLifetime, $data, time(), $this->maxLifetime, $data]);
125 return \true;
126 }
127 /**
128 * Destroy Session - remove data from resource for
129 * given session id
130 *
131 * @param string $id
132 */
133 public function destroy($id) : bool
134 {
135 $id = $this->hashSessionId($id);
136 $sql = 'DELETE FROM `' . $this->config['name'] . '` WHERE ' . $this->config['primary'] . ' = ?';
137 $this->query($sql, [$id]);
138 return \true;
139 }
140 /**
141 * Destroys all Sessions - removes all rows in Session table
142 */
143 public function destroyAll() : bool
144 {
145 $sql = 'TRUNCATE TABLE `' . $this->config['name'] . '`';
146 $this->query($sql, []);
147 return \true;
148 }
149 /**
150 * Garbage Collection - remove old session data older
151 * than $maxlifetime (in seconds)
152 *
153 * @param int $maxlifetime timestamp in seconds
154 * @return bool always true
155 */
156 #[\ReturnTypeWillChange]
157 public function gc($maxlifetime)
158 {
159 $sql = 'DELETE FROM `' . $this->config['name'] . '`' . ' WHERE ' . $this->config['modifiedColumn'] . ' + ' . $this->config['lifetimeColumn'] . ' < ?';
160 $this->query($sql, [time()]);
161 return \true;
162 }
163 private function migrateToDbSessionTable()
164 {
165 // happens when updating from Piwik 1.4 or earlier to Matomo 3.7+
166 // in this case on update it will change the session handler to dbtable, but it hasn't performed
167 // the DB updates just yet which means the session table won't be available as it was only added in
168 // Piwik 1.5 => results in a sql error the session table does not exist
169 try {
170 $sql = DbHelper::getTableCreateSql(self::TABLE_NAME);
171 Db::query($sql);
172 } catch (Exception $e) {
173 if (!Db::get()->isErrNo($e, Migration\Db::ERROR_CODE_TABLE_EXISTS)) {
174 throw $e;
175 }
176 }
177 }
178 }
179