From 253d390e12863bffa64e54c28ee3f86dcc8e70d2 Mon Sep 17 00:00:00 2001 From: cedric Date: Tue, 24 Jun 2025 13:39:47 +0200 Subject: [PATCH] First commit --- index.php | 291 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100644 index.php diff --git a/index.php b/index.php new file mode 100644 index 0000000..e4c420a --- /dev/null +++ b/index.php @@ -0,0 +1,291 @@ + CACHE_MAX_AGE; +} + +function download_instances_json(): bool +{ + $ch = curl_init(INSTANCES_URL); + curl_setopt_array($ch, [ + CURLOPT_RETURNTRANSFER => true, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_TIMEOUT => 10, + CURLOPT_SSL_VERIFYPEER => true, + ]); + $data = curl_exec($ch); + $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + if ($data === false) { + error_log('curl_exec failed: ' . curl_error($ch)); + } + curl_close($ch); + + if ($code === 200 && $data !== false) { + return safe_file_put_contents(INSTANCES_JSON, $data); + } + error_log("Erreur téléchargement instances.json, HTTP $code"); + return false; +} + +function extract_valid_urls(): bool +{ + if (!file_exists(INSTANCES_JSON)) { + error_log("instances.json introuvable"); + return false; + } + + $content = file_get_contents(INSTANCES_JSON); + if ($content === false) { + error_log("Impossible de lire instances.json"); + return false; + } + + $j = json_decode($content, true); + if (!isset($j['instances']) || !is_array($j['instances'])) { + error_log("JSON mal formé"); + return false; + } + + $valid = []; + foreach ($j['instances'] as $url => $data) { + if ( + ($data['network_type'] ?? '') === 'normal' + && ($data['http']['status_code'] ?? 0) === 200 + && ($data['timing']['search']['success_percentage'] ?? 0) === 100.0 + && ($data['timing']['initial']['success_percentage'] ?? 0) === 100.0 + && filter_var($url, FILTER_VALIDATE_URL) + && in_array(parse_url($url, PHP_URL_SCHEME), ['http', 'https'], true) + ) { + $valid[] = rtrim($url, '/'); + } + } + + if (empty($valid)) { + error_log("Aucune URL valide"); + return false; + } + + return safe_file_put_contents(URLS_TXT, implode("\n", $valid)); +} + +function safe_file_put_contents(string $filename, string $data): bool +{ + $fp = fopen($filename, 'c'); + if (!$fp) { + error_log("Impossible d'ouvrir $filename en écriture"); + return false; + } + if (!flock($fp, LOCK_EX)) { + fclose($fp); + error_log("Impossible de verrouiller $filename"); + return false; + } + ftruncate($fp, 0); + $written = fwrite($fp, $data); + fflush($fp); + flock($fp, LOCK_UN); + fclose($fp); + + return $written === strlen($data); +} + +function get_all_urls(): array +{ + if (!file_exists(URLS_TXT)) { + return []; + } + + $fp = fopen(URLS_TXT, 'r'); + if (!$fp) { + error_log("Impossible d'ouvrir urls.txt"); + return []; + } + + if (!flock($fp, LOCK_SH)) { + fclose($fp); + error_log("Impossible de verrouiller urls.txt en lecture"); + return []; + } + + $urls = []; + while (($line = fgets($fp)) !== false) { + $line = trim($line); + if ($line !== '' && filter_var($line, FILTER_VALIDATE_URL)) { + $urls[] = $line; + } + } + flock($fp, LOCK_UN); + fclose($fp); + + return $urls; +} + +function redirect_random_url(): void +{ + $urls = get_all_urls(); + if (empty($urls)) { + http_response_code(500); + exit('Instances indisponibles'); + } + $target = $urls[array_rand($urls)]; + header("Location: $target"); + exit; +} + +function redirect_search(string $query): void +{ + $urls = get_all_urls(); + if (empty($urls)) { + http_response_code(500); + exit('Instances indisponibles pour recherche'); + } + $base = $urls[array_rand($urls)]; + + $parsed = parse_url($base); + if ($parsed === false) { + error_log("Base URL invalide dans urls.txt"); + http_response_code(500); + exit('Erreur interne'); + } + + $path = $parsed['path'] ?? ''; + $path = rtrim($path, '/') . '/search'; + + $query_string = http_build_query(['q' => $query]); + + $target = $parsed['scheme'] . '://' . $parsed['host']; + if (isset($parsed['port'])) { + $target .= ':' . $parsed['port']; + } + $target .= $path . '?' . $query_string; + + header("Location: $target"); + exit; +} + +function is_valid_query(string $query): bool +{ + $query = trim($query); + if ($query === '') { + return false; + } + if (mb_strlen($query) > 200) { + return false; + } + + // Vérifier que la chaîne est en UTF-8 valide + if (!mb_check_encoding($query, 'UTF-8')) { + return false; + } + + return preg_match('/^[^\x00-\x1F\x7F]+$/u', $query) === 1; +} + +// --- Gestion bangs --- // + +function load_bangs(): array +{ + $file = __DIR__ . '/bang.json'; + if (!file_exists($file)) { + error_log("bang.json introuvable"); + return []; + } + $content = file_get_contents($file); + if ($content === false) { + error_log("Impossible de lire bang.json"); + return []; + } + $bangs = json_decode($content, true); + if (!is_array($bangs)) { + error_log("bang.json mal formé"); + return []; + } + return $bangs; +} + +function try_redirect_bang(string $query): bool +{ + if (substr($query, 0, 1) !== '!') { + return false; + } + + if (!preg_match('/^!(\w+)\s?(.*)$/u', $query, $matches)) { + return false; + } + $bang_code = $matches[1]; + $search_term = trim($matches[2]); + + if ($search_term === '') { + return false; + } + + $bangs = load_bangs(); + if (empty($bangs)) { + return false; + } + + foreach ($bangs as $bang) { + if (($bang['bang'] ?? '') === $bang_code) { + $base_url = rtrim($bang['url'], '/'); + $search_url = $base_url . '?q=' . rawurlencode($search_term); + header("Location: $search_url"); + exit; + } + } + return false; +}