<?php
/**
 * PHP 原生项目授权客户端示例（薄客户端版）
 *
 * 核心原则：
 * - 客户端只负责采集运行环境信息并请求授权站。
 * - 域名匹配、泛域名匹配、IP 绑定、Token 比对、状态判断全部放在授权站 API。
 * - 客户端不做本地授权规则判断，也不做离线宽限通过，避免被改代码绕过。
 *
 * 使用方式：
 * 1. 把本文件放到项目入口或公共 bootstrap 中引入。
 * 2. 修改 LICENSE_API_URL 为你的授权站 API 地址，例如 https://auth.example.com/api/。
 * 3. 首次访问会要求输入 AuthToken，并保存到 runtime/license/token.json。
 */

const LICENSE_API_URL = 'https://gd.php13.cn/api/';
const LICENSE_TOKEN_FILE = __DIR__ . '/runtime/license/token.json';
const LICENSE_AUTH_IP = ''; // 如授权站绑定固定公网 IP，可在这里填写；留空则自动上报 SERVER_ADDR。
const LICENSE_TIMEOUT = 8;
const LICENSE_CONNECT_TIMEOUT = 3;

function license_escape($value)
{
    return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

function license_client_domain()
{
    $host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? '';
    $host = strtolower(trim((string)$host));
    $host = preg_replace('/:\d+$/', '', $host);

    return $host !== '' ? $host : 'unknown-domain';
}

function license_client_ip()
{
    if (LICENSE_AUTH_IP !== '') {
        return LICENSE_AUTH_IP;
    }

    return (string)($_SERVER['SERVER_ADDR'] ?? '');
}

function license_valid_token($token)
{
    return is_string($token) && preg_match('/^[A-Za-z0-9]{16,128}$/', $token) === 1;
}

function license_read_json_file($file)
{
    if (!is_file($file)) {
        return null;
    }

    $json = file_get_contents($file);
    if ($json === false) {
        return null;
    }

    $data = json_decode($json, true);
    return is_array($data) ? $data : null;
}

function license_write_json_file($file, array $data)
{
    $dir = dirname($file);
    if (!is_dir($dir) && !mkdir($dir, 0755, true) && !is_dir($dir)) {
        return false;
    }

    $tmp = tempnam($dir, 'license_');
    if ($tmp === false) {
        return false;
    }

    $json = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
    $ok = file_put_contents($tmp, $json, LOCK_EX) !== false && rename($tmp, $file);
    if (!$ok && is_file($tmp)) {
        @unlink($tmp);
    }

    @chmod($file, 0600);
    return $ok;
}

function license_get_token()
{
    $data = license_read_json_file(LICENSE_TOKEN_FILE);
    $token = trim((string)($data['authtoken'] ?? ''));

    return license_valid_token($token) ? $token : null;
}

function license_show_token_input_page($error = '')
{
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $token = trim((string)($_POST['authtoken'] ?? ''));
        if (!license_valid_token($token)) {
            $error = '请输入有效的 AuthToken';
        } elseif (license_write_json_file(LICENSE_TOKEN_FILE, ['authtoken' => $token])) {
            header('Location: ' . ($_SERVER['REQUEST_URI'] ?? '/'));
            exit;
        } else {
            $error = '无法写入授权文件，请检查 runtime/license 目录权限';
        }
    }

    $errorHtml = $error !== '' ? '<div class="error">' . license_escape($error) . '</div>' : '';
    echo '<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>请输入授权 Token</title>
    <style>
        body { margin: 0; padding: 50px; background: #f5f5f5; font-family: Arial, sans-serif; }
        .container { max-width: 500px; margin: 0 auto; background: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px #ddd; }
        h2 { text-align: center; color: #333; margin-bottom: 20px; }
        .error { color: #dc3545; text-align: center; padding: 10px; background: #f8d7da; border-radius: 4px; margin-bottom: 20px; }
        input[type="text"] { box-sizing: border-box; width: 100%; padding: 12px; margin-bottom: 20px; border: 1px solid #ddd; border-radius: 4px; font-size: 16px; }
        button { width: 100%; padding: 12px; background: #007bff; color: white; border: 0; border-radius: 4px; font-size: 16px; cursor: pointer; }
        button:hover { background: #0056b3; }
        .tip { text-align: center; color: #666; margin-top: 20px; font-size: 14px; }
    </style>
</head>
<body>
    <div class="container">
        <h2>授权验证</h2>
        ' . $errorHtml . '
        <form method="post">
            <input type="text" name="authtoken" placeholder="请输入你的 AuthToken" required>
            <button type="submit">保存并验证</button>
        </form>
        <div class="tip">客户端只保存 Token；授权规则由授权站统一判断。</div>
    </div>
</body>
</html>';
    exit;
}

function license_build_payload($token)
{
    return [
        'domain' => license_client_domain(),
        'authtoken' => $token,
        'authip' => license_client_ip(),
    ];
}

function license_request_server(array $payload)
{
    $ch = curl_init(LICENSE_API_URL);
    if ($ch === false) {
        return ['code' => 500, 'msg' => '初始化授权请求失败'];
    }

    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query($payload),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CONNECTTIMEOUT => LICENSE_CONNECT_TIMEOUT,
        CURLOPT_TIMEOUT => LICENSE_TIMEOUT,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2,
        CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded'],
    ]);

    $body = curl_exec($ch);
    $httpCode = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error = curl_error($ch);
    curl_close($ch);

    if ($body === false || $httpCode < 200 || $httpCode >= 300) {
        return ['code' => 500, 'msg' => '连接授权服务器失败' . ($error ? '：' . $error : '')];
    }

    $result = json_decode($body, true);
    if (!is_array($result)) {
        return ['code' => 500, 'msg' => '授权服务器响应格式错误'];
    }

    return $result;
}

function license_verify()
{
    $token = license_get_token();
    if ($token === null) {
        license_show_token_input_page();
    }

    return license_request_server(license_build_payload($token));
}

function license_handle_result(array $result)
{
    $code = (int)($result['code'] ?? 500);
    $msg = (string)($result['msg'] ?? '授权验证失败');

    if ($code === 200) {
        return;
    }

    if ($code === 401) {
        license_show_token_input_page($msg);
    }

    license_show_error_page('授权验证失败：' . $msg);
}

function license_show_error_page($message)
{
    echo '<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>授权错误</title>
    <style>
        body { margin: 0; padding: 0; background: #fff; font-family: Arial, sans-serif; }
        .container { text-align: center; padding: 150px 20px; }
        .error { color: #d93025; font-size: 20px; }
    </style>
</head>
<body>
    <div class="container">
        <div class="error">' . license_escape($message) . '</div>
    </div>
</body>
</html>';
    exit;
}

license_handle_result(license_verify());
