SIMON Master Console Rebuild
True command center for SIMON + WEB360
This rebuild gives you a cleaner production spine: interactive tree, live viewer, guarded editor, dynamic graphics, architecture map, and note storage. It is designed to sit beside your existing
console.php
and become the stronger replacement path.
Dashboard
Tree
Viewer
System Map
File Registry
Notes
Files
15,341
Folders
408
Scanned Size
3.84 GB
PHP Files
891
Editable Text Files
12,602
File viewer
guarded to /htdocs
/sitelogs/sitereg.php
<?php declare(strict_types=1); require_once __DIR__ . '/_bootstrap.php'; /** * SIMON SiteLogs V7 FIXED * Multi-directory log discovery + dashboard * Suggested path: /htdocs/sitelogs/index.php */ date_default_timezone_set('America/Chicago'); if (!headers_sent()) { header('X-App: SIMON-SiteLogs-V7-Fixed'); header('X-Content-Type-Options: nosniff'); header('X-Frame-Options: SAMEORIGIN'); header('Referrer-Policy: strict-origin-when-cross-origin'); header('Permissions-Policy: geolocation=(), microphone=()'); } function h(string $v): string { return htmlspecialchars($v, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); } function fmt_int(int|float $n): string { return number_format((float)$n); } function fmt_pct(float $n, int $d = 2): string { return number_format($n, $d) . '%'; } function fmt_size(int $bytes): string { if ($bytes >= 1073741824) return number_format($bytes / 1073741824, 2) . ' GB'; if ($bytes >= 1048576) return number_format($bytes / 1048576, 2) . ' MB'; if ($bytes >= 1024) return number_format($bytes / 1024, 2) . ' KB'; return $bytes . ' B'; } function is_gz(string $file): bool { return str_ends_with(strtolower($file), '.gz'); } function short_text(string $s, int $len = 80): string { return mb_strlen($s) <= $len ? $s : mb_substr($s, 0, $len - 1) . '…'; } function parse_log_time(?string $raw): ?DateTime { if (!$raw) return null; $dt = DateTime::createFromFormat('d/M/Y:H:i:s O', $raw); if (!$dt) return null; $dt->setTimezone(new DateTimeZone(date_default_timezone_get())); return $dt; } function inc(array &$a, string $k, int $n = 1): void { $a[$k] = ($a[$k] ?? 0) + $n; } function top_assoc(array $a, int $limit = 10): array { arsort($a); return array_slice($a, 0, $limit, true); } function classify_file_type(string $name): string { $n = strtolower($name); if (str_contains($n, 'access.log')) return 'access'; if (str_contains($n, 'sftp.log')) return 'sftp'; if (str_contains($n, 'health.log')) return 'health'; if (str_contains($n, 'contact.log')) return 'contact'; if (str_contains($n, 'ga_ping.log')) return 'analytics'; if (str_contains($n, 'provider_latency.log')) return 'latency'; return 'other'; } function classify_bot_name(string $ua): string { $u = strtolower($ua); if ($u === '' || $u === '-') return 'Unknown'; if (str_contains($u, 'gptbot')) return 'GPTBot'; if (str_contains($u, 'claudebot')) return 'ClaudeBot'; if (str_contains($u, 'bingbot')) return 'BingBot'; if (str_contains($u, 'amazonbot')) return 'AmazonBot'; if (str_contains($u, 'facebookexternalhit')) return 'FacebookExternalHit'; if (str_contains($u, 'meta-externalagent')) return 'Meta-ExternalAgent'; if (str_contains($u, 'googlebot')) return 'GoogleBot'; if (str_contains($u, 'sitelockspider')) return 'SiteLockSpider'; if (str_contains($u, 'node-fetch')) return 'node-fetch'; if (preg_match('/bot|crawl|crawler|spider|slurp|fetch/i', $ua)) return 'Other Bot'; return 'Human/Other'; } function detect_browser(string $ua): string { $u = strtolower($ua); if (str_contains($u, 'safari') && str_contains($u, 'mobile') && !str_contains($u, 'chrome')) return 'Safari Mobile'; if (str_contains($u, 'chrome mobile')) return 'Chrome Mobile'; if (str_contains($u, 'chrome')) return 'Chrome'; if (str_contains($u, 'safari') && !str_contains($u, 'chrome')) return 'Safari'; if (str_contains($u, 'firefox')) return 'Firefox'; if (str_contains($u, 'edg')) return 'Edge'; if (str_contains($u, 'opr') || str_contains($u, 'opera')) return 'Opera'; if (str_contains($u, 'curl')) return 'cURL'; if (str_contains($u, 'node-fetch')) return 'node-fetch'; if (str_contains($u, 'msie') || str_contains($u, 'trident')) return 'IE'; return 'Unknown'; } function detect_os(string $ua): string { $u = strtolower($ua); if (str_contains($u, 'iphone') || str_contains($u, 'ipad') || str_contains($u, 'ios')) return 'iOS'; if (str_contains($u, 'mac os') || str_contains($u, 'macintosh')) return 'macOS'; if (str_contains($u, 'windows')) return 'Windows'; if (str_contains($u, 'android')) return 'Android'; if (str_contains($u, 'linux')) return 'Linux'; return 'Unknown'; } function read_plain_tail(string $path, int $maxBytes): iterable { $fh = @fopen($path, 'rb'); if (!$fh) return; $size = @filesize($path) ?: 0; $start = max(0, $size - $maxBytes); fseek($fh, $start); if ($start > 0) fgets($fh); while (!feof($fh)) { $line = fgets($fh); if ($line === false) break; yield $line; } fclose($fh); } function read_gz_all(string $path): iterable { $gz = @gzopen($path, 'rb'); if (!$gz) return; while (!gzeof($gz)) { $line = gzgets($gz); if ($line === false) break; yield $line; } gzclose($gz); } function summarize_change(string $baselineFile, array $snapshot): array { $prev = is_file($baselineFile) ? json_decode((string)@file_get_contents($baselineFile), true) : null; @file_put_contents($baselineFile, json_encode($snapshot, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); if (!is_array($prev)) { return [ 'text' => 'No previous baseline yet.', 'delta_hits' => 0, 'delta_errors' => 0, 'delta_bots' => 0, ]; } $dh = (int)($snapshot['hits'] ?? 0) - (int)($prev['hits'] ?? 0); $de = (int)($snapshot['errors'] ?? 0) - (int)($prev['errors'] ?? 0); $db = (int)($snapshot['bots'] ?? 0) - (int)($prev['bots'] ?? 0); return [ 'text' => 'Hits ' . ($dh >= 0 ? '+' : '') . $dh . ' · Errors ' . ($de >= 0 ? '+' : '') . $de . ' · Bots ' . ($db >= 0 ? '+' : '') . $db, 'delta_hits' => $dh, 'delta_errors' => $de, 'delta_bots' => $db, ]; } $tabs = [ ['label'=>'Summary','href'=>'summary.php'], ['label'=>'Files','href'=>'index.php'], ['label'=>'IP Intel','href'=>'ipintel.php'], ['label'=>'Traffic','href'=>'traffic.php'], ['label'=>'Security','href'=>'security.php'], ['label'=>'Travel','href'=>'travel.php'], ['label'=>'Guardian','href'=>'guardian.php'], ['label'=>'Site Tracker','href'=>'sitemap_tracker.php'], ['label'=>'Site Audit','href'=>'site_audit.php'], ['label'=>'Tracker AI','href'=>'tracker_ai.php'], ['label'=>'Tracker Analytics','href'=>'tracker_analytics.php'], ['label'=>'OpenAI','href'=>'openai.php'], ['label'=>'HELP','href'=>'help.php'], ['label'=>'Logout','href'=>'logout.php'], ]; $currentScript = basename($_SERVER['PHP_SELF'] ?? 'index.php'); $cfg = [ 'TAIL_MB' => max(1, min(256, (int)($_GET['tail_mb'] ?? 32))), 'TOP' => max(5, min(50, (int)($_GET['top'] ?? 12))), 'ACCESS_LIMIT_FILES' => max(1, min(20, (int)($_GET['access_files'] ?? 12))), 'BASELINE_FILE' => __DIR__ . '/.dashboard_baseline.json', 'SUSPICIOUS_RX' => '#/(wp-admin|xmlrpc\.php|wp-login\.php|phpmyadmin|\.env|\.git|vendor|sql|backup|config|\.DS_Store)#i', 'SCAN_DIRS' => [ __DIR__, '/homepages/7/d4299367777/htdocs/htdocs/sitelogs', '/kunden/homepages/7/d4299367777/logs', '/kunden/homepages/7/d4299367777/logs/logs', ], ]; $allEntries = []; foreach ($cfg['SCAN_DIRS'] as $scanDir) { if (!is_dir($scanDir)) continue; $entries = @scandir($scanDir) ?: []; foreach ($entries as $entry) { if ($entry === '.' || $entry === '..') continue; $path = rtrim($scanDir, '/') . '/' . $entry; if (!is_file($path) || !is_readable($path)) continue; $allEntries[$path] = [ 'name' => $entry, 'path' => $path, 'dir' => $scanDir, 'size' => @filesize($path) ?: 0, 'mtime' => @filemtime($path) ?: 0, 'type' => is_gz($entry) ? 'gz' : 'plain', 'channel' => classify_file_type($entry), ]; } } $files = array_values($allEntries); usort($files, fn($a, $b) => $b['mtime'] <=> $a['mtime']); $totalFiles = count($files); $totalSize = array_sum(array_column($files, 'size')); $fileChannels = []; foreach ($files as $f) { inc($fileChannels, $f['channel']); } $accessFiles = array_values(array_filter($files, fn($f) => $f['channel'] === 'access')); usort($accessFiles, fn($a, $b) => $b['mtime'] <=> $a['mtime']); $accessFiles = array_slice($accessFiles, 0, $cfg['ACCESS_LIMIT_FILES']); $patCombined = '/(?P<ip>[0-9a-fA-F:\.]+)\s+\S+\s+\S+\s+\[(?P<dt>[^\]]+)\]\s+"(?P<method>[A-Z]+)\s+(?P<path>[^"]*?)\s+[^"]*"\s+(?P<status>\d{3})\s+(?P<size>-|\d+)\s+"(?P<ref>[^"]*)"\s+"(?P<ua>[^"]*)"/'; $patSimple = '/(?P<ip>[0-9a-fA-F:\.]+)\s+-\s+-\s+\[(?P<dt>[^\]]+)\]\s+"(?P<method>[A-Z]+)\s+(?P<path>[^ ]+)\s+[^"]*"\s+(?P<status>\d{3})\s+(?P<size>-|\d+)/'; $patLoose = '/(?P<ip>[0-9a-fA-F:\.]+)\s+\S+\s+\S+\s+\[(?P<dt>[^\]]+)\]\s+"(?P<method>[A-Z]+)\s+(?P<path>[^"]*?)\s+[^"]*"\s+(?P<status>\d{3})\s+(?P<size>-|\d+)(?:\s+"(?P<ref>[^"]*)")?(?:\s+"(?P<ua>[^"]*)")?/'; $hits = 0; $errors = 0; $bots = 0; $totalBytes = 0; $uniqueIps = []; $topPaths = []; $top404 = []; $topRefs = []; $topUAs = []; $topStatuses = []; $topMethods = []; $hourly = []; $botBreakdown = []; $browserBreakdown = []; $osBreakdown = []; $suspiciousPaths = []; $firstSeen = null; $lastSeen = null; $maxBytes = $cfg['TAIL_MB'] * 1024 * 1024; foreach ($accessFiles as $file) { $iter = is_gz($file['name']) ? read_gz_all($file['path']) : read_plain_tail($file['path'], $maxBytes); foreach ($iter as $line) { if ( !preg_match($patCombined, $line, $m) && !preg_match($patSimple, $line, $m) && !preg_match($patLoose, $line, $m) ) { continue; } $hits++; $ip = trim((string)($m['ip'] ?? '-')); $path = trim((string)($m['path'] ?? '-')); $status = (string)((int)($m['status'] ?? 0)); $method = trim((string)($m['method'] ?? 'UNKNOWN')); $ref = trim((string)(($m['ref'] ?? '-') ?: '-')); $ua = trim((string)(($m['ua'] ?? '-') ?: '-')); $size = (int)((($m['size'] ?? '-') === '-') ? 0 : $m['size']); $totalBytes += $size; $uniqueIps[$ip] = true; inc($topStatuses, $status); inc($topMethods, $method); $pathOnly = explode('?', $path, 2)[0]; if ($pathOnly === '') $pathOnly = '/'; inc($topPaths, $pathOnly); if ((int)$status >= 400) { $errors++; } if ((int)$status === 404) { inc($top404, $pathOnly); } if ($ref !== '-' && $ref !== '') inc($topRefs, $ref); if ($ua !== '-' && $ua !== '') inc($topUAs, $ua); $botName = classify_bot_name($ua); inc($botBreakdown, $botName); if ($botName !== 'Human/Other' && $botName !== 'Unknown') { $bots++; } inc($browserBreakdown, detect_browser($ua)); inc($osBreakdown, detect_os($ua)); if (preg_match($cfg['SUSPICIOUS_RX'], $pathOnly)) { inc($suspiciousPaths, $pathOnly); } $dt = parse_log_time($m['dt'] ?? null); if ($dt) { $bucket = $dt->format('Y-m-d H:00'); inc($hourly, $bucket); if ($firstSeen === null || $dt < $firstSeen) $firstSeen = $dt; if ($lastSeen === null || $dt > $lastSeen) $lastSeen = $dt; } } } ksort($hourly); $uniqueIpCount = count($uniqueIps); $errorRate = $hits > 0 ? ($errors / $hits) * 100 : 0.0; $botRate = $hits > 0 ? ($bots / $hits) * 100 : 0.0; $threatScore = 0; $threatScore += min(45, (int)round($errorRate * 2.2)); $threatScore += min(35, (int)round($botRate * 0.8)); $threatScore += min(20, count($suspiciousPaths) * 2); $threatScore = max(0, min(100, $threatScore)); $aiInsight = 'Traffic stable.'; if ($threatScore >= 70) { $aiInsight = 'High-risk pattern detected: heavy errors, bot pressure, or suspicious probe activity.'; } elseif ($botRate >= 45) { $aiInsight = 'Bot traffic is a major share of the sample. Review crawl filtering and access policy.'; } elseif ($errorRate >= 10) { $aiInsight = 'Error rate is elevated. Check broken routes, blocked probes, or missing assets.'; } elseif ($hits === 0) { $aiInsight = 'No parsed access data found in the selected access logs.'; } $delta = summarize_change($cfg['BASELINE_FILE'], [ 'hits' => $hits, 'errors' => $errors, 'bots' => $bots, 'timestamp' => date('c'), ]); $topPaths = top_assoc($topPaths, $cfg['TOP']); $top404 = top_assoc($top404, $cfg['TOP']); $topRefs = top_assoc($topRefs, $cfg['TOP']); $topUAs = top_assoc($topUAs, $cfg['TOP']); $topStatuses = top_assoc($topStatuses, 10); $topMethods = top_assoc($topMethods, 8); $botBreakdown = top_assoc($botBreakdown, 8); $browserBreakdown = top_assoc($browserBreakdown, 8); $osBreakdown = top_assoc($osBreakdown, 8); $suspiciousPaths = top_assoc($suspiciousPaths, $cfg['TOP']); $fileChannelsTop = top_assoc($fileChannels, 10); $hourly = array_slice($hourly, -48, 48, true); $statusLabels = array_values(array_map('strval', array_keys($topStatuses))); $statusValues = array_values(array_map('intval', array_values($topStatuses))); $botLabels = array_values(array_map('strval', array_keys($botBreakdown))); $botValues = array_values(array_map('intval', array_values($botBreakdown))); $hourlyLabels = array_values(array_keys($hourly)); $hourlyValues = array_values(array_values($hourly)); ?> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"> <title>SIMON SiteLogs V7 Fixed</title> <meta name="theme-color" content="#070b16"> <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script> <style> :root{ --bg:#05070d; --edge:rgba(255,255,255,.12); --ink:#eaf6ff; --muted:#9fd0ea; --cyan:#00eaff; --indigo:#8aa8ff; --violet:#7c4dff; } *{box-sizing:border-box} html,body{height:100%} body{ margin:0; color:var(--ink); font:15px/1.55 ui-sans-serif,system-ui,Inter,Segoe UI,Roboto,Arial; background: radial-gradient(1200px 700px at 15% -10%, rgba(124,77,255,.24), transparent 46%), radial-gradient(900px 500px at 85% 0%, rgba(0,234,255,.12), transparent 40%), radial-gradient(140% 110% at 50% -10%, #0b1432 0%, #05070d 55%, #050814 100%); overflow-x:hidden; } header{ position:sticky;top:0;z-index:40; background:linear-gradient(180deg, rgba(7,11,22,.96), rgba(7,11,22,.68)); border-bottom:1px solid var(--edge); backdrop-filter:blur(10px); } .console{max-width:1500px;margin:0 auto;padding:14px 16px 16px} .head{display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap} .title{ margin:0;font-weight:900;letter-spacing:.6px;line-height:1; font-size:clamp(1.12rem,2.4vw,1.7rem); color:transparent; background:conic-gradient(from 90deg, var(--cyan), var(--indigo), var(--violet), var(--cyan)); -webkit-background-clip:text;background-clip:text; } .sub{color:var(--muted);font-size:.92rem;margin-top:6px} .orb{ width:70px;height:70px;border-radius:50%; background:radial-gradient(circle at 35% 35%, #c9fbff 0%, #6ae0ff 22%, #3558ff 56%, #120f2e 100%); box-shadow:0 0 22px rgba(0,234,255,.55), 0 0 42px rgba(124,77,255,.28); } .tabs{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px} .tabs a{ padding:8px 11px;border-radius:12px;border:1px solid rgba(255,255,255,.14); background:linear-gradient(180deg, rgba(255,255,255,.11), rgba(255,255,255,.04)); color:var(--ink);text-decoration:none; } .tabs a.active{ border-color:rgba(124,77,255,.42); background:linear-gradient(180deg, rgba(124,77,255,.24), rgba(0,234,255,.08)); } .wrap{max-width:1500px;margin:0 auto;padding:16px} .grid{display:grid;grid-template-columns:repeat(12,1fr);gap:14px} .card{ grid-column:span 12; background:linear-gradient(180deg, rgba(255,255,255,.10), rgba(255,255,255,.03)); border:1px solid var(--edge); border-radius:18px; padding:14px; } .span-4{grid-column:span 4} .span-6{grid-column:span 6} .span-12{grid-column:span 12} @media (max-width:1150px){.span-4,.span-6{grid-column:span 12}} .cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px} .inner{ background:linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.02)); border:1px solid rgba(255,255,255,.10); border-radius:14px;padding:12px; } .k{color:var(--muted);font-size:.88rem;text-transform:uppercase;letter-spacing:.06em} .v{font-size:1.8rem;font-weight:800} table{border-collapse:collapse;width:100%} th,td{border-bottom:1px solid rgba(255,255,255,.10);padding:8px 10px;text-align:left;vertical-align:top} th{color:#bfd1ff} .badge{display:inline-block;padding:4px 8px;border:1px solid rgba(255,255,255,.12);border-radius:999px;color:var(--muted);font-size:.82rem} .note{padding:10px 12px;border-left:4px solid rgba(0,234,255,.42);background:rgba(255,255,255,.04);border-radius:12px;color:var(--muted)} .mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.92rem} form.inline{display:flex;gap:10px;flex-wrap:wrap;align-items:center} input,button{ background:#141c31;color:var(--ink);border:1px solid #2a3245;border-radius:10px;padding:7px 10px } button{cursor:pointer} footer{padding:18px 0 28px;color:var(--muted);text-align:center} </style> </head> <body> <header> <div class="console"> <div class="head"> <div> <h1 class="title">GAYLORD SINCLAIR ™ — Log Intelligence V7 Fixed</h1> <div class="sub">Multi-directory scan, active access source detection, and live access parsing</div> </div> <div class="orb" aria-hidden="true"></div> </div> <nav class="tabs"> <?php foreach ($tabs as $tab): ?> <a class="<?= $currentScript === basename($tab['href']) ? 'active' : '' ?>" href="<?= h($tab['href']) ?>"> <?= h($tab['label']) ?> </a> <?php endforeach; ?> </nav> <div style="margin-top:12px"> <form class="inline" method="get"> <label>tail_mb <input name="tail_mb" value="<?= h((string)$cfg['TAIL_MB']) ?>" size="4"></label> <label>top <input name="top" value="<?= h((string)$cfg['TOP']) ?>" size="4"></label> <label>access_files <input name="access_files" value="<?= h((string)$cfg['ACCESS_LIMIT_FILES']) ?>" size="4"></label> <button type="submit">Apply</button> </form> </div> </div> </header> <div class="wrap"> <div class="grid"> <section class="card span-12"> <h3 style="margin:0 0 10px">Executive Signal</h3> <div class="cards"> <div class="inner"><div class="k">Parsed Hits</div><div class="v"><?= fmt_int($hits) ?></div></div> <div class="inner"><div class="k">Unique IPs</div><div class="v"><?= fmt_int($uniqueIpCount) ?></div></div> <div class="inner"><div class="k">Bandwidth</div><div class="v"><?= fmt_size($totalBytes) ?></div></div> <div class="inner"><div class="k">Error Rate</div><div class="v"><?= fmt_pct($errorRate) ?></div></div> <div class="inner"><div class="k">Bot Rate</div><div class="v"><?= fmt_pct($botRate) ?></div></div> <div class="inner"><div class="k">Threat Score</div><div class="v"><?= fmt_int($threatScore) ?>/100</div></div> </div> <div class="note" style="margin-top:12px"> AI Insight: <b><?= h($aiInsight) ?></b><br> Delta: <b><?= h($delta['text']) ?></b><br> First seen: <b><?= h($firstSeen ? $firstSeen->format('Y-m-d H:i:s') : 'n/a') ?></b><br> Last seen: <b><?= h($lastSeen ? $lastSeen->format('Y-m-d H:i:s') : 'n/a') ?></b><br> Access files loaded: <b><?= fmt_int(count($accessFiles)) ?></b> </div> </section> <section class="card span-4"> <h3 style="margin:0 0 10px">File Inventory</h3> <div class="cards"> <div class="inner"> <div class="k">Total Files</div> <div class="v"><?= fmt_int($totalFiles) ?></div> </div> <div class="inner"> <div class="k">Total Size</div> <div class="v"><?= fmt_size($totalSize) ?></div> </div> </div> </section> <section class="card span-4"> <h3 style="margin:0 0 10px">Channel Breakdown</h3> <table> <tr><th>Channel</th><th>Files</th></tr> <?php foreach ($fileChannelsTop as $k => $v): ?> <tr> <td><?= h((string)$k) ?></td> <td><?= fmt_int((int)$v) ?></td> </tr> <?php endforeach; ?> </table> </section> <section class="card span-4"> <h3 style="margin:0 0 10px">Active Access Sources</h3> <?php if (!$accessFiles): ?> <div style="color:#ffb3b3">No access log files found in scanned directories.</div> <?php else: ?> <table> <tr><th>Name</th><th>Folder</th><th>Type</th></tr> <?php foreach ($accessFiles as $f): ?> <tr> <td class="mono"><?= h($f['name']) ?></td> <td class="mono"><?= h($f['dir']) ?></td> <td><span class="badge"><?= h($f['type']) ?></span></td> </tr> <?php endforeach; ?> </table> <?php endif; ?> </section> <section class="card span-6"> <h3 style="margin:0 0 10px">Status Codes</h3> <canvas id="statusChart" height="170"></canvas> </section> <section class="card span-6"> <h3 style="margin:0 0 10px">Bot Breakdown</h3> <canvas id="botChart" height="170"></canvas> </section> <section class="card span-12"> <h3 style="margin:0 0 10px">Hourly Traffic</h3> <canvas id="hourlyChart" height="110"></canvas> </section> <section class="card span-6"> <h3 style="margin:0 0 10px">Top Paths</h3> <table> <tr><th>Path</th><th>Hits</th></tr> <?php foreach ($topPaths as $k => $v): ?> <tr> <td class="mono"><?= h(short_text((string)$k, 92)) ?></td> <td><?= fmt_int((int)$v) ?></td> </tr> <?php endforeach; ?> </table> </section> <section class="card span-6"> <h3 style="margin:0 0 10px">Top 404</h3> <table> <tr><th>Path</th><th>Count</th></tr> <?php foreach ($top404 as $k => $v): ?> <tr> <td class="mono"><?= h(short_text((string)$k, 92)) ?></td> <td><?= fmt_int((int)$v) ?></td> </tr> <?php endforeach; ?> </table> </section> <section class="card span-4"> <h3 style="margin:0 0 10px">Top Referrers</h3> <table> <tr><th>Referrer</th><th>Hits</th></tr> <?php foreach ($topRefs as $k => $v): ?> <tr> <td class="mono"><?= h(short_text((string)$k, 56)) ?></td> <td><?= fmt_int((int)$v) ?></td> </tr> <?php endforeach; ?> </table> </section> <section class="card span-4"> <h3 style="margin:0 0 10px">Browser Breakdown</h3> <table> <tr><th>Browser</th><th>Hits</th></tr> <?php foreach ($browserBreakdown as $k => $v): ?> <tr> <td><?= h((string)$k) ?></td> <td><?= fmt_int((int)$v) ?></td> </tr> <?php endforeach; ?> </table> </section> <section class="card span-4"> <h3 style="margin:0 0 10px">OS Breakdown</h3> <table> <tr><th>OS</th><th>Hits</th></tr> <?php foreach ($osBreakdown as $k => $v): ?> <tr> <td><?= h((string)$k) ?></td> <td><?= fmt_int((int)$v) ?></td> </tr> <?php endforeach; ?> </table> </section> <section class="card span-12"> <h3 style="margin:0 0 10px">Suspicious Paths</h3> <table> <tr><th>Path</th><th>Count</th></tr> <?php if (!$suspiciousPaths): ?> <tr><td colspan="2">No suspicious paths detected in current parsed sample.</td></tr> <?php else: ?> <?php foreach ($suspiciousPaths as $k => $v): ?> <tr> <td class="mono"><?= h(short_text((string)$k, 120)) ?></td> <td><?= fmt_int((int)$v) ?></td> </tr> <?php endforeach; ?> <?php endif; ?> </table> </section> <section class="card span-12"> <h3 style="margin:0 0 10px">File Inventory Table</h3> <table> <tr> <th>Name</th> <th>Folder</th> <th>Size</th> <th>Modified</th> <th>Type</th> <th>Channel</th> <th>Actions</th> </tr> <?php foreach ($files as $f): ?> <tr> <td class="mono"><?= h($f['name']) ?></td> <td class="mono"><?= h($f['dir']) ?></td> <td><?= h(fmt_size((int)$f['size'])) ?></td> <td><?= h(date('Y-m-d H:i:s', (int)$f['mtime'])) ?></td> <td><span class="badge"><?= h($f['type']) ?></span></td> <td><?= h($f['channel']) ?></td> <td> <a href="summary.php?file=<?= urlencode($f['name']) ?>" style="color:#9fd0ea;text-decoration:none">summary</a> <a href="<?= h($f['path']) ?>" style="color:#9fd0ea;text-decoration:none" download>download</a> </td> </tr> <?php endforeach; ?> </table> </section> </div> <footer> ™ Gaylord Sinclair Publishing LLC — SIMON SiteLogs V7 Fixed </footer> </div> <script> (() => { const statusLabels = <?= json_encode($statusLabels, JSON_UNESCAPED_SLASHES) ?>; const statusValues = <?= json_encode($statusValues, JSON_UNESCAPED_SLASHES) ?>; const botLabels = <?= json_encode($botLabels, JSON_UNESCAPED_SLASHES) ?>; const botValues = <?= json_encode($botValues, JSON_UNESCAPED_SLASHES) ?>; const hourlyLabels = <?= json_encode($hourlyLabels, JSON_UNESCAPED_SLASHES) ?>; const hourlyValues = <?= json_encode($hourlyValues, JSON_UNESCAPED_SLASHES) ?>; const statusCtx = document.getElementById('statusChart')?.getContext('2d'); const botCtx = document.getElementById('botChart')?.getContext('2d'); const hourlyCtx = document.getElementById('hourlyChart')?.getContext('2d'); if (statusCtx) { new Chart(statusCtx, { type: 'doughnut', data: { labels: statusLabels, datasets: [{ data: statusValues, borderWidth: 1 }] }, options: { plugins: { legend: { position: 'bottom', labels: { color: '#eaf6ff' } } } } }); } if (botCtx) { new Chart(botCtx, { type: 'bar', data: { labels: botLabels, datasets: [{ label: 'Hits', data: botValues, borderWidth: 1 }] }, options: { scales: { x: { ticks: { color: '#eaf6ff' }, grid: { color: 'rgba(255,255,255,.06)' } }, y: { beginAtZero: true, ticks: { color: '#eaf6ff' }, grid: { color: 'rgba(255,255,255,.08)' } } }, plugins: { legend: { display: false } } } }); } if (hourlyCtx) { new Chart(hourlyCtx, { type: 'bar', data: { labels: hourlyLabels, datasets: [{ label: 'Hits', data: hourlyValues, borderWidth: 1 }] }, options: { scales: { x: { ticks: { color: '#eaf6ff', maxRotation: 90, minRotation: 45 }, grid: { color: 'rgba(255,255,255,.06)' } }, y: { beginAtZero: true, ticks: { color: '#eaf6ff' }, grid: { color: 'rgba(255,255,255,.08)' } } }, plugins: { legend: { display: false } } } }); } })(); </script> </body> </html>
Save file
Quick jump
open a path
Open