<?php
declare(strict_types=1);

/*
 * Parking / Redirect + Bot Trap
 * PHP 8.4
 *
 * Principe :
 * 1) Détermine le domaine (Host) et sa config DB (PARK / REDIRECT)
 * 2) Détecte incohérences (trap URL / robot usurpé / navigateur usurpé)
 * 3) Si incohérence => appel API (ip, ua, url, reason, host, extra)
 * 4) Applique ensuite l’action (parking ou redirection)
 */

// ====================
// CONFIGURATION
// ====================
const DB_DSN  = 'pgsql:host=y1.lemnia.net;port=5432;dbname=decisionip';
const DB_USER = 'postgres';
const DB_PASS = 'PuertoAngel';

// HTTP status pour redirection (302 ou 301)
const REDIRECT_STATUS = 302;

// API de signalement
const REPORT_API_BASE = 'https://api.decisionip.io/v1/addevent';
const REPORT_API_UKEY = '222a2a23-0e8d-4e96-8746-623ac16d705e';
const REPORT_API_SKEY = 'dip-0r2l29owtbud6s1pihadjrjtdmkanpb8jhtqbo8x';
const REPORT_API_TIMEOUT_MS = 700; // court pour ne pas ralentir ton service
const REPORT_UA_BASE = 'https://api.decisionip.io/v1/addua';

// Proxies de confiance (si applicable)
$TRUSTED_PROXIES = [
  // '127.0.0.1',
];

// Flag: une attaque a été signalée via addevent
$reportAttack = false;

// Trap URLs (regex sur REQUEST_URI)
$TRAP_URI_REGEX = [
  // VCS / IDE
  '~\B/\.git(?:/|$)~i',
  '~\B/\.svn(?:/|$)~i',
  '~\B/\.hg(?:/|$)~i',
  '~\B/\.bzr(?:/|$)~i',
  '~\B/\.idea(?:/|$)~i',
  '~\B/\.vscode(?:/|$)~i',

  // Secrets / configs
  '~\B/\.env(?:\.[a-z0-9_-]+)?\b~i',
  '~\B/config\.(?:php|ya?ml|json)\b~i',
  '~\B/settings\.(?:php|py)\b~i',
  '~\B/secrets\.(?:ya?ml|json)\b~i',
  '~\B/credentials\.(?:json|ya?ml)\b~i',
  '~\B/\.ssh/(?:authorized_keys|config)\b~i',
  '~\B/id_rsa(\.pub)?\b~i',

  // Cloud / CI
  '~\B/\.aws/(?:credentials|config)\b~i',
  '~\B/\.kube/config\b~i',
  '~\B/docker-compose(?:\.[a-z0-9_-]+)?\.ya?ml\b~i',
  '~\B/Dockerfile\b~i',
  '~\B/\.terraform(?:/|$)~i',
  '~\B/terraform\.tfstate\b~i',
  '~\B/\.github/workflows/~i',
  '~\B/\.gitlab-ci\.yml\b~i',

  // Backups
  '~\.(?:bak|old|orig|save|swp|tmp|backup)\b~i',
  '~\.(?:zip|tar|tar\.gz|tgz|7z|rar)\b~i',

  // CMS / frameworks
  '~\B/wp-(?:admin|content|login\.php|config\.php)~i',
  '~\B/xmlrpc\.php\b~i',
  '~\B/administrator(?:/|$)~i',
  '~\B/vendor(?:/|$)~i',
  '~\B/artisan\b~i',
  '~\B/storage/logs(?:/|$)~i',
  '~\B/admin\.php\b~i',

  // Admin / DB
  '~\B/(?:phpmyadmin|pma|adminer)(?:/|\.php|$)~i',
  '~\B/(?:admin|manage|manager|login)(?:/|$)~i',

  // Debug / API
  '~\B/(?:debug|_debugbar|_profiler|__debug__|actuator|metrics|health)\b~i',
  '~\B/(?:swagger|swagger-ui|openapi\.json|v2/api-docs)\b~i',

  // Node / Python
  '~\B/(?:node_modules|__pycache__)(?:/|$)~i',
  '~\B/(?:package|package-lock|yarn)\.json\b~i',
  '~\B/(?:requirements|pyproject)\.toml\b~i',

  // Misc
  '~^/\.well-known/[^?\#]*\.php(?:$|[/?#])~i',
  '~\B/\.ht(?:access|passwd)\b~i',
  '~\B/\.user\.ini\b~i',
  '~\B/\.DS_Store\b~i',
  '~\B/crossdomain\.xml\b~i',
  '~\B/clientaccesspolicy\.xml\b~i',
];

// Bots “vérifiables” : UA regex + suffixes reverse DNS
$VERIFIABLE_BOTS = [
  [
    'service' => 'google',
    'ua_regex' => '~\b(Googlebot|Google-InspectionTool|AdsBot-Google|Mediapartners-Google)\b~i',
    'rdns_suffixes' => ['.googlebot.com', '.google.com'],
    'forward_must_match_ip' => true,
  ],
  [
    'service' => 'bing',
    'ua_regex' => '~\b(bingbot|BingPreview)\b~i',
    'rdns_suffixes' => ['.search.msn.com'],
    'forward_must_match_ip' => true,
  ],
  [
    'service' => 'facebook',
    'ua_regex' => '~\b(facebookexternalhit|Facebot)\b~i',
    'rdns_suffixes' => ['.facebook.com', '.fb.com'],
    'forward_must_match_ip' => true,
  ],
];

// “UA navigateur”
$BROWSER_UA_REGEX = '~\b(Mozilla/5\.0|AppleWebKit|Chrome/|Safari/|Firefox/|Edg/)\b~i';

// Tokens bots/crawlers à exclure du "browser"
$BOT_TOKEN_UA_REGEX = '~\b('
  .'bot|spider|crawler|scrapy|curl|wget|python-requests|aiohttp|httpclient|java|okhttp|libwww|'
  .'go-http-client|php|node|axios|postmanruntime|insomnia|powershell|'
  .'headless|phantomjs|slimerjs|selenium|playwright|puppeteer|chromedriver|'
  .'ClaudeBot|GPTBot|ChatGPT-User|CCBot|Googlebot|bingbot|BingPreview|YandexBot|DuckDuckBot|Baiduspider|'
  .'facebookexternalhit|Facebot|Twitterbot|LinkedInBot|Slackbot|Discordbot|TelegramBot|'
  .'AhrefsBot|SemrushBot|MJ12bot|DotBot|PetalBot|Applebot|'
  .'compatible'
  .')\b~i';


// Cookies de challenge navigateur
const COOKIE_OK     = 'bpok';   // posé si JS OK
const COOKIE_TRIED  = 'bptried';// posé quand on a servi le challenge
const COOKIE_TTL    = 86400;    // 1 jour

// -------------------------
// HELPERS
// -------------------------

function normalize_host(string $host): string {
  $host = strtolower(trim($host));
  return preg_replace('/:\d+$/', '', $host);
}

function get_client_ip(array $trustedProxies): string {
  $remote = $_SERVER['REMOTE_ADDR'] ?? '';
  if ($remote === '') return '';

  if (in_array($remote, $trustedProxies, true)) {
    $xff = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '';
    if ($xff !== '') {
      $parts = array_map('trim', explode(',', $xff));
      if (!empty($parts) && filter_var($parts[0], FILTER_VALIDATE_IP)) {
        return $parts[0];
      }
    }
  }
  return $remote;
}

function fail(int $code, string $message): never {
  http_response_code($code);
  header('Content-Type: text/plain; charset=utf-8');
  echo $message;
  exit;
}

function report_event(string $ip, string $reason, string $ua, string $tmp = ''): void {
  try {
    $GLOBALS['reportAttack'] = true;
    if (!filter_var($ip, FILTER_VALIDATE_IP)) {
      error_log("REPORT_SKIP invalid ip: $ip");
      return;
    }

    $base = REPORT_API_BASE;
    $timeoutMs = 1200;

    $q = [
      'UKey' => REPORT_API_UKEY,
      'SKey' => REPORT_API_SKEY,
      'IP' => $ip,
      'Reason' => $reason,
      'ua' => $ua,
    ];
    // Optional extra context (detection modes, etc.)
    if ($tmp !== '') {
      $q['tmp'] = substr($tmp, 0, 200);
    }

    $params = http_build_query($q);
$url = $base . '?' . $params;

    error_log("REPORT_BEGIN curl=" . (function_exists('curl_init') ? "1" : "0") . " url=" . substr($url, 0, 200));

    if (function_exists('curl_init')) {
      $ch = curl_init($url);
      curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT_MS => $timeoutMs,
        CURLOPT_CONNECTTIMEOUT_MS => $timeoutMs,
        CURLOPT_HTTPGET => true,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2,
      ]);

      $resp = @curl_exec($ch);
      if ($resp === false) {
        error_log("REPORT_CURL_ERR: " . curl_error($ch));
      }
      $code = (int)curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
      error_log("REPORT_END http=" . $code . " resp_len=" . (is_string($resp) ? strlen($resp) : -1));
      @curl_close($ch);
      return;
    }

    $timeoutSec = max(1, (int)ceil($timeoutMs / 1000));
    $ctx = stream_context_create([
      'http' => [
        'method' => 'GET',
        'timeout' => $timeoutSec,
        'ignore_errors' => true,
      ],
      'ssl' => [
        'verify_peer' => true,
        'verify_peer_name' => true,
      ],
    ]);

    $resp = @file_get_contents($url, false, $ctx);
    if ($resp === false) {
      $e = error_get_last();
      error_log("REPORT_FGC_ERR: " . json_encode($e));
    } else {
      error_log("REPORT_END fgc resp_len=" . strlen($resp));
    }
  } catch (Throwable $e) {
    error_log("REPORT_THROW: " . $e->getMessage());
  }
}

function report_user_agent(string $ua): void {
  try {
    $ua = trim($ua);
    if ($ua === '') return;

    $base = REPORT_UA_BASE;
    $timeoutMs = 1200;
    $ua = substr($ua, 0, 512);

    $payload = json_encode([
      'UKey' => REPORT_API_UKEY,
      'SKey' => REPORT_API_SKEY,
      'ua' => $ua,
    ], JSON_UNESCAPED_UNICODE);
    if (!is_string($payload)) return;

    if (function_exists('curl_init')) {
      $ch = curl_init($base);
      curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT_MS => $timeoutMs,
        CURLOPT_CONNECTTIMEOUT_MS => $timeoutMs,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $payload,
        CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2,
      ]);

      $resp = @curl_exec($ch);
      if ($resp === false) {
        error_log("REPORT_UA_CURL_ERR: " . curl_error($ch));
      }
      @curl_close($ch);
      return;
    }

    $timeoutSec = max(1, (int)ceil($timeoutMs / 1000));
    $ctx = stream_context_create([
      'http' => [
        'method' => 'POST',
        'header' => "Content-Type: application/json\r\n",
        'content' => $payload,
        'timeout' => $timeoutSec,
        'ignore_errors' => true,
      ],
      'ssl' => [
        'verify_peer' => true,
        'verify_peer_name' => true,
      ],
    ]);

    $resp = @file_get_contents($base, false, $ctx);
    if ($resp === false) {
      $e = error_get_last();
      error_log("REPORT_UA_FGC_ERR: " . json_encode($e));
    }
  } catch (Throwable $e) {
    error_log("REPORT_UA_THROW: " . $e->getMessage());
  }
}

function is_trap_uri(string $uri, array $patterns): bool {
  foreach ($patterns as $rx) {
    if (@preg_match($rx, $uri) === 1) {
      return true;
    }
  }
  return false;
}

function rdns_lookup(string $ip): string {
  $h = @gethostbyaddr($ip);
  if (!$h || $h === $ip) return '';
  return strtolower(rtrim($h, '.'));
}

function forward_dns_contains_ip(string $hostname, string $ip): bool {
  if ($hostname === '') return false;

  if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
    $records = @dns_get_record($hostname, DNS_A);
    if (!is_array($records)) return false;
    foreach ($records as $r) {
      if (($r['ip'] ?? '') === $ip) return true;
    }
    return false;
  }

  if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
    $records = @dns_get_record($hostname, DNS_AAAA);
    if (!is_array($records)) return false;
    foreach ($records as $r) {
      if (($r['ipv6'] ?? '') === $ip) return true;
    }
    return false;
  }

  return false;
}

function ends_with_any(string $s, array $suffixes): bool {
  foreach ($suffixes as $sf) {
    $sf = strtolower($sf);
    if ($sf !== '' && str_ends_with($s, $sf)) return true;
  }
  return false;
}

// Retourne null si OK / pas concerné, sinon service usurpé (ex: facebook)
function detect_fake_verifiable_bot(string $ip, string $ua, array $bots): ?string {
  foreach ($bots as $b) {
    if (preg_match($b['ua_regex'], $ua) !== 1) continue;

    $ptr = rdns_lookup($ip);
    if ($ptr === '' || !ends_with_any($ptr, $b['rdns_suffixes'])) {
      return (string)$b['service'];
    }

    if (!empty($b['forward_must_match_ip'])) {
      if (!forward_dns_contains_ip($ptr, $ip)) {
        return (string)$b['service'];
      }
    }

    // Bot légitime
    return null;
  }
  return null;
}

function set_cookie(string $name, string $value, int $ttlSeconds): void {
  setcookie($name, $value, [
    'expires' => time() + $ttlSeconds,
    'path' => '/',
    'secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'),
    'httponly' => false,
    'samesite' => 'Lax',
  ]);
}

function send_browser_challenge(): never {
  // Marque qu'on a déjà servi le challenge
  set_cookie(COOKIE_TRIED, '1', COOKIE_TTL);

  header('Content-Type: text/html; charset=utf-8');
  header('Cache-Control: no-store');

  $ttl = COOKIE_TTL;
  ?>
<!doctype html>
<html lang="fr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>Vérification…</title>
</head>
<body>
<noscript><p>JavaScript est nécessaire.</p></noscript>
<script>
  (function(){
    // === Bot / headless detection (Puppeteer/Playwright) ===
    // Techniques: UA "HeadlessChrome", navigator.webdriver, CDP side-effect (with guard), + weak signals.
    function beacon(payload){
      try {
        var body = JSON.stringify(payload || {});
        if (navigator.sendBeacon) {
          navigator.sendBeacon(location.pathname + "?bp_report=1", body);
        } else {
          fetch(location.pathname + "?bp_report=1", {method:"POST", headers:{"Content-Type":"application/json"}, body: body, keepalive:true});
        }
      } catch(e) {}
    }

    var signals = {};
    try { signals.ua = navigator.userAgent || ""; } catch(e) { signals.ua = ""; }
    try { signals.webdriver = !!navigator.webdriver; } catch(e) { signals.webdriver = null; }
    try { signals.pluginsLen = (navigator.plugins && navigator.plugins.length) || 0; } catch(e) { signals.pluginsLen = null; }
    try { signals.languages = (navigator.languages && navigator.languages.slice(0,5)) || []; } catch(e) { signals.languages = null; }
    try { signals.chromeObj = !!window.chrome; } catch(e) { signals.chromeObj = null; }

    // HeadlessChrome in UA (classic headless)
    var headlessUA = false;
    try { headlessUA = (signals.ua.indexOf("HeadlessChrome") !== -1); } catch(e) {}

    // CDP detection (can false-positive when devtools are open) -> guard with weak signals
    var cdpDetected = false;
    try {
      var e = new Error();
      Object.defineProperty(e, 'stack', { get: function(){ cdpDetected = true; }});
      // Important: console.log triggers serialization in CDP
      console.log(e);
    } catch(e) {}

    // Weak signals to reduce CDP-only false positives
    var weak = 0;
    try { if (signals.pluginsLen === 0) weak++; } catch(e) {}
    try { if (signals.languages && signals.languages.length === 0) weak++; } catch(e) {}
    try { if (signals.chromeObj === false) weak++; } catch(e) {}

    // Optional: permissions query (no prompt, just state)
    try {
      if (navigator.permissions && navigator.permissions.query) {
        navigator.permissions.query({name:'notifications'}).then(function(r){
          signals.notificationsPerm = r && r.state ? r.state : null;
          // In some headless contexts, notifications tend to be "denied"
          if (signals.notificationsPerm === 'denied') weak++;
          finalize();
        }).catch(function(){ finalize(); });
        return; // finalize async
      }
    } catch(e) {}

    function finalize(){
      signals.cdp = !!cdpDetected;
      signals.weak = weak;

      var isBot = false;
      var reasons = [];
      if (headlessUA) { isBot = true; reasons.push("ua_headlesschrome"); }
      if (signals.webdriver) { isBot = true; reasons.push("navigator_webdriver"); }
      if (cdpDetected && weak >= 1) { isBot = true; reasons.push("cdp_side_effect"); }

      if (isBot) {
        beacon({type:"headless_detection", reasons: reasons, signals: signals, ts: Date.now()});
      }

      // Always set the cookie and reload (same behavior as before)
      try {
        document.cookie = "<?= COOKIE_OK ?>=1; Max-Age=<?= (int)$ttl ?>; Path=/; SameSite=Lax";
      } catch(e) {}
      location.reload();
    }

    finalize();
  })();
</script>
<p>Vérification en cours…</p>
</body>
</html>
<?php
  exit;
}

// -------------------------
// INPUTS
// -------------------------

$host = normalize_host($_SERVER['HTTP_HOST'] ?? '');
if ($host === '') fail(400, 'Bad Request');

$uri = $_SERVER['REQUEST_URI'] ?? '/';
$ua  = $_SERVER['HTTP_USER_AGENT'] ?? '';
$ip  = get_client_ip($TRUSTED_PROXIES);
if ($ip === '') $ip = ($_SERVER['REMOTE_ADDR'] ?? '');


// -------------------------
// Endpoint: browser-side bot report (from JS challenge)
// -------------------------
if (isset($_GET['bp_report'])) {
  // Accept both sendBeacon (text/plain) and fetch (application/json)
  $raw = file_get_contents('php://input') ?: '';
  $json = json_decode($raw, true);
  if (is_array($json)) {
    $reasons = $json['reasons'] ?? [];
    if (is_string($reasons)) $reasons = [$reasons];
    if (!is_array($reasons)) $reasons = [];
    $reasons = array_values(array_filter(array_map(static fn($v) => is_string($v) ? substr($v, 0, 80) : '', $reasons)));
    $reason = 'fakebrowser-headless';
    $tmp = '';
    if (!empty($reasons)) $tmp = implode(',', $reasons);

    // Include a tiny bit of context (do not log full fingerprint)
    report_event($ip, $reason, $ua, $tmp);
} else {
    // Still log, but with minimal info
    report_event($ip, 'fakebrowser-headless', $ua, 'invalid_payload');
  }
  http_response_code(204);
  exit;
}


// -------------------------
// DETECTIONS (report only)
// -------------------------

// Headless / automation hints from HTTP headers (server-side)
$uaLower = strtolower($ua);
$secChUa = $_SERVER['HTTP_SEC_CH_UA'] ?? '';
$acceptLang = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '';

// 1) Classic HeadlessChrome substring (UA / client hints)
if (stripos($ua, 'HeadlessChrome') !== false) {
  report_event($ip, 'fakebrowser-headless', $ua, 'ua_headlesschrome');
}
if ($secChUa !== '' && stripos($secChUa, 'HeadlessChrome') !== false) {
  report_event($ip, 'fakebrowser-headless', $ua, 'secchua_headlesschrome');
}

// 2) Chromium without Accept-Language can be a headless automation default.
// We only report when UA looks Chromium-based to reduce false positives.
if ($acceptLang === '' && (stripos($ua, 'Chrome/') !== false || stripos($ua, 'Chromium') !== false)) {
  report_event($ip, 'fakebrowser-headless', $ua, 'missing_accept_language');
}



// Trapfile
// Trapfile : report + blocage immédiat
if (is_trap_uri($uri, $TRAP_URI_REGEX)) {
  // Le report ne doit jamais empêcher le 404
  report_event($ip, 'trapfile', $ua);

  http_response_code(404);
  header('Content-Type: text/plain; charset=utf-8');
  echo "Not Found";
  exit;
}

// Fake verifiable bot
$fakeService = detect_fake_verifiable_bot($ip, $ua, $VERIFIABLE_BOTS);
if ($fakeService !== null && $fakeService !== '') {
  report_event($ip, 'fakebot-' . $fakeService, $ua);
}

// Fake browser check:
// - si UA "browser" et pas cookie OK : on sert challenge une fois
// - si UA "browser" et challenge déjà servi (COOKIE_TRIED=1) mais toujours pas OK => fakebrowser + on continue
$isBrowserUA = (preg_match($BROWSER_UA_REGEX, $ua) === 1)
  && (preg_match($BOT_TOKEN_UA_REGEX, $ua) !== 1);
$cookieOk = (($_COOKIE[COOKIE_OK] ?? '') === '1');
$cookieTried = (($_COOKIE[COOKIE_TRIED] ?? '') === '1');

if ($isBrowserUA && !$cookieOk) {
  if ($cookieTried) {
    report_event($ip, 'fakebrowser', $ua);
    // on ne boucle pas en challenge, on continue vers action PARK/REDIRECT
  } else {
    send_browser_challenge();
  }
}

// UA catalog uniquement si aucune attaque signalée
if (trim($ua) !== '' && empty($GLOBALS['reportAttack'])) {
  report_user_agent($ua);
}

// -------------------------
// DB lookup action
// -------------------------

try {
  $pdo = new PDO(DB_DSN, DB_USER, DB_PASS, [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
  ]);
} catch (Throwable $e) {
  fail(500, 'Internal Server Error');
}

$stmt = $pdo->prepare("SELECT action, redirect_url, enabled FROM nddparking WHERE ndd = :ndd LIMIT 1");

// direct host
$stmt->execute([':ndd' => $host]);
$row = $stmt->fetch();

// www -> apex
if (!$row && str_starts_with($host, 'www.')) {
  $apex = substr($host, 4);
  $stmt->execute([':ndd' => $apex]);
  $row = $stmt->fetch();
}

if (!$row || !$row['enabled']) {
  fail(404, 'Not Found');
}

// -------------------------
// Apply action
// -------------------------

if (($row['action'] ?? '') === 'REDIRECT') {
  $target = (string)($row['redirect_url'] ?? '');
  if ($target !== '') {
    header('Location: ' . $target, true, REDIRECT_STATUS);
    exit;
  }
  // config invalide => fallback parking (et tu peux aussi reporter si tu veux)
}

// PARK
header('Content-Type: text/html; charset=utf-8');
$hostEsc = htmlspecialchars($host, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');

// Image (points 1 & 4)
// - Si imgurl est vide => image par défaut
// - Si imgurl n'est pas une URL http/https valide => image par défaut
$defaultImg = 'https://openwebparking.com/openweb-parking-logo.png';
$imgCandidate = trim((string)($row['imgurl'] ?? ''));
$imgSrc = $defaultImg;
if ($imgCandidate !== '' && filter_var($imgCandidate, FILTER_VALIDATE_URL)) {
  $p = @parse_url($imgCandidate);
  $scheme = strtolower((string)($p['scheme'] ?? ''));
  if ($scheme === 'http' || $scheme === 'https') {
    $imgSrc = $imgCandidate;
  }
}

$imgSrcEsc = htmlspecialchars($imgSrc, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
$defaultImgEsc = htmlspecialchars($defaultImg, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
?>
<!doctype html>
<html lang="fr">
<head>
  <meta charset="utf-8">
  <title>Domaine en parking</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    body{font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;background:#f5f5f5;color:#333;margin:0}
    main{max-width:720px;margin:10vh auto;background:#fff;padding:2rem;border-radius:10px;box-shadow:0 10px 25px rgba(0,0,0,.1);text-align:center}
    .parking-image{display:block;margin:2rem auto;max-width:280px;width:100%;height:auto}
    footer{margin-top:2rem;font-size:.9rem;color:#777}
  </style>
</head>
<body>
<main>
  <h1>Ce domaine est en parking</h1>
  <p><strong><?= $hostEsc ?></strong></p>
  <img
    class="parking-image"
    src="<?= $imgSrcEsc ?>"
    alt="Parking"
    onerror="this.onerror=null;this.src='<?= $defaultImgEsc ?>';"
  >
  <p>Ce nom de domaine n’est pas encore utilisé.</p>
  <footer>&copy; <?= date('Y') ?><br />Openweb Parking est un service de LEMNIA SAS</footer>
</main>
</body>
</html>
