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:
@@ -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; ?>
|
||||
|
||||
Reference in New Issue
Block a user