blob: e3a3c505e6529f6df25fcee83c5020892762e24a [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 /**
Andrey Andreev47a47fb2014-05-31 16:08:30 +030048 * Row exists flag
49 *
50 * @var bool
51 */
52 protected $_row_exists = FALSE;
53
54 /**
55 * Lock "driver" flag
56 *
57 * @var string
58 */
Andrey Andreev93d9fa72014-08-27 22:14:36 +030059 protected $_lock_driver = 'semaphore';
Andrey Andreev47a47fb2014-05-31 16:08:30 +030060
61 // ------------------------------------------------------------------------
62
63 /**
64 * Class constructor
65 *
66 * @param array $params Configuration parameters
67 * @return void
68 */
69 public function __construct(&$params)
70 {
71 parent::__construct($params);
72
73 $CI =& get_instance();
74 isset($CI->db) OR $CI->load->database();
75 $this->_db =& $CI->db;
76
77 if ( ! $this->_db instanceof CI_DB_query_builder)
78 {
79 throw new Exception('Query Builder not enabled for the configured database. Aborting.');
80 }
81 elseif ($this->_db->pconnect)
82 {
83 throw new Exception('Configured database connection is persistent. Aborting.');
84 }
85
86 $db_driver = $this->_db->dbdriver.(empty($this->_db->subdriver) ? '' : '_'.$this->_db->subdriver);
87 if (strpos($db_driver, 'mysql') !== FALSE)
88 {
Andrey Andreeve1b96652014-06-02 10:09:56 +030089 $this->_lock_driver = 'mysql';
Andrey Andreev47a47fb2014-05-31 16:08:30 +030090 }
91 elseif (in_array($db_driver, array('postgre', 'pdo_pgsql'), TRUE))
92 {
Andrey Andreeve1b96652014-06-02 10:09:56 +030093 $this->_lock_driver = 'postgre';
Andrey Andreev47a47fb2014-05-31 16:08:30 +030094 }
Andrey Andreev47a47fb2014-05-31 16:08:30 +030095
Andrey Andreevdfb39be2014-10-06 01:50:14 +030096 isset($this->_config['save_path']) OR $this->_config['save_path'] = config_item('sess_table_name');
Andrey Andreev47a47fb2014-05-31 16:08:30 +030097 }
98
99 // ------------------------------------------------------------------------
100
101 public function open($save_path, $name)
102 {
103 return empty($this->_db->conn_id)
104 ? ( ! $this->_db->autoinit && $this->_db->db_connect())
105 : TRUE;
106 }
107
108 // ------------------------------------------------------------------------
109
110 public function read($session_id)
111 {
Andrey Andreevd069b9b2014-09-16 10:18:16 +0300112 if ($this->_get_lock($session_id) !== FALSE)
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300113 {
114 $this->_db
115 ->select('data')
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300116 ->from($this->_config['save_path'])
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300117 ->where('id', $session_id);
118
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300119 if ($this->_config['match_ip'])
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300120 {
121 $this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']);
122 }
123
124 if (($result = $this->_db->get()->row()) === NULL)
125 {
126 $this->_fingerprint = md5('');
127 return '';
128 }
129
130 $this->_fingerprint = md5(rtrim($result->data));
131 $this->_row_exists = TRUE;
132 return $result->data;
133 }
134
135 $this->_fingerprint = md5('');
136 return '';
137 }
138
139 public function write($session_id, $session_data)
140 {
141 if ($this->_lock === FALSE)
142 {
143 return FALSE;
144 }
145
146 if ($this->_row_exists === FALSE)
147 {
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300148 if ($this->_db->insert($this->_config['save_path'], array('id' => $session_id, 'ip_address' => $_SERVER['REMOTE_ADDR'], 'timestamp' => time(), 'data' => $session_data)))
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300149 {
150 $this->_fingerprint = md5($session_data);
151 return $this->_row_exists = TRUE;
152 }
153
154 return FALSE;
155 }
156
157 $this->_db->where('id', $session_id);
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300158 if ($this->_config['match_ip'])
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300159 {
160 $this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']);
161 }
162
163 $update_data = ($this->_fingerprint === md5($session_data))
164 ? array('timestamp' => time())
165 : array('timestamp' => time(), 'data' => $session_data);
166
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300167 if ($this->_db->update($this->_config['save_path'], $update_data))
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300168 {
169 $this->_fingerprint = md5($session_data);
170 return TRUE;
171 }
172
173 return FALSE;
174 }
175
176 // ------------------------------------------------------------------------
177
178 public function close()
179 {
180 return ($this->_lock)
181 ? $this->_release_lock()
182 : TRUE;
183 }
184
185 // ------------------------------------------------------------------------
186
187 public function destroy($session_id)
188 {
189 if ($this->_lock)
190 {
191 $this->_db->where('id', $session_id);
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300192 if ($this->_config['match_ip'])
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300193 {
194 $this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']);
195 }
196
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300197 return $this->_db->delete($this->_config['save_path'])
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300198 ? ($this->close() && $this->_cookie_destroy())
199 : FALSE;
200 }
201
202 return ($this->close() && $this->_cookie_destroy());
203 }
204
205 // ------------------------------------------------------------------------
206
207 public function gc($maxlifetime)
208 {
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300209 return $this->_db->delete($this->_config['save_path'], 'timestamp < '.(time() - $maxlifetime));
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300210 }
211
212 // ------------------------------------------------------------------------
213
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300214 protected function _get_lock($session_id)
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300215 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300216 if ($this->_lock_driver === 'mysql')
217 {
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300218 $arg = $session_id.($this->_config['match_ip'] ? '_'.$_SERVER['REMOTE_ADDR'] : '');
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300219 if ($this->_db->query("SELECT GET_LOCK('".$arg."', 10) AS ci_session_lock")->row()->ci_session_lock)
220 {
221 $this->_lock = $arg;
222 return TRUE;
223 }
224
225 return FALSE;
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300226 }
227 elseif ($this->_lock_driver === 'postgre')
228 {
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300229 $arg = "hashtext('".$session_id."')".($this->_config['match_ip'] ? ", hashtext('".$_SERVER['REMOTE_ADDR']."')" : '');
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300230 if ($this->_db->simple_query('SELECT pg_advisory_lock('.$arg.')'))
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300231 {
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300232 $this->_lock = $arg;
233 return TRUE;
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300234 }
235
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300236 return FALSE;
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300237 }
238
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300239 return parent::_get_lock($session_id);
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300240 }
241
242 // ------------------------------------------------------------------------
243
244 protected function _release_lock()
245 {
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300246 if ( ! $this->_lock)
247 {
248 return TRUE;
249 }
250
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300251 if ($this->_lock_driver === 'mysql')
252 {
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300253 if ($this->_db->query("SELECT RELEASE_LOCK('".$this->_lock."') AS ci_session_lock")->row()->ci_session_lock)
254 {
255 $this->_lock = FALSE;
256 return TRUE;
257 }
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300258
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300259 return FALSE;
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300260 }
261 elseif ($this->_lock_driver === 'postgre')
262 {
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300263 if ($this->_db->simple_query('SELECT pg_advisory_unlock('.$this->_lock.')'))
264 {
265 $this->_lock = FALSE;
266 return TRUE;
267 }
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300268
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300269 return FALSE;
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300270 }
271
Andrey Andreev93d9fa72014-08-27 22:14:36 +0300272 return parent::_release_lock();
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300273 }
274
275}
276
277/* End of file Session_database_driver.php */
278/* Location: ./system/libraries/Session/drivers/Session_database_driver.php */