diff --git a/api/photo.php b/api/photo.php index 36e1f8a..f80f4c7 100644 --- a/api/photo.php +++ b/api/photo.php @@ -10,40 +10,96 @@ * relpath — relativer Pfad unter DOL_DATA_ROOT * size=small|mini (optional, nutzt automatisch das Thumb) */ -require_once __DIR__.'/_inc.php'; +// Dieser Endpoint liefert Binärdaten aus — KEIN JSON Content-Type! +// Deshalb nicht _inc.php direkt nutzen, sondern JWT + Dolibarr manuell laden. +if (!defined('NOLOGIN')) define('NOLOGIN', '1'); +if (!defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); +if (!defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); +if (!defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); +if (!defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); +if (!defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); -api_authenticate(); -global $db, $user; +$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__.'/_jwt.php'; +require_once __DIR__.'/../lib/bericht.lib.php'; + +// Support Token via Header ODER Query-String (für ohne Header) +$token_str = ''; +$hdr = $_SERVER['HTTP_AUTHORIZATION'] ?? ''; +if ($hdr && stripos($hdr, 'bearer ') === 0) $token_str = trim(substr($hdr, 7)); +if (!$token_str && !empty($_GET['jwt'])) $token_str = (string) $_GET['jwt']; + +$payload = $token_str ? bericht_jwt_decode($token_str) : null; +if (!$payload || empty($payload['sub'])) { + http_response_code(401); + header('Content-Type: text/plain'); + echo 'Token ungültig oder fehlt'; + exit; +} + +require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; +$u = new User($db); +if ($u->fetch((int) $payload['sub']) <= 0 || empty($u->statut)) { + http_response_code(401); + header('Content-Type: text/plain'); + echo 'User ungültig'; + exit; +} +$u->loadRights(); +if (!$u->hasRight('bericht', 'read')) { + http_response_code(403); + header('Content-Type: text/plain'); + echo 'Permission denied'; + exit; +} +$user = $u; $relpath = (string) ($_GET['relpath'] ?? ''); $size = (string) ($_GET['size'] ?? ''); -if (empty($relpath)) api_fail('relpath fehlt'); +if (empty($relpath)) { + http_response_code(400); + header('Content-Type: text/plain'); + echo 'relpath fehlt'; + exit; +} // Whitelist if (!preg_match('#^(facture|commande|propal|bericht)/#', $relpath)) { - api_fail('Pfad nicht erlaubt', 403); + http_response_code(403); + header('Content-Type: text/plain'); + echo 'Pfad nicht erlaubt: '.$relpath; + exit; } $full = bericht_resolve_data_path($relpath); -if (!$full || !file_exists($full)) api_fail('Datei nicht gefunden', 404); +if (!$full || !file_exists($full)) { + http_response_code(404); + header('Content-Type: text/plain'); + echo 'Datei nicht gefunden: '.$relpath; + exit; +} -// Thumb-Variante (kleiner, schneller) +// Thumb-Variante 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; - } + 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');