✏️ 编辑:license.php
路径:
/home/boguraj1/public_html/ipsms/includes/license.php
大小:7.85 KB · 修改:2026-06-17 01:07:02 · 权限:0644 · 可写
← 返回目录
👁 查看
⬇ 下载
<?php /** * License verification middleware. * Include config/license.php BEFORE calling checkLicense(). */ // Pages that are allowed without a valid license const LICENSE_BYPASS_PAGES = ['license_activate.php', 'install.php', 'logout.php']; /** * Main entry point — call once per page (from config/db.php). * Exits with an error page if the license is not valid. */ function checkLicense(): void { // Skip on exempt pages if (in_array(basename($_SERVER['PHP_SELF'] ?? ''), LICENSE_BYPASS_PAGES, true)) { return; } // Skip if caller explicitly opted out (e.g., CLI scripts) if (defined('SKIP_LICENSE_CHECK') && SKIP_LICENSE_CHECK) { return; } $domain = _normalizeDomain($_SERVER['HTTP_HOST'] ?? 'localhost'); $license_key = defined('LICENSE_KEY') ? LICENSE_KEY : ''; // Nothing configured yet → send to activation page if ($license_key === '' || $license_key === 'HXZBT-ZRCE5-93C8Z-CGPVH') { _licenseError( 'License Key Not Set', 'Please enter your license key to activate this software.', true ); } // ---- Try cache first ---- $cache = _readCache(); if ($cache !== null && $cache['domain'] === $domain) { $age = time() - $cache['time']; if ($cache['status'] === 'valid' && $age < LICENSE_CACHE_TTL) { return; // Cache is fresh and valid } // Cache is stale → try server; fall back to grace period if unreachable $result = _queryServer($domain, $license_key); if ($result === null) { // Server unreachable if ($cache['status'] === 'valid' && $age < LICENSE_GRACE_TTL) { return; // Grace period: let them work } _licenseError( 'License Server Unreachable', 'Cannot verify your license. Check your internet connection or contact tmitstore.com support.' ); } _writeCache($domain, $result['status'], $result['message'] ?? ''); if ($result['status'] === 'valid') return; _licenseError('License Invalid', $result['message'] ?? 'License verification failed.'); } // ---- No usable cache — must query server ---- $result = _queryServer($domain, $license_key); if ($result === null) { _licenseError( 'License Server Unreachable', 'Cannot contact the license server. Ensure this server has outbound internet access.' ); } _writeCache($domain, $result['status'], $result['message'] ?? ''); if ($result['status'] === 'valid') return; _licenseError('License Invalid', $result['message'] ?? 'This license is not valid for this domain.'); } // ============================================================ // Internal helpers (prefixed with _ to avoid global collisions) // ============================================================ /** Normalize host: lowercase, strip www., strip port. */ function _normalizeDomain(string $host): string { $host = strtolower(trim($host)); $host = preg_replace('/^www\./', '', $host); $host = explode(':', $host)[0]; return $host; } /** Query the remote license server. Returns decoded array or null on failure. */ function _queryServer(string $domain, string $license_key): ?array { $timestamp = time(); $sig = hash_hmac( 'sha256', $domain . $license_key . LICENSE_PRODUCT . $timestamp, LICENSE_HMAC_SECRET ); $payload = json_encode([ 'domain' => $domain, 'license_key' => $license_key, 'product' => LICENSE_PRODUCT, 'timestamp' => $timestamp, 'sig' => $sig, ]); $ctx = stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: application/json\r\nContent-Length: " . strlen($payload), 'content' => $payload, 'timeout' => 8, 'ignore_errors' => true, ], 'ssl' => ['verify_peer' => true, 'verify_peer_name' => true], ]); $raw = @file_get_contents(LICENSE_SERVER_URL, false, $ctx); if ($raw === false) return null; $data = @json_decode($raw, true); if (!is_array($data)) return null; // Verify server's response signature to prevent spoofing if (($data['status'] ?? '') === 'valid') { $expires_at = $data['expires_at'] ?? 'lifetime'; $expected_sig = hash_hmac( 'sha256', 'valid' . $domain . $expires_at . LICENSE_PRODUCT, LICENSE_HMAC_SECRET ); if (empty($data['res_sig']) || !hash_equals($expected_sig, $data['res_sig'])) { return ['status' => 'tampered', 'message' => 'Server response signature is invalid.']; } } return $data; } /** Read cached license result. Returns null if cache missing/corrupt. */ function _readCache(): ?array { $file = LICENSE_CACHE_FILE; if (!file_exists($file)) return null; $raw = @file_get_contents($file); if ($raw === false) return null; // Decode: base64 then JSON $data = @json_decode(base64_decode($raw), true); if (!is_array($data) || !isset($data['domain'], $data['status'], $data['time'])) { return null; } return $data; } /** Write license result to cache file. */ function _writeCache(string $domain, string $status, string $message): void { $data = base64_encode(json_encode([ 'domain' => $domain, 'status' => $status, 'message' => $message, 'time' => time(), ])); @file_put_contents(LICENSE_CACHE_FILE, $data, LOCK_EX); } /** Show a styled license error page and exit. */ function _licenseError(string $title, string $message, bool $show_activate_link = false): void { $domain = _normalizeDomain($_SERVER['HTTP_HOST'] ?? 'localhost'); http_response_code(403); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>License Error — ISP Stock Manager</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet"> <style> body { background: linear-gradient(135deg, #dc3545 0%, #a71d2a 100%); min-height: 100vh; display: flex; align-items: center; justify-content: center; } .lic-card { max-width: 540px; width: 100%; border-radius: 1rem; } .lic-icon { font-size: 4rem; color: #dc3545; } code { background: #f8f9fa; padding: 2px 6px; border-radius: 4px; font-size: 0.9em; } </style> </head> <body> <div class="lic-card card shadow-lg p-4 mx-3"> <div class="text-center mb-4"> <i class="bi bi-shield-lock lic-icon"></i> <h3 class="fw-bold mt-2 text-danger"><?= htmlspecialchars($title) ?></h3> </div> <div class="alert alert-danger"> <i class="bi bi-exclamation-triangle-fill me-2"></i> <?= htmlspecialchars($message) ?> </div> <div class="card bg-light border-0 mb-3"> <div class="card-body small"> <strong>Domain:</strong> <code><?= htmlspecialchars($domain) ?></code><br> <strong>Product:</strong> <code>ISP Stock Manager</code><br> <strong>Support:</strong> <a href="https://tmitstore.com" target="_blank">tmitstore.com</a> </div> </div> <?php if ($show_activate_link): ?> <div class="d-grid"> <a href="license_activate.php" class="btn btn-primary fw-semibold"> <i class="bi bi-key me-1"></i> Activate License </a> </div> <?php else: ?> <p class="text-muted small text-center mb-0"> Contact <strong>tmitstore.com</strong> to purchase or renew your license. </p> <?php endif; ?> </div> </body> </html> <?php exit; }
💾 保存
取消
保存为 UTF-8,换行统一为 LF