Merge branch 'MDL-67380-master' of git://github.com/aanabit/moodle
This commit is contained in:
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace GeoIp2\Compat;
|
||||
|
||||
// @codingStandardsIgnoreFile
|
||||
|
||||
/**
|
||||
* This interface exists to provide backwards compatibility with PHP 5.3
|
||||
*
|
||||
* This should _not_ be used by any third-party code.
|
||||
*
|
||||
* @ignore
|
||||
*/
|
||||
if (interface_exists('JsonSerializable')) {
|
||||
interface JsonSerializable extends \JsonSerializable
|
||||
{
|
||||
}
|
||||
} else {
|
||||
interface JsonSerializable
|
||||
{
|
||||
/**
|
||||
* Returns data that can be serialized by json_encode
|
||||
* @ignore
|
||||
*/
|
||||
public function jsonSerialize();
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,7 @@ use MaxMind\Db\Reader\InvalidDatabaseException;
|
||||
class Reader implements ProviderInterface
|
||||
{
|
||||
private $dbReader;
|
||||
private $dbType;
|
||||
private $locales;
|
||||
|
||||
/**
|
||||
@@ -51,6 +52,7 @@ class Reader implements ProviderInterface
|
||||
$locales = ['en']
|
||||
) {
|
||||
$this->dbReader = new DbReader($filename);
|
||||
$this->dbType = $this->dbReader->metadata()->databaseType;
|
||||
$this->locales = $locales;
|
||||
}
|
||||
|
||||
@@ -212,9 +214,11 @@ class Reader implements ProviderInterface
|
||||
|
||||
private function modelFor($class, $type, $ipAddress)
|
||||
{
|
||||
$record = $this->getRecord($class, $type, $ipAddress);
|
||||
list($record, $prefixLen) = $this->getRecord($class, $type, $ipAddress);
|
||||
|
||||
$record['traits']['ip_address'] = $ipAddress;
|
||||
$record['traits']['prefix_len'] = $prefixLen;
|
||||
|
||||
$class = 'GeoIp2\\Model\\' . $class;
|
||||
|
||||
return new $class($record, $this->locales);
|
||||
@@ -222,9 +226,10 @@ class Reader implements ProviderInterface
|
||||
|
||||
private function flatModelFor($class, $type, $ipAddress)
|
||||
{
|
||||
$record = $this->getRecord($class, $type, $ipAddress);
|
||||
list($record, $prefixLen) = $this->getRecord($class, $type, $ipAddress);
|
||||
|
||||
$record['ip_address'] = $ipAddress;
|
||||
$record['prefix_len'] = $prefixLen;
|
||||
$class = 'GeoIp2\\Model\\' . $class;
|
||||
|
||||
return new $class($record);
|
||||
@@ -232,20 +237,19 @@ class Reader implements ProviderInterface
|
||||
|
||||
private function getRecord($class, $type, $ipAddress)
|
||||
{
|
||||
if (strpos($this->metadata()->databaseType, $type) === false) {
|
||||
if (strpos($this->dbType, $type) === false) {
|
||||
$method = lcfirst($class);
|
||||
throw new \BadMethodCallException(
|
||||
"The $method method cannot be used to open a "
|
||||
. $this->metadata()->databaseType . ' database'
|
||||
"The $method method cannot be used to open a {$this->dbType} database"
|
||||
);
|
||||
}
|
||||
$record = $this->dbReader->get($ipAddress);
|
||||
list($record, $prefixLen) = $this->dbReader->getWithPrefixLen($ipAddress);
|
||||
if ($record === null) {
|
||||
throw new AddressNotFoundException(
|
||||
"The address $ipAddress is not in the database."
|
||||
);
|
||||
}
|
||||
if (!is_array($record)) {
|
||||
if (!\is_array($record)) {
|
||||
// This can happen on corrupt databases. Generally,
|
||||
// MaxMind\Db\Reader will throw a
|
||||
// MaxMind\Db\Reader\InvalidDatabaseException, but occasionally
|
||||
@@ -255,11 +259,11 @@ class Reader implements ProviderInterface
|
||||
// exceptions go unnoticed.
|
||||
throw new InvalidDatabaseException(
|
||||
"Expected an array when looking up $ipAddress but received: "
|
||||
. gettype($record)
|
||||
. \gettype($record)
|
||||
);
|
||||
}
|
||||
|
||||
return $record;
|
||||
return [$record, $prefixLen];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,21 +2,28 @@
|
||||
|
||||
namespace GeoIp2\Model;
|
||||
|
||||
use GeoIp2\Util;
|
||||
|
||||
/**
|
||||
* This class provides the GeoIP2 Anonymous IP model.
|
||||
*
|
||||
* @property-read bool $isAnonymous This is true if the IP address belongs to
|
||||
* any sort of anonymous network.
|
||||
* @property-read bool $isAnonymousVpn This is true if the IP address belongs to
|
||||
* an anonymous VPN system.
|
||||
* @property-read bool $isAnonymousVpn This is true if the IP address is
|
||||
* registered to an anonymous VPN provider. If a VPN provider does not
|
||||
* register subnets under names associated with them, we will likely only
|
||||
* flag their IP ranges using the isHostingProvider property.
|
||||
* @property-read bool $isHostingProvider This is true if the IP address belongs
|
||||
* to a hosting provider.
|
||||
* to a hosting or VPN provider (see description of isAnonymousVpn property).
|
||||
* @property-read bool $isPublicProxy This is true if the IP address belongs to
|
||||
* a public proxy.
|
||||
* @property-read bool $isTorExitNode This is true if the IP address is a Tor
|
||||
* exit node.
|
||||
* @property-read string $ipAddress The IP address that the data in the model is
|
||||
* for.
|
||||
* @property-read string $network The network in CIDR notation associated with
|
||||
* the record. In particular, this is the largest network where all of the
|
||||
* fields besides $ipAddress have the same value.
|
||||
*/
|
||||
class AnonymousIp extends AbstractModel
|
||||
{
|
||||
@@ -26,6 +33,7 @@ class AnonymousIp extends AbstractModel
|
||||
protected $isPublicProxy;
|
||||
protected $isTorExitNode;
|
||||
protected $ipAddress;
|
||||
protected $network;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
@@ -41,6 +49,8 @@ class AnonymousIp extends AbstractModel
|
||||
$this->isHostingProvider = $this->get('is_hosting_provider');
|
||||
$this->isPublicProxy = $this->get('is_public_proxy');
|
||||
$this->isTorExitNode = $this->get('is_tor_exit_node');
|
||||
$this->ipAddress = $this->get('ip_address');
|
||||
$ipAddress = $this->get('ip_address');
|
||||
$this->ipAddress = $ipAddress;
|
||||
$this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace GeoIp2\Model;
|
||||
|
||||
use GeoIp2\Util;
|
||||
|
||||
/**
|
||||
* This class provides the GeoLite2 ASN model.
|
||||
*
|
||||
@@ -12,12 +14,16 @@ namespace GeoIp2\Model;
|
||||
* address.
|
||||
* @property-read string $ipAddress The IP address that the data in the model is
|
||||
* for.
|
||||
* @property-read string $network The network in CIDR notation associated with
|
||||
* the record. In particular, this is the largest network where all of the
|
||||
* fields besides $ipAddress have the same value.
|
||||
*/
|
||||
class Asn extends AbstractModel
|
||||
{
|
||||
protected $autonomousSystemNumber;
|
||||
protected $autonomousSystemOrganization;
|
||||
protected $ipAddress;
|
||||
protected $network;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
@@ -30,6 +36,8 @@ class Asn extends AbstractModel
|
||||
$this->autonomousSystemNumber = $this->get('autonomous_system_number');
|
||||
$this->autonomousSystemOrganization =
|
||||
$this->get('autonomous_system_organization');
|
||||
$this->ipAddress = $this->get('ip_address');
|
||||
$ipAddress = $this->get('ip_address');
|
||||
$this->ipAddress = $ipAddress;
|
||||
$this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,42 +7,25 @@ namespace GeoIp2\Model;
|
||||
*
|
||||
* The only difference between the City and Insights model classes is which
|
||||
* fields in each record may be populated. See
|
||||
* http://dev.maxmind.com/geoip/geoip2/web-services more details.
|
||||
* https://dev.maxmind.com/geoip/geoip2/web-services for more details.
|
||||
*
|
||||
* @property-read \GeoIp2\Record\City $city City data for the requested IP
|
||||
* address.
|
||||
* @property-read \GeoIp2\Record\Continent $continent Continent data for the
|
||||
* requested IP address.
|
||||
* @property-read \GeoIp2\Record\Country $country Country data for the requested
|
||||
* IP address. This object represents the country where MaxMind believes the
|
||||
* end user is located.
|
||||
* @property-read \GeoIp2\Record\Location $location Location data for the
|
||||
* requested IP address.
|
||||
* @property-read \GeoIp2\Record\Postal $postal Postal data for the
|
||||
* requested IP address.
|
||||
* @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
|
||||
* account.
|
||||
* @property-read \GeoIp2\Record\Country $registeredCountry Registered country
|
||||
* data for the requested IP address. This record represents the country
|
||||
* where the ISP has registered a given IP block and may differ from the
|
||||
* user's country.
|
||||
* @property-read \GeoIp2\Record\RepresentedCountry $representedCountry
|
||||
* Represented country data for the requested IP address. The represented
|
||||
* country is used for things like military bases. It is only present when
|
||||
* the represented country differs from the country.
|
||||
* @property-read array $subdivisions An array of {@link \GeoIp2\Record\Subdivision}
|
||||
* @property-read array $subdivisions An array \GeoIp2\Record\Subdivision
|
||||
* objects representing the country subdivisions for the requested IP
|
||||
* address. The number and type of subdivisions varies by country, but a
|
||||
* subdivision is typically a state, province, county, etc. Subdivisions
|
||||
* are ordered from most general (largest) to most specific (smallest).
|
||||
* If the response did not contain any subdivisions, this method returns
|
||||
* an empty array.
|
||||
* @property-read \GeoIp2\Record\Subdivision $mostSpecificSubdivision An object
|
||||
* @property-read \GeoIp2\Record\Subdivision $mostSpecificSubdivision An object
|
||||
* representing the most specific subdivision returned. If the response
|
||||
* did not contain any subdivisions, this method returns an empty
|
||||
* {@link \GeoIp2\Record\Subdivision} object.
|
||||
* @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
|
||||
* requested IP address.
|
||||
* \GeoIp2\Record\Subdivision object.
|
||||
*/
|
||||
class City extends Country
|
||||
{
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace GeoIp2\Model;
|
||||
|
||||
use GeoIp2\Util;
|
||||
|
||||
/**
|
||||
* This class provides the GeoIP2 Connection-Type model.
|
||||
*
|
||||
@@ -10,11 +12,15 @@ namespace GeoIp2\Model;
|
||||
* Additional values may be added in the future.
|
||||
* @property-read string $ipAddress The IP address that the data in the model is
|
||||
* for.
|
||||
* @property-read string $network The network in CIDR notation associated with
|
||||
* the record. In particular, this is the largest network where all of the
|
||||
* fields besides $ipAddress have the same value.
|
||||
*/
|
||||
class ConnectionType extends AbstractModel
|
||||
{
|
||||
protected $connectionType;
|
||||
protected $ipAddress;
|
||||
protected $network;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
@@ -26,6 +32,8 @@ class ConnectionType extends AbstractModel
|
||||
parent::__construct($raw);
|
||||
|
||||
$this->connectionType = $this->get('connection_type');
|
||||
$this->ipAddress = $this->get('ip_address');
|
||||
$ipAddress = $this->get('ip_address');
|
||||
$this->ipAddress = $ipAddress;
|
||||
$this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace GeoIp2\Model;
|
||||
*
|
||||
* The only difference between the City and Insights model classes is which
|
||||
* fields in each record may be populated. See
|
||||
* http://dev.maxmind.com/geoip/geoip2/web-services more details.
|
||||
* https://dev.maxmind.com/geoip/geoip2/web-services for more details.
|
||||
*
|
||||
* @property-read \GeoIp2\Record\Continent $continent Continent data for the
|
||||
* requested IP address.
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace GeoIp2\Model;
|
||||
|
||||
use GeoIp2\Util;
|
||||
|
||||
/**
|
||||
* This class provides the GeoIP2 Domain model.
|
||||
*
|
||||
@@ -10,11 +12,15 @@ namespace GeoIp2\Model;
|
||||
* "example.co.uk", not "foo.example.com".
|
||||
* @property-read string $ipAddress The IP address that the data in the model is
|
||||
* for.
|
||||
* @property-read string $network The network in CIDR notation associated with
|
||||
* the record. In particular, this is the largest network where all of the
|
||||
* fields besides $ipAddress have the same value.
|
||||
*/
|
||||
class Domain extends AbstractModel
|
||||
{
|
||||
protected $domain;
|
||||
protected $ipAddress;
|
||||
protected $network;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
@@ -26,6 +32,8 @@ class Domain extends AbstractModel
|
||||
parent::__construct($raw);
|
||||
|
||||
$this->domain = $this->get('domain');
|
||||
$this->ipAddress = $this->get('ip_address');
|
||||
$ipAddress = $this->get('ip_address');
|
||||
$this->ipAddress = $ipAddress;
|
||||
$this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,40 +7,7 @@ namespace GeoIp2\Model;
|
||||
*
|
||||
* The only difference between the City and Enterprise model classes is which
|
||||
* fields in each record may be populated. See
|
||||
* http://dev.maxmind.com/geoip/geoip2/web-services more details.
|
||||
*
|
||||
* @property-read \GeoIp2\Record\City $city City data for the requested IP
|
||||
* address.
|
||||
* @property-read \GeoIp2\Record\Continent $continent Continent data for the
|
||||
* requested IP address.
|
||||
* @property-read \GeoIp2\Record\Country $country Country data for the requested
|
||||
* IP address. This object represents the country where MaxMind believes the
|
||||
* end user is located.
|
||||
* @property-read \GeoIp2\Record\Location $location Location data for the
|
||||
* requested IP address.
|
||||
* @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
|
||||
* account.
|
||||
* @property-read \GeoIp2\Record\Country $registeredCountry Registered country
|
||||
* data for the requested IP address. This record represents the country
|
||||
* where the ISP has registered a given IP block and may differ from the
|
||||
* user's country.
|
||||
* @property-read \GeoIp2\Record\RepresentedCountry $representedCountry
|
||||
* Represented country data for the requested IP address. The represented
|
||||
* country is used for things like military bases. It is only present when
|
||||
* the represented country differs from the country.
|
||||
* @property-read array $subdivisions An array of {@link \GeoIp2\Record\Subdivision}
|
||||
* objects representing the country subdivisions for the requested IP
|
||||
* address. The number and type of subdivisions varies by country, but a
|
||||
* subdivision is typically a state, province, county, etc. Subdivisions
|
||||
* are ordered from most general (largest) to most specific (smallest).
|
||||
* If the response did not contain any subdivisions, this method returns
|
||||
* an empty array.
|
||||
* @property-read \GeoIp2\Record\Subdivision $mostSpecificSubdivision An object
|
||||
* representing the most specific subdivision returned. If the response
|
||||
* did not contain any subdivisions, this method returns an empty
|
||||
* {@link \GeoIp2\Record\Subdivision} object.
|
||||
* @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
|
||||
* requested IP address.
|
||||
* https://dev.maxmind.com/geoip/geoip2/web-services for more details.
|
||||
*/
|
||||
class Enterprise extends City
|
||||
{
|
||||
|
||||
@@ -7,40 +7,7 @@ namespace GeoIp2\Model;
|
||||
*
|
||||
* The only difference between the City and Insights model classes is which
|
||||
* fields in each record may be populated. See
|
||||
* http://dev.maxmind.com/geoip/geoip2/web-services more details.
|
||||
*
|
||||
* @property-read \GeoIp2\Record\City $city City data for the requested IP
|
||||
* address.
|
||||
* @property-read \GeoIp2\Record\Continent $continent Continent data for the
|
||||
* requested IP address.
|
||||
* @property-read \GeoIp2\Record\Country $country Country data for the requested
|
||||
* IP address. This object represents the country where MaxMind believes the
|
||||
* end user is located.
|
||||
* @property-read \GeoIp2\Record\Location $location Location data for the
|
||||
* requested IP address.
|
||||
* @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
|
||||
* account.
|
||||
* @property-read \GeoIp2\Record\Country $registeredCountry Registered country
|
||||
* data for the requested IP address. This record represents the country
|
||||
* where the ISP has registered a given IP block and may differ from the
|
||||
* user's country.
|
||||
* @property-read \GeoIp2\Record\RepresentedCountry $representedCountry
|
||||
* Represented country data for the requested IP address. The represented
|
||||
* country is used for things like military bases. It is only present when
|
||||
* the represented country differs from the country.
|
||||
* @property-read array $subdivisions An array of {@link \GeoIp2\Record\Subdivision}
|
||||
* objects representing the country subdivisions for the requested IP
|
||||
* address. The number and type of subdivisions varies by country, but a
|
||||
* subdivision is typically a state, province, county, etc. Subdivisions
|
||||
* are ordered from most general (largest) to most specific (smallest).
|
||||
* If the response did not contain any subdivisions, this method returns
|
||||
* an empty array.
|
||||
* @property-read \GeoIp2\Record\Subdivision $mostSpecificSubdivision An object
|
||||
* representing the most specific subdivision returned. If the response
|
||||
* did not contain any subdivisions, this method returns an empty
|
||||
* {@link \GeoIp2\Record\Subdivision} object.
|
||||
* @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
|
||||
* requested IP address.
|
||||
* https://dev.maxmind.com/geoip/geoip2/web-services for more details.
|
||||
*/
|
||||
class Insights extends City
|
||||
{
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace GeoIp2\Model;
|
||||
|
||||
use GeoIp2\Util;
|
||||
|
||||
/**
|
||||
* This class provides the GeoIP2 ISP model.
|
||||
*
|
||||
@@ -16,6 +18,9 @@ namespace GeoIp2\Model;
|
||||
* with the IP address.
|
||||
* @property-read string $ipAddress The IP address that the data in the model is
|
||||
* for.
|
||||
* @property-read string $network The network in CIDR notation associated with
|
||||
* the record. In particular, this is the largest network where all of the
|
||||
* fields besides $ipAddress have the same value.
|
||||
*/
|
||||
class Isp extends AbstractModel
|
||||
{
|
||||
@@ -24,6 +29,7 @@ class Isp extends AbstractModel
|
||||
protected $isp;
|
||||
protected $organization;
|
||||
protected $ipAddress;
|
||||
protected $network;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
@@ -39,6 +45,8 @@ class Isp extends AbstractModel
|
||||
$this->isp = $this->get('isp');
|
||||
$this->organization = $this->get('organization');
|
||||
|
||||
$this->ipAddress = $this->get('ip_address');
|
||||
$ipAddress = $this->get('ip_address');
|
||||
$this->ipAddress = $ipAddress;
|
||||
$this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ abstract class AbstractRecord implements \JsonSerializable
|
||||
|
||||
private function validAttribute($attr)
|
||||
{
|
||||
return in_array($attr, $this->validAttributes, true);
|
||||
return \in_array($attr, $this->validAttributes, true);
|
||||
}
|
||||
|
||||
public function jsonSerialize()
|
||||
|
||||
@@ -15,10 +15,9 @@ namespace GeoIp2\Record;
|
||||
* @property-read bool $isInEuropeanUnion This is true if the country is a
|
||||
* member state of the European Union. This attribute is returned by all
|
||||
* location services and databases.
|
||||
* @property-read string|null $isoCode The
|
||||
* {@link * http://en.wikipedia.org/wiki/ISO_3166-1 two-character ISO 3166-1 alpha
|
||||
* code} for the country. This attribute is returned by all location services
|
||||
* and databases.
|
||||
* @property-read string|null $isoCode The two-character ISO 3166-1 alpha code
|
||||
* for the country. See https://en.wikipedia.org/wiki/ISO_3166-1. This
|
||||
* attribute is returned by all location services and databases.
|
||||
* @property-read string|null $name The name of the country based on the locales
|
||||
* list passed to the constructor. This attribute is returned by all location
|
||||
* services and databases.
|
||||
|
||||
@@ -27,11 +27,11 @@ namespace GeoIp2\Record;
|
||||
* from the Insights service.
|
||||
* @property-read int|null $metroCode The metro code of the location if the location
|
||||
* is in the US. MaxMind returns the same metro codes as the
|
||||
* {@link * https://developers.google.com/adwords/api/docs/appendix/cities-DMAregions
|
||||
* Google AdWords API}.
|
||||
* Google AdWords API. See
|
||||
* https://developers.google.com/adwords/api/docs/appendix/cities-DMAregions.
|
||||
* @property-read string|null $timeZone The time zone associated with location, as
|
||||
* specified by the {@link http://www.iana.org/time-zones IANA Time Zone
|
||||
* Database}, e.g., "America/New_York".
|
||||
* specified by the IANA Time Zone Database, e.g., "America/New_York". See
|
||||
* https://www.iana.org/time-zones.
|
||||
*/
|
||||
class Location extends AbstractRecord
|
||||
{
|
||||
|
||||
@@ -9,19 +9,6 @@ namespace GeoIp2\Record;
|
||||
* for the IP's represented country. The represented country is the country
|
||||
* represented by something like a military base.
|
||||
*
|
||||
* @property-read int|null $confidence A value from 0-100 indicating MaxMind's
|
||||
* confidence that the country is correct. This attribute is only available
|
||||
* from the Insights service and the GeoIP2 Enterprise database.
|
||||
* @property-read int|null $geonameId The GeoName ID for the country.
|
||||
* @property-read bool $isInEuropeanUnion This is true if the country is a
|
||||
* member state of the European Union. This attribute is returned by all
|
||||
* location services and databases.
|
||||
* @property-read string|null $isoCode The {@link http://en.wikipedia.org/wiki/ISO_3166-1
|
||||
* two-character ISO 3166-1 alpha code} for the country.
|
||||
* @property-read string|null $name The name of the country based on the locales list
|
||||
* passed to the constructor.
|
||||
* @property-read array|null $names An array map where the keys are locale codes and
|
||||
* the values are names.
|
||||
* @property-read string|null $type A string indicating the type of entity that is
|
||||
* representing the country. Currently we only return <code>military</code>
|
||||
* but this could expand to include other types in the future.
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace GeoIp2\Record;
|
||||
* This attribute is returned by all location databases and services besides
|
||||
* Country.
|
||||
* @property-read string|null $isoCode This is a string up to three characters long
|
||||
* contain the subdivision portion of the
|
||||
* {@link * http://en.wikipedia.org/wiki/ISO_3166-2 ISO 3166-2 code}. This attribute
|
||||
* is returned by all location databases and services except Country.
|
||||
* contain the subdivision portion of the ISO 3166-2 code. See
|
||||
* https://en.wikipedia.org/wiki/ISO_3166-2. This attribute is returned by all
|
||||
* location databases and services except Country.
|
||||
* @property-read string|null $name The name of the subdivision based on the
|
||||
* locales list passed to the constructor. This attribute is returned by all
|
||||
* location databases and services besides Country.
|
||||
|
||||
@@ -2,21 +2,23 @@
|
||||
|
||||
namespace GeoIp2\Record;
|
||||
|
||||
use GeoIp2\Util;
|
||||
|
||||
/**
|
||||
* Contains data for the traits record associated with an IP address.
|
||||
*
|
||||
* This record is returned by all location services and databases.
|
||||
*
|
||||
* @property-read int|null $autonomousSystemNumber The
|
||||
* {@link * http://en.wikipedia.org/wiki/Autonomous_system_(Internet) autonomous
|
||||
* system number} associated with the IP address. This attribute is only
|
||||
* available from the City and Insights web service and the GeoIP2
|
||||
* @property-read int|null $autonomousSystemNumber The autonomous system number
|
||||
* associated with the IP address. See
|
||||
* https://en.wikipedia.org/wiki/Autonomous_system_(Internet%29. This attribute
|
||||
* is only available from the City and Insights web service and the GeoIP2
|
||||
* Enterprise database.
|
||||
* @property-read string|null $autonomousSystemOrganization The organization
|
||||
* associated with the registered {@link * http://en.wikipedia.org/wiki/Autonomous_system_(Internet) autonomous
|
||||
* system number} for the IP address. This attribute is only available from
|
||||
* the City and Insights web service and the GeoIP2 Enterprise
|
||||
* database.
|
||||
* associated with the registered autonomous system number for the IP address.
|
||||
* See https://en.wikipedia.org/wiki/Autonomous_system_(Internet%29. This
|
||||
* attribute is only available from the City and Insights web service and the
|
||||
* GeoIP2 Enterprise database.
|
||||
* @property-read string|null $connectionType The connection type may take the
|
||||
* following values: "Dialup", "Cable/DSL", "Corporate", "Cellular".
|
||||
* Additional values may be added in the future. This attribute is only
|
||||
@@ -35,16 +37,18 @@ namespace GeoIp2\Record;
|
||||
* @property-read bool $isAnonymous This is true if the IP address belongs to
|
||||
* any sort of anonymous network. This property is only available from GeoIP2
|
||||
* Precision Insights.
|
||||
* @property-read bool $isAnonymousProxy *Deprecated.* Please see our
|
||||
* {@link * https://www.maxmind.com/en/geoip2-anonymous-ip-database GeoIP2
|
||||
* Anonymous IP database} to determine whether the IP address is used by an
|
||||
* anonymizing service.
|
||||
* @property-read bool $isAnonymousVpn This is true if the IP address belongs to
|
||||
* an anonymous VPN system. This property is only available from GeoIP2
|
||||
* Precision Insights.
|
||||
* @property-read bool $isAnonymousProxy *Deprecated.* Please see our GeoIP2
|
||||
* Anonymous IP database
|
||||
* (https://www.maxmind.com/en/geoip2-anonymous-ip-database) to determine
|
||||
* whether the IP address is used by an anonymizing service.
|
||||
* @property-read bool $isAnonymousVpn This is true if the IP address is
|
||||
* registered to an anonymous VPN provider. If a VPN provider does not register
|
||||
* subnets under names associated with them, we will likely only flag their IP
|
||||
* ranges using the isHostingProvider property. This property is only available
|
||||
* from GeoIP2 Precision Insights.
|
||||
* @property-read bool $isHostingProvider This is true if the IP address belongs
|
||||
* to a hosting provider. This property is only available from GeoIP2
|
||||
* Precision Insights.
|
||||
* to a hosting or VPN provider (see description of isAnonymousVpn property).
|
||||
* This property is only available from GeoIP2 Precision Insights.
|
||||
* @property-read bool $isLegitimateProxy This attribute is true if MaxMind
|
||||
* believes this IP address to be a legitimate proxy, such as an internal
|
||||
* VPN used by a corporation. This attribute is only available in the GeoIP2
|
||||
@@ -61,9 +65,19 @@ namespace GeoIp2\Record;
|
||||
* @property-read string|null $isp The name of the ISP associated with the IP
|
||||
* address. This attribute is only available from the City and Insights web
|
||||
* services and the GeoIP2 Enterprise database.
|
||||
* @property-read string $network The network in CIDR notation associated with
|
||||
* the record. In particular, this is the largest network where all of the
|
||||
* fields besides $ipAddress have the same value.
|
||||
* @property-read string|null $organization The name of the organization associated
|
||||
* with the IP address. This attribute is only available from the City and
|
||||
* Insights web services and the GeoIP2 Enterprise database.
|
||||
* @property-read float|null $staticIPScore An indicator of how static or
|
||||
* dynamic an IP address is. This property is only available from GeoIP2
|
||||
* Precision Insights.
|
||||
* @property-read int|null $userCount The estimated number of users sharing
|
||||
* the IP/network during the past 24 hours. For IPv4, the count is for the
|
||||
* individual IP. For IPv6, the count is for the /64 network. This property is
|
||||
* only available from GeoIP2 Precision Insights.
|
||||
* @property-read string|null $userType <p>The user type associated with the IP
|
||||
* address. This can be one of the following values:</p>
|
||||
* <ul>
|
||||
@@ -108,7 +122,19 @@ class Traits extends AbstractRecord
|
||||
'isPublicProxy',
|
||||
'isSatelliteProvider',
|
||||
'isTorExitNode',
|
||||
'network',
|
||||
'organization',
|
||||
'staticIpScore',
|
||||
'userCount',
|
||||
'userType',
|
||||
];
|
||||
|
||||
public function __construct($record)
|
||||
{
|
||||
if (!isset($record['network']) && isset($record['ip_address']) && isset($record['prefix_len'])) {
|
||||
$record['network'] = Util::cidr($record['ip_address'], $record['prefix_len']);
|
||||
}
|
||||
|
||||
parent::__construct($record);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace GeoIp2;
|
||||
|
||||
class Util
|
||||
{
|
||||
/**
|
||||
* This returns the network in CIDR notation for the given IP and prefix
|
||||
* length. This is for internal use only.
|
||||
*
|
||||
* @internal
|
||||
* @ignore
|
||||
*
|
||||
* @param mixed $ipAddress
|
||||
* @param mixed $prefixLen
|
||||
*/
|
||||
public static function cidr($ipAddress, $prefixLen)
|
||||
{
|
||||
$ipBytes = inet_pton($ipAddress);
|
||||
$networkBytes = str_repeat("\0", \strlen($ipBytes));
|
||||
|
||||
$curPrefix = $prefixLen;
|
||||
for ($i = 0; $i < \strlen($ipBytes) && $curPrefix > 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";
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,7 @@ class Client implements ProviderInterface
|
||||
private $client;
|
||||
private static $basePath = '/geoip/v2.1';
|
||||
|
||||
const VERSION = 'v2.9.0';
|
||||
const VERSION = 'v2.10.0';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -74,7 +74,7 @@ class Client implements ProviderInterface
|
||||
|
||||
// This is for backwards compatibility. Do not remove except for a
|
||||
// major version bump.
|
||||
if (is_string($options)) {
|
||||
if (\is_string($options)) {
|
||||
$options = ['host' => $options];
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ class Client implements ProviderInterface
|
||||
* @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.
|
||||
* 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.
|
||||
@@ -173,7 +173,7 @@ class Client implements ProviderInterface
|
||||
* @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.
|
||||
* 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.
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
1.5.1 (2019-12-12)
|
||||
------------------
|
||||
|
||||
* Minor performance improvements.
|
||||
* Make tests pass with older versions of libmaxminddb. PR by Remi
|
||||
Collet. GitHub #90.
|
||||
* Test enhancements. PR by Chun-Sheng, Li. GitHub #91.
|
||||
|
||||
1.5.0 (2019-09-30)
|
||||
------------------
|
||||
|
||||
* PHP 5.6 or greater is now required.
|
||||
* The C extension now supports PHP 8. Pull request by John Boehr.
|
||||
GitHub #87.
|
||||
* A new method, `getWithPrefixLen`, was added to the `Reader` class.
|
||||
This method returns an array containing the record and the prefix
|
||||
length for that record. GitHub #89.
|
||||
|
||||
1.4.1 (2019-01-04)
|
||||
------------------
|
||||
|
||||
* The `maxminddb` extension now returns a string when a `uint32`
|
||||
value is greater than `LONG_MAX`. Previously, the value would
|
||||
overflow. This generally only affects 32-bit machines. Reported
|
||||
by Remi Collet. GitHub #79.
|
||||
* For `uint64` values, the `maxminddb` extension now returns an
|
||||
integer rather than a string when the value is less than or equal
|
||||
to `LONG_MAX`. This more closely matches the behavior of the pure
|
||||
PHP reader.
|
||||
|
||||
1.4.0 (2018-11-20)
|
||||
------------------
|
||||
|
||||
* The `maxminddb` extension now has the arginfo when using reflection.
|
||||
PR by Remi Collet. GitHub #75.
|
||||
* The `maxminddb` extension now provides `MINFO()` function that
|
||||
displays the extension version and the libmaxminddb version. PR by
|
||||
Remi Collet. GitHub #74.
|
||||
* The `maxminddb` `configure` script now uses `pkg-config` when
|
||||
available to get libmaxmindb build info. PR by Remi Collet.
|
||||
GitHub #73.
|
||||
* The pure PHP reader now correctly decodes integers on 32-bit platforms.
|
||||
Previously, large integers would overflow. Reported by Remi Collet.
|
||||
GitHub #77.
|
||||
* There are small performance improvements for the pure PHP reader.
|
||||
|
||||
1.3.0 (2018-02-21)
|
||||
------------------
|
||||
|
||||
* IMPORTANT: The `maxminddb` extension now obeys `open_basedir`. If
|
||||
`open_basedir` is set, you _must_ store the database within the
|
||||
specified directory. Placing the file outside of this directory
|
||||
will result in an exception. Please test your integration before
|
||||
upgrading the extension. This does not affect the pure PHP
|
||||
implementation, which has always had this restriction. Reported
|
||||
by Benoît Burnichon. GitHub #61.
|
||||
* A custom `autoload.php` file is provided for installations without
|
||||
Composer. GitHub #56.
|
||||
|
||||
1.2.0 (2017-10-27)
|
||||
------------------
|
||||
|
||||
* PHP 5.4 or greater is now required.
|
||||
* The `Reader` class for the `maxminddb` extension is no longer final.
|
||||
This was change to match the behavior of the pure PHP class.
|
||||
Reported and fixed by venyii. GitHub #52 & #54.
|
||||
|
||||
1.1.3 (2017-01-19)
|
||||
------------------
|
||||
|
||||
* Fix incorrect version in `ext/php_maxminddb.h`. GitHub #48.
|
||||
|
||||
1.1.2 (2016-11-22)
|
||||
------------------
|
||||
|
||||
* Searching for database metadata only occurs within the last 128KB
|
||||
(128 * 1024 bytes) of the file, speeding detection of corrupt
|
||||
datafiles. Reported by Eric Teubert. GitHub #42.
|
||||
* Suggest relevant extensions when installing with Composer. GitHub #37.
|
||||
|
||||
1.1.1 (2016-09-15)
|
||||
------------------
|
||||
|
||||
* Development files were added to the `.gitattributes` as `export-ignore` so
|
||||
that they are not part of the Composer release. Pull request by Michele
|
||||
Locati. GitHub #39.
|
||||
|
||||
1.1.0 (2016-01-04)
|
||||
------------------
|
||||
|
||||
* The MaxMind DB extension now supports PHP 7. Pull request by John Boehr.
|
||||
GitHub #27.
|
||||
|
||||
1.0.3 (2015-03-13)
|
||||
------------------
|
||||
|
||||
* All uses of `strlen` were removed. This should prevent issues in situations
|
||||
where the function is overloaded or otherwise broken.
|
||||
|
||||
1.0.2 (2015-01-19)
|
||||
------------------
|
||||
|
||||
* Previously the MaxMind DB extension would cause a segfault if the Reader
|
||||
object's destructor was called without first having called the constructor.
|
||||
(Reported by Matthias Saou & Juan Peri. GitHub #20.)
|
||||
|
||||
1.0.1 (2015-01-12)
|
||||
------------------
|
||||
|
||||
* In the last several releases, the version number in the extension was
|
||||
incorrect. This release is being done to correct it. No other code changes
|
||||
are included.
|
||||
|
||||
1.0.0 (2014-09-22)
|
||||
------------------
|
||||
|
||||
* First production release.
|
||||
* In the pure PHP reader, a string length test after `fread()` was replaced
|
||||
with the difference between the start pointer and the end pointer. This
|
||||
provided a 15% speed increase.
|
||||
|
||||
0.3.3 (2014-09-15)
|
||||
------------------
|
||||
|
||||
* Clarified behavior of 128-bit type in documentation.
|
||||
* Updated phpunit and fixed some test breakage from the newer version.
|
||||
|
||||
0.3.2 (2014-09-10)
|
||||
------------------
|
||||
|
||||
* Fixed invalid reference to global class RuntimeException from namespaced
|
||||
code. Fixed by Steven Don. GitHub issue #15.
|
||||
* Additional documentation of `Metadata` class as well as misc. documentation
|
||||
cleanup.
|
||||
|
||||
0.3.1 (2014-05-01)
|
||||
------------------
|
||||
|
||||
* The API now works when `mbstring.func_overload` is set.
|
||||
* BCMath is no longer required. If the decoder encounters a big integer,
|
||||
it will try to use GMP and then BCMath. If both of those fail, it will
|
||||
throw an exception. No databases released by MaxMind currently use big
|
||||
integers.
|
||||
* The API now officially supports HHVM when using the pure PHP reader.
|
||||
|
||||
0.3.0 (2014-02-19)
|
||||
------------------
|
||||
|
||||
* This API is now licensed under the Apache License, Version 2.0.
|
||||
* The code for the C extension was cleaned up, fixing several potential
|
||||
issues.
|
||||
|
||||
0.2.0 (2013-10-21)
|
||||
------------------
|
||||
|
||||
* Added optional C extension for using libmaxminddb in place of the pure PHP
|
||||
reader.
|
||||
* Significantly improved error handling in pure PHP reader.
|
||||
* Improved performance for IPv4 lookups in an IPv6 database.
|
||||
|
||||
0.1.0 (2013-07-16)
|
||||
------------------
|
||||
|
||||
* Initial release
|
||||
@@ -2,14 +2,18 @@
|
||||
|
||||
namespace MaxMind\Db;
|
||||
|
||||
use BadMethodCallException;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use MaxMind\Db\Reader\Decoder;
|
||||
use MaxMind\Db\Reader\InvalidDatabaseException;
|
||||
use MaxMind\Db\Reader\Metadata;
|
||||
use MaxMind\Db\Reader\Util;
|
||||
use UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* Instances of this class provide a reader for the MaxMind DB format. IP
|
||||
* addresses can be looked up using the <code>get</code> method.
|
||||
* addresses can be looked up using the get method.
|
||||
*/
|
||||
class Reader
|
||||
{
|
||||
@@ -31,7 +35,7 @@ class Reader
|
||||
* @param string $database
|
||||
* the MaxMind DB file to use
|
||||
*
|
||||
* @throws \InvalidArgumentException for invalid database path or unknown arguments
|
||||
* @throws InvalidArgumentException for invalid database path or unknown arguments
|
||||
* @throws \MaxMind\Db\Reader\InvalidDatabaseException
|
||||
* if the database is invalid or there is an error reading
|
||||
* from it
|
||||
@@ -39,25 +43,25 @@ class Reader
|
||||
public function __construct($database)
|
||||
{
|
||||
if (\func_num_args() !== 1) {
|
||||
throw new \InvalidArgumentException(
|
||||
throw new InvalidArgumentException(
|
||||
'The constructor takes exactly one argument.'
|
||||
);
|
||||
}
|
||||
|
||||
if (!is_readable($database)) {
|
||||
throw new \InvalidArgumentException(
|
||||
throw new InvalidArgumentException(
|
||||
"The file \"$database\" does not exist or is not readable."
|
||||
);
|
||||
}
|
||||
$this->fileHandle = @fopen($database, 'rb');
|
||||
if ($this->fileHandle === false) {
|
||||
throw new \InvalidArgumentException(
|
||||
throw new InvalidArgumentException(
|
||||
"Error opening \"$database\"."
|
||||
);
|
||||
}
|
||||
$this->fileSize = @filesize($database);
|
||||
if ($this->fileSize === false) {
|
||||
throw new \UnexpectedValueException(
|
||||
throw new UnexpectedValueException(
|
||||
"Error determining the size of \"$database\"."
|
||||
);
|
||||
}
|
||||
@@ -70,115 +74,133 @@ class Reader
|
||||
$this->fileHandle,
|
||||
$this->metadata->searchTreeSize + self::$DATA_SECTION_SEPARATOR_SIZE
|
||||
);
|
||||
$this->ipV4Start = $this->ipV4StartNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the <code>address</code> in the MaxMind DB.
|
||||
* Retrieves the record for the IP address.
|
||||
*
|
||||
* @param string $ipAddress
|
||||
* the IP address to look up
|
||||
*
|
||||
* @throws \BadMethodCallException if this method is called on a closed database
|
||||
* @throws \InvalidArgumentException if something other than a single IP address is passed to the method
|
||||
* @throws BadMethodCallException if this method is called on a closed database
|
||||
* @throws InvalidArgumentException if something other than a single IP address is passed to the method
|
||||
* @throws InvalidDatabaseException
|
||||
* if the database is invalid or there is an error reading
|
||||
* from it
|
||||
* if the database is invalid or there is an error reading
|
||||
* from it
|
||||
*
|
||||
* @return array the record for the IP address
|
||||
* @return mixed the record for the IP address
|
||||
*/
|
||||
public function get($ipAddress)
|
||||
{
|
||||
if (\func_num_args() !== 1) {
|
||||
throw new \InvalidArgumentException(
|
||||
throw new InvalidArgumentException(
|
||||
'Method takes exactly one argument.'
|
||||
);
|
||||
}
|
||||
list($record) = $this->getWithPrefixLen($ipAddress);
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the record for the IP address and its associated network prefix length.
|
||||
*
|
||||
* @param string $ipAddress
|
||||
* the IP address to look up
|
||||
*
|
||||
* @throws BadMethodCallException if this method is called on a closed database
|
||||
* @throws InvalidArgumentException if something other than a single IP address is passed to the method
|
||||
* @throws InvalidDatabaseException
|
||||
* if the database is invalid or there is an error reading
|
||||
* from it
|
||||
*
|
||||
* @return array an array where the first element is the record and the
|
||||
* second the network prefix length for the record
|
||||
*/
|
||||
public function getWithPrefixLen($ipAddress)
|
||||
{
|
||||
if (\func_num_args() !== 1) {
|
||||
throw new InvalidArgumentException(
|
||||
'Method takes exactly one argument.'
|
||||
);
|
||||
}
|
||||
|
||||
if (!\is_resource($this->fileHandle)) {
|
||||
throw new \BadMethodCallException(
|
||||
throw new BadMethodCallException(
|
||||
'Attempt to read from a closed MaxMind DB.'
|
||||
);
|
||||
}
|
||||
|
||||
if (!filter_var($ipAddress, FILTER_VALIDATE_IP)) {
|
||||
throw new \InvalidArgumentException(
|
||||
throw new InvalidArgumentException(
|
||||
"The value \"$ipAddress\" is not a valid IP address."
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->metadata->ipVersion === 4 && strrpos($ipAddress, ':')) {
|
||||
throw new \InvalidArgumentException(
|
||||
"Error looking up $ipAddress. You attempted to look up an"
|
||||
. ' IPv6 address in an IPv4-only database.'
|
||||
);
|
||||
}
|
||||
$pointer = $this->findAddressInTree($ipAddress);
|
||||
list($pointer, $prefixLen) = $this->findAddressInTree($ipAddress);
|
||||
if ($pointer === 0) {
|
||||
return null;
|
||||
return [null, $prefixLen];
|
||||
}
|
||||
|
||||
return $this->resolveDataPointer($pointer);
|
||||
return [$this->resolveDataPointer($pointer), $prefixLen];
|
||||
}
|
||||
|
||||
private function findAddressInTree($ipAddress)
|
||||
{
|
||||
// XXX - could simplify. Done as a byte array to ease porting
|
||||
$rawAddress = array_merge(unpack('C*', inet_pton($ipAddress)));
|
||||
$rawAddress = unpack('C*', inet_pton($ipAddress));
|
||||
|
||||
$bitCount = \count($rawAddress) * 8;
|
||||
|
||||
// The first node of the tree is always node 0, at the beginning of the
|
||||
// value
|
||||
$node = $this->startNode($bitCount);
|
||||
$node = 0;
|
||||
|
||||
for ($i = 0; $i < $bitCount; ++$i) {
|
||||
if ($node >= $this->metadata->nodeCount) {
|
||||
break;
|
||||
$metadata = $this->metadata;
|
||||
|
||||
// Check if we are looking up an IPv4 address in an IPv6 tree. If this
|
||||
// is the case, we can skip over the first 96 nodes.
|
||||
if ($metadata->ipVersion === 6) {
|
||||
if ($bitCount === 32) {
|
||||
$node = $this->ipV4Start;
|
||||
}
|
||||
$tempBit = 0xFF & $rawAddress[$i >> 3];
|
||||
} elseif ($metadata->ipVersion === 4 && $bitCount === 128) {
|
||||
throw new InvalidArgumentException(
|
||||
"Error looking up $ipAddress. You attempted to look up an"
|
||||
. ' IPv6 address in an IPv4-only database.'
|
||||
);
|
||||
}
|
||||
|
||||
$nodeCount = $metadata->nodeCount;
|
||||
|
||||
for ($i = 0; $i < $bitCount && $node < $nodeCount; ++$i) {
|
||||
$tempBit = 0xFF & $rawAddress[($i >> 3) + 1];
|
||||
$bit = 1 & ($tempBit >> 7 - ($i % 8));
|
||||
|
||||
$node = $this->readNode($node, $bit);
|
||||
}
|
||||
if ($node === $this->metadata->nodeCount) {
|
||||
if ($node === $nodeCount) {
|
||||
// Record is empty
|
||||
return 0;
|
||||
} elseif ($node > $this->metadata->nodeCount) {
|
||||
return [0, $i];
|
||||
} elseif ($node > $nodeCount) {
|
||||
// Record is a data pointer
|
||||
return $node;
|
||||
return [$node, $i];
|
||||
}
|
||||
throw new InvalidDatabaseException('Something bad happened');
|
||||
}
|
||||
|
||||
private function startNode($length)
|
||||
{
|
||||
// Check if we are looking up an IPv4 address in an IPv6 tree. If this
|
||||
// is the case, we can skip over the first 96 nodes.
|
||||
if ($this->metadata->ipVersion === 6 && $length === 32) {
|
||||
return $this->ipV4StartNode();
|
||||
}
|
||||
// The first node of the tree is always node 0, at the beginning of the
|
||||
// value
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function ipV4StartNode()
|
||||
{
|
||||
// This is a defensive check. There is no reason to call this when you
|
||||
// have an IPv4 tree.
|
||||
// If we have an IPv4 database, the start node is the first node
|
||||
if ($this->metadata->ipVersion === 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($this->ipV4Start) {
|
||||
return $this->ipV4Start;
|
||||
}
|
||||
$node = 0;
|
||||
|
||||
for ($i = 0; $i < 96 && $node < $this->metadata->nodeCount; ++$i) {
|
||||
$node = $this->readNode($node, 0);
|
||||
}
|
||||
$this->ipV4Start = $node;
|
||||
|
||||
return $node;
|
||||
}
|
||||
@@ -187,7 +209,6 @@ class Reader
|
||||
{
|
||||
$baseOffset = $nodeNumber * $this->metadata->nodeByteSize;
|
||||
|
||||
// XXX - probably could condense this.
|
||||
switch ($this->metadata->recordSize) {
|
||||
case 24:
|
||||
$bytes = Util::read($this->fileHandle, $baseOffset + $index * 3, 3);
|
||||
@@ -195,15 +216,13 @@ class Reader
|
||||
|
||||
return $node;
|
||||
case 28:
|
||||
$middleByte = Util::read($this->fileHandle, $baseOffset + 3, 1);
|
||||
list(, $middle) = unpack('C', $middleByte);
|
||||
$bytes = Util::read($this->fileHandle, $baseOffset + 3 * $index, 4);
|
||||
if ($index === 0) {
|
||||
$middle = (0xF0 & $middle) >> 4;
|
||||
$middle = (0xF0 & \ord($bytes[3])) >> 4;
|
||||
} else {
|
||||
$middle = 0x0F & $middle;
|
||||
$middle = 0x0F & \ord($bytes[0]);
|
||||
}
|
||||
$bytes = Util::read($this->fileHandle, $baseOffset + $index * 4, 3);
|
||||
list(, $node) = unpack('N', \chr($middle) . $bytes);
|
||||
list(, $node) = unpack('N', \chr($middle) . substr($bytes, $index, 3));
|
||||
|
||||
return $node;
|
||||
case 32:
|
||||
@@ -223,7 +242,7 @@ class Reader
|
||||
{
|
||||
$resolved = $pointer - $this->metadata->nodeCount
|
||||
+ $this->metadata->searchTreeSize;
|
||||
if ($resolved > $this->fileSize) {
|
||||
if ($resolved >= $this->fileSize) {
|
||||
throw new InvalidDatabaseException(
|
||||
"The MaxMind DB file's search tree is corrupt"
|
||||
);
|
||||
@@ -246,19 +265,18 @@ class Reader
|
||||
$fileSize = $fstat['size'];
|
||||
$marker = self::$METADATA_START_MARKER;
|
||||
$markerLength = self::$METADATA_START_MARKER_LENGTH;
|
||||
$metadataMaxLengthExcludingMarker
|
||||
= min(self::$METADATA_MAX_SIZE, $fileSize) - $markerLength;
|
||||
|
||||
for ($i = 0; $i <= $metadataMaxLengthExcludingMarker; ++$i) {
|
||||
for ($j = 0; $j < $markerLength; ++$j) {
|
||||
fseek($handle, $fileSize - $i - $j - 1);
|
||||
$matchBit = fgetc($handle);
|
||||
if ($matchBit !== $marker[$markerLength - $j - 1]) {
|
||||
continue 2;
|
||||
}
|
||||
$minStart = $fileSize - min(self::$METADATA_MAX_SIZE, $fileSize);
|
||||
|
||||
for ($offset = $fileSize - $markerLength; $offset >= $minStart; --$offset) {
|
||||
if (fseek($handle, $offset) !== 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
return $fileSize - $i;
|
||||
$value = fread($handle, $markerLength);
|
||||
if ($value === $marker) {
|
||||
return $offset + $markerLength;
|
||||
}
|
||||
}
|
||||
throw new InvalidDatabaseException(
|
||||
"Error opening database file ($filename). " .
|
||||
@@ -267,15 +285,15 @@ class Reader
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \InvalidArgumentException if arguments are passed to the method
|
||||
* @throws \BadMethodCallException if the database has been closed
|
||||
* @throws InvalidArgumentException if arguments are passed to the method
|
||||
* @throws BadMethodCallException if the database has been closed
|
||||
*
|
||||
* @return Metadata object for the database
|
||||
*/
|
||||
public function metadata()
|
||||
{
|
||||
if (\func_num_args()) {
|
||||
throw new \InvalidArgumentException(
|
||||
throw new InvalidArgumentException(
|
||||
'Method takes no arguments.'
|
||||
);
|
||||
}
|
||||
@@ -283,7 +301,7 @@ class Reader
|
||||
// Not technically required, but this makes it consistent with
|
||||
// C extension and it allows us to change our implementation later.
|
||||
if (!\is_resource($this->fileHandle)) {
|
||||
throw new \BadMethodCallException(
|
||||
throw new BadMethodCallException(
|
||||
'Attempt to read from a closed MaxMind DB.'
|
||||
);
|
||||
}
|
||||
@@ -294,13 +312,13 @@ class Reader
|
||||
/**
|
||||
* Closes the MaxMind DB and returns resources to the system.
|
||||
*
|
||||
* @throws \Exception
|
||||
* if an I/O error occurs
|
||||
* @throws Exception
|
||||
* if an I/O error occurs
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
if (!\is_resource($this->fileHandle)) {
|
||||
throw new \BadMethodCallException(
|
||||
throw new BadMethodCallException(
|
||||
'Attempt to close a closed MaxMind DB.'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,13 @@
|
||||
namespace MaxMind\Db\Reader;
|
||||
|
||||
// @codingStandardsIgnoreLine
|
||||
// We subtract 1 from the log to protect against precision loss.
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* We subtract 1 from the log to protect against precision loss.
|
||||
*/
|
||||
\define(__NAMESPACE__ . '\_MM_MAX_INT_BYTES', (log(PHP_INT_MAX, 2) - 1) / 8);
|
||||
|
||||
class Decoder
|
||||
@@ -15,21 +21,37 @@ class Decoder
|
||||
private $pointerTestHack;
|
||||
private $switchByteOrder;
|
||||
|
||||
/** @ignore */
|
||||
const _EXTENDED = 0;
|
||||
/** @ignore */
|
||||
const _POINTER = 1;
|
||||
/** @ignore */
|
||||
const _UTF8_STRING = 2;
|
||||
/** @ignore */
|
||||
const _DOUBLE = 3;
|
||||
/** @ignore */
|
||||
const _BYTES = 4;
|
||||
/** @ignore */
|
||||
const _UINT16 = 5;
|
||||
/** @ignore */
|
||||
const _UINT32 = 6;
|
||||
/** @ignore */
|
||||
const _MAP = 7;
|
||||
/** @ignore */
|
||||
const _INT32 = 8;
|
||||
/** @ignore */
|
||||
const _UINT64 = 9;
|
||||
/** @ignore */
|
||||
const _UINT128 = 10;
|
||||
/** @ignore */
|
||||
const _ARRAY = 11;
|
||||
/** @ignore */
|
||||
const _CONTAINER = 12;
|
||||
/** @ignore */
|
||||
const _END_MARKER = 13;
|
||||
/** @ignore */
|
||||
const _BOOLEAN = 14;
|
||||
/** @ignore */
|
||||
const _FLOAT = 15;
|
||||
|
||||
public function __construct(
|
||||
@@ -48,10 +70,7 @@ class Decoder
|
||||
|
||||
public function decode($offset)
|
||||
{
|
||||
list(, $ctrlByte) = unpack(
|
||||
'C',
|
||||
Util::read($this->fileStream, $offset, 1)
|
||||
);
|
||||
$ctrlByte = \ord(Util::read($this->fileStream, $offset, 1));
|
||||
++$offset;
|
||||
|
||||
$type = $ctrlByte >> 5;
|
||||
@@ -73,10 +92,7 @@ class Decoder
|
||||
}
|
||||
|
||||
if ($type === self::_EXTENDED) {
|
||||
list(, $nextByte) = unpack(
|
||||
'C',
|
||||
Util::read($this->fileStream, $offset, 1)
|
||||
);
|
||||
$nextByte = \ord(Util::read($this->fileStream, $offset, 1));
|
||||
|
||||
$type = $nextByte + 7;
|
||||
|
||||
@@ -233,17 +249,17 @@ class Decoder
|
||||
|
||||
switch ($pointerSize) {
|
||||
case 1:
|
||||
$packed = (pack('C', $ctrlByte & 0x7)) . $buffer;
|
||||
$packed = \chr($ctrlByte & 0x7) . $buffer;
|
||||
list(, $pointer) = unpack('n', $packed);
|
||||
$pointer += $this->pointerBase;
|
||||
break;
|
||||
case 2:
|
||||
$packed = "\x00" . (pack('C', $ctrlByte & 0x7)) . $buffer;
|
||||
$packed = "\x00" . \chr($ctrlByte & 0x7) . $buffer;
|
||||
list(, $pointer) = unpack('N', $packed);
|
||||
$pointer += $this->pointerBase + 2048;
|
||||
break;
|
||||
case 3:
|
||||
$packed = (pack('C', $ctrlByte & 0x7)) . $buffer;
|
||||
$packed = \chr($ctrlByte & 0x7) . $buffer;
|
||||
|
||||
// It is safe to use 'N' here, even on 32 bit machines as the
|
||||
// first bit is 0.
|
||||
@@ -264,7 +280,7 @@ class Decoder
|
||||
} elseif (\extension_loaded('bcmath')) {
|
||||
$pointer = bcadd($pointerOffset, $this->pointerBase);
|
||||
} else {
|
||||
throw new \RuntimeException(
|
||||
throw new RuntimeException(
|
||||
'The gmp or bcmath extension must be installed to read this database.'
|
||||
);
|
||||
}
|
||||
@@ -292,7 +308,7 @@ class Decoder
|
||||
} elseif (\extension_loaded('bcmath')) {
|
||||
$integer = bcadd(bcmul($integer, 256), $part);
|
||||
} else {
|
||||
throw new \RuntimeException(
|
||||
throw new RuntimeException(
|
||||
'The gmp or bcmath extension must be installed to read this database.'
|
||||
);
|
||||
}
|
||||
@@ -319,8 +335,7 @@ class Decoder
|
||||
$size = 285 + $adjust;
|
||||
} elseif ($size > 30) {
|
||||
list(, $adjust) = unpack('N', "\x00" . $bytes);
|
||||
$size = ($adjust & (0x0FFFFFFF >> (32 - (8 * $bytesToRead))))
|
||||
+ 65821;
|
||||
$size = $adjust + 65821;
|
||||
}
|
||||
|
||||
return [$size, $offset + $bytesToRead];
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
|
||||
namespace MaxMind\Db\Reader;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* This class should be thrown when unexpected data is found in the database.
|
||||
*/
|
||||
class InvalidDatabaseException extends \Exception
|
||||
class InvalidDatabaseException extends Exception
|
||||
{
|
||||
}
|
||||
|
||||
@@ -5,31 +5,50 @@ namespace MaxMind\Db\Reader;
|
||||
/**
|
||||
* This class provides the metadata for the MaxMind DB file.
|
||||
*
|
||||
* @property int nodeCount This is an unsigned 32-bit integer indicating
|
||||
* the number of nodes in the search tree.
|
||||
* @property int recordSize This is an unsigned 16-bit integer. It
|
||||
* indicates the number of bits in a record in the search tree. Note that each
|
||||
* node consists of two records.
|
||||
* @property int ipVersion This is an unsigned 16-bit integer which is
|
||||
* always 4 or 6. It indicates whether the database contains IPv4 or IPv6
|
||||
* address data.
|
||||
* @property string databaseType This is a string that indicates the structure
|
||||
* of each data record associated with an IP address. The actual definition of
|
||||
* these structures is left up to the database creator.
|
||||
* @property array languages An array of strings, each of which is a language
|
||||
* code. A given record may contain data items that have been localized to
|
||||
* some or all of these languages. This may be undefined.
|
||||
* @property int binaryFormatMajorVersion This is an unsigned 16-bit
|
||||
* integer indicating the major version number for the database's binary
|
||||
* format.
|
||||
* @property int binaryFormatMinorVersion This is an unsigned 16-bit
|
||||
* integer indicating the minor version number for the database's binary format.
|
||||
* @property int buildEpoch This is an unsigned 64-bit integer that
|
||||
* contains the database build timestamp as a Unix epoch value.
|
||||
* @property array description This key will always point to a map
|
||||
* (associative array). The keys of that map will be language codes, and the
|
||||
* values will be a description in that language as a UTF-8 string. May be
|
||||
* undefined for some databases.
|
||||
* @property int $nodeCount This is an unsigned 32-bit
|
||||
* integer indicating the number of
|
||||
* nodes in the search tree.
|
||||
* @property int $recordSize This is an unsigned 16-bit
|
||||
* integer. It indicates the number
|
||||
* of bits in a record in the search
|
||||
* tree. Note that each node
|
||||
* consists of two records.
|
||||
* @property int $ipVersion This is an unsigned 16-bit
|
||||
* integer which is always 4 or 6.
|
||||
* It indicates whether the database
|
||||
* contains IPv4 or IPv6 address
|
||||
* data.
|
||||
* @property string $databaseType This is a string that indicates
|
||||
* the structure of each data record
|
||||
* associated with an IP address.
|
||||
* The actual definition of these
|
||||
* structures is left up to the
|
||||
* database creator.
|
||||
* @property array $languages An array of strings, each of
|
||||
* which is a language code. A given
|
||||
* record may contain data items
|
||||
* that have been localized to some
|
||||
* or all of these languages. This
|
||||
* may be undefined.
|
||||
* @property int $binaryFormatMajorVersion This is an unsigned 16-bit
|
||||
* integer indicating the major
|
||||
* version number for the database's
|
||||
* binary format.
|
||||
* @property int $binaryFormatMinorVersion This is an unsigned 16-bit
|
||||
* integer indicating the minor
|
||||
* version number for the database's
|
||||
* binary format.
|
||||
* @property int $buildEpoch This is an unsigned 64-bit
|
||||
* integer that contains the
|
||||
* database build timestamp as a
|
||||
* Unix epoch value.
|
||||
* @property array $description This key will always point to a
|
||||
* map (associative array). The keys
|
||||
* of that map will be language
|
||||
* codes, and the values will be a
|
||||
* description in that language as a
|
||||
* UTF-8 string. May be undefined
|
||||
* for some databases.
|
||||
*/
|
||||
class Metadata
|
||||
{
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,178 @@
|
||||
# MaxMind DB Reader PHP API #
|
||||
|
||||
## Description ##
|
||||
|
||||
This is the PHP API for reading MaxMind DB files. MaxMind DB is a binary file
|
||||
format that stores data indexed by IP address subnets (IPv4 or IPv6).
|
||||
|
||||
## Installation (Composer) ##
|
||||
|
||||
We recommend installing this package with [Composer](https://getcomposer.org/).
|
||||
|
||||
### Download Composer ###
|
||||
|
||||
To download Composer, run in the root directory of your project:
|
||||
|
||||
```bash
|
||||
curl -sS https://getcomposer.org/installer | php
|
||||
```
|
||||
|
||||
You should now have the file `composer.phar` in your project directory.
|
||||
|
||||
### Install Dependencies ###
|
||||
|
||||
Run in your project root:
|
||||
|
||||
```
|
||||
php composer.phar require maxmind-db/reader:~1.0
|
||||
```
|
||||
|
||||
You should now have the files `composer.json` and `composer.lock` as well as
|
||||
the directory `vendor` in your project directory. If you use a version control
|
||||
system, `composer.json` should be added to it.
|
||||
|
||||
### Require Autoloader ###
|
||||
|
||||
After installing the dependencies, you need to require the Composer autoloader
|
||||
from your code:
|
||||
|
||||
```php
|
||||
require 'vendor/autoload.php';
|
||||
```
|
||||
|
||||
## Installation (Standalone) ##
|
||||
|
||||
If you don't want to use Composer for some reason, a custom
|
||||
`autoload.php` is provided for you in the project root. To use the
|
||||
library, simply include that file,
|
||||
|
||||
```php
|
||||
require('/path/to/MaxMind-DB-Reader-php/autoload.php');
|
||||
```
|
||||
|
||||
and then instantiate the reader class normally:
|
||||
|
||||
```php
|
||||
use MaxMind\Db\Reader;
|
||||
$reader = new Reader('example.mmdb');
|
||||
```
|
||||
|
||||
## Installation (RPM)
|
||||
|
||||
RPMs are available in the [official Fedora repository](https://apps.fedoraproject.org/packages/php-maxminddb).
|
||||
|
||||
To install on Fedora, run:
|
||||
|
||||
```bash
|
||||
dnf install php-maxminddb
|
||||
```
|
||||
|
||||
To install on CentOS or RHEL 7, first [enable the EPEL repository](https://fedoraproject.org/wiki/EPEL)
|
||||
and then run:
|
||||
|
||||
```bash
|
||||
yum install php-maxminddb
|
||||
```
|
||||
|
||||
Please note that these packages are *not* maintained by MaxMind.
|
||||
|
||||
## Usage ##
|
||||
|
||||
## Example ##
|
||||
|
||||
```php
|
||||
<?php
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
use MaxMind\Db\Reader;
|
||||
|
||||
$ipAddress = '24.24.24.24';
|
||||
$databaseFile = 'GeoIP2-City.mmdb';
|
||||
|
||||
$reader = new Reader($databaseFile);
|
||||
|
||||
// get returns just the record for the IP address
|
||||
print_r($reader->get($ipAddress));
|
||||
|
||||
// getWithPrefixLen returns an array containing the record and the
|
||||
// associated prefix length for that record.
|
||||
print_r($reader->getWithPrefixLen($ipAddress));
|
||||
|
||||
$reader->close();
|
||||
```
|
||||
|
||||
## Optional PHP C Extension ##
|
||||
|
||||
MaxMind provides an optional C extension that is a drop-in replacement for
|
||||
`MaxMind\Db\Reader`. In order to use this extension, you must install the
|
||||
Reader API as described above and install the extension as described below. If
|
||||
you are using an autoloader, no changes to your code should be necessary.
|
||||
|
||||
### Installing Extension ###
|
||||
|
||||
First install [libmaxminddb](https://github.com/maxmind/libmaxminddb) as
|
||||
described in its [README.md
|
||||
file](https://github.com/maxmind/libmaxminddb/blob/master/README.md#installing-from-a-tarball).
|
||||
After successfully installing libmaxmindb, run the following commands from the
|
||||
top-level directory of this distribution:
|
||||
|
||||
```
|
||||
cd ext
|
||||
phpize
|
||||
./configure
|
||||
make
|
||||
make test
|
||||
sudo make install
|
||||
```
|
||||
|
||||
You then must load your extension. The recommend method is to add the
|
||||
following to your `php.ini` file:
|
||||
|
||||
```
|
||||
extension=maxminddb.so
|
||||
```
|
||||
|
||||
Note: You may need to install the PHP development package on your OS such as
|
||||
php5-dev for Debian-based systems or php-devel for RedHat/Fedora-based ones.
|
||||
|
||||
## 128-bit Integer Support ##
|
||||
|
||||
The MaxMind DB format includes 128-bit unsigned integer as a type. Although
|
||||
no MaxMind-distributed database currently makes use of this type, both the
|
||||
pure PHP reader and the C extension support this type. The pure PHP reader
|
||||
requires gmp or bcmath to read databases with 128-bit unsigned integers.
|
||||
|
||||
The integer is currently returned as a hexadecimal string (prefixed with "0x")
|
||||
by the C extension and a decimal string (no prefix) by the pure PHP reader.
|
||||
Any change to make the reader implementations always return either a
|
||||
hexadecimal or decimal representation of the integer will NOT be considered a
|
||||
breaking change.
|
||||
|
||||
## Support ##
|
||||
|
||||
Please report all issues with this code using the [GitHub issue tracker](https://github.com/maxmind/MaxMind-DB-Reader-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 5.6 or greater.
|
||||
|
||||
The GMP or BCMath extension may be required to read some databases
|
||||
using the pure PHP API.
|
||||
|
||||
## Contributing ##
|
||||
|
||||
Patches and pull requests are encouraged. All code should follow the PSR-1 and
|
||||
PSR-2 style guidelines. Please include unit tests whenever possible.
|
||||
|
||||
## Versioning ##
|
||||
|
||||
The MaxMind DB Reader PHP API uses [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## Copyright and License ##
|
||||
|
||||
This software is Copyright (c) 2014-2019 by MaxMind, Inc.
|
||||
|
||||
This is free software, licensed under the Apache License, Version 2.0.
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PSR-4 autoloader implementation for the MaxMind\DB namespace.
|
||||
* First we define the 'mmdb_autoload' function, and then we register
|
||||
* it with 'spl_autoload_register' so that PHP knows to use it.
|
||||
*
|
||||
* @param mixed $class
|
||||
*/
|
||||
|
||||
/**
|
||||
* Automatically include the file that defines <code>class</code>.
|
||||
*
|
||||
* @param string $class
|
||||
* the name of the class to load
|
||||
*/
|
||||
function mmdb_autoload($class)
|
||||
{
|
||||
/*
|
||||
* A project-specific mapping between the namespaces and where
|
||||
* they're located. By convention, we include the trailing
|
||||
* slashes. The one-element array here simply makes things easy
|
||||
* to extend in the future if (for example) the test classes
|
||||
* begin to use one another.
|
||||
*/
|
||||
$namespace_map = ['MaxMind\\Db\\' => __DIR__ . '/src/MaxMind/Db/'];
|
||||
|
||||
foreach ($namespace_map as $prefix => $dir) {
|
||||
/* First swap out the namespace prefix with a directory... */
|
||||
$path = str_replace($prefix, $dir, $class);
|
||||
|
||||
/* replace the namespace separator with a directory separator... */
|
||||
$path = str_replace('\\', '/', $path);
|
||||
|
||||
/* and finally, add the PHP file extension to the result. */
|
||||
$path = $path . '.php';
|
||||
|
||||
/* $path should now contain the path to a PHP file defining $class */
|
||||
if (file_exists($path)) {
|
||||
include $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spl_autoload_register('mmdb_autoload');
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "maxmind-db/reader",
|
||||
"description": "MaxMind DB Reader API",
|
||||
"keywords": ["database", "geoip", "geoip2", "geolocation", "maxmind"],
|
||||
"homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php",
|
||||
"type": "library",
|
||||
"license": "Apache-2.0",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Gregory J. Oschwald",
|
||||
"email": "[email protected]",
|
||||
"homepage": "https://www.maxmind.com/"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.6"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-bcmath": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
|
||||
"ext-gmp": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
|
||||
"ext-maxminddb": "A C-based database decoder that provides significantly faster lookups"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "2.*",
|
||||
"phpunit/phpunit": "5.*",
|
||||
"php-coveralls/php-coveralls": "^2.1",
|
||||
"phpunit/phpcov": "^3.0",
|
||||
"squizlabs/php_codesniffer": "3.*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MaxMind\\Db\\": "src/MaxMind/Db"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"MaxMind\\Db\\Test\\Reader\\": "tests/MaxMind/Db/Test/Reader"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,15 +16,15 @@ Installation
|
||||
------------
|
||||
|
||||
1) Download the latest versions of GeoIP2-php and MaxMind-DB-Reader-php
|
||||
wget https://github.com/maxmind/GeoIP2-php/archive/v2.9.0.zip
|
||||
wget https://github.com/maxmind/MaxMind-DB-Reader-php/archive/v1.4.1.zip
|
||||
wget https://github.com/maxmind/GeoIP2-php/archive/v2.10.0.zip
|
||||
wget https://github.com/maxmind/MaxMind-DB-Reader-php/archive/v1.5.1.zip
|
||||
|
||||
2) Unzip the archives
|
||||
unzip v2.9.0.zip
|
||||
unzip v1.4.1.zip
|
||||
unzip v2.10.0.zip
|
||||
unzip v1.5.1.zip
|
||||
|
||||
3) Move the source code directories into place
|
||||
mv GeoIP2-php-2.9.0/src/ /path/to/moodle/lib/maxmind/GeoIp2/
|
||||
mv MaxMind-DB-Reader-php-1.4.1/src/MaxMind/ /path/to/moodle/lib/maxmind/MaxMind/
|
||||
mv GeoIP2-php-2.10.0/src/ /path/to/moodle/lib/maxmind/GeoIp2/
|
||||
mv MaxMind-DB-Reader-php-1.5.1/src/MaxMind/ /path/to/moodle/lib/maxmind/MaxMind/
|
||||
|
||||
4) Run unit tests on iplookup/tests/geoip_test.php with PHPUNIT_LONGTEST defined.
|
||||
|
||||
@@ -241,13 +241,13 @@
|
||||
<location>maxmind/GeoIp2</location>
|
||||
<name>GeoIP2 PHP API</name>
|
||||
<license>Apache 2.0</license>
|
||||
<version>2.9.0</version>
|
||||
<version>2.10.0</version>
|
||||
</library>
|
||||
<library>
|
||||
<location>maxmind/MaxMind</location>
|
||||
<name>MaxMind DB Reader API</name>
|
||||
<license>Apache 2.0</license>
|
||||
<version>1.4.1</version>
|
||||
<version>1.5.1</version>
|
||||
</library>
|
||||
<library>
|
||||
<location>ltiprovider</location>
|
||||
|
||||
Reference in New Issue
Block a user