<?php
/**
 * 远程热更新系统 - PHP版本
 * 适用于宝塔面板部署
 */

header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Hardware-ID');

// 处理OPTIONS请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    exit(0);
}

// 配置
$config = [
    'upload_dir' => __DIR__ . '/uploads/',
    'current_version' => '1.0.0',
    'max_file_size' => 50 * 1024 * 1024, // 50MB
    'allowed_extensions' => ['js', 'json', 'zip'],
    'require_auth' => false, // 是否需要认证
    'auth_token' => 'your_secure_token_here' // 认证令牌
];

// 确保上传目录存在
if (!file_exists($config['upload_dir'])) {
    mkdir($config['upload_dir'], 0755, true);
}

// 版本信息存储
$version_file = __DIR__ . '/version.json';
$version_info = [
    'current' => $config['current_version'],
    'update_url' => '',
    'changelog' => '初始版本发布',
    'signature' => '',
    'checksum' => '',
    'update_time' => date('Y-m-d H:i:s')
];

// 如果版本文件存在，读取版本信息
if (file_exists($version_file)) {
    $saved_version = json_decode(file_get_contents($version_file), true);
    if ($saved_version) {
        $version_info = array_merge($version_info, $saved_version);
    }
}

// 请求路由
$request_uri = $_SERVER['REQUEST_URI'];
$request_method = $_SERVER['REQUEST_METHOD'];

// 解析请求路径
$path = parse_url($request_uri, PHP_URL_PATH);
$path = str_replace('/index.php', '', $path); // 移除index.php

// 路由处理
switch ($path) {
    case '/api/version':
        handleVersionCheck();
        break;
    case '/api/upload':
        handleFileUpload();
        break;
    case '/api/keys':
        handleGetKeys();
        break;
    case '/download':
        handleFileDownload();
        break;
    default:
        // 尝试处理下载请求
        if (strpos($path, '/download/') === 0) {
            handleFileDownload();
        } else {
            sendErrorResponse('未找到请求的接口', 404);
        }
        break;
}

/**
 * 处理版本检查请求
 */
function handleVersionCheck() {
    global $version_info;
    
    $client_version = $_GET['version'] ?? '';
    $hardware_id = $_SERVER['HTTP_X_HARDWARE_ID'] ?? '';
    
    // 记录请求日志
    logRequest('version_check', [
        'client_version' => $client_version,
        'hardware_id' => $hardware_id,
        'ip' => $_SERVER['REMOTE_ADDR']
    ]);
    
    if ($client_version !== $version_info['current']) {
        sendSuccessResponse([
            'hasUpdate' => true,
            'version' => $version_info['current'],
            'updateUrl' => $version_info['update_url'],
            'changelog' => $version_info['changelog'],
            'signature' => $version_info['signature'],
            'checksum' => $version_info['checksum'],
            'updateTime' => $version_info['update_time']
        ]);
    } else {
        sendSuccessResponse([
            'hasUpdate' => false,
            'version' => $version_info['current']
        ]);
    }
}

/**
 * 处理文件上传请求
 */
function handleFileUpload() {
    global $config, $version_info, $version_file;
    
    // 检查认证
    if ($config['require_auth']) {
        $auth_header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
        if ($auth_header !== 'Bearer ' . $config['auth_token']) {
            sendErrorResponse('认证失败', 401);
            return;
        }
    }
    
    // 检查文件上传
    if (!isset($_FILES['file'])) {
        sendErrorResponse('没有上传文件');
        return;
    }
    
    $file = $_FILES['file'];
    
    // 检查文件大小
    if ($file['size'] > $config['max_file_size']) {
        sendErrorResponse('文件大小超过限制');
        return;
    }
    
    // 检查文件扩展名
    $file_ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
    if (!in_array($file_ext, $config['allowed_extensions'])) {
        sendErrorResponse('不支持的文件类型');
        return;
    }
    
    // 生成唯一文件名
    $filename = time() . '_' . mt_rand(1000, 9999) . '.' . $file_ext;
    $upload_path = $config['upload_dir'] . $filename;
    
    try {
        // 移动上传的文件
        if (!move_uploaded_file($file['tmp_name'], $upload_path)) {
            sendErrorResponse('文件上传失败');
            return;
        }
        
        // 读取文件内容
        $file_content = file_get_contents($upload_path);
        
        // 5层加密
        $encryption = new MultiLayerEncryption();
        $encrypted_data = $encryption->encrypt($file_content);
        
        // 保存加密文件
        $encrypted_filename = $filename . '.encrypted';
        $encrypted_path = $config['upload_dir'] . $encrypted_filename;
        file_put_contents($encrypted_path, $encrypted_data);
        
        // 生成数字签名
        $signature = generateDigitalSignature($encrypted_data);
        
        // 生成校验和
        $checksum = hash('sha256', $encrypted_data);
        
        // 保存加密密钥
        $keys_filename = $filename . '.keys';
        $keys_path = $config['upload_dir'] . $keys_filename;
        file_put_contents($keys_path, json_encode($encryption->getKeys()));
        
        // 更新版本信息
        $new_version = $_POST['version'] ?? $version_info['current'];
        $changelog = $_POST['changelog'] ?? '更新内容';
        
        $version_info = [
            'current' => $new_version,
            'update_url' => '/download/' . $encrypted_filename,
            'changelog' => $changelog,
            'signature' => $signature,
            'checksum' => $checksum,
            'update_time' => date('Y-m-d H:i:s')
        ];
        
        // 保存版本信息
        file_put_contents($version_file, json_encode($version_info));
        
        // 删除原始文件
        unlink($upload_path);
        
        // 记录上传日志
        logRequest('file_upload', [
            'filename' => $filename,
            'version' => $new_version,
            'size' => $file['size'],
            'ip' => $_SERVER['REMOTE_ADDR']
        ]);
        
        sendSuccessResponse([
            'success' => true,
            'message' => '文件上传并加密成功',
            'version' => $new_version,
            'signature' => $signature,
            'checksum' => $checksum,
            'downloadUrl' => $version_info['update_url']
        ]);
        
    } catch (Exception $e) {
        // 清理临时文件
        if (file_exists($upload_path)) {
            unlink($upload_path);
        }
        
        sendErrorResponse('文件处理失败: ' . $e->getMessage());
    }
}

/**
 * 处理获取解密密钥请求
 */
function handleGetKeys() {
    global $config;
    
    $filename = $_GET['filename'] ?? '';
    if (empty($filename)) {
        sendErrorResponse('缺少文件名参数');
        return;
    }
    
    $keys_filename = str_replace('.encrypted', '.keys', $filename);
    $keys_path = $config['upload_dir'] . $keys_filename;
    
    if (!file_exists($keys_path)) {
        sendErrorResponse('密钥文件不存在', 404);
        return;
    }
    
    try {
        $keys = json_decode(file_get_contents($keys_path), true);
        if (!$keys) {
            sendErrorResponse('密钥文件格式错误');
            return;
        }
        
        // 记录密钥请求日志
        logRequest('keys_request', [
            'filename' => $filename,
            'ip' => $_SERVER['REMOTE_ADDR']
        ]);
        
        sendSuccessResponse(['keys' => $keys]);
        
    } catch (Exception $e) {
        sendErrorResponse('读取密钥失败: ' . $e->getMessage());
    }
}

/**
 * 处理文件下载请求
 */
function handleFileDownload() {
    global $config;
    
    // 从URL中获取文件名
    $filename = '';
    if (strpos($_SERVER['REQUEST_URI'], '/download/') !== false) {
        $parts = explode('/download/', $_SERVER['REQUEST_URI']);
        $filename = end($parts);
    }
    
    if (empty($filename)) {
        sendErrorResponse('缺少文件名参数', 400);
        return;
    }
    
    $file_path = $config['upload_dir'] . $filename;
    
    if (!file_exists($file_path)) {
        sendErrorResponse('文件不存在', 404);
        return;
    }
    
    try {
        // 记录下载日志
        logRequest('file_download', [
            'filename' => $filename,
            'ip' => $_SERVER['REMOTE_ADDR']
        ]);
        
        // 设置下载头
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
        header('Content-Length: ' . filesize($file_path));
        header('Cache-Control: no-cache, must-revalidate');
        header('Pragma: no-cache');
        
        // 输出文件内容
        readfile($file_path);
        exit;
        
    } catch (Exception $e) {
        sendErrorResponse('文件下载失败: ' . $e->getMessage());
    }
}

/**
 * 多层加密类
 */
class MultiLayerEncryption {
    private $layers = [];
    
    public function __construct() {
        $this->layers = [
            ['name' => 'AES-256-CBC', 'key' => random_bytes(32), 'iv' => random_bytes(16)],
            ['name' => 'AES-256-GCM', 'key' => random_bytes(32), 'iv' => random_bytes(16)],
            ['name' => 'ChaCha20-Poly1305', 'key' => random_bytes(32), 'nonce' => random_bytes(12)],
            ['name' => 'AES-256-CTR', 'key' => random_bytes(32), 'iv' => random_bytes(16)],
            ['name' => 'AES-256-CFB', 'key' => random_bytes(32), 'iv' => random_bytes(16)]
        ];
    }
    
    public function encrypt($data) {
        $encrypted = $data;
        
        // 第一层：AES-256-CBC
        $encrypted = openssl_encrypt($encrypted, 'aes-256-cbc', $this->layers[0]['key'], OPENSSL_RAW_DATA, $this->layers[0]['iv']);
        
        // 第二层：AES-256-GCM
        $tag = '';
        $encrypted = openssl_encrypt($encrypted, 'aes-256-gcm', $this->layers[1]['key'], OPENSSL_RAW_DATA, $this->layers[1]['iv'], $tag, '', 16);
        $encrypted .= $tag; // 附加GCM标签
        
        // 第三层：ChaCha20-Poly1305 (PHP 7.2+)
        if (function_exists('sodium_crypto_aead_chacha20poly1305_ietf_encrypt')) {
            $nonce = $this->layers[2]['nonce'];
            $encrypted = sodium_crypto_aead_chacha20poly1305_ietf_encrypt($encrypted, '', $nonce, $this->layers[2]['key']);
        } else {
            // 回退到AES-256-CFB
            $encrypted = openssl_encrypt($encrypted, 'aes-256-cfb', $this->layers[2]['key'], OPENSSL_RAW_DATA, $this->layers[2]['iv']);
        }
        
        // 第四层：AES-256-CTR
        $encrypted = openssl_encrypt($encrypted, 'aes-256-ctr', $this->layers[3]['key'], OPENSSL_RAW_DATA, $this->layers[3]['iv']);
        
        // 第五层：AES-256-CFB
        $encrypted = openssl_encrypt($encrypted, 'aes-256-cfb', $this->layers[4]['key'], OPENSSL_RAW_DATA, $this->layers[4]['iv']);
        
        return $encrypted;
    }
    
    public function getKeys() {
        $keys = [];
        foreach ($this->layers as $layer) {
            $keys[] = [
                'name' => $layer['name'],
                'key' => bin2hex($layer['key']),
                'iv' => isset($layer['iv']) ? bin2hex($layer['iv']) : bin2hex($layer['nonce'])
            ];
        }
        return $keys;
    }
}

/**
 * 生成数字签名
 */
function generateDigitalSignature($data) {
    // 简化的签名实现，实际应用中应使用RSA私钥
    return hash_hmac('sha256', $data, 'your_secret_key_here');
}

/**
 * 验证数字签名
 */
function verifyDigitalSignature($data, $signature) {
    $expected_signature = hash_hmac('sha256', $data, 'your_secret_key_here');
    return hash_equals($expected_signature, $signature);
}

/**
 * 记录请求日志
 */
function logRequest($action, $data) {
    $log_file = __DIR__ . '/logs/requests.log';
    $log_dir = dirname($log_file);
    
    if (!file_exists($log_dir)) {
        mkdir($log_dir, 0755, true);
    }
    
    $log_entry = [
        'timestamp' => date('Y-m-d H:i:s'),
        'action' => $action,
        'data' => $data,
        'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
        'ip' => $_SERVER['REMOTE_ADDR']
    ];
    
    file_put_contents($log_file, json_encode($log_entry) . "\n", FILE_APPEND | LOCK_EX);
}

/**
 * 发送成功响应
 */
function sendSuccessResponse($data) {
    echo json_encode([
        'success' => true,
        'data' => $data
    ]);
    exit;
}

/**
 * 发送错误响应
 */
function sendErrorResponse($message, $code = 400) {
    http_response_code($code);
    echo json_encode([
        'success' => false,
        'error' => $message
    ]);
    exit;
}

?>