Move bad log parsing to utils.js and add section headers

This commit is contained in:
2026-02-16 22:58:58 +01:00
parent 4962d398a1
commit 0d551ede53
7 changed files with 179 additions and 249 deletions

View File

@@ -1,6 +1,10 @@
// Utility functions for Fail2ban UI
// Shared utilities for Fail2ban UI.
"use strict";
// =========================================================================
// Data Normalization
// =========================================================================
function normalizeInsights(data) {
var normalized = data && typeof data === 'object' ? data : {};
if (!normalized.totals || typeof normalized.totals !== 'object') {
@@ -26,6 +30,10 @@ function t(key, fallback) {
return fallback !== undefined ? fallback : key;
}
// =========================================================================
// Focus Management
// =========================================================================
function captureFocusState(container) {
var active = document.activeElement;
if (!active || !container || !container.contains(active)) {
@@ -40,9 +48,7 @@ function captureFocusState(container) {
state.selectionStart = active.selectionStart;
state.selectionEnd = active.selectionEnd;
}
} catch (err) {
// Ignore selection errors for elements that do not support it.
}
} catch (err) {}
return state;
}
@@ -65,11 +71,13 @@ function restoreFocusState(state) {
if (typeof state.selectionStart === 'number' && typeof state.selectionEnd === 'number' && typeof next.setSelectionRange === 'function') {
next.setSelectionRange(state.selectionStart, state.selectionEnd);
}
} catch (err) {
// Element may not support setSelectionRange; ignore.
}
} catch (err) {}
}
// =========================================================================
// String Helpers
// =========================================================================
function highlightQueryMatch(value, query) {
var text = value || '';
if (!query) {
@@ -104,3 +112,46 @@ function slugifyId(value, prefix) {
return (prefix || 'id') + '-' + base + '-' + hash;
}
// =========================================================================
// Log Analysis Helper
// =========================================================================
function isSuspiciousLogLine(line, ip) {
if (!line) {
return false;
}
var containsIP = ip && line.indexOf(ip) !== -1;
var lowered = line.toLowerCase();
// Detect HTTP status codes (>= 300 considered problematic)
var statusMatch = line.match(/"[^"]*"\s+(\d{3})\b/);
if (!statusMatch) {
statusMatch = line.match(/\s(\d{3})\s+(?:\d+|-)/);
}
var statusCode = statusMatch ? parseInt(statusMatch[1], 10) : NaN;
var hasBadStatus = !isNaN(statusCode) && statusCode >= 300;
// Detect common attack indicators in URLs/payloads
var indicators = [
'../',
'%2e%2e',
'%252e%252e',
'%24%7b',
'${',
'/etc/passwd',
'select%20',
'union%20',
'cmd=',
'wget',
'curl ',
'nslookup',
'/xmlrpc.php',
'/wp-admin',
'/cgi-bin',
'content-length: 0'
];
var hasIndicator = indicators.some(function(ind) {
return lowered.indexOf(ind) !== -1;
}); if (containsIP) {
return hasBadStatus || hasIndicator;
}
return (hasBadStatus || hasIndicator) && !ip;
}