Spaces:
Running
Running
| // ========================================== | |
| // API ПРОКСИ ДЛЯ GITHUB PAGES | |
| // Возвращает свежую ссылку в JSON формате | |
| // ========================================== | |
| header("Access-Control-Allow-Origin: *"); | |
| header("Content-Type: application/json; charset=UTF-8"); | |
| header("Cache-Control: no-store, no-cache, must-revalidate"); | |
| header("Pragma: no-cache"); | |
| define("CACHE_FILE", __DIR__ . "/domain_cache.txt"); | |
| define("XOR_KEY", "ui-sess-v4-8921-xb-log"); // Должен совпадать с get.php | |
| // Функция дешифрования | |
| function xor_decode($base64_string, $key) { | |
| $string = base64_decode($base64_string); | |
| $out = ''; | |
| for ($i = 0; $i < strlen($string); $i++) { | |
| $out .= $string[$i] ^ $key[$i % strlen($key)]; | |
| } | |
| return $out; | |
| } | |
| // Функция проверки IP по CIDR | |
| function ip_in_cidr($ip, $cidr) { | |
| if (strpos($cidr, '/') === false) { | |
| return $ip === $cidr; | |
| } | |
| list($subnet, $mask) = explode('/', $cidr); | |
| $subnet = ip2long($subnet); | |
| $ip = ip2long($ip); | |
| $mask = -1 << (32 - $mask); | |
| $subnet &= $mask; | |
| return ($ip & $mask) == $subnet; | |
| } | |
| // Определение IP клиента | |
| $client_ip = ''; | |
| if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { | |
| $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); | |
| $client_ip = trim($ips[0]); | |
| } else { | |
| $client_ip = $_SERVER['REMOTE_ADDR'] ?? ''; | |
| } | |
| // Проверка по черному списку | |
| $blacklist_file = __DIR__ . '/blacklist.txt'; | |
| $blacklist = []; | |
| if (file_exists($blacklist_file)) { | |
| $blacklist = file($blacklist_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); | |
| } else { | |
| // Хардкод массив (фоллбэк) | |
| $blacklist = [ | |
| '79.137.0.0/16', | |
| '66.249.0.0/16' | |
| ]; | |
| } | |
| foreach ($blacklist as $cidr) { | |
| $cidr = trim($cidr); | |
| if (empty($cidr)) continue; | |
| if (ip_in_cidr($client_ip, $cidr)) { | |
| http_response_code(403); | |
| die(); // Early Exit для ботов | |
| } | |
| } | |
| $cache_file = CACHE_FILE; | |
| $api_response = ""; | |
| // Безопасное чтение файла с защитой от гонки процессов | |
| if (file_exists($cache_file)) { | |
| $fp = fopen($cache_file, "r"); | |
| if (flock($fp, LOCK_SH)) { | |
| $fsize = filesize($cache_file); | |
| if ($fsize > 0) { | |
| $content = fread($fp, $fsize); | |
| if (!empty($content)) { | |
| $api_response = trim($content); | |
| } | |
| } | |
| flock($fp, LOCK_UN); | |
| } | |
| fclose($fp); | |
| } | |
| if (!empty($api_response)) { | |
| $url = xor_decode($api_response, XOR_KEY); | |
| if (strpos($url, 'http') === 0) { | |
| echo json_encode([ | |
| "success" => true, | |
| "url" => $url | |
| ], JSON_UNESCAPED_SLASHES); | |
| } else { | |
| http_response_code(500); | |
| echo json_encode([ | |
| "success" => false, | |
| "error" => "Invalid decoded URL. Make sure get.php is running." | |
| ]); | |
| } | |
| } else { | |
| http_response_code(404); | |
| echo json_encode([ | |
| "success" => false, | |
| "error" => "No cache available. Wait for get.php to run." | |
| ]); | |
| } | |