151 lines
5.9 KiB
PHP
151 lines
5.9 KiB
PHP
<?php
|
|
if (session_status() === PHP_SESSION_NONE) session_start();
|
|
header('Content-Type: application/json');
|
|
|
|
if (!isset($_SESSION['user_id'])) {
|
|
echo json_encode(['success' => false, 'message' => 'Unauthorized']);
|
|
exit;
|
|
}
|
|
|
|
include 'koneksi.php';
|
|
|
|
function getDeviceDetail($ua) {
|
|
$detail = ['type' => 'Unknown', 'brand' => '', 'os' => ''];
|
|
$uaLower = strtolower($ua);
|
|
|
|
// Detect OS
|
|
if (strpos($uaLower, 'windows nt 10') !== false) {
|
|
$detail['os'] = 'Windows 10/11';
|
|
$detail['type'] = 'Windows PC';
|
|
} elseif (strpos($uaLower, 'windows nt 6.3') !== false) {
|
|
$detail['os'] = 'Windows 8.1';
|
|
$detail['type'] = 'Windows PC';
|
|
} elseif (strpos($uaLower, 'windows nt 6.1') !== false) {
|
|
$detail['os'] = 'Windows 7';
|
|
$detail['type'] = 'Windows PC';
|
|
} elseif (strpos($uaLower, 'windows') !== false) {
|
|
$detail['os'] = 'Windows';
|
|
$detail['type'] = 'Windows PC';
|
|
} elseif (strpos($uaLower, 'macintosh') !== false || strpos($uaLower, 'mac os x') !== false) {
|
|
// Extract macOS version
|
|
if (preg_match('/mac os x (\d+[\._]\d+[\._]?\d*)/i', $ua, $m)) {
|
|
$ver = str_replace('_', '.', $m[1]);
|
|
$detail['os'] = 'macOS ' . $ver;
|
|
} else {
|
|
$detail['os'] = 'macOS';
|
|
}
|
|
$detail['type'] = 'Mac';
|
|
$detail['brand'] = 'Apple';
|
|
} elseif (strpos($uaLower, 'iphone') !== false) {
|
|
$detail['type'] = 'iPhone';
|
|
$detail['brand'] = 'Apple';
|
|
if (preg_match('/iphone os (\d+[\._]\d+)/i', $ua, $m)) {
|
|
$detail['os'] = 'iOS ' . str_replace('_', '.', $m[1]);
|
|
} else {
|
|
$detail['os'] = 'iOS';
|
|
}
|
|
} elseif (strpos($uaLower, 'ipad') !== false) {
|
|
$detail['type'] = 'iPad';
|
|
$detail['brand'] = 'Apple';
|
|
if (preg_match('/cpu os (\d+[\._]\d+)/i', $ua, $m)) {
|
|
$detail['os'] = 'iPadOS ' . str_replace('_', '.', $m[1]);
|
|
} else {
|
|
$detail['os'] = 'iPadOS';
|
|
}
|
|
} elseif (strpos($uaLower, 'android') !== false) {
|
|
// Extract Android version
|
|
$androidVer = '';
|
|
if (preg_match('/android (\d+[\.\d]*)/i', $ua, $m)) {
|
|
$androidVer = $m[1];
|
|
}
|
|
$detail['os'] = 'Android' . ($androidVer ? ' ' . $androidVer : '');
|
|
|
|
// Try to detect brand/model from user agent
|
|
// Common pattern: Android X.X; BRAND MODEL Build/...
|
|
$detail['brand'] = '';
|
|
if (preg_match('/;\s*([^;)]+)\s*Build\//i', $ua, $m)) {
|
|
$model = trim($m[1]);
|
|
// Clean up common prefixes
|
|
$brandMap = [
|
|
'SM-' => 'Samsung', 'GT-' => 'Samsung', 'SAMSUNG' => 'Samsung',
|
|
'Redmi' => 'Xiaomi', 'Mi ' => 'Xiaomi', 'POCO' => 'Xiaomi POCO', 'M2' => 'Xiaomi',
|
|
'vivo' => 'Vivo', 'V2' => 'Vivo',
|
|
'OPPO' => 'OPPO', 'CPH' => 'OPPO', 'RMX' => 'Realme',
|
|
'Pixel' => 'Google Pixel', 'Nexus' => 'Google Nexus',
|
|
'HUAWEI' => 'Huawei', 'VOG' => 'Huawei', 'ELE' => 'Huawei',
|
|
'ASUS' => 'ASUS', 'Nokia' => 'Nokia', 'LG' => 'LG',
|
|
'Sony' => 'Sony', 'OnePlus' => 'OnePlus', 'IN2' => 'OnePlus',
|
|
'Infinix' => 'Infinix', 'TECNO' => 'Tecno', 'itel' => 'Itel',
|
|
];
|
|
$matched = false;
|
|
foreach ($brandMap as $prefix => $brand) {
|
|
if (stripos($model, $prefix) !== false) {
|
|
$detail['brand'] = $brand;
|
|
$detail['type'] = $model;
|
|
$matched = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!$matched) {
|
|
$detail['type'] = $model;
|
|
}
|
|
} else {
|
|
$detail['type'] = 'Android Device';
|
|
}
|
|
} elseif (strpos($uaLower, 'linux') !== false) {
|
|
$detail['os'] = 'Linux';
|
|
$detail['type'] = 'Linux PC';
|
|
}
|
|
|
|
return $detail;
|
|
}
|
|
|
|
function getBrowserName($ua) {
|
|
// Order matters: check Edge before Chrome, check Chrome before Safari
|
|
if (preg_match('/Edg[e\/]?\s*(\d+[\.\d]*)/i', $ua, $m)) return 'Edge ' . intval($m[1]);
|
|
if (preg_match('/OPR\/(\d+[\.\d]*)/i', $ua, $m)) return 'Opera ' . intval($m[1]);
|
|
if (preg_match('/Chrome\/(\d+[\.\d]*)/i', $ua, $m)) return 'Chrome ' . intval($m[1]);
|
|
if (preg_match('/Firefox\/(\d+[\.\d]*)/i', $ua, $m)) return 'Firefox ' . intval($m[1]);
|
|
if (preg_match('/Version\/(\d+[\.\d]*).*Safari/i', $ua, $m)) return 'Safari ' . intval($m[1]);
|
|
if (strpos($ua, 'Safari') !== false) return 'Safari';
|
|
return 'Unknown Browser';
|
|
}
|
|
|
|
try {
|
|
$stmt = $pdo->prepare("SELECT * FROM login_history WHERE id_account = ? ORDER BY login_time DESC");
|
|
$stmt->execute([$_SESSION['user_id']]);
|
|
$logs = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
$result = [];
|
|
foreach ($logs as $log) {
|
|
$time = strtotime($log['login_time']);
|
|
$device = getDeviceDetail($log['device_info']);
|
|
$browser = getBrowserName($log['device_info']);
|
|
|
|
// Build display name
|
|
$deviceName = $device['type'];
|
|
if ($device['brand'] && stripos($device['type'], $device['brand']) === false) {
|
|
$deviceName = $device['brand'] . ' ' . $device['type'];
|
|
}
|
|
|
|
$isDesktop = in_array($device['type'], ['Windows PC', 'Mac', 'Linux PC']) ||
|
|
strpos(strtolower($device['os']), 'windows') !== false ||
|
|
strpos(strtolower($device['os']), 'macos') !== false ||
|
|
strpos(strtolower($device['os']), 'linux') !== false;
|
|
|
|
$result[] = [
|
|
'date' => date('d F Y', $time),
|
|
'time' => date('H:i:s', $time),
|
|
'device' => $deviceName,
|
|
'os' => $device['os'],
|
|
'browser' => $browser,
|
|
'ip' => $log['ip_address'],
|
|
'is_desktop' => $isDesktop
|
|
];
|
|
}
|
|
|
|
echo json_encode(['success' => true, 'logs' => $result]);
|
|
} catch (PDOException $e) {
|
|
echo json_encode(['success' => false, 'message' => 'Database error']);
|
|
}
|