<?php
/*
|--------------------------------------------------------------------------
| RadyoHost.BiZ / Profesyonel Radyo Hosting ve Web Tasarım Hizmetleri
|--------------------------------------------------------------------------
*/

/*
|--------------------------------------------------------------------------
| Okey Platformu / Premium Okey ve Sohbet Platformu
|--------------------------------------------------------------------------
*/

/*
|--------------------------------------------------------------------------
| Okey Platformu / Premium Okey Tanıtım ve Üyelik Sistemi
|--------------------------------------------------------------------------
*/

/*
|--------------------------------------------------------------------------
| GÜVENLİK KORUMA DOSYASI
|--------------------------------------------------------------------------
| security.php
| Okey Platformu Güvenlik, CSRF, Upload, Session ve Request Koruma Modülü
| Developed By VoLKaN75
|--------------------------------------------------------------------------
*/

declare(strict_types=1);

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

function security_headers(): void
{
    if (headers_sent()) {
        return;
    }

    header('X-Frame-Options: SAMEORIGIN');
    header('X-Content-Type-Options: nosniff');
    header('Referrer-Policy: strict-origin-when-cross-origin');
    header('X-XSS-Protection: 1; mode=block');
    header('Permissions-Policy: geolocation=(), microphone=(), camera=()');

    if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') {
        header('Strict-Transport-Security: max-age=31536000; includeSubDomains; preload');
    }
}

security_headers();

function security_db(): ?PDO
{
    global $db, $pdo;

    if (isset($db) && $db instanceof PDO) {
        return $db;
    }

    if (isset($pdo) && $pdo instanceof PDO) {
        return $pdo;
    }

    return null;
}

function security_log_write(string $message, array $context = []): void
{
    $dir = __DIR__ . '/../logs/';

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

    $line = '[' . date('Y-m-d H:i:s') . '] '
        . $message
        . ' | IP: ' . ($_SERVER['REMOTE_ADDR'] ?? '0.0.0.0')
        . ' | URL: ' . ($_SERVER['REQUEST_URI'] ?? '')
        . ' | METHOD: ' . ($_SERVER['REQUEST_METHOD'] ?? '')
        . (!empty($context) ? ' | DATA: ' . json_encode($context, JSON_UNESCAPED_UNICODE) : '')
        . PHP_EOL;

    @file_put_contents($dir . 'security-' . date('Y-m-d') . '.log', $line, FILE_APPEND | LOCK_EX);
}

function security_e($value): string
{
    return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

if (!function_exists('e')) {
    function e($value): string
    {
        return security_e($value);
    }
}

function security_clean_text($value, int $limit = 255): string
{
    $value = trim(strip_tags((string)$value));

    if (function_exists('mb_substr')) {
        return mb_substr($value, 0, $limit, 'UTF-8');
    }

    return substr($value, 0, $limit);
}

function security_clean_array(array $data): array
{
    foreach ($data as $key => $value) {
        $data[$key] = is_array($value)
            ? security_clean_array($value)
            : security_clean_text($value, 1000);
    }

    return $data;
}

function security_int($value, int $default = 0): int
{
    return filter_var($value, FILTER_VALIDATE_INT) !== false ? (int)$value : $default;
}

function security_email(string $email): bool
{
    return (bool)filter_var($email, FILTER_VALIDATE_EMAIL);
}

function security_url(string $url): bool
{
    return (bool)filter_var($url, FILTER_VALIDATE_URL);
}

function security_session_init(): void
{
    if (empty($_SESSION['_sec_started'])) {
        $_SESSION['_sec_started'] = time();
        $_SESSION['_sec_ip'] = $_SERVER['REMOTE_ADDR'] ?? '';
        $_SESSION['_sec_agent'] = $_SERVER['HTTP_USER_AGENT'] ?? '';
        $_SESSION['_sec_last_activity'] = time();
        $_SESSION['_sec_regenerated'] = time();

        if (session_status() === PHP_SESSION_ACTIVE) {
            session_regenerate_id(true);
        }
    }

    $timeout = 60 * 60 * 3;

    if (!empty($_SESSION['_sec_last_activity']) && (time() - (int)$_SESSION['_sec_last_activity']) > $timeout) {
        security_log_write('Session timeout oldu.');
        security_destroy_session();
        return;
    }

    $_SESSION['_sec_last_activity'] = time();

    if ((time() - (int)($_SESSION['_sec_regenerated'] ?? 0)) > 900) {
        session_regenerate_id(true);
        $_SESSION['_sec_regenerated'] = time();
    }
}

function security_destroy_session(): void
{
    $_SESSION = [];

    if (ini_get('session.use_cookies')) {
        $params = session_get_cookie_params();

        setcookie(
            session_name(),
            '',
            [
                'expires' => time() - 42000,
                'path' => $params['path'] ?? '/',
                'domain' => $params['domain'] ?? '',
                'secure' => (bool)($params['secure'] ?? false),
                'httponly' => true,
                'samesite' => $params['samesite'] ?? 'Lax',
            ]
        );
    }

    if (session_status() === PHP_SESSION_ACTIVE) {
        session_destroy();
    }
}

security_session_init();

function security_csrf_token(): string
{
    if (empty($_SESSION['_security_csrf'])) {
        $_SESSION['_security_csrf'] = bin2hex(random_bytes(32));
    }

    return (string)$_SESSION['_security_csrf'];
}

function security_csrf_field(): string
{
    return '<input type="hidden" name="_csrf_token" value="' . security_e(security_csrf_token()) . '">';
}

function security_verify_csrf(?string $token = null): bool
{
    $token = $token ?: ($_POST['_csrf_token'] ?? '');

    return !empty($_SESSION['_security_csrf']) && hash_equals((string)$_SESSION['_security_csrf'], (string)$token);
}

function security_require_csrf(?string $token = null): void
{
    if (!security_verify_csrf($token)) {
        security_log_write('CSRF doğrulaması başarısız.');
        http_response_code(419);
        exit('Güvenlik doğrulaması başarısız.');
    }
}

if (!function_exists('csrf_token')) {
    function csrf_token(): string
    {
        return security_csrf_token();
    }
}

if (!function_exists('csrf_field')) {
    function csrf_field(): string
    {
        return security_csrf_field();
    }
}

if (!function_exists('csrf_check')) {
    function csrf_check(): void
    {
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
            security_require_csrf();
        }
    }
}

function security_require_method(string $method): void
{
    $current = strtoupper($_SERVER['REQUEST_METHOD'] ?? 'GET');

    if ($current !== strtoupper($method)) {
        security_log_write('Geçersiz request method.', [
            'expected' => strtoupper($method),
            'current' => $current,
        ]);

        http_response_code(405);
        exit('Method not allowed.');
    }
}

function security_post_only(): void
{
    security_require_method('POST');
}

function security_get_only(): void
{
    security_require_method('GET');
}

function security_attempt_key(string $key): string
{
    $ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';

    return '_sec_attempt_' . md5($key . '_' . $ip);
}

function security_attempt_allowed(string $key, int $max = 8, int $seconds = 900): bool
{
    $sessionKey = security_attempt_key($key);

    if (empty($_SESSION[$sessionKey])) {
        return true;
    }

    $data = $_SESSION[$sessionKey];

    if ((time() - (int)($data['time'] ?? 0)) > $seconds) {
        unset($_SESSION[$sessionKey]);
        return true;
    }

    return (int)($data['count'] ?? 0) < $max;
}

function security_attempt_add(string $key): void
{
    $sessionKey = security_attempt_key($key);

    if (empty($_SESSION[$sessionKey])) {
        $_SESSION[$sessionKey] = [
            'count' => 1,
            'time' => time(),
        ];
        return;
    }

    $_SESSION[$sessionKey]['count'] = (int)$_SESSION[$sessionKey]['count'] + 1;

    security_log_write('Giriş denemesi kaydedildi.', [
        'key' => $key,
        'count' => $_SESSION[$sessionKey]['count'],
    ]);
}

function security_attempt_clear(string $key): void
{
    unset($_SESSION[security_attempt_key($key)]);
}

function security_ip(): string
{
    return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}

function security_is_ip_blocked(?string $ip = null): bool
{
    $ip = $ip ?: security_ip();

    $file = __DIR__ . '/../storage/blocked_ips.txt';

    if (!is_file($file)) {
        return false;
    }

    $ips = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

    return in_array($ip, $ips ?: [], true);
}

function security_block_ip(?string $ip = null): bool
{
    $ip = $ip ?: security_ip();

    $dir = __DIR__ . '/../storage/';

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

    $file = $dir . 'blocked_ips.txt';

    if (security_is_ip_blocked($ip)) {
        return true;
    }

    security_log_write('IP blacklist eklendi.', ['ip' => $ip]);

    return @file_put_contents($file, $ip . PHP_EOL, FILE_APPEND | LOCK_EX) !== false;
}

function security_check_ip_block(): void
{
    if (security_is_ip_blocked()) {
        security_log_write('Blacklist IP erişimi engellendi.');
        http_response_code(403);
        exit('Erişim engellendi.');
    }
}

security_check_ip_block();

function security_request_is_suspicious(): bool
{
    $uri = strtolower((string)($_SERVER['REQUEST_URI'] ?? ''));
    $query = strtolower((string)($_SERVER['QUERY_STRING'] ?? ''));

    $patterns = [
        '../',
        '..\\',
        '<script',
        'union select',
        'information_schema',
        'base64_decode',
        'eval(',
        'sleep(',
        'benchmark(',
        'cmd=',
        'shell',
        'globals',
        '_server',
    ];

    foreach ($patterns as $pattern) {
        if (str_contains($uri, strtolower($pattern)) || str_contains($query, strtolower($pattern))) {
            return true;
        }
    }

    return false;
}

function security_check_request(): void
{
    if (security_request_is_suspicious()) {
        security_log_write('Şüpheli request engellendi.');
        http_response_code(403);
        exit('Güvenlik nedeniyle işlem engellendi.');
    }
}

security_check_request();

function security_file_mime(string $tmpFile): string
{
    if (!is_file($tmpFile)) {
        return '';
    }

    if (function_exists('finfo_open')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);

        if ($finfo) {
            $mime = finfo_file($finfo, $tmpFile);
            finfo_close($finfo);

            return (string)$mime;
        }
    }

    return (string)mime_content_type($tmpFile);
}

function security_upload_allowed(array $file, array $allowedMime = [], int $maxSize = 5242880): bool
{
    if (empty($file['tmp_name']) || !is_uploaded_file($file['tmp_name'])) {
        security_log_write('Upload dosyası geçersiz.');
        return false;
    }

    if (($file['size'] ?? 0) > $maxSize) {
        security_log_write('Upload boyutu büyük.', ['size' => $file['size'] ?? 0]);
        return false;
    }

    $allowedMime = $allowedMime ?: [
        'image/jpeg' => 'jpg',
        'image/png' => 'png',
        'image/webp' => 'webp',
        'image/gif' => 'gif',
        'application/pdf' => 'pdf',
    ];

    $mime = security_file_mime((string)$file['tmp_name']);

    if (!isset($allowedMime[$mime])) {
        security_log_write('Geçersiz upload mime.', ['mime' => $mime]);
        return false;
    }

    return true;
}

function security_safe_upload_name(string $originalName, string $prefix = 'file'): string
{
    $ext = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
    $ext = preg_replace('/[^a-z0-9]/', '', $ext);

    return $prefix . '-' . date('YmdHis') . '-' . bin2hex(random_bytes(6)) . ($ext ? '.' . $ext : '');
}

function security_password_strong(string $password): bool
{
    if (strlen($password) < 8) {
        return false;
    }

    if (!preg_match('/[A-Z]/', $password)) {
        return false;
    }

    if (!preg_match('/[a-z]/', $password)) {
        return false;
    }

    if (!preg_match('/[0-9]/', $password)) {
        return false;
    }

    return true;
}

function security_token(int $length = 32): string
{
    return bin2hex(random_bytes(max(8, (int)ceil($length / 2))));
}

function security_json(bool $success, string $message = '', array $data = [], int $status = 200): void
{
    if (!headers_sent()) {
        http_response_code($status);
        header('Content-Type: application/json; charset=utf-8');
    }

    echo json_encode([
        'success' => $success,
        'message' => $message,
        'data' => $data,
        'status' => $status,
    ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

    exit;
}

function security_honeypot_field(): string
{
    return '<input type="text" name="website_url" value="" autocomplete="off" tabindex="-1" style="position:absolute;left:-9999px;opacity:0;height:0;width:0;">';
}

function security_check_honeypot(): bool
{
    return empty($_POST['website_url']);
}

function security_is_bot(): bool
{
    $agent = strtolower($_SERVER['HTTP_USER_AGENT'] ?? '');

    $bots = [
        'bot',
        'crawl',
        'spider',
        'slurp',
        'curl',
        'wget',
        'python-requests',
    ];

    foreach ($bots as $bot) {
        if (str_contains($agent, $bot)) {
            return true;
        }
    }

    return false;
}

if (!function_exists('securityLog')) {
    function securityLog(string $message): void
    {
        security_log_write($message);
    }
}