From 2989ec10ed409fe05868946218e2f62930fee115 Mon Sep 17 00:00:00 2001 From: Eduard Wisch Date: Tue, 19 May 2026 12:49:15 +0200 Subject: [PATCH] =?UTF-8?q?Fix:=20master.inc.php=20im=20globalen=20Scope?= =?UTF-8?q?=20laden=20=E2=80=94=20behebt=20500=20beim=20Login=20[deploy]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit netdiag_api_bootstrap() includete master.inc.php innerhalb der Funktion. Dadurch landeten $conf/$db/$langs/$user im Funktions-Scope und waren nach return weg — der erste DB-Zugriff (checkLoginPassEntity -> global $db) lief gegen null: Call to a member function query() on null. master.inc.php wird jetzt im File-Scope der Lib geladen, die Funktion macht nur noch CORS + OPTIONS-Preflight. Co-Authored-By: Claude Opus 4.7 (1M context) --- api/netdiag_api.lib.php | 71 ++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/api/netdiag_api.lib.php b/api/netdiag_api.lib.php index 106acc0..d69af0b 100644 --- a/api/netdiag_api.lib.php +++ b/api/netdiag_api.lib.php @@ -47,42 +47,53 @@ if (!defined('NOREQUIRESOC')) { define('NOREQUIRESOC', '1'); } +// =================================================================== +// Dolibarr-Umgebung laden — MUSS im globalen Scope passieren. +// master.inc.php innerhalb einer Funktion zu includen würde $conf, +// $db, $langs, $user ... in den Funktions-Scope legen; nach return +// wären sie weg und jeder DB-Zugriff liefe gegen null -> HTTP 500. +// Dieser Block läuft, sobald ein Endpunkt die Lib per require_once +// einbindet, also im File-Scope des Endpunkts = global. +// =================================================================== +$res = 0; +$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))."/master.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/master.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/master.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/master.inc.php"; +} +if (!$res && file_exists("../../../master.inc.php")) { + $res = @include "../../../master.inc.php"; +} +if (!$res && file_exists("../../../../master.inc.php")) { + $res = @include "../../../../master.inc.php"; +} +if (!$res) { + header('Content-Type: application/json; charset=utf-8'); + http_response_code(500); + echo json_encode(array('error' => 'Dolibarr environment not found')); + exit; +} +unset($res, $tmp, $tmp2, $i, $j); + /** - * Dolibarr-Umgebung laden (master.inc.php) und CORS-Header setzen. + * CORS-Header setzen und Preflight (OPTIONS) sofort beantworten. + * + * Dolibarr selbst ist zu diesem Zeitpunkt bereits geladen (siehe Block + * oben, der beim require_once dieser Lib im globalen Scope läuft). * * @return void */ function netdiag_api_bootstrap() { - // master.inc.php aus dem Webroot finden - $res = 0; - $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))."/master.inc.php")) { - $res = @include substr($tmp, 0, ($i + 1))."/master.inc.php"; - } - if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/master.inc.php")) { - $res = @include dirname(substr($tmp, 0, ($i + 1)))."/master.inc.php"; - } - if (!$res && file_exists("../../../master.inc.php")) { - $res = @include "../../../master.inc.php"; - } - if (!$res && file_exists("../../../../master.inc.php")) { - $res = @include "../../../../master.inc.php"; - } - if (!$res) { - header('Content-Type: application/json; charset=utf-8'); - http_response_code(500); - echo json_encode(array('error' => 'Dolibarr environment not found')); - exit; - } - // CORS: Bearer-Token-Auth, daher Wildcard-Origin erlaubt (keine Cookies) header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST, OPTIONS');