<?php

/*
ET-Chat Copyright by SEDesign | ET-Chat v3.x.x Lizenz: CCPL | Autor: Evgeni Tcherkasski (info@s-e-d.de)
ET-Chat_T-FISH-MOD Weiterentwicklungen, Optimierungen und Ergänzungen am Code sind das geistige Eigentum von Tommy (Thomas Kuhn) und Harlekin (Bernd Witte).

Die darauf folgende Optimierungen und Ergänzungen am Code sind das Geistige Eigentum von Powermen (Christian K.) 
PHP 8/9 Ready, XML Parser, PDO Prepared Statements Get Set sicherheit usw.
*/

class IndexBox extends DbConectionMaker
{
    public $lang = [];
    public int $aktuell_date_u;
    
    private string $iframeDomainFile = 'cache/loginbox.txt';
    private array $allowedDomains = [];
    private string $chatTitle = '';
    private bool $isIframeRequest = false;
    
    // Flag für Iframe-Modus (wird an Template übergeben)
    public bool $iframeMode = false;

    public function __construct()
    {
        parent::__construct();

        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }

        if (!headers_sent()) {
            header('Content-Type: text/html; charset=utf-8');
        }
        
        // Iframe-Request erkennen und Titel auslesen
        $this->detectIframeRequest();
        
        // Bei Iframe-Request: Domain prüfen
        if ($this->isIframeRequest) {
            $this->iframeMode = true;
            $this->loadAllowedDomains();
            $this->validateReferer();
        }

        // Cookie sicher setzen
        setcookie(
            $this->_prefix . "cookie_test",
            (string) time(),
            [
                'expires'  => time() + 3600,
                'path'     => '/',
                'secure'   => ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || ($_SERVER['SERVER_PORT'] ?? 80) == 443),
                'httponly' => true,
                'samesite' => 'Lax'
            ]
        );

        $this->configTabData2Session();

        $this->runCleanupIfDue();

        $this->aktuell_date_u = time();
        $_SESSION[$this->_prefix . 'set_check'] = hash('sha256', (string) $this->aktuell_date_u);

        $this->loadLanguage();

        $this->initTemplate();
    }
    
    /**
     * Erkennt ob die Seite als Iframe aufgerufen wird und holt den Titel
     */
    private function detectIframeRequest(): void
    {
        // Prüfen ob Parameter 'IndexBox' gesetzt ist
        if (isset($_GET['IndexBox'])) {
            $this->isIframeRequest = true;
            
            // Titel aus GET-Parameter
            if (isset($_GET['titel']) && !empty(trim($_GET['titel']))) {
                $this->chatTitle = $this->sanitize(trim($_GET['titel']));
            }
        }
    }
    
    /**
     * Lädt die erlaubten Domains aus der Konfigurationsdatei
     */
    private function loadAllowedDomains(): void
    {
        $file = __DIR__ . '/../' . $this->iframeDomainFile;
        
        // Wenn Datei nicht existiert, erstelle eine Beispiel-Datei
        if (!is_file($file)) {
            $demo = "# Erlaubte Domains für Iframe-Einbindung\n";
            $demo .= "# Eine Domain pro Zeile\n";
            $demo .= "# Subdomains werden automatisch erlaubt\n\n";
            $demo .= "example.com\n";
            $demo .= "localhost\n";
            $demo .= "127.0.0.1\n";
            file_put_contents($file, $demo, LOCK_EX);
            $this->allowedDomains = ['localhost', '127.0.0.1'];
            return;
        }
        
        $lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        foreach ($lines as $line) {
            $line = trim($line);
            // Kommentare überspringen
            if (str_starts_with($line, '#')) {
                continue;
            }
            $cleanDomain = preg_replace('/[^a-zA-Z0-9\.\-]/', '', $line);
            if (!empty($cleanDomain)) {
                $this->allowedDomains[] = strtolower($cleanDomain);
            }
        }
    }
    
    /**
     * Validiert den HTTP_REFERER gegen die Whitelist
     */
    private function validateReferer(): void
    {
        $referer = $_SERVER['HTTP_REFERER'] ?? '';
        
        // Wenn kein Referer (direkter Aufruf) -> erlauben für Test
        if (empty($referer)) {
            return;
        }
        
        $host = strtolower(parse_url($referer, PHP_URL_HOST));
        $host = preg_replace('/^www\./', '', $host);
        
        $isAllowed = false;
        foreach ($this->allowedDomains as $allowed) {
            // Exakter Match oder Subdomain
            if ($host === $allowed || str_ends_with($host, '.' . $allowed)) {
                $isAllowed = true;
                break;
            }
        }
        
        if (!$isAllowed) {
            $this->showError('Zugriff verweigert', 
                'Die Domain <strong>' . htmlspecialchars($host) . '</strong> ist nicht für die Einbindung autorisiert.');
            exit;
        }
    }
    
    /**
     * Zeigt eine Fehlerseite an
     */
    private function showError(string $title, string $message): void
    {
        echo '<!DOCTYPE html>
        <html>
        <head>
            <meta charset="utf-8">
            <title>' . htmlspecialchars($title) . '</title>
            <style>
                body {
                    background: #1a1a2e;
                    margin: 0;
                    padding: 20px;
                    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    min-height: 100vh;
                }
                .error-box {
                    background: #16213e;
                    padding: 30px;
                    border-radius: 12px;
                    text-align: center;
                    max-width: 400px;
                }
                .error-box h3 {
                    color: #e94560;
                    margin: 0 0 15px 0;
                }
                .error-box p {
                    color: #ccc;
                    margin: 0;
                }
            </style>
        </head>
        <body>
            <div class="error-box">
                <h3>' . htmlspecialchars($title) . '</h3>
                <p>' . $message . '</p>
            </div>
        </body>
        </html>';
        exit;
    }
    
    /**
     * Bereinigt einen String für HTML-Ausgabe
     */
    private function sanitize(string $input): string
    {
        return htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8');
    }
    
    /**
     * Gibt den Chat-Titel zurück (für Template)
     */
    public function getChatTitle(): string
    {
        return $this->chatTitle;
    }
    
    /**
     * Prüft ob Iframe-Request
     */
    public function isIframe(): bool
    {
        return $this->isIframeRequest;
    }

    private function runCleanupTasks(): void
    {
        $deleteDays = (int) ($_SESSION['etchat_' . $this->_prefix . 'loeschen_nach'] ?? 30);

        $messageExpireTime = time() - ($deleteDays * 86400);
        $guestExpireTime    = time() - ($deleteDays * 86400 * 2);
        $currentTime        = time();

        $this->dbObj->sqlSet(
            "DELETE FROM {$this->_prefix}etchat_messages WHERE etchat_timestamp < :ts",
            [':ts' => $messageExpireTime]
        );

        $this->dbObj->sqlSet(
            "DELETE FROM {$this->_prefix}etchat_blacklist WHERE etchat_blacklist_time < :t",
            [':t' => $currentTime]
        );

        $this->dbObj->sqlSet(
            "DELETE FROM {$this->_prefix}etchat_kick_user WHERE etchat_kicked_user_time < :t",
            [':t' => $currentTime]
        );

        $this->dbObj->sqlSet(
            "DELETE FROM {$this->_prefix}etchat_user
             WHERE etchat_userprivilegien = 'gast'
             AND etchat_logintime < :gt",
            [':gt' => $guestExpireTime]
        );
    }

    private function loadLanguage(): void
    {
        try {
            $langObj = new LangXml();
            $langData = $langObj->getLang();
            $this->lang = $langData->index_php[0] ?? [];
        } catch (Throwable $e) {
            error_log("Language load error: " . $e->getMessage());
            $this->lang = [];
        }
    }

	private function initTemplate(): void
	{
		$style = preg_replace('/[^a-zA-Z0-9_\-]/', '', $_SESSION['etchat_' . $this->_prefix . 'style'] ?? 'default');
		$templatePath = "styles/{$style}/index-box.tpl.html";

		if (is_file($templatePath)) {
			// Mache die benötigten Variablen für das Template verfügbar
			$chatTitle = $this->chatTitle;
			$iframeMode = $this->iframeMode;
			$isIframeRequest = $this->isIframeRequest;
        
			include_once $templatePath;
		} else {
			error_log("Template not found: " . $templatePath);
		}
	}

    private function monthlyMaintenance(): void
    {
        if ((int) date('d') !== 31) {
            return;
        }

        try {
            $this->dbObj->sqlSet("SET @a = 0");
            $this->dbObj->sqlSet("UPDATE {$this->_prefix}etchat_messages SET etchat_id = (@a := @a + 1)");
            $this->dbObj->sqlSet("ALTER TABLE {$this->_prefix}etchat_messages AUTO_INCREMENT = 1");
            
            $this->dbObj->sqlSet("OPTIMIZE TABLE {$this->_prefix}etchat_messages");
            
        } catch (Throwable $e) {
            error_log("Monthly maintenance error: " . $e->getMessage());
        }
    }

    private function runCleanupIfDue(): void
    {
        $interval = 3600;
        $file = __DIR__ . '/../cache/cleanup_last_run.txt';

        $lastRun = is_file($file) ? (int) file_get_contents($file) : 0;

        if (time() - $lastRun >= $interval) {
            $this->runCleanupTasks();
            // $this->monthlyMaintenance(); //Aktivieren wenn man an jeden 31 eines Monats also 5 mal im Jahr die ID der Messages zurücksetzen will
            file_put_contents($file, (string) time(), LOCK_EX);
        }
    }
}