= 6 ? $password : null; } /** * Update the number of failed login attempts for an IP address and blacklist if necessary. * Handles file errors and uses file locking for concurrency. * * @param string $ip * @return void */ public static function updateFailedAttempts(string $ip): void { $blacklist_file = BLACKLIST_DIR . "/BLACKLIST.json"; $content = []; if (file_exists($blacklist_file)) { $raw = @file_get_contents($blacklist_file); if ($raw !== false) { $json = json_decode($raw, true); if (is_array($json)) { $content = $json; } } } if (isset($content[$ip])) { $content[$ip]['login_attempts'] += 1; if ($content[$ip]['login_attempts'] >= 3) { $content[$ip]['blacklisted'] = true; $content[$ip]['timestamp'] = time(); } } else { $content[$ip] = [ 'login_attempts' => 1, 'blacklisted' => false, 'timestamp' => time(), ]; } $fp = fopen($blacklist_file, 'c+'); if ($fp) { if (flock($fp, LOCK_EX)) { ftruncate($fp, 0); rewind($fp); fwrite($fp, json_encode($content)); fflush($fp); flock($fp, LOCK_UN); } fclose($fp); } } /** * Check if an IP address is blacklisted. If the blacklist has expired, reset blacklist and login_attempts. * Handles file errors and uses file locking for concurrency. * * @param string $ip * @return bool */ public static function isBlacklisted(string $ip): bool { $blacklist_file = BLACKLIST_DIR . "/BLACKLIST.json"; $blacklist = []; if (file_exists($blacklist_file)) { $raw = @file_get_contents($blacklist_file); if ($raw !== false) { $json = json_decode($raw, true); if (is_array($json)) { $blacklist = $json; } } } if (isset($blacklist[$ip]) && $blacklist[$ip]['blacklisted']) { // Check if the timestamp is older than three days if (time() - $blacklist[$ip]['timestamp'] > (3 * 24 * 60 * 60)) { // Remove the IP address from the blacklist and reset login_attempts $blacklist[$ip]['blacklisted'] = false; $blacklist[$ip]['login_attempts'] = 0; $fp = fopen($blacklist_file, 'c+'); if ($fp) { if (flock($fp, LOCK_EX)) { ftruncate($fp, 0); rewind($fp); fwrite($fp, json_encode($blacklist)); fflush($fp); flock($fp, LOCK_UN); } fclose($fp); } } else { return true; } } return false; } }