fix: photo.php eigener Init ohne _inc.php JSON-Header
All checks were successful
Deploy bericht / deploy (push) Successful in 1s
All checks were successful
Deploy bericht / deploy (push) Successful in 1s
_inc.php setzt standardmäßig Content-Type: application/json — das hat photo.php beim Bildversand blockiert (die Blob kam als JSON rein und der Browser konnte sie nicht als Bild darstellen). Jetzt lädt photo.php Dolibarr direkt, dekodiert JWT manuell (mit Query-Param-Support für Fallback ohne Header-Auth) und sendet NUR image/jpeg-Header beim Ausliefern. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> [deploy]
This commit is contained in:
parent
95701ed2d6
commit
606ffae1fe
1 changed files with 69 additions and 13 deletions
|
|
@ -10,40 +10,96 @@
|
||||||
* relpath — relativer Pfad unter DOL_DATA_ROOT
|
* relpath — relativer Pfad unter DOL_DATA_ROOT
|
||||||
* size=small|mini (optional, nutzt automatisch das Thumb)
|
* 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();
|
$res = 0;
|
||||||
global $db, $user;
|
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 <img src> 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'] ?? '');
|
$relpath = (string) ($_GET['relpath'] ?? '');
|
||||||
$size = (string) ($_GET['size'] ?? '');
|
$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
|
// Whitelist
|
||||||
if (!preg_match('#^(facture|commande|propal|bericht)/#', $relpath)) {
|
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);
|
$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') {
|
if ($size === 'small' || $size === 'mini') {
|
||||||
$dir = dirname($full);
|
$dir = dirname($full);
|
||||||
$base = pathinfo($full, PATHINFO_FILENAME);
|
$base = pathinfo($full, PATHINFO_FILENAME);
|
||||||
$ext = pathinfo($full, PATHINFO_EXTENSION);
|
$ext = pathinfo($full, PATHINFO_EXTENSION);
|
||||||
$thumb = $dir.'/thumbs/'.$base.'_'.$size.'.'.$ext;
|
$thumb = $dir.'/thumbs/'.$base.'_'.$size.'.'.$ext;
|
||||||
if (file_exists($thumb)) {
|
if (file_exists($thumb)) $full = $thumb;
|
||||||
$full = $thumb;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Content-Type aus mimetype
|
|
||||||
$mime = function_exists('dol_mimetype') ? dol_mimetype($full) : 'application/octet-stream';
|
$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-Type: '.$mime);
|
||||||
header('Content-Length: '.filesize($full));
|
header('Content-Length: '.filesize($full));
|
||||||
header('Cache-Control: private, max-age=3600');
|
header('Cache-Control: private, max-age=3600');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue