<?php
/**
 * 门禁 — 给已有站点加防红，原站点文件零改动
 *
 * 支持三种接入方式：
 *   ① standalone : nginx 把 / 交给 gate.php（自己是入口）
 *   ② embedded   : index.php 里 require gate.php
 *   ③ prepend    : .user.ini 的 auto_prepend_file 自动注入（推荐，全站保护）
 *
 * 通过 → 继续原页面 / 拦截 → 中性页
 */
declare(strict_types=1);

/* 错误只记日志，不输出到页面（防止 Warning 破坏输出的 HTML/JSON） */
@ini_set('display_errors', '0');
error_reporting(E_ALL);

require_once __DIR__ . '/lib/judge.php';

/* ================= 配置 ================= */
const ENTRY_FILE = 'index.php';    // 原站点入口（standalone 模式用）
const SHELL_JS   = '_s.js';
const SHELL_CSS  = '_s.css';

/* 白名单：这些路径不判活（接口、蜜罐、静态资源、统计页） */
const GATE_BYPASS = [
    '/api/site-meta', '/h/', '/honeypot.php',
    '/gate.php', '/shell.php', '/stats.php',
    '/s.js', '/s.css', '/_s.js', '/_s.css',
    '/about.html', '/404.html', '/robots.txt',
];

/* ================= 核心逻辑（函数里 return 才安全） ================= */
function gate_run(string $mode): void
{
    /* ---------- ① 通行证有效 → 放行 ---------- */
    $k  = (string)($_GET['k'] ?? ($_COOKIE['lp_k'] ?? ''));
    $tk = j_token_verify($k);

    if ($tk !== null) {
        /* token 有效也要二次确认不是爬虫（防止重放/同段伪造） */
        $h2 = j_header_score();
        if (!j_blacklisted() && !j_is_bot() && $h2['score'] < 3 && !j_country_blocked()) {
            if (($_COOKIE['lp_k'] ?? '') !== $k) {
                setcookie('lp_k', $k, [
                    'expires'  => time() + J_TOKEN_TTL,
                    'path'     => '/',
                    'httponly' => true,
                    'samesite' => 'Lax',
                    'secure'   => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'),
                ]);
            }
            j_count('gate_pass');

            /* standalone：自己去 include 原入口 */
            if ($mode === 'standalone') {
                $entry = __DIR__ . '/' . ENTRY_FILE;
                if (is_file($entry)) {
                    chdir(__DIR__);
                    include $entry;
                    exit;
                }
                http_response_code(500);
                header('Content-Type: text/plain; charset=utf-8');
                exit('entry not found');
            }

            /* embedded / prepend：返回，让原脚本继续 */
            return;
        }

        /* token 有效但是爬虫 → 给中性页 */
        j_count('gate_token_but_bot');
        j_log('gate_block', ['reason' => 'token_but_bot']);
        gate_clean();
    }

    /* ---------- ② 判活 ---------- */
    if (j_blacklisted())          { j_count('gate_blacklisted'); gate_clean(); }
    if (j_is_bot())               { j_count('gate_bot');         gate_clean(); }
    if (j_country_blocked())      { j_count('gate_country');     gate_clean(); }

    $h = j_header_score();
    if ($h['score'] >= 3)         { j_count('gate_headers');     gate_clean(); }

    /* ---------- ③ 真人 → 空壳（JS 拿 cookie 后 reload） ---------- */
    gate_shell();
}

/* ---------- 中性页（按渠道码选不同模板） ---------- */
function gate_clean(): void
{
    header('Content-Type: text/html; charset=utf-8');
    header('Cache-Control: no-store');
    header('X-Robots-Tag: noindex, nofollow');
    header('X-Content-Type-Options: nosniff');
    $c = j_neutral_path();
    if ($c !== '' && is_file($c)) { readfile($c); exit; }
    echo '<!DOCTYPE html><html><head><meta charset="utf-8"><title>Information</title></head>'
       . '<body style="font-family:system-ui;max-width:720px;margin:60px auto;padding:0 20px">'
       . '<h1>Information</h1><p>This page provides general information about our services.</p>'
       . '</body></html>';
    exit;
}

/* ---------- 动态空壳（每次随机） ---------- */
function gate_shell(): void
{
    j_count('gate_shell');
    header('Content-Type: text/html; charset=utf-8');
    header('Cache-Control: no-store');
    header('X-Robots-Tag: noindex, nofollow');
    header('X-Content-Type-Options: nosniff');

    $stamp = bin2hex(random_bytes(4));
    $honey = bin2hex(random_bytes(4));
    $pad   = str_repeat(' ', random_int(0, 3));
    ?>
<!DOCTYPE html><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex,nofollow"><title></title><!-- <?= $stamp ?> --><link rel="stylesheet" href="/<?= SHELL_CSS ?>"><div class="ld"></div><a class="hp" href="/h/<?= $honey ?>" aria-hidden="true" tabindex="-1" rel="nofollow">.</a><script src="/<?= SHELL_JS ?>"></script><?= $pad ?>
<?php
    exit;
}

/* ================= 入口 ================= */
/* CLI（定时任务/脚本）直接放行 */
if (PHP_SAPI === 'cli') {
    return;
}

/* 模式判断 */
$self   = realpath(__FILE__);
$script = realpath((string)($_SERVER['SCRIPT_FILENAME'] ?? ''));
$mode   = ($script === $self) ? 'standalone' : 'embedded';

/* 白名单：命中就不判活，让原脚本执行
   ⚠ 这里不能 return（prepend 模式下 return 会终止整个请求），
     只能用 $skip 控制是否调用 gate_run() */
$uri  = (string)(parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?: '/');
$skip = false;
foreach (GATE_BYPASS as $p) {
    if ($uri === $p || str_starts_with($uri, $p) && str_ends_with($p, '/')) {
        $skip = true;
        break;
    }
}

if (!$skip) {
    gate_run($mode);
}
/* 文件到此结束 → prepend 模式下主脚本自动继续 */
