diff --git a/index.php b/index.php index fe3c6d9..5b91226 100644 --- a/index.php +++ b/index.php @@ -2,20 +2,23 @@ declare(strict_types=1); // -------------------- CONSTANTES -------------------- -const CACHE_DIR = '/var/cache/homepage'; -const INSTANCES_JSON = CACHE_DIR . '/instances.json'; -const URLS_TXT = CACHE_DIR . '/urls.txt'; -const INSTANCES_URL = 'https://searx.space/data/instances.json'; -const CACHE_MAX_AGE = 3600; // 1 heure -const BANG_FILE = __DIR__ . '/bang.json'; +const CACHE_DIR = '/var/cache/homepage'; +const INSTANCES_JSON = CACHE_DIR . '/instances.json'; +const URLS_TXT = __DIR__ . '/urls.txt'; // ← Hors du cache, à la racine +const INSTANCES_URL = 'https://searx.space/data/instances.json'; +const CACHE_MAX_AGE = 3600; // 1 heure +const BANG_FILE = __DIR__ . '/bang.json'; +const USE_SEARX_INSTANCES = true; // false → utilise engines.txt // -------------------- HEADERS DE SÉCURITÉ -------------------- header('X-Frame-Options: SAMEORIGIN'); header('X-Content-Type-Options: nosniff'); header('Referrer-Policy: no-referrer-when-downgrade'); header("Content-Security-Policy: default-src 'none'; frame-ancestors 'none'; sandbox"); +header('X-Search-Mode: ' . (USE_SEARX_INSTANCES ? 'searx' : 'engines')); // ← Point 6 // -------------------- CLASSES -------------------- + class CacheManager { private array $urlsCache = []; @@ -109,22 +112,58 @@ class BangManager } } -class RequestHandler +class EngineManager +{ + private static ?array $cachedEngines = null; + private array $engines = []; + + public function __construct(private string $file = __DIR__ . '/engines.txt') + { + if (self::$cachedEngines === null) { + $this->loadEngines(); + self::$cachedEngines = $this->engines; + } else { + $this->engines = self::$cachedEngines; + } + } + + private function loadEngines(): void + { + if (!file_exists($this->file)) { + throw new RuntimeException("Fichier engines.txt introuvable"); + } + $lines = file($this->file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + $this->engines = array_filter($lines, fn($line) => !empty(trim($line))); + } + + public function getRandomEngine(): string + { + if (empty($this->engines)) { + throw new RuntimeException("Aucun moteur de recherche configuré dans engines.txt"); + } + return $this->engines[array_rand($this->engines)]; + } +} + +class SearxHandler { public function __construct(private CacheManager $cache, private BangManager $bang) {} - public function handle(): void { + public function handle(): void + { $method = $_SERVER['REQUEST_METHOD'] ?? 'GET'; $query = $_REQUEST['q'] ?? null; if ($query !== null && !$this->bang->tryRedirect($query)) { $instance = rtrim($this->cache->getRandomUrl(), '/'); + $url = $instance . '/search?' . http_build_query(['q' => $query]); if ($method === 'GET') { - $this->redirectGet($instance, $query); + header("Location: $url"); + exit; } elseif ($method === 'POST') { - $this->redirectGet($instance, $query); - // $this->proxyPost($instance, $_POST); + header("Location: $url"); // Redirige en GET pour simplifier + exit; } else { http_response_code(405); exit('Méthode non autorisée'); @@ -135,57 +174,80 @@ class RequestHandler header("Location: $instance"); exit; } elseif ($method === 'POST') { - $this->proxyPost($instance, $_POST); + header("Location: $instance"); + exit; } else { http_response_code(405); exit('Méthode non autorisée'); } } } +} - private function redirectGet(string $instance, string $query): void { - $url = $instance . '/search?' . http_build_query(['q' => $query]); - header("Location: $url"); - exit; - } +class EngineHandler +{ + public function __construct(private EngineManager $engineManager, private BangManager $bang) {} - private function proxyPost(string $urlBase, array $postData): void { - $url = $urlBase . '/search'; - $ch = curl_init($url); - curl_setopt_array($ch, [ - CURLOPT_RETURNTRANSFER => true, - CURLOPT_POST => true, - CURLOPT_POSTFIELDS => http_build_query($postData), - CURLOPT_HEADER => false, - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_TIMEOUT => 10, - CURLOPT_SSL_VERIFYPEER => true, - ]); - $response = curl_exec($ch); - $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - curl_close($ch); + public function handle(): void + { + $method = $_SERVER['REQUEST_METHOD'] ?? 'GET'; + $query = $_REQUEST['q'] ?? null; - http_response_code($code); - echo $response; - exit; + if ($query !== null && !$this->bang->tryRedirect($query)) { + $engineTemplate = $this->engineManager->getRandomEngine(); + $url = sprintf($engineTemplate, rawurlencode($query)); + + if ($method === 'GET') { + header("Location: $url"); + exit; + } elseif ($method === 'POST') { + header("Location: $url"); // Redirige en GET + exit; + } else { + http_response_code(405); + exit('Méthode non autorisée'); + } + } elseif ($query === null) { + // Rediriger vers la page d'accueil du premier moteur + $engineTemplate = $this->engineManager->getRandomEngine(); + $homepage = str_replace('?query=%s', '', str_replace('?q=%s', '', $engineTemplate)); + if ($method === 'GET') { + header("Location: $homepage"); + exit; + } elseif ($method === 'POST') { + header("Location: $homepage"); + exit; + } else { + http_response_code(405); + exit('Méthode non autorisée'); + } + } } } // -------------------- EXECUTION -------------------- try { - $cache = new CacheManager(); - if ($cache->isExpired()) { - if (!$cache->downloadInstances() || !$cache->extractValidUrls()) { - http_response_code(500); - exit('Erreur interne : impossible de générer le cache.'); + $bang = new BangManager(); + $engineManager = new EngineManager(); + + if (USE_SEARX_INSTANCES) { + $cache = new CacheManager(); + if ($cache->isExpired()) { + if (!$cache->downloadInstances() || !$cache->extractValidUrls()) { + http_response_code(500); + exit('Erreur interne : veuillez réessayer plus tard.'); + } } + $handler = new SearxHandler($cache, $bang); + } else { + $handler = new EngineHandler($engineManager, $bang); } - $bang = new BangManager(); - $handler = new RequestHandler($cache, $bang); $handler->handle(); } catch (\Throwable $e) { + // Ne pas exposer les détails techniques → Point 3 + error_log('Erreur interne : ' . $e->getMessage() . ' | Trace: ' . $e->getTraceAsString()); http_response_code(500); - exit('Erreur interne : ' . $e->getMessage()); -} + exit('Erreur interne : veuillez réessayer plus tard.'); +} \ No newline at end of file