Foto-Backend: Löschfunktion pro Foto (✕-Knopf am Thumbnail, mit Bestätigung)

- POST-Handler aktion=loeschen: entfernt Upload-Datei + Thumbnail-Cache
- Schutz: kein Pfad-Ausbruch, .note.txt nicht löschbar, hinter PIN, PRG-Redirect
- ✕-Overlay-Button auf jedem Thumbnail, JS-confirm vor dem Löschen

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 15:53:11 +02:00
parent 2e50aaf49f
commit 1f9d52bd2b
+44 -5
View File
@@ -166,9 +166,32 @@ function safeName(string $s): string {
return trim(mb_substr($s, 0, 80), '-.') ?: 'foto';
}
/* ---------- Upload verarbeiten (PRG-Muster) ---------- */
/* ---------- Löschen eines wartenden Uploads (PRG) ---------- */
$fehler = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$geloescht = 0;
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['aktion'] ?? '') === 'loeschen') {
$sim = preg_replace('/[^a-z0-9-]/', '', $_POST['sim'] ?? '');
$file = basename($_POST['file'] ?? '');
$pfad = "{$UPLOAD_BASE}/{$sim}/{$file}";
// nur echte Upload-Dateien (Muster <slug>__…), keine Notizen, kein Pfad-Ausbruch
if ($sim !== '' && $file !== '' && strpos($file, '..') === false
&& substr($file, -9) !== '.note.txt' && is_file($pfad)) {
@unlink($pfad);
// zugehörigen Thumbnail-Cache mitlöschen
@unlink("{$UPLOAD_BASE}/.thumbs/{$sim}__{$file}.jpg");
$geloescht = 1;
} else {
$fehler[] = 'Foto zum Löschen nicht gefunden.';
}
if ($geloescht) {
$anker = $sim . '-' . preg_replace('/__.*/', '', $file);
header("Location: ?del=1&sim=" . urlencode($sim) . "#{$anker}");
exit;
}
}
/* ---------- Upload verarbeiten (PRG-Muster) ---------- */
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['aktion'] ?? '') !== 'loeschen') {
$sim = $_POST['sim'] ?? '';
$slug = preg_replace('/[^a-z0-9-]/', '', $_POST['slug'] ?? '');
$note = trim($_POST['note'] ?? '');
@@ -212,6 +235,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
$ok = isset($_GET['ok']) ? (int)$_GET['ok'] : 0;
$okAnker = $ok ? (($_GET['sim'] ?? '') . '-' . ($_GET['slug'] ?? '')) : '';
$del = isset($_GET['del']);
/* Übersichtszahlen */
$gesamt = 0; $mitFoto = 0; $wartend = 0;
@@ -250,8 +274,14 @@ foreach ($KAPITEL as $sim => $k) {
.thumb { max-width: 190px; border-radius: 8px; display: block; margin: 6px 0; }
a.lightbox { cursor: zoom-in; }
.pgrid { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0; }
.pgrid .pt { position: relative; }
.pgrid .pt img { width: 110px; height: 110px; object-fit: cover; border-radius: 8px; display: block;
border: 2px solid #e8c9a0; background: #eee; }
.pgrid .pt .del { position: absolute; top: 3px; right: 3px; margin: 0; }
.pgrid .pt .del button { width: 26px; height: 26px; border-radius: 999px; border: 0; cursor: pointer;
background: rgba(163,50,39,.92); color: #fff; font-size: 15px; font-weight: 800; line-height: 1;
display: flex; align-items: center; justify-content: center; box-shadow: 0 1px 4px rgba(0,0,0,.35); }
.pgrid .pt .del button:hover { background: #a33227; }
.pnote { font-size: 13px; color: #6b6659; font-style: italic; margin: 2px 0 6px; }
#ov { position: fixed; inset: 0; background: rgba(20,26,30,.88); display: flex; align-items: center;
justify-content: center; z-index: 99; cursor: zoom-out; }
@@ -287,6 +317,7 @@ foreach ($KAPITEL as $sim => $k) {
Version im Kapitel.</div>
<?php if ($ok): ?><div class="okbox">✅ <?= $ok ?> Foto<?= $ok > 1 ? 's' : '' ?> hochgeladen — danke! Atlas kümmert sich um Zuschnitt und Einbau.</div><?php endif; ?>
<?php if ($del): ?><div class="okbox">🗑️ Foto gelöscht.</div><?php endif; ?>
<?php foreach ($fehler as $f): ?><div class="errbox">⚠️ <?= $f ?></div><?php endforeach; ?>
<div class="toc"><b>Kapitel:</b>
@@ -313,9 +344,17 @@ foreach ($KAPITEL as $sim => $k) {
<?php if ($pend): ?>
<div class="pgrid">
<?php foreach ($pend as $p): ?>
<a class="pt lightbox" href="?img=<?= urlencode($sim . '/' . $p['name']) ?>" title="<?= htmlspecialchars($p['name']) ?> · <?= $p['kb'] ?> KB">
<img src="?thumb=<?= urlencode($sim . '/' . $p['name']) ?>" loading="lazy" alt="">
</a>
<div class="pt">
<a class="lightbox" href="?img=<?= urlencode($sim . '/' . $p['name']) ?>" title="<?= htmlspecialchars($p['name']) ?> · <?= $p['kb'] ?> KB">
<img src="?thumb=<?= urlencode($sim . '/' . $p['name']) ?>" loading="lazy" alt="">
</a>
<form method="post" class="del" onsubmit="return confirm('Dieses Foto wirklich löschen?');">
<input type="hidden" name="aktion" value="loeschen">
<input type="hidden" name="sim" value="<?= htmlspecialchars($sim) ?>">
<input type="hidden" name="file" value="<?= htmlspecialchars($p['name']) ?>">
<button type="submit" title="Foto löschen" aria-label="Foto löschen">✕</button>
</form>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>