84 lines
2.3 KiB
PHP
84 lines
2.3 KiB
PHP
<?php
|
|
// ❌ No header() here
|
|
|
|
require_once __DIR__ . '/../.hta_lib/maxmind-db-reader/autoload.php';
|
|
|
|
use MaxMind\Db\Reader;
|
|
|
|
function respond($status, $data = null, $error = null)
|
|
{
|
|
echo json_encode([
|
|
'success' => $status,
|
|
'data' => $data,
|
|
'error' => $error
|
|
], JSON_PRETTY_PRINT);
|
|
exit;
|
|
}
|
|
|
|
if (!isset($_GET['ip']) || trim($_GET['ip']) === '') {
|
|
respond(false, null, 'IP parameter is required');
|
|
}
|
|
|
|
$ip = trim($_GET['ip']);
|
|
|
|
if (!filter_var($ip, FILTER_VALIDATE_IP)) {
|
|
respond(false, null, 'Invalid IP address');
|
|
}
|
|
|
|
try {
|
|
$cityReader = new Reader(__DIR__ . '/../.hta_lib/data/GeoLite2-City.mmdb');
|
|
$asnReader = new Reader(__DIR__ . '/../.hta_lib/data/GeoLite2-ASN.mmdb');
|
|
|
|
$cityData = $cityReader->get($ip);
|
|
$asnData = $asnReader->get($ip);
|
|
|
|
$cityReader->close();
|
|
$asnReader->close();
|
|
|
|
$response = [
|
|
'ip' => $ip,
|
|
|
|
'continent' => [
|
|
'name' => $cityData['continent']['names']['en'] ?? null,
|
|
'code' => $cityData['continent']['code'] ?? null
|
|
],
|
|
|
|
'country' => [
|
|
'name' => $cityData['country']['names']['en'] ?? null,
|
|
'code' => $cityData['country']['iso_code'] ?? null
|
|
],
|
|
|
|
'state' => [
|
|
'name' => $cityData['subdivisions'][0]['names']['en'] ?? null,
|
|
'code' => $cityData['subdivisions'][0]['iso_code'] ?? null
|
|
],
|
|
|
|
'city' => $cityData['city']['names']['en'] ?? null,
|
|
|
|
'timezone' => $cityData['location']['time_zone'] ?? null,
|
|
|
|
'location' => [
|
|
'latitude' => $cityData['location']['latitude'] ?? null,
|
|
'longitude' => $cityData['location']['longitude'] ?? null
|
|
],
|
|
|
|
'postal_code' => $cityData['postal']['code'] ?? null,
|
|
|
|
'asn' => [
|
|
'number' => $asnData['autonomous_system_number'] ?? null,
|
|
'org' => $asnData['autonomous_system_organization'] ?? null
|
|
],
|
|
];
|
|
|
|
$anycastASN = [15169, 13335, 36692];
|
|
$response['is_anycast'] = in_array($response['asn']['number'], $anycastASN);
|
|
$response['note'] = $response['is_anycast']
|
|
? 'Anycast IP detected. Location may vary.'
|
|
: 'IP-based location is approximate.';
|
|
|
|
respond(true, $response);
|
|
|
|
} catch (Exception $e) {
|
|
respond(false, null, $e->getMessage());
|
|
}
|