.app-version-badge{position:fixed;right:12px;bottom:12px;z-index:2147483000;font-size:12px;font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:#0f172a;background:rgba(248,250,252,.85);border:1px solid rgba(148,163,184,.6);border-radius:999px;padding:4px 10px;box-shadow:0 8px 20px rgba(15,23,42,.15);backdrop-filter:blur(6px);} @media print {.app-version-badge{display:none}} HTML; } } if (!defined('APP_VERSION_BADGE_REGISTERED')) { register_shutdown_function('render_app_version_badge'); define('APP_VERSION_BADGE_REGISTERED', true); } // ----------------------------------------------------------- // set cookie / session parameters // ----------------------------------------------------------- if (!defined('CUSTOM_PREFIX')) { define('CUSTOM_PREFIX', APP_PREFIX); } if(!defined('APP_COOKIE_PREFIX')) { if(APP_ENV==="staging"){ define('APP_COOKIE_PREFIX', APP_PREFIX.'_stg'.'_'); } else { define('APP_COOKIE_PREFIX', APP_PREFIX.'_'); } } if (!defined('APP_COOKIE_DOMAIN')) { // Fallback: aktuelle Domain des Hosts define('APP_COOKIE_DOMAIN', '.'.APP_DOMAIN_PRIMARY); define('APP_PRIMARY_DOMAIN', APP_DOMAIN_PRIMARY); } if (!defined('APP_CLIENT_COOKIE_LIFETIME')) { define('APP_CLIENT_COOKIE_LIFETIME', 365 * 24 * 60 * 60); // 1 Jahr } // Einheitliche Cookie-Namen (projektübergreifend steuerbar) $sessionCookieName = APP_COOKIE_PREFIX . 'session'; $clientCookieName = APP_COOKIE_PREFIX . 'client'; // ----------------------------------------------------------- // 1) PHP-Session starten // ----------------------------------------------------------- if (php_sapi_name() !== 'cli') { if (session_status() === PHP_SESSION_NONE) { session_name($sessionCookieName); session_set_cookie_params([ 'lifetime' => 0, 'path' => '/', 'domain' => APP_COOKIE_DOMAIN ?: '', 'secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'), 'httponly' => true, 'samesite' => 'Lax', ]); session_start(); } } // ----------------------------------------------------------- // 2) Persistente Client-ID (für Tracking über Besuche hinweg) // ----------------------------------------------------------- if (php_sapi_name() !== 'cli') { $clientId = $_COOKIE[$clientCookieName] ?? null; // Erwartet wird: 64 Hex-Zeichen (32 Bytes) if ( !is_string($clientId) || $clientId === '' || !preg_match('/^[a-f0-9]{64}$/', $clientId) ) { // neue ID erzeugen try { $clientId = bin2hex(random_bytes(32)); // 32 bytes → 64 hex } catch (Throwable $e) { $clientId = bin2hex(openssl_random_pseudo_bytes(32)); } $cookieOpts = [ 'expires' => time() + APP_CLIENT_COOKIE_LIFETIME, 'path' => '/', 'secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'), 'httponly' => false, // JS darf es lesen, wenn erwünscht 'samesite' => 'Lax', ]; if (!empty(APP_COOKIE_DOMAIN)) { $cookieOpts['domain'] = APP_COOKIE_DOMAIN; } setcookie($clientCookieName, $clientId, $cookieOpts); $_COOKIE[$clientCookieName] = $clientId; } // global verfügbar machen (NEUER NAME!) $GLOBALS['cookie_client_id'] = $clientId; } // ----------------------------------------------------------- // 3) Sprachlogik laden (bleibt sinnvoll zentral) // ----------------------------------------------------------- require_once __DIR__ . '/i18n.php'; // ----------------------------------------------------------- // 4) Rest des Systems laden (DB, Funktionen, Hilfs-Libs) // ----------------------------------------------------------- require_once __DIR__ . "/db.php"; //require_once __DIR__ . '/../src/functions.php';