JFIFxxC      C  " }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3RbrPK9Zddgeoip2/composer.jsonnu[{ "name": "geoip2/geoip2", "description": "MaxMind GeoIP2 PHP API", "keywords": ["geoip", "geoip2", "geolocation", "ip", "maxmind"], "homepage": "https://github.com/maxmind/GeoIP2-php", "type": "library", "license": "Apache-2.0", "authors": [ { "name": "Gregory J. Oschwald", "email": "goschwald@maxmind.com", "homepage": "https://www.maxmind.com/" } ], "require": { "maxmind-db/reader": "~1.8", "maxmind/web-service-common": "~0.8", "php": ">=7.2", "ext-json": "*" }, "require-dev": { "friendsofphp/php-cs-fixer": "3.*", "phpunit/phpunit": "^8.0 || ^9.0", "squizlabs/php_codesniffer": "3.*", "phpstan/phpstan": "*" }, "autoload": { "psr-4": { "GeoIp2\\": "src" } } } PK9ZWA&geoip2/src/Exception/HttpException.phpnu[uri = $uri; parent::__construct($message, $httpStatus, $previous); } } PK9ZUU0geoip2/src/Exception/InvalidRequestException.phpnu[error = $error; parent::__construct($message, $httpStatus, $uri, $previous); } } PK9Zčê0geoip2/src/Exception/AuthenticationException.phpnu[ */ private $locales; /** * @var WsClient */ private $client; /** * @var string */ private static $basePath = '/geoip/v2.1'; public const VERSION = 'v2.13.0'; /** * Constructor. * * @param int $accountId your MaxMind account ID * @param string $licenseKey your MaxMind license key * @param array $locales list of locale codes to use in name property * from most preferred to least preferred * @param array $options array of options. Valid options include: * * `host` - The host to use when querying the web * service. To query the GeoLite2 web service * instead of the GeoIP2 web service, set the * host to `geolite.info`. * * `timeout` - Timeout in seconds. * * `connectTimeout` - Initial connection timeout in seconds. * * `proxy` - The HTTP proxy to use. May include a schema, port, * username, and password, e.g., * `http://username:password@127.0.0.1:10`. */ public function __construct( int $accountId, string $licenseKey, array $locales = ['en'], array $options = [] ) { $this->locales = $locales; // This is for backwards compatibility. Do not remove except for a // major version bump. // @phpstan-ignore-next-line if (\is_string($options)) { $options = ['host' => $options]; } if (!isset($options['host'])) { $options['host'] = 'geoip.maxmind.com'; } $options['userAgent'] = $this->userAgent(); $this->client = new WsClient($accountId, $licenseKey, $options); } private function userAgent(): string { return 'GeoIP2-API/' . self::VERSION; } /** * This method calls the City Plus service. * * @param string $ipAddress IPv4 or IPv6 address as a string. If no * address is provided, the address that the web service is called * from will be used. * * @throws \GeoIp2\Exception\AddressNotFoundException if the address you * provided is not in our database (e.g., a private address). * @throws \GeoIp2\Exception\AuthenticationException if there is a problem * with the account ID or license key that you provided * @throws \GeoIp2\Exception\OutOfQueriesException if your account is out * of queries * @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is * invalid for some other reason. This may indicate an issue * with this API. Please report the error to MaxMind. * @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error code or message was returned. * This could indicate a problem with the connection between * your server and the web service or that the web service * returned an invalid document or 500 error code * @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent * class to the above exceptions. It will be thrown directly * if a 200 status code is returned but the body is invalid. */ public function city(string $ipAddress = 'me'): City { // @phpstan-ignore-next-line return $this->responseFor('city', City::class, $ipAddress); } /** * This method calls the Country service. * * @param string $ipAddress IPv4 or IPv6 address as a string. If no * address is provided, the address that the web service is called * from will be used. * * @throws \GeoIp2\Exception\AddressNotFoundException if the address you provided is not in our database (e.g., * a private address). * @throws \GeoIp2\Exception\AuthenticationException if there is a problem * with the account ID or license key that you provided * @throws \GeoIp2\Exception\OutOfQueriesException if your account is out of queries * @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is * invalid for some other reason. This may indicate an * issue with this API. Please report the error to MaxMind. * @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error * code or message was returned. This could indicate a problem * with the connection between your server and the web service * or that the web service returned an invalid document or 500 * error code. * @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent class to the above exceptions. It * will be thrown directly if a 200 status code is returned but * the body is invalid. */ public function country(string $ipAddress = 'me'): Country { return $this->responseFor('country', Country::class, $ipAddress); } /** * This method calls the Insights service. Insights is only supported by * the GeoIP2 web service. The GeoLite2 web service does not support it. * * @param string $ipAddress IPv4 or IPv6 address as a string. If no * address is provided, the address that the web service is called * from will be used. * * @throws \GeoIp2\Exception\AddressNotFoundException if the address you * provided is not in our database (e.g., a private address). * @throws \GeoIp2\Exception\AuthenticationException if there is a problem * with the account ID or license key that you provided * @throws \GeoIp2\Exception\OutOfQueriesException if your account is out * of queries * @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is * invalid for some other reason. This may indicate an * issue with this API. Please report the error to MaxMind. * @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error code or message was returned. * This could indicate a problem with the connection between * your server and the web service or that the web service * returned an invalid document or 500 error code * @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent * class to the above exceptions. It will be thrown directly * if a 200 status code is returned but the body is invalid. */ public function insights(string $ipAddress = 'me'): Insights { // @phpstan-ignore-next-line return $this->responseFor('insights', Insights::class, $ipAddress); } private function responseFor(string $endpoint, string $class, string $ipAddress): Country { $path = implode('/', [self::$basePath, $endpoint, $ipAddress]); try { $service = (new \ReflectionClass($class))->getShortName(); $body = $this->client->get('GeoIP2 ' . $service, $path); } catch (\MaxMind\Exception\IpAddressNotFoundException $ex) { throw new AddressNotFoundException( $ex->getMessage(), $ex->getStatusCode(), $ex ); } catch (\MaxMind\Exception\AuthenticationException $ex) { throw new AuthenticationException( $ex->getMessage(), $ex->getStatusCode(), $ex ); } catch (\MaxMind\Exception\InsufficientFundsException $ex) { throw new OutOfQueriesException( $ex->getMessage(), $ex->getStatusCode(), $ex ); } catch (\MaxMind\Exception\InvalidRequestException $ex) { throw new InvalidRequestException( $ex->getMessage(), $ex->getErrorCode(), $ex->getStatusCode(), $ex->getUri(), $ex ); } catch (\MaxMind\Exception\HttpException $ex) { throw new HttpException( $ex->getMessage(), $ex->getStatusCode(), $ex->getUri(), $ex ); } catch (\MaxMind\Exception\WebServiceException $ex) { throw new GeoIp2Exception( $ex->getMessage(), $ex->getCode(), $ex ); } return new $class($body, $this->locales); } } PK9Zl\yygeoip2/src/Util.phpnu[ 0; $i++) { $b = $ipBytes[$i]; if ($curPrefix < 8) { $shiftN = 8 - $curPrefix; $b = \chr(0xFF & (\ord($b) >> $shiftN) << $shiftN); } $networkBytes[$i] = $b; $curPrefix -= 8; } $network = inet_ntop($networkBytes); return "$network/$prefixLen"; } } PK9Z<}a((geoip2/src/Database/Reader.phpnu[ */ private $locales; /** * Constructor. * * @param string $filename the path to the GeoIP2 database file * @param array $locales list of locale codes to use in name property * from most preferred to least preferred * * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ public function __construct( string $filename, array $locales = ['en'] ) { $this->dbReader = new DbReader($filename); $this->dbType = $this->dbReader->metadata()->databaseType; $this->locales = $locales; } /** * This method returns a GeoIP2 City model. * * @param string $ipAddress an IPv4 or IPv6 address as a string * * @throws \GeoIp2\Exception\AddressNotFoundException if the address is * not in the database * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ public function city(string $ipAddress): City { // @phpstan-ignore-next-line return $this->modelFor(City::class, 'City', $ipAddress); } /** * This method returns a GeoIP2 Country model. * * @param string $ipAddress an IPv4 or IPv6 address as a string * * @throws \GeoIp2\Exception\AddressNotFoundException if the address is * not in the database * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ public function country(string $ipAddress): Country { // @phpstan-ignore-next-line return $this->modelFor(Country::class, 'Country', $ipAddress); } /** * This method returns a GeoIP2 Anonymous IP model. * * @param string $ipAddress an IPv4 or IPv6 address as a string * * @throws \GeoIp2\Exception\AddressNotFoundException if the address is * not in the database * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ public function anonymousIp(string $ipAddress): AnonymousIp { // @phpstan-ignore-next-line return $this->flatModelFor( AnonymousIp::class, 'GeoIP2-Anonymous-IP', $ipAddress ); } /** * This method returns a GeoLite2 ASN model. * * @param string $ipAddress an IPv4 or IPv6 address as a string * * @throws \GeoIp2\Exception\AddressNotFoundException if the address is * not in the database * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ public function asn(string $ipAddress): Asn { // @phpstan-ignore-next-line return $this->flatModelFor( Asn::class, 'GeoLite2-ASN', $ipAddress ); } /** * This method returns a GeoIP2 Connection Type model. * * @param string $ipAddress an IPv4 or IPv6 address as a string * * @throws \GeoIp2\Exception\AddressNotFoundException if the address is * not in the database * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ public function connectionType(string $ipAddress): ConnectionType { // @phpstan-ignore-next-line return $this->flatModelFor( ConnectionType::class, 'GeoIP2-Connection-Type', $ipAddress ); } /** * This method returns a GeoIP2 Domain model. * * @param string $ipAddress an IPv4 or IPv6 address as a string * * @throws \GeoIp2\Exception\AddressNotFoundException if the address is * not in the database * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ public function domain(string $ipAddress): Domain { // @phpstan-ignore-next-line return $this->flatModelFor( Domain::class, 'GeoIP2-Domain', $ipAddress ); } /** * This method returns a GeoIP2 Enterprise model. * * @param string $ipAddress an IPv4 or IPv6 address as a string * * @throws \GeoIp2\Exception\AddressNotFoundException if the address is * not in the database * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ public function enterprise(string $ipAddress): Enterprise { // @phpstan-ignore-next-line return $this->modelFor(Enterprise::class, 'Enterprise', $ipAddress); } /** * This method returns a GeoIP2 ISP model. * * @param string $ipAddress an IPv4 or IPv6 address as a string * * @throws \GeoIp2\Exception\AddressNotFoundException if the address is * not in the database * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ public function isp(string $ipAddress): Isp { // @phpstan-ignore-next-line return $this->flatModelFor( Isp::class, 'GeoIP2-ISP', $ipAddress ); } private function modelFor(string $class, string $type, string $ipAddress): AbstractModel { [$record, $prefixLen] = $this->getRecord($class, $type, $ipAddress); $record['traits']['ip_address'] = $ipAddress; $record['traits']['prefix_len'] = $prefixLen; return new $class($record, $this->locales); } private function flatModelFor(string $class, string $type, string $ipAddress): AbstractModel { [$record, $prefixLen] = $this->getRecord($class, $type, $ipAddress); $record['ip_address'] = $ipAddress; $record['prefix_len'] = $prefixLen; return new $class($record); } private function getRecord(string $class, string $type, string $ipAddress): array { if (strpos($this->dbType, $type) === false) { $method = lcfirst((new \ReflectionClass($class))->getShortName()); throw new \BadMethodCallException( "The $method method cannot be used to open a {$this->dbType} database" ); } [$record, $prefixLen] = $this->dbReader->getWithPrefixLen($ipAddress); if ($record === null) { throw new AddressNotFoundException( "The address $ipAddress is not in the database." ); } if (!\is_array($record)) { // This can happen on corrupt databases. Generally, // MaxMind\Db\Reader will throw a // MaxMind\Db\Reader\InvalidDatabaseException, but occasionally // the lookup may result in a record that looks valid but is not // an array. This mostly happens when the user is ignoring all // exceptions and the more frequent InvalidDatabaseException // exceptions go unnoticed. throw new InvalidDatabaseException( "Expected an array when looking up $ipAddress but received: " . \gettype($record) ); } return [$record, $prefixLen]; } /** * @throws \InvalidArgumentException if arguments are passed to the method * @throws \BadMethodCallException if the database has been closed * * @return \MaxMind\Db\Reader\Metadata object for the database */ public function metadata(): DbReader\Metadata { return $this->dbReader->metadata(); } /** * Closes the GeoIP2 database and returns the resources to the system. */ public function close(): void { $this->dbReader->close(); } } PK9Z *) ) geoip2/src/Model/AnonymousIp.phpnu[isAnonymous = $this->get('is_anonymous'); $this->isAnonymousVpn = $this->get('is_anonymous_vpn'); $this->isHostingProvider = $this->get('is_hosting_provider'); $this->isPublicProxy = $this->get('is_public_proxy'); $this->isResidentialProxy = $this->get('is_residential_proxy'); $this->isTorExitNode = $this->get('is_tor_exit_node'); $ipAddress = $this->get('ip_address'); $this->ipAddress = $ipAddress; $this->network = Util::cidr($ipAddress, $this->get('prefix_len')); } } PK9Zb)Ogeoip2/src/Model/Enterprise.phpnu[ */ protected $subdivisions = []; /** * @ignore */ public function __construct(array $raw, array $locales = ['en']) { parent::__construct($raw, $locales); $this->city = new \GeoIp2\Record\City($this->get('city'), $locales); $this->location = new \GeoIp2\Record\Location($this->get('location')); $this->postal = new \GeoIp2\Record\Postal($this->get('postal')); $this->createSubdivisions($raw, $locales); } private function createSubdivisions(array $raw, array $locales): void { if (!isset($raw['subdivisions'])) { return; } foreach ($raw['subdivisions'] as $sub) { $this->subdivisions[] = new \GeoIp2\Record\Subdivision($sub, $locales) ; } } /** * @ignore * * @return mixed */ public function __get(string $attr) { if ($attr === 'mostSpecificSubdivision') { return $this->{$attr}(); } return parent::__get($attr); } /** * @ignore */ public function __isset(string $attr): bool { if ($attr === 'mostSpecificSubdivision') { // We always return a mostSpecificSubdivision, even if it is the // empty subdivision return true; } return parent::__isset($attr); } private function mostSpecificSubdivision(): \GeoIp2\Record\Subdivision { return empty($this->subdivisions) ? new \GeoIp2\Record\Subdivision([], $this->locales) : end($this->subdivisions); } } PK9Z'_ geoip2/src/Model/Country.phpnu[ */ protected $locales; /** * @var \GeoIp2\Record\MaxMind */ protected $maxmind; /** * @var \GeoIp2\Record\Country */ protected $registeredCountry; /** * @var \GeoIp2\Record\RepresentedCountry */ protected $representedCountry; /** * @var \GeoIp2\Record\Traits */ protected $traits; /** * @ignore */ public function __construct(array $raw, array $locales = ['en']) { parent::__construct($raw); $this->continent = new \GeoIp2\Record\Continent( $this->get('continent'), $locales ); $this->country = new \GeoIp2\Record\Country( $this->get('country'), $locales ); $this->maxmind = new \GeoIp2\Record\MaxMind($this->get('maxmind')); $this->registeredCountry = new \GeoIp2\Record\Country( $this->get('registered_country'), $locales ); $this->representedCountry = new \GeoIp2\Record\RepresentedCountry( $this->get('represented_country'), $locales ); $this->traits = new \GeoIp2\Record\Traits($this->get('traits')); $this->locales = $locales; } } PK9Zy#geoip2/src/Model/ConnectionType.phpnu[connectionType = $this->get('connection_type'); $ipAddress = $this->get('ip_address'); $this->ipAddress = $ipAddress; $this->network = Util::cidr($ipAddress, $this->get('prefix_len')); } } PK9Zk363 3 geoip2/src/Model/Isp.phpnu[autonomousSystemNumber = $this->get('autonomous_system_number'); $this->autonomousSystemOrganization = $this->get('autonomous_system_organization'); $this->isp = $this->get('isp'); $this->mobileCountryCode = $this->get('mobile_country_code'); $this->mobileNetworkCode = $this->get('mobile_network_code'); $this->organization = $this->get('organization'); $ipAddress = $this->get('ip_address'); $this->ipAddress = $ipAddress; $this->network = Util::cidr($ipAddress, $this->get('prefix_len')); } } PK9Z`@geoip2/src/Model/Insights.phpnu[autonomousSystemNumber = $this->get('autonomous_system_number'); $this->autonomousSystemOrganization = $this->get('autonomous_system_organization'); $ipAddress = $this->get('ip_address'); $this->ipAddress = $ipAddress; $this->network = Util::cidr($ipAddress, $this->get('prefix_len')); } } PK9Zi"geoip2/src/Model/AbstractModel.phpnu[ */ protected $raw; /** * @ignore */ public function __construct(array $raw) { $this->raw = $raw; } /** * @ignore * * @return mixed */ protected function get(string $field) { if (isset($this->raw[$field])) { return $this->raw[$field]; } if (preg_match('/^is_/', $field)) { return false; } return null; } /** * @ignore * * @return mixed */ public function __get(string $attr) { if ($attr !== 'instance' && property_exists($this, $attr)) { return $this->{$attr}; } throw new \RuntimeException("Unknown attribute: $attr"); } /** * @ignore */ public function __isset(string $attr): bool { return $attr !== 'instance' && isset($this->{$attr}); } public function jsonSerialize(): array { return $this->raw; } } PK9ZkdFgeoip2/src/Model/Domain.phpnu[domain = $this->get('domain'); $ipAddress = $this->get('ip_address'); $this->ipAddress = $ipAddress; $this->network = Util::cidr($ipAddress, $this->get('prefix_len')); } } PK9Zr1|dPP(geoip2/src/Record/RepresentedCountry.phpnu[military * but this could expand to include other types in the future. */ class RepresentedCountry extends Country { /** * @ignore * * @var array */ protected $validAttributes = [ 'confidence', 'geonameId', 'isInEuropeanUnion', 'isoCode', 'names', 'type', ]; } PK9ZTܓgeoip2/src/Record/Postal.phpnu[ */ protected $validAttributes = ['code', 'confidence']; } PK9Z9TPPgeoip2/src/Record/City.phpnu[ */ protected $validAttributes = ['confidence', 'geonameId', 'names']; } PK9ZCƕ<<geoip2/src/Record/Country.phpnu[ */ protected $validAttributes = [ 'confidence', 'geonameId', 'isInEuropeanUnion', 'isoCode', 'names', ]; } PK9Z6||geoip2/src/Record/Location.phpnu[ */ protected $validAttributes = [ 'averageIncome', 'accuracyRadius', 'latitude', 'longitude', 'metroCode', 'populationDensity', 'postalCode', 'postalConfidence', 'timeZone', ]; } PK9ZU)geoip2/src/Record/AbstractPlaceRecord.phpnu[ */ private $locales; /** * @ignore */ public function __construct(?array $record, array $locales = ['en']) { $this->locales = $locales; parent::__construct($record); } /** * @ignore * * @return mixed */ public function __get(string $attr) { if ($attr === 'name') { return $this->name(); } return parent::__get($attr); } /** * @ignore */ public function __isset(string $attr): bool { if ($attr === 'name') { return $this->firstSetNameLocale() !== null; } return parent::__isset($attr); } private function name(): ?string { $locale = $this->firstSetNameLocale(); // @phpstan-ignore-next-line return $locale === null ? null : $this->names[$locale]; } private function firstSetNameLocale(): ?string { foreach ($this->locales as $locale) { if (isset($this->names[$locale])) { return $locale; } } return null; } } PK9Zl  !geoip2/src/Record/Subdivision.phpnu[ */ protected $validAttributes = [ 'confidence', 'geonameId', 'isoCode', 'names', ]; } PK9Z~ddgeoip2/src/Record/Continent.phpnu[ */ protected $validAttributes = [ 'code', 'geonameId', 'names', ]; } PK9Z/geoip2/src/Record/Traits.phpnu[The user type associated with the IP * address. This can be one of the following values:

* *

* This attribute is only available from the Insights web service and the * GeoIP2 Enterprise database. *

*/ class Traits extends AbstractRecord { /** * @ignore * * @var array */ protected $validAttributes = [ 'autonomousSystemNumber', 'autonomousSystemOrganization', 'connectionType', 'domain', 'ipAddress', 'isAnonymous', 'isAnonymousProxy', 'isAnonymousVpn', 'isHostingProvider', 'isLegitimateProxy', 'isp', 'isPublicProxy', 'isResidentialProxy', 'isSatelliteProvider', 'isTorExitNode', 'mobileCountryCode', 'mobileNetworkCode', 'network', 'organization', 'staticIpScore', 'userCount', 'userType', ]; public function __construct(?array $record) { if (!isset($record['network']) && isset($record['ip_address'], $record['prefix_len'])) { $record['network'] = Util::cidr($record['ip_address'], $record['prefix_len']); } parent::__construct($record); } } PK9Zx$geoip2/src/Record/AbstractRecord.phpnu[ */ private $record; /** * @ignore */ public function __construct(?array $record) { $this->record = isset($record) ? $record : []; } /** * @ignore * * @return mixed */ public function __get(string $attr) { // XXX - kind of ugly but greatly reduces boilerplate code $key = $this->attributeToKey($attr); if ($this->__isset($attr)) { return $this->record[$key]; } if ($this->validAttribute($attr)) { if (preg_match('/^is_/', $key)) { return false; } return null; } throw new \RuntimeException("Unknown attribute: $attr"); } public function __isset(string $attr): bool { return $this->validAttribute($attr) && isset($this->record[$this->attributeToKey($attr)]); } private function attributeToKey(string $attr): string { return strtolower(preg_replace('/([A-Z])/', '_\1', $attr)); } private function validAttribute(string $attr): bool { // @phpstan-ignore-next-line return \in_array($attr, $this->validAttributes, true); } public function jsonSerialize(): ?array { return $this->record; } } PK9Zqgeoip2/src/Record/MaxMind.phpnu[ */ protected $validAttributes = ['queriesRemaining']; } PK9ZQ geoip2/src/ProviderInterface.phpnu[city('128.101.101.101'); print($record->country->isoCode . "\n"); // 'US' print($record->country->name . "\n"); // 'United States' print($record->country->names['zh-CN'] . "\n"); // '美国' print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota' print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN' print($record->city->name . "\n"); // 'Minneapolis' print($record->postal->code . "\n"); // '55455' print($record->location->latitude . "\n"); // 44.9733 print($record->location->longitude . "\n"); // -93.2323 print($record->traits->network . "\n"); // '128.101.101.101/32' ``` ### Anonymous IP Example ### ```php anonymousIp('128.101.101.101'); if ($record->isAnonymous) { print "anon\n"; } print($record->ipAddress . "\n"); // '128.101.101.101' print($record->network . "\n"); // '128.101.101.101/32' ``` ### Connection-Type Example ### ```php connectionType('128.101.101.101'); print($record->connectionType . "\n"); // 'Corporate' print($record->ipAddress . "\n"); // '128.101.101.101' print($record->network . "\n"); // '128.101.101.101/32' ``` ### Domain Example ### ```php domain('128.101.101.101'); print($record->domain . "\n"); // 'umn.edu' print($record->ipAddress . "\n"); // '128.101.101.101' print($record->network . "\n"); // '128.101.101.101/32' ``` ### Enterprise Example ### ```php enterprise method to do a lookup in the Enterprise database $record = $reader->enterprise('128.101.101.101'); print($record->country->confidence . "\n"); // 99 print($record->country->isoCode . "\n"); // 'US' print($record->country->name . "\n"); // 'United States' print($record->country->names['zh-CN'] . "\n"); // '美国' print($record->mostSpecificSubdivision->confidence . "\n"); // 77 print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota' print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN' print($record->city->confidence . "\n"); // 60 print($record->city->name . "\n"); // 'Minneapolis' print($record->postal->code . "\n"); // '55455' print($record->location->accuracyRadius . "\n"); // 50 print($record->location->latitude . "\n"); // 44.9733 print($record->location->longitude . "\n"); // -93.2323 print($record->traits->network . "\n"); // '128.101.101.101/32' ``` ### ISP Example ### ```php isp('128.101.101.101'); print($record->autonomousSystemNumber . "\n"); // 217 print($record->autonomousSystemOrganization . "\n"); // 'University of Minnesota' print($record->isp . "\n"); // 'University of Minnesota' print($record->organization . "\n"); // 'University of Minnesota' print($record->ipAddress . "\n"); // '128.101.101.101' print($record->network . "\n"); // '128.101.101.101/32' ``` ## Database Updates ## You can keep your databases up to date with our [GeoIP Update program](https://github.com/maxmind/geoipupdate/releases). [Learn more about GeoIP Update on our developer portal.](https://dev.maxmind.com/geoip/updating-databases?lang=en) There is also a third-party tool for updating databases using PHP and Composer. MaxMind does not offer support for this tool or maintain it. [Learn more about the Geoip2 Update tool for PHP and Composer on its GitHub page.](https://github.com/tronovav/geoip2-update) ## Web Service Client ## ### Usage ### To use this API, you must create a new `\GeoIp2\WebService\Client` object with your `$accountId` and `$licenseKey`: ```php $client = new Client(42, 'abcdef123456'); ``` You may also call the constructor with additional arguments. The third argument specifies the language preferences when using the `->name` method on the model classes that this client creates. The fourth argument is additional options such as `host` and `timeout`. For instance, to call the GeoLite2 web service instead of the GeoIP2 web service: ```php $client = new Client(42, 'abcdef123456', ['en'], ['host' => 'geolite.info']); ``` After creating the client, you may now call the method corresponding to a specific endpoint with the IP address to look up, e.g.: ```php $record = $client->city('128.101.101.101'); ``` If the request succeeds, the method call will return a model class for the endpoint you called. This model in turn contains multiple record classes, each of which represents part of the data returned by the web service. If there is an error, a structured exception is thrown. See the API documentation for more details. ### Example ### ```php city('128.101.101.101'); print($record->country->isoCode . "\n"); // 'US' print($record->country->name . "\n"); // 'United States' print($record->country->names['zh-CN'] . "\n"); // '美国' print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota' print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN' print($record->city->name . "\n"); // 'Minneapolis' print($record->postal->code . "\n"); // '55455' print($record->location->latitude . "\n"); // 44.9733 print($record->location->longitude . "\n"); // -93.2323 print($record->traits->network . "\n"); // '128.101.101.101/32' ``` ## Values to use for Database or Array Keys ## **We strongly discourage you from using a value from any `names` property as a key in a database or array.** These names may change between releases. Instead we recommend using one of the following: * `GeoIp2\Record\City` - `$city->geonameId` * `GeoIp2\Record\Continent` - `$continent->code` or `$continent->geonameId` * `GeoIp2\Record\Country` and `GeoIp2\Record\RepresentedCountry` - `$country->isoCode` or `$country->geonameId` * `GeoIp2\Record\Subdivision` - `$subdivision->isoCode` or `$subdivision->geonameId` ### What data is returned? ### While many of the end points return the same basic records, the attributes which can be populated vary between end points. In addition, while an end point may offer a particular piece of data, MaxMind does not always have every piece of data for any given IP address. Because of these factors, it is possible for any end point to return a record where some or all of the attributes are unpopulated. See the [GeoIP2 web service docs](https://dev.maxmind.com/geoip/docs/web-services?lang=en) for details on what data each end point may return. The only piece of data which is always returned is the `ipAddress` attribute in the `GeoIp2\Record\Traits` record. ## Integration with GeoNames ## [GeoNames](https://www.geonames.org/) offers web services and downloadable databases with data on geographical features around the world, including populated places. They offer both free and paid premium data. Each feature is unique identified by a `geonameId`, which is an integer. Many of the records returned by the GeoIP2 web services and databases include a `geonameId` property. This is the ID of a geographical feature (city, region, country, etc.) in the GeoNames database. Some of the data that MaxMind provides is also sourced from GeoNames. We source things like place names, ISO codes, and other similar data from the GeoNames premium data set. ## Reporting data problems ## If the problem you find is that an IP address is incorrectly mapped, please [submit your correction to MaxMind](https://www.maxmind.com/en/correction). If you find some other sort of mistake, like an incorrect spelling, please check the [GeoNames site](https://www.geonames.org/) first. Once you've searched for a place and found it on the GeoNames map view, there are a number of links you can use to correct data ("move", "edit", "alternate names", etc.). Once the correction is part of the GeoNames data set, it will be automatically incorporated into future MaxMind releases. If you are a paying MaxMind customer and you're not sure where to submit a correction, please [contact MaxMind support](https://www.maxmind.com/en/support) for help. ## Other Support ## Please report all issues with this code using the [GitHub issue tracker](https://github.com/maxmind/GeoIP2-php/issues). If you are having an issue with a MaxMind service that is not specific to the client API, please see [our support page](https://www.maxmind.com/en/support). ## Requirements ## This library requires PHP 7.2 or greater. This library also relies on the [MaxMind DB Reader](https://github.com/maxmind/MaxMind-DB-Reader-php). ## Contributing ## Patches and pull requests are encouraged. All code should follow the PSR-2 style guidelines. Please include unit tests whenever possible. You may obtain the test data for the maxmind-db folder by running `git submodule update --init --recursive` or adding `--recursive` to your initial clone, or from https://github.com/maxmind/MaxMind-DB ## Versioning ## The GeoIP2 PHP API uses [Semantic Versioning](https://semver.org/). ## Copyright and License ## This software is Copyright (c) 2013-2020 by MaxMind, Inc. This is free software, licensed under the Apache License, Version 2.0. PK9Zַ33geoip2/examples/benchmark.phpnu[city($ip); } catch (\GeoIp2\Exception\AddressNotFoundException $e) { } if ($i % 10000 === 0) { echo $i . ' ' . $ip . "\n"; } } $endTime = microtime(true); $duration = $endTime - $startTime; echo 'Requests per second: ' . $count / $duration . "\n"; PK9Z^,^,geoip2/LICENSEnu[ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. PK9Z&:*:*geoip2/CHANGELOG.mdnu[CHANGELOG ========= 2.13.0 (2022-08-05) ------------------- * The model class names are no longer constructed by concatenating strings. This change was made to improve support for tools like PHP-Scoper. Reported by Andrew Mead. GitHub #194. * Box 4.0.1 is now used to generate the `geoip2.phar` file. 2.12.2 (2021-11-30) ------------------- * The `geoip2.phar` now works when included from another directory. Reported by Eduardo Ruiz. GitHub #179. 2.12.1 (2021-11-23) ------------------- * The `geoip2.phar` included in 2.12.0 would only work in CLI applications. This was due to a change in Box 3.x. The Phar should now work in all applications. This release only affects users of the Phar file. 2.12.0 (2021-11-18) ------------------- * Support for mobile country code (MCC) and mobile network codes (MNC) was added for the GeoIP2 ISP and Enterprise databases as well as the GeoIP2 City and Insights web services. `$mobileCountryCode` and `$mobileNetworkCode` properties were added to `GeoIp2\Model\Isp` for the GeoIP2 ISP database and `GeoIp2\Record\Traits` for the Enterprise database and the GeoIP2 City and Insights web services. We expect this data to be available by late January, 2022. * `geoip2.phar` is now generated with Box 3.x. 2.11.0 (2020-10-01) ------------------- * IMPORTANT: PHP 7.2 or greater is now required. * Added the `isResidentialProxy` property to `GeoIp2\Model\AnonymousIP` and `GeoIp2\Record\Traits`. * Additional type hints have been added. 2.10.0 (2019-12-12) ------------------- * PHP 5.6 or greater is now required. * The `network` property was added to `GeoIp2\Record\Traits`, `GeoIp2\Model\AnonymousIp`, `GeoIp2\Model\Asn`, `GeoIp2\Model\ConnectionType`, `Geoip2\Model\Domain`, and `GeoIp2\Model\Isp`. This is a string in CIDR format representing the largest network where all of the properties besides `ipAddress` have the same value. * Updated documentation of anonymizer properties - `isAnonymousVpn` and `isHostingProvider` - to be more descriptive. * The `userCount` property was added to `GeoIp2\Record\Traits`. This is an integer which indicates the estimated number of users sharing the IP/network during the past 24 hours. This output is available from GeoIP2 Precision Insights. * The `staticIpScore` property was added to `GeoIp2\Record\Traits`. This is a float which indicates how static or dynamic an IP address is. This output is available from GeoIP2 Precision Insights. 2.9.0 (2018-04-10) ------------------ * Refer to account IDs using the terminology "account" rather than "user". 2.8.0 (2018-01-18) ------------------ * The `isInEuropeanUnion` property was added to `GeoIp2\Record\Country` and `GeoIp2\Record\RepresentedCountry`. This property is `true` if the country is a member state of the European Union. 2.7.0 (2017-10-27) ------------------ * The following new anonymizer properties were added to `GeoIp2\Record\Traits` for use with GeoIP2 Precision Insights: `isAnonymous`, `isAnonymousVpn`, `isHostingProvider`, `isPublicProxy`, and `isTorExitNode`. 2.6.0 (2017-07-10) ----------------- * Code clean-up and tidying. * Set minimum required PHP version to 5.4 in `composer.json`. Previously, 5.3 would work but was not tested. Now 5.4 is hard minimum version. 2.5.0 (2017-05-08) ------------------ * Support for PHP 5.3 was dropped. * Added support for GeoLite2 ASN database. 2.4.5 (2017-01-31) ------------------ * Additional error checking on the data returned from `MaxMind\Db\Reader` was added to help detect corrupt databases. GitHub #83. 2.4.4 (2016-10-11) ------------------ * `isset()` on `mostSpecificSubdivision` attribute now returns the correct value. Reported by Juan Francisco Giordana. GitHub #81. 2.4.3 (2016-10-11) ------------------ * `isset()` on `name` attribute now returns the correct value. Reported by Juan Francisco Giordana. GitHub #79. 2.4.2 (2016-08-17) ------------------ * Updated documentation to clarify what the accuracy radius refers to. * Upgraded `maxmind/web-service-common` to 0.3.0. This version uses `composer/ca-bundle` rather than our own CA bundle. GitHub #75. * Improved PHP documentation generation. 2.4.1 (2016-06-10) ------------------ * Corrected type annotations in documentation. GitHub #66. * Updated documentation to reflect that the accuracy radius is now included in City. * Upgraded web service client, which supports setting a proxy. GitHub #59. 2.4.0 (2016-04-15) ------------------ * Added support for the GeoIP2 Enterprise database. 2.3.3 (2015-09-24) ------------------ * Corrected case on `JsonSerializable` interface. Reported by Axel Etcheverry. GitHub #56. 2.3.2 (2015-09-23) ------------------ * `JsonSerializable` compatibility interface was moved to `GeoIp2\Compat` rather than the global namespace to prevent autoloading issues. Reported by Tomas Buteler. GitHub #54. * Missing documentation for the `$postal` property was added to the `GeoIp2\Model\City` class. Fix by Roy Sindre Norangshol. GitHub #51. * In the Phar distribution, source files for this module no longer have their documentation stripped, allowing IDE introspection to work properly. Reported by Dominic Black. GitHub #52. 2.3.1 (2015-06-30) ------------------ * Updated `maxmind/web-service-common` to version with fixes for PHP 5.3 and 5.4. 2.3.0 (2015-06-29) ------------------ * Support for demographics fields `averageIncome` and `populationDensity` in the `Location` record, returned by the Insights endpoint. * The `isAnonymousProxy` and `isSatelliteProvider` properties on `GeoIP2\Record\Traits` have been deprecated. Please use our [GeoIP2 Anonymous IP database](https://www.maxmind.com/en/geoip2-anonymous-ip-database) to determine whether an IP address is used by an anonymizing service. 2.2.0-beta1 (2015-06-09) ------------------------ * Typo fix in documentation. 2.2.0-alpha2 (2015-06-01) ------------------------- * `maxmind-ws/web-service-common` was renamed to `maxmind/web-service-common`. 2.2.0-alpha1 (2015-05-22) ------------------------- * The library no longer uses Guzzle and instead uses curl directly. * Support for `timeout` and `connectTimout` were added to the `$options` array passed to the `GeoIp2\WebService\Client` constructor. Pull request by Will Bradley. GitHub #36. 2.1.1 (2014-12-03) ------------------ * The 2.1.0 Phar builds included a shebang line, causing issues when loading it as a library. This has been corrected. GitHub #33. 2.1.0 (2014-10-29) ------------------ * Update ApiGen dependency to version that isn't broken on case sensitive file systems. * Added support for the GeoIP2 Anonymous IP database. The `GeoIP2\Database\Reader` class now has an `anonymousIp` method which returns a `GeoIP2\Model\AnonymousIp` object. * Boolean attributes like those in the `GeoIP2\Record\Traits` class now return `false` instead of `null` when they were not true. 2.0.0 (2014-09-22) ------------------ * First production release. 0.9.0 (2014-09-15) ------------------ * IMPORTANT: The deprecated `omni()` and `cityIspOrg()` methods have been removed from `GeoIp2\WebService\Client`. 0.8.1 (2014-09-12) ------------------ * The check added to the `GeoIP2\Database\Reader` lookup methods in 0.8.0 did not work with the GeoIP2 City Database Subset by Continent with World Countries. This has been fixed. Fixes GitHub issue #23. 0.8.0 (2014-09-10) ------------------ * The `GeoIp2\Database\Reader` lookup methods (e.g., `city()`, `isp()`) now throw a `BadMethodCallException` if they are used with a database that does not match the method. In particular, doing a `city()` lookup on a GeoIP2 Country database will result in an exception, and vice versa. * A `metadata()` method has been added to the `GeoIP2\Database\Reader` class. This returns a `MaxMind\Db\Reader\Metadata` class with information about the database. * The name attribute was missing from the RepresentedCountry class. 0.7.0 (2014-07-22) ------------------ * The web service client API has been updated for the v2.1 release of the web service. In particular, the `cityIspOrg` and `omni` methods on `GeoIp2\WebService\Client` should be considered deprecated. The `city` method now provides all of the data formerly provided by `cityIspOrg`, and the `omni` method has been replaced by the `insights` method. * Support was added for GeoIP2 Connection Type, Domain and ISP databases. 0.6.3 (2014-05-12) ------------------ * With the previous Phar builds, some users received `phar error: invalid url or non-existent phar` errors. The correct alias is now used for the Phar, and this should no longer be an issue. 0.6.2 (2014-05-08) ------------------ * The Phar build was broken with Guzzle 3.9.0+. This has been fixed. 0.6.1 (2014-05-01) ------------------ * This API now officially supports HHVM. * The `maxmind-db/reader` dependency was updated to a version that does not require BC Math. * The Composer compatibility autoload rules are now targeted more narrowly. * A `box.json` file is included to build a Phar package. 0.6.0 (2014-02-19) ------------------ * This API is now licensed under the Apache License, Version 2.0. * Model and record classes now implement `JsonSerializable`. * `isset` now works with model and record classes. 0.5.0 (2013-10-21) ------------------ * Renamed $languages constructor parameters to $locales for both the Client and Reader classes. * Documentation and code clean-up (Ben Morel). * Added the interface `GeoIp2\ProviderInterface`, which is implemented by both `\GeoIp2\Database\Reader` and `\GeoIp2\WebService\Client`. 0.4.0 (2013-07-16) ------------------ * This is the first release with the GeoIP2 database reader. Please see the `README.md` file and the `\GeoIp2\Database\Reader` class. * The general exception classes were replaced with specific exception classes representing particular types of errors, such as an authentication error. 0.3.0 (2013-07-12) ------------------ * In namespaces and class names, "GeoIP2" was renamed to "GeoIp2" to improve consistency. 0.2.1 (2013-06-10) ------------------ * First official beta release. * Documentation updates and corrections. 0.2.0 (2013-05-29) ------------------ * `GenericException` was renamed to `GeoIP2Exception`. * We now support more languages. The new languages are de, es, fr, and pt-BR. * The REST API now returns a record with data about your account. There is a new `GeoIP\Records\MaxMind` class for this data. * The `continentCode` attribute on `Continent` was renamed to `code`. * Documentation updates. 0.1.1 (2013-05-14) ------------------ * Updated Guzzle version requirement. * Fixed Composer example in README.md. 0.1.0 (2013-05-13) ------------------ * Initial release. PK9Zddgeoip2/composer.jsonnu[PK9ZWA&geoip2/src/Exception/HttpException.phpnu[PK9ZUU0geoip2/src/Exception/InvalidRequestException.phpnu[PK9Zčê0geoip2/src/Exception/AuthenticationException.phpnu[PK9Z3. geoip2/src/Exception/OutOfQueriesException.phpnu[PK9Z7n J1 geoip2/src/Exception/AddressNotFoundException.phpnu[PK9Z-D( geoip2/src/Exception/GeoIp2Exception.phpnu[PK9ZWW..  geoip2/src/WebService/Client.phpnu[PK9Zl\yy;geoip2/src/Util.phpnu[PK9Z<}a((?geoip2/src/Database/Reader.phpnu[PK9Z *) ) hgeoip2/src/Model/AnonymousIp.phpnu[PK9Zb)O,sgeoip2/src/Model/Enterprise.phpnu[PK9ZoY4u tgeoip2/src/Model/City.phpnu[PK9Z'_ ~geoip2/src/Model/Country.phpnu[PK9Zy#geoip2/src/Model/ConnectionType.phpnu[PK9Zk363 3 Ñgeoip2/src/Model/Isp.phpnu[PK9Z`@>geoip2/src/Model/Insights.phpnu[PK9Z_geoip2/src/Model/Asn.phpnu[PK9Zi"geoip2/src/Model/AbstractModel.phpnu[PK9ZkdFgeoip2/src/Model/Domain.phpnu[PK9Zr1|dPP(geoip2/src/Record/RepresentedCountry.phpnu[PK9ZTܓ-geoip2/src/Record/Postal.phpnu[PK9Z9TPPgeoip2/src/Record/City.phpnu[PK9ZCƕ<<geoip2/src/Record/Country.phpnu[PK9Z6||geoip2/src/Record/Location.phpnu[PK9ZU)geoip2/src/Record/AbstractPlaceRecord.phpnu[PK9Zl  !1geoip2/src/Record/Subdivision.phpnu[PK9Z~ddgeoip2/src/Record/Continent.phpnu[PK9Z/?geoip2/src/Record/Traits.phpnu[PK9Zx$<geoip2/src/Record/AbstractRecord.phpnu[PK9Zq?geoip2/src/Record/MaxMind.phpnu[PK9ZQ Wgeoip2/src/ProviderInterface.phpnu[PK9ZҨd|8|8geoip2/README.mdnu[PK9Zַ338geoip2/examples/benchmark.phpnu[PK9Z^,^,;geoip2/LICENSEnu[PK9Z&:*:*ggeoip2/CHANGELOG.mdnu[PK$$`