<?php
require_once 'config.php';

/**
 * Mendeteksi ID CPU dari critical data dalam file biner
 * 
 * @param string $binPath Jalur ke file biner
 * @return array [status, cpuId]
 */
function detectCpuIdFromCriticaldata($binPath) {
    try {
        // Baca isi file dengan encoding UTF-8 dan abaikan kesalahan
        $isiFile = file_get_contents($binPath);
        if ($isiFile === false) {
            return ["gagal", "cpuId tidak ditemukan"];
        }

        // Cari pola criticalData dalam hex
        if (!preg_match('/criticalData:([0-9a-fA-F]+)/', $isiFile, $cocok)) {
            return ["criticalData tidak ditemukan", "cpuId tidak ditemukan"];
        }

        $hexdata = $cocok[1];

        // Ubah seluruh data hex menjadi byte
        $bindata = hex2bin($hexdata);
        if ($bindata === false) {
            return ["format criticalData salah", "cpuId tidak ditemukan"];
        }

        // Ubah byte menjadi karakter ASCII yang bisa dibaca
        $asciiSemua = '';
        for ($i = 0; $i < strlen($bindata); $i++) {
            $char = $bindata[$i];
            if (ord($char) >= 0x20 && ord($char) <= 0x7E) {
                $asciiSemua .= $char;
            }
        }

        // --- Coba pola Qualcomm terlebih dahulu (berdasarkan '3078' hex = '0x') ---
        $indeksHex = strpos($hexdata, '3078');
        if ($indeksHex !== false) {
            $sisaHex = substr($hexdata, $indeksHex);
            $sisaByte = hex2bin($sisaHex);
            if ($sisaByte === false) {
                return ["format criticalData salah", "cpuId tidak ditemukan"];
            }

            $asciiStr = '';
            $cpuId = '';
            $mulaiAmbil = false;

            for ($i = 0; $i < strlen($sisaByte); $i++) {
                $char = $sisaByte[$i];
                $nilaiByte = ord($char);
                $bisaDibaca = ($nilaiByte >= 0x20 && $nilaiByte <= 0x7E);

                if ($bisaDibaca) {
                    $asciiStr .= $char;
                    if ($mulaiAmbil) {
                        if (strpos('0123456789abcdefABCDEF', $char) !== false) {
                            $cpuId .= $char;
                        } else {
                            break;
                        }
                    } else {
                        if (substr($asciiStr, -2) === '0x') {
                            $cpuId = '0x';
                            $mulaiAmbil = true;
                        }
                    }
                } else {
                    if ($mulaiAmbil) {
                        break;
                    }
                }
            }

            if ($mulaiAmbil && strlen($cpuId) > 2) {
                return ["criticalData", $cpuId];
            }
        }

        // --- Jika pola Qualcomm gagal, coba pola Mediatek: 0x + 32 hex di akhir ---
        if (preg_match('/0x[a-fA-F0-9]{32}$/', $asciiSemua, $cocokCpu)) {
            return ["criticalData", $cocokCpu[0]];
        }

        file_put_contents('debug.log', "ERROR: Pola CPU ID tidak ditemukan (Mediatek/Qualcomm).\n", FILE_APPEND);
        return ["criticalData tidak ditemukan", "cpuId tidak ditemukan"];
    } catch (Exception $e) {
        return ["gagal", "cpuId tidak ditemukan"];
    }
}

/**
 * Mendeteksi MAC WiFi dan Bluetooth dari file critical data
 * 
 * @param string $binPath Jalur ke file biner
 * @return array [wifiMac, btMac]
 */
function detectMacsFromCriticaldata($binPath) {
    try {
        $isiFile = file_get_contents($binPath);
        if ($isiFile === false) {
            return [null, null];
        }

        if (!preg_match('/criticalData:([0-9a-fA-F]+)/', $isiFile, $cocok)) {
            return [null, null];
        }

        $hexdata = strtolower($cocok[1]);
        $wifiMac = null;
        $btMac = null;
        $macDitemukan = [];

        $decodeMac = function($encoded) {
            if (strlen($encoded) !== 24 || !preg_match('/^[a-f0-9]{24}$/', $encoded)) return null;
            $hasil = '';
            for ($i = 0; $i < 24; $i += 2) {
                $hasil .= chr(hexdec(substr($encoded, $i, 2)));
            }
            if (preg_match('/^[a-f0-9]{12}$/i', $hasil) && !preg_match('/^(0{12}|f{12})$/i', $hasil)) {
                return strtoupper($hasil);
            }
            return null;
        };

        // Coba format TLV: [Tipe:2_hex][Panjang:0c][MAC:24_hex]
        if (preg_match_all('/([0-9a-f]{2})(0c)([0-9a-f]{24})/', $hexdata, $hasil, PREG_SET_ORDER)) {
            foreach ($hasil as $match) {
                $tipe = $match[1];
                $macEncoded = $match[3];
                $macAsli = $decodeMac($macEncoded);

                if ($macAsli && !in_array($macAsli, $macDitemukan)) {
                    if ($tipe === '05' && !$wifiMac) {
                        $wifiMac = $macAsli;
                        $macDitemukan[] = $macAsli;
                    } elseif ($tipe === '06' && !$btMac) {
                        $btMac = $macAsli;
                        $macDitemukan[] = $macAsli;
                    }
                    if ($wifiMac && $btMac) break;
                }
            }
        }

        // Coba pakai keyword seperti "wifi", "wlan", "bt", dst
        if (!$wifiMac || !$btMac) {
            $keyword = [
                'wifi' => ['77696669', '776c616e'],
                'bt'   => ['6274', '626c7565746f6f7468']
            ];

            $ambilSetelahKeyword = function($kw, $data) use (&$macDitemukan) {
                $pos = strpos($data, $kw);
                if ($pos !== false) {
                    for ($o = 0; $o <= 4; $o += 2) {
                        $mac = substr($data, $pos + strlen($kw) + $o, 12);
                        if (preg_match('/^[a-f0-9]{12}$/', $mac) && !preg_match('/^(0{12}|f{12})$/', $mac)) {
                            $mac = strtoupper($mac);
                            if (!in_array($mac, $macDitemukan)) {
                                $macDitemukan[] = $mac;
                                return $mac;
                            }
                        }
                    }
                }
                return null;
            };

            if (!$wifiMac) {
                foreach ($keyword['wifi'] as $kw) {
                    if ($ditemukan = $ambilSetelahKeyword($kw, $hexdata)) {
                        $wifiMac = $ditemukan;
                        break;
                    }
                }
            }

            if (!$btMac) {
                foreach ($keyword['bt'] as $kw) {
                    if ($ditemukan = $ambilSetelahKeyword($kw, $hexdata)) {
                        $btMac = $ditemukan;
                        break;
                    }
                }
            }
        }

        // Coba fallback ke semua kandidat 12 digit hex
        if (!$wifiMac || !$btMac) {
            preg_match_all('/([a-f0-9]{12})/', $hexdata, $cocokSemua);
            $semuaMac = array_map('strtoupper', array_unique(array_filter($cocokSemua[1], function($mac) {
                return !preg_match('/^(0{12}|f{12})$/', $mac);
            })));

            $ouisXiaomi = ['38C6BD', '7C1EB3', 'F0B429', 'D8C4E9', 'A0C5F2'];
            if (!$wifiMac) {
                foreach ($semuaMac as $mac) {
                    foreach ($ouisXiaomi as $oui) {
                        if (strpos($mac, $oui) === 0) {
                            $wifiMac = $mac;
                            break 2;
                        }
                    }
                }
                if (!$wifiMac && isset($semuaMac[0])) {
                    $wifiMac = $semuaMac[0];
                }
            }

            if (!$btMac && isset($semuaMac[1])) {
                $btMac = $semuaMac[1];
            }
        }

        return [$wifiMac, $btMac];
    } catch (Exception $e) {
        return [null, null];
    }
}

// Proses AJAX: jika file dikirim, kirim JSON balik
if (isset($_GET['action']) && $_GET['action'] === 'getCpuId' && isset($_FILES['binFile'])) {
    header('Content-Type: application/json');
    $binPath = $_FILES['binFile']['tmp_name'];
    list($status, $cpuId) = detectCpuIdFromCriticaldata($binPath);
    list($wifiMac, $btMac) = detectMacsFromCriticaldata($binPath);
    echo json_encode(['status' => $status, 'cpuId' => $cpuId, 'wifiMac' => $wifiMac, 'btMac' => $btMac]);
    exit;
}

/**
 * Buat nonce unik untuk autentikasi
 */
function generateNonce() {
    $acak = substr(base64_encode(random_bytes(33)), 0, 44);
    $acak = str_replace(['+', '/', '='], ['-', '_', ''], $acak);
    $timestamp = (string)(round(microtime(true) * 1000));
    return $acak . $timestamp;
}

/**
 * Hitung tanda tangan untuk permintaan API
 */
function computeSignature($dataB64, $nonce, $timestamp, $sid, $salt) {
    $input = "POST\n/factory/encrypt/deviceInfo\n" .
             "data={$dataB64}&nonce={$nonce}&sid={$sid}&timestamp={$timestamp}";
    return hash_hmac('sha1', $input, $salt, false);
}

/**
 * Ambil token otentikasi dari server
 */
function getAuthToken() {
    $header = [
        'AuthId: ' . AUTH_ID,
        'AuthKey: ' . AUTH_KEY,
        'Content-Type: application/x-www-form-urlencoded;charset=UTF-8'
    ];
    $curl = curl_init(AUTH_URL);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, '');
    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    curl_setopt($curl, CURLOPT_TIMEOUT, 20);

    $response = curl_exec($curl);
    curl_close($curl);

    if ($response === false) return null;
    $json = json_decode($response, true);
    if (json_last_error() === JSON_ERROR_NONE) {
        foreach (['token', 'authKey', 'authorization', 'access_token', 'data'] as $k) {
            if (isset($json[$k])) return $json[$k];
        }
    }
    return trim($response);
}

/**
 * Kirim permintaan enkripsi ke server
 */
function tryRequest($params) {
    extract($params);
    $jsonStr = json_encode([
        'product' => $product, 'cpuId' => $cpuId, 'realCpuId' => $cpuId,
        'imei1' => $imei1, 'imei2' => $imei2, 'meid' => $meid ?? '',
        'wifiMac' => $wifiMac, 'btMac' => $btMac, 'ufsId' => $ufsId ?? ''
    ]);
    $dataB64 = base64_encode($jsonStr);
    $nonce = generateNonce();
    $timestamp = (string)(round(microtime(true) * 1000));
    $signature = computeSignature($dataB64, $nonce, $timestamp, $sid, $salt);

    $post = http_build_query([
        'sid' => $sid, 'data' => $dataB64, 'nonce' => $nonce,
        'timestamp' => $timestamp, 'sign' => $signature
    ]);

    $auth = getAuthToken();
    if (!$auth) return [null, null, "auth_error"];

    $headers = [
        'Content-Type: application/x-www-form-urlencoded',
        'Accept: */*',
        'User-Agent: MiTool/1.0',
        'Authorization: Bearer ' . $auth
    ];

    $curl = curl_init(ENCRYPT_URL);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($curl, CURLOPT_TIMEOUT, 30);

    $res = curl_exec($curl);
    $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    $error = curl_error($curl);
    curl_close($curl);

    if ($res === false) return [null, null, "Gagal: $error"];
    return [$status, $res, null];
}

/**
 * Validasi input CPU ID manual
 */
function validateManualCpuId($cpuId) {
    $cpuId = trim($cpuId);
    if (empty($cpuId)) return ['valid' => false, 'error' => 'CPU ID tidak boleh kosong'];
    $cpuId = preg_replace('/^(0x)+/i', '', $cpuId);
    $cpuId = preg_replace('/[^a-fA-F0-9]/', '', $cpuId);

    if (empty($cpuId)) return ['valid' => false, 'error' => 'CPU ID mengandung karakter tidak valid'];
    if (!preg_match('/^[a-fA-F0-9]+$/', $cpuId)) return ['valid' => false, 'error' => 'Hanya karakter hex yang diizinkan'];
    if (!in_array(strlen($cpuId), [8, 16, 32])) return ['valid' => false, 'error' => 'Panjang CPU ID harus 8, 16, atau 32 karakter'];
    if (preg_match('/^0+$/', $cpuId) || preg_match('/^f+$/i', $cpuId)) return ['valid' => false, 'error' => 'CPU ID tidak boleh semua 0 atau F'];

    return ['valid' => true, 'cpuId' => '0x' . strtoupper($cpuId)];
}
?>
