Completed
Pull Request — master (#221)
by Maximilian
10:25 queued 07:13
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
$locationProvider = new $locationProviderClass(gGetDb('acc'), $locationProviderApiKey);
47
$rdnsProvider = new $rdnsProviderClass(gGetDb('acc'));
48
$antispoofProvider = new $antispoofProviderClass();
49
$xffTrustProvider = new $xffTrustProviderClass($squidIpList);
50
51
// Clears the action variable.
52
$action = '';
53
54
// Assign the correct value to the action variable.
55
// The value is retrieved from the $GET variable.
56
if (isset($_GET['action'])) {
57
	$action = $_GET['action'];
58
}
59
60
// Clear session before banner and logged in as message is generated on logout attempt - Prom3th3an
61
if ($action == "logout") {
62
	session_unset();
63
    
64
	BootstrapSkin::displayInternalHeader();
65
	echo showlogin();
66
	BootstrapSkin::displayInternalFooter();
67
	die();
68
}
69
70
// Checks whether the user and nocheck variable is set.
71
// When none of these are set, the user should first login.
72
if (!isset($_SESSION['user']) && !isset($_GET['nocheck'])) {
73
//if (!isset($_SESSION['user']) && !($action=='login' && isset($_POST['username']))) {
74
	// Sets the parameter to blank, this way the correct options would be displayed.
75
	// It would tell the user now that he or she should log in or create an account.
76
	$suser = '';
77
	BootstrapSkin::displayInternalHeader();
78
79
	// Checks whether the user want to reset his password or register a new account.
80
	// Performs the clause when the action is not one of the above options.
81
	if ($action != 'register' && $action != 'forgotpw' && $action != 'sreg' && $action != "registercomplete") {
82
		if (isset($action)) {
83
			// Display the login form and the rest of the page coding.
84
			// The data in the current $GET varianle would be send as parameter.
85
			// There it would be used to possibly fill some of the form's fields.
86
			echo showlogin();
87
			BootstrapSkin::displayInternalFooter();
88
		}
89
		elseif (!isset($action)) {
90
			// When the action variable isn't set to anything,
91
			// the login page is displayed for the user to complete.
92
			echo showlogin();
93
			BootstrapSkin::displayInternalFooter();
94
		}
95
		// All the needed HTML code is displayed for the user.
96
		// The script is thus terminated.
97
		die();
98
	}
99
	else {
100
		// A content block is created if the action is none of the above.
101
		// This block would later be used to keep all the HTML except the header and footer.
102
		$out = "<div id=\"content\">";
103
		echo $out;
104
	}
105
}
106
// Executes if the user variable is set, but not the nocheck.
107
// This ussually happens when an user account has been renamed.
108
// LouriePieterse: I cant figure out for what reason this is used.
109
elseif (!isset($_GET['nocheck'])) {
110
		// Forces the current user to logout.
111
		$session->forceLogout($_SESSION['userID']);
112
113
		// ?
114
		BootstrapSkin::displayInternalHeader();
115
		$session->checksecurity();
116
}
117
118
// When no action is specified the default Internal ACC are displayed.
119
// TODO: Improve way the method is called.
120
if ($action == '') {
121
	echo defaultpage();
122
	BootstrapSkin::displayInternalFooter();
123
	die();
124
}
125
elseif ($action == "sreg") {
126
	global $useOauthSignup, $smarty;
127
        
128
	// TODO: check blocked
129
	// TODO: check age.
130
    
131
	// check if user checked the "I have read and understand the interface guidelines" checkbox
132
	if (!isset($_REQUEST['guidelines'])) {
133
		$smarty->display("registration/alert-interfaceguidelines.tpl");
134
		BootstrapSkin::displayInternalFooter();
135
		die();
136
	}
137
	
138
	if (!filter_var($_REQUEST['email'], FILTER_VALIDATE_EMAIL)) {
139
		$smarty->display("registration/alert-invalidemail.tpl");
140
		BootstrapSkin::displayInternalFooter();
141
		die();
142
	}
143
    
144
	if ($_REQUEST['pass'] !== $_REQUEST['pass2']) {
145
		$smarty->display("registration/alert-passwordmismatch.tpl");
146
		BootstrapSkin::displayInternalFooter();
147
		die();
148
	}
149
    
150
	if (!$useOauthSignup) {
151
		if (!((string)(int)$_REQUEST['conf_revid'] === (string)$_REQUEST['conf_revid']) || $_REQUEST['conf_revid'] == "") {
152
			$smarty->display("registration/alert-confrevid.tpl");
153
			BootstrapSkin::displayInternalFooter();
154
			die();		
155
		}
156
	}
157
    
158
	if (User::getByUsername($_REQUEST['name'], gGetDb()) != false) {
159
		$smarty->display("registration/alert-usernametaken.tpl");
160
		BootstrapSkin::displayInternalFooter();
161
		die();
162
	}
163
    
164
	$query = gGetDb()->prepare("SELECT * FROM user WHERE email = :email LIMIT 1;");
165
	$query->execute(array(":email" => $_REQUEST['email']));
166
	if ($query->fetchObject("User") != false) {
167
		$smarty->display("registration/alert-emailtaken.tpl");
168
		BootstrapSkin::displayInternalFooter();
169
		die();
170
	}
171
	$query->closeCursor();
172
173
	$database = gGetDb();
174
    
175
	$database->transactionally(function() use ($database, $useOauthSignup)
176
	{
177
    
178
		$newUser = new User();
179
		$newUser->setDatabase($database);
180
    
181
		$newUser->setUsername($_REQUEST['name']);
182
		$newUser->setPassword($_REQUEST['pass']);
183
		$newUser->setEmail($_REQUEST['email']);
184
        
185
		if (!$useOauthSignup) {
186
			$newUser->setOnWikiName($_REQUEST['wname']);
187
			$newUser->setConfirmationDiff($_REQUEST['conf_revid']);
188
		}
189
        
190
		$newUser->save();
191
    
192
		global $oauthConsumerToken, $oauthSecretToken, $oauthBaseUrl, $oauthBaseUrlInternal, $useOauthSignup;
193
    
194
		if ($useOauthSignup) {
195
			try {
196
				// Get a request token for OAuth
197
				$util = new OAuthUtility($oauthConsumerToken, $oauthSecretToken, $oauthBaseUrl, $oauthBaseUrlInternal);
198
				$requestToken = $util->getRequestToken();
199
    
200
				// save the request token for later
201
				$newUser->setOAuthRequestToken($requestToken->key);
202
				$newUser->setOAuthRequestSecret($requestToken->secret);
203
				$newUser->save();
204
            
205
				Notification::userNew($newUser);
206
        
207
				$redirectUrl = $util->getAuthoriseUrl($requestToken);
208
            
209
				header("Location: {$redirectUrl}");
210
			}
211
			catch (Exception $ex) {
212
				throw new TransactionException(
213
					$ex->getMessage(), 
214
					"Connection to Wikipedia failed.", 
215
					"alert-error", 
216
					0, 
217
					$ex);
218
			}
219
		}
220
		else {
221
			global $baseurl;
222
			Notification::userNew($newUser);
223
			header("Location: {$baseurl}/acc.php?action=registercomplete");
224
		}
225
	});
226
    
227
	die();
228
}
229
elseif ($action == "register") {
230
	global $useOauthSignup, $smarty;
231
	$smarty->assign("useOauthSignup", $useOauthSignup);
232
	$smarty->display("registration/register.tpl");
233
	BootstrapSkin::displayInternalFooter();
234
	die();
235
}
236
elseif ($action == "registercomplete") {
237
	$smarty->display("registration/alert-registrationcomplete.tpl");
238
	BootstrapSkin::displayInternalFooter();
239
}
240
elseif ($action == "forgotpw") {
241
	global $baseurl, $smarty;
242
    
243
	if (isset ($_GET['si']) && isset ($_GET['id'])) {
244
		$user = User::getById($_GET['id'], gGetDb());
245
        
246
		if ($user === false) {
247
			BootstrapSkin::displayAlertBox("User not found.", "alert-error");
248
			BootstrapSkin::displayInternalFooter();
249
			die();
250
		}
251
        
252
		if (isset ($_POST['pw']) && isset ($_POST['pw2'])) {
253
			$hash = $user->getForgottenPasswordHash();
254
            
255
			if ($hash == $_GET['si']) {
256
				if ($_POST['pw'] == $_POST['pw2']) {
257
					$user->setPassword($_POST['pw2']);
258
					$user->save();
259
                    
260
					BootstrapSkin::displayAlertBox(
261
						"You may now <a href=\"$baseurl/acc.php\">Login</a>", 
262
						"alert-error", 
263
						"Password reset!", 
264
						true, 
265
						false);
266
                    
267
					BootstrapSkin::displayInternalFooter();
268
					die();
269
				}
270
				else {
271
					BootstrapSkin::displayAlertBox("Passwords did not match!", "alert-error", "Error", true, false);
272
					BootstrapSkin::displayInternalFooter();
273
					die();
274
				}
275
			}
276
			else {
277
				BootstrapSkin::displayAlertBox("Invalid request<!-- 1 -->", "alert-error", "Error", true, false);
278
				BootstrapSkin::displayInternalFooter();
279
				die();
280
			}
281
		}
282
        
283
		$hash = $user->getForgottenPasswordHash();
284
        
285
		if ($hash == $_GET['si']) {
286
			$smarty->assign('user', $user);
287
			$smarty->assign('si', $_GET['si']);
288
			$smarty->assign('id', $_GET['id']);
289
			$smarty->display('forgot-password/forgotpwreset.tpl');
290
		}
291
		else {
292
			BootstrapSkin::displayAlertBox(
293
				"The hash supplied in the link did not match the hash in the database!", 
294
				"alert-error", 
295
				"Invalid request", 
296
				true, 
297
				false);
298
		}
299
        
300
		BootstrapSkin::displayInternalFooter();
301
		die();
302
	}
303
    
304
	if (isset ($_POST['username'])) {
305
		$user = User::getByUsername($_POST['username'], gGetDb());
306
307
		if ($user == false) {
308
			BootstrapSkin::displayAlertBox(
309
				"Could not find user with that username and email address!", 
310
				"alert-error", 
311
				"Error", 
312
				true, 
313
				false);
314
            
315
			BootstrapSkin::displayInternalFooter();
316
			die();
317
		}
318
		elseif (strtolower($_POST['email']) != strtolower($user->getEmail())) {
319
			BootstrapSkin::displayAlertBox("Could not find user with that username and email address!", 
320
				"alert-error", 
321
				"Error", 
322
				true, 
323
				false);
324
            
325
			BootstrapSkin::displayInternalFooter();
326
			die();
327
		}
328
		else {
329
			$hash = $user->getForgottenPasswordHash();
330
                       
331
			$smarty->assign("user", $user);
332
			$smarty->assign("hash", $hash);
333
			$smarty->assign("remoteAddress", $_SERVER['REMOTE_ADDR']);
334
            
335
			$mailtxt = $smarty->fetch("forgot-password/reset-mail.tpl");
336
			$headers = 'From: [email protected]';
337
            
338
			mail(
339
				$user->getEmail(), 
340
				"English Wikipedia Account Request System - Forgotten password", 
341
				$mailtxt, 
342
				$headers);
343
            
344
			BootstrapSkin::displayAlertBox(
345
				"<strong>Your password reset request has been completed.</strong> Please check your e-mail.", 
346
				"alert-success", 
347
				"", 
348
				false, 
349
				false);
350
            
351
			BootstrapSkin::displayInternalFooter();
352
			die();
353
		}
354
	}
355
    
356
	$smarty->display('forgot-password/forgotpw.tpl');
357
358
	BootstrapSkin::displayInternalFooter();
359
	die();
360
}
361
elseif ($action == "login") {
362
	global $baseurl, $smarty;
363
    
364
	if (!isset($_POST['username'])) {
365
		header("Location: $baseurl/acc.php?error=authfail&tplUsername=");
366
		die();
367
	}
368
369
	$user = User::getByUsername($_POST['username'], gGetDb());
370
    
371
	if ($user == false || !$user->authenticate($_POST['password'])) {
372
		header("Location: $baseurl/acc.php?error=authfail&tplUsername=" . urlencode($_POST['username']));
373
		die();
374
	}
375
    
376
	if ($user->getStoredOnWikiName() == "##OAUTH##" && $user->getOAuthAccessToken() == null) {
377
		reattachOAuthAccount($user);   
378
	}
379
    
380
	if ($user->isOAuthLinked()) {
381
		try {
382
			// test retrieval of the identity
383
			$user->getOAuthIdentity();
384
		}
385
		catch (TransactionException $ex) {
386
			$user->setOAuthAccessToken(null);
387
			$user->setOAuthAccessSecret(null);
388
			$user->save();
389
            
390
			reattachOAuthAccount($user);
391
		}
392
	}
393
	else {
394
		global $enforceOAuth;
395
        
396
		if ($enforceOAuth) {
397
			reattachOAuthAccount($user);
398
		}
399
	}
400
    
401
	// At this point, the user has successfully authenticated themselves.
402
	// We now proceed to perform login-specific actions, and check the user actually has
403
	// the correct permissions to continue with the login.
404
    
405
	if ($user->getForcelogout()) {
406
		$user->setForcelogout(false);
407
		$user->save();
408
	}
409
    
410
	if ($user->isNew()) {
411
		header("Location: $baseurl/acc.php?error=newacct");
412
		die();
413
	}
414
    
415
	$database = gGetDb();
416
    
417
	$sqlText = <<<SQL
418
SELECT comment FROM log
419
WHERE action = :action AND objectid = :userid AND objecttype = 'User'
420
ORDER BY timestamp DESC LIMIT 1;
421
SQL;
422
    
423
	$suspendstatement = $database->prepare($sqlText);
424
    
425 View Code Duplication
	if ($user->isDeclined()) {
426
		$suspendAction = "Declined";
427
		$userid = $user->getId();
428
		$suspendstatement->bindValue(":action", $suspendAction);
429
		$suspendstatement->bindValue(":userid", $userid);
430
		$suspendstatement->execute();
431
        
432
		$suspendreason = $suspendstatement->fetchColumn();
433
        
434
		$suspendstatement->closeCursor();
435
        
436
		BootstrapSkin::displayInternalHeader();
437
		$smarty->assign("suspendreason", $suspendreason);
438
		$smarty->display("login/declined.tpl");
439
		BootstrapSkin::displayInternalFooter();
440
		die();
441
	}
442
    
443 View Code Duplication
	if ($user->isSuspended()) {
444
		$suspendAction = "Suspended";
445
		$userid = $user->getId();
446
		$suspendstatement->bindValue(":action", $suspendAction);
447
		$suspendstatement->bindValue(":userid", $userid);
448
		$suspendstatement->execute();
449
        
450
		$suspendreason = $suspendstatement->fetchColumn();
451
        
452
		$suspendstatement->closeCursor();
453
        
454
		BootstrapSkin::displayInternalHeader();
455
		$smarty->assign("suspendreason", $suspendreason);
456
		$smarty->display("login/suspended.tpl");
457
		BootstrapSkin::displayInternalFooter();
458
		die();
459
	}
460
    
461
	if (!$user->isIdentified() && $forceIdentification == 1) {
462
		header("Location: $baseurl/acc.php?error=noid");
463
		die();
464
	}
465
    
466
	// At this point, we've tested that the user is OK, so we set the login cookies.
467
    
468
	$_SESSION['user'] = $user->getUsername();
469
	$_SESSION['userID'] = $user->getId();
470
    
471
	if ($user->getOAuthAccessToken() == null && $user->getStoredOnWikiName() == "##OAUTH##") {
472
		reattachOAuthAccount($user);
473
	}
474
    
475
	header("Location: $baseurl/acc.php");
476
}
477
elseif ($action == "messagemgmt") {
478
	global $smarty;
479
    
480
	if (isset($_GET['view'])) {
481
		$message = InterfaceMessage::getById($_GET['view'], gGetDb());
482
                
483
		if ($message == false) {
484
			BootstrapSkin::displayAlertBox("Unable to find specified message", "alert-error", "Error", true, false);
485
			BootstrapSkin::displayInternalFooter();
486
			die();
487
		}
488
        
489
		$smarty->assign("message", $message);
490
		$smarty->assign("readonly", true);
491
		$smarty->display("message-management/editform.tpl");
492
		BootstrapSkin::displayInternalFooter();
493
		die();
494
	}
495
	if (isset($_GET['edit'])) {
496
		if (!(User::getCurrent()->isAdmin() || User::getCurrent()->isCheckuser())) {
497
			BootstrapSkin::displayAccessDenied();
498
			BootstrapSkin::displayInternalFooter();
499
			die();
500
		}
501
        
502
		$database = gGetDb();
503
        
504
		$database->transactionally(function() use ($database)
505
		{
506
			global $smarty;
507
            
508
			$message = InterfaceMessage::getById($_GET['edit'], $database);
509
            
510
			if ($message == false) {
511
				throw new TransactionException("Unable to find specified message", "Error");
512
			}
513
            
514
			if (isset($_GET['submit'])) {
515
				$message->setContent($_POST['mailtext']);
516
				$message->setDescription($_POST['maildesc']);
517
				$message->save();
518
            
519
				Logger::interfaceMessageEdited(gGetDb(), $message);
520
              
521
				$smarty->assign("message", $message);
522
				$smarty->display("message-management/alert-editsuccess.tpl");
523
                
524
				Notification::interfaceMessageEdited($message);
525
                
526
				BootstrapSkin::displayInternalFooter();
527
				return;
528
			}
529
            
530
			$smarty->assign("message", $message);
531
			$smarty->assign("readonly", false);
532
			$smarty->display("message-management/editform.tpl");
533
        
534
			BootstrapSkin::displayInternalFooter();
535
		});
536
        
537
		die();
538
	}
539
    
540
	$sqlText = <<<SQL
541
        SELECT * 
542
        FROM interfacemessage 
543
        WHERE type = :type 
544
            AND description NOT LIKE '%[deprecated]';
545
SQL;
546
    
547
	$fetchStatement = gGetDb()->prepare($sqlText);
548
	$data = array();
549
        
550
	//$fetchStatement->execute(array(":type" => "Interface"));
551
	//$data['Public Interface messages'] = $fetchStatement->fetchAll(PDO::FETCH_CLASS, 'InterfaceMessage');
552
    
553
	$fetchStatement->execute(array(":type" => "Internal"));
554
	$data['Internal Interface messages'] = $fetchStatement->fetchAll(PDO::FETCH_CLASS, 'InterfaceMessage');
555
    
556
	$smarty->assign("data", $data);
557
	$smarty->display('message-management/view.tpl');
558
   
559
	BootstrapSkin::displayInternalFooter();
560
	die();
561
}
562
elseif ($action == "templatemgmt") {
563
	global $baseurl, $smarty;
564
    
565
	if (isset($_GET['view'])) {
566
		$template = WelcomeTemplate::getById($_GET['view'], gGetDb());
567
        
568
		if ($template === false) {
569
			SessionAlert::success("Something went wrong, we can't find the template you asked for! Please try again.");
570
			header("Location: {$baseurl}/acc.php?action=templatemgmt");
571
			die();
572
		}
573
        
574
		$smarty->assign("template", $template);
575
		$smarty->display("welcometemplate/view.tpl");
576
		BootstrapSkin::displayInternalFooter();
577
		die();
578
	}
579
    
580
	if (isset($_GET['add'])) {
581
		if (!User::getCurrent()->isAdmin() && !User::getCurrent()->isCheckuser()) {
582
			BootstrapSkin::displayAccessDenied();
583
            
584
			BootstrapSkin::displayInternalFooter();
585
			die();
586
		}
587
        
588
		if (isset($_POST['submit'])) {
589
			global $baseurl;
590
            
591
			$database = gGetDb();
592
            
593 View Code Duplication
			$database->transactionally(function() use ($database, $baseurl)
594
			{
595
				$template = new WelcomeTemplate();
596
				$template->setDatabase($database);
597
				$template->setUserCode($_POST['usercode']);
598
				$template->setBotCode($_POST['botcode']);
599
				$template->save();
600
            
601
				Logger::welcomeTemplateCreated($database, $template);
602
                            
603
				Notification::welcomeTemplateCreated($template);
604
            
605
				SessionAlert::success("Template successfully created.");
606
				header("Location: $baseurl/acc.php?action=templatemgmt");
607
			});
608
		}
609
		else {
610
			
611
			if (isset($_POST['preview'])) {
612
				$usercode = $_POST['usercode'];
613
				$botcode = $_POST['botcode'];
614
				echo displayPreview($usercode);
615
			}
616
			else {
617
				$usercode = '';
618
				$botcode = '';
619
			}
620
621
			$smarty->assign("usercode", $usercode);
622
			$smarty->assign("botcode", $botcode);
623
            
624
			$smarty->display("welcometemplate/add.tpl");
625
			BootstrapSkin::displayInternalFooter();
626
			die();
627
		}
628
        
629
		die();
630
	}
631
    
632
	if (isset($_GET['select'])) {
633
		$user = User::getCurrent();
634
        
635
		if ($_GET['select'] == 0) {
636
			$user->setWelcomeTemplate(null);
637
			$user->save();
638
            
639
			SessionAlert::success("Disabled automatic user welcoming.");
640
			header("Location: {$baseurl}/acc.php?action=templatemgmt");
641
			die();
642
		}
643
		else {
644
			$template = WelcomeTemplate::getById($_GET['select'], gGetDb());
645
			if ($template !== false) {
646
				$user->setWelcomeTemplate($template->getId());
647
				$user->save();
648
                
649
				SessionAlert::success("Updated selected welcome template for automatic welcoming.");
650
				header("Location: {$baseurl}/acc.php?action=templatemgmt");
651
				die();
652
			}
653
			else {
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
	}
660
    
661
	if (isset($_GET['del'])) {
662
		global $baseurl;
663
        
664
		if (!User::getCurrent()->isAdmin() && !User::getCurrent()->isCheckuser()) {
665
			BootstrapSkin::displayAccessDenied();
666
			BootstrapSkin::displayInternalFooter();
667
			die();
668
		}
669
670
		$database = gGetDb();
671
        
672
		$template = WelcomeTemplate::getById($_GET['del'], $database);
673
		if ($template == false) {
674
			SessionAlert::error("Something went wrong, we can't find the template you asked for!");
675
			header("Location: {$baseurl}/acc.php?action=templatemgmt");
676
			die();
677
		}
678
        
679
		$database->transactionally(function() use($database, $template)
680
		{
681
			$tid = $template->getId();
682
            
683
			$database
684
				->prepare("UPDATE user SET welcome_template = NULL WHERE welcome_template = :id;")
685
				->execute(array(":id" => $tid));
686
            
687
			Logger::welcomeTemplateDeleted($database, $template);
688
            
689
			$template->delete();
690
            
691
			SessionAlert::success("Template deleted. Any users who were using this template have had automatic welcoming disabled.");
692
			Notification::welcomeTemplateDeleted($tid);
693
		});
694
        
695
		header("Location: $baseurl/acc.php?action=templatemgmt");
696
		die();			
697
	}
698
    
699
	if (isset($_GET['edit'])) {
700
		if (!User::getCurrent()->isAdmin() && !User::getCurrent()->isCheckuser()) {
701
			BootstrapSkin::displayAccessDenied();
702
			BootstrapSkin::displayInternalFooter();
703
			die();
704
		}
705
706
		$database = gGetDb();
707
        
708
		$template = WelcomeTemplate::getById($_GET['edit'], $database);
709
		if ($template == false) {
710
			SessionAlert::success("Something went wrong, we can't find the template you asked for! Please try again.");
711
			header("Location: {$baseurl}/acc.php?action=templatemgmt");
712
			die();
713
		}
714
715
		if (isset($_POST['submit'])) {
716
			$database->transactionally(function() use($database, $template)
717
			{
718
				$template->setUserCode($_POST['usercode']);
719
				$template->setBotCode($_POST['botcode']);
720
				$template->save();
721
			
722
				Logger::welcomeTemplateEdited($database, $template);
723
                
724
				SessionAlert::success("Template updated.");
725
				Notification::welcomeTemplateEdited($template);
726
			});
727
            
728
			header("Location: $baseurl/acc.php?action=templatemgmt");
729
			die();
730
		}
731
		else {
732
			$smarty->assign("template", $template);
733
			$smarty->display("welcometemplate/edit.tpl");
734
            
735
			BootstrapSkin::displayInternalFooter();
736
			die();
737
		}
738
	}
739
    
740
	$templateList = WelcomeTemplate::getAll();
741
    
742
	$smarty->assign("templatelist", $templateList);
743
	$smarty->display("welcometemplate/list.tpl");
744
    
745
	BootstrapSkin::displayInternalFooter();
746
	die();
747
}
748
elseif ($action == "sban") {
749
	global $smarty;
750
    
751
	// Checks whether the current user is an admin.
752
	if (!User::getCurrent()->isAdmin() && !User::getCurrent()->isCheckuser()) {
753
		BootstrapSkin::displayAccessDenied();
754
		BootstrapSkin::displayInternalFooter();
755
		die();
756
	}
757
	
758
	// Checks whether there is a reason entered for ban.
759
	if (!isset($_POST['banreason']) || $_POST['banreason'] == "") {
760
		BootstrapSkin::displayAlertBox("You must specify a ban reason", "alert-error", "", false, false);
761
		BootstrapSkin::displayInternalFooter();
762
		die();
763
	}
764
	
765
	// Checks whether there is a target entered to ban.
766
	if (!isset($_POST['target']) || $_POST['target'] == "") {
767
		BootstrapSkin::displayAlertBox("You must specify a target to be banned", "alert-error", "", false, false);
768
		BootstrapSkin::displayInternalFooter();
769
		die();
770
	}
771
	
772
	$duration = $_POST['duration'];
773
    
774
	if ($duration == "-1") {
775
		$duration = -1;
776
	}
777
	elseif ($duration == "other") {
778
		$duration = strtotime($_POST['otherduration']);
779
		if (!$duration) {
780
			BootstrapSkin::displayAlertBox("Invalid ban time", "alert-error", "", false, false);
781
			BootstrapSkin::displayInternalFooter();
782
			die();
783
		}
784
		elseif (time() > $duration) {
785
			BootstrapSkin::displayAlertBox("Ban time has already expired!", "alert-error", "", false, false);
786
			BootstrapSkin::displayInternalFooter();
787
			die();
788
		}
789
	}
790
	else {
791
		$duration = $duration + time();
792
	}
793
    
794
	switch ($_POST['type']) {
795
		case 'IP':
796 View Code Duplication
			if (filter_var($_POST['target'], FILTER_VALIDATE_IP) === false) {
797
				BootstrapSkin::displayAlertBox("Invalid target - IP address expected.", "alert-error", "", false, false);
798
				BootstrapSkin::displayInternalFooter();
799
				die();
800
			}
801
            
802
			global $squidIpList;
803
			if (in_array($_POST['target'], $squidIpList)) {
804
				BootstrapSkin::displayAlertBox(
805
					"This IP address is on the protected list of proxies, and cannot be banned.", 
806
					"alert-error", 
807
					"", 
808
					false, 
809
					false);
810
				BootstrapSkin::displayInternalFooter();
811
				die();
812
			}
813
			break;
814
		case 'Name':
815
			break;
816
		case 'EMail':
817
			// TODO: cut this down to a bare-bones implementation so we don't accidentally reject a valid address.
818
			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'])) {
819
				BootstrapSkin::displayAlertBox(
820
					"Invalid target - email address expected.", 
821
					"alert-error", 
822
					"", 
823
					false, 
824
					false);
825
                
826
				BootstrapSkin::displayInternalFooter();
827
				die();
828
			}
829
			break;
830
		default:
831
			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);
832
			BootstrapSkin::displayInternalFooter();
833
			die();
834
	}
835
        
836
	if (count(Ban::getActiveBans($_POST['target'])) > 0) {
837
		BootstrapSkin::displayAlertBox("This target is already banned!", "alert-error", "", false, false);
838
		BootstrapSkin::displayInternalFooter();
839
		die();
840
	}
841
    
842
	$database = gGetDb();
843
    
844
	$ban = new Ban();
845
    
846
	$currentUsername = User::getCurrent()->getUsername();
847
    
848
	$database->transactionally(function() use ($database, $ban, $duration, $currentUsername)
849
	{
850
		$ban->setDatabase($database);
851
		$ban->setActive(1);
852
		$ban->setType($_POST['type']);
853
		$ban->setTarget($_POST['target']);
854
		$ban->setUser($currentUsername);
855
		$ban->setReason($_POST['banreason']);
856
		$ban->setDuration($duration);
857
    
858
		$ban->save();
859
        
860
		Logger::banned($database, $ban, $_POST['banreason']);
861
	});
862
    
863
	$smarty->assign("ban", $ban);
864
	BootstrapSkin::displayAlertBox($smarty->fetch("bans/bancomplete.tpl"), "alert-info", "", false, false);
865
        
866
	Notification::banned($ban);
867
    
868
	BootstrapSkin::displayInternalFooter();
869
	die();
870
}
871
elseif ($action == "unban") {
872
	global $smarty;
873
    
874
	if (!isset($_GET['id']) || $_GET['id'] == "") {
875
		BootstrapSkin::displayAlertBox(
876
			"The ID parameter appears to be missing! This is probably a bug.", 
877
			"alert-error", 
878
			"Ahoy There! Something's not right...", 
879
			true, 
880
			false);
881
		BootstrapSkin::displayInternalFooter();
882
		die();
883
	}
884
    
885
	if (!User::getCurrent()->isAdmin() && !User::getCurrent()->isCheckuser()) {
886
		BootstrapSkin::displayAccessDenied();
887
		BootstrapSkin::displayInternalFooter();
888
		die();
889
	}
890
    
891
	$ban = Ban::getActiveId($_GET['id']);
892
        
893
	if ($ban == false) {
894
		BootstrapSkin::displayAlertBox(
895
			"The specified ban ID is not currently active or doesn't exist!", 
896
			"alert-error", 
897
			"", 
898
			false, 
899
			false);
900
        
901
		BootstrapSkin::displayInternalFooter();
902
		die();
903
	}
904
905
	if (isset($_GET['confirmunban']) && $_GET['confirmunban'] == "true") {
906
		if (!isset($_POST['unbanreason']) || $_POST['unbanreason'] == "") {
907
			BootstrapSkin::displayAlertBox("You must enter an unban reason!", "alert-error", "", false, false);
908
			BootstrapSkin::displayInternalFooter();
909
			die();
910
		}
911
		else {
912
			$database = gGetDb();
913
            
914
			$database->transactionally(function() use ($database, $ban)
915
			{
916
				$ban->setActive(0);
917
				$ban->save();
918
                
919
				$banId = $ban->getId();
920
				$currentUser = User::getCurrent()->getUsername();
921
                
922
				Logger::unbanned($database, $ban, $_POST['unbanreason']);
923
			});
924
        
925
			BootstrapSkin::displayAlertBox("Unbanned " . $ban->getTarget(), "alert-info", "", false, false);
926
			BootstrapSkin::displayInternalFooter();
927
			Notification::unbanned($ban, $_POST['unbanreason']);
928
			die();
929
		}
930
	}
931
	else {
932
		$smarty->assign("ban", $ban);
933
		$smarty->display("bans/unban.tpl");
934
        
935
		BootstrapSkin::displayInternalFooter();
936
	}
937
}
938
elseif ($action == "ban") {
939
	global $smarty;
940
    
941
	if (isset ($_GET['ip']) || isset ($_GET['email']) || isset ($_GET['name'])) {
942
		if (!$session->hasright($_SESSION['user'], "Admin")) {
943
			BootstrapSkin::displayAlertBox("Only administrators or checkusers may ban users", "alert-error");
944
			BootstrapSkin::displayInternalFooter();
945
			die();
946
		}
947
        
948
		$database = gGetDb();
949
		// TODO: rewrite me!
950
		if (isset($_GET['ip'])) {
951
			$query = "SELECT ip, forwardedip FROM request WHERE id = :ip;";
952
			$statement = $database->prepare($query);
953
			$statement->bindValue(":ip", $_GET['ip']);
954
			$statement->execute();
955
			$row = $statement->fetch(PDO::FETCH_ASSOC);
956
			$target = getTrustedClientIP($row['ip'], $row['forwardedip']);
957
			$type = "IP";
958
		}
959 View Code Duplication
		elseif (isset($_GET['email'])) {
960
			$query = "SELECT email FROM request WHERE id = :ip;";
961
			$statement = $database->prepare($query);
962
			$statement->bindValue(":ip", $_GET['email']);
963
			$statement->execute();
964
			$row = $statement->fetch(PDO::FETCH_ASSOC);
965
			$target = $row['email'];
966
			$type = "EMail";
967
		}
968 View Code Duplication
		elseif (isset($_GET['name'])) {
969
			$query = "SELECT name FROM request WHERE id = :ip;";
970
			$statement = $database->prepare($query);
971
			$statement->bindValue(":ip", $_GET['name']);
972
			$statement->execute();
973
			$row = $statement->fetch(PDO::FETCH_ASSOC);
974
			$target = $row['name'];
975
			$type = "Name";
976
		}
977
		else {
978
			BootstrapSkin::displayAlertBox("Unknown ban type.", "alert-error");
979
			BootstrapSkin::displayInternalFooter();
980
			die();    
981
		}
982
        
983
		if (count(Ban::getActiveBans($target))) {
984
			BootstrapSkin::displayAlertBox("This target is already banned!", "alert-error");
985
			BootstrapSkin::displayInternalFooter();
986
			die();
987
		} 
988
        
989
		$smarty->assign("bantype", $type);
990
		$smarty->assign("bantarget", trim($target));
991
		$smarty->display("bans/banform.tpl");
992
	}
993
	else {
994
		$bans = Ban::getActiveBans();
995
  
996
		$smarty->assign("activebans", $bans);
997
		$smarty->display("bans/banlist.tpl");
998
	}
999
    
1000
	BootstrapSkin::displayInternalFooter();
1001
	die();
1002
}
1003
elseif ($action == "defer" && $_GET['id'] != "" && $_GET['sum'] != "") {
1004
	global $availableRequestStates;
1005
	
1006
	if (array_key_exists($_GET['target'], $availableRequestStates)) {
1007
		$request = Request::getById($_GET['id'], gGetDb());
1008
		
1009
		if ($request == false) {
1010
			BootstrapSkin::displayAlertBox(
1011
				"Could not find the specified request!", 
1012
				"alert-error", 
1013
				"Error!", 
1014
				true, 
1015
				false);
1016
            
1017
			BootstrapSkin::displayInternalFooter();
1018
			die();
1019
		}
1020
		
1021
		if ($request->getChecksum() != $_GET['sum']) {
1022
			SessionAlert::error(
1023
				"This is similar to an edit conflict on Wikipedia; it means that you have tried to perform an action "
1024
				. "on a request that someone else has performed an action on since you loaded the page",
1025
				"Invalid checksum");
1026
            
1027
			header("Location: acc.php?action=zoom&id={$request->getId()}");
1028
			die();
1029
		}
1030
        
1031
		$sqlText = <<<SQL
1032
SELECT timestamp FROM log
1033
WHERE objectid = :request and objecttype = 'Request' AND action LIKE 'Closed%'
1034
ORDER BY timestamp DESC LIMIT 1;
1035
SQL;
1036
        
1037
		$statement = gGetDb()->prepare($sqlText);
1038
		$statement->execute(array(":request" => $request->getId()));
1039
		$logTime = $statement->fetchColumn();
1040
		$statement->closeCursor();
1041
        
1042
		$date = new DateTime();
1043
		$date->modify("-7 days");
1044
		$oneweek = $date->format("Y-m-d H:i:s");
1045
        
1046
		if ($request->getStatus() == "Closed" 
1047
			&& $logTime < $oneweek 
1048
			&& !User::getCurrent()->isAdmin() 
1049
			&& !User::getCurrent()->isCheckuser()) {
1050
			SessionAlert::error("Only administrators and checkusers can reopen a request that has been closed for over a week.");
1051
			header("Location: acc.php?action=zoom&id={$request->getId()}");
1052
			die();
1053
		}
1054
        
1055
		if ($request->getStatus() == $_GET['target']) {
1056
			SessionAlert::error(
1057
				"Cannot set status, target already deferred to " . htmlentities($_GET['target']), 
1058
				"Error");
1059
			header("Location: acc.php?action=zoom&id={$request->getId()}");
1060
			die();
1061
		}
1062
        
1063
		$database = gGetDb();
1064
		$database->transactionally(function() use ($database, $request)
1065
		{
1066
			global $availableRequestStates;
1067
                
1068
			$request->setReserved(0);
1069
			$request->setStatus($_GET['target']);
1070
			$request->updateChecksum();
1071
			$request->save();
1072
            
1073
			$deto = $availableRequestStates[$_GET['target']]['deferto'];
1074
			$detolog = $availableRequestStates[$_GET['target']]['defertolog'];
1075
            
1076
			Logger::deferRequest($database, $request, $detolog);
1077
        
1078
			Notification::requestDeferred($request);
1079
			SessionAlert::success("Request {$request->getId()} deferred to $deto");
1080
			header("Location: acc.php");
1081
		});
1082
        
1083
		die();
1084
	}
1085
	else {
1086
		BootstrapSkin::displayAlertBox("Defer target not valid.", "alert-error", "Error", true, false);
1087
		BootstrapSkin::displayInternalFooter();
1088
		die();
1089
	}
1090
}
1091
elseif ($action == "prefs") {
1092
	global $smarty, $enforceOAuth;
1093
    
1094
	if (isset ($_POST['sig'])) {
1095
		$user = User::getCurrent();
1096
		$user->setWelcomeSig($_POST['sig']);
1097
		$user->setEmailSig($_POST['emailsig']);
1098
		$user->setAbortPref(isset($_POST['abortpref']) ? 1 : 0);
1099
        
1100
		if (isset($_POST['email'])) {
1101
			$mailisvalid = filter_var(trim($_POST['email']), FILTER_VALIDATE_EMAIL);
1102
            
1103
			if ($mailisvalid === false) {
1104
				BootstrapSkin::displayAlertBox("Invalid email address", "alert-error", "Error!");
1105
			}
1106
			else {
1107
				$user->setEmail(trim($_POST['email']));
1108
			}
1109
		}
1110
1111
		try {
1112
			$user->save();
1113
		}
1114
		catch (PDOException $ex) {
1115
			BootstrapSkin::displayAlertBox($ex->getMessage(), "alert-error", "Error saving Preferences", true, false);
1116
			BootstrapSkin::displayInternalFooter();
1117
			die();
1118
		}
1119
        
1120
		BootstrapSkin::displayAlertBox("Preferences updated!", "alert-info");
1121
	}
1122
    
1123
	$smarty->assign("enforceOAuth", $enforceOAuth);
1124
	$smarty->display("prefs.tpl");
1125
	BootstrapSkin::displayInternalFooter();
1126
	die();
1127
}
1128
elseif ($action == "done" && $_GET['id'] != "") {
1129
	// check for valid close reasons
1130
	global $messages, $baseurl, $smarty;
1131
	
1132
	if (isset($_GET['email'])) {
1133
		if ($_GET['email'] == 0 || $_GET['email'] == "custom") {
1134
			$validEmail = true;
1135
		}
1136
		else {
1137
			$validEmail = EmailTemplate::getById($_GET['email'], gGetDb()) != false;
1138
		}
1139
	}
1140
	else {
1141
		$validEmail = false;
1142
	}
1143
    
1144
	if ($validEmail == false) {
1145
		BootstrapSkin::displayAlertBox("Invalid close reason", "alert-error", "Error", true, false);
1146
		BootstrapSkin::displayInternalFooter();
1147
		die();
1148
	}
1149
	
1150
	// sanitise this input ready for inclusion in queries
1151
	$request = Request::getById($_GET['id'], gGetDb());
1152
    
1153
	if ($request == false) {
1154
		// Notifies the user and stops the script.
1155
		BootstrapSkin::displayAlertBox("The request ID supplied is invalid!", "alert-error", "Error", true, false);
1156
		BootstrapSkin::displayInternalFooter();
1157
		die();
1158
	}
1159
    
1160
	$gem = $_GET['email'];
1161
	
1162
	// check the checksum is valid
1163
	if ($request->getChecksum() != $_GET['sum']) {
1164
		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);
1165
		BootstrapSkin::displayInternalFooter();
1166
		die();
1167
	}
1168
	
1169
	// check if an email has already been sent
1170
	if ($request->getEmailSent() == "1" && !isset($_GET['override']) && $gem != 0) {
1171
		$alertContent = "<p>This request has already been closed in a manner that has generated an e-mail to the user, Proceed?</p><br />";
1172
		$alertContent .= "<div class=\"row-fluid\">";
1173
		$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>";
1174
		$alertContent .= "<a class=\"btn btn-danger span3\" href=\"$baseurl/acc.php\">No</a>";
1175
		$alertContent .= "</div>";
1176
        
1177
		BootstrapSkin::displayAlertBox($alertContent, "alert-info", "Warning!", true, false, false, true);
1178
		BootstrapSkin::displayInternalFooter();
1179
		die();
1180
	}
1181
	
1182
	// check the request is not reserved by someone else
1183
	if ($request->getReserved() != 0 && !isset($_GET['reserveoverride']) && $request->getReserved() != User::getCurrent()->getId()) {
1184
		$alertContent = "<p>This request is currently marked as being handled by " . $request->getReservedObject()->getUsername() . ", Proceed?</p><br />";
1185
		$alertContent .= "<div class=\"row-fluid\">";
1186
		$alertContent .= "<a class=\"btn btn-success offset3 span3\"  href=\"$baseurl/acc.php?" . $_SERVER["QUERY_STRING"] . "&reserveoverride=yes\">Yes</a>";
1187
		$alertContent .= "<a class=\"btn btn-danger span3\" href=\"$baseurl/acc.php\">No</a>";
1188
		$alertContent .= "</div>";
1189
        
1190
		BootstrapSkin::displayAlertBox($alertContent, "alert-info", "Warning!", true, false, false, true);
1191
		BootstrapSkin::displayInternalFooter();
1192
		die();
1193
	}
1194
	    
1195
	if ($request->getStatus() == "Closed") {
1196
		BootstrapSkin::displayAlertBox("Cannot close this request. Already closed.", "alert-error", "Error", true, false);
1197
		BootstrapSkin::displayInternalFooter();
1198
		die();
1199
	}
1200
	
1201
	// Checks whether the username is already in use on Wikipedia.
1202
	$userexist = file_get_contents("http://en.wikipedia.org/w/api.php?action=query&list=users&ususers=" . urlencode($request->getName()) . "&format=php");
1203
	$ue = unserialize($userexist);
1204
	if (!isset ($ue['query']['users']['0']['missing'])) {
1205
		$exists = true;
1206
	}
1207
	else {
1208
		$exists = false;
1209
	}
1210
	
1211
	// check if a request being created does not already exist. 
1212
	if ($gem == 1 && !$exists && !isset($_GET['createoverride'])) {
1213
		$alertContent = "<p>You have chosen to mark this request as \"created\", but the account does not exist on the English Wikipedia, proceed?</p><br />";
1214
		$alertContent .= "<div class=\"row-fluid\">";
1215
		$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...
1216
		$alertContent .= "<a class=\"btn btn-danger span3\" href=\"$baseurl/acc.php\">No</a>";
1217
		$alertContent .= "</div>";
1218
        
1219
		BootstrapSkin::displayAlertBox($alertContent, "alert-info", "Warning!", true, false, false, true);
1220
		BootstrapSkin::displayInternalFooter();
1221
		die();
1222
	}
1223
	
1224
	$messageBody = null;
1225
    
1226
	// custom close reasons
1227
	if ($gem == 'custom') {
1228
		if (!isset($_POST['msgbody']) or empty($_POST['msgbody'])) {
1229
			// Send it through htmlspecialchars so HTML validators don't complain. 
1230
			$querystring = htmlspecialchars($_SERVER["QUERY_STRING"], ENT_COMPAT, 'UTF-8'); 
1231
            
1232
			$template = false;
1233
			if (isset($_GET['preload'])) {
1234
				$template = EmailTemplate::getById($_GET['preload'], gGetDb());
1235
			}
1236
            
1237
			if ($template != false) {
1238
				$preloadTitle = $template->getName();
1239
				$preloadText = $template->getText();
1240
				$preloadAction = $template->getDefaultAction();
1241
			}
1242
			else {
1243
				$preloadText = "";
1244
				$preloadTitle = "";
1245
				$preloadAction = "";
1246
			}
1247
            
1248
			$smarty->assign("requeststates", $availableRequestStates);
1249
			$smarty->assign("defaultAction", $preloadAction);
1250
			$smarty->assign("preloadtext", $preloadText);
1251
			$smarty->assign("preloadtitle", $preloadTitle);
1252
			$smarty->assign("querystring", $querystring);
1253
			$smarty->assign("request", $request);
1254
			$smarty->assign("iplocation", $locationProvider->getIpLocation($request->getTrustedIp()));
1255
			$smarty->display("custom-close.tpl");
1256
			BootstrapSkin::displayInternalFooter();
1257
			die();
1258
		}
1259
1260
		$headers = 'From: [email protected]' . "\r\n";
1261
		if (!User::getCurrent()->isAdmin() || isset($_POST['ccmailist']) && $_POST['ccmailist'] == "on") {
1262
			$headers .= 'Cc: [email protected]' . "\r\n";
1263
		}
1264
1265
		$headers .= 'X-ACC-Request: ' . $request->getId() . "\r\n";
1266
		$headers .= 'X-ACC-UserID: ' . User::getCurrent()->getId() . "\r\n";
1267
1268
		// Get the closing user's Email signature and append it to the Email.
1269
		if (User::getCurrent()->getEmailSig() != "") {
1270
			$emailsig = html_entity_decode(User::getCurrent()->getEmailSig(), ENT_QUOTES, "UTF-8");
1271
			mail($request->getEmail(), "RE: [ACC #{$request->getId()}] English Wikipedia Account Request", $_POST['msgbody'] . "\n\n" . $emailsig, $headers);
0 ignored issues
show
This line exceeds maximum limit of 120 characters; contains 148 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...
1272
		}
1273
		else {
1274
			mail($request->getEmail(), "RE: [ACC #{$request->getId()}] English Wikipedia Account Request", $_POST['msgbody'], $headers);
0 ignored issues
show
This line exceeds maximum limit of 120 characters; contains 127 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...
1275
		}
1276
1277
		$request->setEmailSent(1);
1278
		$messageBody = $_POST['msgbody'];
1279
1280
		if ($_POST['action'] == EmailTemplate::CREATED || $_POST['action'] == EmailTemplate::NOT_CREATED) {
1281
			$request->setStatus('Closed');
1282
1283
			if($_POST['action'] == EmailTemplate::CREATED){
1284
				$gem  = 'custom-y';
1285
				$crea = "Custom, Created";
1286
			}
1287
			else {
1288
				$gem  = 'custom-n';
1289
				$crea = "Custom, Not Created";
1290
			}
1291
1292
			Logger::closeRequest(gGetDb(), $request, $gem, $messageBody);
1293
			
1294
			Notification::requestClosed($request, $crea);
1295
			BootstrapSkin::displayAlertBox(
1296
				"Request " . $request->getId() . " (" . htmlentities($request->getName(), ENT_COMPAT, 'UTF-8') . ") marked as 'Done'.", 
0 ignored issues
show
This line exceeds maximum limit of 120 characters; contains 124 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...
1297
				"alert-success");
1298
		}
1299
		else if ($_POST['action'] == "mail") {
1300
			// no action other than send mail!
1301
			Logger::sentMail(gGetDb(), $request, $messageBody);
0 ignored issues
show
$request is of type object<DataObject>|null, but the function expects a object<Request>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1302
			Logger::unreserve(gGetDb(), $request);
0 ignored issues
show
$request is of type object<DataObject>|null, but the function expects a object<Request>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1303
1304
			Notification::sentMail($request);
0 ignored issues
show
$request is of type object<DataObject>|null, but the function expects a object<Request>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1305
			BootstrapSkin::displayAlertBox("Sent mail to Request {$request->getId()}", 
1306
				"alert-success");
1307
		}
1308
		else if(array_key_exists($_POST['action'], $availableRequestStates) ) {
1309
			// Defer
1310
1311
			$request->setStatus($_POST['action']);
1312
			$deto = $availableRequestStates[$_POST['action']]['deferto'];
1313
			$detolog = $availableRequestStates[$_POST['action']]['defertolog'];
1314
1315
			Logger::sentMail(gGetDb(), $request, $messageBody);
0 ignored issues
show
$request is of type object<DataObject>|null, but the function expects a object<Request>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1316
			Logger::deferRequest(gGetDb(), $request, $detolog);
0 ignored issues
show
$request is of type object<DataObject>|null, but the function expects a object<Request>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1317
			
1318
			Notification::requestDeferredWithMail($request);
0 ignored issues
show
$request is of type object<DataObject>|null, but the function expects a object<Request>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1319
			BootstrapSkin::displayAlertBox("Request {$request->getId()} deferred to $deto, sending an email.", 
1320
				"alert-success");
1321
		}
1322
		else {
1323
			// hmm. not sure what happened. Log that we sent the mail anyway.
1324
			Logger::sentMail(gGetDb(), $request, $messageBody);
0 ignored issues
show
$request is of type object<DataObject>|null, but the function expects a object<Request>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1325
			Logger::unreserve(gGetDb(), $request);
0 ignored issues
show
$request is of type object<DataObject>|null, but the function expects a object<Request>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1326
1327
			Notification::sentMail($request);
0 ignored issues
show
$request is of type object<DataObject>|null, but the function expects a object<Request>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1328
			BootstrapSkin::displayAlertBox("Sent mail to Request {$request->getId()}", 
1329
				"alert-success");
1330
		}
1331
1332
		$request->setReserved(0);
1333
		$request->save();
1334
		
1335
		$request->updateChecksum();
1336
		$request->save();
1337
1338
		echo defaultpage();
1339
		BootstrapSkin::displayInternalFooter();
1340
		die();		
1341
	}
1342
	else{
1343
		// Not a custom close, just a normal close
1344
	    
1345
		$request->setStatus('Closed');
1346
		$request->setReserved(0);
1347
		
1348
		// TODO: make this transactional
1349
		$request->save();
1350
		
1351
		Logger::closeRequest(gGetDb(), $request, $gem, $messageBody);
0 ignored issues
show
$request is of type object<DataObject>|null, but the function expects a object<Request>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1352
		
1353
		if ($gem == '0') {
1354
			$crea = "Dropped";
1355
		}
1356
		else {
1357
			$template = EmailTemplate::getById($gem, gGetDb());
1358
			$crea = $template->getName();
1359
		}
1360
1361
		Notification::requestClosed($request, $crea);
0 ignored issues
show
$request is of type object<DataObject>|null, but the function expects a object<Request>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1362
		BootstrapSkin::displayAlertBox("Request " . $request->getId() . " (" . htmlentities($request->getName(), ENT_COMPAT, 'UTF-8') . ") marked as 'Done'.", "alert-success");
0 ignored issues
show
This line exceeds maximum limit of 120 characters; contains 170 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...
1363
		
1364
		$towhom = $request->getEmail();
1365
		if ($gem != "0") {
1366
			sendemail($gem, $towhom, $request->getId());
1367
			$request->setEmailSent(1);
1368
		}
1369
		
1370
		$request->updateChecksum();
1371
		$request->save();
1372
		
1373
		echo defaultpage();
1374
		BootstrapSkin::displayInternalFooter();
1375
		die();
1376
	}
1377
}
1378
elseif ($action == "zoom") {
1379
	if (!isset($_GET['id'])) {
1380
		BootstrapSkin::displayAlertBox("No request specified!", "alert-error", "Error!", true, false);
1381
		BootstrapSkin::displayInternalFooter();
1382
		die();
1383
	}
1384
    
1385
	if (isset($_GET['hash'])) {
1386
		$urlhash = $_GET['hash'];
1387
	}
1388
	else {
1389
		$urlhash = "";
1390
	}
1391
	echo zoomPage($_GET['id'], $urlhash);
1392
	BootstrapSkin::displayInternalFooter();
1393
	die();
1394
}
1395
elseif ($action == "logs") {
1396
	global $baseurl;
1397
	
1398
	$filterUser = isset($_GET['filterUser']) && $_GET['filterUser'] != "" ? $_GET['filterUser'] : false;
1399
	$filterAction = isset($_GET['filterAction']) && $_GET['filterAction'] != "" ? $_GET['filterAction'] : false;
1400
	
1401
	$limit = 100;
1402
	if (isset($_GET['limit'])) {
1403
		$limit = (int)$_GET['limit'];
1404
	}
1405
	
1406
	$offset = 0;
1407
	$page = 1;
1408
	if (isset($_GET['page'])) {
1409
		$page = (int)$_GET['page'];
1410
		$offset = ($page - 1) * $limit;
1411
	}
1412
	
1413
	$logs = Logger::getLogs($filterUser, $filterAction, $limit, $offset);
1414
	if ($logs === false) {
1415
		$smarty->assign("logs", array());
1416
		$smarty->display("logs/main.tpl");
1417
		BootstrapSkin::displayInternalFooter();
1418
		die();
1419
	}
1420
	
1421
	$count = $logs['count'];
1422
	unset($logs['count']);
1423
	
1424
	// The number of pages on the pager to show. Must be odd
1425
	$pageLimit = 9;
1426
	
1427
	$pageData = array( 
1428
		'canprev' => $page != 1,
1429
		'cannext' => ($page * $limit) < $count,
1430
		'maxpage' => ceil($count / $limit),
1431
		'pagelimit' => $pageLimit,
1432
	);
1433
	
1434
	$pageMargin = (($pageLimit - 1) / 2);
1435
	$pageData['lowpage'] = max(1, $page - $pageMargin);
1436
	$pageData['hipage'] = min($pageData['maxpage'], $page + $pageMargin);
1437
	
1438
	$pageCount = ($pageData['hipage'] - $pageData['lowpage']) + 1;
1439
	
1440
	if ($pageCount < $pageLimit) {
1441
		if ($pageData['lowpage'] == 1 && $pageData['hipage'] == $pageData['maxpage']) {
1442
			// nothing to do, we're already at max range.	
1443
		}
1444 View Code Duplication
		elseif ($pageData['lowpage'] == 1 && $pageData['hipage'] < $pageData['maxpage']) {
1445
			$pageData['hipage'] = min($pageLimit, $pageData['maxpage']);
1446
		}
1447 View Code Duplication
		elseif ($pageData['lowpage'] > 1 && $pageData['hipage'] == $pageData['maxpage']) {
1448
			$pageData['lowpage'] = max(1, $pageData['maxpage'] - $pageLimit + 1);
1449
		}
1450
	}
1451
	
1452
	$pageData['pages'] = range($pageData['lowpage'], $pageData['hipage']);
1453
		
1454
	$smarty->assign("pagedata", $pageData);
1455
	
1456
	$smarty->assign("limit", $limit);
1457
	$smarty->assign("page", $page);
1458
1459
	$smarty->assign("logs", $logs);
1460
	
1461
	
1462
	$smarty->assign("filterUser", $filterUser);
1463
	$smarty->assign("filterAction", $filterAction);
1464
	$smarty->display("logs/main.tpl");
1465
1466
	$tailscript = getTypeaheadSource(User::getAllUsernames(gGetDb(), true));
1467
	
1468
	BootstrapSkin::displayInternalFooter($tailscript);
1469
	die();
1470
}
1471
elseif ($action == "reserve") {
1472
	$database = gGetDb();
1473
    
1474
	$database->transactionally(function() use ($database)
1475
	{
1476
		$request = Request::getById($_GET['resid'], $database);
1477
        
1478
		if ($request == false) {
1479
			throw new TransactionException("Request not found", "Error");
1480
		}
1481
        
1482
		global $enableEmailConfirm, $baseurl;
1483
		if ($enableEmailConfirm == 1) {
1484
			if ($request->getEmailConfirm() != "Confirmed") {
1485
				throw new TransactionException("Email address not yet confirmed for this request.", "Error");
1486
			}
1487
		}
1488
1489
		$logQuery = $database->prepare(<<<SQL
1490
SELECT timestamp FROM log
1491
WHERE objectid = :request AND objecttype = 'Request' AND action LIKE 'Closed%'
1492
ORDER BY timestamp DESC LIMIT 1;
1493
SQL
1494
		);
1495
		$logQuery->bindValue(":request", $request->getId());
1496
		$logQuery->execute();
1497
		$logTime = $logQuery->fetchColumn();
1498
		$logQuery->closeCursor();
1499
        
1500
		$date = new DateTime();
1501
		$date->modify("-7 days");
1502
		$oneweek = $date->format("Y-m-d H:i:s");
1503
        
1504
		if ($request->getStatus() == "Closed" && $logTime < $oneweek && !User::getCurrent($database)->isAdmin()) {
1505
			throw new TransactionException("Only administrators and checkusers can reserve a request that has been closed for over a week.", "Error");
1506
		}
1507
        
1508
	   	if ($request->getReserved() != 0 && $request->getReserved() != User::getCurrent($database)->getId()) {
1509
			throw new TransactionException("Request is already reserved by {$request->getReservedObject()->getUsername()}.", "Error");
1510
		}
1511
           
1512
		if ($request->getReserved() == 0) {
1513
			// Check the number of requests a user has reserved already
1514
			$doubleReserveCountQuery = $database->prepare("SELECT COUNT(*) FROM request WHERE reserved = :userid;");
1515
			$doubleReserveCountQuery->bindValue(":userid", User::getCurrent($database)->getId());
1516
			$doubleReserveCountQuery->execute();
1517
			$doubleReserveCount = $doubleReserveCountQuery->fetchColumn();
1518
			$doubleReserveCountQuery->closeCursor();
1519
1520
			// User already has at least one reserved. 
1521
			if ($doubleReserveCount != 0) {
1522
				SessionAlert::warning("You have multiple requests reserved!");
1523
			}
1524
1525
			// Is the request closed?
1526
			if (!isset($_GET['confclosed'])) {
1527
				if ($request->getStatus() == "Closed") {
1528
					// FIXME: bootstrappify properly
1529
					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");
1530
				}
1531
			}	
1532
        
1533
			$request->setReserved(User::getCurrent($database)->getId());
1534
			$request->save();
1535
	
1536
			Logger::reserve($database, $request);
1537
                
1538
			Notification::requestReserved($request);
1539
                
1540
			SessionAlert::success("Reserved request {$request->getId()}.");
1541
		}
1542
        
1543
		header("Location: $baseurl/acc.php?action=zoom&id={$request->getId()}");
1544
	});
1545
	    
1546
	die();	
1547
}
1548
elseif ($action == "breakreserve") {
1549
	global $smarty;
1550
    
1551
	$database = gGetDb();
1552
    
1553
	$request = Request::getById($_GET['resid'], $database);
1554
        
1555
	if ($request == false) {
1556
		BootstrapSkin::displayAlertBox("Could not find request.", "alert-error", "Error", true, false);
1557
		BootstrapSkin::displayInternalFooter();
1558
		die();
1559
	}
1560
    
1561
	if ($request->getReserved() == 0) {
1562
		BootstrapSkin::displayAlertBox("Request is not reserved.", "alert-error", "Error", true, false);
1563
		BootstrapSkin::displayInternalFooter();
1564
		die();
1565
	}
1566
    
1567
	$reservedUser = $request->getReservedObject();
1568
    
1569
	if ($reservedUser == false) {
1570
		BootstrapSkin::displayAlertBox("Could not find user who reserved the request (!!).", "alert-error", "Error", true, false);
1571
		BootstrapSkin::displayInternalFooter();
1572
		die();
1573
	}
1574
    
1575
	if ($reservedUser->getId() != User::getCurrent()->getId()) {
1576
		if (User::getCurrent()->isAdmin()) {
1577
			if (isset($_GET['confirm']) && $_GET['confirm'] == 1) {
1578
				$database->transactionally(function() use($database, $request)
1579
				{
1580
					$request->setReserved(0);
1581
					$request->save();
1582
1583
					Logger::breakReserve($database, $request);
1584
                
1585
					Notification::requestReserveBroken($request);
1586
					header("Location: acc.php");
1587
				});
1588
                
1589
				die();
1590
			}
1591
			else {
1592
				global $baseurl;
1593
				$smarty->assign("reservedUser", $reservedUser);
1594
				$smarty->assign("request", $request);
1595
                
1596
				$smarty->display("confirmations/breakreserve.tpl");
1597
			}
1598
		}
1599
		else {
1600
			echo "You cannot break " . $reservedUser->getUsername() . "'s reservation";
1601
		}
1602
	}
1603
	else {
1604
		$database->transactionally(function() use ($database, $request)
1605
		{
1606
			$request->setReserved(0);
1607
			$request->save();
1608
1609
			Logger::unreserve($database, $request);
1610
        
1611
			Notification::requestUnreserved($request);
1612
			header("Location: acc.php");
1613
		});
1614
        
1615
		die();
1616
	}
1617
    
1618
	BootstrapSkin::displayInternalFooter();
1619
	die();		
1620
}
1621
elseif ($action == "comment") {
1622
	global $smarty;
1623
    
1624
	$request = Request::getById($_GET['id'], gGetDb());
1625
	$smarty->assign("request", $request);
1626
	$smarty->display("commentform.tpl");
1627
	BootstrapSkin::displayInternalFooter();
1628
	die();
1629
}
1630
elseif ($action == "comment-add") {
1631
	global $baseurl, $smarty;
1632
    
1633
	$request = Request::getById($_POST['id'], gGetDb());
1634
	if ($request == false) {
1635
		BootstrapSkin::displayAlertBox("Could not find request!", "alert-error", "Error", true, false);
1636
		BootstrapSkin::displayInternalFooter();
1637
		die();
1638
	}
1639
    
1640
	if (!isset($_POST['comment']) || $_POST['comment'] == "") {
1641
		BootstrapSkin::displayAlertBox("Comment must be supplied!", "alert-error", "Error", true, false);
1642
		BootstrapSkin::displayInternalFooter();
1643
		die(); 
1644
	}
1645
    
1646
	$visibility = 'user';
1647
	if (isset($_POST['visibility'])) {
1648
		// sanity check
1649
		$visibility = $_POST['visibility'] == 'user' ? 'user' : 'admin';
1650
	}
1651
    
1652
	//Look for and detect IPv4/IPv6 addresses in comment text, and warn the commenter.
1653 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") {
1654
			BootstrapSkin::displayAlertBox("IP address detected in comment text.  Warning acknowledgement checkbox must be checked.", "alert-error", "Error", true, false);
1655
			$smarty->assign("request", $request);
1656
			$smarty->assign("comment", $_POST['comment']);
1657
			$smarty->assign("actionLocation", "comment-add");
1658
			$smarty->display("privpol-warning.tpl");
1659
			BootstrapSkin::displayInternalFooter();
1660
			die();
1661
		}
1662
    
1663
	$comment = new Comment();
1664
	$comment->setDatabase(gGetDb());
1665
    
1666
	$comment->setRequest($request->getId());
1667
	$comment->setVisibility($visibility);
1668
	$comment->setUser(User::getCurrent()->getId());
1669
	$comment->setComment($_POST['comment']);
1670
    
1671
	$comment->save();
1672
    
1673
	if (isset($_GET['hash'])) {
1674
		$urlhash = urlencode(htmlentities($_GET['hash']));
1675
	}
1676
	else {
1677
		$urlhash = "";
1678
	}
1679
1680
	BootstrapSkin::displayAlertBox(
1681
		"<a href='$baseurl/acc.php?action=zoom&amp;id={$request->getId()}&amp;hash=$urlhash'>Return to request #{$request->getId()}</a>",
1682
		"alert-success",
1683
		"Comment added Successfully!",
1684
		true, false);
1685
        
1686
	Notification::commentCreated($comment);
1687
        
1688
	BootstrapSkin::displayInternalFooter();
1689
	die();
1690
}
1691
elseif ($action == "comment-quick") {
1692
	$request = Request::getById($_POST['id'], gGetDb());
1693
	if ($request == false) {
1694
		BootstrapSkin::displayAlertBox("Could not find request!", "alert-error", "Error", true, false);
1695
		BootstrapSkin::displayInternalFooter();
1696
		die();
1697
	}
1698
    
1699
	if (!isset($_POST['comment']) || $_POST['comment'] == "") {
1700
		header("Location: acc.php?action=zoom&id=" . $request->getId());
1701
		die(); 
1702
	}
1703
    
1704
	$visibility = 'user';
1705
	if (isset($_POST['visibility'])) {
1706
		// sanity check
1707
		$visibility = $_POST['visibility'] == 'user' ? 'user' : 'admin';
1708
	}
1709
1710
	//Look for and detect IPv4/IPv6 addresses in comment text, and warn the commenter.
1711 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") {
1712
			BootstrapSkin::displayAlertBox("IP address detected in comment text.  Warning acknowledgement checkbox must be checked.", "alert-error", "Error", true, false);
1713
			$smarty->assign("request", $request);
1714
			$smarty->assign("comment", $_POST['comment']);
1715
			$smarty->assign("actionLocation", "comment-quick");
1716
			$smarty->display("privpol-warning.tpl");
1717
			BootstrapSkin::displayInternalFooter();
1718
			die();
1719
		}
1720
    
1721
	$comment = new Comment();
1722
	$comment->setDatabase(gGetDb());
1723
    
1724
	$comment->setRequest($request->getId());
1725
	$comment->setVisibility($visibility);
1726
	$comment->setUser(User::getCurrent()->getId());
1727
	$comment->setComment($_POST['comment']);
1728
    
1729
	$comment->save();
1730
    
1731
	Notification::commentCreated($comment);
1732
    
1733
	header("Location: acc.php?action=zoom&id=" . $request->getId());
1734
}
1735
elseif ($action == "changepassword") {
1736
	if ((!isset($_POST['oldpassword'])) || $_POST['oldpassword'] == "") {
1737
		//Throw an error if old password is not specified.
1738
		BootstrapSkin::displayAlertBox("You did not enter your old password.", "alert-error", "Error", true, false);
1739
		BootstrapSkin::displayInternalFooter();
1740
		die();
1741
	}
1742
	
1743 View Code Duplication
	if ((!isset($_POST['newpassword'])) || $_POST['newpassword'] == "") {
1744
		//Throw an error if new password is not specified.
1745
		BootstrapSkin::displayAlertBox("You did not enter your new password.", "alert-error", "Error", true, false);
1746
		BootstrapSkin::displayInternalFooter();
1747
		die();
1748
	}
1749
	
1750 View Code Duplication
	if ($_POST['newpassword'] != $_POST['newpasswordconfirm']) {
1751
		//Throw an error if new password does not match what is in the confirmation box.
1752
		BootstrapSkin::displayAlertBox("The 2 new passwords you entered do not match.", "alert-error", "Error", true, false);
1753
		BootstrapSkin::displayInternalFooter();
1754
		die();
1755
	}
1756
    
1757
	$user = User::getCurrent();
1758
	   
1759
	if (!$user->authenticate($_POST['oldpassword'])) {
1760
		//Throw an error if the old password field's value does not match the user's current password.
1761
		BootstrapSkin::displayAlertBox("The old password you entered is not correct.", "alert-error", "Error", true, false);
1762
		BootstrapSkin::displayInternalFooter();
1763
		die();
1764
	}
1765
    
1766
	$user->setPassword($_POST['newpassword']);
1767
	$user->save();
1768
    
1769
	BootstrapSkin::displayAlertBox("Password successfully changed!", "alert-success", "", false, false);
1770
	BootstrapSkin::displayInternalFooter();
1771
	die();
1772
}
1773
elseif ($action == "ec") {
1774
	// edit comment
1775
  
1776
	global $smarty, $baseurl;
1777
    
1778
	$comment = Comment::getById($_GET['id'], gGetDb());
1779
    
1780
	if ($comment == false) {
1781
		// Only using die("Message"); for errors looks ugly.
1782
		BootstrapSkin::displayAlertBox("Comment not found.", "alert-error", "Error", true, false);
1783
		BootstrapSkin::displayInternalFooter();
1784
		die();
1785
	}
1786
	
1787
	// Unauthorized if user is not an admin or the user who made the comment being edited.
1788
	if (!User::getCurrent()->isAdmin() && !User::getCurrent()->isCheckuser() && $comment->getUser() != User::getCurrent()->getId()) {
1789
		BootstrapSkin::displayAccessDenied();
1790
		BootstrapSkin::displayInternalFooter();
1791
		die();
1792
	}
1793
	
1794
	// get[id] is safe by this point.
1795
	
1796
	if ($_SERVER['REQUEST_METHOD'] == 'POST') {
1797
		$database = gGetDb();
1798 View Code Duplication
		$database->transactionally(function() use ($database, $comment, $baseurl)
1799
		{
1800
            
1801
			$comment->setComment($_POST['newcomment']);
1802
			$comment->setVisibility($_POST['visibility']);
1803
        
1804
			$comment->save();
1805
        
1806
			Logger::editComment($database, $comment);
1807
        
1808
			Notification::commentEdited($comment);
1809
        
1810
			SessionAlert::success("Comment has been saved successfully");
1811
			header("Location: $baseurl/acc.php?action=zoom&id=" . $comment->getRequest());
1812
		});
1813
        
1814
		die();    
1815
	}
1816
	else {
1817
		$smarty->assign("comment", $comment);
1818
		$smarty->display("edit-comment.tpl");
1819
		BootstrapSkin::displayInternalFooter();
1820
		die();
1821
	}
1822
}
1823
elseif ($action == "sendtouser") {
1824
	global $baseurl;
1825
    
1826
	$database = gGetDb();
1827
    
1828
	$requestObject = Request::getById($_POST['id'], $database);
1829
	if ($requestObject == false) {
1830
		BootstrapSkin::displayAlertBox("Request invalid", "alert-error", "Could not find request", true, false);
1831
		BootstrapSkin::displayInternalFooter();
1832
		die();
1833
	}
1834
    
1835
	$request = $requestObject->getId();
1836
    
1837
	$user = User::getByUsername($_POST['user'], $database);
1838
	$curuser = User::getCurrent()->getUsername();
1839
    
1840
	if ($user == false) {
1841
		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);
1842
		BootstrapSkin::displayInternalFooter();
1843
		die();
1844
	}
1845
    
1846
	$database->transactionally(function() use ($database, $user, $request, $curuser)
1847
	{
1848
		$updateStatement = $database->prepare("UPDATE request SET reserved = :userid WHERE id = :request LIMIT 1;");
1849
		$updateStatement->bindValue(":userid", $user->getId());
1850
		$updateStatement->bindValue(":request", $request);
1851
		if (!$updateStatement->execute()) {
1852
			throw new TransactionException("Error updating reserved status of request.");   
1853
		}
1854
        
1855
		Logger::sendReservation($database, Request::getById($request, $database), $user);
1856
	});
1857
    
1858
	Notification::requestReservationSent($request, $user);
1859
	SessionAlert::success("Reservation sent successfully");
1860
	header("Location: $baseurl/acc.php?action=zoom&id=$request");
1861
}
1862
elseif ($action == "emailmgmt") {
1863
	global $smarty, $createdid, $availableRequestStates;
1864
    
1865
	/* New page for managing Emails, since I would rather not be handling editing
1866
	interface messages (such as the Sitenotice) and the new Emails in the same place. */
1867
	if (isset($_GET['create'])) {
1868
		if (!User::getCurrent()->isAdmin()) {
1869
			BootstrapSkin::displayAccessDenied();
1870
			BootstrapSkin::displayInternalFooter();
1871
			die();
1872
		}
1873
		if (isset($_POST['submit'])) {
1874
			$database = gGetDb();
1875
			$database->transactionally(function() use ($database)
1876
			{
1877
				global $baseurl;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
1878
                
1879
				$emailTemplate = new EmailTemplate();
1880
				$emailTemplate->setDatabase($database);
1881
            
1882
				$emailTemplate->setName($_POST['name']);
1883
				$emailTemplate->setText($_POST['text']);
1884
				$emailTemplate->setJsquestion($_POST['jsquestion']);
1885
				$emailTemplate->setDefaultAction($_POST['defaultaction']);
1886
				$emailTemplate->setActive(isset($_POST['active']));
1887
1888
				// Check if the entered name already exists (since these names are going to be used as the labels for buttons on the zoom page).
1889
				// getByName(...) returns false on no records found.
1890
				if (EmailTemplate::getByName($_POST['name'], $database)) {
1891
					throw new TransactionException("That Email template name is already being used. Please choose another.");
1892
				}
1893
			
1894
				$emailTemplate->save();
1895
                
1896
				Logger::createEmail($database, $emailTemplate);
1897
                
1898
				Notification::emailCreated($emailTemplate);
1899
                
1900
				SessionAlert::success("Email template has been saved successfully.");
1901
				header("Location: $baseurl/acc.php?action=emailmgmt");
1902
			});
1903
            
1904
			die();
1905
		}
1906
        
1907
		$smarty->assign('id', null);
1908
		$smarty->assign('createdid', $createdid);
1909
		$smarty->assign('requeststates', $availableRequestStates);
1910
		$smarty->assign('emailTemplate', new EmailTemplate());
1911
		$smarty->assign('emailmgmtpage', 'Create'); //Use a variable so we don't need two Smarty templates for creating and editing.
1912
		$smarty->display("email-management/edit.tpl");
1913
		BootstrapSkin::displayInternalFooter();
1914
		die();
1915
	}
1916
	if (isset($_GET['edit'])) {
1917
		global $createdid;
1918
        
1919
		$database = gGetDb();
1920
        
1921
		if (isset($_POST['submit'])) {
1922
			$emailTemplate = EmailTemplate::getById($_GET['edit'], $database);
1923
			// Allow the user to see the edit form (with read only fields) but not POST anything.
1924
			if (!User::getCurrent()->isAdmin()) {
1925
				BootstrapSkin::displayAccessDenied();
1926
				BootstrapSkin::displayInternalFooter();
1927
				die();
1928
			}
1929
            
1930
			$emailTemplate->setName($_POST['name']);
1931
			$emailTemplate->setText($_POST['text']);
1932
			$emailTemplate->setJsquestion($_POST['jsquestion']);
1933
			
1934
			if ($_GET['edit'] == $createdid) {
1935
				// Both checkboxes on the main created message should always be enabled.
1936
				$emailTemplate->setDefaultAction(EmailTemplate::CREATED);
1937
				$emailTemplate->setActive(1);
1938
				$emailTemplate->setPreloadOnly(0);
1939
			}
1940
			else {
1941
				$emailTemplate->setDefaultAction($_POST['defaultaction']);
1942
				$emailTemplate->setActive(isset($_POST['active']));
1943
				$emailTemplate->setPreloadOnly(isset($_POST['preloadonly']));
1944
			}
1945
				
1946
			// Check if the entered name already exists (since these names are going to be used as the labels for buttons on the zoom page).
1947
			$nameCheck = EmailTemplate::getByName($_POST['name'], gGetDb());
1948
			if ($nameCheck != false && $nameCheck->getId() != $_GET['edit']) {
1949
				BootstrapSkin::displayAlertBox("That Email template name is already being used. Please choose another.");
1950
				BootstrapSkin::displayInternalFooter();
1951
				die();
1952
			}
1953
1954
			$database->transactionally(function() use ($database, $emailTemplate)
1955
			{
1956
				$emailTemplate->save();
1957
                
1958
				Logger::editedEmail($database, $emailTemplate);
1959
            
1960
				global $baseurl;
1961
                
1962
				Notification::emailEdited($emailTemplate);
1963
				SessionAlert::success("Email template has been saved successfully.");
1964
				header("Location: $baseurl/acc.php?action=emailmgmt");
1965
			});
1966
            
1967
			die();
1968
		}
1969
        
1970
		$emailTemplate = EmailTemplate::getById($_GET['edit'], gGetDb());
1971
		$smarty->assign('id', $emailTemplate->getId());
1972
		$smarty->assign('emailTemplate', $emailTemplate);
1973
		$smarty->assign('createdid', $createdid);
1974
		$smarty->assign('requeststates', $availableRequestStates);
1975
		$smarty->assign('emailmgmtpage', 'Edit'); // Use a variable so we don't need two Smarty templates for creating and editing.
1976
		$smarty->display("email-management/edit.tpl");
1977
		BootstrapSkin::displayInternalFooter();
1978
		die();
1979
	}
1980
    
1981
	$query = "SELECT * FROM emailtemplate WHERE active = 1";
1982
	$statement = gGetDb()->prepare($query);
1983
	$statement->execute();
1984
	$rows = $statement->fetchAll(PDO::FETCH_CLASS, "EmailTemplate");
1985
	$smarty->assign('activeemails', $rows);
1986
        
1987
	$query = "SELECT * FROM emailtemplate WHERE active = 0";
1988
	$statement = gGetDb()->prepare($query);
1989
	$statement->execute();
1990
	$inactiverows = $statement->fetchAll(PDO::FETCH_CLASS, "EmailTemplate");
1991
	$smarty->assign('inactiveemails', $inactiverows);
1992
 
1993
	if (count($inactiverows) > 0) {
1994
		$smarty->assign('displayinactive', true);
1995
	}
1996
	else {
1997
		$smarty->assign('displayinactive', false);
1998
	}
1999
    
2000
	$smarty->display("email-management/main.tpl");
2001
	BootstrapSkin::displayInternalFooter();
2002
	die();
2003
}
2004
elseif ($action == "oauthdetach") {
2005
	if ($enforceOAuth) {
2006
		BootstrapSkin::displayAccessDenied();
2007
		BootstrapSkin::displayInternalFooter();
2008
		die();
2009
	}
2010
    
2011
	global $baseurl;
2012
        
2013
	$currentUser = User::getCurrent();
2014
	$currentUser->detachAccount();
2015
        
2016
	header("Location: {$baseurl}/acc.php?action=logout&nocheck=1");
2017
}
2018
elseif ($action == "oauthattach") {
2019
	$database = gGetDb();
2020 View Code Duplication
	$database->transactionally(function() use ($database)
2021
	{
2022
		try {
2023
			global $oauthConsumerToken, $oauthSecretToken, $oauthBaseUrl, $oauthBaseUrlInternal;
2024
            
2025
			$user = User::getCurrent();
2026
            
2027
			// Get a request token for OAuth
2028
			$util = new OAuthUtility($oauthConsumerToken, $oauthSecretToken, $oauthBaseUrl, $oauthBaseUrlInternal);
2029
			$requestToken = $util->getRequestToken();
2030
2031
			// save the request token for later
2032
			$user->setOAuthRequestToken($requestToken->key);
2033
			$user->setOAuthRequestSecret($requestToken->secret);
2034
			$user->save();
2035
        
2036
			$redirectUrl = $util->getAuthoriseUrl($requestToken);
2037
        
2038
			header("Location: {$redirectUrl}");
2039
        
2040
		}
2041
		catch (Exception $ex) {
2042
			throw new TransactionException($ex->getMessage(), "Connection to Wikipedia failed.", "alert-error", 0, $ex);
2043
		}
2044
	});
2045
}
2046
# If the action specified does not exist, goto the default page.
2047
else {
2048
	echo defaultpage();
2049
	BootstrapSkin::displayInternalFooter();
2050
	die();
2051
}
2052