<?php
/**
 * 主入口 (PHP 8+ 兼容)
 * 流程: security过滤 -> zhizhu识别 -> func装载 -> jinzhi黑名单 -> 缓存命中? -> 抓取&渲染
 */

require_once __DIR__ . '/security.php'; // 最前置: 拦截扫描器/恶意路径,减少 PHP-FPM 压力

$t1 = microtime(true);

// 必须前置: func.php 定义 get_xiaotou + 全局 $djym/$mubiao; cache_New.php 设 $static_mode
require_once __DIR__ . '/func.php';
require_once __DIR__ . '/cache_New.php';

// ============================================================
// ★ 缓存第一位 (2026-05-30 重构)
//
// 速度三档:
//   L1: nginx 缓存短路 (scripts/nginx_cache_shortcut.conf) → 1-3ms, 完全跳过 PHP
//   L2: PHP 极速短路 (这里) → ~5ms, 命中即吐
//   L3: 完整流水线 (下面) → 15-50ms+, 抓远程 + 渲染 + 写缓存
//
// jinzhi.php (IP 黑名单) 延后到 cache miss 路径 — 黑名单 IP 拿缓存 HTML
// 没有任何敏感数据泄露, 反而减少服务器压力 (黑名单主要是防 CC, 命中缓存就是减压).
// security.php 已经拦了真正的攻击者 (APCu ban / payload / 恶意 UA).
// ============================================================
ob_clean();

$cachefile = get_xiaotou();
if (is_file($cachefile)) {
    if (!empty($static_mode)) {
        // 静态模式: 10 年浏览器/CDN 缓存
        $expire = 315360000;
        header('Cache-Control: public, max-age=' . $expire);
        header('Pragma: cache');
        header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expire) . ' GMT');
    }
    header('Content-Type: text/html; charset=utf-8');
    readfile($cachefile);
    echo '<!--' . round(microtime(true) - $t1, 6) . 's-->';
    exit;
}

// ============================================================
// 缓存 miss → 才检查 IP 黑名单, 走完整抓取流水线
// ============================================================
require_once __DIR__ . '/jinzhi.php';
// require_once __DIR__ . '/zhizhu.php';   // 如需蜘蛛流量统计/反爬,放开此行

// ============================================================
// 抓取目标站
// ============================================================
$url = str_replace(' ', '%20', $url);
$url = str_replace(['%06', '%07', '%05', '%08', '%EF%BB%BF'], '', $url);

// 优先用站群级源缓存 (多站共用同源时只抓 1 次)
$_nrStatus = 0;  // 透传 mubiao 的真实状态码
$nr = '';
// 远程抓取源站 (localmb 本地模板模式已于 2026-06 废弃)
if ($nr === '') {
    $nr = get_content_cached($url, $_nrStatus);
    if ($nr === '' && $_nrStatus !== 404) {
        // 只在 "不是真 404" 的失败下才重试 (mubiao 真 404 重试也没用, 浪费 worker)
        $nr = get_content_cached($url, $_nrStatus);
    }
}

if ($nr === '') {
    // ============================================================
    // 2026-05-30 优雅降级 (按 mubiao 真实状态分流, 精准 SEO 处理):
    //
    //   ★ mubiao 返回 404 (真 404) → 301 跳首页
    //      场景: 随便输入的 URL / 蜘蛛爬旧索引死链
    //      SEO 意图: 告诉蜘蛛"这页永久迁到首页", 把权重转给首页
    //
    //   ★ 其他错误 (TCP fast-fail / 熔断 / 超时 / 5xx) → 不跳首页
    //      场景: 我们暂时抓不到, 但 URL 可能真有内容
    //      SEO 意图: 不让蜘蛛把所有抓不到的 URL 都误认为搬移到首页
    //              (蜘蛛 200 + canonical 当前 URL, 用户 404)
    //
    //   ① 先 stale 缓存兜底 (无视 TTL)
    //   ② stale 没有 + 真 404 → 301 跳首页
    //   ③ stale 没有 + 其他错 + 蜘蛛 → 200 + TDK + canonical (保留索引意图)
    //   ④ stale 没有 + 其他错 + 用户首页 → 503 + Retry-After: 30
    //   ⑤ stale 没有 + 其他错 + 用户子页 → 404 + 简单提示
    // ============================================================
    $stale = function_exists('get_content_stale') ? get_content_stale($url) : '';
    if ($stale !== '') {
        // ✅ 有 stale, 继续走下面的正常流水线渲染 (域名替换/TDK/缓存等)
        $nr = $stale;
    } else {
        $homeUrl = $http . 'www.' . $djym . '/';
        $curPath = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
        $isHome  = in_array($curPath, ['/', '', '/index.html', '/index.php'], true);

        // ============================================================
        // ★ mubiao 真 404 + 非首页 → 301 跳首页 (蜘蛛索引迁移到首页, SEO 友好)
        // ============================================================
        if ($_nrStatus === 404 && !$isHome) {
            header('HTTP/1.1 301 Moved Permanently');
            header('Location: ' . $homeUrl);
            header('Cache-Control: max-age=3600');
            exit;
        }

        // ============================================================
        // 2026-05-30 治理: 子页面不再 301 跳首页 (软 404 SEO 灾难)
        //
        // 之前: 非首页抓不到 → 301 跳首页 → 蜘蛛认为"100 个子页全跳首页"
        //       搜索引擎识别为大规模软 404 → 整站降权
        //
        // 现在: 不管首页非首页, 蜘蛛永远 200 + TDK + 当前 URL canonical
        //       普通用户首页 503, 普通用户子页面 404 (告诉浏览器这页不存在)
        // ============================================================
        $_ua = strtolower($_SERVER['HTTP_USER_AGENT'] ?? '');
        $_isSpider = (
            strpos($_ua, 'baiduspider')   !== false ||
            strpos($_ua, 'googlebot')     !== false ||
            strpos($_ua, 'bingbot')       !== false ||
            strpos($_ua, 'bytespider')    !== false ||
            strpos($_ua, 'sogou')         !== false ||
            strpos($_ua, '360spider')     !== false ||
            strpos($_ua, 'yandexbot')     !== false ||
            strpos($_ua, 'applebot')      !== false ||
            strpos($_ua, 'yisouspider')   !== false ||
            strpos($_ua, 'haosou')        !== false ||
            strpos($_ua, 'petalbot')      !== false
        );

        if ($_isSpider) {
            // 蜘蛛 → 200 + 占位 HTML (不分首页/子页)
            //   ① TDK 来自本站配置 (首页 TDK 给所有页用, 至少能撑住蜘蛛识别)
            //   ② canonical 用蜘蛛当前请求的 URL (不再跳首页)
            //   ③ 30s meta refresh, 蜘蛛通常会再来一次
            //   ④ 不写文件缓存 (源恢复后重新走完整流水线)
            $_safeTitle = htmlspecialchars((string)($biaoti ?? $djym), ENT_QUOTES, 'UTF-8');
            $_safeDesc  = htmlspecialchars((string)($miaoshu ?? ''),    ENT_QUOTES, 'UTF-8');
            $_safeKw    = htmlspecialchars((string)($guanjianzi ?? ''), ENT_QUOTES, 'UTF-8');

            // canonical: 用蜘蛛实际请求的 URL, 而不是首页
            $_reqUri    = $_SERVER['REQUEST_URI'] ?? '/';
            $_canonical = $http . 'www.' . $djym . $_reqUri;
            $_canonical = htmlspecialchars($_canonical, ENT_QUOTES, 'UTF-8');

            http_response_code(200);
            header('Content-Type: text/html; charset=utf-8');
            header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
            header('Pragma: no-cache');
            echo '<!--PA988-PLACEHOLDER-' . htmlspecialchars($djym, ENT_QUOTES, 'UTF-8') . '-->';
            echo '<!DOCTYPE html><html lang="zh-CN"><head>';
            echo '<meta charset="UTF-8">';
            echo '<title>' . $_safeTitle . '</title>';
            echo '<meta name="description" content="' . $_safeDesc . '">';
            echo '<meta name="keywords" content="' . $_safeKw . '">';
            echo '<meta name="viewport" content="width=device-width,initial-scale=1.0">';
            echo '<meta http-equiv="refresh" content="30">';
            echo '<link rel="canonical" href="' . $_canonical . '">';
            echo '</head><body>';
            echo '<h1>' . $_safeTitle . '</h1>';
            if ($_safeDesc !== '') echo '<p>' . $_safeDesc . '</p>';
            echo '<p><a href="/">' . $_safeTitle . '</a></p>';  // 一条回首页链接, 蜘蛛可继续爬
            echo '</body></html>';
            exit;
        }

        // === 普通用户 ===
        if ($isHome) {
            // 首页用户 → 503 + Retry-After 30s (告诉浏览器/CDN 短期内重试)
            header('HTTP/1.1 503 Service Temporarily Unavailable');
            header('Retry-After: 30');
            exit;
        }

        // 子页面用户 → 404 + 简短提示页 (告诉浏览器这页确实不存在, 不再误导跳首页)
        // 蜘蛛走的是上面的 200 分支, 这里不影响 SEO
        http_response_code(404);
        header('Content-Type: text/html; charset=utf-8');
        $_safeTitle = htmlspecialchars((string)($biaoti ?? $djym), ENT_QUOTES, 'UTF-8');
        echo '<!DOCTYPE html><html lang="zh-CN"><head>';
        echo '<meta charset="UTF-8"><title>404 - ' . $_safeTitle . '</title>';
        echo '<meta name="viewport" content="width=device-width,initial-scale=1.0">';
        echo '<style>body{font-family:sans-serif;text-align:center;padding:80px 20px;color:#444}h1{font-size:64px;margin:0;color:#888}p{margin:20px 0}a{color:#06c}</style>';
        echo '</head><body>';
        echo '<h1>404</h1>';
        echo '<p>抱歉, 该页面暂时无法访问</p>';
        echo '<p><a href="/">返回 ' . $_safeTitle . ' 首页</a></p>';
        echo '</body></html>';
        exit;
    }
}

// ============================================================
// 编码统一
// ============================================================
$encode = mb_detect_encoding($nr, ['ASCII', 'UTF-8', 'GB2312', 'GBK', 'BIG5']);
if ($encode !== 'UTF-8') {
    $nr = iconv('gbk', 'utf-8//IGNORE', $nr);
    $nr = strtr($nr, [
        'gbk'    => 'utf-8',
        'gb2312' => 'utf-8',
        'GBK'    => 'utf-8',
        'GB2312' => 'utf-8',
        'BIG5'   => 'utf-8',
        'big5'   => 'utf-8',
    ]);
}

// ============================================================
// 基础替换 (合并为一次 strtr)
// ============================================================
$srcDomain = $mubiao;
$mubiaoTop = top_domain($srcDomain);
$nr = preg_replace("@hm.baidu.com(.*?)('|\")@is", "hm.baidu.com$1z6'", $nr);
$nr = strtr($nr, [
    'cnzz.com'                  => 'cnzz.co',
    'users.51.la'               => 'user.51.la',
    '"//'                       => '"http://',
    "'//"                       => "'http://",
    // 中期防呆: 目标站自身的 https:// 链接降级为 http://
    // (站点未配 HTTPS, 后续 preg_replace 会再把 http://target 改写为 / )
    'https://' . $srcDomain     => 'http://' . $srcDomain,
    'https://' . $mubiaoTop     => 'http://' . $mubiaoTop,
]);

// ============================================================
// 核心: mubiaoTop -> djym 的精确域名改写
// (修订 2026-05-29: 老版本用 strtr [$mubiaoTop => $djym] 暴力子串替换,
//  把 cdn.mubiaoTop.com / img.mubiaoTop.com 等 CDN 子域也改成 cdn.djym.com,
//  这些子域没 DNS -> 所有图片 404. 治理后:
//    ① 只精确匹配 host 位 (前 ://, 后 / " ' ) 等边界)
//    ② 主域 + www. 改写为本站
//    ③ CDN/img/static 等子域不动, 浏览器直接抓源, SEO 无损 (nofollow 已加))
// ============================================================
$tld = preg_quote($mubiaoTop, '#');
$nr = preg_replace(
    '#(["\'\(](?:https?:)?//)(?:www\.)?' . $tld . '(?=[/"\'\)\s:?])#i',
    '$1' . $djym,
    $nr
);

// 给所有外链加 nofollow (本域名除外)
$nr = preg_replace('@<a (?!(rel=|>).*)(.*?)href="http@is', '<a $2rel="nofollow" href="http', $nr);
$nr = preg_replace("@<a (?!(rel=|>).*)(.*?)href='http@is", "<a $2rel='nofollow' href='http", $nr);
$nr = str_replace('<option', '<option rel="nofollow"', $nr);

// 把本域名链接还原 + 转相对
$nr = strtr($nr, [
    'rel="nofollow" href="http://www.' . $djym  => 'href="http://www.' . $djym,
    "rel='nofollow' href='http://www." . $djym  => "href='http://www." . $djym,
    'rel="nofollow" href="https://www.' . $djym => 'href="https://www.' . $djym,
    "rel='nofollow' href='https://www." . $djym => "href='https://www." . $djym,
    '"http://www.' . $djym                      => '"/',
    "'http://www." . $djym                      => "'/",
    '"https://www.' . $djym                     => '"/',
    "'https://www." . $djym                     => "'/",
    '"https://' . $djym                         => '"/',
    "'https://" . $djym                         => "'/",
    '"http://' . $djym                          => '"/',
    "'http://" . $djym                          => "'/",
    '"//'                                       => '"/',
    "'//"                                       => "'/",
]);

// 兜底: 任何指向自己域名(含 m./api./cdn. 等子域)的 https:// 链接,都剥成相对路径,防白屏
$nr = preg_replace(
    '@(["\'\(])https?://[a-z0-9.\-]*' . preg_quote($djym, '@') . '(?=[/"\'\)\s])@i',
    '$1',
    $nr
);

// ============================================================
// 站群内链导流 (2026-05-30 新增)
// 把指向外站的 <a href="http://..."> 替换成站群其他站,
// 蜘蛛沿这些链接爬遍站群 → 收录率大幅提升 + 内部权重传递
// 控制开关: 想关掉就把下面这行注释掉
// ============================================================
$nr = replace_external_with_group_links($nr, $djym);

// ============================================================
// 给 div/li/h3/a 注入递增 ID
//   ★ 2026-07-08 修复: 基准 ID 由域名派生 (原为 mt_rand → 每次重生成缓存
//      ID 全变, 4点定时清缓存后首页 ID 每天换一批 → 搜索引擎认为结构大改 → 掉收录)。
//      改为 md5($djym) 派生的固定基准: 同站永久稳定, 源结构不变时每次渲染得到
//      完全相同的 ID 序列。每天只有文章/sitemap 更新, ID 不再抖动。
// ============================================================
$startId = 100000000 + (int)(hexdec(substr(md5($djym), 0, 7)) % 900000000);
$counter = 0;
$nr = preg_replace_callback(
    '@<(div|li|h3)(\s+[^>]*)>@is',
    function ($m) use ($startId, &$counter) {
        if (!preg_match('/\sid\s*=\s*/i', $m[2])) {
            $id = $startId + $counter++;
            return '<' . $m[1] . ' id="' . $id . '"' . $m[2] . '>';
        }
        return '<' . $m[1] . $m[2] . '>';
    },
    $nr
);

// ============================================================
// 设备关键词替换
// ============================================================
$nr = preg_replace(
    ['/iPhone/i','/eval/i','/ipod/i','/android/i','/ios/i','/phone/i','/webos/i','/mobile/i','/ucweb/i','/midp/i','/windows ce/i','/location/i','/ipad/i'],
    ['iphones','evals','ipods','androids','ioses','phones','weboses','mobiles','ucwebs','midps','windows ces','locations','ipads'],
    $nr
);

// ============================================================
// 统计脚本 + 移动端 meta
// ============================================================
$tjScript = '<div style="display:none;"><script src="//www.' . $djym . '/push.js"></script></div>';
$nr = (stripos($nr, '</body>') !== false)
    ? preg_replace('/<\/body>/i', $tjScript . '</body>', $nr)
    : $nr . $tjScript;

$mobileMeta = '<link rel="canonical" href="' . $dqurl . '"/>
<meta name="SiteName" content="' . $biaoti . '" />
<script>document.write(unescape("%3Cscript%20src%3D%22\u002f\u006f\u006b\u002e\u006a\u0073%22%20type%3D%27text/javascript%27%3E%3C/script%3E"));</script>
<meta name="mobile-agent" content="format=[wml|xhtml|html5];url=' . $m_url . '" />
<link href="' . $m_url . '" rel="alternate" media="only screen and (max-width: 640px)" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<meta http-equiv="Cache-Control" content="no-transform" />
<meta name="applicable-device" content="pc,mobile">
<meta name="MobileOptimized" content="width" />
<meta name="HandheldFriendly" content="true" />
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />';
$nr = str_replace('</title>', "</title>\r\n" . $mobileMeta, $nr);

// ============================================================
// 注入隐藏装饰 div (保留原 body 属性)
// ============================================================
$nr = preg_replace_callback(
    '/<body([^>]*)>/i',
    fn($m) => '<body' . $m[1] . ">\n" . rand_body_label(),
    $nr,
    1
);

// ============================================================
// ICP + 友链
// ============================================================
$nr = RandIcp($nr);
$nr = strtr($nr, [
    'href="/"' => 'href="/index.html"',
    "href='/'" => "href='/index.html'",
]);

// ============================================================
// 首页 TDK 改写
// ============================================================
if ($sy) {
    $safeMiaoshu    = htmlspecialchars($miaoshu, ENT_QUOTES, 'UTF-8');
    $safeGuanjianzi = htmlspecialchars($guanjianzi, ENT_QUOTES, 'UTF-8');

    $nr = injectMeta($nr, 'keywords',    $safeGuanjianzi);
    $nr = injectMeta($nr, 'description', $safeMiaoshu);
    $nr = preg_replace('@<title>(.*?)</title>@is', '<title>' . $biaoti . '</title>', $nr);
}

function injectMeta(string $html, string $name, string $content): string {
    $tag = '<meta name="' . $name . '" content="' . $content . '" />';
    $count = 0;
    $html = preg_replace(
        '@<meta([^>]*?)("' . $name . '"|\'' . $name . '\'|' . $name . ')([^>]*?)>@is',
        $tag,
        $html,
        -1,
        $count
    );
    if ($count > 0) {
        return $html;
    }
    if (preg_match('@<title[^>]*>(.*?)</title>@is', $html, $m, PREG_OFFSET_CAPTURE)) {
        $pos = $m[0][1] + strlen($m[0][0]);
        return substr_replace($html, "\n" . $tag, $pos, 0);
    }
    $headPos = stripos($html, '<head>');
    if ($headPos !== false) {
        return substr_replace($html, "\n" . $tag, $headPos + 6, 0);
    }
    $bodyPos = stripos($html, '<body');
    if ($bodyPos !== false) {
        return substr_replace($html, $tag . "\n", $bodyPos, 0);
    }
    return $tag . "\n" . $html;
}

// ============================================================
// 关键词替换
// ============================================================
if (!empty($tihuanci) && !empty($beitihuanci)) {
    $nr = str_replace($tihuanci, $beitihuanci, $nr);
}

// localmb: 清理模板里残留的 BDSEO entity 占位符 (否则 {{ENTITY_*}}/{CANONICAL_URL} 泄漏到页面)
// 清理 entity/占位符: localmb 本地模板 或 远程 muban 模板都可能带 {SITE_URL}/{{ENTITY_*}}/{CANONICAL_URL}
// (无占位时 lcmb_strip_entities 内部直接 return, 零开销; 故对所有站统一跑)
$_kw = trim(explode(',', (string)$guanjianzi)[0]);
if ($_kw === '') $_kw = (string)$biaoti;
$nr = lcmb_strip_entities($nr, $_kw, $http . 'www.' . $djym);

// ============================================================
// 结构化数据 JSON-LD (2026-06-01 新增)
//   首页 + 内页统一在 </head> 前注入 WebSite schema。
//   ★ 必须放在"关键词替换"之后:
//      ① 替换词 str_replace 不会再污染我们的 JSON
//      ② 之后 daima() 只处理 <body>, 不碰 <head> 里的它 (保持 JSON 干净)
//   name = 配置标题($biaoti), url = 本站根域。随 $nr 一起写入缓存, 缓存后固定不变。
//   url 跟随请求实际协议 $http (http:// 或 https://); @context 的 schema.org 固定 https 不动。
// ============================================================
$_ld = json_encode([
    '@context' => 'https://schema.org',
    '@type'    => 'WebSite',
    'name'     => (string)$biaoti,
    'url'      => $http . 'www.' . $djym . '/',
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);

if ($_ld !== false) {
    $_ldBlock = '<link rel="sitemap" type="application/xml" href="' . $http . 'www.' . $djym . '/sitemap.xml">' . "\n"
              . '<script type="application/ld+json">' . "\n" . $_ld . "\n" . '</script>' . "\n";
    // 用 substr_replace 按位置插入, 避免 preg_replace 把 JSON 里的 $ 当反向引用
    $_hp = stripos($nr, '</head>');
    if ($_hp !== false) {
        $nr = substr_replace($nr, $_ldBlock, $_hp, 0);          // 插在 </head> 前
    } elseif (($_bp = stripos($nr, '<body')) !== false) {
        $nr = substr_replace($nr, $_ldBlock, $_bp, 0);          // 没 </head> 退回 <body 前
    } else {
        $nr = $_ldBlock . $nr;                                  // 极端兜底
    }
}

// ============================================================
// 最新资讯链接块 (footer; 读 data/news_cache/list.json, 无文章则原样返回) — 供蜘蛛/用户发现 /news/ 文章
//   ★ 2026-06-04: 必须排在干扰码之前注入 — 资讯是真内容, 要在结尾干扰码(off-screen 垃圾标签)
//      的上面; 否则真链接被埋在一大堆乱码 <div> 之后, 不利收录。
// ============================================================
$nr = inject_news_block($nr, $djym, $http);

// ============================================================
// 干扰码 (一次生成共享)
// ============================================================
$cachefile_ganrao = get_ganrao();
if (!is_file($cachefile_ganrao)) {
    write($cachefile_ganrao, ganrao(100));
}
$ganrao = (string)file_get_contents($cachefile_ganrao);
$nr = str_replace('</body>', $ganrao . '</body>', $nr);

// 繁体转换: 2026-06-01 移除 (本就是死代码 — $jianti 恒为 1, $chinese 恒 null, 从不执行)

// ============================================================
// daima 加干扰符号 + 写缓存
//   ★ 2026-06-01 修复: daima 只对 <body> 正文加干扰符, 不碰 <head>。
//   原来对整篇(含 head)处理, 会给 <meta description>/<meta keywords>/
//   <title> 里的中文标点 ，。！？：；、 也插入干扰符, 导致搜索结果里的
//   站点描述显示乱七八糟。现在 TDK 直接输出 /data/domain 配置里的原值,
//   保持干净; 干扰符只加在正文里(防采集照常生效)。
// ============================================================
$_bodyPos = stripos($nr, '<body');
if ($_bodyPos !== false) {
    // head 原样保留 (TDK 干净), 只处理 body
    $nrr = substr($nr, 0, $_bodyPos) . daima(substr($nr, $_bodyPos));
} else {
    // 没有 body 标签的极端情况 (碎片/异常), 退回整篇处理
    $nrr = daima($nr);
}
write($cachefile, $nrr);

echo $nrr;
echo '<!--' . round(microtime(true) - $t1, 6) . 's-->';
exit;
