Completed
Branch master (6f8699)
by Simon
03:42
created

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