Completed
Push — sessionstart ( 52a658 )
by Simon
03:37
created

acc.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**************************************************************************
3
**********      English Wikipedia Account Request Interface      **********
4
***************************************************************************
5
** Wikipedia Account Request Graphic Design by Charles Melbye,           **
6
** which is licensed under a Creative Commons                            **
7
** Attribution-Noncommercial-Share Alike 3.0 United States License.      **
8
**                                                                       **
9
** All other code are released under the Public Domain                   **
10
** by the ACC Development Team.                                          **
11
**                                                                       **
12
** See CREDITS for the list of developers.                               **
13
***************************************************************************/
14
15
// stop all output until we want it
16
ob_start();
17
18
// load the configuration
19
require_once 'config.inc.php';
20
21
// Get all the classes.
22
require_once 'functions.php';
23
initialiseSession();
24
require_once 'includes/PdoDatabase.php';
25
require_once 'includes/SmartyInit.php'; // this needs to be high up, but below config, functions, database and session init
0 ignored issues
show
This line exceeds maximum limit of 120 characters; contains 123 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
26
require_once 'includes/session.php';
27
28
// Check to see if the database is unavailable.
29
// Uses the false variable as its the internal interface.
30
if (Offline::isOffline()) {
31
	echo Offline::getOfflineMessage(false);
32
	die();
33
}
34
35
// Initialize the class objects.
36
$session = new session();
37
$date = new DateTime();
38
39
// initialise providers
40
global $squidIpList;
41
/** @var ILocationProvider $locationProvider */
42
$locationProvider = new $locationProviderClass(gGetDb('acc'), $locationProviderApiKey);
43
/** @var IRDnsProvider $rdnsProvider */
44
$rdnsProvider = new $rdnsProviderClass(gGetDb('acc'));
45
/** @var IAntiSpoofProvider $antispoofProvider */
46
$antispoofProvider = new $antispoofProviderClass();
47
/** @var IXffTrustProvider $xffTrustProvider */
48
$xffTrustProvider = new $xffTrustProviderClass($squidIpList);
49
50
// Clears the action variable.
51
$action = '';
52
53
// Assign the correct value to the action variable.
54
// The value is retrieved from the $GET variable.
55
if (isset($_GET['action'])) {
56
	$action = $_GET['action'];
57
}
58
59
// Clear session before banner and logged in as message is generated on logout attempt - Prom3th3an
60
if ($action == "logout") {
61
	session_unset();
62
    
63
	BootstrapSkin::displayInternalHeader();
64
	echo showlogin();
65
	BootstrapSkin::displayInternalFooter();
66
	die();
67
}
68
69
// Checks whether the user is set - the user should first login.
70
if (!isset($_SESSION['user'])) {
71
	$suser = '';
72
	BootstrapSkin::displayInternalHeader();
73
74
	// Checks whether the user want to reset his password or register a new account.
75
	// Performs the clause when the action is not one of the above options.
76
	if ($action != 'register' && $action != 'forgotpw' && $action != 'sreg' && $action != "registercomplete" && $action != "login") {
77
		echo showlogin();
78
		BootstrapSkin::displayInternalFooter();
79
		die();
80
	}
81
	else {
82
		// A content block is created if the action is none of the above.
83
		// This block would later be used to keep all the HTML except the header and footer.
84
		$out = "<div id=\"content\">";
85
		echo $out;
86
	}
87
}
88
89
// Forces the current user to logout if necessary.
90
if (isset($_SESSION['userID'])) {
91
	$session->forceLogout($_SESSION['userID']);
92
}
93
94
BootstrapSkin::displayInternalHeader();
95
$session->checksecurity();
96
97
98
// When no action is specified the default Internal ACC are displayed.
99
// TODO: Improve way the method is called.
100
if ($action == '') {
101
	echo defaultpage();
102
	BootstrapSkin::displayInternalFooter();
103
	die();
104
}
105
elseif ($action == "sreg") {
106
	global $useOauthSignup, $smarty;
107
        
108
	// TODO: check blocked
109
	// TODO: check age.
110
    
111
	// check if user checked the "I have read and understand the interface guidelines" checkbox
112
	if (!isset($_REQUEST['guidelines'])) {
113
		$smarty->display("registration/alert-interfaceguidelines.tpl");
114
		BootstrapSkin::displayInternalFooter();
115
		die();
116
	}
117
	
118
	if (!filter_var($_REQUEST['email'], FILTER_VALIDATE_EMAIL)) {
119
		$smarty->display("registration/alert-invalidemail.tpl");
120
		BootstrapSkin::displayInternalFooter();
121
		die();
122
	}
123
    
124
	if ($_REQUEST['pass'] !== $_REQUEST['pass2']) {
125
		$smarty->display("registration/alert-passwordmismatch.tpl");
126
		BootstrapSkin::displayInternalFooter();
127
		die();
128
	}
129
    
130
	if (!$useOauthSignup) {
131
		if (!((string)(int)$_REQUEST['conf_revid'] === (string)$_REQUEST['conf_revid']) || $_REQUEST['conf_revid'] == "") {
132
			$smarty->display("registration/alert-confrevid.tpl");
133
			BootstrapSkin::displayInternalFooter();
134
			die();		
135
		}
136
	}
137
    
138
	if (User::getByUsername($_REQUEST['name'], gGetDb()) != false) {
139
		$smarty->display("registration/alert-usernametaken.tpl");
140
		BootstrapSkin::displayInternalFooter();
141
		die();
142
	}
143
    
144
	$query = gGetDb()->prepare("SELECT * FROM user WHERE email = :email LIMIT 1;");
145
	$query->execute(array(":email" => $_REQUEST['email']));
146
	if ($query->fetchObject("User") != false) {
147
		$smarty->display("registration/alert-emailtaken.tpl");
148
		BootstrapSkin::displayInternalFooter();
149
		die();
150
	}
151
	$query->closeCursor();
152
153
	$database = gGetDb();
154
    
155
	$database->transactionally(function() use ($database, $useOauthSignup)
156
	{
157
    
158
		$newUser = new User();
159
		$newUser->setDatabase($database);
160
    
161
		$newUser->setUsername($_REQUEST['name']);
162
		$newUser->setPassword($_REQUEST['pass']);
163
		$newUser->setEmail($_REQUEST['email']);
164
        
165
		if (!$useOauthSignup) {
166
			$newUser->setOnWikiName($_REQUEST['wname']);
167
			$newUser->setConfirmationDiff($_REQUEST['conf_revid']);
168
		}
169
        
170
		$newUser->save();
171
    
172
		global $oauthConsumerToken, $oauthSecretToken, $oauthBaseUrl, $oauthBaseUrlInternal, $useOauthSignup;
173
    
174
		if ($useOauthSignup) {
175
			try {
176
				// Get a request token for OAuth
177
				$util = new OAuthUtility($oauthConsumerToken, $oauthSecretToken, $oauthBaseUrl, $oauthBaseUrlInternal);
178
				$requestToken = $util->getRequestToken();
179
    
180
				// save the request token for later
181
				$newUser->setOAuthRequestToken($requestToken->key);
182
				$newUser->setOAuthRequestSecret($requestToken->secret);
183
				$newUser->save();
184
            
185
				Notification::userNew($newUser);
186
        
187
				$redirectUrl = $util->getAuthoriseUrl($requestToken);
188
            
189
				header("Location: {$redirectUrl}");
190
			}
191
			catch (Exception $ex) {
192
				throw new TransactionException(
193
					$ex->getMessage(), 
194
					"Connection to Wikipedia failed.", 
195
					"alert-error", 
196
					0, 
197
					$ex);
198
			}
199
		}
200
		else {
201
			global $baseurl;
202
			Notification::userNew($newUser);
203
			header("Location: {$baseurl}/acc.php?action=registercomplete");
204
		}
205
	});
206
    
207
	die();
208
}
209
elseif ($action == "register") {
210
	global $useOauthSignup, $smarty;
211
	$smarty->assign("useOauthSignup", $useOauthSignup);
212
	$smarty->display("registration/register.tpl");
213
	BootstrapSkin::displayInternalFooter();
214
	die();
215
}
216
elseif ($action == "registercomplete") {
217
	$smarty->display("registration/alert-registrationcomplete.tpl");
218
	BootstrapSkin::displayInternalFooter();
219
}
220
elseif ($action == "forgotpw") {
221
	global $baseurl, $smarty;
222
    
223
	if (isset ($_GET['si']) && isset ($_GET['id'])) {
224
		$user = User::getById($_GET['id'], gGetDb());
225
        
226
		if ($user === false) {
227
			BootstrapSkin::displayAlertBox("User not found.", "alert-error");
228
			BootstrapSkin::displayInternalFooter();
229
			die();
230
		}
231
        
232
		if (isset ($_POST['pw']) && isset ($_POST['pw2'])) {
233
			$hash = $user->getForgottenPasswordHash();
234
            
235
			if ($hash == $_GET['si']) {
236
				if ($_POST['pw'] == $_POST['pw2']) {
237
					$user->setPassword($_POST['pw2']);
238
					$user->save();
239
                    
240
					BootstrapSkin::displayAlertBox(
241
						"You may now <a href=\"$baseurl/acc.php\">Login</a>", 
242
						"alert-error", 
243
						"Password reset!", 
244
						true, 
245
						false);
246
                    
247
					BootstrapSkin::displayInternalFooter();
248
					die();
249
				}
250
				else {
251
					BootstrapSkin::displayAlertBox("Passwords did not match!", "alert-error", "Error", true, false);
252
					BootstrapSkin::displayInternalFooter();
253
					die();
254
				}
255
			}
256
			else {
257
				BootstrapSkin::displayAlertBox("Invalid request<!-- 1 -->", "alert-error", "Error", true, false);
258
				BootstrapSkin::displayInternalFooter();
259
				die();
260
			}
261
		}
262
        
263
		$hash = $user->getForgottenPasswordHash();
264
        
265
		if ($hash == $_GET['si']) {
266
			$smarty->assign('user', $user);
267
			$smarty->assign('si', $_GET['si']);
268
			$smarty->assign('id', $_GET['id']);
269
			$smarty->display('forgot-password/forgotpwreset.tpl');
270
		}
271
		else {
272
			BootstrapSkin::displayAlertBox(
273
				"The hash supplied in the link did not match the hash in the database!", 
274
				"alert-error", 
275
				"Invalid request", 
276
				true, 
277
				false);
278
		}
279
        
280
		BootstrapSkin::displayInternalFooter();
281
		die();
282
	}
283
    
284
	if (isset ($_POST['username'])) {
285
		$user = User::getByUsername($_POST['username'], gGetDb());
286
287
		if ($user == false) {
288
			BootstrapSkin::displayAlertBox(
289
				"Could not find user with that username and email address!", 
290
				"alert-error", 
291
				"Error", 
292
				true, 
293
				false);
294
            
295
			BootstrapSkin::displayInternalFooter();
296
			die();
297
		}
298
		elseif (strtolower($_POST['email']) != strtolower($user->getEmail())) {
299
			BootstrapSkin::displayAlertBox("Could not find user with that username and email address!", 
300
				"alert-error", 
301
				"Error", 
302
				true, 
303
				false);
304
            
305
			BootstrapSkin::displayInternalFooter();
306
			die();
307
		}
308
		else {
309
			$hash = $user->getForgottenPasswordHash();
310
                       
311
			$smarty->assign("user", $user);
312
			$smarty->assign("hash", $hash);
313
			$smarty->assign("remoteAddress", $_SERVER['REMOTE_ADDR']);
314
            
315
			$mailtxt = $smarty->fetch("forgot-password/reset-mail.tpl");
316
			$headers = 'From: [email protected]';
317
            
318
			mail(
319
				$user->getEmail(), 
320
				"English Wikipedia Account Request System - Forgotten password", 
321
				$mailtxt, 
322
				$headers);
323
            
324
			BootstrapSkin::displayAlertBox(
325
				"<strong>Your password reset request has been completed.</strong> Please check your e-mail.", 
326
				"alert-success", 
327
				"", 
328
				false, 
329
				false);
330
            
331
			BootstrapSkin::displayInternalFooter();
332
			die();
333
		}
334
	}
335
    
336
	$smarty->display('forgot-password/forgotpw.tpl');
337
338
	BootstrapSkin::displayInternalFooter();
339
	die();
340
}
341
elseif ($action == "login") {
342
	global $baseurl, $smarty;
343
    
344
	if (!isset($_POST['username'])) {
345
		header("Location: $baseurl/acc.php?error=authfail&tplUsername=");
346
		die();
347
	}
348
349
	$user = User::getByUsername($_POST['username'], gGetDb());
350
    
351
	if ($user == false || !$user->authenticate($_POST['password'])) {
352
		header("Location: $baseurl/acc.php?error=authfail&tplUsername=" . urlencode($_POST['username']));
353
		die();
354
	}
355
    
356
	if ($user->getStoredOnWikiName() == "##OAUTH##" && $user->getOAuthAccessToken() == null) {
357
		reattachOAuthAccount($user);   
358
	}
359
    
360
	if ($user->isOAuthLinked()) {
361
		try {
362
			// test retrieval of the identity
363
			$user->getOAuthIdentity();
364
		}
365
		catch (TransactionException $ex) {
366
			$user->setOAuthAccessToken(null);
367
			$user->setOAuthAccessSecret(null);
368
			$user->save();
369
            
370
			reattachOAuthAccount($user);
371
		}
372
	}
373
	else {
374
		global $enforceOAuth;
375
        
376
		if ($enforceOAuth) {
377
			reattachOAuthAccount($user);
378
		}
379
	}
380
    
381
	// At this point, the user has successfully authenticated themselves.
382
	// We now proceed to perform login-specific actions, and check the user actually has
383
	// the correct permissions to continue with the login.
384
    
385
	if ($user->getForcelogout()) {
386
		$user->setForcelogout(false);
387
		$user->save();
388
	}
389
    
390
	if ($user->isNew()) {
391
		header("Location: $baseurl/acc.php?error=newacct");
392
		die();
393
	}
394
    
395
	$database = gGetDb();
396
    
397
	$sqlText = <<<SQL
398
SELECT comment FROM log
399
WHERE action = :action AND objectid = :userid AND objecttype = 'User'
400
ORDER BY timestamp DESC LIMIT 1;
401
SQL;
402
    
403
	$suspendstatement = $database->prepare($sqlText);
404
    
405 View Code Duplication
	if ($user->isDeclined()) {
406
		$suspendAction = "Declined";
407
		$userid = $user->getId();
408
		$suspendstatement->bindValue(":action", $suspendAction);
409
		$suspendstatement->bindValue(":userid", $userid);
410
		$suspendstatement->execute();
411
        
412
		$suspendreason = $suspendstatement->fetchColumn();
413
        
414
		$suspendstatement->closeCursor();
415
        
416
		BootstrapSkin::displayInternalHeader();
417
		$smarty->assign("suspendreason", $suspendreason);
418
		$smarty->display("login/declined.tpl");
419
		BootstrapSkin::displayInternalFooter();
420
		die();
421
	}
422
    
423 View Code Duplication
	if ($user->isSuspended()) {
424
		$suspendAction = "Suspended";
425
		$userid = $user->getId();
426
		$suspendstatement->bindValue(":action", $suspendAction);
427
		$suspendstatement->bindValue(":userid", $userid);
428
		$suspendstatement->execute();
429
        
430
		$suspendreason = $suspendstatement->fetchColumn();
431
        
432
		$suspendstatement->closeCursor();
433
        
434
		BootstrapSkin::displayInternalHeader();
435
		$smarty->assign("suspendreason", $suspendreason);
436
		$smarty->display("login/suspended.tpl");
437
		BootstrapSkin::displayInternalFooter();
438
		die();
439
	}
440
    
441
	if (!$user->isIdentified() && $forceIdentification == 1) {
442
		header("Location: $baseurl/acc.php?error=noid");
443
		die();
444
	}
445
    
446
	// At this point, we've tested that the user is OK, so we set the login cookies.
447
    
448
	$_SESSION['user'] = $user->getUsername();
449
	$_SESSION['userID'] = $user->getId();
450
    
451
	if ($user->getOAuthAccessToken() == null && $user->getStoredOnWikiName() == "##OAUTH##") {
452
		reattachOAuthAccount($user);
453
	}
454
    
455
	header("Location: $baseurl/acc.php");
456
}
457
elseif ($action == "messagemgmt") {
458
	global $smarty;
459
    
460
	if (isset($_GET['view'])) {
461
		$message = InterfaceMessage::getById($_GET['view'], gGetDb());
462
                
463
		if ($message == false) {
464
			BootstrapSkin::displayAlertBox("Unable to find specified message", "alert-error", "Error", true, false);
465
			BootstrapSkin::displayInternalFooter();
466
			die();
467
		}
468
        
469
		$smarty->assign("message", $message);
470
		$smarty->assign("readonly", true);
471
		$smarty->display("message-management/editform.tpl");
472
		BootstrapSkin::displayInternalFooter();
473
		die();
474
	}
475
	if (isset($_GET['edit'])) {
476
		if (!(User::getCurrent()->isAdmin() || User::getCurrent()->isCheckuser())) {
477
			BootstrapSkin::displayAccessDenied();
478
			BootstrapSkin::displayInternalFooter();
479
			die();
480
		}
481
        
482
		$database = gGetDb();
483
        
484
		$database->transactionally(function() use ($database)
485
		{
486
			global $smarty;
487
            
488
			$message = InterfaceMessage::getById($_GET['edit'], $database);
489
            
490
			if ($message == false) {
491
				throw new TransactionException("Unable to find specified message", "Error");
492
			}
493
            
494
			if (isset($_GET['submit'])) {
495
				$message->setContent($_POST['mailtext']);
496
				$message->setDescription($_POST['maildesc']);
497
				$message->save();
498
            
499
				Logger::interfaceMessageEdited(gGetDb(), $message);
500
              
501
				$smarty->assign("message", $message);
502
				$smarty->display("message-management/alert-editsuccess.tpl");
503
                
504
				Notification::interfaceMessageEdited($message);
505
                
506
				BootstrapSkin::displayInternalFooter();
507
				return;
508
			}
509
            
510
			$smarty->assign("message", $message);
511
			$smarty->assign("readonly", false);
512
			$smarty->display("message-management/editform.tpl");
513
        
514
			BootstrapSkin::displayInternalFooter();
515
		});
516
        
517
		die();
518
	}
519
    
520
	$sqlText = <<<SQL
521
        SELECT * 
522
        FROM interfacemessage 
523
        WHERE type = :type 
524
            AND description NOT LIKE '%[deprecated]';
525
SQL;
526
    
527
	$fetchStatement = gGetDb()->prepare($sqlText);
528
	$data = array();
529
        
530
	//$fetchStatement->execute(array(":type" => "Interface"));
531
	//$data['Public Interface messages'] = $fetchStatement->fetchAll(PDO::FETCH_CLASS, 'InterfaceMessage');
532
    
533
	$fetchStatement->execute(array(":type" => "Internal"));
534
	$data['Internal Interface messages'] = $fetchStatement->fetchAll(PDO::FETCH_CLASS, 'InterfaceMessage');
535
    
536
	$smarty->assign("data", $data);
537
	$smarty->display('message-management/view.tpl');
538
   
539
	BootstrapSkin::displayInternalFooter();
540
	die();
541
}
542
elseif ($action == "templatemgmt") {
543
	global $baseurl, $smarty;
544
    
545
	if (isset($_GET['view'])) {
546
		$template = WelcomeTemplate::getById($_GET['view'], gGetDb());
547
        
548
		if ($template === false) {
549
			SessionAlert::success("Something went wrong, we can't find the template you asked for! Please try again.");
550
			header("Location: {$baseurl}/acc.php?action=templatemgmt");
551
			die();
552
		}
553
        
554
		$smarty->assign("template", $template);
555
		$smarty->display("welcometemplate/view.tpl");
556
		BootstrapSkin::displayInternalFooter();
557
		die();
558
	}
559
    
560
	if (isset($_GET['add'])) {
561
		if (!User::getCurrent()->isAdmin() && !User::getCurrent()->isCheckuser()) {
562
			BootstrapSkin::displayAccessDenied();
563
            
564
			BootstrapSkin::displayInternalFooter();
565
			die();
566
		}
567
        
568
		if (isset($_POST['submit'])) {
569
			global $baseurl;
570
            
571
			$database = gGetDb();
572
            
573 View Code Duplication
			$database->transactionally(function() use ($database, $baseurl)
574
			{
575
				$template = new WelcomeTemplate();
576
				$template->setDatabase($database);
577
				$template->setUserCode($_POST['usercode']);
578
				$template->setBotCode($_POST['botcode']);
579
				$template->save();
580
            
581
				Logger::welcomeTemplateCreated($database, $template);
582
                            
583
				Notification::welcomeTemplateCreated($template);
584
            
585
				SessionAlert::success("Template successfully created.");
586
				header("Location: $baseurl/acc.php?action=templatemgmt");
587
			});
588
		}
589
		else {
590
			
591
			if (isset($_POST['preview'])) {
592
				$usercode = $_POST['usercode'];
593
				$botcode = $_POST['botcode'];
594
				echo displayPreview($usercode);
595
			}
596
			else {
597
				$usercode = '';
598
				$botcode = '';
599
			}
600
601
			$smarty->assign("usercode", $usercode);
602
			$smarty->assign("botcode", $botcode);
603
            
604
			$smarty->display("welcometemplate/add.tpl");
605
			BootstrapSkin::displayInternalFooter();
606
			die();
607
		}
608
        
609
		die();
610
	}
611
    
612
	if (isset($_GET['select'])) {
613
		$user = User::getCurrent();
614
        
615
		if ($_GET['select'] == 0) {
616
			$user->setWelcomeTemplate(null);
617
			$user->save();
618
            
619
			SessionAlert::success("Disabled automatic user welcoming.");
620
			header("Location: {$baseurl}/acc.php?action=templatemgmt");
621
			die();
622
		}
623
		else {
624
			$template = WelcomeTemplate::getById($_GET['select'], gGetDb());
625
			if ($template !== false) {
626
				$user->setWelcomeTemplate($template->getId());
627
				$user->save();
628
                
629
				SessionAlert::success("Updated selected welcome template for automatic welcoming.");
630
				header("Location: {$baseurl}/acc.php?action=templatemgmt");
631
				die();
632
			}
633
			else {
634
				SessionAlert::error("Something went wrong, we can't find the template you asked for!");
635
				header("Location: {$baseurl}/acc.php?action=templatemgmt");
636
				die();
637
			}
638
		}
639
	}
640
    
641
	if (isset($_GET['del'])) {
642
		global $baseurl;
643
        
644
		if (!User::getCurrent()->isAdmin() && !User::getCurrent()->isCheckuser()) {
645
			BootstrapSkin::displayAccessDenied();
646
			BootstrapSkin::displayInternalFooter();
647
			die();
648
		}
649
650
		$database = gGetDb();
651
        
652
		$template = WelcomeTemplate::getById($_GET['del'], $database);
653
		if ($template == false) {
654
			SessionAlert::error("Something went wrong, we can't find the template you asked for!");
655
			header("Location: {$baseurl}/acc.php?action=templatemgmt");
656
			die();
657
		}
658
        
659
		$database->transactionally(function() use($database, $template)
660
		{
661
			$tid = $template->getId();
662
            
663
			$database
664
				->prepare("UPDATE user SET welcome_template = NULL WHERE welcome_template = :id;")
665
				->execute(array(":id" => $tid));
666
            
667
			Logger::welcomeTemplateDeleted($database, $template);
668
            
669
			$template->delete();
670
            
671
			SessionAlert::success("Template deleted. Any users who were using this template have had automatic welcoming disabled.");
672
			Notification::welcomeTemplateDeleted($tid);
673
		});
674
        
675
		header("Location: $baseurl/acc.php?action=templatemgmt");
676
		die();			
677
	}
678
    
679
	if (isset($_GET['edit'])) {
680
		if (!User::getCurrent()->isAdmin() && !User::getCurrent()->isCheckuser()) {
681
			BootstrapSkin::displayAccessDenied();
682
			BootstrapSkin::displayInternalFooter();
683
			die();
684
		}
685
686
		$database = gGetDb();
687
        
688
		$template = WelcomeTemplate::getById($_GET['edit'], $database);
689
		if ($template == false) {
690
			SessionAlert::success("Something went wrong, we can't find the template you asked for! Please try again.");
691
			header("Location: {$baseurl}/acc.php?action=templatemgmt");
692
			die();
693
		}
694
695
		if (isset($_POST['submit'])) {
696
			$database->transactionally(function() use($database, $template)
697
			{
698
				$template->setUserCode($_POST['usercode']);
699
				$template->setBotCode($_POST['botcode']);
700
				$template->save();
701
			
702
				Logger::welcomeTemplateEdited($database, $template);
703
                
704
				SessionAlert::success("Template updated.");
705
				Notification::welcomeTemplateEdited($template);
706
			});
707
            
708
			header("Location: $baseurl/acc.php?action=templatemgmt");
709
			die();
710
		}
711
		else {
712
			$smarty->assign("template", $template);
713
			$smarty->display("welcometemplate/edit.tpl");
714
            
715
			BootstrapSkin::displayInternalFooter();
716
			die();
717
		}
718
	}
719
    
720
	$templateList = WelcomeTemplate::getAll();
721
    
722
	$smarty->assign("templatelist", $templateList);
723
	$smarty->display("welcometemplate/list.tpl");
724
    
725
	BootstrapSkin::displayInternalFooter();
726
	die();
727
}
728
elseif ($action == "sban") {
729
	global $smarty;
730
    
731
	// Checks whether the current user is an admin.
732
	if (!User::getCurrent()->isAdmin() && !User::getCurrent()->isCheckuser()) {
733
		BootstrapSkin::displayAccessDenied();
734
		BootstrapSkin::displayInternalFooter();
735
		die();
736
	}
737
	
738
	// Checks whether there is a reason entered for ban.
739
	if (!isset($_POST['banreason']) || $_POST['banreason'] == "") {
740
		BootstrapSkin::displayAlertBox("You must specify a ban reason", "alert-error", "", false, false);
741
		BootstrapSkin::displayInternalFooter();
742
		die();
743
	}
744
	
745
	// Checks whether there is a target entered to ban.
746
	if (!isset($_POST['target']) || $_POST['target'] == "") {
747
		BootstrapSkin::displayAlertBox("You must specify a target to be banned", "alert-error", "", false, false);
748
		BootstrapSkin::displayInternalFooter();
749
		die();
750
	}
751
	
752
	$duration = $_POST['duration'];
753
    
754
	if ($duration == "-1") {
755
		$duration = -1;
756
	}
757
	elseif ($duration == "other") {
758
		$duration = strtotime($_POST['otherduration']);
759
		if (!$duration) {
760
			BootstrapSkin::displayAlertBox("Invalid ban time", "alert-error", "", false, false);
761
			BootstrapSkin::displayInternalFooter();
762
			die();
763
		}
764
		elseif (time() > $duration) {
765
			BootstrapSkin::displayAlertBox("Ban time has already expired!", "alert-error", "", false, false);
766
			BootstrapSkin::displayInternalFooter();
767
			die();
768
		}
769
	}
770
	else {
771
		$duration = $duration + time();
772
	}
773
    
774
	switch ($_POST['type']) {
775
		case 'IP':
776 View Code Duplication
			if (filter_var($_POST['target'], FILTER_VALIDATE_IP) === false) {
777
				BootstrapSkin::displayAlertBox("Invalid target - IP address expected.", "alert-error", "", false, false);
778
				BootstrapSkin::displayInternalFooter();
779
				die();
780
			}
781
            
782
			global $squidIpList;
783
			if (in_array($_POST['target'], $squidIpList)) {
784
				BootstrapSkin::displayAlertBox(
785
					"This IP address is on the protected list of proxies, and cannot be banned.", 
786
					"alert-error", 
787
					"", 
788
					false, 
789
					false);
790
				BootstrapSkin::displayInternalFooter();
791
				die();
792
			}
793
			break;
794
		case 'Name':
795
			break;
796
		case 'EMail':
797
			// TODO: cut this down to a bare-bones implementation so we don't accidentally reject a valid address.
798
			if (!preg_match(';^(?:[A-Za-z0-9!#$%&\'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&\'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?\.)+[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[A-Za-z0-9-]*[A-Za-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$;', $_POST['target'])) {
799
				BootstrapSkin::displayAlertBox(
800
					"Invalid target - email address expected.", 
801
					"alert-error", 
802
					"", 
803
					false, 
804
					false);
805
                
806
				BootstrapSkin::displayInternalFooter();
807
				die();
808
			}
809
			break;
810
		default:
811
			BootstrapSkin::displayAlertBox("I don't know what type of target you want to ban! You'll need to choose from email address, IP, or requested name.", "alert-error", "", false, false);
812
			BootstrapSkin::displayInternalFooter();
813
			die();
814
	}
815
        
816
	if (count(Ban::getActiveBans($_POST['target'])) > 0) {
817
		BootstrapSkin::displayAlertBox("This target is already banned!", "alert-error", "", false, false);
818
		BootstrapSkin::displayInternalFooter();
819
		die();
820
	}
821
    
822
	$database = gGetDb();
823
    
824
	$ban = new Ban();
825
    
826
	$currentUsername = User::getCurrent()->getUsername();
827
    
828
	$database->transactionally(function() use ($database, $ban, $duration, $currentUsername)
829
	{
830
		$ban->setDatabase($database);
831
		$ban->setActive(1);
832
		$ban->setType($_POST['type']);
833
		$ban->setTarget($_POST['target']);
834
		$ban->setUser($currentUsername);
835
		$ban->setReason($_POST['banreason']);
836
		$ban->setDuration($duration);
837
    
838
		$ban->save();
839
        
840
		Logger::banned($database, $ban, $_POST['banreason']);
841
	});
842
    
843
	$smarty->assign("ban", $ban);
844
	BootstrapSkin::displayAlertBox($smarty->fetch("bans/bancomplete.tpl"), "alert-info", "", false, false);
845
        
846
	Notification::banned($ban);
847
    
848
	BootstrapSkin::displayInternalFooter();
849
	die();
850
}
851
elseif ($action == "unban") {
852
	global $smarty;
853
    
854
	if (!isset($_GET['id']) || $_GET['id'] == "") {
855
		BootstrapSkin::displayAlertBox(
856
			"The ID parameter appears to be missing! This is probably a bug.", 
857
			"alert-error", 
858
			"Ahoy There! Something's not right...", 
859
			true, 
860
			false);
861
		BootstrapSkin::displayInternalFooter();
862
		die();
863
	}
864
    
865
	if (!User::getCurrent()->isAdmin() && !User::getCurrent()->isCheckuser()) {
866
		BootstrapSkin::displayAccessDenied();
867
		BootstrapSkin::displayInternalFooter();
868
		die();
869
	}
870
    
871
	$ban = Ban::getActiveId($_GET['id']);
872
        
873
	if ($ban == false) {
874
		BootstrapSkin::displayAlertBox(
875
			"The specified ban ID is not currently active or doesn't exist!", 
876
			"alert-error", 
877
			"", 
878
			false, 
879
			false);
880
        
881
		BootstrapSkin::displayInternalFooter();
882
		die();
883
	}
884
885
	if (isset($_GET['confirmunban']) && $_GET['confirmunban'] == "true") {
886
		if (!isset($_POST['unbanreason']) || $_POST['unbanreason'] == "") {
887
			BootstrapSkin::displayAlertBox("You must enter an unban reason!", "alert-error", "", false, false);
888
			BootstrapSkin::displayInternalFooter();
889
			die();
890
		}
891
		else {
892
			$database = gGetDb();
893
            
894
			$database->transactionally(function() use ($database, $ban)
895
			{
896
				$ban->setActive(0);
897
				$ban->save();
898
                
899
				$banId = $ban->getId();
900
				$currentUser = User::getCurrent()->getUsername();
901
                
902
				Logger::unbanned($database, $ban, $_POST['unbanreason']);
903
			});
904
        
905
			BootstrapSkin::displayAlertBox("Unbanned " . $ban->getTarget(), "alert-info", "", false, false);
906
			BootstrapSkin::displayInternalFooter();
907
			Notification::unbanned($ban, $_POST['unbanreason']);
908
			die();
909
		}
910
	}
911
	else {
912
		$smarty->assign("ban", $ban);
913
		$smarty->display("bans/unban.tpl");
914
        
915
		BootstrapSkin::displayInternalFooter();
916
	}
917
}
918
elseif ($action == "ban") {
919
	global $smarty;
920
    
921
	if (isset ($_GET['ip']) || isset ($_GET['email']) || isset ($_GET['name'])) {
922
		if (!User::getCurrent()->isAdmin() && !User::getCurrent()->isCheckuser()) {
923
			BootstrapSkin::displayAlertBox("Only administrators or checkusers may ban users", "alert-error");
924
			BootstrapSkin::displayInternalFooter();
925
			die();
926
		}
927
        
928
		$database = gGetDb();
929
		// TODO: rewrite me!
930
		if (isset($_GET['ip'])) {
931
			$query = "SELECT ip, forwardedip FROM request WHERE id = :ip;";
932
			$statement = $database->prepare($query);
933
			$statement->bindValue(":ip", $_GET['ip']);
934
			$statement->execute();
935
			$row = $statement->fetch(PDO::FETCH_ASSOC);
936
			$target = getTrustedClientIP($row['ip'], $row['forwardedip']);
937
			$type = "IP";
938
		}
939 View Code Duplication
		elseif (isset($_GET['email'])) {
940
			$query = "SELECT email FROM request WHERE id = :ip;";
941
			$statement = $database->prepare($query);
942
			$statement->bindValue(":ip", $_GET['email']);
943
			$statement->execute();
944
			$row = $statement->fetch(PDO::FETCH_ASSOC);
945
			$target = $row['email'];
946
			$type = "EMail";
947
		}
948 View Code Duplication
		elseif (isset($_GET['name'])) {
949
			$query = "SELECT name FROM request WHERE id = :ip;";
950
			$statement = $database->prepare($query);
951
			$statement->bindValue(":ip", $_GET['name']);
952
			$statement->execute();
953
			$row = $statement->fetch(PDO::FETCH_ASSOC);
954
			$target = $row['name'];
955
			$type = "Name";
956
		}
957
		else {
958
			BootstrapSkin::displayAlertBox("Unknown ban type.", "alert-error");
959
			BootstrapSkin::displayInternalFooter();
960
			die();    
961
		}
962
        
963
		if (count(Ban::getActiveBans($target))) {
964
			BootstrapSkin::displayAlertBox("This target is already banned!", "alert-error");
965
			BootstrapSkin::displayInternalFooter();
966
			die();
967
		} 
968
        
969
		$smarty->assign("bantype", $type);
970
		$smarty->assign("bantarget", trim($target));
971
		$smarty->display("bans/banform.tpl");
972
	}
973
	else {
974
		$bans = Ban::getActiveBans();
975
  
976
		$smarty->assign("activebans", $bans);
977
		$smarty->display("bans/banlist.tpl");
978
	}
979
    
980
	BootstrapSkin::displayInternalFooter();
981
	die();
982
}
983
elseif ($action == "defer" && $_GET['id'] != "" && $_GET['sum'] != "") {
984
	global $availableRequestStates;
985
	
986
	if (array_key_exists($_GET['target'], $availableRequestStates)) {
987
		$request = Request::getById($_GET['id'], gGetDb());
988
		
989
		if ($request == false) {
990
			BootstrapSkin::displayAlertBox(
991
				"Could not find the specified request!", 
992
				"alert-error", 
993
				"Error!", 
994
				true, 
995
				false);
996
            
997
			BootstrapSkin::displayInternalFooter();
998
			die();
999
		}
1000
		
1001
		if ($request->getChecksum() != $_GET['sum']) {
1002
			SessionAlert::error(
1003
				"This is similar to an edit conflict on Wikipedia; it means that you have tried to perform an action "
1004
				. "on a request that someone else has performed an action on since you loaded the page",
1005
				"Invalid checksum");
1006
            
1007
			header("Location: acc.php?action=zoom&id={$request->getId()}");
1008
			die();
1009
		}
1010
        
1011
		$sqlText = <<<SQL
1012
SELECT timestamp FROM log
1013
WHERE objectid = :request and objecttype = 'Request' AND action LIKE 'Closed%'
1014
ORDER BY timestamp DESC LIMIT 1;
1015
SQL;
1016
        
1017
		$statement = gGetDb()->prepare($sqlText);
1018
		$statement->execute(array(":request" => $request->getId()));
1019
		$logTime = $statement->fetchColumn();
1020
		$statement->closeCursor();
1021
        
1022
		$date = new DateTime();
1023
		$date->modify("-7 days");
1024
		$oneweek = $date->format("Y-m-d H:i:s");
1025
        
1026
		if ($request->getStatus() == "Closed" 
1027
			&& $logTime < $oneweek 
1028
			&& !User::getCurrent()->isAdmin() 
1029
			&& !User::getCurrent()->isCheckuser()) {
1030
			SessionAlert::error("Only administrators and checkusers can reopen a request that has been closed for over a week.");
1031
			header("Location: acc.php?action=zoom&id={$request->getId()}");
1032
			die();
1033
		}
1034
        
1035
		if ($request->getStatus() == $_GET['target']) {
1036
			SessionAlert::error(
1037
				"Cannot set status, target already deferred to " . htmlentities($_GET['target']), 
1038
				"Error");
1039
			header("Location: acc.php?action=zoom&id={$request->getId()}");
1040
			die();
1041
		}
1042
        
1043
		$database = gGetDb();
1044
		$database->transactionally(function() use ($database, $request)
1045
		{
1046
			global $availableRequestStates;
1047
                
1048
			$request->setReserved(0);
1049
			$request->setStatus($_GET['target']);
1050
			$request->updateChecksum();
1051
			$request->save();
1052
            
1053
			$deto = $availableRequestStates[$_GET['target']]['deferto'];
1054
			$detolog = $availableRequestStates[$_GET['target']]['defertolog'];
1055
            
1056
			Logger::deferRequest($database, $request, $detolog);
1057
        
1058
			Notification::requestDeferred($request);
1059
			SessionAlert::success("Request {$request->getId()} deferred to $deto");
1060
			header("Location: acc.php");
1061
		});
1062
        
1063
		die();
1064
	}
1065
	else {
1066
		BootstrapSkin::displayAlertBox("Defer target not valid.", "alert-error", "Error", true, false);
1067
		BootstrapSkin::displayInternalFooter();
1068
		die();
1069
	}
1070
}
1071
elseif ($action == "prefs") {
1072
	global $smarty, $enforceOAuth;
1073
    
1074
	if (isset ($_POST['sig'])) {
1075
		$user = User::getCurrent();
1076
		$user->setWelcomeSig($_POST['sig']);
1077
		$user->setEmailSig($_POST['emailsig']);
1078
		$user->setAbortPref(isset($_POST['abortpref']) ? 1 : 0);
1079
        
1080
		if (isset($_POST['email'])) {
1081
			$mailisvalid = filter_var(trim($_POST['email']), FILTER_VALIDATE_EMAIL);
1082
            
1083
			if ($mailisvalid === false) {
1084
				BootstrapSkin::displayAlertBox("Invalid email address", "alert-error", "Error!");
1085
			}
1086
			else {
1087
				$user->setEmail(trim($_POST['email']));
1088
			}
1089
		}
1090
1091
		try {
1092
			$user->save();
1093
		}
1094
		catch (PDOException $ex) {
1095
			BootstrapSkin::displayAlertBox($ex->getMessage(), "alert-error", "Error saving Preferences", true, false);
1096
			BootstrapSkin::displayInternalFooter();
1097
			die();
1098
		}
1099
        
1100
		BootstrapSkin::displayAlertBox("Preferences updated!", "alert-info");
1101
	}
1102
    
1103
	$smarty->assign("enforceOAuth", $enforceOAuth);
1104
	$smarty->display("prefs.tpl");
1105
	BootstrapSkin::displayInternalFooter();
1106
	die();
1107
}
1108
elseif ($action == "done" && $_GET['id'] != "") {
1109
	// check for valid close reasons
1110
	global $messages, $baseurl, $smarty;
1111
	
1112
	if (isset($_GET['email'])) {
1113
		if ($_GET['email'] == 0 || $_GET['email'] == "custom") {
1114
			$validEmail = true;
1115
		}
1116
		else {
1117
			$validEmail = EmailTemplate::getById($_GET['email'], gGetDb()) != false;
1118
		}
1119
	}
1120
	else {
1121
		$validEmail = false;
1122
	}
1123
    
1124
	if ($validEmail == false) {
1125
		BootstrapSkin::displayAlertBox("Invalid close reason", "alert-error", "Error", true, false);
1126
		BootstrapSkin::displayInternalFooter();
1127
		die();
1128
	}
1129
	
1130
	// sanitise this input ready for inclusion in queries
1131
	$request = Request::getById($_GET['id'], gGetDb());
1132
    
1133
	if ($request == false) {
1134
		// Notifies the user and stops the script.
1135
		BootstrapSkin::displayAlertBox("The request ID supplied is invalid!", "alert-error", "Error", true, false);
1136
		BootstrapSkin::displayInternalFooter();
1137
		die();
1138
	}
1139
    
1140
	$gem = $_GET['email'];
1141
	
1142
	// check the checksum is valid
1143
	if ($request->getChecksum() != $_GET['sum']) {
1144
		BootstrapSkin::displayAlertBox("This is similar to an edit conflict on Wikipedia; it means that you have tried to perform an action on a request that someone else has performed an action on since you loaded the page.", "alert-error", "Invalid Checksum", true, false);
1145
		BootstrapSkin::displayInternalFooter();
1146
		die();
1147
	}
1148
	
1149
	// check if an email has already been sent
1150
	if ($request->getEmailSent() == "1" && !isset($_GET['override']) && $gem != 0) {
1151
		$alertContent = "<p>This request has already been closed in a manner that has generated an e-mail to the user, Proceed?</p><br />";
1152
		$alertContent .= "<div class=\"row-fluid\">";
1153
		$alertContent .= "<a class=\"btn btn-success offset3 span3\"  href=\"$baseurl/acc.php?sum=" . $_GET['sum'] . "&amp;action=done&amp;id=" . $_GET['id'] . "&amp;override=yes&amp;email=" . $_GET['email'] . "\">Yes</a>";
1154
		$alertContent .= "<a class=\"btn btn-danger span3\" href=\"$baseurl/acc.php\">No</a>";
1155
		$alertContent .= "</div>";
1156
        
1157
		BootstrapSkin::displayAlertBox($alertContent, "alert-info", "Warning!", true, false, false, true);
1158
		BootstrapSkin::displayInternalFooter();
1159
		die();
1160
	}
1161
	
1162
	// check the request is not reserved by someone else
1163
	if ($request->getReserved() != 0 && !isset($_GET['reserveoverride']) && $request->getReserved() != User::getCurrent()->getId()) {
1164
		$alertContent = "<p>This request is currently marked as being handled by " . $request->getReservedObject()->getUsername() . ", Proceed?</p><br />";
1165
		$alertContent .= "<div class=\"row-fluid\">";
1166
		$alertContent .= "<a class=\"btn btn-success offset3 span3\"  href=\"$baseurl/acc.php?" . $_SERVER["QUERY_STRING"] . "&reserveoverride=yes\">Yes</a>";
1167
		$alertContent .= "<a class=\"btn btn-danger span3\" href=\"$baseurl/acc.php\">No</a>";
1168
		$alertContent .= "</div>";
1169
        
1170
		BootstrapSkin::displayAlertBox($alertContent, "alert-info", "Warning!", true, false, false, true);
1171
		BootstrapSkin::displayInternalFooter();
1172
		die();
1173
	}
1174
	    
1175
	if ($request->getStatus() == "Closed") {
1176
		BootstrapSkin::displayAlertBox("Cannot close this request. Already closed.", "alert-error", "Error", true, false);
1177
		BootstrapSkin::displayInternalFooter();
1178
		die();
1179
	}
1180
	
1181
	// Checks whether the username is already in use on Wikipedia.
1182
	$userexist = file_get_contents("http://en.wikipedia.org/w/api.php?action=query&list=users&ususers=" . urlencode($request->getName()) . "&format=php");
1183
	$ue = unserialize($userexist);
1184
	if (!isset ($ue['query']['users']['0']['missing'])) {
1185
		$exists = true;
1186
	}
1187
	else {
1188
		$exists = false;
1189
	}
1190
1191
	/** @var EmailTemplate $emailTemplate */
1192
	$emailTemplate = EmailTemplate::getById($gem, gGetDb());
1193
	if ($emailTemplate instanceof EmailTemplate) {
1194
		$isForCreated = $emailTemplate->getDefaultAction() === EmailTemplate::CREATED;
1195
	} else {
1196
		$isForCreated = false;
1197
	}
1198
1199
	// check if a request being created does not already exist.
1200
	if ($isForCreated && !$exists && !isset($_GET['createoverride'])) {
1201
		$alertContent = "<p>You have chosen to mark this request as \"created\", but the account does not exist on the English Wikipedia, proceed?</p><br />";
1202
		$alertContent .= "<div class=\"row-fluid\">";
1203
		$alertContent .= "<a class=\"btn btn-success offset3 span3\"  href=\"$baseurl/acc.php?" . $_SERVER["QUERY_STRING"] . "&amp;createoverride=yes\">Yes</a>";
1204
		$alertContent .= "<a class=\"btn btn-danger span3\" href=\"$baseurl/acc.php\">No</a>";
1205
		$alertContent .= "</div>";
1206
        
1207
		BootstrapSkin::displayAlertBox($alertContent, "alert-info", "Warning!", true, false, false, true);
1208
		BootstrapSkin::displayInternalFooter();
1209
		die();
1210
	}
1211
	
1212
	$messageBody = null;
1213
    
1214
	// custom close reasons
1215
	if ($gem == 'custom') {
1216
		if (!isset($_POST['msgbody']) or empty($_POST['msgbody'])) {
1217
			// Send it through htmlspecialchars so HTML validators don't complain. 
1218
			$querystring = htmlspecialchars($_SERVER["QUERY_STRING"], ENT_COMPAT, 'UTF-8'); 
1219
            
1220
			$template = false;
1221
			if (isset($_GET['preload'])) {
1222
				$template = EmailTemplate::getById($_GET['preload'], gGetDb());
1223
			}
1224
            
1225
			if ($template != false) {
1226
				$preloadTitle = $template->getName();
1227
				$preloadText = $template->getText();
1228
				$preloadAction = $template->getDefaultAction();
1229
			}
1230
			else {
1231
				$preloadText = "";
1232
				$preloadTitle = "";
1233
				$preloadAction = "";
1234
			}
1235
            
1236
			$smarty->assign("requeststates", $availableRequestStates);
1237
			$smarty->assign("defaultAction", $preloadAction);
1238
			$smarty->assign("preloadtext", $preloadText);
1239
			$smarty->assign("preloadtitle", $preloadTitle);
1240
			$smarty->assign("querystring", $querystring);
1241
			$smarty->assign("request", $request);
1242
			$smarty->assign("iplocation", $locationProvider->getIpLocation($request->getTrustedIp()));
1243
			$smarty->display("custom-close.tpl");
1244
			BootstrapSkin::displayInternalFooter();
1245
			die();
1246
		}
1247
1248
		$headers = 'From: [email protected]' . "\r\n";
1249
		if (!User::getCurrent()->isAdmin() || isset($_POST['ccmailist']) && $_POST['ccmailist'] == "on") {
1250
			$headers .= 'Cc: [email protected]' . "\r\n";
1251
		}
1252
1253
		$headers .= 'X-ACC-Request: ' . $request->getId() . "\r\n";
1254
		$headers .= 'X-ACC-UserID: ' . User::getCurrent()->getId() . "\r\n";
1255
1256
		// Get the closing user's Email signature and append it to the Email.
1257
		if (User::getCurrent()->getEmailSig() != "") {
1258
			$emailsig = html_entity_decode(User::getCurrent()->getEmailSig(), ENT_QUOTES, "UTF-8");
1259
			mail($request->getEmail(), "RE: [ACC #{$request->getId()}] English Wikipedia Account Request", $_POST['msgbody'] . "\n\n" . $emailsig, $headers);
1260
		}
1261
		else {
1262
			mail($request->getEmail(), "RE: [ACC #{$request->getId()}] English Wikipedia Account Request", $_POST['msgbody'], $headers);
1263
		}
1264
1265
		$request->setEmailSent(1);
1266
		$messageBody = $_POST['msgbody'];
1267
1268
		if ($_POST['action'] == EmailTemplate::CREATED || $_POST['action'] == EmailTemplate::NOT_CREATED) {
1269
			$request->setStatus('Closed');
1270
1271
			if ($_POST['action'] == EmailTemplate::CREATED) {
1272
				$gem  = 'custom-y';
1273
				$crea = "Custom, Created";
1274
			}
1275
			else {
1276
				$gem  = 'custom-n';
1277
				$crea = "Custom, Not Created";
1278
			}
1279
1280
			Logger::closeRequest(gGetDb(), $request, $gem, $messageBody);
1281
			
1282
			Notification::requestClosed($request, $crea);
1283
			BootstrapSkin::displayAlertBox(
1284
				"Request " . $request->getId() . " (" . htmlentities($request->getName(), ENT_COMPAT, 'UTF-8') . ") marked as 'Done'.", 
1285
				"alert-success");
1286
		}
1287
		else if ($_POST['action'] == "mail") {
1288
			// no action other than send mail!
1289
			Logger::sentMail(gGetDb(), $request, $messageBody);
1290
			Logger::unreserve(gGetDb(), $request);
1291
1292
			Notification::sentMail($request);
1293
			BootstrapSkin::displayAlertBox("Sent mail to Request {$request->getId()}", 
1294
				"alert-success");
1295
		}
1296
		else if (array_key_exists($_POST['action'], $availableRequestStates)) {
1297
			// Defer
1298
1299
			$request->setStatus($_POST['action']);
1300
			$deto = $availableRequestStates[$_POST['action']]['deferto'];
1301
			$detolog = $availableRequestStates[$_POST['action']]['defertolog'];
1302
1303
			Logger::sentMail(gGetDb(), $request, $messageBody);
1304
			Logger::deferRequest(gGetDb(), $request, $detolog);
1305
			
1306
			Notification::requestDeferredWithMail($request);
1307
			BootstrapSkin::displayAlertBox("Request {$request->getId()} deferred to $deto, sending an email.", 
1308
				"alert-success");
1309
		}
1310
		else {
1311
			// hmm. not sure what happened. Log that we sent the mail anyway.
1312
			Logger::sentMail(gGetDb(), $request, $messageBody);
1313
			Logger::unreserve(gGetDb(), $request);
1314
1315
			Notification::sentMail($request);
1316
			BootstrapSkin::displayAlertBox("Sent mail to Request {$request->getId()}", 
1317
				"alert-success");
1318
		}
1319
1320
		$request->setReserved(0);
1321
		$request->save();
1322
		
1323
		$request->updateChecksum();
1324
		$request->save();
1325
1326
		echo defaultpage();
1327
		BootstrapSkin::displayInternalFooter();
1328
		die();		
1329
	}
1330
	else {
1331
		// Not a custom close, just a normal close
1332
	    
1333
		$request->setStatus('Closed');
1334
		$request->setReserved(0);
1335
		
1336
		// TODO: make this transactional
1337
		$request->save();
1338
		
1339
		Logger::closeRequest(gGetDb(), $request, $gem, $messageBody);
1340
		
1341
		if ($gem == '0') {
1342
			$crea = "Dropped";
1343
		}
1344
		else {
1345
			$template = EmailTemplate::getById($gem, gGetDb());
1346
			$crea = $template->getName();
1347
		}
1348
1349
		Notification::requestClosed($request, $crea);
1350
		BootstrapSkin::displayAlertBox("Request " . $request->getId() . " (" . htmlentities($request->getName(), ENT_COMPAT, 'UTF-8') . ") marked as 'Done'.", "alert-success");
1351
		
1352
		$towhom = $request->getEmail();
1353
		if ($gem != "0") {
1354
			sendemail($gem, $towhom, $request->getId());
1355
			$request->setEmailSent(1);
1356
		}
1357
		
1358
		$request->updateChecksum();
1359
		$request->save();
1360
		
1361
		echo defaultpage();
1362
		BootstrapSkin::displayInternalFooter();
1363
		die();
1364
	}
1365
}
1366
elseif ($action == "zoom") {
1367
	if (!isset($_GET['id'])) {
1368
		BootstrapSkin::displayAlertBox("No request specified!", "alert-error", "Error!", true, false);
1369
		BootstrapSkin::displayInternalFooter();
1370
		die();
1371
	}
1372
    
1373
	if (isset($_GET['hash'])) {
1374
		$urlhash = $_GET['hash'];
1375
	}
1376
	else {
1377
		$urlhash = "";
1378
	}
1379
	echo zoomPage($_GET['id'], $urlhash);
1380
1381
	$tailscript = getTypeaheadSource(User::getAllUsernames(gGetDb()));
1382
	BootstrapSkin::displayInternalFooter($tailscript);
1383
	die();
1384
}
1385
elseif ($action == "logs") {
1386
	global $baseurl;
1387
	
1388
	$filterUser = isset($_GET['filterUser']) && $_GET['filterUser'] != "" ? $_GET['filterUser'] : false;
1389
	$filterAction = isset($_GET['filterAction']) && $_GET['filterAction'] != "" ? $_GET['filterAction'] : false;
1390
	
1391
	$limit = 100;
1392
	if (isset($_GET['limit'])) {
1393
		$limit = (int)$_GET['limit'];
1394
	}
1395
	
1396
	$offset = 0;
1397
	$page = 1;
1398
	if (isset($_GET['page'])) {
1399
		$page = (int)$_GET['page'];
1400
		$offset = ($page - 1) * $limit;
1401
	}
1402
	
1403
	$logs = Logger::getLogs($filterUser, $filterAction, $limit, $offset);
1404
	if ($logs === false) {
1405
		$smarty->assign("logs", array());
1406
		$smarty->display("logs/main.tpl");
1407
		BootstrapSkin::displayInternalFooter();
1408
		die();
1409
	}
1410
	
1411
	$count = $logs['count'];
1412
	unset($logs['count']);
1413
	
1414
	// The number of pages on the pager to show. Must be odd
1415
	$pageLimit = 9;
1416
	
1417
	$pageData = array( 
1418
		'canprev' => $page != 1,
1419
		'cannext' => ($page * $limit) < $count,
1420
		'maxpage' => ceil($count / $limit),
1421
		'pagelimit' => $pageLimit,
1422
	);
1423
	
1424
	$pageMargin = (($pageLimit - 1) / 2);
1425
	$pageData['lowpage'] = max(1, $page - $pageMargin);
1426
	$pageData['hipage'] = min($pageData['maxpage'], $page + $pageMargin);
1427
	
1428
	$pageCount = ($pageData['hipage'] - $pageData['lowpage']) + 1;
1429
	
1430
	if ($pageCount < $pageLimit) {
1431
		if ($pageData['lowpage'] == 1 && $pageData['hipage'] == $pageData['maxpage']) {
1432
			// nothing to do, we're already at max range.	
1433
		}
1434 View Code Duplication
		elseif ($pageData['lowpage'] == 1 && $pageData['hipage'] < $pageData['maxpage']) {
1435
			$pageData['hipage'] = min($pageLimit, $pageData['maxpage']);
1436
		}
1437 View Code Duplication
		elseif ($pageData['lowpage'] > 1 && $pageData['hipage'] == $pageData['maxpage']) {
1438
			$pageData['lowpage'] = max(1, $pageData['maxpage'] - $pageLimit + 1);
1439
		}
1440
	}
1441
	
1442
	$pageData['pages'] = range($pageData['lowpage'], $pageData['hipage']);
1443
		
1444
	$smarty->assign("pagedata", $pageData);
1445
	
1446
	$smarty->assign("limit", $limit);
1447
	$smarty->assign("page", $page);
1448
1449
	$smarty->assign("logs", $logs);
1450
	
1451
	
1452
	$smarty->assign("filterUser", $filterUser);
1453
	$smarty->assign("filterAction", $filterAction);
1454
	$smarty->display("logs/main.tpl");
1455
1456
	$tailscript = getTypeaheadSource(User::getAllUsernames(gGetDb(), true));
1457
	
1458
	BootstrapSkin::displayInternalFooter($tailscript);
1459
	die();
1460
}
1461
elseif ($action == "reserve") {
1462
	$database = gGetDb();
1463
    
1464
	$database->transactionally(function() use ($database)
1465
	{
1466
		$request = Request::getById($_GET['resid'], $database);
1467
        
1468
		if ($request == false) {
1469
			throw new TransactionException("Request not found", "Error");
1470
		}
1471
        
1472
		global $enableEmailConfirm, $baseurl;
1473
		if ($enableEmailConfirm == 1) {
1474
			if ($request->getEmailConfirm() != "Confirmed") {
1475
				throw new TransactionException("Email address not yet confirmed for this request.", "Error");
1476
			}
1477
		}
1478
1479
		$logQuery = $database->prepare(<<<SQL
1480
SELECT timestamp FROM log
1481
WHERE objectid = :request AND objecttype = 'Request' AND action LIKE 'Closed%'
1482
ORDER BY timestamp DESC LIMIT 1;
1483
SQL
1484
		);
1485
		$logQuery->bindValue(":request", $request->getId());
1486
		$logQuery->execute();
1487
		$logTime = $logQuery->fetchColumn();
1488
		$logQuery->closeCursor();
1489
        
1490
		$date = new DateTime();
1491
		$date->modify("-7 days");
1492
		$oneweek = $date->format("Y-m-d H:i:s");
1493
        
1494
		if ($request->getStatus() == "Closed" && $logTime < $oneweek && !User::getCurrent($database)->isAdmin()) {
1495
			throw new TransactionException("Only administrators and checkusers can reserve a request that has been closed for over a week.", "Error");
1496
		}
1497
        
1498
	   	if ($request->getReserved() != 0 && $request->getReserved() != User::getCurrent($database)->getId()) {
1499
			throw new TransactionException("Request is already reserved by {$request->getReservedObject()->getUsername()}.", "Error");
1500
		}
1501
           
1502
		if ($request->getReserved() == 0) {
1503
			// Check the number of requests a user has reserved already
1504
			$doubleReserveCountQuery = $database->prepare("SELECT COUNT(*) FROM request WHERE reserved = :userid;");
1505
			$doubleReserveCountQuery->bindValue(":userid", User::getCurrent($database)->getId());
1506
			$doubleReserveCountQuery->execute();
1507
			$doubleReserveCount = $doubleReserveCountQuery->fetchColumn();
1508
			$doubleReserveCountQuery->closeCursor();
1509
1510
			// User already has at least one reserved. 
1511
			if ($doubleReserveCount != 0) {
1512
				SessionAlert::warning("You have multiple requests reserved!");
1513
			}
1514
1515
			// Is the request closed?
1516
			if (!isset($_GET['confclosed'])) {
1517
				if ($request->getStatus() == "Closed") {
1518
					// FIXME: bootstrappify properly
1519
					throw new TransactionException('This request is currently closed. Are you sure you wish to reserve it?<br /><ul><li><a href="' . $_SERVER["REQUEST_URI"] . '&confclosed=yes">Yes, reserve this closed request</a></li><li><a href="' . $baseurl . '/acc.php">No, return to main request interface</a></li></ul>', "Request closed", "alert-info");
1520
				}
1521
			}	
1522
        
1523
			$request->setReserved(User::getCurrent($database)->getId());
1524
			$request->save();
1525
	
1526
			Logger::reserve($database, $request);
1527
                
1528
			Notification::requestReserved($request);
1529
                
1530
			SessionAlert::success("Reserved request {$request->getId()}.");
1531
		}
1532
        
1533
		header("Location: $baseurl/acc.php?action=zoom&id={$request->getId()}");
1534
	});
1535
	    
1536
	die();	
1537
}
1538
elseif ($action == "breakreserve") {
1539
	global $smarty;
1540
    
1541
	$database = gGetDb();
1542
    
1543
	$request = Request::getById($_GET['resid'], $database);
1544
        
1545
	if ($request == false) {
1546
		BootstrapSkin::displayAlertBox("Could not find request.", "alert-error", "Error", true, false);
1547
		BootstrapSkin::displayInternalFooter();
1548
		die();
1549
	}
1550
    
1551
	if ($request->getReserved() == 0) {
1552
		BootstrapSkin::displayAlertBox("Request is not reserved.", "alert-error", "Error", true, false);
1553
		BootstrapSkin::displayInternalFooter();
1554
		die();
1555
	}
1556
    
1557
	$reservedUser = $request->getReservedObject();
1558
    
1559
	if ($reservedUser == false) {
1560
		BootstrapSkin::displayAlertBox("Could not find user who reserved the request (!!).", "alert-error", "Error", true, false);
1561
		BootstrapSkin::displayInternalFooter();
1562
		die();
1563
	}
1564
    
1565
	if ($reservedUser->getId() != User::getCurrent()->getId()) {
1566
		if (User::getCurrent()->isAdmin()) {
1567
			if (isset($_GET['confirm']) && $_GET['confirm'] == 1) {
1568
				$database->transactionally(function() use($database, $request)
1569
				{
1570
					$request->setReserved(0);
1571
					$request->save();
1572
1573
					Logger::breakReserve($database, $request);
1574
                
1575
					Notification::requestReserveBroken($request);
1576
					header("Location: acc.php");
1577
				});
1578
                
1579
				die();
1580
			}
1581
			else {
1582
				global $baseurl;
1583
				$smarty->assign("reservedUser", $reservedUser);
1584
				$smarty->assign("request", $request);
1585
                
1586
				$smarty->display("confirmations/breakreserve.tpl");
1587
			}
1588
		}
1589
		else {
1590
			echo "You cannot break " . htmlentities($reservedUser->getUsername()) . "'s reservation";
1591
		}
1592
	}
1593
	else {
1594
		$database->transactionally(function() use ($database, $request)
1595
		{
1596
			$request->setReserved(0);
1597
			$request->save();
1598
1599
			Logger::unreserve($database, $request);
1600
        
1601
			Notification::requestUnreserved($request);
1602
			header("Location: acc.php");
1603
		});
1604
        
1605
		die();
1606
	}
1607
    
1608
	BootstrapSkin::displayInternalFooter();
1609
	die();		
1610
}
1611
elseif ($action == "comment") {
1612
	global $smarty;
1613
    
1614
	$request = Request::getById($_GET['id'], gGetDb());
1615
	$smarty->assign("request", $request);
1616
	$smarty->display("commentform.tpl");
1617
	BootstrapSkin::displayInternalFooter();
1618
	die();
1619
}
1620
elseif ($action == "comment-add") {
1621
	global $baseurl, $smarty;
1622
    
1623
	$request = Request::getById($_POST['id'], gGetDb());
1624
	if ($request == false) {
1625
		BootstrapSkin::displayAlertBox("Could not find request!", "alert-error", "Error", true, false);
1626
		BootstrapSkin::displayInternalFooter();
1627
		die();
1628
	}
1629
    
1630
	if (!isset($_POST['comment']) || $_POST['comment'] == "") {
1631
		BootstrapSkin::displayAlertBox("Comment must be supplied!", "alert-error", "Error", true, false);
1632
		BootstrapSkin::displayInternalFooter();
1633
		die(); 
1634
	}
1635
    
1636
	$visibility = 'user';
1637
	if (isset($_POST['visibility'])) {
1638
		// sanity check
1639
		$visibility = $_POST['visibility'] == 'user' ? 'user' : 'admin';
1640
	}
1641
    
1642
	//Look for and detect IPv4/IPv6 addresses in comment text, and warn the commenter.
1643 View Code Duplication
	if ((preg_match('/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/', $_POST['comment']) || preg_match('/(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/', $_POST['comment'])) && $_POST['privpol-check-override'] != "override") {
1644
			BootstrapSkin::displayAlertBox("IP address detected in comment text.  Warning acknowledgement checkbox must be checked.", "alert-error", "Error", true, false);
1645
			$smarty->assign("request", $request);
1646
			$smarty->assign("comment", $_POST['comment']);
1647
			$smarty->assign("actionLocation", "comment-add");
1648
			$smarty->display("privpol-warning.tpl");
1649
			BootstrapSkin::displayInternalFooter();
1650
			die();
1651
		}
1652
    
1653
	$comment = new Comment();
1654
	$comment->setDatabase(gGetDb());
1655
    
1656
	$comment->setRequest($request->getId());
1657
	$comment->setVisibility($visibility);
1658
	$comment->setUser(User::getCurrent()->getId());
1659
	$comment->setComment($_POST['comment']);
1660
    
1661
	$comment->save();
1662
    
1663
	if (isset($_GET['hash'])) {
1664
		$urlhash = urlencode(htmlentities($_GET['hash']));
1665
	}
1666
	else {
1667
		$urlhash = "";
1668
	}
1669
1670
	BootstrapSkin::displayAlertBox(
1671
		"<a href='$baseurl/acc.php?action=zoom&amp;id={$request->getId()}&amp;hash=$urlhash'>Return to request #{$request->getId()}</a>",
1672
		"alert-success",
1673
		"Comment added Successfully!",
1674
		true, false);
1675
        
1676
	Notification::commentCreated($comment);
1677
        
1678
	BootstrapSkin::displayInternalFooter();
1679
	die();
1680
}
1681
elseif ($action == "comment-quick") {
1682
	$request = Request::getById($_POST['id'], gGetDb());
1683
	if ($request == false) {
1684
		BootstrapSkin::displayAlertBox("Could not find request!", "alert-error", "Error", true, false);
1685
		BootstrapSkin::displayInternalFooter();
1686
		die();
1687
	}
1688
    
1689
	if (!isset($_POST['comment']) || $_POST['comment'] == "") {
1690
		header("Location: acc.php?action=zoom&id=" . $request->getId());
1691
		die(); 
1692
	}
1693
    
1694
	$visibility = 'user';
1695
	if (isset($_POST['visibility'])) {
1696
		// sanity check
1697
		$visibility = $_POST['visibility'] == 'user' ? 'user' : 'admin';
1698
	}
1699
1700
	//Look for and detect IPv4/IPv6 addresses in comment text, and warn the commenter.
1701 View Code Duplication
	if ((preg_match('/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/', $_POST['comment']) || preg_match('/(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/', $_POST['comment'])) && $_POST['privpol-check-override'] != "override") {
1702
			BootstrapSkin::displayAlertBox("IP address detected in comment text.  Warning acknowledgement checkbox must be checked.", "alert-error", "Error", true, false);
1703
			$smarty->assign("request", $request);
1704
			$smarty->assign("comment", $_POST['comment']);
1705
			$smarty->assign("actionLocation", "comment-quick");
1706
			$smarty->display("privpol-warning.tpl");
1707
			BootstrapSkin::displayInternalFooter();
1708
			die();
1709
		}
1710
    
1711
	$comment = new Comment();
1712
	$comment->setDatabase(gGetDb());
1713
    
1714
	$comment->setRequest($request->getId());
1715
	$comment->setVisibility($visibility);
1716
	$comment->setUser(User::getCurrent()->getId());
1717
	$comment->setComment($_POST['comment']);
1718
    
1719
	$comment->save();
1720
    
1721
	Notification::commentCreated($comment);
1722
    
1723
	header("Location: acc.php?action=zoom&id=" . $request->getId());
1724
}
1725
elseif ($action == "changepassword") {
1726
	if ((!isset($_POST['oldpassword'])) || $_POST['oldpassword'] == "") {
1727
		//Throw an error if old password is not specified.
1728
		BootstrapSkin::displayAlertBox("You did not enter your old password.", "alert-error", "Error", true, false);
1729
		BootstrapSkin::displayInternalFooter();
1730
		die();
1731
	}
1732
	
1733 View Code Duplication
	if ((!isset($_POST['newpassword'])) || $_POST['newpassword'] == "") {
1734
		//Throw an error if new password is not specified.
1735
		BootstrapSkin::displayAlertBox("You did not enter your new password.", "alert-error", "Error", true, false);
1736
		BootstrapSkin::displayInternalFooter();
1737
		die();
1738
	}
1739
	
1740 View Code Duplication
	if ($_POST['newpassword'] != $_POST['newpasswordconfirm']) {
1741
		//Throw an error if new password does not match what is in the confirmation box.
1742
		BootstrapSkin::displayAlertBox("The 2 new passwords you entered do not match.", "alert-error", "Error", true, false);
1743
		BootstrapSkin::displayInternalFooter();
1744
		die();
1745
	}
1746
    
1747
	$user = User::getCurrent();
1748
	   
1749
	if (!$user->authenticate($_POST['oldpassword'])) {
1750
		//Throw an error if the old password field's value does not match the user's current password.
1751
		BootstrapSkin::displayAlertBox("The old password you entered is not correct.", "alert-error", "Error", true, false);
1752
		BootstrapSkin::displayInternalFooter();
1753
		die();
1754
	}
1755
    
1756
	$user->setPassword($_POST['newpassword']);
1757
	$user->save();
1758
    
1759
	BootstrapSkin::displayAlertBox("Password successfully changed!", "alert-success", "", false, false);
1760
	BootstrapSkin::displayInternalFooter();
1761
	die();
1762
}
1763
elseif ($action == "ec") {
1764
	// edit comment
1765
  
1766
	global $smarty, $baseurl;
1767
    
1768
	$comment = Comment::getById($_GET['id'], gGetDb());
1769
    
1770
	if ($comment == false) {
1771
		// Only using die("Message"); for errors looks ugly.
1772
		BootstrapSkin::displayAlertBox("Comment not found.", "alert-error", "Error", true, false);
1773
		BootstrapSkin::displayInternalFooter();
1774
		die();
1775
	}
1776
	
1777
	// Unauthorized if user is not an admin or the user who made the comment being edited.
1778
	if (!User::getCurrent()->isAdmin() && !User::getCurrent()->isCheckuser() && $comment->getUser() != User::getCurrent()->getId()) {
1779
		BootstrapSkin::displayAccessDenied();
1780
		BootstrapSkin::displayInternalFooter();
1781
		die();
1782
	}
1783
	
1784
	// get[id] is safe by this point.
1785
	
1786
	if ($_SERVER['REQUEST_METHOD'] == 'POST') {
1787
		$database = gGetDb();
1788 View Code Duplication
		$database->transactionally(function() use ($database, $comment, $baseurl)
1789
		{
1790
            
1791
			$comment->setComment($_POST['newcomment']);
1792
			$comment->setVisibility($_POST['visibility']);
1793
        
1794
			$comment->save();
1795
        
1796
			Logger::editComment($database, $comment);
1797
        
1798
			Notification::commentEdited($comment);
1799
        
1800
			SessionAlert::success("Comment has been saved successfully");
1801
			header("Location: $baseurl/acc.php?action=zoom&id=" . $comment->getRequest());
1802
		});
1803
        
1804
		die();    
1805
	}
1806
	else {
1807
		$smarty->assign("comment", $comment);
1808
		$smarty->display("edit-comment.tpl");
1809
		BootstrapSkin::displayInternalFooter();
1810
		die();
1811
	}
1812
}
1813
elseif ($action == "sendtouser") {
1814
	global $baseurl;
1815
    
1816
	$database = gGetDb();
1817
1818
	/** @var Request $requestObject */
1819
	$requestObject = Request::getById($_POST['id'], $database);
1820
	if ($requestObject == false) {
1821
		BootstrapSkin::displayAlertBox("Request invalid", "alert-error", "Could not find request", true, false);
1822
		BootstrapSkin::displayInternalFooter();
1823
		die();
1824
	}
1825
    
1826
	$request = $requestObject->getId();
1827
    
1828
	$user = User::getByUsername($_POST['user'], $database);
1829
	$curuser = User::getCurrent()->getUsername();
1830
    
1831
	if ($user == false) {
1832
		BootstrapSkin::displayAlertBox("We couldn't find the user you wanted to send the reservation to. Please check that this user exists and is an active user on the tool.", "alert-error", "Could not find user", true, false);
1833
		BootstrapSkin::displayInternalFooter();
1834
		die();
1835
	}
1836
    
1837
	$database->transactionally(function() use ($database, $user, $requestObject, $curuser)
1838
	{
1839
		$updateStatement = $database->prepare("UPDATE request SET reserved = :userid WHERE id = :request LIMIT 1;");
1840
		$updateStatement->bindValue(":userid", $user->getId());
1841
		$updateStatement->bindValue(":request", $requestObject->getId());
1842
		if (!$updateStatement->execute()) {
1843
			throw new TransactionException("Error updating reserved status of request.");   
1844
		}
1845
        
1846
		Logger::sendReservation($database, $requestObject, $user);
1847
	});
1848
    
1849
	Notification::requestReservationSent($requestObject, $user);
1850
	SessionAlert::success("Reservation sent successfully");
1851
	header("Location: $baseurl/acc.php?action=zoom&id=$request");
1852
}
1853
elseif ($action == "emailmgmt") {
1854
	global $smarty, $createdid, $availableRequestStates;
1855
    
1856
	/* New page for managing Emails, since I would rather not be handling editing
1857
	interface messages (such as the Sitenotice) and the new Emails in the same place. */
1858
	if (isset($_GET['create'])) {
1859
		if (!User::getCurrent()->isAdmin()) {
1860
			BootstrapSkin::displayAccessDenied();
1861
			BootstrapSkin::displayInternalFooter();
1862
			die();
1863
		}
1864
		if (isset($_POST['submit'])) {
1865
			$database = gGetDb();
1866
			$database->transactionally(function() use ($database)
1867
			{
1868
				global $baseurl;
1869
                
1870
				$emailTemplate = new EmailTemplate();
1871
				$emailTemplate->setDatabase($database);
1872
            
1873
				$emailTemplate->setName($_POST['name']);
1874
				$emailTemplate->setText($_POST['text']);
1875
				$emailTemplate->setJsquestion($_POST['jsquestion']);
1876
				$emailTemplate->setDefaultAction($_POST['defaultaction']);
1877
				$emailTemplate->setActive(isset($_POST['active']));
1878
1879
				// Check if the entered name already exists (since these names are going to be used as the labels for buttons on the zoom page).
1880
				// getByName(...) returns false on no records found.
1881
				if (EmailTemplate::getByName($_POST['name'], $database)) {
1882
					throw new TransactionException("That Email template name is already being used. Please choose another.");
1883
				}
1884
			
1885
				$emailTemplate->save();
1886
                
1887
				Logger::createEmail($database, $emailTemplate);
1888
                
1889
				Notification::emailCreated($emailTemplate);
1890
                
1891
				SessionAlert::success("Email template has been saved successfully.");
1892
				header("Location: $baseurl/acc.php?action=emailmgmt");
1893
			});
1894
            
1895
			die();
1896
		}
1897
        
1898
		$smarty->assign('id', null);
1899
		$smarty->assign('createdid', $createdid);
1900
		$smarty->assign('requeststates', $availableRequestStates);
1901
		$smarty->assign('emailTemplate', new EmailTemplate());
1902
		$smarty->assign('emailmgmtpage', 'Create'); //Use a variable so we don't need two Smarty templates for creating and editing.
1903
		$smarty->display("email-management/edit.tpl");
1904
		BootstrapSkin::displayInternalFooter();
1905
		die();
1906
	}
1907
	if (isset($_GET['edit'])) {
1908
		global $createdid;
1909
        
1910
		$database = gGetDb();
1911
        
1912
		if (isset($_POST['submit'])) {
1913
			$emailTemplate = EmailTemplate::getById($_GET['edit'], $database);
1914
			// Allow the user to see the edit form (with read only fields) but not POST anything.
1915
			if (!User::getCurrent()->isAdmin()) {
1916
				BootstrapSkin::displayAccessDenied();
1917
				BootstrapSkin::displayInternalFooter();
1918
				die();
1919
			}
1920
            
1921
			$emailTemplate->setName($_POST['name']);
1922
			$emailTemplate->setText($_POST['text']);
1923
			$emailTemplate->setJsquestion($_POST['jsquestion']);
1924
			
1925
			if ($_GET['edit'] == $createdid) {
1926
				// Both checkboxes on the main created message should always be enabled.
1927
				$emailTemplate->setDefaultAction(EmailTemplate::CREATED);
1928
				$emailTemplate->setActive(1);
1929
				$emailTemplate->setPreloadOnly(0);
1930
			}
1931
			else {
1932
				$emailTemplate->setDefaultAction($_POST['defaultaction']);
1933
				$emailTemplate->setActive(isset($_POST['active']));
1934
				$emailTemplate->setPreloadOnly(isset($_POST['preloadonly']));
1935
			}
1936
				
1937
			// Check if the entered name already exists (since these names are going to be used as the labels for buttons on the zoom page).
1938
			$nameCheck = EmailTemplate::getByName($_POST['name'], gGetDb());
1939
			if ($nameCheck != false && $nameCheck->getId() != $_GET['edit']) {
1940
				BootstrapSkin::displayAlertBox("That Email template name is already being used. Please choose another.");
1941
				BootstrapSkin::displayInternalFooter();
1942
				die();
1943
			}
1944
1945
			$database->transactionally(function() use ($database, $emailTemplate)
1946
			{
1947
				$emailTemplate->save();
1948
                
1949
				Logger::editedEmail($database, $emailTemplate);
1950
            
1951
				global $baseurl;
1952
                
1953
				Notification::emailEdited($emailTemplate);
1954
				SessionAlert::success("Email template has been saved successfully.");
1955
				header("Location: $baseurl/acc.php?action=emailmgmt");
1956
			});
1957
            
1958
			die();
1959
		}
1960
        
1961
		$emailTemplate = EmailTemplate::getById($_GET['edit'], gGetDb());
1962
		$smarty->assign('id', $emailTemplate->getId());
1963
		$smarty->assign('emailTemplate', $emailTemplate);
1964
		$smarty->assign('createdid', $createdid);
1965
		$smarty->assign('requeststates', $availableRequestStates);
1966
		$smarty->assign('emailmgmtpage', 'Edit'); // Use a variable so we don't need two Smarty templates for creating and editing.
1967
		$smarty->display("email-management/edit.tpl");
1968
		BootstrapSkin::displayInternalFooter();
1969
		die();
1970
	}
1971
    
1972
	$query = "SELECT * FROM emailtemplate WHERE active = 1";
1973
	$statement = gGetDb()->prepare($query);
1974
	$statement->execute();
1975
	$rows = $statement->fetchAll(PDO::FETCH_CLASS, "EmailTemplate");
1976
	$smarty->assign('activeemails', $rows);
1977
        
1978
	$query = "SELECT * FROM emailtemplate WHERE active = 0";
1979
	$statement = gGetDb()->prepare($query);
1980
	$statement->execute();
1981
	$inactiverows = $statement->fetchAll(PDO::FETCH_CLASS, "EmailTemplate");
1982
	$smarty->assign('inactiveemails', $inactiverows);
1983
 
1984
	if (count($inactiverows) > 0) {
1985
		$smarty->assign('displayinactive', true);
1986
	}
1987
	else {
1988
		$smarty->assign('displayinactive', false);
1989
	}
1990
    
1991
	$smarty->display("email-management/main.tpl");
1992
	BootstrapSkin::displayInternalFooter();
1993
	die();
1994
}
1995
elseif ($action == "oauthdetach") {
1996
	if ($enforceOAuth) {
1997
		BootstrapSkin::displayAccessDenied();
1998
		BootstrapSkin::displayInternalFooter();
1999
		die();
2000
	}
2001
    
2002
	global $baseurl;
2003
        
2004
	$currentUser = User::getCurrent();
2005
	$currentUser->detachAccount();
2006
        
2007
	header("Location: {$baseurl}/acc.php?action=logout");
2008
}
2009
elseif ($action == "oauthattach") {
2010
	$database = gGetDb();
2011 View Code Duplication
	$database->transactionally(function() use ($database)
2012
	{
2013
		try {
2014
			global $oauthConsumerToken, $oauthSecretToken, $oauthBaseUrl, $oauthBaseUrlInternal;
2015
            
2016
			$user = User::getCurrent();
2017
            
2018
			// Get a request token for OAuth
2019
			$util = new OAuthUtility($oauthConsumerToken, $oauthSecretToken, $oauthBaseUrl, $oauthBaseUrlInternal);
2020
			$requestToken = $util->getRequestToken();
2021
2022
			// save the request token for later
2023
			$user->setOAuthRequestToken($requestToken->key);
2024
			$user->setOAuthRequestSecret($requestToken->secret);
2025
			$user->save();
2026
        
2027
			$redirectUrl = $util->getAuthoriseUrl($requestToken);
2028
        
2029
			header("Location: {$redirectUrl}");
2030
        
2031
		}
2032
		catch (Exception $ex) {
2033
			throw new TransactionException($ex->getMessage(), "Connection to Wikipedia failed.", "alert-error", 0, $ex);
2034
		}
2035
	});
2036
}
2037
elseif ($action == "listall") {
2038
    global $availableRequestStates, $enableEmailConfirm;
2039
2040
	if (isset($_GET['status']) && isset($availableRequestStates[$_GET['status']])) {
2041
		$type = $_GET['status']; // safe, we've verified it's sane in the above if statement.
2042
2043
	    $database = gGetDb();
2044
2045
	    if ($enableEmailConfirm == 1) {
2046
	        $query = "SELECT * FROM request WHERE status = :type AND emailconfirm = 'Confirmed';";
2047
	    } else {
2048
	        $query = "SELECT * FROM request WHERE status = :type;";
2049
	    }
2050
2051
	    $statement = $database->prepare($query);
2052
2053
        $statement->bindValue(":type", $type);
2054
        $statement->execute();
2055
2056
        $requests = $statement->fetchAll(PDO::FETCH_CLASS, "Request");
2057
        foreach ($requests as $req) {
2058
        	/** @var Request $req */
2059
            $req->setDatabase($database);
2060
        }
2061
2062
        global $smarty;
2063
        $smarty->assign("requests", $requests);
2064
        $smarty->assign("showStatus", false);
2065
        $html = $smarty->fetch("mainpage/requesttable.tpl");
2066
        echo $html;
2067
    } else {
2068
        echo defaultpage();
2069
    }
2070
2071
    BootstrapSkin::displayInternalFooter();
2072
    die();
2073
}
2074
# If the action specified does not exist, goto the default page.
2075
else {
2076
	echo defaultpage();
2077
	BootstrapSkin::displayInternalFooter();
2078
	die();
2079
}
2080