* 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 _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;