Completed
Push — newinternal-releasecandidate ( 45827b...b95206 )
by Simon
08:27
created
includes/Tasks/PageBase.php 2 patches
Indentation   +374 added lines, -374 removed lines patch added patch discarded remove patch
@@ -23,378 +23,378 @@
 block discarded – undo
23 23
 
24 24
 abstract class PageBase extends TaskBase implements IRoutedTask
25 25
 {
26
-    use TemplateOutput;
27
-    /** @var string Smarty template to display */
28
-    protected $template = "base.tpl";
29
-    /** @var string HTML title. Currently unused. */
30
-    protected $htmlTitle;
31
-    /** @var bool Determines if the page is a redirect or not */
32
-    protected $isRedirecting = false;
33
-    /** @var array Queue of headers to be sent on successful completion */
34
-    protected $headerQueue = array();
35
-    /** @var string The name of the route to use, as determined by the request router. */
36
-    private $routeName = null;
37
-    /** @var TokenManager */
38
-    protected $tokenManager;
39
-    /** @var ContentSecurityPolicyManager */
40
-    private $cspManager;
41
-    /** @var string[] Extra CSS files to include */
42
-    private $extraCss = array();
43
-    /** @var string[] Extra JS files to include */
44
-    private $extraJs = array();
45
-
46
-    /**
47
-     * Sets the route the request will take. Only should be called from the request router or barrier test.
48
-     *
49
-     * @param string $routeName        The name of the route
50
-     * @param bool   $skipCallableTest Don't use this unless you know what you're doing, and what the implications are.
51
-     *
52
-     * @throws Exception
53
-     * @category Security-Critical
54
-     */
55
-    final public function setRoute($routeName, $skipCallableTest = false)
56
-    {
57
-        // Test the new route is callable before adopting it.
58
-        if (!$skipCallableTest && !is_callable(array($this, $routeName))) {
59
-            throw new Exception("Proposed route '$routeName' is not callable.");
60
-        }
61
-
62
-        // Adopt the new route
63
-        $this->routeName = $routeName;
64
-    }
65
-
66
-    /**
67
-     * Gets the name of the route that has been passed from the request router.
68
-     * @return string
69
-     */
70
-    final public function getRouteName()
71
-    {
72
-        return $this->routeName;
73
-    }
74
-
75
-    /**
76
-     * Performs generic page setup actions
77
-     */
78
-    final protected function setupPage()
79
-    {
80
-        $this->setUpSmarty();
81
-
82
-        $siteNoticeText = SiteNotice::get($this->getDatabase());
83
-
84
-        $this->assign('siteNoticeText', $siteNoticeText);
85
-
86
-        $currentUser = User::getCurrent($this->getDatabase());
87
-        $this->assign('currentUser', $currentUser);
88
-        $this->assign('loggedIn', (!$currentUser->isCommunityUser()));
89
-    }
90
-
91
-    /**
92
-     * Runs the page logic as routed by the RequestRouter
93
-     *
94
-     * Only should be called after a security barrier! That means only from execute().
95
-     */
96
-    final protected function runPage()
97
-    {
98
-        $database = $this->getDatabase();
99
-
100
-        // initialise a database transaction
101
-        if (!$database->beginTransaction()) {
102
-            throw new Exception('Failed to start transaction on primary database.');
103
-        }
104
-
105
-        try {
106
-            // run the page code
107
-            $this->{$this->getRouteName()}();
108
-
109
-            $database->commit();
110
-        }
111
-        catch (ApplicationLogicException $ex) {
112
-            // it's an application logic exception, so nothing went seriously wrong with the site. We can use the
113
-            // standard templating system for this.
114
-
115
-            // Firstly, let's undo anything that happened to the database.
116
-            $database->rollBack();
117
-
118
-            // Reset smarty
119
-            $this->setUpSmarty();
120
-
121
-            // Set the template
122
-            $this->setTemplate('exception/application-logic.tpl');
123
-            $this->assign('message', $ex->getMessage());
124
-
125
-            // Force this back to false
126
-            $this->isRedirecting = false;
127
-            $this->headerQueue = array();
128
-        }
129
-        catch (OptimisticLockFailedException $ex) {
130
-            // it's an optimistic lock failure exception, so nothing went seriously wrong with the site. We can use the
131
-            // standard templating system for this.
132
-
133
-            // Firstly, let's undo anything that happened to the database.
134
-            $database->rollBack();
135
-
136
-            // Reset smarty
137
-            $this->setUpSmarty();
138
-
139
-            // Set the template
140
-            $this->setTemplate('exception/optimistic-lock-failure.tpl');
141
-            $this->assign('message', $ex->getMessage());
142
-
143
-            $this->assign('debugTrace', false);
144
-
145
-            if ($this->getSiteConfiguration()->getDebuggingTraceEnabled()) {
146
-                ob_start();
147
-                var_dump(ExceptionHandler::getExceptionData($ex));
148
-                $textErrorData = ob_get_contents();
149
-                ob_end_clean();
150
-
151
-                $this->assign('exceptionData', $textErrorData);
152
-                $this->assign('debugTrace', true);
153
-            }
154
-
155
-            // Force this back to false
156
-            $this->isRedirecting = false;
157
-            $this->headerQueue = array();
158
-        }
159
-        finally {
160
-            // Catch any hanging on transactions
161
-            if ($database->hasActiveTransaction()) {
162
-                $database->rollBack();
163
-            }
164
-        }
165
-
166
-        // run any finalisation code needed before we send the output to the browser.
167
-        $this->finalisePage();
168
-
169
-        // Send the headers
170
-        $this->sendResponseHeaders();
171
-
172
-        // Check we have a template to use!
173
-        if ($this->template !== null) {
174
-            $content = $this->fetchTemplate($this->template);
175
-            ob_clean();
176
-            print($content);
177
-            ob_flush();
178
-
179
-            return;
180
-        }
181
-    }
182
-
183
-    /**
184
-     * Performs final tasks needed before rendering the page.
185
-     */
186
-    protected function finalisePage()
187
-    {
188
-        if ($this->isRedirecting) {
189
-            $this->template = null;
190
-
191
-            return;
192
-        }
193
-
194
-        $this->assign('extraCss', $this->extraCss);
195
-        $this->assign('extraJs', $this->extraJs);
196
-
197
-        // If we're actually displaying content, we want to add the session alerts here!
198
-        $this->assign('alerts', SessionAlert::getAlerts());
199
-        SessionAlert::clearAlerts();
200
-
201
-        $this->assign('htmlTitle', $this->htmlTitle);
202
-    }
203
-
204
-    /**
205
-     * @return TokenManager
206
-     */
207
-    public function getTokenManager()
208
-    {
209
-        return $this->tokenManager;
210
-    }
211
-
212
-    /**
213
-     * @param TokenManager $tokenManager
214
-     */
215
-    public function setTokenManager($tokenManager)
216
-    {
217
-        $this->tokenManager = $tokenManager;
218
-    }
219
-
220
-    /**
221
-     * @return ContentSecurityPolicyManager
222
-     */
223
-    public function getCspManager(): ContentSecurityPolicyManager
224
-    {
225
-        return $this->cspManager;
226
-    }
227
-
228
-    /**
229
-     * @param ContentSecurityPolicyManager $cspManager
230
-     */
231
-    public function setCspManager(ContentSecurityPolicyManager $cspManager): void
232
-    {
233
-        $this->cspManager = $cspManager;
234
-    }
235
-
236
-    /**
237
-     * Sends the redirect headers to perform a GET at the destination page.
238
-     *
239
-     * Also nullifies the set template so Smarty does not render it.
240
-     *
241
-     * @param string      $page   The page to redirect requests to (as used in the UR)
242
-     * @param null|string $action The action to use on the page.
243
-     * @param null|array  $parameters
244
-     * @param null|string $script The script (relative to index.php) to redirect to
245
-     */
246
-    final protected function redirect($page = '', $action = null, $parameters = null, $script = null)
247
-    {
248
-        $currentScriptName = WebRequest::scriptName();
249
-
250
-        // Are we changing script?
251
-        if ($script === null || substr($currentScriptName, -1 * count($script)) === $script) {
252
-            $targetScriptName = $currentScriptName;
253
-        }
254
-        else {
255
-            $targetScriptName = $this->getSiteConfiguration()->getBaseUrl() . '/' . $script;
256
-        }
257
-
258
-        $pathInfo = array($targetScriptName);
259
-
260
-        $pathInfo[1] = $page;
261
-
262
-        if ($action !== null) {
263
-            $pathInfo[2] = $action;
264
-        }
265
-
266
-        $url = implode('/', $pathInfo);
267
-
268
-        if (is_array($parameters) && count($parameters) > 0) {
269
-            $url .= '?' . http_build_query($parameters);
270
-        }
271
-
272
-        $this->redirectUrl($url);
273
-    }
274
-
275
-    /**
276
-     * Sends the redirect headers to perform a GET at the new address.
277
-     *
278
-     * Also nullifies the set template so Smarty does not render it.
279
-     *
280
-     * @param string $path URL to redirect to
281
-     */
282
-    final protected function redirectUrl($path)
283
-    {
284
-        // 303 See Other = re-request at new address with a GET.
285
-        $this->headerQueue[] = 'HTTP/1.1 303 See Other';
286
-        $this->headerQueue[] = "Location: $path";
287
-
288
-        $this->setTemplate(null);
289
-        $this->isRedirecting = true;
290
-    }
291
-
292
-    /**
293
-     * Sets the name of the template this page should display.
294
-     *
295
-     * @param string $name
296
-     *
297
-     * @throws Exception
298
-     */
299
-    final protected function setTemplate($name)
300
-    {
301
-        if ($this->isRedirecting) {
302
-            throw new Exception('This page has been set as a redirect, no template can be displayed!');
303
-        }
304
-
305
-        $this->template = $name;
306
-    }
307
-
308
-    /**
309
-     * Adds an extra CSS file to to the page
310
-     *
311
-     * @param string $path The path (relative to the application root) of the file
312
-     */
313
-    final protected function addCss($path) {
314
-        if(in_array($path, $this->extraCss)){
315
-            // nothing to do
316
-            return;
317
-        }
318
-
319
-        $this->extraCss[] = $path;
320
-    }
321
-
322
-    /**
323
-     * Adds an extra JS file to to the page
324
-     *
325
-     * @param string $path The path (relative to the application root) of the file
326
-     */
327
-    final protected function addJs($path){
328
-        if(in_array($path, $this->extraJs)){
329
-            // nothing to do
330
-            return;
331
-        }
332
-
333
-        $this->extraJs[] = $path;
334
-    }
335
-
336
-    /**
337
-     * Main function for this page, when no specific actions are called.
338
-     * @return void
339
-     */
340
-    abstract protected function main();
341
-
342
-    /**
343
-     * Takes a smarty template string and sets the HTML title to that value
344
-     *
345
-     * @param string $title
346
-     *
347
-     * @throws SmartyException
348
-     */
349
-    final protected function setHtmlTitle($title)
350
-    {
351
-        $this->htmlTitle = $this->smarty->fetch('string:' . $title);
352
-    }
353
-
354
-    public function execute()
355
-    {
356
-        if ($this->getRouteName() === null) {
357
-            throw new Exception('Request is unrouted.');
358
-        }
359
-
360
-        if ($this->getSiteConfiguration() === null) {
361
-            throw new Exception('Page has no configuration!');
362
-        }
363
-
364
-        $this->setupPage();
365
-
366
-        $this->runPage();
367
-    }
368
-
369
-    public function assignCSRFToken()
370
-    {
371
-        $token = $this->tokenManager->getNewToken();
372
-        $this->assign('csrfTokenData', $token->getTokenData());
373
-    }
374
-
375
-    public function validateCSRFToken()
376
-    {
377
-        if (!$this->tokenManager->validateToken(WebRequest::postString('csrfTokenData'))) {
378
-            throw new ApplicationLogicException('Form token is not valid, please reload and try again');
379
-        }
380
-    }
381
-
382
-    protected function sendResponseHeaders()
383
-    {
384
-        if (headers_sent()) {
385
-            throw new ApplicationLogicException('Headers have already been sent! This is likely a bug in the application.');
386
-        }
387
-
388
-        // send the CSP headers now
389
-        header($this->getCspManager()->getHeader());
390
-
391
-        foreach ($this->headerQueue as $item) {
392
-            if (mb_strpos($item, "\r") !== false || mb_strpos($item, "\n") !== false) {
393
-                // Oops. We're not allowed to do this.
394
-                throw new Exception('Unable to split header');
395
-            }
396
-
397
-            header($item);
398
-        }
399
-    }
26
+	use TemplateOutput;
27
+	/** @var string Smarty template to display */
28
+	protected $template = "base.tpl";
29
+	/** @var string HTML title. Currently unused. */
30
+	protected $htmlTitle;
31
+	/** @var bool Determines if the page is a redirect or not */
32
+	protected $isRedirecting = false;
33
+	/** @var array Queue of headers to be sent on successful completion */
34
+	protected $headerQueue = array();
35
+	/** @var string The name of the route to use, as determined by the request router. */
36
+	private $routeName = null;
37
+	/** @var TokenManager */
38
+	protected $tokenManager;
39
+	/** @var ContentSecurityPolicyManager */
40
+	private $cspManager;
41
+	/** @var string[] Extra CSS files to include */
42
+	private $extraCss = array();
43
+	/** @var string[] Extra JS files to include */
44
+	private $extraJs = array();
45
+
46
+	/**
47
+	 * Sets the route the request will take. Only should be called from the request router or barrier test.
48
+	 *
49
+	 * @param string $routeName        The name of the route
50
+	 * @param bool   $skipCallableTest Don't use this unless you know what you're doing, and what the implications are.
51
+	 *
52
+	 * @throws Exception
53
+	 * @category Security-Critical
54
+	 */
55
+	final public function setRoute($routeName, $skipCallableTest = false)
56
+	{
57
+		// Test the new route is callable before adopting it.
58
+		if (!$skipCallableTest && !is_callable(array($this, $routeName))) {
59
+			throw new Exception("Proposed route '$routeName' is not callable.");
60
+		}
61
+
62
+		// Adopt the new route
63
+		$this->routeName = $routeName;
64
+	}
65
+
66
+	/**
67
+	 * Gets the name of the route that has been passed from the request router.
68
+	 * @return string
69
+	 */
70
+	final public function getRouteName()
71
+	{
72
+		return $this->routeName;
73
+	}
74
+
75
+	/**
76
+	 * Performs generic page setup actions
77
+	 */
78
+	final protected function setupPage()
79
+	{
80
+		$this->setUpSmarty();
81
+
82
+		$siteNoticeText = SiteNotice::get($this->getDatabase());
83
+
84
+		$this->assign('siteNoticeText', $siteNoticeText);
85
+
86
+		$currentUser = User::getCurrent($this->getDatabase());
87
+		$this->assign('currentUser', $currentUser);
88
+		$this->assign('loggedIn', (!$currentUser->isCommunityUser()));
89
+	}
90
+
91
+	/**
92
+	 * Runs the page logic as routed by the RequestRouter
93
+	 *
94
+	 * Only should be called after a security barrier! That means only from execute().
95
+	 */
96
+	final protected function runPage()
97
+	{
98
+		$database = $this->getDatabase();
99
+
100
+		// initialise a database transaction
101
+		if (!$database->beginTransaction()) {
102
+			throw new Exception('Failed to start transaction on primary database.');
103
+		}
104
+
105
+		try {
106
+			// run the page code
107
+			$this->{$this->getRouteName()}();
108
+
109
+			$database->commit();
110
+		}
111
+		catch (ApplicationLogicException $ex) {
112
+			// it's an application logic exception, so nothing went seriously wrong with the site. We can use the
113
+			// standard templating system for this.
114
+
115
+			// Firstly, let's undo anything that happened to the database.
116
+			$database->rollBack();
117
+
118
+			// Reset smarty
119
+			$this->setUpSmarty();
120
+
121
+			// Set the template
122
+			$this->setTemplate('exception/application-logic.tpl');
123
+			$this->assign('message', $ex->getMessage());
124
+
125
+			// Force this back to false
126
+			$this->isRedirecting = false;
127
+			$this->headerQueue = array();
128
+		}
129
+		catch (OptimisticLockFailedException $ex) {
130
+			// it's an optimistic lock failure exception, so nothing went seriously wrong with the site. We can use the
131
+			// standard templating system for this.
132
+
133
+			// Firstly, let's undo anything that happened to the database.
134
+			$database->rollBack();
135
+
136
+			// Reset smarty
137
+			$this->setUpSmarty();
138
+
139
+			// Set the template
140
+			$this->setTemplate('exception/optimistic-lock-failure.tpl');
141
+			$this->assign('message', $ex->getMessage());
142
+
143
+			$this->assign('debugTrace', false);
144
+
145
+			if ($this->getSiteConfiguration()->getDebuggingTraceEnabled()) {
146
+				ob_start();
147
+				var_dump(ExceptionHandler::getExceptionData($ex));
148
+				$textErrorData = ob_get_contents();
149
+				ob_end_clean();
150
+
151
+				$this->assign('exceptionData', $textErrorData);
152
+				$this->assign('debugTrace', true);
153
+			}
154
+
155
+			// Force this back to false
156
+			$this->isRedirecting = false;
157
+			$this->headerQueue = array();
158
+		}
159
+		finally {
160
+			// Catch any hanging on transactions
161
+			if ($database->hasActiveTransaction()) {
162
+				$database->rollBack();
163
+			}
164
+		}
165
+
166
+		// run any finalisation code needed before we send the output to the browser.
167
+		$this->finalisePage();
168
+
169
+		// Send the headers
170
+		$this->sendResponseHeaders();
171
+
172
+		// Check we have a template to use!
173
+		if ($this->template !== null) {
174
+			$content = $this->fetchTemplate($this->template);
175
+			ob_clean();
176
+			print($content);
177
+			ob_flush();
178
+
179
+			return;
180
+		}
181
+	}
182
+
183
+	/**
184
+	 * Performs final tasks needed before rendering the page.
185
+	 */
186
+	protected function finalisePage()
187
+	{
188
+		if ($this->isRedirecting) {
189
+			$this->template = null;
190
+
191
+			return;
192
+		}
193
+
194
+		$this->assign('extraCss', $this->extraCss);
195
+		$this->assign('extraJs', $this->extraJs);
196
+
197
+		// If we're actually displaying content, we want to add the session alerts here!
198
+		$this->assign('alerts', SessionAlert::getAlerts());
199
+		SessionAlert::clearAlerts();
200
+
201
+		$this->assign('htmlTitle', $this->htmlTitle);
202
+	}
203
+
204
+	/**
205
+	 * @return TokenManager
206
+	 */
207
+	public function getTokenManager()
208
+	{
209
+		return $this->tokenManager;
210
+	}
211
+
212
+	/**
213
+	 * @param TokenManager $tokenManager
214
+	 */
215
+	public function setTokenManager($tokenManager)
216
+	{
217
+		$this->tokenManager = $tokenManager;
218
+	}
219
+
220
+	/**
221
+	 * @return ContentSecurityPolicyManager
222
+	 */
223
+	public function getCspManager(): ContentSecurityPolicyManager
224
+	{
225
+		return $this->cspManager;
226
+	}
227
+
228
+	/**
229
+	 * @param ContentSecurityPolicyManager $cspManager
230
+	 */
231
+	public function setCspManager(ContentSecurityPolicyManager $cspManager): void
232
+	{
233
+		$this->cspManager = $cspManager;
234
+	}
235
+
236
+	/**
237
+	 * Sends the redirect headers to perform a GET at the destination page.
238
+	 *
239
+	 * Also nullifies the set template so Smarty does not render it.
240
+	 *
241
+	 * @param string      $page   The page to redirect requests to (as used in the UR)
242
+	 * @param null|string $action The action to use on the page.
243
+	 * @param null|array  $parameters
244
+	 * @param null|string $script The script (relative to index.php) to redirect to
245
+	 */
246
+	final protected function redirect($page = '', $action = null, $parameters = null, $script = null)
247
+	{
248
+		$currentScriptName = WebRequest::scriptName();
249
+
250
+		// Are we changing script?
251
+		if ($script === null || substr($currentScriptName, -1 * count($script)) === $script) {
252
+			$targetScriptName = $currentScriptName;
253
+		}
254
+		else {
255
+			$targetScriptName = $this->getSiteConfiguration()->getBaseUrl() . '/' . $script;
256
+		}
257
+
258
+		$pathInfo = array($targetScriptName);
259
+
260
+		$pathInfo[1] = $page;
261
+
262
+		if ($action !== null) {
263
+			$pathInfo[2] = $action;
264
+		}
265
+
266
+		$url = implode('/', $pathInfo);
267
+
268
+		if (is_array($parameters) && count($parameters) > 0) {
269
+			$url .= '?' . http_build_query($parameters);
270
+		}
271
+
272
+		$this->redirectUrl($url);
273
+	}
274
+
275
+	/**
276
+	 * Sends the redirect headers to perform a GET at the new address.
277
+	 *
278
+	 * Also nullifies the set template so Smarty does not render it.
279
+	 *
280
+	 * @param string $path URL to redirect to
281
+	 */
282
+	final protected function redirectUrl($path)
283
+	{
284
+		// 303 See Other = re-request at new address with a GET.
285
+		$this->headerQueue[] = 'HTTP/1.1 303 See Other';
286
+		$this->headerQueue[] = "Location: $path";
287
+
288
+		$this->setTemplate(null);
289
+		$this->isRedirecting = true;
290
+	}
291
+
292
+	/**
293
+	 * Sets the name of the template this page should display.
294
+	 *
295
+	 * @param string $name
296
+	 *
297
+	 * @throws Exception
298
+	 */
299
+	final protected function setTemplate($name)
300
+	{
301
+		if ($this->isRedirecting) {
302
+			throw new Exception('This page has been set as a redirect, no template can be displayed!');
303
+		}
304
+
305
+		$this->template = $name;
306
+	}
307
+
308
+	/**
309
+	 * Adds an extra CSS file to to the page
310
+	 *
311
+	 * @param string $path The path (relative to the application root) of the file
312
+	 */
313
+	final protected function addCss($path) {
314
+		if(in_array($path, $this->extraCss)){
315
+			// nothing to do
316
+			return;
317
+		}
318
+
319
+		$this->extraCss[] = $path;
320
+	}
321
+
322
+	/**
323
+	 * Adds an extra JS file to to the page
324
+	 *
325
+	 * @param string $path The path (relative to the application root) of the file
326
+	 */
327
+	final protected function addJs($path){
328
+		if(in_array($path, $this->extraJs)){
329
+			// nothing to do
330
+			return;
331
+		}
332
+
333
+		$this->extraJs[] = $path;
334
+	}
335
+
336
+	/**
337
+	 * Main function for this page, when no specific actions are called.
338
+	 * @return void
339
+	 */
340
+	abstract protected function main();
341
+
342
+	/**
343
+	 * Takes a smarty template string and sets the HTML title to that value
344
+	 *
345
+	 * @param string $title
346
+	 *
347
+	 * @throws SmartyException
348
+	 */
349
+	final protected function setHtmlTitle($title)
350
+	{
351
+		$this->htmlTitle = $this->smarty->fetch('string:' . $title);
352
+	}
353
+
354
+	public function execute()
355
+	{
356
+		if ($this->getRouteName() === null) {
357
+			throw new Exception('Request is unrouted.');
358
+		}
359
+
360
+		if ($this->getSiteConfiguration() === null) {
361
+			throw new Exception('Page has no configuration!');
362
+		}
363
+
364
+		$this->setupPage();
365
+
366
+		$this->runPage();
367
+	}
368
+
369
+	public function assignCSRFToken()
370
+	{
371
+		$token = $this->tokenManager->getNewToken();
372
+		$this->assign('csrfTokenData', $token->getTokenData());
373
+	}
374
+
375
+	public function validateCSRFToken()
376
+	{
377
+		if (!$this->tokenManager->validateToken(WebRequest::postString('csrfTokenData'))) {
378
+			throw new ApplicationLogicException('Form token is not valid, please reload and try again');
379
+		}
380
+	}
381
+
382
+	protected function sendResponseHeaders()
383
+	{
384
+		if (headers_sent()) {
385
+			throw new ApplicationLogicException('Headers have already been sent! This is likely a bug in the application.');
386
+		}
387
+
388
+		// send the CSP headers now
389
+		header($this->getCspManager()->getHeader());
390
+
391
+		foreach ($this->headerQueue as $item) {
392
+			if (mb_strpos($item, "\r") !== false || mb_strpos($item, "\n") !== false) {
393
+				// Oops. We're not allowed to do this.
394
+				throw new Exception('Unable to split header');
395
+			}
396
+
397
+			header($item);
398
+		}
399
+	}
400 400
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -252,7 +252,7 @@  discard block
 block discarded – undo
252 252
             $targetScriptName = $currentScriptName;
253 253
         }
254 254
         else {
255
-            $targetScriptName = $this->getSiteConfiguration()->getBaseUrl() . '/' . $script;
255
+            $targetScriptName = $this->getSiteConfiguration()->getBaseUrl().'/'.$script;
256 256
         }
257 257
 
258 258
         $pathInfo = array($targetScriptName);
@@ -266,7 +266,7 @@  discard block
 block discarded – undo
266 266
         $url = implode('/', $pathInfo);
267 267
 
268 268
         if (is_array($parameters) && count($parameters) > 0) {
269
-            $url .= '?' . http_build_query($parameters);
269
+            $url .= '?'.http_build_query($parameters);
270 270
         }
271 271
 
272 272
         $this->redirectUrl($url);
@@ -311,7 +311,7 @@  discard block
 block discarded – undo
311 311
      * @param string $path The path (relative to the application root) of the file
312 312
      */
313 313
     final protected function addCss($path) {
314
-        if(in_array($path, $this->extraCss)){
314
+        if (in_array($path, $this->extraCss)) {
315 315
             // nothing to do
316 316
             return;
317 317
         }
@@ -324,8 +324,8 @@  discard block
 block discarded – undo
324 324
      *
325 325
      * @param string $path The path (relative to the application root) of the file
326 326
      */
327
-    final protected function addJs($path){
328
-        if(in_array($path, $this->extraJs)){
327
+    final protected function addJs($path) {
328
+        if (in_array($path, $this->extraJs)) {
329 329
             // nothing to do
330 330
             return;
331 331
         }
@@ -348,7 +348,7 @@  discard block
 block discarded – undo
348 348
      */
349 349
     final protected function setHtmlTitle($title)
350 350
     {
351
-        $this->htmlTitle = $this->smarty->fetch('string:' . $title);
351
+        $this->htmlTitle = $this->smarty->fetch('string:'.$title);
352 352
     }
353 353
 
354 354
     public function execute()
Please login to merge, or discard this patch.
includes/WebStart.php 1 patch
Indentation   +221 added lines, -221 removed lines patch added patch discarded remove patch
@@ -32,225 +32,225 @@
 block discarded – undo
32 32
  */
33 33
 class WebStart extends ApplicationBase
34 34
 {
35
-    /**
36
-     * @var IRequestRouter $requestRouter The request router to use. Note that different entry points have different
37
-     *                                    routers and hence different URL mappings
38
-     */
39
-    private $requestRouter;
40
-    /**
41
-     * @var bool $isPublic Determines whether to use public interface objects or internal interface objects
42
-     */
43
-    private $isPublic = false;
44
-
45
-    /**
46
-     * WebStart constructor.
47
-     *
48
-     * @param SiteConfiguration $configuration The site configuration
49
-     * @param IRequestRouter    $router        The request router to use
50
-     */
51
-    public function __construct(SiteConfiguration $configuration, IRequestRouter $router)
52
-    {
53
-        parent::__construct($configuration);
54
-
55
-        $this->requestRouter = $router;
56
-    }
57
-
58
-    /**
59
-     * @param ITask             $page
60
-     * @param SiteConfiguration $siteConfiguration
61
-     * @param PdoDatabase       $database
62
-     * @param PdoDatabase       $notificationsDatabase
63
-     *
64
-     * @return void
65
-     */
66
-    protected function setupHelpers(
67
-        ITask $page,
68
-        SiteConfiguration $siteConfiguration,
69
-        PdoDatabase $database,
70
-        PdoDatabase $notificationsDatabase = null
71
-    ) {
72
-        parent::setupHelpers($page, $siteConfiguration, $database, $notificationsDatabase);
73
-
74
-        if ($page instanceof PageBase) {
75
-            $page->setTokenManager(new TokenManager());
76
-            $page->setCspManager(new ContentSecurityPolicyManager());
77
-
78
-            if ($page instanceof InternalPageBase) {
79
-                $page->setTypeAheadHelper(new TypeAheadHelper());
80
-
81
-                $identificationVerifier = new IdentificationVerifier($page->getHttpHelper(), $siteConfiguration,
82
-                    $database);
83
-                $page->setIdentificationVerifier($identificationVerifier);
84
-
85
-                $page->setSecurityManager(new SecurityManager($identificationVerifier, new RoleConfiguration()));
86
-
87
-                if ($siteConfiguration->getTitleBlacklistEnabled()) {
88
-                    $page->setBlacklistHelper(new FakeBlacklistHelper());
89
-                }
90
-                else {
91
-                    $page->setBlacklistHelper(new BlacklistHelper($page->getHttpHelper(),
92
-                        $siteConfiguration->getMediawikiWebServiceEndpoint()));
93
-                }
94
-            }
95
-        }
96
-    }
97
-
98
-    /**
99
-     * Application entry point.
100
-     *
101
-     * Sets up the environment and runs the application, performing any global cleanup operations when done.
102
-     */
103
-    public function run()
104
-    {
105
-        try {
106
-            if ($this->setupEnvironment()) {
107
-                $this->main();
108
-            }
109
-        }
110
-        catch (EnvironmentException $ex) {
111
-            ob_end_clean();
112
-            print Offline::getOfflineMessage($this->isPublic(), $ex->getMessage());
113
-        }
114
-        catch (ReadableException $ex) {
115
-            ob_end_clean();
116
-            print $ex->getReadableError();
117
-        }
118
-        finally {
119
-            $this->cleanupEnvironment();
120
-        }
121
-    }
122
-
123
-    /**
124
-     * Environment setup
125
-     *
126
-     * This method initialises the tool environment. If the tool cannot be initialised correctly, it will return false
127
-     * and shut down prematurely.
128
-     *
129
-     * @return bool
130
-     * @throws EnvironmentException
131
-     */
132
-    protected function setupEnvironment()
133
-    {
134
-        // initialise global exception handler
135
-        set_exception_handler(array(ExceptionHandler::class, 'exceptionHandler'));
136
-        set_error_handler(array(ExceptionHandler::class, 'errorHandler'), E_RECOVERABLE_ERROR);
137
-
138
-        // start output buffering if necessary
139
-        if (ob_get_level() === 0) {
140
-            ob_start();
141
-        }
142
-
143
-        // initialise super-global providers
144
-        WebRequest::setGlobalStateProvider(new GlobalStateProvider());
145
-
146
-        if (Offline::isOffline()) {
147
-            print Offline::getOfflineMessage($this->isPublic());
148
-            ob_end_flush();
149
-
150
-            return false;
151
-        }
152
-
153
-        // Call parent setup
154
-        if (!parent::setupEnvironment()) {
155
-            return false;
156
-        }
157
-
158
-        // Start up sessions
159
-        Session::start();
160
-
161
-        // Check the user is allowed to be logged in still. This must be before we call any user-loading functions and
162
-        // get the current user cached.
163
-        // I'm not sure if this function call being here is particularly a good thing, but it's part of starting up a
164
-        // session I suppose.
165
-        $this->checkForceLogout();
166
-
167
-        // environment initialised!
168
-        return true;
169
-    }
170
-
171
-    /**
172
-     * Main application logic
173
-     */
174
-    protected function main()
175
-    {
176
-        // Get the right route for the request
177
-        $page = $this->requestRouter->route();
178
-
179
-        $siteConfiguration = $this->getConfiguration();
180
-        $database = PdoDatabase::getDatabaseConnection('acc');
181
-
182
-        if ($siteConfiguration->getIrcNotificationsEnabled()) {
183
-            $notificationsDatabase = PdoDatabase::getDatabaseConnection('notifications');
184
-        }
185
-        else {
186
-            // @todo federated table here?
187
-            $notificationsDatabase = $database;
188
-        }
189
-
190
-        $this->setupHelpers($page, $siteConfiguration, $database, $notificationsDatabase);
191
-
192
-        /* @todo Remove this global statement! It's here for User.php, which does far more than it should. */
193
-        global $oauthProtocolHelper;
194
-        $oauthProtocolHelper = $page->getOAuthProtocolHelper();
195
-
196
-        /* @todo Remove this global statement! It's here for Request.php, which does far more than it should. */
197
-        global $globalXffTrustProvider;
198
-        $globalXffTrustProvider = $page->getXffTrustProvider();
199
-
200
-        // run the route code for the request.
201
-        $page->execute();
202
-    }
203
-
204
-    /**
205
-     * Any cleanup tasks should go here
206
-     *
207
-     * Note that we need to be very careful here, as exceptions may have been thrown and handled.
208
-     * This should *only* be for cleaning up, no logic should go here.
209
-     */
210
-    protected function cleanupEnvironment()
211
-    {
212
-        // Clean up anything we splurged after sending the page.
213
-        if (ob_get_level() > 0) {
214
-            for ($i = ob_get_level(); $i > 0; $i--) {
215
-                ob_end_clean();
216
-            }
217
-        }
218
-    }
219
-
220
-    private function checkForceLogout()
221
-    {
222
-        $database = PdoDatabase::getDatabaseConnection('acc');
223
-
224
-        $sessionUserId = WebRequest::getSessionUserId();
225
-        iF ($sessionUserId === null) {
226
-            return;
227
-        }
228
-
229
-        // Note, User::getCurrent() caches it's result, which we *really* don't want to trigger.
230
-        $currentUser = User::getById($sessionUserId, $database);
231
-
232
-        if ($currentUser === false) {
233
-            // Umm... this user has a session cookie with a userId set, but no user exists...
234
-            Session::restart();
235
-
236
-            $currentUser = User::getCurrent($database);
237
-        }
238
-
239
-        if ($currentUser->getForceLogout()) {
240
-            Session::restart();
241
-
242
-            $currentUser->setForceLogout(false);
243
-            $currentUser->save();
244
-        }
245
-    }
246
-
247
-    public function isPublic()
248
-    {
249
-        return $this->isPublic;
250
-    }
251
-
252
-    public function setPublic($isPublic)
253
-    {
254
-        $this->isPublic = $isPublic;
255
-    }
35
+	/**
36
+	 * @var IRequestRouter $requestRouter The request router to use. Note that different entry points have different
37
+	 *                                    routers and hence different URL mappings
38
+	 */
39
+	private $requestRouter;
40
+	/**
41
+	 * @var bool $isPublic Determines whether to use public interface objects or internal interface objects
42
+	 */
43
+	private $isPublic = false;
44
+
45
+	/**
46
+	 * WebStart constructor.
47
+	 *
48
+	 * @param SiteConfiguration $configuration The site configuration
49
+	 * @param IRequestRouter    $router        The request router to use
50
+	 */
51
+	public function __construct(SiteConfiguration $configuration, IRequestRouter $router)
52
+	{
53
+		parent::__construct($configuration);
54
+
55
+		$this->requestRouter = $router;
56
+	}
57
+
58
+	/**
59
+	 * @param ITask             $page
60
+	 * @param SiteConfiguration $siteConfiguration
61
+	 * @param PdoDatabase       $database
62
+	 * @param PdoDatabase       $notificationsDatabase
63
+	 *
64
+	 * @return void
65
+	 */
66
+	protected function setupHelpers(
67
+		ITask $page,
68
+		SiteConfiguration $siteConfiguration,
69
+		PdoDatabase $database,
70
+		PdoDatabase $notificationsDatabase = null
71
+	) {
72
+		parent::setupHelpers($page, $siteConfiguration, $database, $notificationsDatabase);
73
+
74
+		if ($page instanceof PageBase) {
75
+			$page->setTokenManager(new TokenManager());
76
+			$page->setCspManager(new ContentSecurityPolicyManager());
77
+
78
+			if ($page instanceof InternalPageBase) {
79
+				$page->setTypeAheadHelper(new TypeAheadHelper());
80
+
81
+				$identificationVerifier = new IdentificationVerifier($page->getHttpHelper(), $siteConfiguration,
82
+					$database);
83
+				$page->setIdentificationVerifier($identificationVerifier);
84
+
85
+				$page->setSecurityManager(new SecurityManager($identificationVerifier, new RoleConfiguration()));
86
+
87
+				if ($siteConfiguration->getTitleBlacklistEnabled()) {
88
+					$page->setBlacklistHelper(new FakeBlacklistHelper());
89
+				}
90
+				else {
91
+					$page->setBlacklistHelper(new BlacklistHelper($page->getHttpHelper(),
92
+						$siteConfiguration->getMediawikiWebServiceEndpoint()));
93
+				}
94
+			}
95
+		}
96
+	}
97
+
98
+	/**
99
+	 * Application entry point.
100
+	 *
101
+	 * Sets up the environment and runs the application, performing any global cleanup operations when done.
102
+	 */
103
+	public function run()
104
+	{
105
+		try {
106
+			if ($this->setupEnvironment()) {
107
+				$this->main();
108
+			}
109
+		}
110
+		catch (EnvironmentException $ex) {
111
+			ob_end_clean();
112
+			print Offline::getOfflineMessage($this->isPublic(), $ex->getMessage());
113
+		}
114
+		catch (ReadableException $ex) {
115
+			ob_end_clean();
116
+			print $ex->getReadableError();
117
+		}
118
+		finally {
119
+			$this->cleanupEnvironment();
120
+		}
121
+	}
122
+
123
+	/**
124
+	 * Environment setup
125
+	 *
126
+	 * This method initialises the tool environment. If the tool cannot be initialised correctly, it will return false
127
+	 * and shut down prematurely.
128
+	 *
129
+	 * @return bool
130
+	 * @throws EnvironmentException
131
+	 */
132
+	protected function setupEnvironment()
133
+	{
134
+		// initialise global exception handler
135
+		set_exception_handler(array(ExceptionHandler::class, 'exceptionHandler'));
136
+		set_error_handler(array(ExceptionHandler::class, 'errorHandler'), E_RECOVERABLE_ERROR);
137
+
138
+		// start output buffering if necessary
139
+		if (ob_get_level() === 0) {
140
+			ob_start();
141
+		}
142
+
143
+		// initialise super-global providers
144
+		WebRequest::setGlobalStateProvider(new GlobalStateProvider());
145
+
146
+		if (Offline::isOffline()) {
147
+			print Offline::getOfflineMessage($this->isPublic());
148
+			ob_end_flush();
149
+
150
+			return false;
151
+		}
152
+
153
+		// Call parent setup
154
+		if (!parent::setupEnvironment()) {
155
+			return false;
156
+		}
157
+
158
+		// Start up sessions
159
+		Session::start();
160
+
161
+		// Check the user is allowed to be logged in still. This must be before we call any user-loading functions and
162
+		// get the current user cached.
163
+		// I'm not sure if this function call being here is particularly a good thing, but it's part of starting up a
164
+		// session I suppose.
165
+		$this->checkForceLogout();
166
+
167
+		// environment initialised!
168
+		return true;
169
+	}
170
+
171
+	/**
172
+	 * Main application logic
173
+	 */
174
+	protected function main()
175
+	{
176
+		// Get the right route for the request
177
+		$page = $this->requestRouter->route();
178
+
179
+		$siteConfiguration = $this->getConfiguration();
180
+		$database = PdoDatabase::getDatabaseConnection('acc');
181
+
182
+		if ($siteConfiguration->getIrcNotificationsEnabled()) {
183
+			$notificationsDatabase = PdoDatabase::getDatabaseConnection('notifications');
184
+		}
185
+		else {
186
+			// @todo federated table here?
187
+			$notificationsDatabase = $database;
188
+		}
189
+
190
+		$this->setupHelpers($page, $siteConfiguration, $database, $notificationsDatabase);
191
+
192
+		/* @todo Remove this global statement! It's here for User.php, which does far more than it should. */
193
+		global $oauthProtocolHelper;
194
+		$oauthProtocolHelper = $page->getOAuthProtocolHelper();
195
+
196
+		/* @todo Remove this global statement! It's here for Request.php, which does far more than it should. */
197
+		global $globalXffTrustProvider;
198
+		$globalXffTrustProvider = $page->getXffTrustProvider();
199
+
200
+		// run the route code for the request.
201
+		$page->execute();
202
+	}
203
+
204
+	/**
205
+	 * Any cleanup tasks should go here
206
+	 *
207
+	 * Note that we need to be very careful here, as exceptions may have been thrown and handled.
208
+	 * This should *only* be for cleaning up, no logic should go here.
209
+	 */
210
+	protected function cleanupEnvironment()
211
+	{
212
+		// Clean up anything we splurged after sending the page.
213
+		if (ob_get_level() > 0) {
214
+			for ($i = ob_get_level(); $i > 0; $i--) {
215
+				ob_end_clean();
216
+			}
217
+		}
218
+	}
219
+
220
+	private function checkForceLogout()
221
+	{
222
+		$database = PdoDatabase::getDatabaseConnection('acc');
223
+
224
+		$sessionUserId = WebRequest::getSessionUserId();
225
+		iF ($sessionUserId === null) {
226
+			return;
227
+		}
228
+
229
+		// Note, User::getCurrent() caches it's result, which we *really* don't want to trigger.
230
+		$currentUser = User::getById($sessionUserId, $database);
231
+
232
+		if ($currentUser === false) {
233
+			// Umm... this user has a session cookie with a userId set, but no user exists...
234
+			Session::restart();
235
+
236
+			$currentUser = User::getCurrent($database);
237
+		}
238
+
239
+		if ($currentUser->getForceLogout()) {
240
+			Session::restart();
241
+
242
+			$currentUser->setForceLogout(false);
243
+			$currentUser->save();
244
+		}
245
+	}
246
+
247
+	public function isPublic()
248
+	{
249
+		return $this->isPublic;
250
+	}
251
+
252
+	public function setPublic($isPublic)
253
+	{
254
+		$this->isPublic = $isPublic;
255
+	}
256 256
 }
Please login to merge, or discard this patch.
includes/Fragments/TemplateOutput.php 1 patch
Indentation   +79 added lines, -79 removed lines patch added patch discarded remove patch
@@ -15,94 +15,94 @@
 block discarded – undo
15 15
 
16 16
 trait TemplateOutput
17 17
 {
18
-    /** @var Smarty */
19
-    private $smarty;
20
-    /** @var string Extra JavaScript to include at the end of the page's execution */
21
-    private $tailScript;
22
-    /** @var string */
23
-    private $tailScriptNonce;
18
+	/** @var Smarty */
19
+	private $smarty;
20
+	/** @var string Extra JavaScript to include at the end of the page's execution */
21
+	private $tailScript;
22
+	/** @var string */
23
+	private $tailScriptNonce;
24 24
 
25
-    /**
26
-     * @return SiteConfiguration
27
-     */
28
-    protected abstract function getSiteConfiguration();
25
+	/**
26
+	 * @return SiteConfiguration
27
+	 */
28
+	protected abstract function getSiteConfiguration();
29 29
 
30
-    /**
31
-     * Include extra JavaScript at the end of the page's execution
32
-     *
33
-     * @param $nonce string CSP Nonce generated by ContentSecurityPolicyManager::getNonce()
34
-     * @param $script string JavaScript to include at the end of the page
35
-     */
36
-    final protected function setTailScript($nonce, $script)
37
-    {
38
-        $this->tailScriptNonce = $nonce;
39
-        $this->tailScript = $script;
40
-    }
30
+	/**
31
+	 * Include extra JavaScript at the end of the page's execution
32
+	 *
33
+	 * @param $nonce string CSP Nonce generated by ContentSecurityPolicyManager::getNonce()
34
+	 * @param $script string JavaScript to include at the end of the page
35
+	 */
36
+	final protected function setTailScript($nonce, $script)
37
+	{
38
+		$this->tailScriptNonce = $nonce;
39
+		$this->tailScript = $script;
40
+	}
41 41
 
42
-    /**
43
-     * Assigns a Smarty variable
44
-     *
45
-     * @param  array|string $name  the template variable name(s)
46
-     * @param  mixed        $value the value to assign
47
-     */
48
-    final protected function assign($name, $value)
49
-    {
50
-        $this->smarty->assign($name, $value);
51
-    }
42
+	/**
43
+	 * Assigns a Smarty variable
44
+	 *
45
+	 * @param  array|string $name  the template variable name(s)
46
+	 * @param  mixed        $value the value to assign
47
+	 */
48
+	final protected function assign($name, $value)
49
+	{
50
+		$this->smarty->assign($name, $value);
51
+	}
52 52
 
53
-    /**
54
-     * Sets up the variables used by the main Smarty base template.
55
-     *
56
-     * This list is getting kinda long.
57
-     */
58
-    final protected function setUpSmarty()
59
-    {
60
-        $this->smarty = new Smarty();
61
-        $this->smarty->addPluginsDir($this->getSiteConfiguration()->getFilePath() . '/smarty-plugins');
53
+	/**
54
+	 * Sets up the variables used by the main Smarty base template.
55
+	 *
56
+	 * This list is getting kinda long.
57
+	 */
58
+	final protected function setUpSmarty()
59
+	{
60
+		$this->smarty = new Smarty();
61
+		$this->smarty->addPluginsDir($this->getSiteConfiguration()->getFilePath() . '/smarty-plugins');
62 62
 
63
-        $this->assign('currentUser', User::getCommunity());
64
-        $this->assign('loggedIn', false);
65
-        $this->assign('baseurl', $this->getSiteConfiguration()->getBaseUrl());
66
-        $this->assign('mediawikiScriptPath', $this->getSiteConfiguration()->getMediawikiScriptPath());
63
+		$this->assign('currentUser', User::getCommunity());
64
+		$this->assign('loggedIn', false);
65
+		$this->assign('baseurl', $this->getSiteConfiguration()->getBaseUrl());
66
+		$this->assign('mediawikiScriptPath', $this->getSiteConfiguration()->getMediawikiScriptPath());
67 67
 
68
-        $this->assign('siteNoticeText', '');
69
-        $this->assign('toolversion', Environment::getToolVersion());
68
+		$this->assign('siteNoticeText', '');
69
+		$this->assign('toolversion', Environment::getToolVersion());
70 70
 
71
-        // default these
72
-        $this->assign('onlineusers', array());
73
-        $this->assign('typeAheadBlock', '');
74
-        $this->assign('extraJs', array());
75
-        $this->assign('extraCss', array());
71
+		// default these
72
+		$this->assign('onlineusers', array());
73
+		$this->assign('typeAheadBlock', '');
74
+		$this->assign('extraJs', array());
75
+		$this->assign('extraCss', array());
76 76
 
77
-        // nav menu access control
78
-        $this->assign('nav__canRequests', false);
79
-        $this->assign('nav__canLogs', false);
80
-        $this->assign('nav__canUsers', false);
81
-        $this->assign('nav__canSearch', false);
82
-        $this->assign('nav__canStats', false);
83
-        $this->assign('nav__canBan', false);
84
-        $this->assign('nav__canEmailMgmt', false);
85
-        $this->assign('nav__canWelcomeMgmt', false);
86
-        $this->assign('nav__canSiteNoticeMgmt', false);
87
-        $this->assign('nav__canUserMgmt', false);
88
-        $this->assign('nav__canViewRequest', false);
89
-        $this->assign('nav__canJobQueue', false);
77
+		// nav menu access control
78
+		$this->assign('nav__canRequests', false);
79
+		$this->assign('nav__canLogs', false);
80
+		$this->assign('nav__canUsers', false);
81
+		$this->assign('nav__canSearch', false);
82
+		$this->assign('nav__canStats', false);
83
+		$this->assign('nav__canBan', false);
84
+		$this->assign('nav__canEmailMgmt', false);
85
+		$this->assign('nav__canWelcomeMgmt', false);
86
+		$this->assign('nav__canSiteNoticeMgmt', false);
87
+		$this->assign('nav__canUserMgmt', false);
88
+		$this->assign('nav__canViewRequest', false);
89
+		$this->assign('nav__canJobQueue', false);
90 90
 
91
-        $this->assign('page', $this);
92
-    }
91
+		$this->assign('page', $this);
92
+	}
93 93
 
94
-    /**
95
-     * Fetches a rendered Smarty template
96
-     *
97
-     * @param $template string Template file path, relative to /templates/
98
-     *
99
-     * @return string Templated HTML
100
-     */
101
-    final protected function fetchTemplate($template)
102
-    {
103
-        $this->assign('tailScript', $this->tailScript);
104
-        $this->assign('tailScriptNonce', $this->tailScriptNonce);
94
+	/**
95
+	 * Fetches a rendered Smarty template
96
+	 *
97
+	 * @param $template string Template file path, relative to /templates/
98
+	 *
99
+	 * @return string Templated HTML
100
+	 */
101
+	final protected function fetchTemplate($template)
102
+	{
103
+		$this->assign('tailScript', $this->tailScript);
104
+		$this->assign('tailScriptNonce', $this->tailScriptNonce);
105 105
 
106
-        return $this->smarty->fetch($template);
107
-    }
106
+		return $this->smarty->fetch($template);
107
+	}
108 108
 }
Please login to merge, or discard this patch.
includes/Pages/UserAuth/MultiFactor/PageMultiFactor.php 2 patches
Indentation   +385 added lines, -385 removed lines patch added patch discarded remove patch
@@ -25,243 +25,243 @@  discard block
 block discarded – undo
25 25
 
26 26
 class PageMultiFactor extends InternalPageBase
27 27
 {
28
-    /**
29
-     * Main function for this page, when no specific actions are called.
30
-     * @return void
31
-     */
32
-    protected function main()
33
-    {
34
-        $database = $this->getDatabase();
35
-        $currentUser = User::getCurrent($database);
36
-
37
-        $yubikeyOtpCredentialProvider = new YubikeyOtpCredentialProvider($database, $this->getSiteConfiguration(),
38
-            $this->getHttpHelper());
39
-        $this->assign('yubikeyOtpIdentity', $yubikeyOtpCredentialProvider->getYubikeyData($currentUser->getId()));
40
-        $this->assign('yubikeyOtpEnrolled', $yubikeyOtpCredentialProvider->userIsEnrolled($currentUser->getId()));
41
-
42
-        $totpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration());
43
-        $this->assign('totpEnrolled', $totpCredentialProvider->userIsEnrolled($currentUser->getId()));
44
-
45
-        $u2fCredentialProvider = new U2FCredentialProvider($database, $this->getSiteConfiguration());
46
-        $this->assign('u2fEnrolled', $u2fCredentialProvider->userIsEnrolled($currentUser->getId()));
47
-
48
-        $scratchCredentialProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
49
-        $this->assign('scratchEnrolled', $scratchCredentialProvider->userIsEnrolled($currentUser->getId()));
50
-        $this->assign('scratchRemaining', $scratchCredentialProvider->getRemaining($currentUser->getId()));
51
-
52
-        $this->setTemplate('mfa/mfa.tpl');
53
-    }
54
-
55
-    protected function enableYubikeyOtp()
56
-    {
57
-        $database = $this->getDatabase();
58
-        $currentUser = User::getCurrent($database);
59
-
60
-        $otpCredentialProvider = new YubikeyOtpCredentialProvider($database,
61
-            $this->getSiteConfiguration(), $this->getHttpHelper());
62
-
63
-        if (WebRequest::wasPosted()) {
64
-            $this->validateCSRFToken();
65
-
66
-            $passwordCredentialProvider = new PasswordCredentialProvider($database,
67
-                $this->getSiteConfiguration());
68
-
69
-            $password = WebRequest::postString('password');
70
-            $otp = WebRequest::postString('otp');
71
-
72
-            $result = $passwordCredentialProvider->authenticate($currentUser, $password);
73
-
74
-            if ($result) {
75
-                try {
76
-                    $otpCredentialProvider->setCredential($currentUser, 2, $otp);
77
-                    SessionAlert::success('Enabled YubiKey OTP.');
78
-
79
-                    $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
80
-                    if($scratchProvider->getRemaining($currentUser->getId()) < 3) {
81
-                        $scratchProvider->setCredential($currentUser, 2, null);
82
-                        $tokens = $scratchProvider->getTokens();
83
-                        $this->assign('tokens', $tokens);
84
-                        $this->setTemplate('mfa/regenScratchTokens.tpl');
85
-                        return;
86
-                    }
87
-                }
88
-                catch (ApplicationLogicException $ex) {
89
-                    SessionAlert::error('Error enabling YubiKey OTP: ' . $ex->getMessage());
90
-                }
91
-
92
-                $this->redirect('multiFactor');
93
-            }
94
-            else {
95
-                SessionAlert::error('Error enabling YubiKey OTP - invalid credentials.');
96
-                $this->redirect('multiFactor');
97
-            }
98
-        }
99
-        else {
100
-            if ($otpCredentialProvider->userIsEnrolled($currentUser->getId())) {
101
-                // user is not enrolled, we shouldn't have got here.
102
-                throw new ApplicationLogicException('User is already enrolled in the selected MFA mechanism');
103
-            }
104
-
105
-            $this->assignCSRFToken();
106
-            $this->setTemplate('mfa/enableYubikey.tpl');
107
-        }
108
-    }
109
-
110
-    protected function disableYubikeyOtp()
111
-    {
112
-        $database = $this->getDatabase();
113
-        $currentUser = User::getCurrent($database);
114
-
115
-        $otpCredentialProvider = new YubikeyOtpCredentialProvider($database,
116
-            $this->getSiteConfiguration(), $this->getHttpHelper());
117
-
118
-        $factorType = 'YubiKey OTP';
119
-
120
-        $this->deleteCredential($database, $currentUser, $otpCredentialProvider, $factorType);
121
-    }
122
-
123
-    protected function enableTotp()
124
-    {
125
-        $database = $this->getDatabase();
126
-        $currentUser = User::getCurrent($database);
127
-
128
-        $otpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration());
129
-
130
-        if (WebRequest::wasPosted()) {
131
-            $this->validateCSRFToken();
132
-
133
-            // used for routing only, not security
134
-            $stage = WebRequest::postString('stage');
135
-
136
-            if ($stage === "auth") {
137
-                $password = WebRequest::postString('password');
138
-
139
-                $passwordCredentialProvider = new PasswordCredentialProvider($database,
140
-                    $this->getSiteConfiguration());
141
-                $result = $passwordCredentialProvider->authenticate($currentUser, $password);
142
-
143
-                if ($result) {
144
-                    $otpCredentialProvider->setCredential($currentUser, 2, null);
145
-
146
-                    $provisioningUrl = $otpCredentialProvider->getProvisioningUrl($currentUser);
147
-
148
-                    $renderer = new Svg();
149
-                    $renderer->setHeight(256);
150
-                    $renderer->setWidth(256);
151
-                    $writer = new Writer($renderer);
152
-                    $svg = $writer->writeString($provisioningUrl);
153
-
154
-                    $this->assign('svg', $svg);
155
-                    $this->assign('secret', $otpCredentialProvider->getSecret($currentUser));
156
-
157
-                    $this->assignCSRFToken();
158
-                    $this->setTemplate('mfa/enableTotpEnroll.tpl');
159
-
160
-                    return;
161
-                }
162
-                else {
163
-                    SessionAlert::error('Error enabling TOTP - invalid credentials.');
164
-                    $this->redirect('multiFactor');
165
-
166
-                    return;
167
-                }
168
-            }
169
-
170
-            if ($stage === "enroll") {
171
-                // we *must* have a defined credential already here,
172
-                if ($otpCredentialProvider->isPartiallyEnrolled($currentUser)) {
173
-                    $otp = WebRequest::postString('otp');
174
-                    $result = $otpCredentialProvider->verifyEnable($currentUser, $otp);
175
-
176
-                    if ($result) {
177
-                        SessionAlert::success('Enabled TOTP.');
178
-
179
-                        $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
180
-                        if($scratchProvider->getRemaining($currentUser->getId()) < 3) {
181
-                            $scratchProvider->setCredential($currentUser, 2, null);
182
-                            $tokens = $scratchProvider->getTokens();
183
-                            $this->assign('tokens', $tokens);
184
-                            $this->setTemplate('mfa/regenScratchTokens.tpl');
185
-                            return;
186
-                        }
187
-                    }
188
-                    else {
189
-                        $otpCredentialProvider->deleteCredential($currentUser);
190
-                        SessionAlert::error('Error enabling TOTP: invalid token provided');
191
-                    }
192
-
193
-
194
-                    $this->redirect('multiFactor');
195
-                    return;
196
-                }
197
-                else {
198
-                    SessionAlert::error('Error enabling TOTP - no enrollment found or enrollment expired.');
199
-                    $this->redirect('multiFactor');
28
+	/**
29
+	 * Main function for this page, when no specific actions are called.
30
+	 * @return void
31
+	 */
32
+	protected function main()
33
+	{
34
+		$database = $this->getDatabase();
35
+		$currentUser = User::getCurrent($database);
36
+
37
+		$yubikeyOtpCredentialProvider = new YubikeyOtpCredentialProvider($database, $this->getSiteConfiguration(),
38
+			$this->getHttpHelper());
39
+		$this->assign('yubikeyOtpIdentity', $yubikeyOtpCredentialProvider->getYubikeyData($currentUser->getId()));
40
+		$this->assign('yubikeyOtpEnrolled', $yubikeyOtpCredentialProvider->userIsEnrolled($currentUser->getId()));
41
+
42
+		$totpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration());
43
+		$this->assign('totpEnrolled', $totpCredentialProvider->userIsEnrolled($currentUser->getId()));
44
+
45
+		$u2fCredentialProvider = new U2FCredentialProvider($database, $this->getSiteConfiguration());
46
+		$this->assign('u2fEnrolled', $u2fCredentialProvider->userIsEnrolled($currentUser->getId()));
47
+
48
+		$scratchCredentialProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
49
+		$this->assign('scratchEnrolled', $scratchCredentialProvider->userIsEnrolled($currentUser->getId()));
50
+		$this->assign('scratchRemaining', $scratchCredentialProvider->getRemaining($currentUser->getId()));
51
+
52
+		$this->setTemplate('mfa/mfa.tpl');
53
+	}
200 54
 
201
-                    return;
202
-                }
203
-            }
55
+	protected function enableYubikeyOtp()
56
+	{
57
+		$database = $this->getDatabase();
58
+		$currentUser = User::getCurrent($database);
59
+
60
+		$otpCredentialProvider = new YubikeyOtpCredentialProvider($database,
61
+			$this->getSiteConfiguration(), $this->getHttpHelper());
62
+
63
+		if (WebRequest::wasPosted()) {
64
+			$this->validateCSRFToken();
65
+
66
+			$passwordCredentialProvider = new PasswordCredentialProvider($database,
67
+				$this->getSiteConfiguration());
68
+
69
+			$password = WebRequest::postString('password');
70
+			$otp = WebRequest::postString('otp');
71
+
72
+			$result = $passwordCredentialProvider->authenticate($currentUser, $password);
73
+
74
+			if ($result) {
75
+				try {
76
+					$otpCredentialProvider->setCredential($currentUser, 2, $otp);
77
+					SessionAlert::success('Enabled YubiKey OTP.');
78
+
79
+					$scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
80
+					if($scratchProvider->getRemaining($currentUser->getId()) < 3) {
81
+						$scratchProvider->setCredential($currentUser, 2, null);
82
+						$tokens = $scratchProvider->getTokens();
83
+						$this->assign('tokens', $tokens);
84
+						$this->setTemplate('mfa/regenScratchTokens.tpl');
85
+						return;
86
+					}
87
+				}
88
+				catch (ApplicationLogicException $ex) {
89
+					SessionAlert::error('Error enabling YubiKey OTP: ' . $ex->getMessage());
90
+				}
91
+
92
+				$this->redirect('multiFactor');
93
+			}
94
+			else {
95
+				SessionAlert::error('Error enabling YubiKey OTP - invalid credentials.');
96
+				$this->redirect('multiFactor');
97
+			}
98
+		}
99
+		else {
100
+			if ($otpCredentialProvider->userIsEnrolled($currentUser->getId())) {
101
+				// user is not enrolled, we shouldn't have got here.
102
+				throw new ApplicationLogicException('User is already enrolled in the selected MFA mechanism');
103
+			}
104
+
105
+			$this->assignCSRFToken();
106
+			$this->setTemplate('mfa/enableYubikey.tpl');
107
+		}
108
+	}
204 109
 
205
-            // urgh, dunno what happened, but it's not something expected.
206
-            throw new ApplicationLogicException();
207
-        }
208
-        else {
209
-            if ($otpCredentialProvider->userIsEnrolled($currentUser->getId())) {
210
-                // user is not enrolled, we shouldn't have got here.
211
-                throw new ApplicationLogicException('User is already enrolled in the selected MFA mechanism');
212
-            }
110
+	protected function disableYubikeyOtp()
111
+	{
112
+		$database = $this->getDatabase();
113
+		$currentUser = User::getCurrent($database);
213 114
 
214
-            $this->assignCSRFToken();
115
+		$otpCredentialProvider = new YubikeyOtpCredentialProvider($database,
116
+			$this->getSiteConfiguration(), $this->getHttpHelper());
215 117
 
216
-            $this->assign('alertmessage', 'To enable your multi-factor credentials, please prove you are who you say you are by providing the information below.');
217
-            $this->assign('alertheader', 'Provide credentials');
218
-            $this->assign('continueText', 'Verify password');
219
-            $this->setTemplate('mfa/enableAuth.tpl');
220
-        }
221
-    }
118
+		$factorType = 'YubiKey OTP';
222 119
 
223
-    protected function disableTotp()
224
-    {
225
-        $database = $this->getDatabase();
226
-        $currentUser = User::getCurrent($database);
120
+		$this->deleteCredential($database, $currentUser, $otpCredentialProvider, $factorType);
121
+	}
122
+
123
+	protected function enableTotp()
124
+	{
125
+		$database = $this->getDatabase();
126
+		$currentUser = User::getCurrent($database);
127
+
128
+		$otpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration());
129
+
130
+		if (WebRequest::wasPosted()) {
131
+			$this->validateCSRFToken();
132
+
133
+			// used for routing only, not security
134
+			$stage = WebRequest::postString('stage');
135
+
136
+			if ($stage === "auth") {
137
+				$password = WebRequest::postString('password');
138
+
139
+				$passwordCredentialProvider = new PasswordCredentialProvider($database,
140
+					$this->getSiteConfiguration());
141
+				$result = $passwordCredentialProvider->authenticate($currentUser, $password);
142
+
143
+				if ($result) {
144
+					$otpCredentialProvider->setCredential($currentUser, 2, null);
145
+
146
+					$provisioningUrl = $otpCredentialProvider->getProvisioningUrl($currentUser);
147
+
148
+					$renderer = new Svg();
149
+					$renderer->setHeight(256);
150
+					$renderer->setWidth(256);
151
+					$writer = new Writer($renderer);
152
+					$svg = $writer->writeString($provisioningUrl);
153
+
154
+					$this->assign('svg', $svg);
155
+					$this->assign('secret', $otpCredentialProvider->getSecret($currentUser));
156
+
157
+					$this->assignCSRFToken();
158
+					$this->setTemplate('mfa/enableTotpEnroll.tpl');
159
+
160
+					return;
161
+				}
162
+				else {
163
+					SessionAlert::error('Error enabling TOTP - invalid credentials.');
164
+					$this->redirect('multiFactor');
165
+
166
+					return;
167
+				}
168
+			}
169
+
170
+			if ($stage === "enroll") {
171
+				// we *must* have a defined credential already here,
172
+				if ($otpCredentialProvider->isPartiallyEnrolled($currentUser)) {
173
+					$otp = WebRequest::postString('otp');
174
+					$result = $otpCredentialProvider->verifyEnable($currentUser, $otp);
175
+
176
+					if ($result) {
177
+						SessionAlert::success('Enabled TOTP.');
178
+
179
+						$scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
180
+						if($scratchProvider->getRemaining($currentUser->getId()) < 3) {
181
+							$scratchProvider->setCredential($currentUser, 2, null);
182
+							$tokens = $scratchProvider->getTokens();
183
+							$this->assign('tokens', $tokens);
184
+							$this->setTemplate('mfa/regenScratchTokens.tpl');
185
+							return;
186
+						}
187
+					}
188
+					else {
189
+						$otpCredentialProvider->deleteCredential($currentUser);
190
+						SessionAlert::error('Error enabling TOTP: invalid token provided');
191
+					}
192
+
193
+
194
+					$this->redirect('multiFactor');
195
+					return;
196
+				}
197
+				else {
198
+					SessionAlert::error('Error enabling TOTP - no enrollment found or enrollment expired.');
199
+					$this->redirect('multiFactor');
200
+
201
+					return;
202
+				}
203
+			}
204
+
205
+			// urgh, dunno what happened, but it's not something expected.
206
+			throw new ApplicationLogicException();
207
+		}
208
+		else {
209
+			if ($otpCredentialProvider->userIsEnrolled($currentUser->getId())) {
210
+				// user is not enrolled, we shouldn't have got here.
211
+				throw new ApplicationLogicException('User is already enrolled in the selected MFA mechanism');
212
+			}
213
+
214
+			$this->assignCSRFToken();
215
+
216
+			$this->assign('alertmessage', 'To enable your multi-factor credentials, please prove you are who you say you are by providing the information below.');
217
+			$this->assign('alertheader', 'Provide credentials');
218
+			$this->assign('continueText', 'Verify password');
219
+			$this->setTemplate('mfa/enableAuth.tpl');
220
+		}
221
+	}
227 222
 
228
-        $otpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration());
223
+	protected function disableTotp()
224
+	{
225
+		$database = $this->getDatabase();
226
+		$currentUser = User::getCurrent($database);
227
+
228
+		$otpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration());
229
+
230
+		$factorType = 'TOTP';
231
+
232
+		$this->deleteCredential($database, $currentUser, $otpCredentialProvider, $factorType);
233
+	}
229 234
 
230
-        $factorType = 'TOTP';
235
+	protected function enableU2F() {
236
+		$database = $this->getDatabase();
237
+		$currentUser = User::getCurrent($database);
231 238
 
232
-        $this->deleteCredential($database, $currentUser, $otpCredentialProvider, $factorType);
233
-    }
239
+		$otpCredentialProvider = new U2FCredentialProvider($database, $this->getSiteConfiguration());
234 240
 
235
-    protected function enableU2F() {
236
-        $database = $this->getDatabase();
237
-        $currentUser = User::getCurrent($database);
241
+		if (WebRequest::wasPosted()) {
242
+			$this->validateCSRFToken();
238 243
 
239
-        $otpCredentialProvider = new U2FCredentialProvider($database, $this->getSiteConfiguration());
240
-
241
-        if (WebRequest::wasPosted()) {
242
-            $this->validateCSRFToken();
243
-
244
-            // used for routing only, not security
245
-            $stage = WebRequest::postString('stage');
246
-
247
-            if ($stage === "auth") {
248
-                $password = WebRequest::postString('password');
249
-
250
-                $passwordCredentialProvider = new PasswordCredentialProvider($database,
251
-                    $this->getSiteConfiguration());
252
-                $result = $passwordCredentialProvider->authenticate($currentUser, $password);
253
-
254
-                if ($result) {
255
-                    $otpCredentialProvider->setCredential($currentUser, 2, null);
256
-                    $this->assignCSRFToken();
257
-
258
-                    list($data, $reqs) = $otpCredentialProvider->getRegistrationData();
259
-
260
-                    $u2fRequest =json_encode($data);
261
-                    $u2fSigns = json_encode($reqs);
262
-
263
-                    $this->addJs('/vendor/yubico/u2flib-server/examples/assets/u2f-api.js');
264
-                    $this->setTailScript($this->getCspManager()->getNonce(), <<<JS
244
+			// used for routing only, not security
245
+			$stage = WebRequest::postString('stage');
246
+
247
+			if ($stage === "auth") {
248
+				$password = WebRequest::postString('password');
249
+
250
+				$passwordCredentialProvider = new PasswordCredentialProvider($database,
251
+					$this->getSiteConfiguration());
252
+				$result = $passwordCredentialProvider->authenticate($currentUser, $password);
253
+
254
+				if ($result) {
255
+					$otpCredentialProvider->setCredential($currentUser, 2, null);
256
+					$this->assignCSRFToken();
257
+
258
+					list($data, $reqs) = $otpCredentialProvider->getRegistrationData();
259
+
260
+					$u2fRequest =json_encode($data);
261
+					$u2fSigns = json_encode($reqs);
262
+
263
+					$this->addJs('/vendor/yubico/u2flib-server/examples/assets/u2f-api.js');
264
+					$this->setTailScript($this->getCspManager()->getNonce(), <<<JS
265 265
 var request = ${u2fRequest};
266 266
 var signs = ${u2fSigns};
267 267
 
@@ -280,162 +280,162 @@  discard block
 block discarded – undo
280 280
 	form.submit();
281 281
 });
282 282
 JS
283
-                    );
284
-
285
-                    $this->setTemplate('mfa/enableU2FEnroll.tpl');
286
-
287
-                    return;
288
-                }
289
-                else {
290
-                    SessionAlert::error('Error enabling TOTP - invalid credentials.');
291
-                    $this->redirect('multiFactor');
292
-
293
-                    return;
294
-                }
295
-            }
296
-
297
-            if ($stage === "enroll") {
298
-                // we *must* have a defined credential already here,
299
-                if ($otpCredentialProvider->isPartiallyEnrolled($currentUser)) {
300
-
301
-                    $request = json_decode(WebRequest::postString('u2fRequest'));
302
-                    $u2fData = json_decode(WebRequest::postString('u2fData'));
303
-
304
-                    $otpCredentialProvider->enable($currentUser, $request, $u2fData);
305
-
306
-                    SessionAlert::success('Enabled U2F.');
307
-
308
-                    $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
309
-                    if($scratchProvider->getRemaining($currentUser->getId()) < 3) {
310
-                        $scratchProvider->setCredential($currentUser, 2, null);
311
-                        $tokens = $scratchProvider->getTokens();
312
-                        $this->assign('tokens', $tokens);
313
-                        $this->setTemplate('mfa/regenScratchTokens.tpl');
314
-                        return;
315
-                    }
316
-
317
-                    $this->redirect('multiFactor');
318
-                    return;
319
-                }
320
-                else {
321
-                    SessionAlert::error('Error enabling TOTP - no enrollment found or enrollment expired.');
322
-                    $this->redirect('multiFactor');
323
-
324
-                    return;
325
-                }
326
-            }
327
-
328
-            // urgh, dunno what happened, but it's not something expected.
329
-            throw new ApplicationLogicException();
330
-        }
331
-        else {
332
-            if ($otpCredentialProvider->userIsEnrolled($currentUser->getId())) {
333
-                // user is not enrolled, we shouldn't have got here.
334
-                throw new ApplicationLogicException('User is already enrolled in the selected MFA mechanism');
335
-            }
336
-
337
-            $this->assignCSRFToken();
338
-
339
-            $this->assign('alertmessage', 'To enable your multi-factor credentials, please prove you are who you say you are by providing the information below.');
340
-            $this->assign('alertheader', 'Provide credentials');
341
-            $this->assign('continueText', 'Verify password');
342
-            $this->setTemplate('mfa/enableAuth.tpl');
343
-        }
344
-    }
345
-
346
-    protected function disableU2F() {
347
-        $database = $this->getDatabase();
348
-        $currentUser = User::getCurrent($database);
349
-
350
-        $otpCredentialProvider = new U2FCredentialProvider($database, $this->getSiteConfiguration());
351
-
352
-        $factorType = 'U2F';
353
-
354
-        $this->deleteCredential($database, $currentUser, $otpCredentialProvider, $factorType);
355
-    }
356
-
357
-    protected function scratch()
358
-    {
359
-        $database = $this->getDatabase();
360
-        $currentUser = User::getCurrent($database);
361
-
362
-        if (WebRequest::wasPosted()) {
363
-            $this->validateCSRFToken();
364
-
365
-            $passwordCredentialProvider = new PasswordCredentialProvider($database,
366
-                $this->getSiteConfiguration());
367
-
368
-            $otpCredentialProvider = new ScratchTokenCredentialProvider($database,
369
-                $this->getSiteConfiguration());
370
-
371
-            $password = WebRequest::postString('password');
372
-
373
-            $result = $passwordCredentialProvider->authenticate($currentUser, $password);
374
-
375
-            if ($result) {
376
-                $otpCredentialProvider->setCredential($currentUser, 2, null);
377
-                $tokens = $otpCredentialProvider->getTokens();
378
-                $this->assign('tokens', $tokens);
379
-                $this->setTemplate('mfa/regenScratchTokens.tpl');
380
-            }
381
-            else {
382
-                SessionAlert::error('Error refreshing scratch tokens - invalid credentials.');
383
-                $this->redirect('multiFactor');
384
-            }
385
-        }
386
-        else {
387
-            $this->assignCSRFToken();
388
-
389
-            $this->assign('alertmessage', 'To regenerate your emergency scratch tokens, please prove you are who you say you are by providing the information below. Note that continuing will invalidate all remaining scratch tokens, and provide a set of new ones.');
390
-            $this->assign('alertheader', 'Re-generate scratch tokens');
391
-            $this->assign('continueText', 'Regenerate Scratch Tokens');
392
-
393
-            $this->setTemplate('mfa/enableAuth.tpl');
394
-        }
395
-    }
396
-
397
-    /**
398
-     * @param PdoDatabase         $database
399
-     * @param User                $currentUser
400
-     * @param ICredentialProvider $otpCredentialProvider
401
-     * @param string              $factorType
402
-     *
403
-     * @throws ApplicationLogicException
404
-     */
405
-    private function deleteCredential(
406
-        PdoDatabase $database,
407
-        User $currentUser,
408
-        ICredentialProvider $otpCredentialProvider,
409
-        $factorType
410
-    ) {
411
-        if (WebRequest::wasPosted()) {
412
-            $passwordCredentialProvider = new PasswordCredentialProvider($database,
413
-                $this->getSiteConfiguration());
414
-
415
-            $this->validateCSRFToken();
416
-
417
-            $password = WebRequest::postString('password');
418
-            $result = $passwordCredentialProvider->authenticate($currentUser, $password);
419
-
420
-            if ($result) {
421
-                $otpCredentialProvider->deleteCredential($currentUser);
422
-                SessionAlert::success('Disabled ' . $factorType . '.');
423
-                $this->redirect('multiFactor');
424
-            }
425
-            else {
426
-                SessionAlert::error('Error disabling ' . $factorType . ' - invalid credentials.');
427
-                $this->redirect('multiFactor');
428
-            }
429
-        }
430
-        else {
431
-            if (!$otpCredentialProvider->userIsEnrolled($currentUser->getId())) {
432
-                // user is not enrolled, we shouldn't have got here.
433
-                throw new ApplicationLogicException('User is not enrolled in the selected MFA mechanism');
434
-            }
435
-
436
-            $this->assignCSRFToken();
437
-            $this->assign('otpType', $factorType);
438
-            $this->setTemplate('mfa/disableOtp.tpl');
439
-        }
440
-    }
283
+					);
284
+
285
+					$this->setTemplate('mfa/enableU2FEnroll.tpl');
286
+
287
+					return;
288
+				}
289
+				else {
290
+					SessionAlert::error('Error enabling TOTP - invalid credentials.');
291
+					$this->redirect('multiFactor');
292
+
293
+					return;
294
+				}
295
+			}
296
+
297
+			if ($stage === "enroll") {
298
+				// we *must* have a defined credential already here,
299
+				if ($otpCredentialProvider->isPartiallyEnrolled($currentUser)) {
300
+
301
+					$request = json_decode(WebRequest::postString('u2fRequest'));
302
+					$u2fData = json_decode(WebRequest::postString('u2fData'));
303
+
304
+					$otpCredentialProvider->enable($currentUser, $request, $u2fData);
305
+
306
+					SessionAlert::success('Enabled U2F.');
307
+
308
+					$scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
309
+					if($scratchProvider->getRemaining($currentUser->getId()) < 3) {
310
+						$scratchProvider->setCredential($currentUser, 2, null);
311
+						$tokens = $scratchProvider->getTokens();
312
+						$this->assign('tokens', $tokens);
313
+						$this->setTemplate('mfa/regenScratchTokens.tpl');
314
+						return;
315
+					}
316
+
317
+					$this->redirect('multiFactor');
318
+					return;
319
+				}
320
+				else {
321
+					SessionAlert::error('Error enabling TOTP - no enrollment found or enrollment expired.');
322
+					$this->redirect('multiFactor');
323
+
324
+					return;
325
+				}
326
+			}
327
+
328
+			// urgh, dunno what happened, but it's not something expected.
329
+			throw new ApplicationLogicException();
330
+		}
331
+		else {
332
+			if ($otpCredentialProvider->userIsEnrolled($currentUser->getId())) {
333
+				// user is not enrolled, we shouldn't have got here.
334
+				throw new ApplicationLogicException('User is already enrolled in the selected MFA mechanism');
335
+			}
336
+
337
+			$this->assignCSRFToken();
338
+
339
+			$this->assign('alertmessage', 'To enable your multi-factor credentials, please prove you are who you say you are by providing the information below.');
340
+			$this->assign('alertheader', 'Provide credentials');
341
+			$this->assign('continueText', 'Verify password');
342
+			$this->setTemplate('mfa/enableAuth.tpl');
343
+		}
344
+	}
345
+
346
+	protected function disableU2F() {
347
+		$database = $this->getDatabase();
348
+		$currentUser = User::getCurrent($database);
349
+
350
+		$otpCredentialProvider = new U2FCredentialProvider($database, $this->getSiteConfiguration());
351
+
352
+		$factorType = 'U2F';
353
+
354
+		$this->deleteCredential($database, $currentUser, $otpCredentialProvider, $factorType);
355
+	}
356
+
357
+	protected function scratch()
358
+	{
359
+		$database = $this->getDatabase();
360
+		$currentUser = User::getCurrent($database);
361
+
362
+		if (WebRequest::wasPosted()) {
363
+			$this->validateCSRFToken();
364
+
365
+			$passwordCredentialProvider = new PasswordCredentialProvider($database,
366
+				$this->getSiteConfiguration());
367
+
368
+			$otpCredentialProvider = new ScratchTokenCredentialProvider($database,
369
+				$this->getSiteConfiguration());
370
+
371
+			$password = WebRequest::postString('password');
372
+
373
+			$result = $passwordCredentialProvider->authenticate($currentUser, $password);
374
+
375
+			if ($result) {
376
+				$otpCredentialProvider->setCredential($currentUser, 2, null);
377
+				$tokens = $otpCredentialProvider->getTokens();
378
+				$this->assign('tokens', $tokens);
379
+				$this->setTemplate('mfa/regenScratchTokens.tpl');
380
+			}
381
+			else {
382
+				SessionAlert::error('Error refreshing scratch tokens - invalid credentials.');
383
+				$this->redirect('multiFactor');
384
+			}
385
+		}
386
+		else {
387
+			$this->assignCSRFToken();
388
+
389
+			$this->assign('alertmessage', 'To regenerate your emergency scratch tokens, please prove you are who you say you are by providing the information below. Note that continuing will invalidate all remaining scratch tokens, and provide a set of new ones.');
390
+			$this->assign('alertheader', 'Re-generate scratch tokens');
391
+			$this->assign('continueText', 'Regenerate Scratch Tokens');
392
+
393
+			$this->setTemplate('mfa/enableAuth.tpl');
394
+		}
395
+	}
396
+
397
+	/**
398
+	 * @param PdoDatabase         $database
399
+	 * @param User                $currentUser
400
+	 * @param ICredentialProvider $otpCredentialProvider
401
+	 * @param string              $factorType
402
+	 *
403
+	 * @throws ApplicationLogicException
404
+	 */
405
+	private function deleteCredential(
406
+		PdoDatabase $database,
407
+		User $currentUser,
408
+		ICredentialProvider $otpCredentialProvider,
409
+		$factorType
410
+	) {
411
+		if (WebRequest::wasPosted()) {
412
+			$passwordCredentialProvider = new PasswordCredentialProvider($database,
413
+				$this->getSiteConfiguration());
414
+
415
+			$this->validateCSRFToken();
416
+
417
+			$password = WebRequest::postString('password');
418
+			$result = $passwordCredentialProvider->authenticate($currentUser, $password);
419
+
420
+			if ($result) {
421
+				$otpCredentialProvider->deleteCredential($currentUser);
422
+				SessionAlert::success('Disabled ' . $factorType . '.');
423
+				$this->redirect('multiFactor');
424
+			}
425
+			else {
426
+				SessionAlert::error('Error disabling ' . $factorType . ' - invalid credentials.');
427
+				$this->redirect('multiFactor');
428
+			}
429
+		}
430
+		else {
431
+			if (!$otpCredentialProvider->userIsEnrolled($currentUser->getId())) {
432
+				// user is not enrolled, we shouldn't have got here.
433
+				throw new ApplicationLogicException('User is not enrolled in the selected MFA mechanism');
434
+			}
435
+
436
+			$this->assignCSRFToken();
437
+			$this->assign('otpType', $factorType);
438
+			$this->setTemplate('mfa/disableOtp.tpl');
439
+		}
440
+	}
441 441
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -77,7 +77,7 @@  discard block
 block discarded – undo
77 77
                     SessionAlert::success('Enabled YubiKey OTP.');
78 78
 
79 79
                     $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
80
-                    if($scratchProvider->getRemaining($currentUser->getId()) < 3) {
80
+                    if ($scratchProvider->getRemaining($currentUser->getId()) < 3) {
81 81
                         $scratchProvider->setCredential($currentUser, 2, null);
82 82
                         $tokens = $scratchProvider->getTokens();
83 83
                         $this->assign('tokens', $tokens);
@@ -86,7 +86,7 @@  discard block
 block discarded – undo
86 86
                     }
87 87
                 }
88 88
                 catch (ApplicationLogicException $ex) {
89
-                    SessionAlert::error('Error enabling YubiKey OTP: ' . $ex->getMessage());
89
+                    SessionAlert::error('Error enabling YubiKey OTP: '.$ex->getMessage());
90 90
                 }
91 91
 
92 92
                 $this->redirect('multiFactor');
@@ -177,7 +177,7 @@  discard block
 block discarded – undo
177 177
                         SessionAlert::success('Enabled TOTP.');
178 178
 
179 179
                         $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
180
-                        if($scratchProvider->getRemaining($currentUser->getId()) < 3) {
180
+                        if ($scratchProvider->getRemaining($currentUser->getId()) < 3) {
181 181
                             $scratchProvider->setCredential($currentUser, 2, null);
182 182
                             $tokens = $scratchProvider->getTokens();
183 183
                             $this->assign('tokens', $tokens);
@@ -257,7 +257,7 @@  discard block
 block discarded – undo
257 257
 
258 258
                     list($data, $reqs) = $otpCredentialProvider->getRegistrationData();
259 259
 
260
-                    $u2fRequest =json_encode($data);
260
+                    $u2fRequest = json_encode($data);
261 261
                     $u2fSigns = json_encode($reqs);
262 262
 
263 263
                     $this->addJs('/vendor/yubico/u2flib-server/examples/assets/u2f-api.js');
@@ -306,7 +306,7 @@  discard block
 block discarded – undo
306 306
                     SessionAlert::success('Enabled U2F.');
307 307
 
308 308
                     $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
309
-                    if($scratchProvider->getRemaining($currentUser->getId()) < 3) {
309
+                    if ($scratchProvider->getRemaining($currentUser->getId()) < 3) {
310 310
                         $scratchProvider->setCredential($currentUser, 2, null);
311 311
                         $tokens = $scratchProvider->getTokens();
312 312
                         $this->assign('tokens', $tokens);
@@ -419,11 +419,11 @@  discard block
 block discarded – undo
419 419
 
420 420
             if ($result) {
421 421
                 $otpCredentialProvider->deleteCredential($currentUser);
422
-                SessionAlert::success('Disabled ' . $factorType . '.');
422
+                SessionAlert::success('Disabled '.$factorType.'.');
423 423
                 $this->redirect('multiFactor');
424 424
             }
425 425
             else {
426
-                SessionAlert::error('Error disabling ' . $factorType . ' - invalid credentials.');
426
+                SessionAlert::error('Error disabling '.$factorType.' - invalid credentials.');
427 427
                 $this->redirect('multiFactor');
428 428
             }
429 429
         }
Please login to merge, or discard this patch.
includes/Pages/UserAuth/Login/PageU2FLogin.php 1 patch
Indentation   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -14,20 +14,20 @@  discard block
 block discarded – undo
14 14
 
15 15
 class PageU2FLogin extends LoginCredentialPageBase
16 16
 {
17
-    protected function providerSpecificSetup()
18
-    {
19
-        $this->assign('showSignIn', false);
20
-        $this->setTemplate('login/u2f.tpl');
17
+	protected function providerSpecificSetup()
18
+	{
19
+		$this->assign('showSignIn', false);
20
+		$this->setTemplate('login/u2f.tpl');
21 21
 
22
-        if ($this->partialUser === null) {
23
-            throw new ApplicationLogicException("U2F cannot be first-stage authentication");
24
-        }
22
+		if ($this->partialUser === null) {
23
+			throw new ApplicationLogicException("U2F cannot be first-stage authentication");
24
+		}
25 25
 
26
-        $u2f = new U2FCredentialProvider($this->getDatabase(), $this->getSiteConfiguration());
27
-        $authData = json_encode($u2f->getAuthenticationData($this->partialUser));
26
+		$u2f = new U2FCredentialProvider($this->getDatabase(), $this->getSiteConfiguration());
27
+		$authData = json_encode($u2f->getAuthenticationData($this->partialUser));
28 28
 
29
-        $this->addJs('/vendor/yubico/u2flib-server/examples/assets/u2f-api.js');
30
-        $this->setTailScript($this->getCspManager()->getNonce(), <<<JS
29
+		$this->addJs('/vendor/yubico/u2flib-server/examples/assets/u2f-api.js');
30
+		$this->setTailScript($this->getCspManager()->getNonce(), <<<JS
31 31
 var request = {$authData};
32 32
 u2f.sign(request, function(data) {
33 33
     document.getElementById('authenticate').value=JSON.stringify(data);
@@ -35,19 +35,19 @@  discard block
 block discarded – undo
35 35
     document.getElementById('loginForm').submit();
36 36
 });
37 37
 JS
38
-        );
38
+		);
39 39
 
40
-    }
40
+	}
41 41
 
42
-    protected function getProviderCredentials()
43
-    {
44
-        $authenticate = WebRequest::postString("authenticate");
45
-        $request = WebRequest::postString("request");
42
+	protected function getProviderCredentials()
43
+	{
44
+		$authenticate = WebRequest::postString("authenticate");
45
+		$request = WebRequest::postString("request");
46 46
 
47
-        if ($authenticate === null || $authenticate === "" || $request === null || $request === "") {
48
-              throw new ApplicationLogicException("No authentication specified");
49
-        }
47
+		if ($authenticate === null || $authenticate === "" || $request === null || $request === "") {
48
+			  throw new ApplicationLogicException("No authentication specified");
49
+		}
50 50
 
51
-        return array(json_decode($authenticate), json_decode($request), 'u2f');
52
-    }
51
+		return array(json_decode($authenticate), json_decode($request), 'u2f');
52
+	}
53 53
 }
Please login to merge, or discard this patch.
includes/Security/ContentSecurityPolicyManager.php 2 patches
Indentation   +54 added lines, -54 removed lines patch added patch discarded remove patch
@@ -10,67 +10,67 @@
 block discarded – undo
10 10
 
11 11
 class ContentSecurityPolicyManager
12 12
 {
13
-    private $policy = [
14
-        'default-src'     => [],
15
-        'script-src-elem' => ['self', 'nonce'],
16
-        'connect-src'     => ['self'],
17
-        'style-src-elem'  => ['self'],
18
-        'img-src'         => ['self', 'data:', 'https://upload.wikimedia.org'],
19
-        'font-src'        => ['self'],
20
-        'form-action'     => ['self'],
21
-        'frame-ancestors' => [],
22
-    ];
13
+	private $policy = [
14
+		'default-src'     => [],
15
+		'script-src-elem' => ['self', 'nonce'],
16
+		'connect-src'     => ['self'],
17
+		'style-src-elem'  => ['self'],
18
+		'img-src'         => ['self', 'data:', 'https://upload.wikimedia.org'],
19
+		'font-src'        => ['self'],
20
+		'form-action'     => ['self'],
21
+		'frame-ancestors' => [],
22
+	];
23 23
 
24
-    private $nonce = null;
25
-    private $reportOnly = false;
24
+	private $nonce = null;
25
+	private $reportOnly = false;
26 26
 
27
-    public function getNonce()
28
-    {
29
-        if($this->nonce === null) {
30
-            $this->nonce = base64_encode(openssl_random_pseudo_bytes(32));
31
-        }
27
+	public function getNonce()
28
+	{
29
+		if($this->nonce === null) {
30
+			$this->nonce = base64_encode(openssl_random_pseudo_bytes(32));
31
+		}
32 32
 
33
-        return $this->nonce;
34
-    }
33
+		return $this->nonce;
34
+	}
35 35
 
36
-    public function getHeader() : string
37
-    {
38
-        $reportOnly = '';
39
-        if($this->reportOnly) {
40
-            $reportOnly = '-Report-Only';
41
-        }
36
+	public function getHeader() : string
37
+	{
38
+		$reportOnly = '';
39
+		if($this->reportOnly) {
40
+			$reportOnly = '-Report-Only';
41
+		}
42 42
 
43
-        $constructedPolicy = "Content-Security-Policy{$reportOnly}: ";
43
+		$constructedPolicy = "Content-Security-Policy{$reportOnly}: ";
44 44
 
45
-        foreach ($this->policy as $item => $values) {
46
-            $constructedPolicy .= $item . ' ';
45
+		foreach ($this->policy as $item => $values) {
46
+			$constructedPolicy .= $item . ' ';
47 47
 
48
-            if (count($values) > 0) {
49
-                foreach ($values as $value) {
50
-                    switch ($value) {
51
-                        case 'none':
52
-                        case 'self':
53
-                        case 'strict-dynamic':
54
-                            $constructedPolicy .= "'{$value}' ";
55
-                            break;
56
-                        case 'nonce':
57
-                            if($this->nonce !== null) {
58
-                                $constructedPolicy .= "'nonce-{$this->nonce}' ";
59
-                            }
60
-                            break;
61
-                        default:
62
-                            $constructedPolicy .= $value . ' ';
63
-                            break;
64
-                    }
65
-                }
66
-            }
67
-            else {
68
-                $constructedPolicy .= "'none' ";
69
-            }
48
+			if (count($values) > 0) {
49
+				foreach ($values as $value) {
50
+					switch ($value) {
51
+						case 'none':
52
+						case 'self':
53
+						case 'strict-dynamic':
54
+							$constructedPolicy .= "'{$value}' ";
55
+							break;
56
+						case 'nonce':
57
+							if($this->nonce !== null) {
58
+								$constructedPolicy .= "'nonce-{$this->nonce}' ";
59
+							}
60
+							break;
61
+						default:
62
+							$constructedPolicy .= $value . ' ';
63
+							break;
64
+					}
65
+				}
66
+			}
67
+			else {
68
+				$constructedPolicy .= "'none' ";
69
+			}
70 70
 
71
-            $constructedPolicy .= '; ';
72
-        }
71
+			$constructedPolicy .= '; ';
72
+		}
73 73
 
74
-        return $constructedPolicy;
75
-    }
74
+		return $constructedPolicy;
75
+	}
76 76
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -26,7 +26,7 @@  discard block
 block discarded – undo
26 26
 
27 27
     public function getNonce()
28 28
     {
29
-        if($this->nonce === null) {
29
+        if ($this->nonce === null) {
30 30
             $this->nonce = base64_encode(openssl_random_pseudo_bytes(32));
31 31
         }
32 32
 
@@ -36,14 +36,14 @@  discard block
 block discarded – undo
36 36
     public function getHeader() : string
37 37
     {
38 38
         $reportOnly = '';
39
-        if($this->reportOnly) {
39
+        if ($this->reportOnly) {
40 40
             $reportOnly = '-Report-Only';
41 41
         }
42 42
 
43 43
         $constructedPolicy = "Content-Security-Policy{$reportOnly}: ";
44 44
 
45 45
         foreach ($this->policy as $item => $values) {
46
-            $constructedPolicy .= $item . ' ';
46
+            $constructedPolicy .= $item.' ';
47 47
 
48 48
             if (count($values) > 0) {
49 49
                 foreach ($values as $value) {
@@ -54,12 +54,12 @@  discard block
 block discarded – undo
54 54
                             $constructedPolicy .= "'{$value}' ";
55 55
                             break;
56 56
                         case 'nonce':
57
-                            if($this->nonce !== null) {
57
+                            if ($this->nonce !== null) {
58 58
                                 $constructedPolicy .= "'nonce-{$this->nonce}' ";
59 59
                             }
60 60
                             break;
61 61
                         default:
62
-                            $constructedPolicy .= $value . ' ';
62
+                            $constructedPolicy .= $value.' ';
63 63
                             break;
64 64
                     }
65 65
                 }
Please login to merge, or discard this patch.