<?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 Filesend extends DbConectionMaker
{
    public function __construct()
    {
        parent::__construct();

        if (session_status() === PHP_SESSION_NONE) {
            session_start();
        }

        header('Cache-Control: no-store, no-cache, must-revalidate');
        header('Content-Type: text/html; charset=utf-8');

        if (!isset($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
            die('Kein Upload erkannt.');
        }

        if ($_FILES['file']['size'] > 5 * 1024 * 1024) {
            die('Datei zu groß.');
        }

        if (!is_uploaded_file($_FILES['file']['tmp_name'])) {
            die('Ungültiger Upload.');
        }

        $filedir = dirname(__DIR__) . '/userpic/';

        if (!is_dir($filedir)) {
            mkdir($filedir, 0755, true);
        }

        // MIME prüfen
        $finfo = new finfo(FILEINFO_MIME_TYPE);
        $mime = $finfo->file($_FILES['file']['tmp_name']);

        $allowedMime = [
            'image/jpeg' => 'jpg',
            'image/png'  => 'png',
            'image/gif'  => 'gif'
        ];

        if (!isset($allowedMime[$mime])) {
            die('Dateityp nicht erlaubt.');
        }

        // extra Bildprüfung
        if (@getimagesize($_FILES['file']['tmp_name']) === false) {
            die('Ungültiges Bild.');
        }

        $extension = $allowedMime[$mime];

        $newname = bin2hex(random_bytes(8)) . '_' . time() . '.' . $extension;

        $targetPath = $filedir . $newname;

        if (!move_uploaded_file($_FILES['file']['tmp_name'], $targetPath)) {
            die('Upload fehlgeschlagen.');
        }

        // GIF Limit
        if ($mime === 'image/gif' && filesize($targetPath) > 1500000) {
            unlink($targetPath);
            die('GIF zu groß. Max 1.5MB');
        }

        // Bilder optimieren
        if ($mime === 'image/jpeg' || $mime === 'image/png') {

            $this->resizeImageIfTooLarge($targetPath);
            $this->compressImageToTargetSize($targetPath);
        }

        $username = $_SESSION['etchat_' . $this->_prefix . 'username'] ?? 'Unbekannt';

        $datum = date('d.m.Y H:i');

        file_put_contents(
            $targetPath . '.txt',
            $username . '|' . $datum . '|' . ($_SERVER['REMOTE_ADDR'] ?? '0.0.0.0')
        );

        $baseUrl = rtrim(dirname($_SERVER['PHP_SELF']), '/\\') . '/userpic/';

        $imgurl = $baseUrl . $newname;

        $messageText = '';

        if (!empty($_POST['bildtext'])) {
            $messageText = htmlspecialchars($_POST['bildtext'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . ' ';
        }

        $messageText .= '[img]' . $imgurl . '[/img]';

        // CSS sicher filtern
        $textcolor = substr($_POST['textcolor'] ?? '', 0, 7);
        $textbold  = substr($_POST['textbold'] ?? '', 0, 6);
        $textitalic= substr($_POST['textitalic'] ?? '', 0, 6);

        $fontstyle = "color:$textcolor;font-weight:$textbold;font-style:$textitalic;";

        $userId = (int)($_SESSION['etchat_' . $this->_prefix . 'user_id'] ?? 0);
        $roomId = (int)($_POST['raum'] ?? 0);
        $privat = (int)($_POST['privat'] ?? 0);
        $ip     = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';

        $sql = "
            INSERT INTO {$this->_prefix}etchat_messages
            (etchat_user_fid, etchat_text, etchat_text_css, etchat_timestamp,
             etchat_fid_room, etchat_privat, etchat_user_ip)
            VALUES
            (?, ?, ?, ?, ?, ?, ?)
        ";

        $this->dbObj->sqlSet($sql, [
            $userId,
            $messageText,
            $fontstyle,
            time(),
            $roomId,
            $privat,
            $ip
        ]);

        $this->cleanupOldFiles($filedir);
    }

    private function cleanupOldFiles(string $dir): void
    {
        $maxAge = 7 * 24 * 3600;
        $now = time();

        foreach (glob($dir . '*.{jpg,png,gif,txt}', GLOB_BRACE) as $file) {

            if (is_file($file) && ($now - filemtime($file) > $maxAge)) {
                unlink($file);
            }
        }
    }

    private function resizeImageIfTooLarge(string $sourcePath, int $maxWidth = 1600, int $maxHeight = 900): void
    {
        $info = @getimagesize($sourcePath);
        if (!$info) return;

        [$width, $height, $type] = $info;

        if ($width <= $maxWidth && $height <= $maxHeight) return;

        $ratio = min($maxWidth / $width, $maxHeight / $height);

        $newWidth  = (int)($width * $ratio);
        $newHeight = (int)($height * $ratio);

        $src = ($type === IMAGETYPE_JPEG)
            ? imagecreatefromjpeg($sourcePath)
            : imagecreatefrompng($sourcePath);

        if (!$src) return;

        $dst = imagecreatetruecolor($newWidth, $newHeight);

        imagecopyresampled($dst, $src, 0,0,0,0,$newWidth,$newHeight,$width,$height);

        if ($type === IMAGETYPE_JPEG) {
            imagejpeg($dst, $sourcePath, 85);
        } else {
            imagepng($dst, $sourcePath, 6);
        }

        imagedestroy($src);
        imagedestroy($dst);
    }

    private function compressImageToTargetSize(string $sourcePath, int $maxSizeBytes = 1500000): void
    {
        $info = @getimagesize($sourcePath);
        if (!$info || $info['mime'] !== 'image/jpeg') return;

        $image = imagecreatefromjpeg($sourcePath);
        if (!$image) return;

        $quality = 85;

        do {

            ob_start();
            imagejpeg($image, null, $quality);
            $data = ob_get_clean();

            $size = strlen($data);

            $quality -= 5;

        } while ($size > $maxSizeBytes && $quality >= 40);

        file_put_contents($sourcePath, $data);

        imagedestroy($image);
    }
}