Failed Conditions
Branch release-2.1 (4e22cf)
by Rick
06:39
created

Session.php ➔ sessionGC()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 19
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 8
nc 4
nop 1
dl 0
loc 19
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
/**
4
 *  Implementation of PHP's session API.
5
 * 	What it does:
6
 * 	- it handles the session data in the database (more scalable.)
7
 * 	- it uses the databaseSession_lifetime setting for garbage collection.
8
 * 	- the custom session handler is set by loadSession().
9
 *
10
 * Simple Machines Forum (SMF)
11
 *
12
 * @package SMF
13
 * @author Simple Machines http://www.simplemachines.org
14
 * @copyright 2017 Simple Machines and individual contributors
15
 * @license http://www.simplemachines.org/about/smf/license.php BSD
16
 *
17
 * @version 2.1 Beta 4
18
 */
19
20
if (!defined('SMF'))
21
	die('No direct access...');
22
23
/**
24
 * Attempt to start the session, unless it already has been.
25
 */
26
function loadSession()
27
{
28
	global $modSettings, $boardurl, $sc;
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $sc. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
29
30
	// Attempt to change a few PHP settings.
31
	@ini_set('session.use_cookies', true);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
32
	@ini_set('session.use_only_cookies', false);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
33
	@ini_set('url_rewriter.tags', '');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
34
	@ini_set('session.use_trans_sid', false);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
35
	@ini_set('arg_separator.output', '&amp;');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
36
37
	if (!empty($modSettings['globalCookies']))
38
	{
39
		$parsed_url = parse_url($boardurl);
40
41
		if (preg_match('~^\d{1,3}(\.\d{1,3}){3}$~', $parsed_url['host']) == 0 && preg_match('~(?:[^\.]+\.)?([^\.]{2,}\..+)\z~i', $parsed_url['host'], $parts) == 1)
42
			@ini_set('session.cookie_domain', '.' . $parts[1]);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
43
	}
44
	// @todo Set the session cookie path?
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
45
46
	// If it's already been started... probably best to skip this.
47
	if ((ini_get('session.auto_start') == 1 && !empty($modSettings['databaseSession_enable'])) || session_id() == '')
48
	{
49
		// Attempt to end the already-started session.
50
		if (ini_get('session.auto_start') == 1)
51
			session_write_close();
52
53
		// This is here to stop people from using bad junky PHPSESSIDs.
54
		if (isset($_REQUEST[session_name()]) && preg_match('~^[A-Za-z0-9,-]{16,64}$~', $_REQUEST[session_name()]) == 0 && !isset($_COOKIE[session_name()]))
55
		{
56
			$session_id = md5(md5('smf_sess_' . time()) . mt_rand());
57
			$_REQUEST[session_name()] = $session_id;
58
			$_GET[session_name()] = $session_id;
59
			$_POST[session_name()] = $session_id;
60
		}
61
62
		// Use database sessions? (they don't work in 4.1.x!)
63
		if (!empty($modSettings['databaseSession_enable']))
64
		{
65
			@ini_set('session.serialize_handler', 'php');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
66
			session_set_save_handler('sessionOpen', 'sessionClose', 'sessionRead', 'sessionWrite', 'sessionDestroy', 'sessionGC');
67
			@ini_set('session.gc_probability', '1');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
68
		}
69
		elseif (ini_get('session.gc_maxlifetime') <= 1440 && !empty($modSettings['databaseSession_lifetime']))
70
			@ini_set('session.gc_maxlifetime', max($modSettings['databaseSession_lifetime'], 60));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
71
72
		// Use cache setting sessions?
73
		if (empty($modSettings['databaseSession_enable']) && !empty($modSettings['cache_enable']) && php_sapi_name() != 'cli')
74
			call_integration_hook('integrate_session_handlers');
75
76
		session_start();
77
78
		// Change it so the cache settings are a little looser than default.
79
		if (!empty($modSettings['databaseSession_loose']))
80
			header('Cache-Control: private');
81
	}
82
83
	// Set the randomly generated code.
84 View Code Duplication
	if (!isset($_SESSION['session_var']))
85
	{
86
		$_SESSION['session_value'] = md5(session_id() . mt_rand());
87
		$_SESSION['session_var'] = substr(preg_replace('~^\d+~', '', sha1(mt_rand() . session_id() . mt_rand())), 0, mt_rand(7, 12));
88
	}
89
	$sc = $_SESSION['session_value'];
90
}
91
92
/**
93
 * Implementation of sessionOpen() replacing the standard open handler.
94
 * It simply returns true.
95
 *
96
 * @param string $save_path The path to save the session to
97
 * @param string $session_name The name of the session
98
 * @return boolean Always returns true
99
 */
100
function sessionOpen($save_path, $session_name)
0 ignored issues
show
Unused Code introduced by
The parameter $save_path is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $session_name is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
101
{
102
	return true;
103
}
104
105
/**
106
 * Implementation of sessionClose() replacing the standard close handler.
107
 * It simply returns true.
108
 *
109
 * @return boolean Always returns true
110
 */
111
function sessionClose()
112
{
113
	return true;
114
}
115
116
/**
117
 * Implementation of sessionRead() replacing the standard read handler.
118
 *
119
 * @param string $session_id The session ID
120
 * @return string The session data
121
 */
122
function sessionRead($session_id)
123
{
124
	global $smcFunc;
125
126
	if (preg_match('~^[A-Za-z0-9,-]{16,64}$~', $session_id) == 0)
127
		return '';
128
129
	// Look for it in the database.
130
	$result = $smcFunc['db_query']('', '
131
		SELECT data
132
		FROM {db_prefix}sessions
133
		WHERE session_id = {string:session_id}
134
		LIMIT 1',
135
		array(
136
			'session_id' => $session_id,
137
		)
138
	);
139
	list ($sess_data) = $smcFunc['db_fetch_row']($result);
140
	$smcFunc['db_free_result']($result);
141
142
	return $sess_data != null ? $sess_data : '';
143
}
144
145
/**
146
 * Implementation of sessionWrite() replacing the standard write handler.
147
 *
148
 * @param string $session_id The session ID
149
 * @param string $data The data to write to the session
150
 * @return boolean Whether the info was successfully written
151
 */
152
function sessionWrite($session_id, $data)
153
{
154
	global $smcFunc;
155
156
	if (preg_match('~^[A-Za-z0-9,-]{16,64}$~', $session_id) == 0)
157
		return false;
158
159
	// First try to update an existing row...
160
	$smcFunc['db_query']('', '
161
		UPDATE {db_prefix}sessions
162
		SET data = {string:data}, last_update = {int:last_update}
163
		WHERE session_id = {string:session_id}',
164
		array(
165
			'last_update' => time(),
166
			'data' => $data,
167
			'session_id' => $session_id,
168
		)
169
	);
170
171
	// If that didn't work, try inserting a new one.
172
	if ($smcFunc['db_affected_rows']() == 0)
173
		$smcFunc['db_insert']('ignore',
174
			'{db_prefix}sessions',
175
			array('session_id' => 'string', 'data' => 'string', 'last_update' => 'int'),
176
			array($session_id, $data, time()),
177
			array('session_id')
178
		);
179
180
	return ($smcFunc['db_affected_rows']() == 0 ? false : true);
181
}
182
183
/**
184
 * Implementation of sessionDestroy() replacing the standard destroy handler.
185
 *
186
 * @param string $session_id The session ID
187
 * @return boolean Whether the session was successfully destroyed
188
 */
189
function sessionDestroy($session_id)
190
{
191
	global $smcFunc;
192
193
	if (preg_match('~^[A-Za-z0-9,-]{16,64}$~', $session_id) == 0)
194
		return false;
195
196
	// Just delete the row...
197
	$smcFunc['db_query']('', '
198
		DELETE FROM {db_prefix}sessions
199
		WHERE session_id = {string:session_id}',
200
		array(
201
			'session_id' => $session_id,
202
		)
203
	);
204
205
	return true;
206
}
207
208
/**
209
 * Implementation of sessionGC() replacing the standard gc handler.
210
 * Callback for garbage collection.
211
 *
212
 * @param int $max_lifetime The maximum lifetime (in seconds) - prevents deleting of sessions older than this
213
 * @return boolean Whether the option was successful
214
 */
215
function sessionGC($max_lifetime)
216
{
217
	global $modSettings, $smcFunc;
218
219
	// Just set to the default or lower?  Ignore it for a higher value. (hopefully)
220
	if (!empty($modSettings['databaseSession_lifetime']) && ($max_lifetime <= 1440 || $modSettings['databaseSession_lifetime'] > $max_lifetime))
221
		$max_lifetime = max($modSettings['databaseSession_lifetime'], 60);
222
223
	// Clean up after yerself ;).
224
	$smcFunc['db_query']('', '
225
		DELETE FROM {db_prefix}sessions
226
		WHERE last_update < {int:last_update}',
227
		array(
228
			'last_update' => time() - $max_lifetime,
229
		)
230
	);
231
232
	return ($smcFunc['db_affected_rows']() == 0 ? false : true);
233
}
234
235
?>