All checks were successful
Deploy bericht / deploy (push) Successful in 1s
Neuer Endpoint liefert Dateien aus DOL_DATA_ROOT aus, geschützt per JWT statt Dolibarr-Session. Whitelist auf facture/commande/propal/ bericht. Optional size=small/mini für Thumbs (Dolibarr _small Variante). CORS-Header damit PWA direkt zugreifen kann. Die PWA kann damit Anhang-Bilder in der Auftrags-Detail-Ansicht rendern — vorher nutzte sie document.php was nur mit Session ging und deshalb im Standalone-Mode leer blieb. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> [deploy]
52 lines
1.6 KiB
PHP
52 lines
1.6 KiB
PHP
<?php
|
|
/* GET /api/photo.php?relpath=<path>
|
|
* Liefert eine Datei aus DOL_DATA_ROOT aus, authentifiziert per JWT.
|
|
* Whitelist: nur facture/, commande/, propal/, bericht/
|
|
*
|
|
* Für den Thumb-Request der PWA werden auch Thumbnails ausgeliefert
|
|
* (Dolibarr legt <name>_small.png unter thumbs/ ab).
|
|
*
|
|
* Query:
|
|
* relpath — relativer Pfad unter DOL_DATA_ROOT
|
|
* size=small|mini (optional, nutzt automatisch das Thumb)
|
|
*/
|
|
require_once __DIR__.'/_inc.php';
|
|
|
|
api_authenticate();
|
|
global $db, $user;
|
|
|
|
$relpath = (string) ($_GET['relpath'] ?? '');
|
|
$size = (string) ($_GET['size'] ?? '');
|
|
|
|
if (empty($relpath)) api_fail('relpath fehlt');
|
|
|
|
// Whitelist
|
|
if (!preg_match('#^(facture|commande|propal|bericht)/#', $relpath)) {
|
|
api_fail('Pfad nicht erlaubt', 403);
|
|
}
|
|
|
|
$full = bericht_resolve_data_path($relpath);
|
|
if (!$full || !file_exists($full)) api_fail('Datei nicht gefunden', 404);
|
|
|
|
// Thumb-Variante (kleiner, schneller)
|
|
if ($size === 'small' || $size === 'mini') {
|
|
$dir = dirname($full);
|
|
$base = pathinfo($full, PATHINFO_FILENAME);
|
|
$ext = pathinfo($full, PATHINFO_EXTENSION);
|
|
$thumb = $dir.'/thumbs/'.$base.'_'.$size.'.'.$ext;
|
|
if (file_exists($thumb)) {
|
|
$full = $thumb;
|
|
}
|
|
}
|
|
|
|
// Content-Type aus mimetype
|
|
$mime = function_exists('dol_mimetype') ? dol_mimetype($full) : 'application/octet-stream';
|
|
|
|
// Binary ausliefern — header() ersetzt vorherigen JSON Content-Type
|
|
header_remove('Content-Type');
|
|
header('Content-Type: '.$mime);
|
|
header('Content-Length: '.filesize($full));
|
|
header('Cache-Control: private, max-age=3600');
|
|
header('Access-Control-Allow-Origin: *');
|
|
readfile($full);
|
|
exit;
|