| <?php |
|
|
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\Session\SaveHandler; |
|
|
| use Piwik\Db; |
| use Piwik\DbHelper; |
| use Exception; |
| use Piwik\SettingsPiwik; |
| use Piwik\Updater\Migration; |
| use Zend_Session; |
|
|
| |
| |
| |
| |
| class DbTable implements \SessionHandlerInterface |
| { |
| public static $wasSessionToLargeToRead = false; |
|
|
| protected $config; |
| protected $maxLifetime; |
|
|
| public const TABLE_NAME = 'session'; |
| public const TOKEN_HASH_ALGO = 'sha512'; |
|
|
| |
| |
| |
| public function __construct($config) |
| { |
| $this->config = $config; |
| $this->maxLifetime = ini_get('session.gc_maxlifetime'); |
| } |
|
|
| private function hashSessionId($id) |
| { |
| $salt = SettingsPiwik::getSalt(); |
| return hash(self::TOKEN_HASH_ALGO, $id . $salt); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| public function __destruct() |
| { |
| Zend_Session::writeClose(); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function open($save_path, $name): bool |
| { |
| Db::get()->getConnection(); |
|
|
| return true; |
| } |
|
|
| |
| |
| |
| public function close(): bool |
| { |
| return true; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| #[\ReturnTypeWillChange] |
| public function read($id) |
| { |
| $id = $this->hashSessionId($id); |
| $sql = 'SELECT ' . $this->config['dataColumn'] . ' FROM `' . $this->config['name'] . '`' |
| . ' WHERE ' . $this->config['primary'] . ' = ?' |
| . ' AND ' . $this->config['modifiedColumn'] . ' + ' . $this->config['lifetimeColumn'] . ' >= ?'; |
|
|
| $result = $this->fetchOne($sql, [$id, time()]); |
|
|
| if (!$result) { |
| $result = ''; |
| } |
|
|
| return $result; |
| } |
|
|
| private function fetchOne($sql, $bind) |
| { |
| try { |
| $result = Db::get()->fetchOne($sql, $bind); |
| } catch (Exception $e) { |
| if (Db::get()->isErrNo($e, Migration\Db::ERROR_CODE_TABLE_NOT_EXISTS)) { |
| $this->migrateToDbSessionTable(); |
| $result = Db::get()->fetchOne($sql, $bind); |
| } else { |
| throw $e; |
| } |
| } |
| return $result; |
| } |
|
|
| private function query($sql, $bind) |
| { |
| try { |
| $result = Db::get()->query($sql, $bind); |
| } catch (Exception $e) { |
| if (Db::get()->isErrNo($e, Migration\Db::ERROR_CODE_TABLE_NOT_EXISTS)) { |
| $this->migrateToDbSessionTable(); |
| $result = Db::get()->query($sql, $bind); |
| } else { |
| throw $e; |
| } |
| } |
| return $result; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function write($id, $data): bool |
| { |
| $id = $this->hashSessionId($id); |
|
|
| $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'] . ' = ?'; |
|
|
| $this->query($sql, [$id, time(), $this->maxLifetime, $data, time(), $this->maxLifetime, $data]); |
|
|
| return true; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function destroy($id): bool |
| { |
| $id = $this->hashSessionId($id); |
|
|
| $sql = 'DELETE FROM `' . $this->config['name'] . '` WHERE ' . $this->config['primary'] . ' = ?'; |
|
|
| $this->query($sql, [$id]); |
|
|
| return true; |
| } |
|
|
| |
| |
| |
| public function destroyAll(): bool |
| { |
| $sql = 'TRUNCATE TABLE `' . $this->config['name'] . '`'; |
|
|
| $this->query($sql, []); |
|
|
| return true; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| #[\ReturnTypeWillChange] |
| public function gc($maxlifetime) |
| { |
| $sql = 'DELETE FROM `' . $this->config['name'] . '`' |
| . ' WHERE ' . $this->config['modifiedColumn'] . ' + ' . $this->config['lifetimeColumn'] . ' < ?'; |
|
|
| $this->query($sql, [time()]); |
|
|
| return true; |
| } |
|
|
| private function migrateToDbSessionTable() |
| { |
| |
| |
| |
| |
| try { |
| $sql = DbHelper::getTableCreateSql(self::TABLE_NAME); |
| Db::query($sql); |
| } catch (Exception $e) { |
| if (!Db::get()->isErrNo($e, Migration\Db::ERROR_CODE_TABLE_EXISTS)) { |
| throw $e; |
| } |
| } |
| } |
| } |
|
|