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