blob: 032199fc14d0b55ef9252a998590481b031cf98b [file] [log] [blame]
Andrey Andreev47a47fb2014-05-31 16:08:30 +03001<?php
2/**
3 * CodeIgniter
4 *
5 * An open source application development framework for PHP 5.2.4 or newer
6 *
7 * NOTICE OF LICENSE
8 *
9 * Licensed under the Open Software License version 3.0
10 *
11 * This source file is subject to the Open Software License (OSL 3.0) that is
12 * bundled with this package in the files license.txt / license.rst. It is
13 * also available through the world wide web at this URL:
14 * http://opensource.org/licenses/OSL-3.0
15 * If you did not receive a copy of the license and are unable to obtain it
16 * through the world wide web, please send an email to
17 * licensing@ellislab.com so we can send you a copy immediately.
18 *
19 * @package CodeIgniter
20 * @author Andrey Andreev
21 * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
22 * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
23 * @link http://codeigniter.com
24 * @since Version 3.0
25 * @filesource
26 */
27defined('BASEPATH') OR exit('No direct script access allowed');
28
29/**
30 * CodeIgniter Session Database Driver
31 *
32 * @package CodeIgniter
33 * @subpackage Libraries
34 * @category Sessions
35 * @author Andrey Andreev
36 * @link http://codeigniter.com/user_guide/libraries/sessions.html
37 */
38class CI_Session_database_driver extends CI_Session_driver implements SessionHandlerInterface {
39
40 /**
41 * DB object
42 *
43 * @var object
44 */
45 protected $_db;
46
47 /**
48 * DB table
49 *
50 * @var string
51 */
52 protected $_table;
53
54 /**
Andrey Andreev47a47fb2014-05-31 16:08:30 +030055 * Row exists flag
56 *
57 * @var bool
58 */
59 protected $_row_exists = FALSE;
60
61 /**
62 * Lock "driver" flag
63 *
64 * @var string
65 */
Andrey Andreev93d9fa72014-08-27 22:14:36 +030066 protected $_lock_driver = 'semaphore';
Andrey Andreev47a47fb2014-05-31 16:08:30 +030067
68 // ------------------------------------------------------------------------
69
70 /**
71 * Class constructor
72 *
73 * @param array $params Configuration parameters
74 * @return void
75 */
76 public function __construct(&$params)
77 {
78 parent::__construct($params);
79
80 $CI =& get_instance();
81 isset($CI->db) OR $CI->load->database();
82 $this->_db =& $CI->db;
83
84 if ( ! $this->_db instanceof CI_DB_query_builder)
85 {
86 throw new Exception('Query Builder not enabled for the configured database. Aborting.');
87 }
88 elseif ($this->_db->pconnect)
89 {
90 throw new Exception('Configured database connection is persistent. Aborting.');
91 }
92
93 $db_driver = $this->_db->dbdriver.(empty($this->_db->subdriver) ? '' : '_'.$this->_db->subdriver);
94 if (strpos($db_driver, 'mysql') !== FALSE)
95 {
Andrey Andreeve1b96652014-06-02 10:09:56 +030096 $this->_lock_driver = 'mysql';
Andrey Andreev47a47fb2014-05-31 16:08:30 +030097 }
98 elseif (in_array($db_driver, array('postgre', 'pdo_pgsql'), TRUE))
99 {
Andrey Andreeve1b96652014-06-02 10:09:56 +0300100 $this->_lock_driver = 'postgre';
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300101 }
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300102
103 isset($this->_table) OR $this->_table = config_item('sess_table_name');
104 }
105
106 // ------------------------------------------------------------------------
107
108 public function open($save_path, $name)
109 {
110 return empty($this->_db->conn_id)
111 ? ( ! $this->_db->autoinit && $this->_db->db_connect())
112 : TRUE;
113 }
114
115 // ------------------------------------------------------------------------
116
117 public function read($session_id)
118 {
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300119 if ($this->_get_lock() !== FALSE)
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300120 {
121 $this->_db
122 ->select('data')
123 ->from($this->_table)
124 ->where('id', $session_id);
125
126 if ($this->_match_ip)
127 {
128 $this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']);
129 }
130
131 if (($result = $this->_db->get()->row()) === NULL)
132 {
133 $this->_fingerprint = md5('');
134 return '';
135 }
136
137 $this->_fingerprint = md5(rtrim($result->data));
138 $this->_row_exists = TRUE;
139 return $result->data;
140 }
141
142 $this->_fingerprint = md5('');
143 return '';
144 }
145
146 public function write($session_id, $session_data)
147 {
148 if ($this->_lock === FALSE)
149 {
150 return FALSE;
151 }
152
153 if ($this->_row_exists === FALSE)
154 {
155 if ($this->_db->insert($this->_table, array('id' => $session_id, 'ip_address' => $_SERVER['REMOTE_ADDR'], 'timestamp' => time(), 'data' => $session_data)))
156 {
157 $this->_fingerprint = md5($session_data);
158 return $this->_row_exists = TRUE;
159 }
160
161 return FALSE;
162 }
163
164 $this->_db->where('id', $session_id);
165 if ($this->_match_ip)
166 {
167 $this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']);
168 }
169
170 $update_data = ($this->_fingerprint === md5($session_data))
171 ? array('timestamp' => time())
172 : array('timestamp' => time(), 'data' => $session_data);
173
174 if ($this->_db->update($this->_table, $update_data))
175 {
176 $this->_fingerprint = md5($session_data);
177 return TRUE;
178 }
179
180 return FALSE;
181 }
182
183 // ------------------------------------------------------------------------
184
185 public function close()
186 {
187 return ($this->_lock)
188 ? $this->_release_lock()
189 : TRUE;
190 }
191
192 // ------------------------------------------------------------------------
193
194 public function destroy($session_id)
195 {
196 if ($this->_lock)
197 {
198 $this->_db->where('id', $session_id);
199 if ($this->_match_ip)
200 {
201 $this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']);
202 }
203
204 return $this->_db->delete($this->_table)
205 ? ($this->close() && $this->_cookie_destroy())
206 : FALSE;
207 }
208
209 return ($this->close() && $this->_cookie_destroy());
210 }
211
212 // ------------------------------------------------------------------------
213
214 public function gc($maxlifetime)
215 {
216 return $this->_db->delete($this->_table, 'timestamp < '.(time() - $maxlifetime));
217 }
218
219 // ------------------------------------------------------------------------
220
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300221 protected function _get_lock($session_id)
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300222 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300223 if ($this->_lock_driver === 'mysql')
224 {
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300225 $arg = $session_id.($this->_match_ip ? '_'.$_SERVER['REMOTE_ADDR'] : '');
226 if ($this->_db->query("SELECT GET_LOCK('".$arg."', 10) AS ci_session_lock")->row()->ci_session_lock)
227 {
228 $this->_lock = $arg;
229 return TRUE;
230 }
231
232 return FALSE;
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300233 }
234 elseif ($this->_lock_driver === 'postgre')
235 {
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300236 $arg = "hashtext('".$session_id."')".($this->_match_ip ? ", hashtext('".$_SERVER['REMOTE_ADDR']."')" : '');
237 if ($this->_db->simple_query('SELECT pg_advisory_lock('.$arg.')'))
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300238 {
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300239 $this->_lock = $arg;
240 return TRUE;
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300241 }
242
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300243 return FALSE;
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300244 }
245
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300246 return parent::_get_lock($session_id);
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300247 }
248
249 // ------------------------------------------------------------------------
250
251 protected function _release_lock()
252 {
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300253 if ( ! $this->_lock)
254 {
255 return TRUE;
256 }
257
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300258 if ($this->_lock_driver === 'mysql')
259 {
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300260 if ($this->_db->query("SELECT RELEASE_LOCK('".$this->_lock."') AS ci_session_lock")->row()->ci_session_lock)
261 {
262 $this->_lock = FALSE;
263 return TRUE;
264 }
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300265
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300266 return FALSE;
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300267 }
268 elseif ($this->_lock_driver === 'postgre')
269 {
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300270 if ($this->_db->simple_query('SELECT pg_advisory_unlock('.$this->_lock.')'))
271 {
272 $this->_lock = FALSE;
273 return TRUE;
274 }
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300275
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300276 return FALSE;
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300277 }
278
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300279 return parent::_release_lock();
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300280 }
281
282}
283
284/* End of file Session_database_driver.php */
285/* Location: ./system/libraries/Session/drivers/Session_database_driver.php */