Files
ukaiautomation/admin/spam-dashboard.php

233 lines
9.1 KiB
PHP
Raw Normal View History

2025-06-17 19:22:58 +01:00
<?php
// Spam Analysis Dashboard
session_start();
// Simple authentication check (you should implement proper admin authentication)
$authKey = $_GET['key'] ?? '';
if ($authKey !== 'your-secret-admin-key-2024') {
header('HTTP/1.0 403 Forbidden');
exit('Access Denied');
}
// Function to parse log files
function parseLogFile($filename) {
if (!file_exists($filename)) {
return [];
}
$entries = [];
$lines = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $line) {
if (preg_match('/^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) - (.+)$/', $line, $matches)) {
$entries[] = [
'timestamp' => $matches[1],
'message' => $matches[2]
];
}
}
return array_reverse($entries); // Most recent first
}
// Get log data
$contactSubmissions = parseLogFile('../logs/contact-submissions.log');
$contactErrors = parseLogFile('../logs/contact-errors.log');
$blockedIPs = file_exists('../logs/blocked-ips.txt') ? file('../logs/blocked-ips.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) : [];
// Analyze spam patterns
$spamPatterns = [
'recaptcha_failures' => 0,
'direct_post_attempts' => 0,
'rate_limit_hits' => 0,
'low_interaction_scores' => 0,
'blocked_ips_count' => count($blockedIPs),
'hourly_distribution' => array_fill(0, 24, 0),
'top_ips' => []
];
$ipCounts = [];
foreach ($contactErrors as $error) {
if (strpos($error['message'], 'RECAPTCHA FAILED') !== false) {
$spamPatterns['recaptcha_failures']++;
}
if (strpos($error['message'], 'DIRECT POST') !== false) {
$spamPatterns['direct_post_attempts']++;
}
if (strpos($error['message'], 'Too many requests') !== false) {
$spamPatterns['rate_limit_hits']++;
}
if (strpos($error['message'], 'LOW INTERACTION SCORE') !== false) {
$spamPatterns['low_interaction_scores']++;
}
// Extract IP addresses
if (preg_match('/from ([0-9.]+)/', $error['message'], $matches)) {
$ip = $matches[1];
$ipCounts[$ip] = ($ipCounts[$ip] ?? 0) + 1;
}
// Track hourly distribution
$hour = (int)date('G', strtotime($error['timestamp']));
$spamPatterns['hourly_distribution'][$hour]++;
}
// Get top spam IPs
arsort($ipCounts);
$spamPatterns['top_ips'] = array_slice($ipCounts, 0, 10, true);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Spam Analysis Dashboard - UK Data Services</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f5; color: #333; }
.container { max-width: 1200px; margin: 0 auto; padding: 20px; }
h1 { margin-bottom: 30px; color: #764ba2; }
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 30px; }
.stat-card { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.stat-card h3 { font-size: 14px; color: #666; margin-bottom: 10px; }
.stat-card .value { font-size: 32px; font-weight: bold; color: #764ba2; }
.section { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); margin-bottom: 20px; }
.section h2 { margin-bottom: 15px; color: #333; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 10px; text-align: left; border-bottom: 1px solid #eee; }
th { background: #f8f8f8; font-weight: 600; }
.log-entry { font-family: monospace; font-size: 12px; }
.error { color: #ef4444; }
.success { color: #10b981; }
.chart { margin: 20px 0; }
.bar { background: #764ba2; height: 20px; margin-bottom: 5px; transition: width 0.3s; }
.bar-label { font-size: 12px; color: #666; }
.blocked-ip { background: #fee; color: #c00; padding: 2px 6px; border-radius: 3px; font-family: monospace; font-size: 12px; }
</style>
</head>
<body>
<div class="container">
<h1>Spam Analysis Dashboard</h1>
<div class="stats-grid">
<div class="stat-card">
<h3>reCAPTCHA Failures</h3>
<div class="value"><?php echo $spamPatterns['recaptcha_failures']; ?></div>
</div>
<div class="stat-card">
<h3>Direct POST Attempts</h3>
<div class="value"><?php echo $spamPatterns['direct_post_attempts']; ?></div>
</div>
<div class="stat-card">
<h3>Rate Limit Hits</h3>
<div class="value"><?php echo $spamPatterns['rate_limit_hits']; ?></div>
</div>
<div class="stat-card">
<h3>Low Interaction Scores</h3>
<div class="value"><?php echo $spamPatterns['low_interaction_scores']; ?></div>
</div>
<div class="stat-card">
<h3>Blocked IPs</h3>
<div class="value"><?php echo $spamPatterns['blocked_ips_count']; ?></div>
</div>
<div class="stat-card">
<h3>Successful Submissions</h3>
<div class="value"><?php echo count($contactSubmissions); ?></div>
</div>
</div>
<div class="section">
<h2>Hourly Spam Distribution</h2>
<div class="chart">
<?php
$maxHourly = max($spamPatterns['hourly_distribution']);
for ($hour = 0; $hour < 24; $hour++):
$count = $spamPatterns['hourly_distribution'][$hour];
$width = $maxHourly > 0 ? ($count / $maxHourly * 100) : 0;
?>
<div style="display: flex; align-items: center; margin-bottom: 5px;">
<div class="bar-label" style="width: 40px;"><?php echo str_pad($hour, 2, '0', STR_PAD_LEFT); ?>:00</div>
<div class="bar" style="width: <?php echo $width; ?>%;"></div>
<div class="bar-label" style="margin-left: 10px;"><?php echo $count; ?></div>
</div>
<?php endfor; ?>
</div>
</div>
<div class="section">
<h2>Top Spam Source IPs</h2>
<table>
<thead>
<tr>
<th>IP Address</th>
<th>Attempts</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<?php foreach ($spamPatterns['top_ips'] as $ip => $count): ?>
<tr>
<td><span class="blocked-ip"><?php echo htmlspecialchars($ip); ?></span></td>
<td><?php echo $count; ?></td>
<td>
<?php
$isBlocked = false;
foreach ($blockedIPs as $blockedEntry) {
if (strpos($blockedEntry, $ip . '|') === 0) {
$isBlocked = true;
break;
}
}
echo $isBlocked ? '<span class="error">Blocked</span>' : '<span class="success">Active</span>';
?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<div class="section">
<h2>Recent Error Log (Last 20)</h2>
<table>
<thead>
<tr>
<th>Timestamp</th>
<th>Error</th>
</tr>
</thead>
<tbody>
<?php foreach (array_slice($contactErrors, 0, 20) as $error): ?>
<tr>
<td><?php echo htmlspecialchars($error['timestamp']); ?></td>
<td class="log-entry"><?php echo htmlspecialchars($error['message']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<div class="section">
<h2>Recent Successful Submissions (Last 10)</h2>
<table>
<thead>
<tr>
<th>Timestamp</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<?php foreach (array_slice($contactSubmissions, 0, 10) as $submission): ?>
<tr>
<td><?php echo htmlspecialchars($submission['timestamp']); ?></td>
<td class="log-entry"><?php echo htmlspecialchars($submission['message']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</body>
</html>