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

Completed
Push — master ( cc690b...a55be4 )
by Dan
25s queued 16s
created

SmrSession::updateSN()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
if (!defined('USING_AJAX')) {
4
	define('USING_AJAX', false);
5
}
6
7
class SmrSession {
8
	const ALWAYS_AVAILABLE = 999999;
9
	const TIME_BEFORE_EXPIRY = 3600;
10
11
	// Defines the number of pages that can be loaded after
12
	// this page before the links on this page become invalid
13
	// (i.e. before you get a back button error).
14
	private const URL_DEFAULT_REMAINING_PAGE_LOADS = array(
15
			'alliance_broadcast.php' => self::ALWAYS_AVAILABLE,
16
			'alliance_forces.php' => self::ALWAYS_AVAILABLE,
17
			'alliance_list.php' => self::ALWAYS_AVAILABLE,
18
			'alliance_message_view.php' => self::ALWAYS_AVAILABLE,
19
			'alliance_message.php' => self::ALWAYS_AVAILABLE,
20
			'alliance_mod.php' => self::ALWAYS_AVAILABLE,
21
			'alliance_option.php' => self::ALWAYS_AVAILABLE,
22
			'alliance_pick.php' => self::ALWAYS_AVAILABLE,
23
			'alliance_remove_member.php' => self::ALWAYS_AVAILABLE,
24
			'alliance_roster.php' => self::ALWAYS_AVAILABLE,
25
			'beta_functions.php' => self::ALWAYS_AVAILABLE,
26
			'bug_report.php' => self::ALWAYS_AVAILABLE,
27
			'cargo_dump.php' => self::ALWAYS_AVAILABLE,
28
			'council_list.php' => self::ALWAYS_AVAILABLE,
29
			'course_plot.php' => self::ALWAYS_AVAILABLE,
30
			'changelog_view.php' => self::ALWAYS_AVAILABLE,
31
			'chat_rules.php' => self::ALWAYS_AVAILABLE,
32
			'chess_play.php' => self::ALWAYS_AVAILABLE,
33
			'combat_log_list.php' => self::ALWAYS_AVAILABLE,
34
			'combat_log_viewer.php' => self::ALWAYS_AVAILABLE,
35
			'current_sector.php' => self::ALWAYS_AVAILABLE,
36
			'configure_hardware.php' => self::ALWAYS_AVAILABLE,
37
			'contact.php' => self::ALWAYS_AVAILABLE,
38
			'council_embassy.php' => self::ALWAYS_AVAILABLE,
39
			'council_list.php' => self::ALWAYS_AVAILABLE,
40
			'council_politics.php' => self::ALWAYS_AVAILABLE,
41
			'council_send_message.php' => self::ALWAYS_AVAILABLE,
42
			'council_vote.php' => self::ALWAYS_AVAILABLE,
43
			'current_players.php' => self::ALWAYS_AVAILABLE,
44
			'donation.php' => self::ALWAYS_AVAILABLE,
45
			'feature_request_comments.php' => self::ALWAYS_AVAILABLE,
46
			'feature_request.php' => self::ALWAYS_AVAILABLE,
47
			'forces_list.php' => self::ALWAYS_AVAILABLE,
48
			'forces_mass_refresh.php' => self::ALWAYS_AVAILABLE,
49
			'government.php' => 1,
50
			'hall_of_fame_player_new.php' => self::ALWAYS_AVAILABLE,
51
			'hall_of_fame_player_detail.php' => self::ALWAYS_AVAILABLE,
52
			'leave_newbie.php' => self::ALWAYS_AVAILABLE,
53
			'logoff.php' => self::ALWAYS_AVAILABLE,
54
			'map_local.php' => self::ALWAYS_AVAILABLE,
55
			'message_view.php' => self::ALWAYS_AVAILABLE,
56
			'message_send.php' => self::ALWAYS_AVAILABLE,
57
			'news_read_advanced.php' => self::ALWAYS_AVAILABLE,
58
			'news_read_current.php' => 1,
59
			'news_read.php' => self::ALWAYS_AVAILABLE,
60
			'planet_construction.php' => self::ALWAYS_AVAILABLE,
61
			'planet_defense.php' => self::ALWAYS_AVAILABLE,
62
			'planet_financial.php' => self::ALWAYS_AVAILABLE,
63
			'planet_main.php' => self::ALWAYS_AVAILABLE,
64
			'planet_ownership.php' => self::ALWAYS_AVAILABLE,
65
			'planet_stockpile.php' => self::ALWAYS_AVAILABLE,
66
			'planet_list.php' => self::ALWAYS_AVAILABLE,
67
			'planet_list_financial.php' => self::ALWAYS_AVAILABLE,
68
			'preferences.php' => self::ALWAYS_AVAILABLE,
69
			'rankings_alliance_death.php' => self::ALWAYS_AVAILABLE,
70
			'rankings_alliance_experience.php' => self::ALWAYS_AVAILABLE,
71
			'rankings_alliance_kills.php' => self::ALWAYS_AVAILABLE,
72
			'rankings_alliance_vs_alliance.php' => self::ALWAYS_AVAILABLE,
73
			'rankings_player_death.php' => self::ALWAYS_AVAILABLE,
74
			'rankings_player_experience.php' => self::ALWAYS_AVAILABLE,
75
			'rankings_player_kills.php' => self::ALWAYS_AVAILABLE,
76
			'rankings_player_profit.php' => self::ALWAYS_AVAILABLE,
77
			'rankings_race_death.php' => self::ALWAYS_AVAILABLE,
78
			'rankings_race_kills.php' => self::ALWAYS_AVAILABLE,
79
			'rankings_race.php' => self::ALWAYS_AVAILABLE,
80
			'rankings_sector_kill.php' => self::ALWAYS_AVAILABLE,
81
			'rankings_player_kills.php' => self::ALWAYS_AVAILABLE,
82
			'rankings_player_kills.php' => self::ALWAYS_AVAILABLE,
83
			'rankings_player_kills.php' => self::ALWAYS_AVAILABLE,
84
			'rankings_view.php' => self::ALWAYS_AVAILABLE,
85
			'sector_scan.php' => self::ALWAYS_AVAILABLE,
86
			'trader_bounties.php' => self::ALWAYS_AVAILABLE,
87
			'trader_relations.php' => self::ALWAYS_AVAILABLE,
88
			'trader_savings.php' => self::ALWAYS_AVAILABLE,
89
			'trader_search_result.php' => self::ALWAYS_AVAILABLE,
90
			'trader_search.php' => self::ALWAYS_AVAILABLE,
91
			'trader_status.php' => self::ALWAYS_AVAILABLE,
92
			'weapon_reorder.php' => self::ALWAYS_AVAILABLE,
93
			//Processing pages
94
			'alliance_message_add_processing.php' => self::ALWAYS_AVAILABLE,
95
			'alliance_message_delete_processing.php' => self::ALWAYS_AVAILABLE,
96
			'alliance_pick_processing.php' => self::ALWAYS_AVAILABLE,
97
			'chess_move_processing.php' => self::ALWAYS_AVAILABLE,
98
			'toggle_processing.php' => self::ALWAYS_AVAILABLE,
99
			//Admin pages
100
			'account_edit.php' => self::ALWAYS_AVAILABLE,
101
			'album_moderate.php' => self::ALWAYS_AVAILABLE,
102
			'box_view.php' => self::ALWAYS_AVAILABLE,
103
			'changelog.php' => self::ALWAYS_AVAILABLE,
104
			'comp_share.php' => self::ALWAYS_AVAILABLE,
105
			'form_open.php' => self::ALWAYS_AVAILABLE,
106
			'ip_view_results.php' => self::ALWAYS_AVAILABLE,
107
			'ip_view.php' => self::ALWAYS_AVAILABLE,
108
			'permission_manage.php' => self::ALWAYS_AVAILABLE,
109
			'word_filter.php' => self::ALWAYS_AVAILABLE,
110
			//Uni gen
111
			'1.6/check_map.php' => self::ALWAYS_AVAILABLE,
112
			'1.6/universe_create_locations.php' => self::ALWAYS_AVAILABLE,
113
			'1.6/universe_create_planets.php' => self::ALWAYS_AVAILABLE,
114
			'1.6/universe_create_ports.php' => self::ALWAYS_AVAILABLE,
115
			'1.6/universe_create_sector_details.php' => self::ALWAYS_AVAILABLE,
116
			'1.6/universe_create_sectors.php' => self::ALWAYS_AVAILABLE,
117
			'1.6/universe_create_warps.php' => self::ALWAYS_AVAILABLE,
118
		);
119
120
	private const URL_LOAD_DELAY = array(
121
		'configure_hardware.php' => .4,
122
		'forces_drop.php' => .4,
123
		'forces_drop_processing.php' => .5,
124
		'forces_refresh_processing.php' => .4,
125
		'sector_jump_processing.php' => .4,
126
		'sector_move_processing.php' => .4,
127
		'sector_scan.php' => .4,
128
		'shop_goods_processing.php' => .4,
129
		'trader_attack_processing.php' => .75,
130
		'trader_examine.php' => .75
131
	);
132
133
	protected static $db;
134
135
	private static $session_id;
136
	private static $game_id;
137
	private static $var;
138
	private static $commonIDs;
139
	private static $generate;
140
	private static $SN = '';
141
	private static $lastSN;
142
	private static $account_id;
143
	public static $last_accessed;
144
	private static Time $pageRequestTime;
145
146
	protected static $previousAjaxReturns;
147
	protected static $ajaxReturns = array();
148
149
	/**
150
	 * Returns the time (in seconds) associated with this page request.
151
	 */
152
	public static function getTime() : int {
153
		return self::$pageRequestTime->getTime();
154
	}
155
156
	/**
157
	 * Returns the time (in seconds, with microsecond-level precision)
158
	 * associated with this page request.
159
	 */
160
	public static function getMicroTime() : float {
161
		return self::$pageRequestTime->getMicroTime();
162
	}
163
164
	/**
165
	 * Update the time associated with this page request.
166
	 *
167
	 * NOTE: This should never be called by normal page requests, and should
168
	 * only be used by the CLI programs that run continuously.
169
	 */
170
	public static function updateTime() : void {
171
		if (!defined('NPC_SCRIPT')) {
172
			throw new Exception('Only call this function from CLI programs!');
173
		}
174
		self::$pageRequestTime = new Time();
175
	}
176
177
	public static function init() {
178
		// Return immediately if the SmrSession is already initialized
179
		if (isset(self::$session_id)) {
180
			return;
181
		}
182
183
		// Initialize the page request time
184
		self::$pageRequestTime = new Time();
185
186
		// Initialize the db connector here, since `init` is always called
187
		self::$db = new SmrMySqlDatabase();
188
189
		// now try the cookie
190
		if (isset($_COOKIE['session_id']) && strlen($_COOKIE['session_id']) === 32) {
191
			self::$session_id = $_COOKIE['session_id'];
192
		} else {
193
			// create a new session id
194
			do {
195
				self::$session_id = md5(uniqid(strval(rand())));
196
				self::$db->query('SELECT 1 FROM active_session WHERE session_id = ' . self::$db->escapeString(self::$session_id) . ' LIMIT 1');
197
			} while (self::$db->nextRecord()); //Make sure we haven't somehow clashed with someone else's session.
198
199
			// This is a minor hack to make sure that setcookie is not called
200
			// for CLI programs and tests (to avoid "headers already sent").
201
			if (headers_sent() === false) {
202
				setcookie('session_id', self::$session_id);
203
			}
204
		}
205
206
		// try to get current session
207
		self::$db->query('DELETE FROM active_session WHERE last_accessed < ' . self::$db->escapeNumber(time() - self::TIME_BEFORE_EXPIRY));
208
		self::fetchVarInfo();
209
210
		if (!USING_AJAX && isset($_REQUEST['sn']) && isset(self::$var[$_REQUEST['sn']]) && !empty(self::$var[$_REQUEST['sn']])) {
211
			$var = self::$var[$_REQUEST['sn']];
212
			$currentPage = $var['url'] == 'skeleton.php' ? $var['body'] : $var['url'];
213
			$loadDelay = self::URL_LOAD_DELAY[$currentPage] ?? 0;
214
			$initialTimeBetweenLoads = microtime(true) - $var['PreviousRequestTime'];
215
			while (($timeBetweenLoads = microtime(true) - $var['PreviousRequestTime']) < $loadDelay) {
216
				$sleepTime = IRound(($loadDelay - $timeBetweenLoads) * 1000000);
217
			//	echo 'Sleeping for: ' . $sleepTime . 'us';
218
				usleep($sleepTime);
219
			}
220
			if (ENABLE_DEBUG) {
221
				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) . ')');
222
			}
223
		}
224
	}
225
226
	public static function fetchVarInfo() {
227
		self::$db->query('SELECT * FROM active_session WHERE session_id = ' . self::$db->escapeString(self::$session_id) . ' LIMIT 1');
228
		if (self::$db->nextRecord()) {
229
			self::$generate = false;
230
			self::$session_id = self::$db->getField('session_id');
231
			self::$account_id = self::$db->getInt('account_id');
232
			self::$game_id = self::$db->getInt('game_id');
233
			self::$last_accessed = self::$db->getInt('last_accessed');
234
			self::$commonIDs = array();
235
			self::$lastSN = self::$db->getField('last_sn');
236
			// We may not have ajax_returns if ajax was disabled
237
			$ajaxReturns = self::$db->getField('ajax_returns');
238
			if (!empty($ajaxReturns)) {
239
				self::$previousAjaxReturns = unserialize(gzuncompress($ajaxReturns));
240
			}
241
			self::$var = self::$db->getField('session_var');
242
			if (self::$var != '') {
243
				self::$var = unserialize(gzuncompress(self::$var));
244
			}
245
			if (!is_array(self::$var)) {
246
				self::$account_id = 0;
247
				self::$game_id = 0;
248
				self::$var = array();
249
			} else {
250
				foreach (self::$var as $key => &$value) {
251
					if ($value['Expires'] > 0 && $value['Expires'] <= self::getTime()) { // Use 0 for infinity
252
						//This link is no longer valid
253
						unset(self::$var[$key]);
254
					} elseif ($value['RemainingPageLoads'] < 0) {
255
						//This link is no longer valid
256
						unset(self::$var[$key]);
257
					} else {
258
						--$value['RemainingPageLoads'];
259
						if (isset($value['CommonID'])) {
260
							self::$commonIDs[$value['CommonID']] = $key;
261
						}
262
					}
263
				} unset($value);
264
			}
265
		} else {
266
			self::$generate = true;
267
			self::$account_id = 0;
268
			self::$game_id = 0;
269
			self::$var = array();
270
			self::$commonIDs = array();
271
		}
272
	}
273
274
	public static function update() {
275
		foreach (self::$var as $key => &$value) {
276
			if ($value['RemainingPageLoads'] <= 0) {
277
				//This link was valid this load but will not be in the future, removing it now saves database space and data transfer.
278
				unset(self::$var[$key]);
279
			}
280
		} unset($value);
281
		$compressed = gzcompress(serialize(self::$var));
282
		if (!self::$generate) {
283
			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(self::getTime()) : '') . ',session_var=' . self::$db->escapeBinary($compressed) .
284
					',last_sn=' . self::$db->escapeString(self::$SN) .
285
					' WHERE session_id=' . self::$db->escapeString(self::$session_id) . (USING_AJAX ? ' AND last_sn=' . self::$db->escapeString(self::$lastSN) : '') . ' LIMIT 1');
286
		} else {
287
			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));
288
			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(self::getTime()) . ',' . self::$db->escapeBinary($compressed) . ')');
289
			self::$generate = false;
290
		}
291
	}
292
293
	/**
294
	 * Returns the Game ID associated with the session.
295
	 */
296
	public static function getGameID() {
297
		return self::$game_id;
298
	}
299
300
	/**
301
	 * Returns true if the session is inside a game, false otherwise.
302
	 */
303
	public static function hasGame() {
304
		return self::$game_id != 0;
305
	}
306
307
	public static function hasAccount() {
308
		return self::$account_id > 0;
309
	}
310
311
	public static function getAccountID() {
312
		return self::$account_id;
313
	}
314
315
	public static function getAccount() {
316
		return SmrAccount::getAccount(self::$account_id);
317
	}
318
319
	/**
320
	 * Sets the `account_id` attribute of this session.
321
	 */
322
	public static function setAccount(AbstractSmrAccount $account) {
323
		self::$account_id = $account->getAccountID();
324
	}
325
326
	/**
327
	 * Updates the `game_id` attribute of the session and deletes any other
328
	 * active sessions in this game for this account.
329
	 */
330
	public static function updateGame($gameID) {
331
		if (self::$game_id == $gameID) {
332
			return;
333
		}
334
		self::$game_id = $gameID;
335
		self::$db->query('DELETE FROM active_session WHERE account_id = ' . self::$db->escapeNumber(self::$account_id) . ' AND game_id = ' . self::$game_id);
336
		self::$db->query('UPDATE active_session SET game_id=' . self::$db->escapeNumber(self::$game_id) . ' WHERE session_id=' . self::$db->escapeString(self::$session_id));
337
	}
338
339
	/**
340
	 * Returns true if the current SN is different than the previous SN.
341
	 */
342
	public static function hasChangedSN() {
343
		return self::$SN != self::$lastSN;
344
	}
345
346
	private static function updateSN() {
347
		if (!USING_AJAX) {
348
			self::$db->query('UPDATE active_session SET last_sn=' . self::$db->escapeString(self::$SN) .
349
				' WHERE session_id=' . self::$db->escapeString(self::$session_id) . ' LIMIT 1');
350
		}
351
	}
352
353
	public static function destroy() {
354
		self::$db->query('DELETE FROM active_session WHERE session_id = ' . self::$db->escapeString(self::$session_id));
355
		self::$session_id = null;
356
		self::$account_id = 0;
357
		self::$game_id = 0;
358
	}
359
360
	/**
361
	 * Retrieve the session var for the page given by $sn.
362
	 * If $sn is not specified, use the current page (i.e. self::$SN).
363
	 */
364
	public static function retrieveVar($sn = null) {
365
		if (is_null($sn)) {
366
			$sn = self::$SN;
367
		}
368
		if (empty(self::$var[$sn])) {
369
			return false;
370
		}
371
		self::$SN = $sn;
372
		SmrSession::updateSN();
373
		if (isset(self::$var[$sn]['body']) && isset(self::$var[$sn]['CommonID'])) {
374
//			if(preg_match('/processing/',self::$var[$sn]['body']))
375
			unset(self::$commonIDs[self::$var[$sn]['CommonID']]); //Do not store common id for current page
376
			unset(self::$var[$sn]['CommonID']);
377
		}
378
379
		self::$var[$sn]['RemainingPageLoads'] += 1; // Allow refreshing
380
		self::$var[$sn]['Expires'] = 0; // Allow refreshing forever
381
		return self::$var[$sn];
382
	}
383
384
	/**
385
	 * Gets a var from $var, $_REQUEST, or $default. Then stores it in the
386
	 * session so that it can still be retrieved when the page auto-refreshes.
387
	 * This is the recommended way to get $_REQUEST data for display pages.
388
	 * For processing pages, see the Request class.
389
	 */
390
	public static function getRequestVar(string $varName, string $default = null) : string {
391
		$result = Request::getVar($varName, $default);
392
		self::updateVar($varName, $result);
393
		return $result;
394
	}
395
396
	public static function getRequestVarInt(string $varName, int $default = null) : int {
397
		$result = Request::getVarInt($varName, $default);
398
		self::updateVar($varName, $result);
399
		return $result;
400
	}
401
402
	public static function getRequestVarIntArray(string $varName, array $default = null) : array {
403
		$result = Request::getVarIntArray($varName, $default);
404
		self::updateVar($varName, $result);
405
		return $result;
406
	}
407
408
	public static function resetLink($container, $sn) { //Do not allow sharing SN, useful for forwarding.
409
		global $lock;
410
		if (isset(self::$var[$sn]['CommonID'])) {
411
			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
412
		}
413
		self::$SN = $sn;
414
		if (!isset($container['Expires'])) {
415
			$container['Expires'] = 0; // Lasts forever
416
		}
417
		if (!isset($container['RemainingPageLoads'])) {
418
			$container['RemainingPageLoads'] = 1; // Allow refreshing
419
		}
420
		if (!isset($container['PreviousRequestTime'])) {
421
			if (isset(self::$var[$sn]['PreviousRequestTime'])) {
422
				$container['PreviousRequestTime'] = self::$var[$sn]['PreviousRequestTime']; // Copy across the previous request time if not explicitly set.
423
			}
424
		}
425
426
		self::$var[$sn] = $container;
427
		if (!$lock && !USING_AJAX) {
428
			self::update();
429
		}
430
		return $sn;
431
	}
432
433
	public static function updateVar($key, $value) {
434
		global $var;
435
		if ($value === null) {
436
			unset($var[$key]);
437
			unset(self::$var[self::$SN][$key]);
438
		} else {
439
			$var[$key] = $value;
440
			self::$var[self::$SN][$key] = $value;
441
		}
442
	}
443
444
	public static function clearLinks() {
445
		self::$var = array(self::$SN => self::$var[self::$SN]);
446
		self::$commonIDs = array();
447
	}
448
449
	protected 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.
450
		if (!isset($container['Expires'])) {
451
			$container['Expires'] = 0; // Lasts forever
452
		}
453
		if (!isset($container['RemainingPageLoads'])) {
454
			$pageURL = $container['url'] == 'skeleton.php' ? $container['body'] : $container['url'];
455
			$container['RemainingPageLoads'] = self::URL_DEFAULT_REMAINING_PAGE_LOADS[$pageURL] ?? 1; // Allow refreshing
456
		}
457
458
		if ($sn === false) {
459
			$sn = self::generateSN($container);
460
		} else {
461
			// If we've been provided an SN to use then copy over the existing 'PreviousRequestTime'
462
			$container['PreviousRequestTime'] = self::$var[$sn]['PreviousRequestTime'];
463
		}
464
		self::$var[$sn] = $container;
465
		return $sn;
466
	}
467
468
	protected static function generateSN(&$container) {
469
		$container['CommonID'] = self::getCommonID($container);
470
		if (isset(self::$commonIDs[$container['CommonID']])) {
471
			$sn = self::$commonIDs[$container['CommonID']];
472
			$container['PreviousRequestTime'] = isset(self::$var[$sn]) ? self::$var[$sn]['PreviousRequestTime'] : self::getMicroTime();
473
		} else {
474
			do {
475
				$sn = substr(md5(strval(rand())), 0, 8);
476
			} while (isset(self::$var[$sn]));
477
			$container['PreviousRequestTime'] = self::getMicroTime();
478
		}
479
		self::$commonIDs[$container['CommonID']] = $sn;
480
		return $sn;
481
	}
482
483
	protected static function getCommonID($commonContainer) {
484
		unset($commonContainer['Expires']);
485
		unset($commonContainer['RemainingPageLoads']);
486
		unset($commonContainer['PreviousRequestTime']);
487
		unset($commonContainer['CommonID']);
488
		// NOTE: This ID will change if the order of elements in the container
489
		// changes. If this causes unnecessary SN changes, sort the container!
490
		return md5(serialize($commonContainer));
491
	}
492
493
	public static function getNewHREF($container, $forceFullURL = false) {
494
		$sn = self::addLink($container);
495
		if ($forceFullURL === true || stripos($_SERVER['REQUEST_URI'], 'loader.php') === false) {
496
			return '/loader.php?sn=' . $sn;
497
		}
498
		return '?sn=' . $sn;
499
	}
500
501
	public static function addAjaxReturns($element, $contents) {
502
		self::$ajaxReturns[$element] = $contents;
503
		return isset(self::$previousAjaxReturns[$element]) && self::$previousAjaxReturns[$element] == $contents;
504
	}
505
506
	public static function saveAjaxReturns() {
507
		if (empty(self::$ajaxReturns)) {
508
			return;
509
		}
510
		$compressed = gzcompress(serialize(self::$ajaxReturns));
511
		self::$db->query('UPDATE active_session SET ajax_returns=' . self::$db->escapeBinary($compressed) .
512
				' WHERE session_id=' . self::$db->escapeString(self::$session_id) . ' LIMIT 1');
513
	}
514
}
515
516
SmrSession::init();
517