Virenscan
Der Virenscan ist nur für Administratoren zugänglich.
'; return; }
$message = null;
$error = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
verify_csrf();
if (!$isAdmin) {
$error = 'Änderungen sind Administratoren vorbehalten.';
} else {
$action = $_POST['action'] ?? '';
if ($action === 'save') {
$mode = in_array($_POST['mode'] ?? '', ['auto', 'clamdscan', 'clamscan', 'builtin'], true) ? $_POST['mode'] : 'auto';
$binary = trim((string) ($_POST['binary'] ?? ''));
if ($binary !== '' && (preg_match('/[\r\n\0]/', $binary) || !is_file($binary) || !is_executable($binary))) {
$error = 'Der angegebene Pfad ist keine ausführbare Datei.';
} else {
plugin_set_setting(VIRENSCAN, 'mode', $mode);
plugin_set_setting(VIRENSCAN, 'binary', $binary);
plugin_set_setting(VIRENSCAN, 'timeout', (string) max(5, min(300, (int) ($_POST['timeout'] ?? 60))));
plugin_set_setting(VIRENSCAN, 'max_mb', (string) max(1, min(500, (int) ($_POST['max_mb'] ?? 25))));
plugin_set_setting(VIRENSCAN, 'block_on_error', !empty($_POST['block_on_error']) ? '1' : '0');
plugin_set_setting(VIRENSCAN, 'notify', !empty($_POST['notify']) ? '1' : '0');
foreach (['analysis', 'block_macros', 'block_encrypted', 'block_unscannable'] as $k) plugin_set_setting(VIRENSCAN, $k, !empty($_POST[$k]) ? '1' : '0');
plugin_set_setting(VIRENSCAN, 'vt_threshold', (string) max(1, min(30, (int) ($_POST['vt_threshold'] ?? 3))));
$newKey = trim((string) ($_POST['vt_key'] ?? ''));
if (!empty($_POST['vt_clear'])) plugin_set_setting(VIRENSCAN, 'vt_key', '');
elseif ($newKey !== '') {
if (!preg_match('/^[a-f0-9]{64}$/i', $newKey)) $error = 'Der VirusTotal-Schlüssel besteht aus 64 Zeichen (0–9, a–f).';
else { plugin_set_setting(VIRENSCAN, 'vt_key', encrypt_secret($newKey)); plugin_set_setting(VIRENSCAN, 'vt_error', ''); }
}
if (!$error) $message = 'Einstellungen gespeichert.';
}
} elseif ($action === 'test') {
$tmp = tempnam(sys_get_temp_dir(), 'vsc');
file_put_contents($tmp, virenscan_eicar());
$res = virenscan_scan_file($tmp);
@unlink($tmp);
$message = $res['status'] === 'infected'
? 'Test bestanden: Die Standard-Testdatei (EICAR) wurde erkannt' . ($res['signature'] ? ' (' . $res['signature'] . ')' : '') . '.'
: null;
if ($message === null) $error = 'Test nicht bestanden: Die Testdatei wurde nicht erkannt (' . ($res['message'] ?? $res['status']) . ').';
} elseif ($action === 'backlog') {
plugin_set_setting(VIRENSCAN, 'start_id', '0');
$message = 'Der gesamte Bestand wird jetzt nach und nach geprüft (jeweils bis zu 25 Dateien alle paar Minuten).';
} elseif ($action === 'release') {
$message = virenscan_release($pdo, (int) ($_POST['id'] ?? 0)) ? 'Datei freigegeben. Sie ist im Ticket wieder herunterladbar.' : null;
if ($message === null) $error = 'Die Datei konnte nicht freigegeben werden.';
} elseif ($action === 'delete') {
$message = virenscan_delete($pdo, (int) ($_POST['id'] ?? 0)) ? 'Datei endgültig gelöscht.' : null;
if ($message === null) $error = 'Die Datei konnte nicht gelöscht werden.';
}
}
}
$cfg = virenscan_config();
$status = virenscan_status();
$stats = virenscan_stats($pdo);
$labels = ['clean' => 'Sauber', 'infected' => 'Verseucht', 'error' => 'Fehler', 'skipped' => 'Übersprungen', 'blocked' => 'Gesperrt (Fehler)', 'released' => 'Freigegeben', 'deleted' => 'Gelöscht'];
// Reiter: Übersicht, Quarantäne (mit Anzahl), Geprüft, Einstellungen
$tabs = ['uebersicht' => ['Übersicht', 0], 'quarantaene' => ['Quarantäne', (int) $stats['quarantined']], 'geprueft' => ['Geprüft', 0], 'einstellungen' => ['Einstellungen', 0]];
$tab = isset($tabs[$_GET['tab'] ?? '']) ? (string) $_GET['tab'] : 'uebersicht';
// Geprüft: Filter und Seiten
$filter = isset($labels[$_GET['status'] ?? '']) ? (string) $_GET['status'] : '';
$perPage = 50;
$pageNo = max(1, (int) ($_GET['seite'] ?? 1));
if ($tab === 'geprueft') {
$cnt = $pdo->prepare('SELECT COUNT(*) FROM plugin_virenscan_files' . ($filter !== '' ? ' WHERE status = ?' : ''));
$cnt->execute($filter !== '' ? [$filter] : []);
$totalChecked = (int) $cnt->fetchColumn();
$pages = max(1, (int) ceil($totalChecked / $perPage));
$pageNo = min($pageNo, $pages);
$q = $pdo->prepare('SELECT f.*, t.ticket_number FROM plugin_virenscan_files f LEFT JOIN tickets t ON t.id = f.ticket_id' . ($filter !== '' ? ' WHERE f.status = ?' : '') . ' ORDER BY f.id DESC LIMIT ' . $perPage . ' OFFSET ' . (($pageNo - 1) * $perPage));
$q->execute($filter !== '' ? [$filter] : []);
$checked = $q->fetchAll();
}
if ($tab === 'quarantaene') {
$quarantine = $pdo->query('SELECT f.*, t.ticket_number FROM plugin_virenscan_files f LEFT JOIN tickets t ON t.id = f.ticket_id WHERE f.quarantined = 1 ORDER BY f.id DESC LIMIT 200')->fetchAll();
}
?>
Virenscan
= e($message) ?>
= e($error) ?>
= virenscan_tabs($tab, $tabs) ?>
Zustand
✓ Dateianalyse aktivDateianalyse ausgeschaltet
· ClamAV bereit (= e($status['mode']) ?>, = e((string) $status['version']) ?>)ClamAV nicht vorhanden (optional)
· ✓ Hash-Abfrage aktiv (heute = plugin_setting(VIRENSCAN, 'vt_day', '') === date('Y-m-d') ? (int) plugin_setting(VIRENSCAN, 'vt_count', '0') : 0 ?> von 450 Abfragen)Hash-Abfrage aus (kein Schlüssel)
= e($status['message']) ?>
Hash-Abfrage: = e((string) plugin_setting(VIRENSCAN, 'vt_error', '')) ?>
Geprüft: = (int) $stats['clean'] ?> sauber · = (int) $stats['infected'] ?> verseucht · = (int) $stats['error'] ?> Fehler · = (int) $stats['skipped'] ?> übersprungen · in Quarantäne: = (int) $stats['quarantined'] ?>
Letzter Hintergrundlauf: = e(plugin_setting(VIRENSCAN, 'last_run', '') ?: 'noch nicht') ?>
0): ?>
= (int) $stats['quarantined'] ?> Datei(en) in Quarantäne prüfen
Ohne diesen Knopf werden nur Anhänge geprüft, die nach dem Einschalten des Plugins eingehen.
Quarantäne
Keine gesperrten Dateien. Alles in Ordnung.
Geprüfte Dateien (= (int) $totalChecked ?>= $filter !== '' ? ' mit Ergebnis „' . e($labels[$filter]) . '“' : '' ?>)
Keine Einträge.
| Datei | Ergebnis | Hinweis | Ticket | Wann |
| = e($r['original_name']) ?> |
= e($labels[$r['status']] ?? $r['status']) ?> |
= e((string) ($r['signature'] ?: $r['message'])) ?> |
#= e((string) $r['ticket_number']) ?> |
= e((string) $r['scanned_at']) ?> |
1): ?>