0
|
1 <?php
|
|
2
|
|
3 /**
|
|
4 +-----------------------------------------------------------------------+
|
|
5 | This file is part of the Roundcube Webmail client |
|
|
6 | Copyright (C) 2005-2014, The Roundcube Dev Team |
|
|
7 | Copyright (C) 2011, Kolab Systems AG |
|
|
8 | |
|
|
9 | Licensed under the GNU General Public License version 3 or |
|
|
10 | any later version with exceptions for skins & plugins. |
|
|
11 | See the README file for a full license statement. |
|
|
12 | |
|
|
13 | PURPOSE: |
|
|
14 | Provide database supported session management |
|
|
15 +-----------------------------------------------------------------------+
|
|
16 | Author: Thomas Bruederli <roundcube@gmail.com> |
|
|
17 | Author: Aleksander Machniak <alec@alec.pl> |
|
|
18 | Author: Cor Bosman <cor@roundcu.be> |
|
|
19 +-----------------------------------------------------------------------+
|
|
20 */
|
|
21
|
|
22 /**
|
|
23 * Class to provide database session storage
|
|
24 *
|
|
25 * @package Framework
|
|
26 * @subpackage Core
|
|
27 * @author Thomas Bruederli <roundcube@gmail.com>
|
|
28 * @author Aleksander Machniak <alec@alec.pl>
|
|
29 * @author Cor Bosman <cor@roundcu.be>
|
|
30 */
|
|
31 class rcube_session_db extends rcube_session
|
|
32 {
|
|
33 private $db;
|
|
34 private $table_name;
|
|
35
|
|
36 /**
|
|
37 * @param Object $config
|
|
38 */
|
|
39 public function __construct($config)
|
|
40 {
|
|
41 parent::__construct($config);
|
|
42
|
|
43 // get db instance
|
|
44 $this->db = rcube::get_instance()->get_dbh();
|
|
45
|
|
46 // session table name
|
|
47 $this->table_name = $this->db->table_name('session', true);
|
|
48
|
|
49 // register sessions handler
|
|
50 $this->register_session_handler();
|
|
51
|
|
52 // register db gc handler
|
|
53 $this->register_gc_handler(array($this, 'gc_db'));
|
|
54 }
|
|
55
|
|
56 /**
|
|
57 * @param $save_path
|
|
58 * @param $session_name
|
|
59 * @return bool
|
|
60 */
|
|
61 public function open($save_path, $session_name)
|
|
62 {
|
|
63 return true;
|
|
64 }
|
|
65
|
|
66 /**
|
|
67 * @return bool
|
|
68 */
|
|
69 public function close()
|
|
70 {
|
|
71 return true;
|
|
72 }
|
|
73
|
|
74 /**
|
|
75 * Handler for session_destroy()
|
|
76 *
|
|
77 * @param $key
|
|
78 * @return bool
|
|
79 */
|
|
80 public function destroy($key)
|
|
81 {
|
|
82 if ($key) {
|
|
83 $this->db->query("DELETE FROM {$this->table_name} WHERE `sess_id` = ?", $key);
|
|
84 }
|
|
85
|
|
86 return true;
|
|
87 }
|
|
88
|
|
89 /**
|
|
90 * Read session data from database
|
|
91 *
|
|
92 * @param string Session ID
|
|
93 *
|
|
94 * @return string Session vars
|
|
95 */
|
|
96 public function read($key)
|
|
97 {
|
|
98 $sql_result = $this->db->query(
|
|
99 "SELECT `vars`, `ip`, `changed`, " . $this->db->now() . " AS ts"
|
|
100 . " FROM {$this->table_name} WHERE `sess_id` = ?", $key);
|
|
101
|
|
102 if ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) {
|
|
103 $this->time_diff = time() - strtotime($sql_arr['ts']);
|
|
104 $this->changed = strtotime($sql_arr['changed']);
|
|
105 $this->ip = $sql_arr['ip'];
|
|
106 $this->vars = base64_decode($sql_arr['vars']);
|
|
107 $this->key = $key;
|
|
108
|
|
109 $this->db->reset();
|
|
110
|
|
111 return !empty($this->vars) ? (string) $this->vars : '';
|
|
112 }
|
|
113
|
|
114 return '';
|
|
115 }
|
|
116
|
|
117 /**
|
|
118 * insert new data into db session store
|
|
119 *
|
|
120 * @param $key
|
|
121 * @param $vars
|
|
122 * @return bool
|
|
123 */
|
|
124 public function write($key, $vars)
|
|
125 {
|
|
126 $now = $this->db->now();
|
|
127
|
|
128 $this->db->query("INSERT INTO {$this->table_name}"
|
|
129 . " (`sess_id`, `vars`, `ip`, `changed`)"
|
|
130 . " VALUES (?, ?, ?, $now)",
|
|
131 $key, base64_encode($vars), (string)$this->ip);
|
|
132
|
|
133 return true;
|
|
134 }
|
|
135
|
|
136 /**
|
|
137 * update session data
|
|
138 *
|
|
139 * @param $key
|
|
140 * @param $newvars
|
|
141 * @param $oldvars
|
|
142 *
|
|
143 * @return bool
|
|
144 */
|
|
145 public function update($key, $newvars, $oldvars)
|
|
146 {
|
|
147 $now = $this->db->now();
|
|
148 $ts = microtime(true);
|
|
149
|
|
150 // if new and old data are not the same, update data
|
|
151 // else update expire timestamp only when certain conditions are met
|
|
152 if ($newvars !== $oldvars) {
|
|
153 $this->db->query("UPDATE {$this->table_name} "
|
|
154 . "SET `changed` = $now, `vars` = ? WHERE `sess_id` = ?",
|
|
155 base64_encode($newvars), $key);
|
|
156 }
|
|
157 else if ($ts - $this->changed + $this->time_diff > $this->lifetime / 2) {
|
|
158 $this->db->query("UPDATE {$this->table_name} SET `changed` = $now"
|
|
159 . " WHERE `sess_id` = ?", $key);
|
|
160 }
|
|
161
|
|
162 return true;
|
|
163 }
|
|
164
|
|
165 /**
|
|
166 * Clean up db sessions.
|
|
167 */
|
|
168 public function gc_db()
|
|
169 {
|
|
170 // just clean all old sessions when this GC is called
|
|
171 $this->db->query("DELETE FROM " . $this->db->table_name('session')
|
|
172 . " WHERE changed < " . $this->db->now(-$this->gc_enabled));
|
|
173
|
|
174 $this->log("Session GC (DB): remove records < "
|
|
175 . date('Y-m-d H:i:s', time() - $this->gc_enabled)
|
|
176 . '; rows = ' . intval($this->db->affected_rows()));
|
|
177 }
|
|
178 }
|