Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Passed
Push — master ( be6889...6f2492 )
by Dan
03:30
created

SmrSession::updateVar()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 2 Features 0
Metric Value
eloc 7
c 4
b 2
f 0
dl 0
loc 9
rs 10
cc 2
nc 2
nop 2
1
<?php
2
3
if(!defined('USING_AJAX'))
4
	define('USING_AJAX',false);
5
class SmrSession {
6
	const ALWAYS_AVAILABLE = 999999;
7
	const TIME_BEFORE_EXPIRY = 3600;
8
9
	// Defines the number of pages that can be loaded after
10
	// this page before the links on this page become invalid
11
	// (i.e. before you get a back button error).
12
	private const URL_DEFAULT_REMAINING_PAGE_LOADS = array(
13
			'alliance_broadcast.php' => self::ALWAYS_AVAILABLE,
14
			'alliance_forces.php' => self::ALWAYS_AVAILABLE,
15
			'alliance_list.php' => self::ALWAYS_AVAILABLE,
16
			'alliance_message_view.php' => self::ALWAYS_AVAILABLE,
17
			'alliance_message.php' => self::ALWAYS_AVAILABLE,
18
			'alliance_mod.php' => self::ALWAYS_AVAILABLE,
19
			'alliance_option.php' => self::ALWAYS_AVAILABLE,
20
			'alliance_pick.php' => self::ALWAYS_AVAILABLE,
21
			'alliance_remove_member.php' => self::ALWAYS_AVAILABLE,
22
			'alliance_roster.php' => self::ALWAYS_AVAILABLE,
23
			'beta_functions.php' => self::ALWAYS_AVAILABLE,
24
			'bug_report.php' => self::ALWAYS_AVAILABLE,
25
			'cargo_dump.php' => self::ALWAYS_AVAILABLE,
26
			'council_list.php' => self::ALWAYS_AVAILABLE,
27
			'course_plot.php' => self::ALWAYS_AVAILABLE,
28
			'changelog_view.php' => self::ALWAYS_AVAILABLE,
29
			'chat_rules.php' => self::ALWAYS_AVAILABLE,
30
			'chess_play.php' => self::ALWAYS_AVAILABLE,
31
			'combat_log_list.php' => self::ALWAYS_AVAILABLE,
32
			'combat_log_viewer.php' => self::ALWAYS_AVAILABLE,
33
			'current_sector.php' => self::ALWAYS_AVAILABLE,
34
			'configure_hardware.php' => self::ALWAYS_AVAILABLE,
35
			'contact.php' => self::ALWAYS_AVAILABLE,
36
			'council_embassy.php' => self::ALWAYS_AVAILABLE,
37
			'council_list.php' => self::ALWAYS_AVAILABLE,
38
			'council_politics.php' => self::ALWAYS_AVAILABLE,
39
			'council_send_message.php' => self::ALWAYS_AVAILABLE,
40
			'council_vote.php' => self::ALWAYS_AVAILABLE,
41
			'current_players.php' => self::ALWAYS_AVAILABLE,
42
			'donation.php' => self::ALWAYS_AVAILABLE,
43
			'feature_request_comments.php' => self::ALWAYS_AVAILABLE,
44
			'feature_request.php' => self::ALWAYS_AVAILABLE,
45
			'forces_list.php' => self::ALWAYS_AVAILABLE,
46
			'forces_mass_refresh.php' => self::ALWAYS_AVAILABLE,
47
			'government.php' => 1,
48
			'hall_of_fame_player_new.php' => self::ALWAYS_AVAILABLE,
49
			'hall_of_fame_player_detail.php' => self::ALWAYS_AVAILABLE,
50
			'leave_newbie.php' => self::ALWAYS_AVAILABLE,
51
			'logoff.php' => self::ALWAYS_AVAILABLE,
52
			'map_local.php' => self::ALWAYS_AVAILABLE,
53
			'message_view.php' => self::ALWAYS_AVAILABLE,
54
			'message_send.php' => self::ALWAYS_AVAILABLE,
55
			'news_read_advanced.php' => self::ALWAYS_AVAILABLE,
56
			'news_read_current.php' => 1,
57
			'news_read.php' => self::ALWAYS_AVAILABLE,
58
			'planet_construction.php' => self::ALWAYS_AVAILABLE,
59
			'planet_defense.php' => self::ALWAYS_AVAILABLE,
60
			'planet_financial.php' => self::ALWAYS_AVAILABLE,
61
			'planet_main.php' => self::ALWAYS_AVAILABLE,
62
			'planet_ownership.php' => self::ALWAYS_AVAILABLE,
63
			'planet_stockpile.php' => self::ALWAYS_AVAILABLE,
64
			'planet_list.php' => self::ALWAYS_AVAILABLE,
65
			'planet_list_financial.php' => self::ALWAYS_AVAILABLE,
66
			'preferences.php' => self::ALWAYS_AVAILABLE,
67
			'rankings_alliance_death.php' => self::ALWAYS_AVAILABLE,
68
			'rankings_alliance_experience.php' => self::ALWAYS_AVAILABLE,
69
			'rankings_alliance_kills.php' => self::ALWAYS_AVAILABLE,
70
			'rankings_alliance_vs_alliance.php' => self::ALWAYS_AVAILABLE,
71
			'rankings_player_death.php' => self::ALWAYS_AVAILABLE,
72
			'rankings_player_experience.php' => self::ALWAYS_AVAILABLE,
73
			'rankings_player_kills.php' => self::ALWAYS_AVAILABLE,
74
			'rankings_player_profit.php' => self::ALWAYS_AVAILABLE,
75
			'rankings_race_death.php' => self::ALWAYS_AVAILABLE,
76
			'rankings_race_kills.php' => self::ALWAYS_AVAILABLE,
77
			'rankings_race.php' => self::ALWAYS_AVAILABLE,
78
			'rankings_sector_kill.php' => self::ALWAYS_AVAILABLE,
79
			'rankings_player_kills.php' => self::ALWAYS_AVAILABLE,
80
			'rankings_player_kills.php' => self::ALWAYS_AVAILABLE,
81
			'rankings_player_kills.php' => self::ALWAYS_AVAILABLE,
82
			'rankings_view.php' => self::ALWAYS_AVAILABLE,
83
			'sector_scan.php' => self::ALWAYS_AVAILABLE,
84
			'trader_bounties.php' => self::ALWAYS_AVAILABLE,
85
			'trader_relations.php' => self::ALWAYS_AVAILABLE,
86
			'trader_savings.php' => self::ALWAYS_AVAILABLE,
87
			'trader_search_result.php' => self::ALWAYS_AVAILABLE,
88
			'trader_search.php' => self::ALWAYS_AVAILABLE,
89
			'trader_status.php' => self::ALWAYS_AVAILABLE,
90
			'weapon_reorder.php' => self::ALWAYS_AVAILABLE,
91
			//Processing pages
92
			'alliance_message_add_processing.php' => self::ALWAYS_AVAILABLE,
93
			'alliance_message_delete_processing.php' => self::ALWAYS_AVAILABLE,
94
			'alliance_pick_processing.php' => self::ALWAYS_AVAILABLE,
95
			'chess_move_processing.php' => self::ALWAYS_AVAILABLE,
96
			'toggle_processing.php' => self::ALWAYS_AVAILABLE,
97
			//Admin pages
98
			'account_edit.php' => self::ALWAYS_AVAILABLE,
99
			'album_moderate.php' => self::ALWAYS_AVAILABLE,
100
			'box_view.php' => self::ALWAYS_AVAILABLE,
101
			'changelog.php' => self::ALWAYS_AVAILABLE,
102
			'comp_share.php' => self::ALWAYS_AVAILABLE,
103
			'form_open.php' => self::ALWAYS_AVAILABLE,
104
			'ip_view_results.php' => self::ALWAYS_AVAILABLE,
105
			'ip_view.php' => self::ALWAYS_AVAILABLE,
106
			'permission_manage.php' => self::ALWAYS_AVAILABLE,
107
			'word_filter.php' => self::ALWAYS_AVAILABLE,
108
			//Uni gen
109
			'universe_create_locations.php' => self::ALWAYS_AVAILABLE,
110
			'universe_create_planets.php' => self::ALWAYS_AVAILABLE,
111
			'universe_create_ports.php' => self::ALWAYS_AVAILABLE,
112
			'universe_create_sector_details.php' => self::ALWAYS_AVAILABLE,
113
			'universe_create_sectors.php' => self::ALWAYS_AVAILABLE,
114
			'universe_create_warps.php' => self::ALWAYS_AVAILABLE
115
		);
116
117
	private const URL_LOAD_DELAY = array(
118
		'configure_hardware.php' => .4,
119
		'forces_drop.php' => .4,
120
		'forces_drop_processing.php' => .5,
121
		'forces_refresh_processing.php' => .4,
122
		'sector_jump_processing.php' => .4,
123
		'sector_move_processing.php' => .4,
124
		'sector_scan.php' => .4,
125
		'shop_goods_processing.php' => .4,
126
		'trader_attack_processing.php' => .75,
127
		'trader_examine.php' => .75
128
	);
129
130
	protected static $db;
131
132
	private static $session_id;
133
	private static $game_id;
134
	private static $var;
135
	private static $commonIDs;
136
	private static $generate;
137
	private static $SN;
138
	private static $lastSN;
139
	public static $account_id;
140
	public static $last_accessed;
141
142
	protected static $previousAjaxReturns;
143
	protected static $ajaxReturns=array();
144
145
	public static function init() {
146
		// Initialize the db connector here, since `init` is always called
147
		self::$db = new SmrMySqlDatabase();
148
149
		// now try the cookie
150
		if (isset($_COOKIE['session_id'])) {
151
			self::$session_id = $_COOKIE['session_id'];
152
		}
153
		else {
154
			// create a new session id
155
			do {
156
				self::$session_id = md5 (uniqid (mt_rand()) );
157
				self::$db->query('SELECT 1 FROM active_session WHERE session_id = ' . self::$db->escapeString(self::$session_id) . ' LIMIT 1');
158
			} while(self::$db->nextRecord()); //Make sure we haven't somehow clashed with someone else's session.
159
			setcookie('session_id', self::$session_id);
160
		}
161
162
		// try to get current session
163
		self::$db->query('DELETE FROM active_session WHERE last_accessed < ' . self::$db->escapeNumber(time() - self::TIME_BEFORE_EXPIRY));
164
		self::fetchVarInfo();
165
166
		if(!USING_AJAX && isset($_REQUEST['sn']) && isset(self::$var[$_REQUEST['sn']]) && !empty(self::$var[$_REQUEST['sn']])) {
167
			$var = self::$var[$_REQUEST['sn']];
168
			$currentPage = $var['url'] == 'skeleton.php' ? $var['body'] : $var['url'];
169
			$loadDelay = isset(self::URL_LOAD_DELAY[$currentPage]) ? self::URL_LOAD_DELAY[$currentPage] : 0;
170
			$initialTimeBetweenLoads = microtime(true) - $var['PreviousRequestTime'];
171
			while(($timeBetweenLoads = microtime(true) - $var['PreviousRequestTime']) < $loadDelay) {
172
				$sleepTime = round(($loadDelay-$timeBetweenLoads)*1000000);
173
			//	echo 'Sleeping for: ' . $sleepTime . 'us';
174
				usleep($sleepTime);
0 ignored issues
show
Bug introduced by
$sleepTime of type double is incompatible with the type integer expected by parameter $micro_seconds of usleep(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

174
				usleep(/** @scrutinizer ignore-type */ $sleepTime);
Loading history...
175
			}
176
			if (ENABLE_DEBUG) {
177
				self::$db->query('INSERT INTO debug VALUES (' . self::$db->escapeString('Delay: ' . $currentPage) . ',' . self::$db->escapeNumber(self::$account_id) . ',' . self::$db->escapeNumber($initialTimeBetweenLoads) . ',' . self::$db->escapeNumber($timeBetweenLoads) . ')');
178
			}
179
		}
180
	}
181
182
	public static function fetchVarInfo() {
183
		self::$db->query('SELECT * FROM active_session WHERE session_id = ' . self::$db->escapeString(self::$session_id) . ' LIMIT 1');
184
		if (self::$db->nextRecord()) {
185
			self::$generate = false;
186
			self::$session_id		= self::$db->getField('session_id');
187
			self::$account_id		= self::$db->getInt('account_id');
188
			self::$game_id			= self::$db->getInt('game_id');
189
			self::$last_accessed	= self::$db->getInt('last_accessed');
190
			self::$var = @unserialize(@gzuncompress(self::$db->getField('session_var')));
191
			self::$commonIDs	= array();
192
			self::$lastSN = self::$db->getField('last_sn');
193
			// We may not have ajax_returns if ajax was disabled
194
			$ajaxReturns = self::$db->getField('ajax_returns');
195
			if (!empty($ajaxReturns)) {
196
				self::$previousAjaxReturns = unserialize(gzuncompress($ajaxReturns));
197
			}
198
			if(!is_array(self::$var)) {
199
				self::$account_id	= 0;
200
				self::$game_id		= 0;
201
				self::$var			= array();
202
			}
203
			else {
204
				foreach(self::$var as $key => &$value) {
205
					if ($value['Expires'] > 0 && $value['Expires'] <= TIME) { // Use 0 for infinity
206
						//This link is no longer valid
207
						unset(self::$var[$key]);
208
					}
209
					else if ($value['RemainingPageLoads'] < 0) {
210
						//This link is no longer valid
211
						unset(self::$var[$key]);
212
					}
213
					else {
214
						--$value['RemainingPageLoads'];
215
						if(isset($value['CommonID'])) {
216
							self::$commonIDs[$value['CommonID']] = $key;
217
						}
218
					}
219
				} unset($value);
220
			}
221
		}
222
		else {
223
			self::$generate = true;
224
			self::$account_id	= 0;
225
			self::$game_id		= 0;
226
			self::$var			= array();
227
			self::$commonIDs	= array();
228
		}
229
	}
230
231
	public static function update() {
232
		foreach(self::$var as $key => &$value) {
233
			if ($value['RemainingPageLoads'] <= 0) {
234
				//This link was valid this load but will not be in the future, removing it now saves database space and data transfer.
235
				unset(self::$var[$key]);
236
			}
237
		} unset($value);
238
		$compressed = gzcompress(serialize(self::$var));
239
		if(!self::$generate) {
240
			self::$db->query('UPDATE active_session SET account_id=' . self::$db->escapeNumber(self::$account_id) . ',game_id=' . self::$db->escapeNumber(self::$game_id) . (!USING_AJAX ? ',last_accessed=' . self::$db->escapeNumber(TIME) : '') . ',session_var=' . self::$db->escapeBinary($compressed) .
241
					',last_sn='.self::$db->escapeString(self::$SN).
242
					' WHERE session_id=' . self::$db->escapeString(self::$session_id) . (USING_AJAX ? ' AND last_sn='.self::$db->escapeString(self::$lastSN) : '') . ' LIMIT 1');
243
		}
244
		else {
245
			self::$db->query('DELETE FROM active_session WHERE account_id = ' . self::$db->escapeNumber(self::$account_id) . ' AND game_id = ' . self::$db->escapeNumber(self::$game_id));
246
			self::$db->query('INSERT INTO active_session (session_id, account_id, game_id, last_accessed, session_var) VALUES(' . self::$db->escapeString(self::$session_id) . ',' . self::$db->escapeNumber(self::$account_id) . ',' . self::$db->escapeNumber(self::$game_id) . ',' . self::$db->escapeNumber(TIME) . ',' . self::$db->escapeBinary($compressed) . ')');
247
			self::$generate = false;
248
		}
249
	}
250
251
	/**
252
	 * Returns the Game ID associated with the session.
253
	 */
254
	public static function getGameID() {
255
		return self::$game_id;
256
	}
257
258
	/**
259
	 * Returns true if the session is inside a game, false otherwise.
260
	 */
261
	public static function hasGame() {
262
		return self::$game_id != 0;
263
	}
264
265
	/**
266
	 * Updates the `game_id` attribute of the session and deletes any other
267
	 * active sessions in this game for this account.
268
	 */
269
	public static function updateGame($gameID) {
270
		if (self::$game_id == $gameID) {
271
			return;
272
		}
273
		self::$game_id = $gameID;
274
		self::$db->query('DELETE FROM active_session WHERE account_id = ' . self::$db->escapeNumber(self::$account_id) . ' AND game_id = ' . self::$game_id);
275
		self::$db->query('UPDATE active_session SET game_id=' . self::$db->escapeNumber(self::$game_id) . ' WHERE session_id=' . self::$db->escapeString(self::$session_id));
276
	}
277
278
	/**
279
	 * Returns true if the current SN is different than the previous SN.
280
	 */
281
	public static function hasChangedSN() {
282
		return self::$SN != self::$lastSN;
283
	}
284
285
	private static function updateSN() {
286
		if(!USING_AJAX)
287
			self::$db->query('UPDATE active_session SET last_sn='.self::$db->escapeString(self::$SN).
288
				' WHERE session_id=' . self::$db->escapeString(self::$session_id) . ' LIMIT 1');
289
	}
290
291
	public static function destroy() {
292
		self::$db->query('UPDATE active_session SET account_id=0,game_id=0,session_var=\'\',ajax_returns=\'\' WHERE session_id = ' . self::$db->escapeString(self::$session_id) . ' LIMIT 1');
293
		self::$session_id = '';
294
		self::$account_id = 0;
295
		self::$game_id = 0;
296
	}
297
298
	/**
299
	 * Retrieve the session var for the page given by $sn.
300
	 * If $sn is not specified, use the current page (i.e. self::$SN).
301
	 */
302
	public static function retrieveVar($sn=null) {
303
		if (is_null($sn)) {
304
			$sn = self::$SN;
305
		}
306
		if (empty(self::$var[$sn])) {
307
			return false;
308
		}
309
		self::$SN = $sn;
310
		SmrSession::updateSN();
311
		if(isset(self::$var[$sn]['body']) && isset(self::$var[$sn]['CommonID'])) {
312
//			if(preg_match('/processing/',self::$var[$sn]['body']))
313
			unset(self::$commonIDs[self::$var[$sn]['CommonID']]); //Do not store common id for current page
314
			unset(self::$var[$sn]['CommonID']);
315
		}
316
317
		self::$var[$sn]['RemainingPageLoads'] += 1; // Allow refreshing
318
		self::$var[$sn]['Expires'] = 0; // Allow refreshing forever
319
		return self::$var[$sn];
320
	}
321
322
	/**
323
	 * Gets a var from $_REQUEST (or $default) and then stores it in the
324
	 * session so that it can still be retrieved when the page auto-refreshes.
325
	 * This is the recommended way to get $_REQUEST data.
326
	 */
327
	public static function getRequestVar($varName, $default=null) {
328
		global $var;
329
		// Set the session var, if in $_REQUESTS or if a default is given
330
		if (isset($_REQUEST[$varName])) {
331
			self::updateVar($varName, $_REQUEST[$varName]);
332
		} elseif (isset($default) && !isset($var[$varName])) {
333
			self::updateVar($varName, $default);
334
		}
335
		// Return the possibly updated session var
336
		if (isset($var[$varName])) {
337
			return $var[$varName];
338
		}
339
	}
340
341
	public static function resetLink($container, $sn) { //Do not allow sharing SN, useful for forwarding.
342
		global $lock;
343
		if(isset(self::$var[$sn]['CommonID'])) {
344
			unset(self::$commonIDs[self::$var[$sn]['CommonID']]); //Do not store common id for reset page, to allow refreshing to always give the same page in response
345
		}
346
		self::$SN = $sn;
347
		if(!isset($container['Expires'])) {
348
			$container['Expires'] = 0; // Lasts forever
349
		}
350
		if(!isset($container['RemainingPageLoads'])) {
351
			$container['RemainingPageLoads'] = 1; // Allow refreshing
352
		}
353
		if(!isset($container['PreviousRequestTime'])) {
354
			if(isset(self::$var[$sn]['PreviousRequestTime'])) {
355
				$container['PreviousRequestTime'] = self::$var[$sn]['PreviousRequestTime']; // Copy across the previous request time if not explicitly set.
356
			}
357
		}
358
359
		self::$var[$sn] = $container;
360
		if(!$lock && !USING_AJAX)
361
			self::update();
362
		return $sn;
363
	}
364
365
	public static function updateVar($key,$value) {
366
		global $var;
367
		if($value===null) {
368
			unset($var[$key]);
369
			unset(self::$var[self::$SN][$key]);
370
		}
371
		else {
372
			$var[$key] = $value;
373
			self::$var[self::$SN][$key] = $value;
374
		}
375
	}
376
377
	public static function clearLinks() {
378
		self::$var = array(self::$SN => self::$var[self::$SN]);
379
		self::$commonIDs = array();
380
	}
381
382
	public static function addLink($container, $sn = false) { // Container['ID'] MUST be unique to a specific action, if there will be two different outcomes from containers given the same ID then problems will likely arise.
383
		if(!isset($container['Expires'])) {
384
			$container['Expires'] = 0; // Lasts forever
385
		}
386
		if(!isset($container['RemainingPageLoads'])) {
387
			$pageURL = $container['url'] == 'skeleton.php' ? $container['body'] : $container['url'];
388
			$container['RemainingPageLoads'] = isset(self::URL_DEFAULT_REMAINING_PAGE_LOADS[$pageURL]) ? self::URL_DEFAULT_REMAINING_PAGE_LOADS[$pageURL] : 1; // Allow refreshing
389
		}
390
391
		if($sn === false) {
392
			$sn = self::generateSN($container);
393
		}
394
		else {
395
			// If we've been provided an SN to use then copy over the existing 'PreviousRequestTime'
396
			$container['PreviousRequestTime'] = self::$var[$sn]['PreviousRequestTime'];
397
		}
398
		self::$var[$sn] = $container;
399
		return $sn;
400
	}
401
402
	protected static function generateSN(&$container) {
403
		$container['CommonID'] = self::getCommonID($container);
404
		if(isset(self::$commonIDs[$container['CommonID']])) {
405
			$sn = self::$commonIDs[$container['CommonID']];
406
			$container['PreviousRequestTime'] = isset(self::$var[$sn]) ? self::$var[$sn]['PreviousRequestTime'] : MICRO_TIME;
407
		}
408
		else {
409
			do {
410
				$sn = substr(md5(mt_rand()),0,8);
411
			} while(isset(self::$var[$sn]));
412
			$container['PreviousRequestTime'] = MICRO_TIME;
413
		}
414
		self::$commonIDs[$container['CommonID']] = $sn;
415
		return $sn;
416
	}
417
418
	protected static function getCommonID($commonContainer) {
419
		unset($commonContainer['Expires']);
420
		unset($commonContainer['RemainingPageLoads']);
421
		unset($commonContainer['PreviousRequestTime']);
422
		unset($commonContainer['CommonID']);
423
		return md5(serialize($commonContainer));
424
	}
425
426
	public static function getNewHREF($container, $forceFullURL=false) {
427
		$sn = self::addLink($container) . (isset($container['AJAX']) && $container['AJAX'] == true ? '&ajax=1':'');
428
		if($forceFullURL===true||stripos($_SERVER['REQUEST_URI'],'loader.php')===false)
429
			return '/loader.php?sn=' . $sn;
430
		else
431
			return '?sn=' . $sn;
432
	}
433
434
	public static function addAjaxReturns($element,$contents) {
435
		self::$ajaxReturns[$element] = $contents;
436
		return isset(self::$previousAjaxReturns[$element])&&self::$previousAjaxReturns[$element]==$contents;
437
	}
438
439
	public static function saveAjaxReturns() {
440
		if(empty(self::$ajaxReturns))
441
			return;
442
		$compressed = gzcompress(serialize(self::$ajaxReturns));
443
		self::$db->query('UPDATE active_session SET ajax_returns=' . self::$db->escapeBinary($compressed) .
444
				' WHERE session_id=' . self::$db->escapeString(self::$session_id) . ' LIMIT 1');
445
	}
446
}
447
448
SmrSession::init();
449