Browse Source

Add more "check spam" notices

pjc 5 years ago
parent
commit
43c6b298d0

+ 33
- 21
classes/autoenable.class.php View File

1
-<?
1
+<?php
2
 
2
 
3
-class AutoEnable {
3
+class AutoEnable
4
+{
4
 
5
 
5
     // Constants for database values
6
     // Constants for database values
6
     const APPROVED = 1;
7
     const APPROVED = 1;
11
     const CACHE_KEY_NAME = 'num_enable_requests';
12
     const CACHE_KEY_NAME = 'num_enable_requests';
12
 
13
 
13
     // The default request rejected message
14
     // The default request rejected message
14
-    const REJECTED_MESSAGE = "Your request to re-enable your account has been rejected.<br>This may be because a request is already pending for your username, or because a recent request was denied.<br><br>You are encouraged to discuss this with staff by visiting %s on %s";
15
+    const REJECTED_MESSAGE = "Your request to re-enable your account has been rejected.<br /><br />This may be because a request is already pending for your username, or because a recent request was denied.<br /><br />You are encouraged to discuss this with staff by visiting %s on %s";
15
 
16
 
16
     // The default request received message
17
     // The default request received message
17
-    const RECEIVED_MESSAGE = "Your request to re-enable your account has been received. Most requests are responded to within minutes. Remember to check your spam.<br>If you do not receive an email after 48 hours have passed, please visit us on IRC for assistance.";
18
+    const RECEIVED_MESSAGE = "Your request to re-enable your account has been received. Most requests are responded to within minutes. Remember to check your spam.<br /><br />If you do not receive an email after 48 hours have passed, please visit us on IRC for assistance.";
18
 
19
 
19
     /**
20
     /**
20
      * Handle a new enable request
21
      * Handle a new enable request
23
      * @param string $Email The user's email address
24
      * @param string $Email The user's email address
24
      * @return string The output
25
      * @return string The output
25
      */
26
      */
26
-    public static function new_request($Username, $Email) {
27
+    public static function new_request($Username, $Email)
28
+    {
27
         if (empty($Username)) {
29
         if (empty($Username)) {
28
             header("Location: login.php");
30
             header("Location: login.php");
29
             die();
31
             die();
69
             // New disable activation request
71
             // New disable activation request
70
             $UserAgent = db_string($_SERVER['HTTP_USER_AGENT']);
72
             $UserAgent = db_string($_SERVER['HTTP_USER_AGENT']);
71
 
73
 
72
-            G::$DB->query("
74
+            G::$DB->query(
75
+                "
73
                 INSERT INTO users_enable_requests
76
                 INSERT INTO users_enable_requests
74
                 (UserID, Email, IP, UserAgent, Timestamp)
77
                 (UserID, Email, IP, UserAgent, Timestamp)
75
                 VALUES (?, ?, ?, ?, NOW())",
78
                 VALUES (?, ?, ?, ?, NOW())",
76
-                $UserID, Crypto::encrypt($Email), Crypto::encrypt($IP), $UserAgent);
79
+                $UserID,
80
+                Crypto::encrypt($Email),
81
+                Crypto::encrypt($IP),
82
+                $UserAgent
83
+            );
77
             $RequestID = G::$DB->inserted_id();
84
             $RequestID = G::$DB->inserted_id();
78
 
85
 
79
             // Cache the number of requests for the modbar
86
             // Cache the number of requests for the modbar
82
             $Output = self::RECEIVED_MESSAGE;
89
             $Output = self::RECEIVED_MESSAGE;
83
             Tools::update_user_notes($UserID, sqltime() . " - Enable request " . G::$DB->inserted_id() . " received from $IP\n\n");
90
             Tools::update_user_notes($UserID, sqltime() . " - Enable request " . G::$DB->inserted_id() . " received from $IP\n\n");
84
             if ($BanReason == 3) {
91
             if ($BanReason == 3) {
85
-              //self::handle_requests([$RequestID], self::APPROVED, "Automatically approved (inactivity)");
92
+                //self::handle_requests([$RequestID], self::APPROVED, "Automatically approved (inactivity)");
86
             }
93
             }
87
         }
94
         }
88
 
95
 
96
      * @param int $Status The status to mark the requests as
103
      * @param int $Status The status to mark the requests as
97
      * @param string $Comment The staff member comment
104
      * @param string $Comment The staff member comment
98
      */
105
      */
99
-    public static function handle_requests($IDs, $Status, $Comment) {
106
+    public static function handle_requests($IDs, $Status, $Comment)
107
+    {
100
         if ($Status != self::APPROVED && $Status != self::DENIED && $Status != self::DISCARDED) {
108
         if ($Status != self::APPROVED && $Status != self::DENIED && $Status != self::DISCARDED) {
101
             error(404);
109
             error(404);
102
         }
110
         }
123
         if ($Status != self::DISCARDED) {
131
         if ($Status != self::DISCARDED) {
124
             // Prepare email
132
             // Prepare email
125
             require_once(SERVER_ROOT . '/classes/templates.class.php');
133
             require_once(SERVER_ROOT . '/classes/templates.class.php');
126
-            $TPL = NEW TEMPLATE;
134
+            $TPL = new TEMPLATE;
127
             if ($Status == self::APPROVED) {
135
             if ($Status == self::APPROVED) {
128
                 $TPL->open(SERVER_ROOT . '/templates/enable_request_accepted.tpl');
136
                 $TPL->open(SERVER_ROOT . '/templates/enable_request_accepted.tpl');
129
                 $TPL->set('SITE_DOMAIN', SITE_DOMAIN);
137
                 $TPL->set('SITE_DOMAIN', SITE_DOMAIN);
168
             FROM users_main
176
             FROM users_main
169
             WHERE ID = ?", $StaffID);
177
             WHERE ID = ?", $StaffID);
170
         if (G::$DB->has_results()) {
178
         if (G::$DB->has_results()) {
171
-          list($StaffUser) = G::$DB->next_record();
179
+            list($StaffUser) = G::$DB->next_record();
172
         } else {
180
         } else {
173
-          $StaffUser = "System";
174
-          $StaffID = 0;
181
+            $StaffUser = "System";
182
+            $StaffID = 0;
175
         }
183
         }
176
 
184
 
177
         foreach ($UserInfo as $User) {
185
         foreach ($UserInfo as $User) {
196
      *
204
      *
197
      * @param int $ID The request ID
205
      * @param int $ID The request ID
198
      */
206
      */
199
-    public static function unresolve_request($ID) {
207
+    public static function unresolve_request($ID)
208
+    {
200
         $ID = (int) $ID;
209
         $ID = (int) $ID;
201
 
210
 
202
         if (empty($ID)) {
211
         if (empty($ID)) {
235
      * @param int $Outcome The outcome integer
244
      * @param int $Outcome The outcome integer
236
      * @return string The formatted output string
245
      * @return string The formatted output string
237
      */
246
      */
238
-    public static function get_outcome_string($Outcome) {
247
+    public static function get_outcome_string($Outcome)
248
+    {
239
         if ($Outcome == self::APPROVED) {
249
         if ($Outcome == self::APPROVED) {
240
             $String = "Approved";
250
             $String = "Approved";
241
-        } else if ($Outcome == self::DENIED) {
251
+        } elseif ($Outcome == self::DENIED) {
242
             $String = "Rejected";
252
             $String = "Rejected";
243
-        } else if ($Outcome == self::DISCARDED) {
253
+        } elseif ($Outcome == self::DISCARDED) {
244
             $String = "Discarded";
254
             $String = "Discarded";
245
         } else {
255
         } else {
246
             $String = "---";
256
             $String = "---";
255
      * @param string $Token The token
265
      * @param string $Token The token
256
      * @return string The error output, or an empty string
266
      * @return string The error output, or an empty string
257
      */
267
      */
258
-    public static function handle_token($Token) {
268
+    public static function handle_token($Token)
269
+    {
259
         $Token = db_string($Token);
270
         $Token = db_string($Token);
260
         G::$DB->query("
271
         G::$DB->query("
261
             SELECT uer.UserID, uer.HandledTimestamp, um.torrent_pass, um.Visible, um.IP
272
             SELECT uer.UserID, uer.HandledTimestamp, um.torrent_pass, um.Visible, um.IP
299
      * @param boolean $Checked Should checked requests be included?
310
      * @param boolean $Checked Should checked requests be included?
300
      * @return array The WHERE conditions for the query
311
      * @return array The WHERE conditions for the query
301
      */
312
      */
302
-    public static function build_search_query($Username, $IP, $SubmittedBetween, $SubmittedTimestamp1, $SubmittedTimestamp2, $HandledUsername, $HandledBetween, $HandledTimestamp1, $HandledTimestamp2, $OutcomeSearch, $Checked) {
313
+    public static function build_search_query($Username, $IP, $SubmittedBetween, $SubmittedTimestamp1, $SubmittedTimestamp2, $HandledUsername, $HandledBetween, $HandledTimestamp1, $HandledTimestamp2, $OutcomeSearch, $Checked)
314
+    {
303
         $Where = [];
315
         $Where = [];
304
 
316
 
305
         if (!empty($Username)) {
317
         if (!empty($Username)) {
312
         }
324
         }
313
 
325
 
314
         if (!empty($SubmittedTimestamp1)) {
326
         if (!empty($SubmittedTimestamp1)) {
315
-            switch($SubmittedBetween) {
327
+            switch ($SubmittedBetween) {
316
                 case 'on':
328
                 case 'on':
317
                     $Where[] = "DATE(uer.Timestamp) = DATE('$SubmittedTimestamp1')";
329
                     $Where[] = "DATE(uer.Timestamp) = DATE('$SubmittedTimestamp1')";
318
                     break;
330
                     break;
333
         }
345
         }
334
 
346
 
335
         if (!empty($HandledTimestamp1)) {
347
         if (!empty($HandledTimestamp1)) {
336
-            switch($HandledBetween) {
348
+            switch ($HandledBetween) {
337
                 case 'on':
349
                 case 'on':
338
                     $Where[] = "DATE(uer.HandledTimestamp) = DATE('$HandledTimestamp1')";
350
                     $Where[] = "DATE(uer.HandledTimestamp) = DATE('$HandledTimestamp1')";
339
                     break;
351
                     break;

+ 2
- 0
classes/rules.class.php View File

109
 
109
 
110
   <li>Please discuss site news in the corresponding Announcements thread instead of making a new General thread.
110
   <li>Please discuss site news in the corresponding Announcements thread instead of making a new General thread.
111
     Discussing science-related news in General is highly encouraged, but discussing political news is much less so.
111
     Discussing science-related news in General is highly encouraged, but discussing political news is much less so.
112
+    But don't self-censor, e.g., you can discuss the political and economic factors of the 2019-nCoV outbreak,
113
+    but you can't start a thread about trade deals and hope to steer it toward biology.
112
     Thank you.</li>
114
     Thank you.</li>
113
 
115
 
114
   <li>No advertising, referrals, affiliate links, cryptocurrency pumps, or calls to action that involve using a
116
   <li>No advertising, referrals, affiliate links, cryptocurrency pumps, or calls to action that involve using a

+ 63
- 46
sections/donate/donate.php View File

17
 ?>
17
 ?>
18
 
18
 
19
 <div class="thin">
19
 <div class="thin">
20
-  <span class="donation_info_title"><?= SITE_NAME ?> budget breakdown</span>
20
+  <span class="donation_info_title"><?= SITE_NAME ?> budget
21
+    breakdown</span>
21
   <div class="box pad donation_info">
22
   <div class="box pad donation_info">
22
-  <p>
23
-      <?= SITE_NAME ?> has no advertisements, is not sponsored, and provides its services free of charge.
23
+    <p>
24
+      <?= SITE_NAME ?> has no advertisements, is not sponsored, and
25
+      provides its services free of charge.
24
       For these reasons, its main income source is voluntary user donations.
26
       For these reasons, its main income source is voluntary user donations.
25
-      Supporting <?= SITE_NAME ?> is and will always remain voluntary.
27
+      Supporting <?= SITE_NAME ?> is and will always remain
28
+      voluntary.
26
       If you're financially able, please help pay its bills by donating.
29
       If you're financially able, please help pay its bills by donating.
27
       We use the donations to cover the costs of running the site, tracker, and IRC network.
30
       We use the donations to cover the costs of running the site, tracker, and IRC network.
28
     </p>
31
     </p>
30
     <p>
33
     <p>
31
       No staff member or other individual responsible for the site's operation personally profits from user donations.
34
       No staff member or other individual responsible for the site's operation personally profits from user donations.
32
       As a donor, your financial support is exclusively applied to operating costs.
35
       As a donor, your financial support is exclusively applied to operating costs.
33
-      By donating to <?= SITE_NAME ?>, you're helping to defray the recurring costs of necessary information services.
36
+      By donating to <?= SITE_NAME ?>, you're helping to defray the
37
+      recurring costs of necessary information services.
34
     </p>
38
     </p>
35
 
39
 
36
     <p>
40
     <p>
41
     </p>
45
     </p>
42
 
46
 
43
     <ul>
47
     <ul>
44
-        <li><strong>Tracker Server.</strong> We currently use one budget VPS at 2.50€ per month, and can add more at the same price as needed.</li>
45
-        <li><strong>Seedbox Server.</strong> A dedicated seedbox in Europe to supplement my home servers in North America is forthcoming. It's not expected to exceed $20 per month.</li>
46
-        <li><strong>Domain Name.</strong> The site domain name costs $15 per year. The SSL certificate is gratis.</li>
47
-        <li><strong>Parent Company.</strong> Because I'm handling personal information such as email and IP addresses, and soliciting donations from the public, legal protection is prudent. An LLC is forthcoming and not expected to exceed $75 per year.</li>
48
-      </ul>
48
+      <li><strong>Tracker Server.</strong> We currently use one budget VPS at 2.50€ per month, and can add more at the
49
+        same price as needed.</li>
50
+      <li><strong>Seedbox Server.</strong> A dedicated seedbox in Europe to supplement my home servers in North America
51
+        is forthcoming. It's not expected to exceed $20 per month.</li>
52
+      <li><strong>Domain Name.</strong> The site domain name costs $15 per year. The SSL certificate is gratis.</li>
53
+      <li><strong>Parent Company.</strong> Because I'm handling personal information such as email and IP addresses, and
54
+        soliciting donations from the public, legal protection is prudent. An LLC is forthcoming and not expected to
55
+        exceed $75 per year.</li>
56
+    </ul>
49
   </div>
57
   </div>
50
 
58
 
51
   <span class="donation_info_title">How to donate to <?= SITE_NAME ?></span>
59
   <span class="donation_info_title">How to donate to <?= SITE_NAME ?></span>
52
   <div class="box pad donation_info">
60
   <div class="box pad donation_info">
53
     <p>
61
     <p>
54
-      <?= SITE_NAME ?> accepts donations on a tactful array of platforms.
62
+      <?= SITE_NAME ?> accepts donations on a tactful array of
63
+      platforms.
55
       We also accept <strong>tax-deductible donations</strong> on behalf of the
64
       We also accept <strong>tax-deductible donations</strong> on behalf of the
56
       <a href="https://www.boslab.org/donate" target="_blank">Boston Open Science Laboratory (BosLab)</a>,
65
       <a href="https://www.boslab.org/donate" target="_blank">Boston Open Science Laboratory (BosLab)</a>,
57
       a registered 501c3.
66
       a registered 501c3.
58
       Please use the memo field on BosLab's PayPal form to credit your <?= SITE_NAME ?> account.
67
       Please use the memo field on BosLab's PayPal form to credit your <?= SITE_NAME ?> account.
59
-      <strong>From: your username on <?= SITE_NAME ?>'s behalf, CC: ohm at biotorrents dot de.</strong>
68
+      <strong>From: your username on <?= SITE_NAME ?>'s behalf, CC:
69
+        ohm at biotorrents dot de.</strong>
60
     </p>
70
     </p>
61
 
71
 
62
     <p>
72
     <p>
63
-      Unlike affiliate donations to BosLab, where the funds are beyond my control, direct donations are used exclusively for <?= SITE_NAME ?>'s operating costs.
64
-      Please see <a href="https://www.patreon.com/biotorrents" target="_blank"><?= SITE_NAME ?>'s Patreon</a> for a detailed overview of funding goals.
73
+      Unlike affiliate donations to BosLab, where the funds are beyond my control, direct donations are used exclusively
74
+      for <?= SITE_NAME ?>'s operating costs.
75
+      Please see <a href="https://www.patreon.com/biotorrents" target="_blank"><?= SITE_NAME ?>'s Patreon</a> for a detailed overview of funding
76
+      goals.
65
       There are some benefits to donating that culmulate with each tier pledged.
77
       There are some benefits to donating that culmulate with each tier pledged.
66
       Each tier's awards include those already listed.
78
       Each tier's awards include those already listed.
67
     </p>
79
     </p>
68
 
80
 
69
     <p style="margin: 2em 0;">
81
     <p style="margin: 2em 0;">
70
-    <a href="https://www.patreon.com/bePatron?u=27142321" data-patreon-widget-type="become-patron-button">Become a Patron!</a><script async src="https://c6.patreon.com/becomePatronButton.bundle.js"></script>
82
+      <a href="https://www.patreon.com/bePatron?u=27142321" data-patreon-widget-type="become-patron-button">Become a
83
+        Patron!</a>
84
+      <script async src="https://c6.patreon.com/becomePatronButton.bundle.js"></script>
71
     </p>
85
     </p>
72
 
86
 
73
-      <ul>
74
-        <li><strong>Bronze.</strong> A donor badge and forum access for your user account on the BioTorrents.de website
75
-        </li>
76
-        <li><strong>Silver.</strong> Unlimited API calls to the BioTorrents.de database</li>
77
-        <li><strong>Gold.</strong> Monthly Skype calls to discuss wetlab and software ideas.
78
-          My expertise includes fungal biotechnology, nonprofit administration, and LEMP+ development</li>
79
-        <li><strong>Sponsor a Seedbox.</strong> Shell access to, and share ratio credit from, a seedbox that I manage on
80
-          your behalf.
81
-          Please understand that network services beyond the scope of seedbox administration should be negotiated
82
-          separately</li>
83
-      </ul>
87
+    <ul>
88
+      <li><strong>Bronze.</strong> A donor badge and forum access for your user account on the BioTorrents.de website
89
+      </li>
90
+      <li><strong>Silver.</strong> Unlimited API calls to the BioTorrents.de database</li>
91
+      <li><strong>Gold.</strong> Monthly Skype calls to discuss wetlab and software ideas.
92
+        My expertise includes fungal biotechnology, nonprofit administration, and LEMP+ development</li>
93
+      <!--
94
+        <li><strong>Sponsor a Seedbox.</strong> Shell access to, and share ratio credit from, a seedbox that I manage on your behalf.
95
+          Please understand that network services beyond the scope of seedbox administration should be negotiated separately</li>
96
+        -->
97
+    </ul>
84
 
98
 
85
     <p>
99
     <p>
86
-      I also accept private donations of cash and cash equivalents, including <strong>Bitcoin</strong> and other cryptocurrencies.
87
-      Besides gift transactions sent to my personal <strong>PayPal</strong> account, I'll also accept <strong>USPS money orders</strong> in the mail.
100
+      I also accept private donations of cash and cash equivalents, including <strong>Bitcoin</strong> and other
101
+      cryptocurrencies.
102
+      Besides gift transactions sent to my personal <strong>PayPal</strong> account, I'll also accept <strong>USPS money
103
+        orders</strong> in the mail.
88
       I can generate unique cryptocurrency addresses for donations in Bitcoin, Litecoin, Curecoin, and Namecoin.
104
       I can generate unique cryptocurrency addresses for donations in Bitcoin, Litecoin, Curecoin, and Namecoin.
89
-      Please use <a href="https://pgp.mit.edu/pks/lookup?op=get&search=0x760EBED7CFE266D7" target="_blank">GPG key 760EBED7CFE266D7</a> if you desire.
105
+      Please use <a href="https://pgp.mit.edu/pks/lookup?op=get&search=0x760EBED7CFE266D7" target="_blank">GPG key
106
+        760EBED7CFE266D7</a> if you desire.
90
     </p>
107
     </p>
91
   </div>
108
   </div>
92
 
109
 
93
   <span class="donation_info_title">What donating means for your account</span>
110
   <span class="donation_info_title">What donating means for your account</span>
94
   <div class="box pad donation_info">
111
   <div class="box pad donation_info">
95
-  <p>
96
-    Please remember that when you make a donation, you aren't "purchasing" Donor Ranks, invites, or any <?= SITE_NAME ?>-specific benefit.
97
-    When donating, you're helping <?= SITE_NAME ?> pay its bills, and your donation should be made in this spirit.
98
-    The <?= SITE_NAME ?> staff does its best to recognize our financial supporters in a fair and fun way,
99
-    but all donor perks are subject to change or cancellation at any time, without notice.
100
-  </p>
101
-
102
-  <p>
103
-    Any donation or contribution option listed above gives you the opportunity to receive Donor Points.
104
-    Donor Points are awarded at a rate of one point per transaction, regardless of the amount.
105
-    After acquiring your first Donor Point, your account will unlock Donor Rank #1.
106
-    This rank will last forever, and you'll receive the below perks when you unlock it.
107
-  </p>
112
+    <p>
113
+      Please remember that when you make a donation, you aren't "purchasing" Donor Ranks, invites, or any <?= SITE_NAME ?>-specific benefit.
114
+      When donating, you're helping <?= SITE_NAME ?> pay its bills,
115
+      and your donation should be made in this spirit.
116
+      The <?= SITE_NAME ?> staff does its best to recognize our
117
+      financial supporters in a fair and fun way,
118
+      but all donor perks are subject to change or cancellation at any time, without notice.
119
+    </p>
120
+
121
+    <p>
122
+      Any donation or contribution option listed above gives you the opportunity to receive Donor Points.
123
+      Donor Points are awarded at a rate of one point per transaction, regardless of the amount.
124
+      After acquiring your first Donor Point, your account will unlock Donor Rank #1.
125
+      This rank will last forever, and you'll receive the below perks when you unlock it.
126
+    </p>
108
 
127
 
109
     <ul>
128
     <ul>
110
       <li>Our eternal love, as represented by the heart you get next to your name</li>
129
       <li>Our eternal love, as represented by the heart you get next to your name</li>
117
       <li>A warm, fuzzy feeling</li>
136
       <li>A warm, fuzzy feeling</li>
118
     </ul>
137
     </ul>
119
 
138
 
120
-<p>What you won't receive for donating:</P.
121
-
122
-    <ul>
139
+    <p>What you won't receive for donating:</P. <ul>
123
       <li>Immunity from the rules</li>
140
       <li>Immunity from the rules</li>
124
       <li>Additional upload credit</li>
141
       <li>Additional upload credit</li>
125
-    </ul>
142
+      </ul>
126
   </div>
143
   </div>
127
 </div>
144
 </div>
128
 <!-- END Donate -->
145
 <!-- END Donate -->

+ 363
- 360
sections/login/index.php View File

6
 
6
 
7
 // Allow users to reset their password while logged in
7
 // Allow users to reset their password while logged in
8
 if (!empty($LoggedUser['ID']) && $_REQUEST['act'] != 'recover') {
8
 if (!empty($LoggedUser['ID']) && $_REQUEST['act'] != 'recover') {
9
-  header('Location: index.php');
10
-  die();
9
+    header('Location: index.php');
10
+    die();
11
 }
11
 }
12
 
12
 
13
 if (BLOCK_OPERA_MINI && isset($_SERVER['HTTP_X_OPERAMINI_PHONE'])) {
13
 if (BLOCK_OPERA_MINI && isset($_SERVER['HTTP_X_OPERAMINI_PHONE'])) {
14
-  error('Opera Mini is banned. Please use another browser.');
14
+    error('Opera Mini is banned. Please use another browser.');
15
 }
15
 }
16
 
16
 
17
 // Check if IP is banned
17
 // Check if IP is banned
18
 if (Tools::site_ban_ip($_SERVER['REMOTE_ADDR'])) {
18
 if (Tools::site_ban_ip($_SERVER['REMOTE_ADDR'])) {
19
-  error('Your IP address has been banned.');
19
+    error('Your IP address has been banned.');
20
 }
20
 }
21
 
21
 
22
 require_once SERVER_ROOT.'/classes/twofa.class.php';
22
 require_once SERVER_ROOT.'/classes/twofa.class.php';
27
 $TwoFA = new TwoFactorAuth(SITE_NAME);
27
 $TwoFA = new TwoFactorAuth(SITE_NAME);
28
 $U2F = new u2f\U2F('https://'.SITE_DOMAIN);
28
 $U2F = new u2f\U2F('https://'.SITE_DOMAIN);
29
 
29
 
30
+# todo: Test strict equality very gently here
30
 if (array_key_exists('action', $_GET) && $_GET['action'] == 'disabled') {
31
 if (array_key_exists('action', $_GET) && $_GET['action'] == 'disabled') {
31
-  require('disabled.php');
32
-  die();
32
+    require('disabled.php');
33
+    die();
33
 }
34
 }
34
 
35
 
35
 if (isset($_REQUEST['act']) && $_REQUEST['act'] == 'recover') {
36
 if (isset($_REQUEST['act']) && $_REQUEST['act'] == 'recover') {
36
-  // Recover password
37
-  if (!empty($_REQUEST['key'])) {
38
-    // User has entered a new password, use step 2
39
-    $DB->query("
40
-      SELECT
41
-        m.ID,
42
-        m.Email,
43
-        m.ipcc,
44
-        i.ResetExpires
45
-      FROM users_main AS m
46
-        INNER JOIN users_info AS i ON i.UserID = m.ID
47
-      WHERE i.ResetKey = ?
48
-        AND i.ResetKey != ''", $_REQUEST['key']);
49
-    list($UserID, $Email, $Country, $Expires) = $DB->next_record();
50
-
51
-    if (!apcu_exists('DBKEY')) {
52
-      error('Database not fully decrypted. Please wait for staff to fix this and try again later');
53
-    }
54
-
55
-    $Email = Crypto::decrypt($Email);
56
-
57
-    if ($UserID && strtotime($Expires) > time()) {
58
-      // If the user has requested a password change, and his key has not expired
59
-      $Validate->SetFields('password', '1', 'regex', 'You entered an invalid password. Any password at least 6 characters long is accepted, but a strong password is 8 characters or longer, contains at least 1 lowercase and uppercase letter, contains at least a number or symbol', array('regex' => '/(?=^.{6,}$).*$/'));
60
-      $Validate->SetFields('verifypassword', '1', 'compare', 'Your passwords did not match.', array('comparefield' => 'password'));
61
-
62
-      if (!empty($_REQUEST['password'])) {
63
-        // If the user has entered a password.
64
-        // If the user has not entered a password, $PassWasReset is not set to 1, and the success message is not shown
65
-        $Err = $Validate->ValidateForm($_REQUEST);
66
-        if ($Err == '') {
67
-          // Form validates without error, set new secret and password.
68
-          $DB->query("
69
-            UPDATE
70
-              users_main AS m,
71
-              users_info AS i
72
-            SET
73
-              m.PassHash = ?,
74
-              i.ResetKey = '',
75
-              m.LastLogin = NOW(),
76
-              i.ResetExpires = NULL
77
-            WHERE m.ID = ?
78
-              AND i.UserID = m.ID", Users::make_sec_hash($_REQUEST['password']), $UserID);
79
-          $DB->query("
80
-            INSERT INTO users_history_passwords
81
-              (UserID, ChangerIP, ChangeTime)
82
-            VALUES
83
-              (?, ?, NOW())", $UserID, Crypto::encrypt($_SERVER['REMOTE_ADDR']));
84
-          $PassWasReset = true;
85
-          $LoggedUser['ID'] = $UserID; // Set $LoggedUser['ID'] for logout_all_sessions() to work
86
-          logout_all_sessions();
87
-
37
+    // Recover password
38
+    if (!empty($_REQUEST['key'])) {
39
+        // User has entered a new password, use step 2
40
+        $DB->query("
41
+        SELECT
42
+          m.ID,
43
+          m.Email,
44
+          m.ipcc,
45
+          i.ResetExpires
46
+        FROM users_main AS m
47
+          INNER JOIN users_info AS i ON i.UserID = m.ID
48
+          WHERE i.ResetKey = ?
49
+          AND i.ResetKey != ''", $_REQUEST['key']);
50
+        list($UserID, $Email, $Country, $Expires) = $DB->next_record();
51
+
52
+        if (!apcu_exists('DBKEY')) {
53
+            error('Database not fully decrypted. Please wait for staff to fix this and try again later');
88
         }
54
         }
89
-      }
90
-
91
-      // Either a form asking for them to enter the password
92
-      // Or a success message if $PassWasReset is 1
93
-      require('recover_step2.php');
94
 
55
 
95
-    } else {
96
-      // Either his key has expired, or he hasn't requested a pass change at all
97
-      if (strtotime($Expires) < time() && $UserID) {
98
-        // If his key has expired, clear all the reset information
99
-        $DB->query("
100
-          UPDATE users_info
101
-          SET ResetKey = '',
102
-            ResetExpires = NULL
103
-          WHERE UserID = ?", $UserID);
104
-        $_SESSION['reseterr'] = 'The link you were given has expired.'; // Error message to display on form
105
-      }
106
-      // Show him the first form (enter email address)
107
-      header('Location: login.php?act=recover');
108
-    }
56
+        $Email = Crypto::decrypt($Email);
109
 
57
 
110
-  } // End step 2
58
+        if ($UserID && strtotime($Expires) > time()) {
59
+            // If the user has requested a password change, and his key has not expired
60
+            $Validate->SetFields('password', '1', 'regex', 'You entered an invalid password. Any password at least 6 characters long is accepted, but a strong password is 8 characters or longer, contains at least 1 lowercase and uppercase letter, contains at least a number or symbol', array('regex' => '/(?=^.{6,}$).*$/'));
61
+            $Validate->SetFields('verifypassword', '1', 'compare', 'Your passwords did not match.', array('comparefield' => 'password'));
62
+
63
+            if (!empty($_REQUEST['password'])) {
64
+                // If the user has entered a password.
65
+                // If the user has not entered a password, $PassWasReset is not set to 1, and the success message is not shown
66
+                $Err = $Validate->ValidateForm($_REQUEST);
67
+                if ($Err == '') {
68
+                    // Form validates without error, set new secret and password.
69
+                    $DB->query("
70
+                    UPDATE
71
+                      users_main AS m,
72
+                      users_info AS i
73
+                    SET
74
+                      m.PassHash = ?,
75
+                      i.ResetKey = '',
76
+                      m.LastLogin = NOW(),
77
+                      i.ResetExpires = NULL
78
+                      WHERE m.ID = ?
79
+                      AND i.UserID = m.ID", Users::make_sec_hash($_REQUEST['password']), $UserID);
80
+                    $DB->query("
81
+                    INSERT INTO users_history_passwords
82
+                      (UserID, ChangerIP, ChangeTime)
83
+                    VALUES
84
+                      (?, ?, NOW())", $UserID, Crypto::encrypt($_SERVER['REMOTE_ADDR']));
85
+                    $PassWasReset = true;
86
+                    $LoggedUser['ID'] = $UserID; // Set $LoggedUser['ID'] for logout_all_sessions() to work
87
+                    logout_all_sessions();
88
+                }
89
+            }
111
 
90
 
112
-  // User has not clicked the link in his email, use step 1
113
-  else {
114
-    $Validate->SetFields('email', '1', 'email', 'You entered an invalid email address.');
91
+            // Either a form asking for them to enter the password
92
+            // Or a success message if $PassWasReset is 1
93
+            require('recover_step2.php');
94
+        } else {
95
+            // Either his key has expired, or he hasn't requested a pass change at all
96
+            if (strtotime($Expires) < time() && $UserID) {
97
+                // If his key has expired, clear all the reset information
98
+                $DB->query("
99
+                UPDATE users_info
100
+                SET ResetKey = '',
101
+                  ResetExpires = NULL
102
+                  WHERE UserID = ?", $UserID);
103
+                $_SESSION['reseterr'] = 'The link you were given has expired.'; // Error message to display on form
104
+            }
105
+            // Show him the first form (enter email address)
106
+            header('Location: login.php?act=recover');
107
+        }
108
+    } // End step 2
115
 
109
 
116
-    if (!empty($_REQUEST['email'])) {
117
-      // User has entered email and submitted form
118
-      $Err = $Validate->ValidateForm($_REQUEST);
119
-      if (!apcu_exists('DBKEY')) {
120
-        $Err = 'Database not fully decrypted. Please wait for staff to fix this and try again.';
121
-      }
110
+    // User has not clicked the link in his email, use step 1
111
+    else {
112
+        $Validate->SetFields('email', '1', 'email', 'You entered an invalid email address');
122
 
113
 
123
-      if (!$Err) {
124
-        // Form validates correctly
125
-        $DB->query("
126
-          SELECT
127
-            Email
128
-          FROM users_main");
129
-        while(list($EncEmail) = $DB->next_record()) {
130
-          if (strtolower($_REQUEST['email']) == strtolower(Crypto::decrypt($EncEmail))) {
131
-            break; // $EncEmail is now the encrypted form of the given email from the database
132
-          }
133
-        }
114
+        if (!empty($_REQUEST['email'])) {
115
+            // User has entered email and submitted form
116
+            $Err = $Validate->ValidateForm($_REQUEST);
117
+            if (!apcu_exists('DBKEY')) {
118
+                $Err = 'Database not fully decrypted. Please wait for staff to fix this and try again';
119
+            }
134
 
120
 
135
-        $DB->query("
136
-          SELECT
137
-            ID,
138
-            Username,
139
-            Email
140
-          FROM users_main
141
-          WHERE Email = ?", $EncEmail);
142
-        list($UserID, $Username, $Email) = $DB->next_record();
143
-        $Email = Crypto::decrypt($Email);
121
+            if (!$Err) {
122
+                // Form validates correctly
123
+                $DB->query("
124
+                SELECT
125
+                  Email
126
+                FROM users_main");
127
+                while (list($EncEmail) = $DB->next_record()) {
128
+                    if (strtolower($_REQUEST['email']) == strtolower(Crypto::decrypt($EncEmail))) {
129
+                        break; // $EncEmail is now the encrypted form of the given email from the database
130
+                    }
131
+                }
144
 
132
 
145
-        if ($UserID) {
146
-          // Email exists in the database
147
-          // Set ResetKey, send out email, and set $Sent to 1 to show success page
148
-          Users::reset_password($UserID, $Username, $Email);
149
-
150
-          $Sent = 1; // If $Sent is 1, recover_step1.php displays a success message
151
-
152
-          //Log out all of the users current sessions
153
-          $Cache->delete_value("user_info_$UserID");
154
-          $Cache->delete_value("user_info_heavy_$UserID");
155
-          $Cache->delete_value("user_stats_$UserID");
156
-          $Cache->delete_value("enabled_$UserID");
157
-
158
-          $DB->query("
159
-            SELECT SessionID
160
-            FROM users_sessions
161
-            WHERE UserID = ?", $UserID);
162
-          while (list($SessionID) = $DB->next_record()) {
163
-            $Cache->delete_value("session_$UserID"."_$SessionID");
164
-          }
165
-          $DB->query("
166
-            UPDATE users_sessions
167
-            SET Active = 0
168
-            WHERE UserID = ?
169
-              AND Active = 1", $UserID);
170
-        } else {
171
-          $Err = 'There is no user with that email address.';
133
+                $DB->query("
134
+                SELECT
135
+                  ID,
136
+                  Username,
137
+                  Email
138
+                FROM users_main
139
+                  WHERE Email = ?", $EncEmail);
140
+                list($UserID, $Username, $Email) = $DB->next_record();
141
+                $Email = Crypto::decrypt($Email);
142
+
143
+                if ($UserID) {
144
+                    // Email exists in the database
145
+                    // Set ResetKey, send out email, and set $Sent to 1 to show success page
146
+                    Users::reset_password($UserID, $Username, $Email);
147
+
148
+                    $Sent = 1; // If $Sent is 1, recover_step1.php displays a success message
149
+
150
+                    //Log out all of the users current sessions
151
+                    $Cache->delete_value("user_info_$UserID");
152
+                    $Cache->delete_value("user_info_heavy_$UserID");
153
+                    $Cache->delete_value("user_stats_$UserID");
154
+                    $Cache->delete_value("enabled_$UserID");
155
+
156
+                    $DB->query("
157
+                    SELECT SessionID
158
+                    FROM users_sessions
159
+                      WHERE UserID = ?", $UserID);
160
+                    while (list($SessionID) = $DB->next_record()) {
161
+                        $Cache->delete_value("session_$UserID"."_$SessionID");
162
+                    }
163
+                    $DB->query("
164
+                    UPDATE users_sessions
165
+                    SET Active = 0
166
+                      WHERE UserID = ?
167
+                      AND Active = 1", $UserID);
168
+                } else {
169
+                    $Err = 'There is no user with that email address';
170
+                }
171
+            }
172
+        } elseif (!empty($_SESSION['reseterr'])) {
173
+            // User has not entered email address, and there is an error set in session data
174
+            // This is typically because their key has expired.
175
+            // Stick the error into $Err so recover_step1.php can take care of it
176
+            $Err = $_SESSION['reseterr'];
177
+            unset($_SESSION['reseterr']);
172
         }
178
         }
173
-      }
174
-
175
-    } elseif (!empty($_SESSION['reseterr'])) {
176
-      // User has not entered email address, and there is an error set in session data
177
-      // This is typically because their key has expired.
178
-      // Stick the error into $Err so recover_step1.php can take care of it
179
-      $Err = $_SESSION['reseterr'];
180
-      unset($_SESSION['reseterr']);
181
-    }
182
-
183
-    // Either a form for the user's email address, or a success message
184
-    require('recover_step1.php');
185
-  }
186
 
179
 
180
+        // Either a form for the user's email address, or a success message
181
+        require('recover_step1.php');
182
+    }
187
 } // End password recovery
183
 } // End password recovery
188
 
184
 
189
-else if (isset($_REQUEST['act']) && $_REQUEST['act'] == 'newlocation') {
190
-  if (isset($_REQUEST['key'])) {
191
-    if ($ASNCache = $Cache->get_value('new_location_'.$_REQUEST['key'])) {
192
-      $Cache->cache_value('new_location_'.$ASNCache['UserID'].'_'.$ASNCache['ASN'], true);
193
-      require('newlocation.php');
194
-      die();
185
+elseif (isset($_REQUEST['act']) && $_REQUEST['act'] == 'newlocation') {
186
+    if (isset($_REQUEST['key'])) {
187
+        if ($ASNCache = $Cache->get_value('new_location_'.$_REQUEST['key'])) {
188
+            $Cache->cache_value('new_location_'.$ASNCache['UserID'].'_'.$ASNCache['ASN'], true);
189
+            require('newlocation.php');
190
+            die();
191
+        } else {
192
+            error(403);
193
+        }
195
     } else {
194
     } else {
196
-      error(403);
195
+        error(403);
197
     }
196
     }
198
-  } else {
199
-    error(403);
200
-  }
201
 } // End new location
197
 } // End new location
202
 
198
 
203
 // Normal login
199
 // Normal login
204
 else {
200
 else {
205
-  $Validate->SetFields('username', true, 'regex', 'You did not enter a valid username.', array('regex' => USERNAME_REGEX));
206
-  $Validate->SetFields('password', '1', 'string', 'You entered an invalid password.', array('minlength' => '6', 'maxlength' => '307200'));
207
-
208
-  list($Attempts, $Banned) = $Cache->get_value('login_attempts_'.db_string($_SERVER['REMOTE_ADDR']));
209
-
210
-  // Function to log a user's login attempt
211
-  function log_attempt() {
212
-    global $Cache, $Attempts;
213
-    $Attempts = ($Attempts ?? 0) + 1;
214
-    $Cache->cache_value('login_attempts_'.db_string($_SERVER['REMOTE_ADDR']), array($Attempts, ($Attempts > 5)), 60*60*$Attempts);
215
-    $AllAttempts = $Cache->get_value('login_attempts');
216
-    $AllAttempts[$_SERVER['REMOTE_ADDR']] = time()+(60*60*$Attempts);
217
-    foreach($AllAttempts as $IP => $Time) {
218
-      if ($Time < time()) { unset($AllAttempts[$IP]); }
219
-    }
220
-    $Cache->cache_value('login_attempts', $AllAttempts, 0);
221
-  }
222
-
223
-  // If user has submitted form
224
-  if (isset($_POST['username']) && !empty($_POST['username']) && isset($_POST['password']) && !empty($_POST['password'])) {
225
-    if ($Banned) {
226
-      header("Location: login.php");
227
-      die();
201
+    $Validate->SetFields('username', true, 'regex', 'You did not enter a valid username', array('regex' => USERNAME_REGEX));
202
+    $Validate->SetFields('password', '1', 'string', 'You entered an invalid password', array('minlength' => '6', 'maxlength' => '307200'));
203
+
204
+    list($Attempts, $Banned) = $Cache->get_value('login_attempts_'.db_string($_SERVER['REMOTE_ADDR']));
205
+
206
+    // Function to log a user's login attempt
207
+    function log_attempt()
208
+    {
209
+        global $Cache, $Attempts;
210
+        $Attempts = ($Attempts ?? 0) + 1;
211
+        $Cache->cache_value('login_attempts_'.db_string($_SERVER['REMOTE_ADDR']), array($Attempts, ($Attempts > 5)), 60*60*$Attempts);
212
+        $AllAttempts = $Cache->get_value('login_attempts');
213
+        $AllAttempts[$_SERVER['REMOTE_ADDR']] = time()+(60*60*$Attempts);
214
+        foreach ($AllAttempts as $IP => $Time) {
215
+            if ($Time < time()) {
216
+                unset($AllAttempts[$IP]);
217
+            }
218
+        }
219
+        $Cache->cache_value('login_attempts', $AllAttempts, 0);
228
     }
220
     }
229
-    $Err = $Validate->ValidateForm($_POST);
230
 
221
 
231
-    if (!$Err) {
232
-      // Passes preliminary validation (username and password "look right")
233
-      $DB->query("
234
-        SELECT
235
-          ID,
236
-          PermissionID,
237
-          CustomPermissions,
238
-          PassHash,
239
-          TwoFactor,
240
-          Enabled
241
-        FROM users_main
242
-        WHERE Username = ?
243
-          AND Username != ''", $_POST['username']);
244
-      list($UserID, $PermissionID, $CustomPermissions, $PassHash, $TwoFactor, $Enabled) = $DB->next_record(MYSQLI_NUM, array(2));
245
-      if (!$Banned) {
246
-        if ($UserID && Users::check_password($_POST['password'], $PassHash)) {
247
-          // Update hash if better algorithm available
248
-          if (password_needs_rehash($PassHash, PASSWORD_DEFAULT)) {
222
+    // If user has submitted form
223
+    if (isset($_POST['username']) && !empty($_POST['username']) && isset($_POST['password']) && !empty($_POST['password'])) {
224
+        if ($Banned) {
225
+            header("Location: login.php");
226
+            die();
227
+        }
228
+        $Err = $Validate->ValidateForm($_POST);
229
+
230
+        if (!$Err) {
231
+            // Passes preliminary validation (username and password "look right")
249
             $DB->query("
232
             $DB->query("
250
-              UPDATE users_main
251
-              SET PassHash = ?
252
-              WHERE Username = ?", make_sec_hash($_POST['password']), $_POST['username']);
253
-          }
233
+            SELECT
234
+              ID,
235
+              PermissionID,
236
+              CustomPermissions,
237
+              PassHash,
238
+              TwoFactor,
239
+              Enabled
240
+            FROM users_main
241
+              WHERE Username = ?
242
+              AND Username != ''", $_POST['username']);
243
+            list($UserID, $PermissionID, $CustomPermissions, $PassHash, $TwoFactor, $Enabled) = $DB->next_record(MYSQLI_NUM, array(2));
244
+            if (!$Banned) {
245
+                if ($UserID && Users::check_password($_POST['password'], $PassHash)) {
246
+                    // Update hash if better algorithm available
247
+                    if (password_needs_rehash($PassHash, PASSWORD_DEFAULT)) {
248
+                        $DB->query("
249
+                        UPDATE users_main
250
+                        SET PassHash = ?
251
+                          WHERE Username = ?", make_sec_hash($_POST['password']), $_POST['username']);
252
+                    }
254
 
253
 
255
-          if (empty($TwoFactor) || $TwoFA->verifyCode($TwoFactor, $_POST['twofa'])) {
256
-            # todo: Make sure the type is (int)
257
-            if ($Enabled === '1') {
254
+                    if (empty($TwoFactor) || $TwoFA->verifyCode($TwoFactor, $_POST['twofa'])) {
255
+                        # todo: Make sure the type is (int)
256
+                        if ($Enabled === '1') {
258
 
257
 
259
               // Check if the current login attempt is from a location previously logged in from
258
               // Check if the current login attempt is from a location previously logged in from
260
-              if (apcu_exists('DBKEY')) {
261
-                $DB->query("
262
-                  SELECT IP
263
-                  FROM users_history_ips
264
-                  WHERE UserID = ?", $UserID);
265
-                $IPs = $DB->to_array(false, MYSQLI_NUM);
266
-                $QueryParts = [];
267
-                foreach ($IPs as $i => $IP) {
268
-                  $IPs[$i] = Crypto::decrypt($IP[0]);
269
-                }
270
-                $IPs = array_unique($IPs);
271
-                if (count($IPs) > 0) { // Always allow first login
272
-                  foreach ($IPs as $IP) {
273
-                    $QueryParts[] = "(StartIP<=INET6_ATON('$IP') AND EndIP>=INET6_ATON('$IP'))";
274
-                  }
275
-                  $DB->query('SELECT ASN FROM geoip_asn WHERE '.implode(' OR ', $QueryParts));
276
-                  $PastASNs = array_column($DB->to_array(false, MYSQLI_NUM), 0);
277
-                  $DB->query("SELECT ASN FROM geoip_asn WHERE StartIP<=INET6_ATON('$_SERVER[REMOTE_ADDR]') AND EndIP>=INET6_ATON('$_SERVER[REMOTE_ADDR]')");
278
-                  list($CurrentASN) = $DB->next_record();
279
-
280
-                  // If FEATURE_ENFORCE_LOCATIONS is enabled, require users to confirm new logins
281
-                  if (!in_array($CurrentASN, $PastASNs) && FEATURE_ENFORCE_LOCATIONS) {
282
-                    // Never logged in from this location before
283
-                    if ($Cache->get_value('new_location_'.$UserID.'_'.$CurrentASN) !== true) {
284
-                      $DB->query("
285
-                        SELECT
286
-                          UserName,
287
-                          Email
288
-                        FROM users_main
289
-                        WHERE ID = ?", $UserID);
290
-                      list($Username, $Email) = $DB->next_record();
291
-                      Users::auth_location($UserID, $Username, $CurrentASN, Crypto::decrypt($Email));
292
-                      require('newlocation.php');
293
-                      die();
294
-                    }
295
-                  }
296
-                }
297
-              }
298
-
299
-              $U2FRegs = [];
300
-              $DB->query("
301
-                SELECT KeyHandle, PublicKey, Certificate, Counter, Valid
302
-                FROM u2f
303
-                WHERE UserID = ?", $UserID);
304
-              // Needs to be an array of objects, so we can't use to_array()
305
-              while (list($KeyHandle, $PublicKey, $Certificate, $Counter, $Valid) = $DB->next_record()) {
306
-                $U2FRegs[] = (object)['keyHandle'=>$KeyHandle, 'publicKey'=>$PublicKey, 'certificate'=>$Certificate, 'counter'=>$Counter, 'valid'=>$Valid];
307
-              }
308
-
309
-              if (sizeof($U2FRegs) > 0) {
310
-                // U2F is enabled for this account
311
-                if (isset($_POST['u2f-request']) && isset($_POST['u2f-response'])) {
312
-                  // Data from the U2F login page is present. Verify it.
313
-                  try {
314
-                    $U2FReg = $U2F->doAuthenticate(json_decode($_POST['u2f-request']), $U2FRegs, json_decode($_POST['u2f-response']));
315
-                    if ($U2FReg->valid != '1') throw new Exception('Token disabled.');
316
-                    $DB->query("UPDATE u2f
259
+                            if (apcu_exists('DBKEY')) {
260
+                                $DB->query("
261
+                                SELECT IP
262
+                                FROM users_history_ips
263
+                                  WHERE UserID = ?", $UserID);
264
+                                $IPs = $DB->to_array(false, MYSQLI_NUM);
265
+                                $QueryParts = [];
266
+                                foreach ($IPs as $i => $IP) {
267
+                                    $IPs[$i] = Crypto::decrypt($IP[0]);
268
+                                }
269
+                                $IPs = array_unique($IPs);
270
+                                if (count($IPs) > 0) { // Always allow first login
271
+                                    foreach ($IPs as $IP) {
272
+                                        $QueryParts[] = "(StartIP<=INET6_ATON('$IP') AND EndIP>=INET6_ATON('$IP'))";
273
+                                    }
274
+                                    $DB->query('SELECT ASN FROM geoip_asn WHERE '.implode(' OR ', $QueryParts));
275
+                                    $PastASNs = array_column($DB->to_array(false, MYSQLI_NUM), 0);
276
+                                    $DB->query("SELECT ASN FROM geoip_asn WHERE StartIP<=INET6_ATON('$_SERVER[REMOTE_ADDR]') AND EndIP>=INET6_ATON('$_SERVER[REMOTE_ADDR]')");
277
+                                    list($CurrentASN) = $DB->next_record();
278
+
279
+                                    // If FEATURE_ENFORCE_LOCATIONS is enabled, require users to confirm new logins
280
+                                    if (!in_array($CurrentASN, $PastASNs) && FEATURE_ENFORCE_LOCATIONS) {
281
+                                        // Never logged in from this location before
282
+                                        if ($Cache->get_value('new_location_'.$UserID.'_'.$CurrentASN) !== true) {
283
+                                            $DB->query("
284
+                                            SELECT
285
+                                              UserName,
286
+                                              Email
287
+                                            FROM users_main
288
+                                              WHERE ID = ?", $UserID);
289
+                                            list($Username, $Email) = $DB->next_record();
290
+                                            Users::auth_location($UserID, $Username, $CurrentASN, Crypto::decrypt($Email));
291
+                                            require('newlocation.php');
292
+                                            die();
293
+                                        }
294
+                                    }
295
+                                }
296
+                            }
297
+
298
+                            $U2FRegs = [];
299
+                            $DB->query("
300
+                            SELECT KeyHandle, PublicKey, Certificate, Counter, Valid
301
+                            FROM u2f
302
+                              WHERE UserID = ?", $UserID);
303
+                            // Needs to be an array of objects, so we can't use to_array()
304
+                            while (list($KeyHandle, $PublicKey, $Certificate, $Counter, $Valid) = $DB->next_record()) {
305
+                                $U2FRegs[] = (object)['keyHandle'=>$KeyHandle, 'publicKey'=>$PublicKey, 'certificate'=>$Certificate, 'counter'=>$Counter, 'valid'=>$Valid];
306
+                            }
307
+
308
+                            if (sizeof($U2FRegs) > 0) {
309
+                                // U2F is enabled for this account
310
+                                if (isset($_POST['u2f-request']) && isset($_POST['u2f-response'])) {
311
+                                    // Data from the U2F login page is present. Verify it.
312
+                                    try {
313
+                                        $U2FReg = $U2F->doAuthenticate(json_decode($_POST['u2f-request']), $U2FRegs, json_decode($_POST['u2f-response']));
314
+                                        if ($U2FReg->valid != '1') {
315
+                                            throw new Exception('Token disabled.');
316
+                                        }
317
+                                        $DB->query(
318
+                                            "UPDATE u2f
317
                                 SET Counter = ?
319
                                 SET Counter = ?
318
                                 WHERE KeyHandle = ?
320
                                 WHERE KeyHandle = ?
319
                                 AND UserID = ?",
321
                                 AND UserID = ?",
320
-                      $U2FReg->counter, $U2FReg->keyHandle, $UserID);
321
-                  } catch (Exception $e) {
322
-                    $U2FErr = 'U2F key invalid. Error: '.($e->getMessage());
323
-                    if ($e->getMessage() == 'Token disabled.') {
324
-                      $U2FErr = 'This token was disabled due to suspected cloning. Contact staff for assistance';
325
-                    }
326
-                    if ($e->getMessage() == 'Counter too low.') {
327
-                      $BadHandle = json_decode($_POST['u2f-response'], true)['keyHandle'];
328
-                      $DB->query("UPDATE u2f
322
+                                            $U2FReg->counter,
323
+                                            $U2FReg->keyHandle,
324
+                                            $UserID
325
+                                        );
326
+                                    } catch (Exception $e) {
327
+                                        $U2FErr = 'U2F key invalid. Error: '.($e->getMessage());
328
+                                        if ($e->getMessage() == 'Token disabled.') {
329
+                                            $U2FErr = 'This token was disabled due to suspected cloning. Contact staff for assistance';
330
+                                        }
331
+                                        if ($e->getMessage() == 'Counter too low.') {
332
+                                            $BadHandle = json_decode($_POST['u2f-response'], true)['keyHandle'];
333
+                                            $DB->query("UPDATE u2f
329
                                   SET Valid = '0'
334
                                   SET Valid = '0'
330
                                   WHERE KeyHandle = ?
335
                                   WHERE KeyHandle = ?
331
                                   AND UserID = ?", $BadHandle, $UserID);
336
                                   AND UserID = ?", $BadHandle, $UserID);
332
-                      $U2FErr = 'U2F counter too low. This token has been disabled due to suspected cloning. Contact staff for assistance.';
333
-                    }
334
-                  }
335
-                } else {
336
-                  // Data from the U2F login page is not present. Go there
337
-                  require('u2f.php');
338
-                  die();
339
-                }
340
-              }
341
-
342
-              if (sizeof($U2FRegs) == 0 || !isset($U2FErr)) {
343
-                $SessionID = Users::make_secret(64);
344
-                setcookie('session', $SessionID, (time()+60*60*24*365), '/', '', true, true);
345
-                setcookie('userid', $UserID, (time()+60*60*24*365), '/', '', true, true);
346
-
347
-                // Because we <3 our staff
348
-                $Permissions = Permissions::get_permissions($PermissionID);
349
-                $CustomPermissions = unserialize($CustomPermissions);
350
-                if (isset($Permissions['Permissions']['site_disable_ip_history'])
351
-                  || isset($CustomPermissions['site_disable_ip_history'])
337
+                                            $U2FErr = 'U2F counter too low. This token has been disabled due to suspected cloning. Contact staff for assistance';
338
+                                        }
339
+                                    }
340
+                                } else {
341
+                                    // Data from the U2F login page is not present. Go there
342
+                                    require('u2f.php');
343
+                                    die();
344
+                                }
345
+                            }
346
+
347
+                            if (sizeof($U2FRegs) == 0 || !isset($U2FErr)) {
348
+                                $SessionID = Users::make_secret(64);
349
+                                setcookie('session', $SessionID, (time()+60*60*24*365), '/', '', true, true);
350
+                                setcookie('userid', $UserID, (time()+60*60*24*365), '/', '', true, true);
351
+
352
+                                // Because we <3 our staff
353
+                                $Permissions = Permissions::get_permissions($PermissionID);
354
+                                $CustomPermissions = unserialize($CustomPermissions);
355
+                                if (isset($Permissions['Permissions']['site_disable_ip_history'])
356
+                                 || isset($CustomPermissions['site_disable_ip_history'])
352
                 ) {
357
                 ) {
353
-                  $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
354
-                }
355
-
356
-                $DB->query("
357
-                  INSERT INTO users_sessions
358
-                    (UserID, SessionID, KeepLogged, Browser, OperatingSystem, IP, LastUpdate, FullUA)
359
-                  VALUES
360
-                    ('$UserID', '".db_string($SessionID)."', '1', '$Browser', '$OperatingSystem', '".db_string(apcu_exists('DBKEY')?Crypto::encrypt($_SERVER['REMOTE_ADDR']):'0.0.0.0')."', NOW(), '".db_string($_SERVER['HTTP_USER_AGENT'])."')");
361
-
362
-                $Cache->begin_transaction("users_sessions_$UserID");
363
-                $Cache->insert_front($SessionID, [
364
-                  'SessionID' => $SessionID,
365
-                  'Browser' => $Browser,
366
-                  'OperatingSystem' => $OperatingSystem,
367
-                  'IP' => (apcu_exists('DBKEY')?Crypto::encrypt($_SERVER['REMOTE_ADDR']):'0.0.0.0'),
368
-                  'LastUpdate' => sqltime()
369
-                ]);
370
-                $Cache->commit_transaction(0);
371
-
372
-                $Sql = "
373
-                  UPDATE users_main
374
-                  SET
375
-                    LastLogin = NOW(),
376
-                    LastAccess = NOW()
377
-                  WHERE ID = '".db_string($UserID)."'";
378
-
379
-                $DB->query($Sql);
380
-
381
-                if (!empty($_COOKIE['redirect'])) {
382
-                  $URL = $_COOKIE['redirect'];
383
-                  setcookie('redirect', '', time() - 60 * 60 * 24, '/', '', false);
384
-                  header("Location: $URL");
385
-                  die();
358
+                                    $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
359
+                                }
360
+
361
+                                $DB->query("
362
+                                INSERT INTO users_sessions
363
+                                  (UserID, SessionID, KeepLogged, Browser, OperatingSystem, IP, LastUpdate, FullUA)
364
+                                VALUES
365
+                                  ('$UserID', '".db_string($SessionID)."', '1', '$Browser', '$OperatingSystem', '".db_string(apcu_exists('DBKEY')?Crypto::encrypt($_SERVER['REMOTE_ADDR']):'0.0.0.0')."', NOW(), '".db_string($_SERVER['HTTP_USER_AGENT'])."')");
366
+
367
+                                $Cache->begin_transaction("users_sessions_$UserID");
368
+                                $Cache->insert_front($SessionID, [
369
+                                  'SessionID' => $SessionID,
370
+                                  'Browser' => $Browser,
371
+                                  'OperatingSystem' => $OperatingSystem,
372
+                                  'IP' => (apcu_exists('DBKEY')?Crypto::encrypt($_SERVER['REMOTE_ADDR']):'0.0.0.0'),
373
+                                  'LastUpdate' => sqltime()
374
+                                ]);
375
+                                $Cache->commit_transaction(0);
376
+
377
+                                $Sql = "
378
+                                UPDATE users_main
379
+                                SET
380
+                                  LastLogin = NOW(),
381
+                                  LastAccess = NOW()
382
+                                  WHERE ID = '".db_string($UserID)."'";
383
+
384
+                                $DB->query($Sql);
385
+
386
+                                if (!empty($_COOKIE['redirect'])) {
387
+                                    $URL = $_COOKIE['redirect'];
388
+                                    setcookie('redirect', '', time() - 60 * 60 * 24, '/', '', false);
389
+                                    header("Location: $URL");
390
+                                    die();
391
+                                } else {
392
+                                    header('Location: index.php');
393
+                                    die();
394
+                                }
395
+                            } else {
396
+                                log_attempt();
397
+                                $Err = $U2FErr;
398
+                                setcookie('keeplogged', '', time() + 60 * 60 * 24 * 365, '/', '', false);
399
+                            }
400
+                        } else {
401
+                            log_attempt();
402
+                            if ($Enabled == 2) {
403
+
404
+                                // Save the username in a cookie for the disabled page
405
+                                setcookie('username', db_string($_POST['username']), time() + 60 * 60, '/', '', false);
406
+                                header('Location: login.php?action=disabled');
407
+                            # todo: Make sure the type is (int)
408
+                            } elseif ($Enabled === '0') {
409
+                                $Err = 'Your account has not been confirmed. Please check your email, including the spam folder';
410
+                            }
411
+                            setcookie('keeplogged', '', time() + 60 * 60 * 24 * 365, '/', '', false);
412
+                        }
413
+                    } else {
414
+                        log_attempt();
415
+                        $Err = 'Two-factor authentication failed';
416
+                        setcookie('keeplogged', '', time() + 60 * 60 * 24 * 365, '/', '', false);
417
+                    }
386
                 } else {
418
                 } else {
387
-                  header('Location: index.php');
388
-                  die();
419
+                    log_attempt();
420
+                    $Err = 'Your username or password was incorrect';
421
+                    setcookie('keeplogged', '', time() + 60 * 60 * 24 * 365, '/', '', false);
389
                 }
422
                 }
390
-              } else {
423
+            } else {
391
                 log_attempt();
424
                 log_attempt();
392
-                $Err = $U2FErr;
393
                 setcookie('keeplogged', '', time() + 60 * 60 * 24 * 365, '/', '', false);
425
                 setcookie('keeplogged', '', time() + 60 * 60 * 24 * 365, '/', '', false);
394
-              }
395
-            } else {
396
-              log_attempt();
397
-              if ($Enabled == 2) {
398
-
399
-                // Save the username in a cookie for the disabled page
400
-                setcookie('username', db_string($_POST['username']), time() + 60 * 60, '/', '', false);
401
-                header('Location: login.php?action=disabled');
402
-                # todo: Make sure the type is (int)
403
-              } elseif ($Enabled === '0') {
404
-                $Err = 'Your account has not been confirmed.<br />Please check your email.';
405
-              }
406
-              setcookie('keeplogged', '', time() + 60 * 60 * 24 * 365, '/', '', false);
407
             }
426
             }
408
-          } else {
427
+        } else {
409
             log_attempt();
428
             log_attempt();
410
-            $Err = 'Two-factor authentication failed.';
411
             setcookie('keeplogged', '', time() + 60 * 60 * 24 * 365, '/', '', false);
429
             setcookie('keeplogged', '', time() + 60 * 60 * 24 * 365, '/', '', false);
412
-          }
413
-        } else {
414
-          log_attempt();
415
-          $Err = 'Your username or password was incorrect.';
416
-          setcookie('keeplogged', '', time() + 60 * 60 * 24 * 365, '/', '', false);
417
         }
430
         }
418
-
419
-      } else {
420
-        log_attempt();
421
-        setcookie('keeplogged', '', time() + 60 * 60 * 24 * 365, '/', '', false);
422
-      }
423
-
424
-    } else {
425
-      log_attempt();
426
-      setcookie('keeplogged', '', time() + 60 * 60 * 24 * 365, '/', '', false);
427
     }
431
     }
428
-  }
429
-  require('sections/login/login.php');
432
+    require('sections/login/login.php');
430
 }
433
 }

+ 13
- 12
sections/login/recover_step1.php View File

1
 <?php
1
 <?php
2
+
2
 View::show_header('Recover Password', 'validate');
3
 View::show_header('Recover Password', 'validate');
3
 echo $Validate->GenerateJS('recoverform');
4
 echo $Validate->GenerateJS('recoverform');
4
 ?>
5
 ?>
5
 <form class="auth_form" name="recovery" id="recoverform" method="post" action="" onsubmit="return formVal();">
6
 <form class="auth_form" name="recovery" id="recoverform" method="post" action="" onsubmit="return formVal();">
6
   <div style="width: 250px;">
7
   <div style="width: 250px;">
7
     <p class="titletext"><strong>Reset Your Password</strong></p>
8
     <p class="titletext"><strong>Reset Your Password</strong></p>
8
-<?php
9
+    <?php
9
 if (empty($Sent) || (!empty($Sent) && $Sent != 1)) {
10
 if (empty($Sent) || (!empty($Sent) && $Sent != 1)) {
10
     if (!empty($Err)) {
11
     if (!empty($Err)) {
11
         ?>
12
         ?>
12
     <strong class="important_text"><?=$Err ?></strong>
13
     <strong class="important_text"><?=$Err ?></strong>
13
-<?php
14
+    <?php
14
     } ?>
15
     } ?>
15
-    <p>An email will be sent to your email address with information on how to reset your password.</p>
16
+    <p>An email will be sent to your email address with information on how to reset your password. Please remember to
17
+      check your spam folder.</p>
16
     <table class="layout" cellpadding="2" cellspacing="1" border="0" align="center">
18
     <table class="layout" cellpadding="2" cellspacing="1" border="0" align="center">
17
       <tr valign="center">
19
       <tr valign="center">
18
         <!-- <td align="right"><strong>Email Address&nbsp;</strong></td> -->
20
         <!-- <td align="right"><strong>Email Address&nbsp;</strong></td> -->
19
         <td align="left">
21
         <td align="left">
20
-        <input type="email" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" name="email"
21
-          id="email" class="inputtext" required="required" maxlength="50"
22
-          autofocus="autofocus" placeholder="Email" size="40"
23
-          autocomplete="email" />
24
-      </td>
22
+          <input type="email" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" name="email"
23
+            id="email" class="inputtext" required="required" maxlength="50" autofocus="autofocus" placeholder="Email"
24
+            size="40" autocomplete="email" />
25
+        </td>
25
       </tr>
26
       </tr>
26
       <tr>
27
       <tr>
27
         <td colspan="2" align="right"><input type="submit" name="reset" value="Reset" class="submit" /></td>
28
         <td colspan="2" align="right"><input type="submit" name="reset" value="Reset" class="submit" /></td>
28
       </tr>
29
       </tr>
29
     </table>
30
     </table>
30
-<?php
31
+    <?php
31
 } else { ?>
32
 } else { ?>
32
-  <p>An email has been sent to you. Please follow the directions to reset your password.</p>
33
-<?php
33
+    <p>An email has been sent to you. Please follow the directions to reset your password and remember to check your
34
+      spam folder.</p>
35
+    <?php
34
 } ?>
36
 } ?>
35
   </div>
37
   </div>
36
 </form>
38
 </form>
37
 <?php
39
 <?php
38
 View::show_footer(['recover' => true]);
40
 View::show_footer(['recover' => true]);
39
-?>

Loading…
Cancel
Save