<?php
/**************************************************************************
                   
                     Sivas-CMS 
                Copyright ©
                    Sivas-CMS
                    Selim Güney
            37154 Northeim
                 email: cem27_m@yahoo.de



**************************************************************************/

defined('SIVAS_ENTRY') or define('SIVAS_ENTRY', true);
include_once("includes/__configuration.inc.php");
require_once("includes/menu_builder.class.php");
require_once("includes/index_controller.class.php");

// Webserver-agnostischer URL-Rewrite-Fallback (greift nur wenn Apache/.htaccess nicht bereits gemappt hat)
if (empty($_GET['page']) && empty($_GET['pageid'])) {
    $_uriMatch = \Sivas\Core\UrlRewriter::resolve($_SERVER['REQUEST_URI'] ?? '');
    if ($_uriMatch !== null && empty($_uriMatch['_entrypoint'])) {
        foreach ($_uriMatch as $_k => $_v) {
            if ($_k[0] !== '_' && !isset($_GET[$_k])) $_GET[$_k] = $_v;
        }
    }
    unset($_uriMatch, $_k, $_v);
}

// OV-only: Gäste sehen auf der Startseite die moderne Landing-Seite (statt CMS-Homepage).
// Eingeloggte Nutzer + konkrete Seiten/Aktionen laufen normal weiter.
if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'GET'
    && empty($_GET['page']) && empty($_GET['pageid'])
    && empty($_GET['cc_action']) && empty($_GET['logmsg']) && empty($_GET['logout'])
    && (int)($_SESSION[$ssPrefix]['userid'] ?? 0) === 0) {
    require __DIR__ . '/landing.php';
    exit();
}

// OV-only: eingeloggte Nutzer sehen auf der nackten Startseite NICHT die alte CMS-Homepage,
// sondern landen auf ihrer Startseite (OV-Dashboard, login_startpage). Konkrete Seiten/Aktionen laufen normal weiter.
if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'GET'
    && empty($_GET['page']) && empty($_GET['pageid'])
    && empty($_GET['cc_action']) && empty($_GET['logmsg']) && empty($_GET['logout'])
    && (int)($_SESSION[$ssPrefix]['userid'] ?? 0) > 0) {
    $ovStart = preg_replace('/[\r\n]+/', '', trim((string)($configinfo['login_startpage'] ?? '')));
    if ($ovStart === '') $ovStart = 'index.php?page=objektverwaltung.php&ovp=dashboard&p=dashboard';
    header('Location: ' . $ovStart);
    exit();
}

$NO_RIGHT = 0;
$NO_LEFT  = 0;

// WEG-Magic-Session: externe Eigentümer NIEMALS durch das CMS-Template laufen lassen.
// (Sicherheit + UX: kein Wartungs-Modus-Block, keine CMS-Tracker/-Module, keine WAF-Konflikte.)
// Siehe Memory feedback_sivas_eig_portal_standalone.
if (!empty($_SESSION['sivascms_eig_portal_eig_id'] ?? null)
    && (int)($_SESSION[$ssPrefix]['userid'] ?? 0) === 0
    && $_SERVER['REQUEST_URI'] !== '/eigentuemer-portal.php'
    && $_SERVER['REQUEST_URI'] !== '/eigentuemer-login.php'
    // Die Anwendung liegt seit 2026-08-15 unter /app/ (vorher admin/objektverwaltung).
    // Ohne diese Ausnahmen landet ein angemeldeter Eigentuemer beim Laden der Anwendung in
    // der Weiterleitung aufs Portal und die Seite bleibt ohne Skripte und Stile zurueck.
    && strpos($_SERVER['REQUEST_URI'] ?? '', '/app/api.php') !== 0
    && strpos($_SERVER['REQUEST_URI'] ?? '', '/app/js/') !== 0
    && strpos($_SERVER['REQUEST_URI'] ?? '', '/app/css/') !== 0
) {
    header('Location: /eigentuemer-portal.php');
    exit;
}

// OV-only: alte CMS-/Community-Seiten komplett sperren. Erlaubt sind NUR die OV-Produktseiten;
// jede andere page=/pageid= (mail/forum/member/vz/video/register/kontakt/oveditor/… = alter CMS-Rest)
// → Dashboard (eingeloggt) bzw. Landing (Gast). Standalone-Seiten (landing/tarife/ov-legal/kuendigung/
// kontakt-public/…) laufen über eigene Dateien und sind nicht betroffen.
$ovReqPage = (string)($_GET['page'] ?? '');
if ($ovReqPage !== '' || !empty($_GET['pageid'])) {
    $ovAllowed = ['objektverwaltung.php', 'anmelden.php', 'user_login.php', 'user_logout.php', 'error.php'];
    if (!in_array($ovReqPage, $ovAllowed, true)) {
        if ((int)($_SESSION[$ssPrefix]['userid'] ?? 0) > 0) {
            $ovTo = preg_replace('/[\r\n]+/', '', trim((string)($configinfo['login_startpage'] ?? '')));
            if ($ovTo === '') $ovTo = 'index.php?page=objektverwaltung.php&ovp=dashboard&p=dashboard';
            header('Location: ' . $ovTo);
        } else {
            header('Location: /landing.php');
        }
        exit();
    }
}

$ctrl = new IndexController(
    $db, $ssPrefix, $configinfo, $styleinfo, $style_tpl_url, $baseurl
);

// ── IP-Blacklist ──────────────────────────────────────────────────────────────
$Ip_block = $ctrl->isIpBlocked($_SERVER['REMOTE_ADDR'] ?? '');

// Admins/Mods (status >= 2) sind nie gesperrt
if (intval($_SESSION[$ssPrefix]['status'] ?? -1) >= 2) {
    $Ip_block = false;
}

// Defaults für das früh evaluierte site_offline-Template (es nutzt $title/$pagemetadesc/
// $pagemetakey/$JavaScript, die erst ab ~Z.104 gesetzt werden). Verhindert
// "Undefined variable"-Warnings bei gesperrter IP / Portal-Offline. Wird im Normalfluss
// später ohnehin überschrieben → keine Verhaltensänderung.
$title        = $title ?? '';
$pagemetadesc = $pagemetadesc ?? '';
$pagemetakey  = $pagemetakey ?? '';
$JavaScript   = $JavaScript ?? '';

// ── Portal offline / IP gesperrt ─────────────────────────────────────────────
if (($configinfo['portal_offline'] == '1' && intval($_SESSION[$ssPrefix]['status'] ?? -1) <= 2)
    || $Ip_block === true
) {
    $offline_message = $parsing->parscontent($configinfo['portal_offline_msg']);

    if ($Ip_block && intval($_REQUEST['admin'] ?? 0) == 0) {
        // Echter HTTP-403 statt stiller 200 — sonst taucht ein IP-Block nirgends im
        // Access-Log als Fehler auf (das hat die Diagnose der Selbst-Aussperrung massiv
        // erschwert: Nutzer sah die Sperrseite, im Log stand überall 200).
        if (!headers_sent()) http_response_code(403);
        $site_offline = '<center><p>' . $lang['stop']
            . '<img src="images/dur.jpg" alt="' . htmlspecialchars($lang['stop'], ENT_QUOTES) . '" /></p></center>';
    } else {
        $site_offline = '';
        $site_offline = renderTemplate('site_offline', get_defined_vars(), '');
    }

    // Im Offline-Modus nur Login erlauben
    $page = $ctrl->getSecurePage();
    if ($page === 'user_login.php') {
        include($page);
    }

    echo $site_offline;
    exit;
}

// ── Cookie-Consent Reset (kein JS, reiner GET-Link im Footer) ────────────────
if (isset($_GET['cc_action']) && $_GET['cc_action'] === 'reset') {
    CookieConsent::reset();
    $proto = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
    header('Location: ' . $proto . '://' . $_SERVER['HTTP_HOST'] . '/index.php');
    exit;
}

parsertime('start');

$menuBuilder = new MenuBuilder(
    $db,
    intval($_SESSION[$ssPrefix]['status'] ?? -1),
    $_SESSION[$ssPrefix]['userid'] ?? '',
    $style_tpl_url
);
$menu_bottom = $menuBuilder->buildBottom();

// ── Referer-Logging ───────────────────────────────────────────────────────────
if (!empty($thisSivasCms['referer'])) {
    $ctrl->logReferer($thisSivasCms['referer']);
}

// ── Bot-Erkennung (fix: stripos statt strpos>0) ───────────────────────────────
$useragent = $_SERVER['HTTP_USER_AGENT'] ?? '';
$bot       = $ctrl->isBot($useragent) ? 1 : 0;

if ($bot && session_status() === PHP_SESSION_NONE) {
    ini_set('session.use_trans_sid', 0);
}

// ── JavaScript-Includes ───────────────────────────────────────────────────────
$JavaScript  = "<script src=\"{$baseurl}js/main.js?v=20260302c\" type=\"text/javascript\"></script>\n";
$JavaScript .= "<script src=\"{$baseurl}js/fenster.js?v=20260302\" type=\"text/javascript\"></script>\n";
// Globaler Office-Editor-Modal-Interceptor: faengt Klicks auf editierbare Office-Files
// in /uploads/objektverwaltung/{userFolder}/ ab und oeffnet sie im Modal-Overlay.
$_ovModalVer = @filemtime(__DIR__ . '/editor-modal.js') ?: time();
$JavaScript .= "<script src=\"{$baseurl}editor-modal.js?v={$_ovModalVer}\" type=\"text/javascript\" defer></script>\n";

// ── Seiten-Routing (sicher validiert) ─────────────────────────────────────────
$page    = $ctrl->getSecurePage();
$EXT_PAGE = '';

// ── Mandanten-Isolation (OV-SaaS) ─────────────────────────────────────────────
// Eingeloggte Kunden/Team-Mitglieder (Session-Status < 2 = keine Admins/Mods) dürfen über
// index.php?page=… NUR OV-/Konto-/Rechts-/Auth-Seiten erreichen. Die alten Community-/
// Nutzer-Seiten (Mitgliedersuche, Nutzer-Karte, fremde Galerien, Gästebuch …) sind tabu —
// sonst könnte ein Kunde andere Kunden sehen. Deny-by-default → zurück aufs OV-Dashboard.
// Operator/Mods (Status >= 2) sind ausgenommen, ebenso direkte Datei-Aufrufe ohne index.php.
if ($page !== '' && intval($_SESSION[$ssPrefix]['status'] ?? -1) < 2) {
    $ovAllowedPages = [
        // OV-Produkt
        'objektverwaltung.php', 'objektverwaltung_api.php',
        'eigentuemer-portal.php', 'eigentuemer-login.php',
        'oveditor.php', 'office-editor.php', 'editor.php', 'editor_api.php',
        // Öffentliche / Konto- / Rechts- / Auth-Seiten
        'landing.php', 'anmelden.php', 'tarife.php', 'ov-register.php', 'beitritt.php',
        'ov-legal.php', 'impressum.php', 'datenschutz.php', 'disclaimer.php',
        'kuendigung.php', 'kontakt-public.php',
        'user_login.php', 'user_logout.php', 'pw_recover.php', 'twofactor_qr.php',
        'editprofil.php', 'theme_set.php', 'cookie_consent_save.php', 'secure_code.php', 'error.php',
    ];
    if (!in_array($page, $ovAllowedPages, true)) {
        $ovLoggedIn = intval($_SESSION[$ssPrefix]['userid'] ?? 0) > 0;
        header('Location: ' . ($ovLoggedIn ? '/index.php?page=objektverwaltung.php' : '/'));
        exit;
    }
}

if ($page !== '') {
    $index_body = $index_body ?? '';
    if (filecheck($page)) {
        include($page);
    } else {
        $NO_ALL     = 1;
        $index_body = '<center><img src="images/error_pages/error_404.jpg" alt="Seite nicht gefunden" /></center>';
    }
}

// ── Navigation / Startseite laden ─────────────────────────────────────────────
$pageid       = 0;
$pagerefer    = '';
$templateid   = 0;
$title        = '';
$pagemetakey  = '';
$pagemetadesc = '';

if (isset($_REQUEST['pageid']) && intval($_REQUEST['pageid']) > 0 && $page === '') {

    $pageid = intval($_REQUEST['pageid']);
    $ctrl->loadNavPoints($pageid, 1);

    $data = $db->one(
        "SELECT parentid, pagerefer, templateid, page_title, page_meta_key, page_meta_desc "
        . "FROM {$db->prefix}navigation WHERE id=? LIMIT 1",
        [$pageid]
    );
    if (!empty($data)) {
        $data_parentid = $db->one(
            "SELECT templateid FROM {$db->prefix}navigation WHERE parentid=0 AND id=? LIMIT 1",
            [intval($data['parentid'])]
        );
        $templateid   = intval($data_parentid['templateid'] ?? 0);
        $pagerefer    = $data['pagerefer'];
        $title        = $data['page_title'];
        $pagemetakey  = $data['page_meta_key'];
        $pagemetadesc = $data['page_meta_desc'];
    }

    $bot ? $ctrl->trackBot() : $ctrl->trackVisit($pageid);

} elseif ($page === '') {

    $data = $db->one(
        "SELECT id, pagerefer, templateid, page_title, page_meta_key, page_meta_desc "
        . "FROM {$db->prefix}navigation WHERE startseite=1 LIMIT 1",
        []
    );
    if (!empty($data)) {
        $pagerefer    = $data['pagerefer'];
        $templateid   = intval($data['templateid']);
        $pageid       = intval($data['id']);
        $title        = $data['page_title'];
        $pagemetakey  = $data['page_meta_key'];
        $pagemetadesc = $data['page_meta_desc'];
    }

    $bot ? $ctrl->trackBot() : $ctrl->trackVisit(0);
}

// ── Startseite: Cats/Module laden ─────────────────────────────────────────────
if ((!isset($_REQUEST['pageid']) || intval($_REQUEST['pageid']) == 0) && $page === '') {
    $userStatus    = intval($_SESSION[$ssPrefix]['status'] ?? -1);
    $start_results = $db->all(
        "SELECT templateid, data_include, grouprights FROM {$db->prefix}cats "
        . "WHERE publik=1 AND data_include!='' AND pagerefer='' AND startseite=1 "
        . "AND rights<=? ORDER BY pos, titel",
        [$userStatus]
    );

    foreach ($start_results as $res_start) {
        $data_include_start = $res_start['data_include'];
        $temp   = explode('&', $data_include_start);
        $anzahl = count($temp);

        if ($data_include_start !== ''
            && is_readable($temp[0])
            && $data_include_start !== 'index.php'
        ) {
            $MODUL_USERGROUP_RIGHTS = new CUsergroup;
            if ($MODUL_USERGROUP_RIGHTS->get_usergroup(
                $_SESSION[$ssPrefix]['userid'] ?? '',
                $res_start['grouprights']
            )) {
                if ($anzahl == 2) {
                    $temp_param = explode('=', $temp[1]);
                    if (count($temp_param) == 2) {
                        $_REQUEST[$temp_param[0]] = $temp_param[1];
                    }
                }
                include($temp[0]);
            }
        }
        $templateid = intval($res_start['templateid']);
    }
}

// ── Umleitung — nur relative oder eigene Domain erlaubt ──────────────────────
if (!empty($pagerefer)) {
    if (preg_match('#^https?://#i', $pagerefer)) {
        $rHost = parse_url($pagerefer, PHP_URL_HOST);
        $myHost = parse_url($configinfo['baseurl'] ?? '', PHP_URL_HOST);
        if ($rHost !== $myHost) {
            $pagerefer = ''; // Externe Redirects blockieren (Open-Redirect-Schutz)
        }
    }
    if ($pagerefer !== '') {
        header('Location: ' . $pagerefer);
        exit;
    }
}

// ── Login- / Logout-Meldungen ─────────────────────────────────────────────────
$logmsg    = intval($_REQUEST['logmsg']   ?? 0);
$logoutmsg = trim($_REQUEST['logoutmsg'] ?? '');
$msglogin  = '';

// Login-Fehlermeldungen (Codes 30–34 → login_user-Template)
$loginMsgs = [
    30 => 'Ihr Account ist nicht Aktiviert ! <br />'
        . 'Sie haben Ihren Account nicht Aktiviert — nach dem Registrieren bekommen Sie '
        . 'ein Aktivierungslink an Ihre Email-Adresse zugesendet. <br />'
        . 'Wenn Sie kein Aktivierungs-Email bekommen haben, klicken Sie hier: '
        . '<a href="index.php?page=aktiv.php">Aktivierungs-Mail anfordern</a>',
    31 => 'Bitte überprüfe deine E-Mail-Adresse oder dein Passwort ist falsch.',
    32 => $lang['login_errormsg']  ?? '',
    33 => $lang['login_relogmsg1'] ?? '',
    34 => $lang['login_relogmsg']  ?? '',
];
$useTwig = class_exists('Sivas\\Core\\TwigEngine');

if (isset($loginMsgs[$logmsg])) {
    $msglogin = $loginMsgs[$logmsg];
    $index_body = $useTwig
        ? \Sivas\Core\TwigEngine::render('login_user.twig', ['msglogin' => $msglogin])
        : renderTemplate('login_user', ['msglogin' => $msglogin]);
}

// Session-Ereignisse (Codes 35–37 → event_msg-Template)
$eventMsgs = [
    35 => 'Ihre Session ist nicht mehr gültig! <br /> Loggen Sie sich bitte wieder neu ein!',
    36 => 'Ihre Session wurde wegen zu langer Inaktivität gelöscht!',
    37 => 'Ihre alte Session wurde neu generiert!',
];
if (isset($eventMsgs[$logmsg])) {
    $event_msg = $eventMsgs[$logmsg];
    $index_body = $useTwig
        ? \Sivas\Core\TwigEngine::render('event_msg_nobacklink.twig', ['event_msg' => $event_msg, 'get_link' => $get_link ?? ''])
        : renderTemplate('event_msg_nobacklink', ['event_msg' => $event_msg]);
}

if ($logoutmsg === '31') {
    $index_body = $useTwig
        ? \Sivas\Core\TwigEngine::render('logout_user.twig', [])
        : renderTemplate('logout_user', []);
}
if ($logoutmsg === 'del') {
    $delete_msg = 'Ihr Account wurde erfolgreich gelöscht';
    $index_body = $useTwig
        ? \Sivas\Core\TwigEngine::render('logout_user.twig', ['delete_msg' => $delete_msg])
        : renderTemplate('logout_user', ['delete_msg' => $delete_msg]);
}

// ── Offline-Info-Banner ───────────────────────────────────────────────────────
$offlineInfo = $configinfo['portal_offline'] == '1'
    ? '<div style="width:500px;margin:auto;"><blockquote>'
        . '<p>Information</p><p>Sie befinden sich derzeit im Offline Modus</p>'
        . '</blockquote></div>'
    : '';

// ── Session-URL Update ────────────────────────────────────────────────────────
$ctrl->updateSessionUrl();

// ── Mail-Counter & Login-Box ──────────────────────────────────────────────────
$goright        = $configinfo['right_nav_active'];
$goleft         = $configinfo['left_nav_active'];
$NEWMAILS       = '';
$NEWMAIL_TICKER = '';

$userid = $_SESSION[$ssPrefix]['userid'] ?? '';
if ($userid !== '' && intval($_SESSION[$ssPrefix]['status'] ?? -1) >= 0) {
    $MY_NICK  = htmlentities($_SESSION[$ssPrefix]['nick'] ?? '');
    $mailInfo = $ctrl->getMailInfo($userid);
    $NEWMAILS       = $mailInfo['text'];
    $NEWMAIL_TICKER = $mailInfo['ticker'];

    $setLastLogin = '';
    if (empty($tmpLastLogin)) {
        $getLastLogin = $db->one(
            "SELECT last_login FROM {$db->prefix}user WHERE userid=? LIMIT 1",
            [intval($userid)]
        );
        if (!empty($getLastLogin['last_login']) && $getLastLogin['last_login'] > '0') {
            $tmpLastLogin = formattime($getLastLogin['last_login'], 'datetime');
            $setLastLogin = $lang['index_Besuch'] . $tmpLastLogin . ' <br />';
        }
    }

    $login_oben = renderTemplate("$style_tpl_url/index_mail", get_defined_vars(), '');
}

// ── Menü oben ─────────────────────────────────────────────────────────────────
$menu_top = $menuBuilder->buildTop();

// ── Navigation: globale Wrapper-Funktionen delegieren an $ctrl ────────────────
// (Aufruf aus Seiten-Skripten; Templates enthalten keinen Code mehr)
function loadnavigation(int $pid, int $tmpebene): void
{
    global $ctrl;
    $ctrl->loadNavigation($pid, $tmpebene);
}
function loadnavigation_prim(int $pid, int $tmpebene): void
{
    global $ctrl;
    $ctrl->loadNavPrim($pid, $tmpebene);
}
function loadseknavigation(int $pid, int $tmpebene): void
{
    global $ctrl;
    $ctrl->loadNavSek($pid, $tmpebene);
}
function load_navpoints(int $tmpmenu, int $tmp): void
{
    global $ctrl;
    $ctrl->loadNavPoints($tmpmenu, $tmp);
}

// ── Naviboxen laden ───────────────────────────────────────────────────────────
for ($i = 0; $i < 10; $i++) {
    $cbnr = $i;

    $template = $db->one(
        "SELECT cmsbox{$i} AS boxtyp FROM {$db->prefix}templates WHERE publik=1 AND id=?",
        [intval($templateid)]
    );
    if (empty($template)) {
        continue;
    }

    $cmsboxtyp = intval($template['boxtyp']);
    $module    = $db->one(
        "SELECT fileoutput FROM {$db->prefix}module WHERE id=?",
        [$cmsboxtyp]
    );
    if (empty($module)) {
        continue;
    }

    $file = $ctrl->safeNaviboxFile($module['fileoutput']);
    if ($file !== '' && ($page === '' || $cbnr == 8)) {
        include($file);
    }
}

// ── Mobil / Desktop Layout ────────────────────────────────────────────────────
$isMobile = (bool) preg_match('/iPhone|Android|BlackBerry/i', $useragent);

if ($isMobile) {
    $conten_w = intval($styleinfo['style_breite']) - 10;
    unset($loadleftnav, $loadrightnav);
} else {
    $conten_w = intval($styleinfo['style_breite']);

    if ($NO_RIGHT == 1) {
        $conten_w -= intval($styleinfo['navi_breite']);
    } else {
        unset($loadrightnav);
    }

    if ($NO_LEFT == 1) {
        $conten_w -= intval($styleinfo['navi_breite']);
    } else {
        unset($loadleftnav);
    }

    if ((isset($NO_ALL) && $NO_ALL == 1)
        || (!empty($_SESSION[$ssPrefix]['NO_ALL']))
    ) {
        $_SESSION[$ssPrefix]['NO_ALL'] = 0;
        $conten_w = intval($styleinfo['style_breite']) - 7;
        unset($loadleftnav, $loadrightnav);
    }
}

// Modern/Atelier nutzen Flex-Layout — kein float/width override nötig.
if (isset($style_tpl_url) && in_array($style_tpl_url, ['style/modern', 'style/atelier'], true)) {
    $style_w = '';
} else {
    $style_w = ".art-contentLayout .art-content {
    position: relative; margin: 0; padding: 0; border: 0;
    float: left; overflow: hidden; width: {$conten_w}px;
}";
}

$pos_w     = $isMobile ? $conten_w - 10 : $conten_w - 210;
$posting_w = "#show_posting { width: {$pos_w}px; }";

$ladezeit = parsertime('stop');
$currentYear = date('Y');

// ── Template-Variablen absichern ──────────────────────────────────────────────
$meta_title     = $meta_title     ?? '';
$login_oben     = $login_oben     ?? '';
$loadleftnav    = $loadleftnav    ?? '';
$loadrightnav   = $loadrightnav   ?? '';
$loadcontentnav = $loadcontentnav ?? '';
$loadbottomnav  = $loadbottomnav  ?? '';
$index_body     = $index_body     ?? '';
$titele         = $titele         ?? '';
$meta_tags_Fb   = $meta_tags_Fb   ?? '';
$index          = '';
$videoinfo      = $videoinfo ?? [
    'video_keywords' => '', 'video_titel' => '', 'video_descr' => '',
    'gamekeywords'   => '', 'gametitle'   => '', 'gamedesc'    => '',
];

// ── Templates rendern ─────────────────────────────────────────────────────────
$index_kopf    = renderTemplate("$style_tpl_url/index_kopf", get_defined_vars(), '');
$index_fuss    = renderTemplate("$style_tpl_url/index_fuss", get_defined_vars(), '');
$index_content = renderTemplate("$style_tpl_url/index_body", get_defined_vars(), '');

// ── URL-Rewriting (dedupliziert über IndexController::applyUrlRewrite) ────────
if (!empty($configinfo['url_rewrite'])) {
    $index_kopf    = $ctrl->applyUrlRewrite($index_kopf);
    $index_fuss    = $ctrl->applyUrlRewrite($index_fuss);
    $index_content = $ctrl->applyUrlRewrite($index_content);
}

// ── Cookie-Banner (EU DSGVO) ──────────────────────────────────────────────────
$cookie_banner_class       = CookieConsent::needed() ? '' : 'cc-hidden';
$cookie_functional_checked = CookieConsent::allowed('functional') ? 'checked' : '';
$cookie_statistics_checked = CookieConsent::allowed('statistics') ? 'checked' : '';
$cookie_redirect_url       = $baseurl . ltrim($_SERVER['REQUEST_URI'] ?? '/', '/');
$cookie_banner = '';
if (class_exists('Sivas\\Core\\TwigEngine')) {
    $cookie_banner = \Sivas\Core\TwigEngine::render('cookie_banner.twig', [
        'cookie_banner_class'       => $cookie_banner_class,
        'baseurl'                   => $baseurl,
        'cookie_redirect_url'       => $cookie_redirect_url,
        'cookie_functional_checked' => $cookie_functional_checked,
        'cookie_statistics_checked' => $cookie_statistics_checked,
    ]);
} else {
    $cookie_banner = renderTemplate("$style_tpl_url/cookie_banner", get_defined_vars(), '');
}

// ── Ausgabe ───────────────────────────────────────────────────────────────────
$index .= renderTemplate("$style_tpl_url/index", get_defined_vars(), '');
echo $index;

// ── Session-URL (finale Ablage für Zurück-Navigation) ────────────────────────
// Login-/Logout-Seiten NICHT als Rücksprungziel merken — sonst schickt
// redirectAfterLogin() nach erfolgreichem Login wieder auf die Login-Seite
// → Endlos-Login-Loop (Fix 2026-06-16).
$reqUriForReturn = $_SERVER['REQUEST_URI'] ?? '';
if (stripos($reqUriForReturn, 'user_login.php') === false
    && stripos($reqUriForReturn, 'user_logout.php') === false) {
    $_SESSION[$ssPrefix]['url'] = $baseurl . $reqUriForReturn;
}
