# This patch file was generated by NetBeans IDE
# This patch can be applied using context Tools: Apply Diff Patch action on respective folder.
# It uses platform neutral UTF-8 encoding.
# Above lines and this line are ignored by the patching process.
Index: contributions/modules/login_security/login_security.module
--- contributions/modules/login_security/login_security.module Base (1.12.2.6)
+++ contributions/modules/login_security/login_security.module Locally Modified (Based On 1.12.2.6)
@@ -30,9 +30,8 @@
  * Implementation of hook_cron().
  */
 function login_security_cron() {
-  // calc expiring time of login security tracked entries
-  $time = time() - (variable_get('login_security_track_time', LOGIN_SECURITY_TRACK_TIME) * 3600);
-  db_query("DELETE FROM {login_security_track} WHERE timestamp < %d", $time);
+  // Remove expired events
+  _login_security_remove_events();
   return;
 }
 
@@ -43,14 +42,17 @@
   switch ($op) {
     case 'login':
       // On success login remove any temporary protection for the IP address and the username
-      db_query("DELETE FROM {login_security_track} WHERE name = '%s' AND host = '%s'", check_plain($edit['name']), check_plain(ip_address()));
+      _login_security_remove_events($edit['name'], ip_address());
       break;
     case 'update':
-      // The update case can be launched by the user or by any user administrator
-      // On update, remove only the unser information tracked
-      db_query("DELETE FROM {login_security_track} WHERE name = '%s'", check_plain($edit['name']));
+      // The update case can be launched by the user or by any administrator
+      // On update, remove only the unser information tracked.
+      if ($edit['status'] != 0) {
+        // Don't remove tracking events if account is being blocked
+        _login_security_remove_events($account->name);
+      }
       break;
-      // Cron will clean the forgotten tracking entries, including the deleted users.
+      // Cron will clean the forgotten tracking entries, including relating to deleted users.
   }
 }
 
@@ -230,6 +232,8 @@
  * Previous incarnations of this code put it in hook_submit or hook_user, but since
  * Drupal core validation updates the login timestamp, we have to set the message before
  * it gets updated with the current login instance.
+ *
+ * Also we save the login attempt event here.
  */
 function login_security_set_login_timestamp($form, &$form_state) {
   $account = user_load(array('name' => $form_state['values']['name'], 'pass' => trim($form_state['values']['pass']), 'status' => 1));
@@ -239,6 +243,8 @@
   if (variable_get('login_security_last_access_timestamp', 0) && $account->access > 0) {
     drupal_set_message(t('Your last page access (site activity) was !stamp', array('!stamp' => format_date($account->access, 'large'))), 'status');
   }
+    // Save entry in security log, Username and IP Address
+  _login_security_add_event(check_plain($form_state['values']['name']), check_plain(ip_address()));
 }
 
 /**
@@ -276,8 +282,8 @@
     return;
   }
 
-  // Save entry in security log, Username and IP Address
-  _login_security_add_event($name, check_plain(ip_address()));
+  // Expire old tracked entries
+  _login_security_remove_events();
 
   // Populate variables to be used in any module message or login operation
   $variables = _login_security_get_variables_by_name($name);
@@ -325,7 +331,7 @@
 
     // Should the user be advised about the remaining login attempts?
     $notice_user = variable_get('login_security_notice_attempts_available', LOGIN_SECURITY_NOTICE_ATTEMPTS_AVAILABLE);
-    if (($notice_user == TRUE) && ($variables['%user_block_attempts'] > 0)) {
+    if (($notice_user == TRUE) && ($variables['%user_block_attempts'] > 0) && $variables['%user_block_attempts'] >= $variables['%user_current_count']) {
         // this loop is instead of doing t() because t() can only translate static strings, not variables.
         foreach ($variables as $key => $value) {
           $variables[$key] = theme('placeholder', $value);
@@ -336,6 +342,33 @@
   }
 
 /**
+ * Remove tracked events or expire old ones.
+ *
+ * @param $name
+ *   if specified, events for this user name will be removed.
+ *
+ * @param $ip
+ *   if specified, IP Address of the name-ip pair to be removed.
+ */
+function _login_security_remove_events($name = NULL, $ip = NULL) {
+  // Remove selected events
+  if (empty($name)) {
+    if (empty($host)) {
+      db_query("DELETE FROM {login_security_track} WHERE name = '%s' AND host = '%s'", check_plain($name), check_plain(ip_address()));
+    }
+    else {
+      db_query("DELETE FROM {login_security_track} WHERE name = '%s'", check_plain($name));
+    }
+  }
+  else {
+    // Calculate protection time window and remove expired events
+    $time = time() - (variable_get('login_security_track_time', LOGIN_SECURITY_TRACK_TIME) * 3600);
+    db_query("DELETE FROM {login_security_track} WHERE timestamp < %d", $time);
+  }
+  return;
+}
+
+/**
  * Save the login attempt in the tracking database: user name and ip address.
  *
  * @param $name
Index: contributions/modules/login_security/login_security.test
--- contributions/modules/login_security/login_security.test Base (1.1.2.6)
+++ contributions/modules/login_security/login_security.test Locally Modified (Based On 1.1.2.6)
@@ -21,6 +21,8 @@
     // Create and login user
     $admin_user = $this->drupalCreateUser(array('administer users'));
     $this->drupalLogin($admin_user);
+    // Set time tracking window to 1 hour
+    variable_set('login_security_track_time', 1);
   }
 
   function testAdminUserSettings() {
@@ -58,6 +60,8 @@
     parent::setUp('login_security');
     // Ensure the table has no entries
     db_query("TRUNCATE TABLE {login_security_track}");
+    // Set time tracking window to 1 hour
+    variable_set('login_security_track_time', 1);
   }
 
   // Check if login is break somewhere
@@ -71,7 +75,7 @@
   function testUserBlocking() {
     $login_attempts_limit = 2;
 
-    // allow 3 attempts to login before being blocking is enforced
+    // allow 2 attempts to login before being blocking is enforced
     variable_set('login_security_user_wrong_count', $login_attempts_limit);
 
     // in Drupal 7, we can drupalGetMails() to see if a notice went out to admin
@@ -186,6 +190,8 @@
     parent::setUp('login_security');
     // Ensure the table has no entries
     db_query("TRUNCATE TABLE {login_security_track}");
+    // Set time tracking window to 1 hour
+    variable_set('login_security_track_time', 1);
   }
 
   function testLogin() {
@@ -197,9 +203,9 @@
 
   function testSoftBlocking() {
 
-    $login_attempts_limit = 2;
+    $login_attempts_limit = 3;
 
-    // allow 2 attempts to login before being soft-blocking is enforced
+    // allow 3 attempts to login before being soft-blocking is enforced
     variable_set('login_security_user_wrong_count', 0);
     variable_set('login_security_host_wrong_count', 2);
     // remove notices
@@ -229,6 +235,7 @@
     // remove error messages
     variable_set('login_security_disable_core_login_error', 1);
 
+    // Third try, still valid without soft blocking
     $this->drupalLoginLite($normal_user);
     $this->assertNoText("This host is not allowed to log in", t('Soft-block message does not display.'));
     $this->assertFieldByName('form_id', 'user_login', t('Login form found.'));
@@ -236,6 +243,7 @@
     // restore error messages
     variable_set('login_security_disable_core_login_error', 0);
 
+    // 4th attempt, the host is not allowed this time
\ No newline at end of file
     $this->drupalLoginLite($normal_user);
     $this->assertText("This host is not allowed to log in", t('Soft-block message displays.'));
     $this->assertFieldByName('form_id', 'user_login', t('Login form found.'));
