bericht/ajax/attachment_thumb.php
Eduard Wisch 4102ebfe5b
All checks were successful
Deploy bericht / deploy (push) Successful in 13s
Editor-Ueberarbeitung 1.5.0: Anhaenge-Kacheln, echte Seitengeometrie, Arbeiten ohne Reload [deploy]
Anhaenge-Spalte: Kachelraster mit Server-Thumbnails statt Dateinamen-Liste (Bilder per GD,
PDFs per PDF.js), Grossansicht per Klick, Auswahlreihenfolge sichtbar, Sortierung/Filter
(Aufnahmezeit per eigenem EXIF-Parser, da im Prod-Container ohne exif-Modul), ziehbare
Spaltenbreite, Kachelgroesse, Drag & Drop auf Seitenliste/Arbeitsflaeche/Raster-Plaetze.

Arbeitstisch zeigt jetzt Kopf-, Inhalts- und Fussbereich passend zur echten Seitengeometrie
(bericht_page_geometry()) - Editor und PDF-Erzeugung rechnen mit denselben Werten, das PDF
setzt die Arbeitsflaeche 1:1 statt sie ein zweites Mal einzupassen.

Neu: Bild einer Seite austauschen (auch einzelne Raster-Plaetze), Seiten mehrfach markieren
und sammeln loeschen/duplizieren, Autosave mit Verlassen-Warnung, Tastenkuerzel, kein
location.reload() mehr nach Hinzufuegen/Loeschen/Hochladen (ajax/fragments.php).

Nebenbei behoben: dol_dir_list() ohne mode=1 (Dateigroesse leer), PDF.js-Worker-Pfad ohne
/custom-Praefix, PDFs liefen als Download statt inline, Groessen-Select blieb leer,
Mehrfach-Upload nahm nur die erste Datei, Race-Condition bei schnellem Seitenwechsel.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 00:33:20 +02:00

55 lines
2.6 KiB
PHP

<?php
/* Liefert eine verkleinerte Vorschau (Thumbnail) einer Anhang-Datei.
*
* GET: relpath Pfad relativ zu DOL_DATA_ROOT (wie in bericht_collect_attachments)
* w Maximale Kantenlaenge in Pixel (Default 260, max 800)
*
* Nur Bilder (jpeg/png/gif/webp). PDFs werden clientseitig per PDF.js gerendert,
* weil im Prod-Container weder Imagick noch eine garantierte shell_exec-Freigabe
* zur Verfuegung steht.
*
* Thumbnails werden in DOL_DATA_ROOT/bericht/thumbs/ zwischengespeichert und ueber
* die mtime der Quelldatei invalidiert.
*/
$res = 0;
if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1;
while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; }
if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php";
if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php";
if (!$res) die("Include of main fails");
require_once __DIR__.'/../lib/bericht.lib.php';
if (!$user->hasRight('bericht', 'read')) accessforbidden();
$relpath = GETPOST('relpath', 'alpha');
// GETPOST 'alpha' wuerde Slashes behalten, aber Umlaute/Leerzeichen in Dateinamen
// killen - deshalb den Rohwert nehmen und selbst absichern.
if (isset($_GET['relpath'])) $relpath = $_GET['relpath'];
$maxside = GETPOSTINT('w');
if ($maxside <= 0) $maxside = 260;
if ($maxside > 800) $maxside = 800;
if ($relpath === '' || strpos($relpath, "\0") !== false) { http_response_code(400); exit; }
$full = bericht_resolve_data_path($relpath);
if (!$full || !is_file($full)) { http_response_code(404); exit; }
$thumb = bericht_attachment_thumb($full, $maxside);
if ($thumb === null) { http_response_code(415); exit; }
// Bedingtes GET: spart bei 40 Kacheln jede Menge Traffic
$etag = '"'.md5($full.'|'.filemtime($full).'|'.$maxside).'"';
header('ETag: '.$etag);
header('Cache-Control: private, max-age=86400');
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && trim($_SERVER['HTTP_IF_NONE_MATCH']) === $etag) {
http_response_code(304);
exit;
}
header('Content-Type: image/jpeg');
header('Content-Length: '.strlen($thumb));
echo $thumb;