From 1f9d52bd2b55084aceed6d281c82c82ca0c1b3c1 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 16 Jul 2026 15:53:11 +0200 Subject: [PATCH] =?UTF-8?q?Foto-Backend:=20L=C3=B6schfunktion=20pro=20Foto?= =?UTF-8?q?=20(=E2=9C=95-Knopf=20am=20Thumbnail,=20mit=20Best=C3=A4tigung)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- App/pages/foto-upload.php | 49 +++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/App/pages/foto-upload.php b/App/pages/foto-upload.php index 7261d41..1eff309 100644 --- a/App/pages/foto-upload.php +++ b/App/pages/foto-upload.php @@ -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 __…), 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.
Foto 1 ? 's' : '' ?> hochgeladen — danke! Atlas kümmert sich um Zuschnitt und Einbau.
+
🗑️ Foto gelöscht.
⚠️
Kapitel: @@ -313,9 +344,17 @@ foreach ($KAPITEL as $sim => $k) {
- - - +
+ + + +
+ + + + +
+