<?php
namespace App;


final class Security
{
// رنج‌های رسمی تلگرام (در زمان نگارش). بهتره دوره‌ای آپدیت شوند.
private const CIDR = [
'149.154.160.0/20',
'91.108.4.0/22',
];


public static function verifyTelegram(string $method, array $server, Logger $logger): void
{
if ($method !== 'POST') self::fail('Method not allowed');


// 1) هدر مخفی وبهوک
$expected = Env::get('TELEGRAM_SECRET_TOKEN');
$given = $server['HTTP_X_TELEGRAM_BOT_API_SECRET_TOKEN'] ?? '';
if (!$expected || !hash_equals($expected, $given)) self::fail('Bad secret token');


// 2) تطبیق IP با CIDR تلگرام (اگر behind proxy هستید، X-Forwarded-For را با لیست امن استخراج کنید)
$ip = $server['REMOTE_ADDR'] ?? '0.0.0.0';
if (!self::ipInCidrs($ip, self::CIDR)) self::fail('IP not allowed: '.$ip);


// 3) ضد CSRF برای safety (اینجا کافی است چون فقط POST از Telegram می‌آید)
$ctype = $server['CONTENT_TYPE'] ?? '';
if (stripos($ctype, 'application/json') === false) self::fail('Bad content-type');


$logger->info('Webhook verified', ['ip'=>$ip]);
}


private static function fail(string $msg): void
{ http_response_code(403); echo 'Forbidden'; throw new \RuntimeException($msg); }


private static function ipInCidrs(string $ip, array $cidrs): bool
{
$ipl = ip2long($ip); if ($ipl === false) return false;
foreach ($cidrs as $cidr) {
[$subnet, $mask] = explode('/', $cidr, 2);
$mask = -1 << (32 - (int)$mask); $subnetl = ip2long($subnet);
if (($ipl & $mask) === ($subnetl & $mask)) return true;
}
return false;
}
}