diff --git a/README.md b/README.md index 6f1e8ec..dee2d27 100644 --- a/README.md +++ b/README.md @@ -14,27 +14,13 @@ Below are the methods supported in this class. ### BIN Database Class -|Method Name|Description| +| Function Name | Description | |---|---| -|open|Open the IP2Proxy BIN data for lookup. Please see the **Usage** section of the 3 modes supported to load the BIN data file.| -|close|Close and clean up the file pointer.| -|getPackageVersion|Get the package version (1 to 10 for PX1 to PX10 respectively).| -|getModuleVersion|Get the module version.| -|getDatabaseVersion|Get the database version.| -|isProxy|Check whether if an IP address was a proxy. Returned value:| -|getAll|Return the proxy information in array.| -|getProxyType|Return the proxy type. Please visit IP2Location for the list of proxy types supported| -|getCountryShort|Return the ISO3166-1 country code (2-digits) of the proxy.| -|getCountryLong|Return the ISO3166-1 country name of the proxy.| -|getRegion|Return the ISO3166-2 region name of the proxy. Please visit ISO3166-2 Subdivision Code for the information of ISO3166-2 supported| -|getCity|Return the city name of the proxy.| -|getISP|Return the ISP name of the proxy.| -|getDomain|Internet domain name associated with IP address range.| -|getUsageType|Usage type classification of ISP or company. Refer to usage type reference below.| -|getASN|Autonomous system number (ASN).| -|getAS|Autonomous system (AS) name.| -|getLastSeen|Proxy last seen in days.| -|getThreat|Security threat reported.| +|Constructor|Expect 2 input parameters:
  1. Full path of IP2Proxy BIN data file.
  2. File Open Mode
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** getDatabaseVersion()|Return the database's compilation date as a string of the form 'YYYY-MM-DD',| +|**string** getPackageVersion()|Return the database's type, 1 to 10 respectively for PX1 to PX10. Please visit https://www.ip2location.com/databases/ip2proxy for details.| +|**string** getModuleVersion()|Return the version of module.| +|**array** lookup($ip)|Return the IP information in array. Below is the information returned:You can visit [IP2Location](https://www.ip2location.com/database/px10-ip-proxytype-country-region-city-isp-domain-usagetype-asn-lastseen-threat-residential) website 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.| @@ -59,16 +45,15 @@ Open and read IP2Proxy binary database. There are 3 modes: 3. **\IP2Proxy\Database::SHARED_MEMORY** - Stores whole IP2Proxy database into system memory. Lookup is possible across all applications within the system. Extremely resources consuming. Do not use this mode if your system do not have enough memory. ```php -require 'class.IP2Proxy.php'; +require 'vendor/autoload.php'; -$db = new \IP2Proxy\Database(); -$db->open('./samples/IP2PROXY-IP-PROXYTYPE-COUNTRY-REGION-CITY-ISP-DOMAIN-USAGETYPE-ASN-LASTSEEN-THREAT-RESIDENTIAL.SAMPLE.BIN', \IP2Proxy\Database::FILE_IO); +$db = new \IP2Proxy\Database('vendor/ip2location/ip2proxy-php/data/PX10.SAMPLE.BIN', \IP2PROXY\Database::FILE_IO); ``` To start lookup result from database, use the following codes: -``` -$records = $db->getAll('1.0.241.135'); +```php +$records = $db->lookup('1.0.0.8', \IP2PROXY\Database::ALL); ``` Results are returned in array. @@ -95,27 +80,9 @@ echo '

Proxy Type: ' . $records['proxyType'] . '

'; */ echo '

Is Proxy: ' . $records['isProxy'] . '

'; echo '

ISP: ' . $records['isp'] . '

'; - -$domain = $db->getDomain('1.0.241.135'); -echo '

Domain: ' . $domain . '

'; - -$usageType = $db->getUsageType('1.0.241.135'); -echo '

Usage Type: ' . $usageType . '

'; - -$asn = $db->getASN('1.0.241.135'); -echo '

ASN: ' . $asn . '

'; - -$as = $db->getAS('1.0.241.135'); -echo '

AS: ' . $as . '

'; - -$lastSeen = $db->getLastSeen('1.0.241.135'); -echo '

Last Seen: ' . $lastSeen . '

'; - -$threat = $db->getThreat('1.0.241.135'); -echo '

Threat: ' . $threat . '

'; ``` -Note: if you are getting error such as `Call to undefined function IP2Proxy\gmp_import()`, you probably did not have the module to install or enable in php.ini. You can check your php.ini to make sure that the module has been enabled. + ### Web Service API @@ -124,7 +91,7 @@ To lookup by Web service, you will need to sign up for [IP2Proxy Web Service](ht Start your lookup by following codes: ```php -require 'class.IP2Proxy.php'; +require 'vendor/autoload.php'; // Lookup by Web API $ws = new \IP2Proxy\WebService('YOUR_API_KEY', 'PX10', false); @@ -152,6 +119,20 @@ if ($results !== false) { # Reference +### Proxy Type + +| Type | Description | Anonymity | +| ---- | ------------------------------------------------------------ | --------- | +| VPN | Anonymizing VPN services. These services offer users a publicly accessible VPN for the purpose of hiding their IP address. | High | +| TOR | Tor Exit Nodes. The Tor Project is an open network used by those who wish to maintain anonymity. | High | +| DCH | Hosting Provider, Data Center or Content Delivery Network. Since hosting providers and data centers can serve to provide anonymity, the Anonymous IP database flags IP addresses associated with them. | Low | +| PUB | Public Proxies. These are services which make connection requests on a user's behalf. Proxy server software can be configured by the administrator to listen on some specified port. These differ from VPNs in that the proxies usually have limited functions compare to VPNs. | High | +| WEB | Web Proxies. These are web services which make web requests on a user's behalf. These differ from VPNs or Public Proxies in that they are simple web-based proxies rather than operating at the IP address and other ports level. | High | +| SES | Search Engine Robots. These are services which perform crawling or scraping to a website, such as, the search engine spider or bots engine. | Low | +| RES | Residential proxies. These services offer users proxy connections through residential ISP with or without consents of peers to share their idle resources. Only available with PX10 | Medium | + + + ### Usage Type - (COM) Commercial diff --git a/composer.json b/composer.json index 55a33bb..d8a4802 100644 --- a/composer.json +++ b/composer.json @@ -11,13 +11,19 @@ "email": "support@ip2location.com" } ], + "require-dev": { + "phpunit/phpunit": "^9.5" + }, "require": { - "php": ">=5.6", - "ext-bcmath" : "*" + "php": ">=7.2", + "ext-bcmath": "*", + "ext-curl": "*", + "ext-gmp": "*", + "ext-json": "*" }, "autoload": { - "classmap": [ - "class.IP2Proxy.php" - ] + "psr-4": { + "IP2Proxy\\": "src" + } } } diff --git a/data/PX10.SAMPLE.BIN b/data/PX10.SAMPLE.BIN new file mode 100644 index 0000000..1c0033a Binary files /dev/null and b/data/PX10.SAMPLE.BIN differ diff --git a/example.php b/example.php deleted file mode 100644 index 357c2d3..0000000 --- a/example.php +++ /dev/null @@ -1,62 +0,0 @@ -open('./data/IP2PROXY-IP-PROXYTYPE-COUNTRY-REGION-CITY-ISP-DOMAIN-USAGETYPE-ASN-LASTSEEN-THREAT-RESIDENTIAL.SAMPLE.BIN', \IP2Proxy\Database::FILE_IO); - -$countryCode = $db->getCountryShort('1.0.241.135'); -echo '

Country Code: ' . $countryCode . '

'; - -$countryName = $db->getCountryLong('1.0.241.135'); -echo '

Country: ' . $countryName . '

'; - -$regionName = $db->getRegion('1.0.241.135'); -echo '

Region: ' . $regionName . '

'; - -$cityName = $db->getCity('1.0.241.135'); -echo '

City: ' . $cityName . '

'; - -$isp = $db->getISP('1.0.241.135'); -echo '

ISP: ' . $isp . '

'; - -$proxyType = $db->getProxyType('1.0.241.135'); -echo '

Proxy Type: ' . $proxyType . '

'; - -$isProxy = $db->isProxy('1.0.241.135'); -echo '

Is Proxy: ' . $isProxy . '

'; - -$domain = $db->getDomain('1.0.241.135'); -echo '

Domain: ' . $domain . '

'; - -$usageType = $db->getUsageType('1.0.241.135'); -echo '

Usage Type: ' . $usageType . '

'; - -$asn = $db->getASN('1.0.241.135'); -echo '

ASN: ' . $asn . '

'; - -$as = $db->getAS('1.0.241.135'); -echo '

AS: ' . $as . '

'; - -$lastSeen = $db->getLastSeen('1.0.241.135'); -echo '

Last Seen: ' . $lastSeen . '

'; - -$threat = $db->getThreat('1.0.241.135'); -echo '

Threat: ' . $threat . '

'; - -$records = $db->getAll('1.0.241.135'); - -echo '
';
-print_r($records);
-echo '
'; - -$db->close(); - -// Lookup by Web API -$ws = new \IP2Proxy\WebService('demo', 'PX10', false); - -$results = $ws->lookup('1.0.241.135'); - -echo '
';
-print_r($results);
-echo '
'; diff --git a/examples/example.php b/examples/example.php new file mode 100644 index 0000000..54894f5 --- /dev/null +++ b/examples/example.php @@ -0,0 +1,20 @@ +lookup('1.0.0.8', \IP2PROXY\Database::ALL); +print_r($records); + +echo PHP_EOL . PHP_EOL; + +echo 'Web Service' . PHP_EOL; + +// Lookup by Web API +$ws = new \IP2Proxy\WebService('demo', 'PX10', false); + +$results = $ws->lookup('1.0.0.8'); +print_r($results); diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..b12c2cf --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,7 @@ + + + + ./tests/ + + + \ No newline at end of file diff --git a/class.IP2Proxy.php b/src/Database.php similarity index 92% rename from class.IP2Proxy.php rename to src/Database.php index edc8f1e..845470c 100644 --- a/class.IP2Proxy.php +++ b/src/Database.php @@ -1,24 +1,5 @@ . - * - */ - namespace IP2Proxy; /** @@ -31,7 +12,7 @@ class Database * * @var string */ - public const VERSION = '3.0.0'; + public const VERSION = '3.1.0'; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Error field constants /////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -498,43 +479,19 @@ class Database // This variable will be used to hold the raw row of columns's positions private $rawPositionsRow; - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Default fields ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - /** - * Default fields to return during lookup. - * - * @var array|int - */ - private $defaultFields = self::ALL; - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Administrative public interface ///////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. - */ - public function __construct() - { - } - - /** - * Destructor. - */ - public function __destruct() - { - } - - /** - * @param string $file Filename of the BIN database to load - * @param int $mode Caching mode (one of FILE_IO, MEMORY_CACHE, or SHARED_MEMORY) - * @param mixed $defaultFields + * + * @param string $file Filename of the BIN database to load + * @param int $mode Caching mode (one of FILE_IO, MEMORY_CACHE, or SHARED_MEMORY) * * @throws \Exception */ - public function open($file = null, $mode = self::FILE_IO, $defaultFields = self::ALL) + public function __construct($file = null, $mode = self::FILE_IO) { if (!\function_exists('bcadd')) { throw new \Exception(__CLASS__ . ': BCMath extension is not installed.', self::EXCEPTION_BCMATH_NOT_INSTALLED); @@ -630,9 +587,6 @@ public function open($file = null, $mode = self::FILE_IO, $defaultFields = self: self::$floatSize = \strlen(pack('f', M_PI)); } - // set default fields to retrieve - $this->defaultFields = $defaultFields; - // extract database metadata $this->type = $this->readByte(1) - 1; $this->columnWidth[4] = $this->readByte(2) * 4; @@ -651,27 +605,35 @@ public function open($file = null, $mode = self::FILE_IO, $defaultFields = self: $this->indexBaseAddr[6] = $this->readWord(26); } + /** + * Destructor. + */ + public function __destruct() + { + self::close(); + } + /** * Close. */ public function close() { switch ($this->mode) { - case self::FILE_IO: - // free the file pointer - if ($this->resource !== false) { - fclose($this->resource); - $this->resource = false; - } - break; - case self::SHARED_MEMORY: - // detach from the memory segment - if ($this->resource !== false) { - shmop_close($this->resource); - $this->resource = false; + case self::FILE_IO: + // free the file pointer + if ($this->resource !== false) { + fclose($this->resource); + $this->resource = false; + } + break; + case self::SHARED_MEMORY: + // detach from the memory segment + if ($this->resource !== false) { + shmop_close($this->resource); + $this->resource = false; + } + break; } - break; - } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -704,154 +666,6 @@ public function getDatabaseVersion() return $this->year . '.' . $this->month . '.' . $this->day; } - /** - * Return -1, 0, 1, 2. - * - * @param mixed $ip - */ - public function isProxy($ip) - { - return self::lookup($ip, self::IS_PROXY); - } - - // Return string - public function getCountryShort($ip) - { - return self::lookup($ip, self::COUNTRY_CODE); - } - - // Return string - public function getCountryLong($ip) - { - return self::lookup($ip, self::COUNTRY_NAME); - } - - // Return string - public function getRegion($ip) - { - return self::lookup($ip, self::REGION_NAME); - } - - // Return string - public function getCity($ip) - { - return self::lookup($ip, self::CITY_NAME); - } - - // Return string - public function getISP($ip) - { - return self::lookup($ip, self::ISP); - } - - // Return string - public function getProxyType($ip) - { - return self::lookup($ip, self::PROXY_TYPE); - } - - // Return string - public function getDomain($ip) - { - return self::lookup($ip, self::DOMAIN); - } - - // Return string - public function getUsageType($ip) - { - return self::lookup($ip, self::USAGE_TYPE); - } - - // Return string - public function getASN($ip) - { - return self::lookup($ip, self::ASN); - } - - // Return string - public function getAS($ip) - { - return self::lookup($ip, self::_AS); - } - - // Return string - public function getLastSeen($ip) - { - return self::lookup($ip, self::LAST_SEEN); - } - - // Return string - public function getThreat($ip) - { - return self::lookup($ip, self::THREAT); - } - - // Return array - public function getAll($ip) - { - return self::lookup($ip, self::ALL); - } - - /** - * Tear down a shared memory segment created for the given file. - * - * @param string $file Filename of the BIN database whise segment must be deleted - * - * @throws \Exception - */ - protected function shmTeardown($file) - { - // verify the shmop extension is loaded - if (!\extension_loaded('shmop')) { - throw new \Exception(__CLASS__ . ": Please make sure your PHP setup has the 'shmop' extension enabled.", self::EXCEPTION_NO_SHMOP); - } - - // Get actual file path - $rfile = realpath($file); - - // If the file cannot be found, except away - if ($rfile === false) { - throw new \Exception(__CLASS__ . ": Database file '{$file}' does not seem to exist.", self::EXCEPTION_DBFILE_NOT_FOUND); - } - - $shmKey = self::getShmKey($rfile); - - // Try to open the memory segment for writing - $shmId = @shmop_open($shmKey, 'w', 0, 0); - if ($shmId === false) { - throw new \Exception(__CLASS__ . ": Unable to access shared memory block '{$shmKey}' for writing.", self::EXCEPTION_SHMOP_WRITING_FAILED); - } - - // Delete and close the descriptor - shmop_delete($shmId); - shmop_close($shmId); - } - - /** - * Return this database's available fields. - * - * @param bool $asNames Whether to return the mapped names intead of numbered constants - * - * @return array - */ - protected function getFields($asNames = false) - { - $result = array_keys(array_filter(self::$columns, function ($field) { - return $field[$this->type] !== 0; - })); - - if ($asNames) { - $return = []; - foreach ($result as $field) { - $return[] = self::$names[$field]; - } - - return $return; - } - - return $result; - } - /** * This function will look the given IP address up in the database and return the result(s) asked for. * @@ -866,7 +680,7 @@ protected function getFields($asNames = false) * * @return array|bool|mixed */ - protected function lookup($ip, $fields = null, $asNamed = true) + public function lookup($ip, $fields = null, $asNamed = true) { // Extract IP version and number list($ipVersion, $ipNumber) = self::ipVersionAndNumber($ip); @@ -876,7 +690,7 @@ protected function lookup($ip, $fields = null, $asNamed = true) // Apply defaults if needed if ($fields === null) { - $fields = $this->defaultFields; + $fields = self::ALL; } // Get the entire row based on the pointer value. @@ -1102,6 +916,66 @@ protected function lookup($ip, $fields = null, $asNamed = true) return array_values($results)[0]; } + /** + * Tear down a shared memory segment created for the given file. + * + * @param string $file Filename of the BIN database whise segment must be deleted + * + * @throws \Exception + */ + protected function shmTeardown($file) + { + // verify the shmop extension is loaded + if (!\extension_loaded('shmop')) { + throw new \Exception(__CLASS__ . ": Please make sure your PHP setup has the 'shmop' extension enabled.", self::EXCEPTION_NO_SHMOP); + } + + // Get actual file path + $rfile = realpath($file); + + // If the file cannot be found, except away + if ($rfile === false) { + throw new \Exception(__CLASS__ . ": Database file '{$file}' does not seem to exist.", self::EXCEPTION_DBFILE_NOT_FOUND); + } + + $shmKey = self::getShmKey($rfile); + + // Try to open the memory segment for writing + $shmId = @shmop_open($shmKey, 'w', 0, 0); + if ($shmId === false) { + throw new \Exception(__CLASS__ . ": Unable to access shared memory block '{$shmKey}' for writing.", self::EXCEPTION_SHMOP_WRITING_FAILED); + } + + // Delete and close the descriptor + shmop_delete($shmId); + shmop_close($shmId); + } + + /** + * Return this database's available fields. + * + * @param bool $asNames Whether to return the mapped names intead of numbered constants + * + * @return array + */ + protected function getFields($asNames = false) + { + $result = array_keys(array_filter(self::$columns, function ($field) { + return $field[$this->type] !== 0; + })); + + if ($asNames) { + $return = []; + foreach ($result as $field) { + $return[] = self::$names[$field]; + } + + return $return; + } + + return $result; + } + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Static tools //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1845,7 +1719,7 @@ class WebService * * @throws \Exception */ - public function __construct($apiKey, $package = 'PX1', $useSsl = false) + public function __construct($apiKey, $package = 'PX1', $useSsl = true) { if (!\extension_loaded('curl')) { throw new \Exception(__CLASS__ . ": Please make sure your PHP setup has the 'curl' extension enabled.", self::EXCEPTION_NO_CURL); @@ -1875,7 +1749,7 @@ public function __construct($apiKey, $package = 'PX1', $useSsl = false) */ public function lookup($ip) { - $response = $this->httpRequest('http://api.ip2proxy.com/?' . http_build_query([ + $response = $this->httpRequest('http' . (($this->useSsl) ? 's' : '') . '://api.ip2proxy.com/?' . http_build_query([ 'key' => $this->apiKey, 'ip' => $ip, 'package' => $this->package, @@ -1899,7 +1773,7 @@ public function lookup($ip) */ public function getCredit() { - $response = $this->httpRequest('http://api.ip2proxy.com/?' . http_build_query([ + $response = $this->httpRequest('http' . (($this->useSsl) ? 's' : '') . '://api.ip2proxy.com/?' . http_build_query([ 'key' => $this->apiKey, 'check' => true, ])); diff --git a/src/WebService.php b/src/WebService.php new file mode 100644 index 0000000..f0fc900 --- /dev/null +++ b/src/WebService.php @@ -0,0 +1,139 @@ +apiKey = $apiKey; + $this->package = $package; + $this->useSsl = $useSsl; + } + + /** + * This function will look the given IP address up in IP2Proxy web service. + * + * @param string $ip IP address to look up + * + * @throws \Exception + * + * @return array|false + */ + public function lookup($ip) + { + $response = $this->httpRequest('http' . (($this->useSsl) ? 's' : '') . '://api.ip2proxy.com/?' . http_build_query([ + 'key' => $this->apiKey, + 'ip' => $ip, + 'package' => $this->package, + ])); + + if (($data = json_decode($response, true)) === null) { + return false; + } + + if ($data['response'] != 'OK') { + throw new \Exception(__CLASS__ . ': ' . $data['response'], self::EXCEPTION_WEB_SERVICE_ERROR); + } + + return $data; + } + + /** + * Get the remaing credit in your IP2Proxy web service account. + * + * @return int + */ + public function getCredit() + { + $response = $this->httpRequest('http' . (($this->useSsl) ? 's' : '') . '://api.ip2proxy.com/?' . http_build_query([ + 'key' => $this->apiKey, + 'check' => true, + ])); + + if (($data = json_decode($response, true)) === null) { + return 0; + } + + if (!isset($data['response'])) { + return 0; + } + + return $data['response']; + } + + /** + * Open a remote web address. + * + * @param string $url Website URL + * + * @return bool|string + */ + private function httpRequest($url) + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_FAILONERROR, 1); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_TIMEOUT, 30); + + $response = curl_exec($ch); + + if (!curl_errno($ch)) { + curl_close($ch); + + return $response; + } + + curl_close($ch); + + return false; + } +} diff --git a/tests/DatabaseTest.php b/tests/DatabaseTest.php new file mode 100644 index 0000000..b48eb77 --- /dev/null +++ b/tests/DatabaseTest.php @@ -0,0 +1,76 @@ +assertStringContainsString('does not seem to exist.', $e->getMessage()); + } + } + + public function testInvalidIp() + { + $db = new \IP2Proxy\Database('./data/PX10.SAMPLE.BIN', \IP2Proxy\Database::FILE_IO); + + $records = $db->lookup('1.0.0.x', \IP2Proxy\Database::ALL); + + $this->assertStringContainsString('INVALID IP ADDRESS', $records['countryCode']); + } + + public function testIpv4CountryCode() + { + $db = new \IP2Proxy\Database('./data/PX10.SAMPLE.BIN', \IP2Proxy\Database::FILE_IO); + + $records = $db->lookup('1.0.0.8', \IP2Proxy\Database::ALL); + + $this->assertEquals( + 'US', + $records['countryCode'], + ); + } + + public function testIpv4CountryName() + { + $db = new \IP2Proxy\Database('./data/PX10.SAMPLE.BIN', \IP2Proxy\Database::FILE_IO); + + $records = $db->lookup('1.0.0.8', \IP2Proxy\Database::ALL); + + $this->assertEquals( + 'United States of America', + $records['countryName'], + ); + } + + public function testIpv6CountryCode() + { + $db = new \IP2Proxy\Database('./data/PX10.SAMPLE.BIN', \IP2Proxy\Database::FILE_IO); + + $records = $db->lookup('2c0f:ffa0::4', \IP2Proxy\Database::ALL); + + $this->assertEquals( + 'UG', + $records['countryCode'], + ); + } + + public function testIpv6CountryName() + { + $db = new \IP2Proxy\Database('./data/PX10.SAMPLE.BIN', \IP2Proxy\Database::FILE_IO); + + $records = $db->lookup('2c0f:ffa0::4', \IP2Proxy\Database::ALL); + + $this->assertEquals( + 'Uganda', + $records['countryName'], + ); + } +} diff --git a/tests/WebServiceTest.php b/tests/WebServiceTest.php new file mode 100644 index 0000000..17bbe77 --- /dev/null +++ b/tests/WebServiceTest.php @@ -0,0 +1,52 @@ +assertMatchesRegularExpression('/^[0-9]+$/', (string) $ws->getCredit()); + } + + public function testInvalidIp() + { + $ws = new \IP2Proxy\WebService('demo', 'PX10', true); + + $records = $ws->lookup('1.0.0.x'); + + $this->assertEquals( + 'INVALID IP ADDRESS', + $records['countryCode'], + ); + } + + public function testCountryCodeIpv4() + { + $ws = new \IP2Proxy\WebService('demo', 'PX10', true); + + $records = $ws->lookup('1.0.0.8'); + + $this->assertEquals( + 'US', + $records['countryCode'], + ); + } + + public function testCountryCodeIpv6() + { + $ws = new \IP2Proxy\WebService('demo', 'PX10', true); + + $records = $ws->lookup('2c0f:ffa0::4'); + + $this->assertEquals( + 'UG', + $records['countryCode'], + ); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..c7d48ca --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,9 @@ +add('IP2Proxy\Test', __DIR__);