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

Failed Conditions
Pull Request — main (#1446)
by Dan
06:16
created

src/bootstrap.php (1 issue)

Labels
Severity
1
<?php declare(strict_types=1);
2
3
use Smr\Container\DiContainer;
4
use Smr\Exceptions\UserError;
5
use Smr\SectorLock;
6
use Smr\Session;
7
8
function logException(Throwable $e): void {
9
	$message = '';
10
	$delim = "\n\n-----------\n\n";
11
12
	$message .= 'Error Message: ' . $e . $delim;
13
14
	if (DiContainer::initialized(Session::class)) {
15
		$session = Session::getInstance();
16
17
		if ($session->hasAccount()) {
18
			$account = $session->getAccount();
19
			$message .= 'Login: ' . $account->getLogin() . "\n" .
20
				'E-Mail: ' . $account->getEmail() . "\n" .
21
				'Account ID: ' . $account->getAccountID();
22
			if ($session->hasGame()) {
23
				$message .= "\n" .
24
					'Game ID: ' . $session->getGameID() . "\n" .
25
					'Sector ID: ' . $session->getPlayer()->getSectorID();
26
			}
27
			$message .= $delim;
28
		}
29
30
		$var = $session->hasCurrentVar() ? $session->getCurrentVar() : null;
31
		$message .= '$var: ' . print_r($var, true) . $delim;
32
	}
33
34
	// Don't display passwords input by users in the log message!
35
	if (isset($_REQUEST['password'])) {
36
		$_REQUEST['password'] = '*****';
37
	}
38
	$message .= '$_REQUEST: ' . var_export($_REQUEST, true);
39
	$message .= $delim;
40
41
	$message .=
42
		'User IP: ' . getIpAddress() . "\n" .
43
		'User Agent: ' . ($_SERVER['HTTP_USER_AGENT'] ?? 'undefined') . "\n" .
44
		'USING_AJAX: ' . (defined('USING_AJAX') ? var_export(USING_AJAX, true) : 'undefined') . "\n" .
45
		'URL: ' . (defined('URL') ? URL : 'undefined');
46
47
	// Try to release lock so they can carry on normally
48
	if (DiContainer::initialized(SectorLock::class)) {
49
		try {
50
			SectorLock::getInstance()->release();
51
		} catch (Throwable $ee) {
52
			$message .= $delim .
53
					'Releasing Lock Failed' . "\n" .
54
					'Message: ' . $ee . "\n";
55
		}
56
	}
57
58
	if (defined('SCRIPT_ID')) {
59
		$message = 'Script: ' . SCRIPT_ID . $delim . $message . "\n\n";
60
	}
61
62
	// Unconditionally send error message to the log
63
	error_log($message);
64
65
	if (ENABLE_DEBUG) {
66
		// Display error message on the page (redundant with error_log for CLI)
67
		if (PHP_SAPI !== 'cli') {
68
			echo '<pre>' . $message . '</pre>';
69
		}
70
		// Skip remaining log methods (too disruptive during development)
71
		return;
72
	}
73
74
	// Send error message to the in-game auto bugs mailbox
75
	if (isset($session) && $session->hasGame()) {
76
		$session->getPlayer()->sendMessageToBox(BOX_BUGS_AUTO, $message);
77
	} elseif (isset($session) && $session->hasAccount()) {
78
		// Will be logged without a game_id
79
		$session->getAccount()->sendMessageToBox(BOX_BUGS_AUTO, $message);
80
	} else {
81
		// Will be logged without a game_id or sender_id
82
		SmrAccount::doMessageSendingToBox(0, BOX_BUGS_AUTO, $message, 0);
83
	}
84
85
	// Send error message to e-mail so that we have a permanent record
86
	if (!empty(BUG_REPORT_TO_ADDRESSES)) {
87
		$mail = setupMailer();
88
		$mail->Subject = (defined('PAGE_PREFIX') ? PAGE_PREFIX : '??? ') .
89
		                 'Automatic Bug Report';
90
		$mail->setFrom('[email protected]');
91
		$mail->Body = $message;
92
		foreach (BUG_REPORT_TO_ADDRESSES as $toAddress) {
93
			$mail->addAddress($toAddress);
94
		}
95
		$mail->send();
96
	}
97
}
98
99
/**
100
 * Handles all user-facing exceptions.
101
 *
102
 * If the error is fatal, the exception is logged and the player is redirected
103
 * to an appropriate error page.
104
 *
105
 * If the error is just informational (e.g. the user input an invalid value),
106
 * then the message is displayed on the page without being logged.
107
 */
108
function handleException(Throwable $e): void {
109
	// The real error message may display sensitive information, so we
110
	// need to catch any exceptions that are thrown while logging the error.
111
	try {
112
		if ($e instanceof UserError) {
113
			handleUserError($e->getMessage());
114
		}
115
		logException($e);
116
		$errorType = 'Unexpected Error!';
117
	} catch (Throwable $e2) {
118
		error_log('Original exception: ' . $e);
119
		error_log('Exception during logException: ' . $e2);
120
		$errorType = 'This error cannot be automatically reported. Please notify an admin!';
121
	}
122
123
	// If this is an ajax update, we don't really have a way to redirect
124
	// to an error page at this time.
125
	if (!ENABLE_DEBUG && (!defined('USING_AJAX') || !USING_AJAX)) {
126
		header('location: /error.php?msg=' . urlencode($errorType));
127
	}
128
}
129
130
/**
131
 * Can be used to convert any type of notice into an exception.
132
 */
133
function exception_error_handler(int $errno, string $errstr, string $errfile, int $errline): bool {
134
	if (!(error_reporting() & $errno)) {
135
		return false; // error is suppressed
136
	}
137
	throw new ErrorException($errstr, $errno, E_ERROR, $errfile, $errline);
138
}
139
140
function setupMailer(): \PHPMailer\PHPMailer\PHPMailer {
141
	$mail = new \PHPMailer\PHPMailer\PHPMailer(true);
142
	if (!empty(SMTP_HOSTNAME)) {
143
		$mail->isSMTP();
144
		$mail->Host = SMTP_HOSTNAME;
145
	}
146
	return $mail;
147
}
148
149
function getIpAddress(): string {
150
	foreach (['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR'] as $key) {
151
		if (array_key_exists($key, $_SERVER) === true) {
152
			foreach (explode(',', $_SERVER[$key]) as $ip) {
153
				if (filter_var($ip, FILTER_VALIDATE_IP) !== false) {
154
					return $ip;
155
				}
156
			}
157
		}
158
	}
159
	return 'unknown';
160
}
161
162
/**
163
 * Wrapper around the floor() builtin for returning an integer type.
164
 */
165
function IFloor(float $val): int {
166
	return (int)floor($val);
167
}
168
169
/**
170
 * Wrapper around the ceil() builtin for returning an integer type.
171
 */
172
function ICeil(float $val): int {
173
	return (int)ceil($val);
174
}
175
176
/**
177
 * Wrapper around the round() builtin for returning an integer type.
178
 */
179
function IRound(float $val): int {
180
	return (int)round($val);
181
}
182
183
/**
184
 * Convert a numeric string to an int with input validation.
185
 */
186
function str2int(string $val): int {
187
	$result = filter_var($val, FILTER_VALIDATE_INT);
188
	if ($result === false) {
189
		throw new Exception('Input value is not an integer: ' . $val);
190
	}
191
	return $result;
192
}
193
194
/**
195
 * Generate a cryptographically strong random hexadecimal string.
196
 * The requested length must be a multiple of 2.
197
 */
198
function random_string(int $length): string {
199
	if ($length % 2 != 0) {
200
		throw new Exception('Length must be a multiple of 2!');
201
	}
202
	return bin2hex(random_bytes($length / 2));
203
}
204
205
/**
206
 * Generate a (non-cryptographic) random alphabetic string.
207
 * This is slower for longer strings.
208
 */
209
function random_alphabetic_string(int $length): string {
210
	$result = '';
211
	for ($i = 0; $i < $length; ++$i) {
212
		$result .= chr(rand(ord('a'), ord('z')));
213
	}
214
	return $result;
215
}
216
217
/**
218
 * Return the value of a random key from an array.
219
 *
220
 * @template T
221
 * @param array<T> $arr
222
 * @return T
223
 */
224
function array_rand_value(array $arr): mixed {
225
	if (empty($arr)) {
226
		throw new Exception('Cannot pick random value from empty array!');
227
	}
228
	return $arr[array_rand($arr)];
229
}
230
231
// Defines all constants
232
require_once('config.php');
233
234
// Set up vendor and class autoloaders
235
require_once(ROOT . 'vendor/autoload.php');
236
require_once(LIB . 'autoload.inc.php');
237
spl_autoload_register(get_class_loc(...));
0 ignored issues
show
A parse error occurred: Syntax error, unexpected ')' on line 237 at column 39
Loading history...
238
239
// Load common functions
240
require_once(LIB . 'Default/smr.inc.php');
241
242
// Set up dependency injection container
243
DiContainer::initialize(getenv('DISABLE_PHPDI_COMPILATION') !== 'true');
244