Browse Source

Add more "check spam" notices

pjc 5 years ago
parent
commit
43c6b298d0
5 changed files with 474 additions and 439 deletions
  1. 33
    21
      classes/autoenable.class.php
  2. 2
    0
      classes/rules.class.php
  3. 63
    46
      sections/donate/donate.php
  4. 363
    360
      sections/login/index.php
  5. 13
    12
      sections/login/recover_step1.php

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

@@ -1,6 +1,7 @@
1
-<?
1
+<?php
2 2
 
3
-class AutoEnable {
3
+class AutoEnable
4
+{
4 5
 
5 6
     // Constants for database values
6 7
     const APPROVED = 1;
@@ -11,10 +12,10 @@ class AutoEnable {
11 12
     const CACHE_KEY_NAME = 'num_enable_requests';
12 13
 
13 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 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 21
      * Handle a new enable request
@@ -23,7 +24,8 @@ class AutoEnable {
23 24
      * @param string $Email The user's email address
24 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 29
         if (empty($Username)) {
28 30
             header("Location: login.php");
29 31
             die();
@@ -69,11 +71,16 @@ class AutoEnable {
69 71
             // New disable activation request
70 72
             $UserAgent = db_string($_SERVER['HTTP_USER_AGENT']);
71 73
 
72
-            G::$DB->query("
74
+            G::$DB->query(
75
+                "
73 76
                 INSERT INTO users_enable_requests
74 77
                 (UserID, Email, IP, UserAgent, Timestamp)
75 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 84
             $RequestID = G::$DB->inserted_id();
78 85
 
79 86
             // Cache the number of requests for the modbar
@@ -82,7 +89,7 @@ class AutoEnable {
82 89
             $Output = self::RECEIVED_MESSAGE;
83 90
             Tools::update_user_notes($UserID, sqltime() . " - Enable request " . G::$DB->inserted_id() . " received from $IP\n\n");
84 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,7 +103,8 @@ class AutoEnable {
96 103
      * @param int $Status The status to mark the requests as
97 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 108
         if ($Status != self::APPROVED && $Status != self::DENIED && $Status != self::DISCARDED) {
101 109
             error(404);
102 110
         }
@@ -123,7 +131,7 @@ class AutoEnable {
123 131
         if ($Status != self::DISCARDED) {
124 132
             // Prepare email
125 133
             require_once(SERVER_ROOT . '/classes/templates.class.php');
126
-            $TPL = NEW TEMPLATE;
134
+            $TPL = new TEMPLATE;
127 135
             if ($Status == self::APPROVED) {
128 136
                 $TPL->open(SERVER_ROOT . '/templates/enable_request_accepted.tpl');
129 137
                 $TPL->set('SITE_DOMAIN', SITE_DOMAIN);
@@ -168,10 +176,10 @@ class AutoEnable {
168 176
             FROM users_main
169 177
             WHERE ID = ?", $StaffID);
170 178
         if (G::$DB->has_results()) {
171
-          list($StaffUser) = G::$DB->next_record();
179
+            list($StaffUser) = G::$DB->next_record();
172 180
         } else {
173
-          $StaffUser = "System";
174
-          $StaffID = 0;
181
+            $StaffUser = "System";
182
+            $StaffID = 0;
175 183
         }
176 184
 
177 185
         foreach ($UserInfo as $User) {
@@ -196,7 +204,8 @@ class AutoEnable {
196 204
      *
197 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 209
         $ID = (int) $ID;
201 210
 
202 211
         if (empty($ID)) {
@@ -235,12 +244,13 @@ class AutoEnable {
235 244
      * @param int $Outcome The outcome integer
236 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 249
         if ($Outcome == self::APPROVED) {
240 250
             $String = "Approved";
241
-        } else if ($Outcome == self::DENIED) {
251
+        } elseif ($Outcome == self::DENIED) {
242 252
             $String = "Rejected";
243
-        } else if ($Outcome == self::DISCARDED) {
253
+        } elseif ($Outcome == self::DISCARDED) {
244 254
             $String = "Discarded";
245 255
         } else {
246 256
             $String = "---";
@@ -255,7 +265,8 @@ class AutoEnable {
255 265
      * @param string $Token The token
256 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 270
         $Token = db_string($Token);
260 271
         G::$DB->query("
261 272
             SELECT uer.UserID, uer.HandledTimestamp, um.torrent_pass, um.Visible, um.IP
@@ -299,7 +310,8 @@ class AutoEnable {
299 310
      * @param boolean $Checked Should checked requests be included?
300 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 315
         $Where = [];
304 316
 
305 317
         if (!empty($Username)) {
@@ -312,7 +324,7 @@ class AutoEnable {
312 324
         }
313 325
 
314 326
         if (!empty($SubmittedTimestamp1)) {
315
-            switch($SubmittedBetween) {
327
+            switch ($SubmittedBetween) {
316 328
                 case 'on':
317 329
                     $Where[] = "DATE(uer.Timestamp) = DATE('$SubmittedTimestamp1')";
318 330
                     break;
@@ -333,7 +345,7 @@ class AutoEnable {
333 345
         }
334 346
 
335 347
         if (!empty($HandledTimestamp1)) {
336
-            switch($HandledBetween) {
348
+            switch ($HandledBetween) {
337 349
                 case 'on':
338 350
                     $Where[] = "DATE(uer.HandledTimestamp) = DATE('$HandledTimestamp1')";
339 351
                     break;

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

@@ -109,6 +109,8 @@ class Rules
109 109
 
110 110
   <li>Please discuss site news in the corresponding Announcements thread instead of making a new General thread.
111 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 114
     Thank you.</li>
113 115
 
114 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,12 +17,15 @@ View::show_header('Donate');
17 17
 ?>
18 18
 
19 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 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 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 29
       If you're financially able, please help pay its bills by donating.
27 30
       We use the donations to cover the costs of running the site, tracker, and IRC network.
28 31
     </p>
@@ -30,7 +33,8 @@ View::show_header('Donate');
30 33
     <p>
31 34
       No staff member or other individual responsible for the site's operation personally profits from user donations.
32 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 38
     </p>
35 39
 
36 40
     <p>
@@ -41,70 +45,85 @@ View::show_header('Donate');
41 45
     </p>
42 46
 
43 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 57
   </div>
50 58
 
51 59
   <span class="donation_info_title">How to donate to <?= SITE_NAME ?></span>
52 60
   <div class="box pad donation_info">
53 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 64
       We also accept <strong>tax-deductible donations</strong> on behalf of the
56 65
       <a href="https://www.boslab.org/donate" target="_blank">Boston Open Science Laboratory (BosLab)</a>,
57 66
       a registered 501c3.
58 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 70
     </p>
61 71
 
62 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 77
       There are some benefits to donating that culmulate with each tier pledged.
66 78
       Each tier's awards include those already listed.
67 79
     </p>
68 80
 
69 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 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 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 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 107
     </p>
91 108
   </div>
92 109
 
93 110
   <span class="donation_info_title">What donating means for your account</span>
94 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 128
     <ul>
110 129
       <li>Our eternal love, as represented by the heart you get next to your name</li>
@@ -117,12 +136,10 @@ View::show_header('Donate');
117 136
       <li>A warm, fuzzy feeling</li>
118 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 140
       <li>Immunity from the rules</li>
124 141
       <li>Additional upload credit</li>
125
-    </ul>
142
+      </ul>
126 143
   </div>
127 144
 </div>
128 145
 <!-- END Donate -->

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

@@ -6,17 +6,17 @@ Add the JavaScript validation into the display page using the class
6 6
 
7 7
 // Allow users to reset their password while logged in
8 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 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 17
 // Check if IP is banned
18 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 22
 require_once SERVER_ROOT.'/classes/twofa.class.php';
@@ -27,404 +27,407 @@ $Validate = new Validate;
27 27
 $TwoFA = new TwoFactorAuth(SITE_NAME);
28 28
 $U2F = new u2f\U2F('https://'.SITE_DOMAIN);
29 29
 
30
+# todo: Test strict equality very gently here
30 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 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 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 194
     } else {
196
-      error(403);
195
+        error(403);
197 196
     }
198
-  } else {
199
-    error(403);
200
-  }
201 197
 } // End new location
202 198
 
203 199
 // Normal login
204 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 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 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 319
                                 SET Counter = ?
318 320
                                 WHERE KeyHandle = ?
319 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 334
                                   SET Valid = '0'
330 335
                                   WHERE KeyHandle = ?
331 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 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 424
                 log_attempt();
392
-                $Err = $U2FErr;
393 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 428
             log_attempt();
410
-            $Err = 'Two-factor authentication failed.';
411 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,39 +1,40 @@
1 1
 <?php
2
+
2 3
 View::show_header('Recover Password', 'validate');
3 4
 echo $Validate->GenerateJS('recoverform');
4 5
 ?>
5 6
 <form class="auth_form" name="recovery" id="recoverform" method="post" action="" onsubmit="return formVal();">
6 7
   <div style="width: 250px;">
7 8
     <p class="titletext"><strong>Reset Your Password</strong></p>
8
-<?php
9
+    <?php
9 10
 if (empty($Sent) || (!empty($Sent) && $Sent != 1)) {
10 11
     if (!empty($Err)) {
11 12
         ?>
12 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 18
     <table class="layout" cellpadding="2" cellspacing="1" border="0" align="center">
17 19
       <tr valign="center">
18 20
         <!-- <td align="right"><strong>Email Address&nbsp;</strong></td> -->
19 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 26
       </tr>
26 27
       <tr>
27 28
         <td colspan="2" align="right"><input type="submit" name="reset" value="Reset" class="submit" /></td>
28 29
       </tr>
29 30
     </table>
30
-<?php
31
+    <?php
31 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 37
   </div>
36 38
 </form>
37 39
 <?php
38 40
 View::show_footer(['recover' => true]);
39
-?>

Loading…
Cancel
Save