GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — develop ( 7d455c...f6fa23 )
by Lonnie
07:56
created

CI_Session_memcached_driver::_get_lock()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 40
Code Lines 22

Duplication

Lines 18
Ratio 45 %
Metric Value
dl 18
loc 40
rs 6.7273
cc 7
eloc 22
nc 7
nop 1
1
<?php
2
/**
3
 * CodeIgniter
4
 *
5
 * An open source application development framework for PHP
6
 *
7
 * This content is released under the MIT License (MIT)
8
 *
9
 * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a copy
12
 * of this software and associated documentation files (the "Software"), to deal
13
 * in the Software without restriction, including without limitation the rights
14
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
 * copies of the Software, and to permit persons to whom the Software is
16
 * furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies or substantial portions of the Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
 * THE SOFTWARE.
28
 *
29
 * @package	CodeIgniter
30
 * @author	EllisLab Dev Team
31
 * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
32
 * @copyright	Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
33
 * @license	http://opensource.org/licenses/MIT	MIT License
34
 * @link	http://codeigniter.com
35
 * @since	Version 3.0.0
36
 * @filesource
37
 */
38
defined('BASEPATH') OR exit('No direct script access allowed');
39
40
/**
41
 * CodeIgniter Session Memcached Driver
42
 *
43
 * @package	CodeIgniter
44
 * @subpackage	Libraries
45
 * @category	Sessions
46
 * @author	Andrey Andreev
47
 * @link	http://codeigniter.com/user_guide/libraries/sessions.html
48
 */
49
class CI_Session_memcached_driver extends CI_Session_driver implements SessionHandlerInterface {
50
51
	/**
52
	 * Memcached instance
53
	 *
54
	 * @var	Memcached
55
	 */
56
	protected $_memcached;
57
58
	/**
59
	 * Key prefix
60
	 *
61
	 * @var	string
62
	 */
63
	protected $_key_prefix = 'ci_session:';
64
65
	/**
66
	 * Lock key
67
	 *
68
	 * @var	string
69
	 */
70
	protected $_lock_key;
71
72
	// ------------------------------------------------------------------------
73
74
	/**
75
	 * Class constructor
76
	 *
77
	 * @param	array	$params	Configuration parameters
78
	 * @return	void
79
	 */
80
	public function __construct(&$params)
81
	{
82
		parent::__construct($params);
83
84
		if (empty($this->_config['save_path']))
85
		{
86
			log_message('error', 'Session: No Memcached save path configured.');
87
		}
88
89 View Code Duplication
		if ($this->_config['match_ip'] === TRUE)
90
		{
91
			$this->_key_prefix .= $_SERVER['REMOTE_ADDR'].':';
92
		}
93
	}
94
95
	// ------------------------------------------------------------------------
96
97
	/**
98
	 * Open
99
	 *
100
	 * Sanitizes save_path and initializes connections.
101
	 *
102
	 * @param	string	$save_path	Server path(s)
103
	 * @param	string	$name		Session cookie name, unused
104
	 * @return	bool
105
	 */
106
	public function open($save_path, $name)
107
	{
108
		$this->_memcached = new Memcached();
109
		$this->_memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, TRUE); // required for touch() usage
110
		$server_list = array();
111
		foreach ($this->_memcached->getServerList() as $server)
112
		{
113
			$server_list[] = $server['host'].':'.$server['port'];
114
		}
115
116
		if ( ! preg_match_all('#,?([^,:]+)\:(\d{1,5})(?:\:(\d+))?#', $this->_config['save_path'], $matches, PREG_SET_ORDER))
117
		{
118
			$this->_memcached = NULL;
119
			log_message('error', 'Session: Invalid Memcached save path format: '.$this->_config['save_path']);
120
			return $this->_failure;
121
		}
122
123
		foreach ($matches as $match)
124
		{
125
			// If Memcached already has this server (or if the port is invalid), skip it
126
			if (in_array($match[1].':'.$match[2], $server_list, TRUE))
127
			{
128
				log_message('debug', 'Session: Memcached server pool already has '.$match[1].':'.$match[2]);
129
				continue;
130
			}
131
132
			if ( ! $this->_memcached->addServer($match[1], $match[2], isset($match[3]) ? $match[3] : 0))
133
			{
134
				log_message('error', 'Could not add '.$match[1].':'.$match[2].' to Memcached server pool.');
135
			}
136
			else
137
			{
138
				$server_list[] = $match[1].':'.$match[2];
139
			}
140
		}
141
142
		if (empty($server_list))
143
		{
144
			log_message('error', 'Session: Memcached server pool is empty.');
145
			return $this->_failure;
146
		}
147
148
		return $this->_success;
149
	}
150
151
	// ------------------------------------------------------------------------
152
153
	/**
154
	 * Read
155
	 *
156
	 * Reads session data and acquires a lock
157
	 *
158
	 * @param	string	$session_id	Session ID
159
	 * @return	string	Serialized session data
160
	 */
161 View Code Duplication
	public function read($session_id)
162
	{
163
		if (isset($this->_memcached) && $this->_get_lock($session_id))
164
		{
165
			// Needed by write() to detect session_regenerate_id() calls
166
			$this->_session_id = $session_id;
167
168
			$session_data = (string) $this->_memcached->get($this->_key_prefix.$session_id);
169
			$this->_fingerprint = md5($session_data);
170
			return $session_data;
171
		}
172
173
		return $this->_failure;
174
	}
175
176
	// ------------------------------------------------------------------------
177
178
	/**
179
	 * Write
180
	 *
181
	 * Writes (create / update) session data
182
	 *
183
	 * @param	string	$session_id	Session ID
184
	 * @param	string	$session_data	Serialized session data
185
	 * @return	bool
186
	 */
187 View Code Duplication
	public function write($session_id, $session_data)
188
	{
189
		if ( ! isset($this->_memcached))
190
		{
191
			return $this->_failure;
192
		}
193
		// Was the ID regenerated?
194
		elseif ($session_id !== $this->_session_id)
195
		{
196
			if ( ! $this->_release_lock() OR ! $this->_get_lock($session_id))
197
			{
198
				return $this->_failure;
199
			}
200
201
			$this->_fingerprint = md5('');
202
			$this->_session_id = $session_id;
203
		}
204
205
		if (isset($this->_lock_key))
206
		{
207
			$this->_memcached->replace($this->_lock_key, time(), 300);
208
			if ($this->_fingerprint !== ($fingerprint = md5($session_data)))
209
			{
210
				if ($this->_memcached->set($this->_key_prefix.$session_id, $session_data, $this->_config['expiration']))
211
				{
212
					$this->_fingerprint = $fingerprint;
213
					return $this->_success;
214
				}
215
216
				return $this->_failure;
217
			}
218
219
			return $this->_memcached->touch($this->_key_prefix.$session_id, $this->_config['expiration'])
220
				? $this->_success
221
				: $this->_failure;
222
		}
223
224
		return $this->_failure;
225
	}
226
227
	// ------------------------------------------------------------------------
228
229
	/**
230
	 * Close
231
	 *
232
	 * Releases locks and closes connection.
233
	 *
234
	 * @return	bool
235
	 */
236
	public function close()
237
	{
238
		if (isset($this->_memcached))
239
		{
240
			isset($this->_lock_key) && $this->_memcached->delete($this->_lock_key);
241
			if ( ! $this->_memcached->quit())
242
			{
243
				return $this->_failure;
244
			}
245
246
			$this->_memcached = NULL;
247
			return $this->_success;
248
		}
249
250
		return $this->_failure;
251
	}
252
253
	// ------------------------------------------------------------------------
254
255
	/**
256
	 * Destroy
257
	 *
258
	 * Destroys the current session.
259
	 *
260
	 * @param	string	$session_id	Session ID
261
	 * @return	bool
262
	 */
263
	public function destroy($session_id)
264
	{
265
		if (isset($this->_memcached, $this->_lock_key))
266
		{
267
			$this->_memcached->delete($this->_key_prefix.$session_id);
268
			$this->_cookie_destroy();
269
			return $this->_success;
270
		}
271
272
		return $this->_failure;
273
	}
274
275
	// ------------------------------------------------------------------------
276
277
	/**
278
	 * Garbage Collector
279
	 *
280
	 * Deletes expired sessions
281
	 *
282
	 * @param	int 	$maxlifetime	Maximum lifetime of sessions
283
	 * @return	bool
284
	 */
285
	public function gc($maxlifetime)
286
	{
287
		// Not necessary, Memcached takes care of that.
288
		return $this->_success;
289
	}
290
291
	// ------------------------------------------------------------------------
292
293
	/**
294
	 * Get lock
295
	 *
296
	 * Acquires an (emulated) lock.
297
	 *
298
	 * @param	string	$session_id	Session ID
299
	 * @return	bool
300
	 */
301
	protected function _get_lock($session_id)
302
	{
303
		if (isset($this->_lock_key))
304
		{
305
			return ($this->_memcached->replace($this->_lock_key, time(), 300))
306
				? $this->_success
307
				: $this->_failure;
308
		}
309
310
		// 30 attempts to obtain a lock, in case another request already has it
311
		$lock_key = $this->_key_prefix.$session_id.':lock';
312
		$attempt = 0;
313 View Code Duplication
		do
314
		{
315
			if ($this->_memcached->get($lock_key))
316
			{
317
				sleep(1);
318
				continue;
319
			}
320
321
			if ( ! $this->_memcached->set($lock_key, time(), 300))
322
			{
323
				log_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id);
324
				return $this->_failure;
325
			}
326
327
			$this->_lock_key = $lock_key;
328
			break;
329
		}
330
		while (++$attempt < 30);
331
332
		if ($attempt === 30)
333
		{
334
			log_message('error', 'Session: Unable to obtain lock for '.$this->_key_prefix.$session_id.' after 30 attempts, aborting.');
335
			return $this->_failure;
336
		}
337
338
		$this->_lock = TRUE;
339
		return $this->_success;
340
	}
341
342
	// ------------------------------------------------------------------------
343
344
	/**
345
	 * Release lock
346
	 *
347
	 * Releases a previously acquired lock
348
	 *
349
	 * @return	bool
350
	 */
351 View Code Duplication
	protected function _release_lock()
352
	{
353
		if (isset($this->_memcached, $this->_lock_key) && $this->_lock)
354
		{
355
			if ( ! $this->_memcached->delete($this->_lock_key) && $this->_memcached->getResultCode() !== Memcached::RES_NOTFOUND)
356
			{
357
				log_message('error', 'Session: Error while trying to free lock for '.$this->_lock_key);
358
				return FALSE;
359
			}
360
361
			$this->_lock_key = NULL;
362
			$this->_lock = FALSE;
363
		}
364
365
		return TRUE;
366
	}
367
368
}
369