&machine_id=&hostname= * Vérification toutes les 30 min, résultat mis en cache en BDD. */ define('VISION_LICENSE_URL', 'https://vision.copydev.fr/api/license.php'); define('VISION_PRODUCT', 'copymail'); define('VISION_CACHE_TTL', 1800); // 30 minutes function vision_machine_id(): string { $id = cfg('vision_machine_id', ''); if (!$id) { $id = strtolower('copymail-' . bin2hex(random_bytes(6))); cfg_set('vision_machine_id', $id); } return $id; } function vision_check(): array { $key = cfg('vision_license_key', ''); if (!$key) { return ['valid' => false, 'msg' => 'Licence non configurée.', 'unconfigured' => true]; } // Cache : si dernier check < 30 min et résultat valide, on ne re-vérifie pas $lastCheck = (int)cfg('vision_last_check', '0'); $lastResult = cfg('vision_last_result', ''); if ($lastResult && (time() - $lastCheck) < VISION_CACHE_TTL) { $cached = json_decode($lastResult, true); if ($cached) return $cached; } $url = VISION_LICENSE_URL . '?' . http_build_query([ 'key' => $key, 'machine_id' => vision_machine_id(), 'hostname' => cfg('hostname', gethostname()), ]); $ctx = stream_context_create(['http' => [ 'method' => 'GET', 'timeout' => 5, 'ignore_errors' => true, ]]); $resp = @file_get_contents($url, false, $ctx); if ($resp === false) { // Vision injoignable — mode dégradé selon offline_timeout $lastOk = (int)cfg('vision_last_ok', '0'); $timeout = (int)cfg('vision_offline_timeout', '72'); $elapsed = (time() - $lastOk) / 3600; if ($lastOk && $elapsed < $timeout) { $result = ['valid' => true, 'msg' => "Vision injoignable — mode dégradé ({$timeout}h max)", 'degraded' => true]; } else { $result = ['valid' => false, 'msg' => 'Vision injoignable et délai hors-ligne dépassé.']; } return $result; } $data = json_decode($resp, true); if (!empty($data['valid'])) { $result = [ 'valid' => true, 'client' => $data['client'] ?? '', 'product' => $data['product'] ?? '', 'expires' => $data['expires_at'] ?? null, 'devices' => $data['max_devices'] ?? 1, ]; cfg_set('vision_last_ok', (string)time()); cfg_set('vision_last_check', (string)time()); cfg_set('vision_last_result', json_encode($result)); cfg_set('vision_offline_timeout', (string)($data['offline_timeout_hours'] ?? 72)); return $result; } // Licence invalide / désactivée depuis Vision : invalide immédiatement le cache $result = ['valid' => false, 'msg' => $data['message'] ?? 'Licence invalide ou désactivée.']; cfg_set('vision_last_check', (string)time()); cfg_set('vision_last_result', json_encode($result)); cfg_set('vision_last_ok', '0'); // reset grace period return $result; } /** * Vérifie la licence et bloque si invalide. * À appeler sur toutes les pages. * Exception : la page de config (/admin/domain.php) reste accessible aux admins. */ function vision_enforce(): void { $result = vision_check(); if ($result['valid']) return; $uri = $_SERVER['REQUEST_URI'] ?? ''; // L'admin peut toujours accéder à la config pour saisir la clé if (is_admin() && strpos($uri, '/admin/domain.php') !== false) return; // Bloque tout le reste $msg = htmlspecialchars($result['msg'] ?? 'Licence invalide.'); $isAdmin = is_admin(); $configLink = $isAdmin ? 'Configurer la licence' : ''; http_response_code(403); echo " Licence CopyMail

CopyMail — Accès bloqué

{$msg}

Contactez CopyDev pour régulariser votre licence.

{$configLink}
"; exit; }