Skip to content

Commit

Permalink
Added support for district, ASN and AS
Browse files Browse the repository at this point in the history
  • Loading branch information
ip2location committed May 5, 2023
1 parent fd1879e commit e84153c
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 26 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ IP2Location (PHP Module)

*This is the official release maintained by IP2Location.com*

This PHP module provides fast lookup of country, region, city, latitude, longitude, ZIP code, time zone, ISP, domain name, connection speed, IDD code, area code, weather station code, weather station name, MNC, MCC, mobile brand, elevation, usage type, address type and IAB category from IP address by using IP2Location database. This module uses a file based database available at IP2Location.com.
This PHP module provides fast lookup of country, region, district, city, latitude, longitude, ZIP code, time zone, ISP, domain name, connection speed, IDD code, area code, weather station code, weather station name, MNC, MCC, mobile brand, elevation, usage type, address type, IAB category and ASN from IP address by using IP2Location database. This module uses a file based database available at IP2Location.com.

This module can be used in many types of projects such as:

Expand Down Expand Up @@ -50,10 +50,10 @@ Below is the description of the functions available in the **Database** class.
|---|---|
|Constructor|Expect 2 input parameters:<ol><li>Full path of IP2Location BIN data file.</li><li>File Open Mode<ul><li> SHARED_MEMORY</li><li>MEMORY_CACHE</li><li>FILE_IO</li></ul></li></ol>For SHARED_MEMORY and MEMORY_CACHE, it will require your server to have sufficient memory to hold the BIN data, otherwise it will raise the errors during the object initialization.|
|**string** getDate()|Return the database's compilation date as a string of the form 'YYYY-MM-DD'|
|**string** getType()|Return the database's type, 1 to 25 respectively for DB1 to DB25. Please visit https://www.ip2location.com/databases for details.|
|**string** getType()|Return the database's type, 1 to 26 respectively for DB1 to DB26. Please visit https://www.ip2location.com/databases for details.|
|**string** getModuleVersion()|Return the version of module|
|**string** getDatabaseVersion()|Return the version of database|
|**array** lookup($ip)|Return the IP information in array. Below is the information returned:<ul><li>ipNumber</li><li>ipVersion</li><li>ipAddress</li><li>countryCode</li><li>countryName</li><li>regionName</li><li>cityName</li><li>latitude</li><li>longitude</li><li>areaCode</li><li>iddCode</li><li>weatherStationCode</li><li>weatherStationName</li><li>mcc</li><li>mnc</li><li>mobileCarrierName</li><li>usageType</li><li>elevation</li><li>netSpeed</li><li>timeZone</li><li>zipCode</li><li>domainName</li><li>isp</li><li>addressType</li><li>category</li></ul>You can visit [IP2Location](https://www.ip2location.com/databases/db25-ip-country-region-city-latitude-longitude-zipcode-timezone-isp-domain-netspeed-areacode-weather-mobile-elevation-usagetype-addresstype-category) for the description of each field. Note: although the above names are not exactly matched with the names given in this link, but they are self-described.|
|**array** lookup($ip)|Return the IP information in array. Below is the information returned:<ul><li>ipNumber</li><li>ipVersion</li><li>ipAddress</li><li>countryCode</li><li>countryName</li><li>regionName</li><li>cityName</li><li>latitude</li><li>longitude</li><li>areaCode</li><li>iddCode</li><li>weatherStationCode</li><li>weatherStationName</li><li>mcc</li><li>mnc</li><li>mobileCarrierName</li><li>usageType</li><li>elevation</li><li>netSpeed</li><li>timeZone</li><li>zipCode</li><li>domainName</li><li>isp</li><li>addressType</li><li>category</li><li>district</li><li>asn</li><li>as</li></ul>You can visit [IP2Location](https://www.ip2location.com/databases/db26-ip-country-region-city-latitude-longitude-zipcode-timezone-isp-domain-netspeed-areacode-weather-mobile-elevation-usagetype-addresstype-category-district-asn) for the description of each field. Note: although the above names are not exactly matched with the names given in this link, but they are self-described.|
|**array** getCidr($ip)|Return an array of the complete IP list in CIDR format of the detected row record based on the given IP address.|


Expand Down
3 changes: 3 additions & 0 deletions examples/example.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@
echo 'ISP Name : ' . $records['isp'] . "\n";
echo 'Address Type : ' . $records['addressType'] . "\n";
echo 'Category : ' . $records['category'] . "\n";
echo 'District : ' . $records['district'] . "\n";
echo 'ASN : ' . $records['asn'] . "\n";
echo 'AS : ' . $records['as'] . "\n";
echo '</pre>';

echo '<pre>
Expand Down
166 changes: 143 additions & 23 deletions src/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class Database
*
* @var string
*/
public const VERSION = '9.6.1';
public const VERSION = '9.7.0';

/**
* Unsupported field message.
Expand Down Expand Up @@ -203,6 +203,27 @@ class Database
*/
public const CATEGORY = 22;

/**
* District.
*
* @var int
*/
public const DISTRICT = 23;

/**
* ASN.
*
* @var int
*/
public const ASN = 24;

/**
* AS.
*
* @var int
*/
public const AS = 25;

/**
* Country name and code.
*
Expand Down Expand Up @@ -394,28 +415,31 @@ class Database
* @var array
*/
private $columns = [
self::COUNTRY_CODE => [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8],
self::COUNTRY_NAME => [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8],
self::REGION_NAME => [0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12],
self::CITY_NAME => [0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16],
self::LATITUDE => [0, 0, 0, 0, 20, 20, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20],
self::LONGITUDE => [0, 0, 0, 0, 24, 24, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24],
self::ZIP_CODE => [0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 28, 28, 0, 28, 28, 28, 0, 28, 0, 28, 28, 28, 0, 28, 28],
self::TIME_ZONE => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 28, 32, 32, 32, 28, 32, 0, 32, 32, 32, 0, 32, 32],
self::ISP => [0, 12, 0, 20, 0, 28, 20, 28, 0, 32, 0, 36, 0, 36, 0, 36, 0, 36, 28, 36, 0, 36, 28, 36, 36],
self::DOMAIN_NAME => [0, 0, 0, 0, 0, 0, 24, 32, 0, 36, 0, 40, 0, 40, 0, 40, 0, 40, 32, 40, 0, 40, 32, 40, 40],
self::NET_SPEED => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 44, 0, 44, 32, 44, 0, 44, 0, 44, 0, 44, 44],
self::IDD_CODE => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 48, 0, 48, 0, 48, 36, 48, 0, 48, 48],
self::AREA_CODE => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 52, 0, 52, 0, 52, 40, 52, 0, 52, 52],
self::WEATHER_STATION_CODE => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 56, 0, 56, 0, 56, 0, 56, 56],
self::WEATHER_STATION_NAME => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 60, 0, 60, 0, 60, 0, 60, 60],
self::MCC => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 64, 0, 64, 36, 64, 64],
self::MNC => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 68, 0, 68, 40, 68, 68],
self::MOBILE_CARRIER_NAME => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 72, 0, 72, 44, 72, 72],
self::ELEVATION => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 76, 0, 76, 76],
self::USAGE_TYPE => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 80, 80],
self::ADDRESS_TYPE => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84],
self::CATEGORY => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88],
self::COUNTRY_CODE => [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8],
self::COUNTRY_NAME => [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8],
self::REGION_NAME => [0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12],
self::CITY_NAME => [0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16],
self::LATITUDE => [0, 0, 0, 0, 20, 20, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20],
self::LONGITUDE => [0, 0, 0, 0, 24, 24, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24],
self::ZIP_CODE => [0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 28, 28, 0, 28, 28, 28, 0, 28, 0, 28, 28, 28, 0, 28, 28, 28],
self::TIME_ZONE => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 28, 32, 32, 32, 28, 32, 0, 32, 32, 32, 0, 32, 32, 32],
self::ISP => [0, 12, 0, 20, 0, 28, 20, 28, 0, 32, 0, 36, 0, 36, 0, 36, 0, 36, 28, 36, 0, 36, 28, 36, 36, 36],
self::DOMAIN_NAME => [0, 0, 0, 0, 0, 0, 24, 32, 0, 36, 0, 40, 0, 40, 0, 40, 0, 40, 32, 40, 0, 40, 32, 40, 40, 40],
self::NET_SPEED => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 44, 0, 44, 32, 44, 0, 44, 0, 44, 0, 44, 44, 44],
self::IDD_CODE => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 48, 0, 48, 0, 48, 36, 48, 0, 48, 48, 48],
self::AREA_CODE => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 52, 0, 52, 0, 52, 40, 52, 0, 52, 52, 52],
self::WEATHER_STATION_CODE => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 56, 0, 56, 0, 56, 0, 56, 56, 56],
self::WEATHER_STATION_NAME => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 60, 0, 60, 0, 60, 0, 60, 60, 60],
self::MCC => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 64, 0, 64, 36, 64, 64, 64],
self::MNC => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 68, 0, 68, 40, 68, 68, 68],
self::MOBILE_CARRIER_NAME => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 72, 0, 72, 44, 72, 72, 72],
self::ELEVATION => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 76, 0, 76, 76, 76],
self::USAGE_TYPE => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 80, 80, 80],
self::ADDRESS_TYPE => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 84],
self::CATEGORY => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 88],
self::DISTRICT => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92],
self::ASN => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96],
self::AS => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100],
];

/**
Expand Down Expand Up @@ -446,6 +470,9 @@ class Database
self::USAGE_TYPE => 'usageType',
self::ADDRESS_TYPE => 'addressType',
self::CATEGORY => 'category',
self::DISTRICT => 'district',
self::ASN => 'asn',
self::AS => 'as',
self::IP_ADDRESS => 'ipAddress',
self::IP_VERSION => 'ipVersion',
self::IP_NUMBER => 'ipNumber',
Expand All @@ -458,6 +485,7 @@ class Database
*/
private $databases = [
// IPv4 databases
'IP-COUNTRY-REGION-CITY-LATITUDE-LONGITUDE-ZIPCODE-TIMEZONE-ISP-DOMAIN-NETSPEED-AREACODE-WEATHER-MOBILE-ELEVATION-USAGETYPE-ADDRESSTYPE-CATEGORY-DISTRICT-ASN',
'IP-COUNTRY-REGION-CITY-LATITUDE-LONGITUDE-ZIPCODE-TIMEZONE-ISP-DOMAIN-NETSPEED-AREACODE-WEATHER-MOBILE-ELEVATION-USAGETYPE-ADDRESSTYPE-CATEGORY',
'IP-COUNTRY-REGION-CITY-LATITUDE-LONGITUDE-ZIPCODE-TIMEZONE-ISP-DOMAIN-NETSPEED-AREACODE-WEATHER-MOBILE-ELEVATION-USAGETYPE',
'IP-COUNTRY-REGION-CITY-LATITUDE-LONGITUDE-ISP-DOMAIN-MOBILE-USAGETYPE',
Expand Down Expand Up @@ -485,6 +513,7 @@ class Database
'IP-COUNTRY',

// IPv6 databases
'IPV6-COUNTRY-REGION-CITY-LATITUDE-LONGITUDE-ZIPCODE-TIMEZONE-ISP-DOMAIN-NETSPEED-AREACODE-WEATHER-MOBILE-ELEVATION-USAGETYPE-ADDRESSTYPE-CATEGORY-DISTRICT-ASN',
'IPV6-COUNTRY-REGION-CITY-LATITUDE-LONGITUDE-ZIPCODE-TIMEZONE-ISP-DOMAIN-NETSPEED-AREACODE-WEATHER-MOBILE-ELEVATION-USAGETYPE-ADDRESSTYPE-CATEGORY',
'IPV6-COUNTRY-REGION-CITY-LATITUDE-LONGITUDE-ZIPCODE-TIMEZONE-ISP-DOMAIN-NETSPEED-AREACODE-WEATHER-MOBILE-ELEVATION-USAGETYPE',
'IPV6-COUNTRY-REGION-CITY-LATITUDE-LONGITUDE-ISP-DOMAIN-MOBILE-USAGETYPE',
Expand Down Expand Up @@ -968,6 +997,10 @@ public function lookup($ip, $fields = null, $asNamed = true)
// Get IP version and number
list($ipVersion, $ipNumber) = $this->ipVersionAndNumber($ip);

if (!$ipVersion) {
return false;
}

// Perform a binary search
$pointer = $this->binSearch($ipVersion, $ipNumber);

Expand Down Expand Up @@ -1003,6 +1036,9 @@ public function lookup($ip, $fields = null, $asNamed = true)
$ifields[] = self::USAGE_TYPE;
$ifields[] = self::ADDRESS_TYPE;
$ifields[] = self::CATEGORY;
$ifields[] = self::DISTRICT;
$ifields[] = self::ASN;
$ifields[] = self::AS;

$ifields[] = self::COUNTRY;
$ifields[] = self::COORDINATES;
Expand Down Expand Up @@ -1046,6 +1082,9 @@ public function lookup($ip, $fields = null, $asNamed = true)
self::USAGE_TYPE => false,
self::ADDRESS_TYPE => false,
self::CATEGORY => false,
self::DISTRICT => false,
self::ASN => false,
self::AS => false,
self::COUNTRY => false,
self::COORDINATES => false,
self::IDD_AREA => false,
Expand Down Expand Up @@ -1264,6 +1303,27 @@ public function lookup($ip, $fields = null, $asNamed = true)
}
break;

case self::DISTRICT:
if (!$done[self::DISTRICT]) {
$results[self::DISTRICT] = $this->readDistrict($pointer);
$done[self::DISTRICT] = true;
}
break;

case self::ASN:
if (!$done[self::ASN]) {
$results[self::ASN] = $this->readAsn($pointer);
$done[self::ASN] = true;
}
break;

case self::AS:
if (!$done[self::AS]) {
$results[self::AS] = $this->readAs($pointer);
$done[self::AS] = true;
}
break;

case self::IP_ADDRESS:
if (!$done[self::IP_ADDRESS]) {
$results[self::IP_ADDRESS] = $ip;
Expand Down Expand Up @@ -2037,6 +2097,66 @@ private function readCategory($pointer)
return $this->readString($this->columns[self::CATEGORY][$this->type]);
}

/**
* High level function to fetch the district.
*
* @param int $pointer Position to read from, if false, return self::INVALID_IP_ADDRESS
*
* @return string
*/
private function readDistrict($pointer)
{
if ($pointer === false) {
return self::INVALID_IP_ADDRESS;
}

if ($this->columns[self::DISTRICT][$this->type] === 0) {
return self::FIELD_NOT_SUPPORTED;
}

return $this->readString($this->columns[self::DISTRICT][$this->type]);
}

/**
* High level function to fetch the ASN.
*
* @param int $pointer Position to read from, if false, return self::INVALID_IP_ADDRESS
*
* @return string
*/
private function readAsn($pointer)
{
if ($pointer === false) {
return self::INVALID_IP_ADDRESS;
}

if ($this->columns[self::ASN][$this->type] === 0) {
return self::FIELD_NOT_SUPPORTED;
}

return $this->readString($this->columns[self::ASN][$this->type]);
}

/**
* High level function to fetch the AS.
*
* @param int $pointer Position to read from, if false, return self::INVALID_IP_ADDRESS
*
* @return string
*/
private function readAs($pointer)
{
if ($pointer === false) {
return self::INVALID_IP_ADDRESS;
}

if ($this->columns[self::AS][$this->type] === 0) {
return self::FIELD_NOT_SUPPORTED;
}

return $this->readString($this->columns[self::AS][$this->type]);
}

/**
* Get the boundaries for an IP address.
*
Expand Down

0 comments on commit e84153c

Please sign in to comment.