diff --git a/lib/maxmind/GeoIp2/Database/Reader.php b/lib/maxmind/GeoIp2/Database/Reader.php
index 813654753a1..0c370b730fe 100644
--- a/lib/maxmind/GeoIp2/Database/Reader.php
+++ b/lib/maxmind/GeoIp2/Database/Reader.php
@@ -1,5 +1,7 @@
dbReader = new DbReader($filename);
$this->dbType = $this->dbReader->metadata()->databaseType;
@@ -65,10 +67,8 @@ class Reader implements ProviderInterface
* not in the database
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
- *
- * @return \GeoIp2\Model\City
*/
- public function city($ipAddress)
+ public function city(string $ipAddress): \GeoIp2\Model\City
{
return $this->modelFor('City', 'City', $ipAddress);
}
@@ -82,10 +82,8 @@ class Reader implements ProviderInterface
* not in the database
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
- *
- * @return \GeoIp2\Model\Country
*/
- public function country($ipAddress)
+ public function country(string $ipAddress): \GeoIp2\Model\Country
{
return $this->modelFor('Country', 'Country', $ipAddress);
}
@@ -99,10 +97,8 @@ class Reader implements ProviderInterface
* not in the database
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
- *
- * @return \GeoIp2\Model\AnonymousIp
*/
- public function anonymousIp($ipAddress)
+ public function anonymousIp(string $ipAddress): \GeoIp2\Model\AnonymousIp
{
return $this->flatModelFor(
'AnonymousIp',
@@ -120,10 +116,8 @@ class Reader implements ProviderInterface
* not in the database
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
- *
- * @return \GeoIp2\Model\Asn
*/
- public function asn($ipAddress)
+ public function asn(string $ipAddress): \GeoIp2\Model\Asn
{
return $this->flatModelFor(
'Asn',
@@ -141,10 +135,8 @@ class Reader implements ProviderInterface
* not in the database
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
- *
- * @return \GeoIp2\Model\ConnectionType
*/
- public function connectionType($ipAddress)
+ public function connectionType(string $ipAddress): \GeoIp2\Model\ConnectionType
{
return $this->flatModelFor(
'ConnectionType',
@@ -162,10 +154,8 @@ class Reader implements ProviderInterface
* not in the database
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
- *
- * @return \GeoIp2\Model\Domain
*/
- public function domain($ipAddress)
+ public function domain(string $ipAddress): \GeoIp2\Model\Domain
{
return $this->flatModelFor(
'Domain',
@@ -183,10 +173,8 @@ class Reader implements ProviderInterface
* not in the database
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
- *
- * @return \GeoIp2\Model\Enterprise
*/
- public function enterprise($ipAddress)
+ public function enterprise(string $ipAddress): \GeoIp2\Model\Enterprise
{
return $this->modelFor('Enterprise', 'Enterprise', $ipAddress);
}
@@ -200,10 +188,8 @@ class Reader implements ProviderInterface
* not in the database
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
- *
- * @return \GeoIp2\Model\Isp
*/
- public function isp($ipAddress)
+ public function isp(string $ipAddress): \GeoIp2\Model\Isp
{
return $this->flatModelFor(
'Isp',
@@ -212,7 +198,7 @@ class Reader implements ProviderInterface
);
}
- private function modelFor($class, $type, $ipAddress)
+ private function modelFor(string $class, string $type, string $ipAddress)
{
list($record, $prefixLen) = $this->getRecord($class, $type, $ipAddress);
@@ -224,7 +210,7 @@ class Reader implements ProviderInterface
return new $class($record, $this->locales);
}
- private function flatModelFor($class, $type, $ipAddress)
+ private function flatModelFor(string $class, string $type, string $ipAddress)
{
list($record, $prefixLen) = $this->getRecord($class, $type, $ipAddress);
@@ -235,7 +221,7 @@ class Reader implements ProviderInterface
return new $class($record);
}
- private function getRecord($class, $type, $ipAddress)
+ private function getRecord(string $class, string $type, string $ipAddress): array
{
if (strpos($this->dbType, $type) === false) {
$method = lcfirst($class);
@@ -272,7 +258,7 @@ class Reader implements ProviderInterface
*
* @return \MaxMind\Db\Reader\Metadata object for the database
*/
- public function metadata()
+ public function metadata(): \MaxMind\Db\Reader\Metadata
{
return $this->dbReader->metadata();
}
@@ -280,7 +266,7 @@ class Reader implements ProviderInterface
/**
* Closes the GeoIP2 database and returns the resources to the system.
*/
- public function close()
+ public function close(): void
{
$this->dbReader->close();
}
diff --git a/lib/maxmind/GeoIp2/Exception/AddressNotFoundException.php b/lib/maxmind/GeoIp2/Exception/AddressNotFoundException.php
index d5483388b10..628fb0672a1 100644
--- a/lib/maxmind/GeoIp2/Exception/AddressNotFoundException.php
+++ b/lib/maxmind/GeoIp2/Exception/AddressNotFoundException.php
@@ -1,5 +1,7 @@
uri = $uri;
diff --git a/lib/maxmind/GeoIp2/Exception/InvalidRequestException.php b/lib/maxmind/GeoIp2/Exception/InvalidRequestException.php
index 6464bcbb1eb..e469f56ccd7 100644
--- a/lib/maxmind/GeoIp2/Exception/InvalidRequestException.php
+++ b/lib/maxmind/GeoIp2/Exception/InvalidRequestException.php
@@ -1,5 +1,7 @@
error = $error;
diff --git a/lib/maxmind/GeoIp2/Exception/OutOfQueriesException.php b/lib/maxmind/GeoIp2/Exception/OutOfQueriesException.php
index 87a6ade4121..9734c8ce403 100644
--- a/lib/maxmind/GeoIp2/Exception/OutOfQueriesException.php
+++ b/lib/maxmind/GeoIp2/Exception/OutOfQueriesException.php
@@ -1,5 +1,7 @@
raw = $raw;
}
/**
* @ignore
- *
- * @param mixed $field
*/
- protected function get($field)
+ protected function get(string $field)
{
if (isset($this->raw[$field])) {
return $this->raw[$field];
@@ -38,10 +36,8 @@ abstract class AbstractModel implements \JsonSerializable
/**
* @ignore
- *
- * @param mixed $attr
*/
- public function __get($attr)
+ public function __get(string $attr)
{
if ($attr !== 'instance' && property_exists($this, $attr)) {
return $this->$attr;
@@ -52,15 +48,13 @@ abstract class AbstractModel implements \JsonSerializable
/**
* @ignore
- *
- * @param mixed $attr
*/
- public function __isset($attr)
+ public function __isset(string $attr): bool
{
return $attr !== 'instance' && isset($this->$attr);
}
- public function jsonSerialize()
+ public function jsonSerialize(): array
{
return $this->raw;
}
diff --git a/lib/maxmind/GeoIp2/Model/AnonymousIp.php b/lib/maxmind/GeoIp2/Model/AnonymousIp.php
index a8f946ee865..bdfbc258a33 100644
--- a/lib/maxmind/GeoIp2/Model/AnonymousIp.php
+++ b/lib/maxmind/GeoIp2/Model/AnonymousIp.php
@@ -1,5 +1,7 @@
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;
diff --git a/lib/maxmind/GeoIp2/Model/Asn.php b/lib/maxmind/GeoIp2/Model/Asn.php
index 8e7c802eeba..38a0f750c64 100644
--- a/lib/maxmind/GeoIp2/Model/Asn.php
+++ b/lib/maxmind/GeoIp2/Model/Asn.php
@@ -1,5 +1,7 @@
autonomousSystemNumber = $this->get('autonomous_system_number');
diff --git a/lib/maxmind/GeoIp2/Model/City.php b/lib/maxmind/GeoIp2/Model/City.php
index 3e78c4f14c4..1840e778f21 100644
--- a/lib/maxmind/GeoIp2/Model/City.php
+++ b/lib/maxmind/GeoIp2/Model/City.php
@@ -1,5 +1,7 @@
createSubdivisions($raw, $locales);
}
- private function createSubdivisions($raw, $locales)
+ private function createSubdivisions(array $raw, array $locales): void
{
if (!isset($raw['subdivisions'])) {
return;
@@ -79,10 +78,8 @@ class City extends Country
/**
* @ignore
- *
- * @param mixed $attr
*/
- public function __get($attr)
+ public function __get(string $attr)
{
if ($attr === 'mostSpecificSubdivision') {
return $this->$attr();
@@ -93,10 +90,8 @@ class City extends Country
/**
* @ignore
- *
- * @param mixed $attr
*/
- public function __isset($attr)
+ public function __isset(string $attr): bool
{
if ($attr === 'mostSpecificSubdivision') {
// We always return a mostSpecificSubdivision, even if it is the
@@ -107,7 +102,7 @@ class City extends Country
return parent::__isset($attr);
}
- private function mostSpecificSubdivision()
+ private function mostSpecificSubdivision(): \GeoIp2\Record\Subdivision
{
return empty($this->subdivisions) ?
new \GeoIp2\Record\Subdivision([], $this->locales) :
diff --git a/lib/maxmind/GeoIp2/Model/ConnectionType.php b/lib/maxmind/GeoIp2/Model/ConnectionType.php
index 8091e26ce50..5f7747fe527 100644
--- a/lib/maxmind/GeoIp2/Model/ConnectionType.php
+++ b/lib/maxmind/GeoIp2/Model/ConnectionType.php
@@ -1,5 +1,7 @@
autonomousSystemNumber = $this->get('autonomous_system_number');
diff --git a/lib/maxmind/GeoIp2/ProviderInterface.php b/lib/maxmind/GeoIp2/ProviderInterface.php
index 44851b07e12..4e28eff1bd0 100644
--- a/lib/maxmind/GeoIp2/ProviderInterface.php
+++ b/lib/maxmind/GeoIp2/ProviderInterface.php
@@ -1,5 +1,7 @@
locales = $locales;
parent::__construct($record);
@@ -20,10 +19,8 @@ abstract class AbstractPlaceRecord extends AbstractRecord
/**
* @ignore
- *
- * @param mixed $attr
*/
- public function __get($attr)
+ public function __get(string $attr)
{
if ($attr === 'name') {
return $this->name();
@@ -34,26 +31,24 @@ abstract class AbstractPlaceRecord extends AbstractRecord
/**
* @ignore
- *
- * @param mixed $attr
*/
- public function __isset($attr)
+ public function __isset(string $attr): bool
{
if ($attr === 'name') {
- return $this->firstSetNameLocale() === null ? false : true;
+ return $this->firstSetNameLocale() !== null;
}
return parent::__isset($attr);
}
- private function name()
+ private function name(): ?string
{
$locale = $this->firstSetNameLocale();
return $locale === null ? null : $this->names[$locale];
}
- private function firstSetNameLocale()
+ private function firstSetNameLocale(): ?string
{
foreach ($this->locales as $locale) {
if (isset($this->names[$locale])) {
diff --git a/lib/maxmind/GeoIp2/Record/AbstractRecord.php b/lib/maxmind/GeoIp2/Record/AbstractRecord.php
index dad2fd3f376..e2abcf16c4c 100644
--- a/lib/maxmind/GeoIp2/Record/AbstractRecord.php
+++ b/lib/maxmind/GeoIp2/Record/AbstractRecord.php
@@ -1,5 +1,7 @@
record = isset($record) ? $record : [];
}
/**
* @ignore
- *
- * @param mixed $attr
*/
- public function __get($attr)
+ public function __get(string $attr)
{
// XXX - kind of ugly but greatly reduces boilerplate code
$key = $this->attributeToKey($attr);
@@ -38,23 +36,23 @@ abstract class AbstractRecord implements \JsonSerializable
throw new \RuntimeException("Unknown attribute: $attr");
}
- public function __isset($attr)
+ public function __isset(string $attr): bool
{
return $this->validAttribute($attr) &&
isset($this->record[$this->attributeToKey($attr)]);
}
- private function attributeToKey($attr)
+ private function attributeToKey(string $attr): string
{
return strtolower(preg_replace('/([A-Z])/', '_\1', $attr));
}
- private function validAttribute($attr)
+ private function validAttribute(string $attr): bool
{
return \in_array($attr, $this->validAttributes, true);
}
- public function jsonSerialize()
+ public function jsonSerialize(): ?array
{
return $this->record;
}
diff --git a/lib/maxmind/GeoIp2/Record/City.php b/lib/maxmind/GeoIp2/Record/City.php
index 7f495ad7cc0..ac62bea6e2d 100644
--- a/lib/maxmind/GeoIp2/Record/City.php
+++ b/lib/maxmind/GeoIp2/Record/City.php
@@ -1,5 +1,7 @@
locales = $locales;
@@ -87,7 +89,7 @@ class Client implements ProviderInterface
$this->client = new WsClient($accountId, $licenseKey, $options);
}
- private function userAgent()
+ private function userAgent(): string
{
return 'GeoIP2-API/' . self::VERSION;
}
@@ -115,10 +117,8 @@ class Client implements ProviderInterface
* @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.
- *
- * @return \GeoIp2\Model\City
*/
- public function city($ipAddress = 'me')
+ public function city(string $ipAddress = 'me'): \GeoIp2\Model\City
{
return $this->responseFor('city', 'City', $ipAddress);
}
@@ -146,10 +146,8 @@ class Client implements ProviderInterface
* @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.
- *
- * @return \GeoIp2\Model\Country
*/
- public function country($ipAddress = 'me')
+ public function country(string $ipAddress = 'me'): \GeoIp2\Model\Country
{
return $this->responseFor('country', 'Country', $ipAddress);
}
@@ -177,15 +175,13 @@ class Client implements ProviderInterface
* @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.
- *
- * @return \GeoIp2\Model\Insights
*/
- public function insights($ipAddress = 'me')
+ public function insights(string $ipAddress = 'me'): \GeoIp2\Model\Insights
{
return $this->responseFor('insights', 'Insights', $ipAddress);
}
- private function responseFor($endpoint, $class, $ipAddress)
+ private function responseFor(string $endpoint, string $class, string $ipAddress)
{
$path = implode('/', [self::$basePath, $endpoint, $ipAddress]);
diff --git a/lib/maxmind/MaxMind/CHANGELOG.md b/lib/maxmind/MaxMind/CHANGELOG.md
index 9ed49bd416d..91e2aa46035 100644
--- a/lib/maxmind/MaxMind/CHANGELOG.md
+++ b/lib/maxmind/MaxMind/CHANGELOG.md
@@ -1,6 +1,45 @@
CHANGELOG
=========
+1.9.0 (2021-01-07)
+------------------
+
+* The `maxminddb` extension is now buildable on Windows. Pull request
+ by Jan Ehrhardt. GitHub #115.
+
+1.8.0 (2020-10-01)
+------------------
+
+* Fixes for PHP 8.0. Pull Request by Remi Collet. GitHub #108.
+
+1.7.0 (2020-08-07)
+------------------
+
+* IMPORTANT: PHP 7.2 or greater is now required.
+* The extension no longer depends on the pure PHP classes in
+ `maxmind-db/reader`. You can use it independently.
+* Type hints have been added to both the pure PHP implementation
+ and the extension.
+* The `metadata` method on the reader now returns a new copy of the
+ metadata object rather than the actual object used by the reader.
+* Work around PHP `is_readable()` bug. Reported by Ben Roberts. GitHub
+ #92.
+* This is the first release of the extension as a PECL package.
+ GitHub #34.
+
+1.6.0 (2019-12-19)
+------------------
+
+* 1.5.0 and 1.5.1 contained a possible memory corruptions when using
+ `getWithPrefixLen`. This has been fixed. Reported by proton-ab.
+ GitHub #96.
+* The `composer.json` file now conflicts with all versions of the
+ `maxminddb` C extension less than the Composer version. This is to
+ reduce the chance of having an older, conflicting version of the
+ extension installed. You will need to upgrade the extension before
+ running `composer update`. Pull request by BenoƮt Burnichon. GitHub
+ #97.
+
1.5.1 (2019-12-12)
------------------
diff --git a/lib/maxmind/MaxMind/Db/Reader.php b/lib/maxmind/MaxMind/Db/Reader.php
index 3d5a8291d95..ee444f8f18c 100644
--- a/lib/maxmind/MaxMind/Db/Reader.php
+++ b/lib/maxmind/MaxMind/Db/Reader.php
@@ -1,7 +1,10 @@
fileHandle = @fopen($database, 'rb');
- if ($this->fileHandle === false) {
- throw new InvalidArgumentException(
- "Error opening \"$database\"."
- );
- }
- $this->fileSize = @filesize($database);
- if ($this->fileSize === false) {
+ $this->fileHandle = $fileHandle;
+
+ $fileSize = @filesize($database);
+ if ($fileSize === false) {
throw new UnexpectedValueException(
"Error determining the size of \"$database\"."
);
}
+ $this->fileSize = $fileSize;
$start = $this->findMetadataStart($database);
$metadataDecoder = new Decoder($this->fileHandle, $start);
- list($metadataArray) = $metadataDecoder->decode($start);
+ [$metadataArray] = $metadataDecoder->decode($start);
$this->metadata = new Metadata($metadataArray);
$this->decoder = new Decoder(
$this->fileHandle,
@@ -91,14 +119,14 @@ class Reader
*
* @return mixed the record for the IP address
*/
- public function get($ipAddress)
+ public function get(string $ipAddress)
{
if (\func_num_args() !== 1) {
- throw new InvalidArgumentException(
- 'Method takes exactly one argument.'
+ throw new ArgumentCountError(
+ sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
);
}
- list($record) = $this->getWithPrefixLen($ipAddress);
+ [$record] = $this->getWithPrefixLen($ipAddress);
return $record;
}
@@ -118,11 +146,11 @@ class Reader
* @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)
+ public function getWithPrefixLen(string $ipAddress): array
{
if (\func_num_args() !== 1) {
- throw new InvalidArgumentException(
- 'Method takes exactly one argument.'
+ throw new ArgumentCountError(
+ sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
);
}
@@ -132,13 +160,7 @@ class Reader
);
}
- if (!filter_var($ipAddress, FILTER_VALIDATE_IP)) {
- throw new InvalidArgumentException(
- "The value \"$ipAddress\" is not a valid IP address."
- );
- }
-
- list($pointer, $prefixLen) = $this->findAddressInTree($ipAddress);
+ [$pointer, $prefixLen] = $this->findAddressInTree($ipAddress);
if ($pointer === 0) {
return [null, $prefixLen];
}
@@ -146,9 +168,16 @@ class Reader
return [$this->resolveDataPointer($pointer), $prefixLen];
}
- private function findAddressInTree($ipAddress)
+ private function findAddressInTree(string $ipAddress): array
{
- $rawAddress = unpack('C*', inet_pton($ipAddress));
+ $packedAddr = @inet_pton($ipAddress);
+ if ($packedAddr === false) {
+ throw new InvalidArgumentException(
+ "The value \"$ipAddress\" is not a valid IP address."
+ );
+ }
+
+ $rawAddress = unpack('C*', $packedAddr);
$bitCount = \count($rawAddress) * 8;
@@ -186,10 +215,12 @@ class Reader
// Record is a data pointer
return [$node, $i];
}
- throw new InvalidDatabaseException('Something bad happened');
+ throw new InvalidDatabaseException(
+ 'Invalid or corrupt database. Maximum search depth reached without finding a leaf node'
+ );
}
- private function ipV4StartNode()
+ private function ipV4StartNode(): int
{
// If we have an IPv4 database, the start node is the first node
if ($this->metadata->ipVersion === 4) {
@@ -205,14 +236,14 @@ class Reader
return $node;
}
- private function readNode($nodeNumber, $index)
+ private function readNode(int $nodeNumber, int $index): int
{
$baseOffset = $nodeNumber * $this->metadata->nodeByteSize;
switch ($this->metadata->recordSize) {
case 24:
$bytes = Util::read($this->fileHandle, $baseOffset + $index * 3, 3);
- list(, $node) = unpack('N', "\x00" . $bytes);
+ [, $node] = unpack('N', "\x00" . $bytes);
return $node;
case 28:
@@ -222,12 +253,12 @@ class Reader
} else {
$middle = 0x0F & \ord($bytes[0]);
}
- list(, $node) = unpack('N', \chr($middle) . substr($bytes, $index, 3));
+ [, $node] = unpack('N', \chr($middle) . substr($bytes, $index, 3));
return $node;
case 32:
$bytes = Util::read($this->fileHandle, $baseOffset + $index * 4, 4);
- list(, $node) = unpack('N', $bytes);
+ [, $node] = unpack('N', $bytes);
return $node;
default:
@@ -238,7 +269,10 @@ class Reader
}
}
- private function resolveDataPointer($pointer)
+ /**
+ * @return mixed
+ */
+ private function resolveDataPointer(int $pointer)
{
$resolved = $pointer - $this->metadata->nodeCount
+ $this->metadata->searchTreeSize;
@@ -248,7 +282,7 @@ class Reader
);
}
- list($data) = $this->decoder->decode($resolved);
+ [$data] = $this->decoder->decode($resolved);
return $data;
}
@@ -258,7 +292,7 @@ class Reader
* are much faster algorithms (e.g., Boyer-Moore) for this if speed is ever
* an issue, but I suspect it won't be.
*/
- private function findMetadataStart($filename)
+ private function findMetadataStart(string $filename): int
{
$handle = $this->fileHandle;
$fstat = fstat($handle);
@@ -290,11 +324,11 @@ class Reader
*
* @return Metadata object for the database
*/
- public function metadata()
+ public function metadata(): Metadata
{
if (\func_num_args()) {
- throw new InvalidArgumentException(
- 'Method takes no arguments.'
+ throw new ArgumentCountError(
+ sprintf('%s() expects exactly 0 parameters, %d given', __METHOD__, \func_num_args())
);
}
@@ -306,7 +340,7 @@ class Reader
);
}
- return $this->metadata;
+ return clone $this->metadata;
}
/**
@@ -315,8 +349,14 @@ class Reader
* @throws Exception
* if an I/O error occurs
*/
- public function close()
+ public function close(): void
{
+ if (\func_num_args()) {
+ throw new ArgumentCountError(
+ sprintf('%s() expects exactly 0 parameters, %d given', __METHOD__, \func_num_args())
+ );
+ }
+
if (!\is_resource($this->fileHandle)) {
throw new BadMethodCallException(
'Attempt to close a closed MaxMind DB.'
diff --git a/lib/maxmind/MaxMind/Db/Reader/Decoder.php b/lib/maxmind/MaxMind/Db/Reader/Decoder.php
index 132dae82c22..9816befa66e 100644
--- a/lib/maxmind/MaxMind/Db/Reader/Decoder.php
+++ b/lib/maxmind/MaxMind/Db/Reader/Decoder.php
@@ -1,5 +1,7 @@
fileStream = $fileStream;
$this->pointerBase = $pointerBase;
@@ -68,7 +73,7 @@ class Decoder
$this->switchByteOrder = $this->isPlatformLittleEndian();
}
- public function decode($offset)
+ public function decode(int $offset): array
{
$ctrlByte = \ord(Util::read($this->fileStream, $offset, 1));
++$offset;
@@ -79,14 +84,14 @@ class Decoder
// use the size to determine the length of the pointer and then follow
// it.
if ($type === self::_POINTER) {
- list($pointer, $offset) = $this->decodePointer($ctrlByte, $offset);
+ [$pointer, $offset] = $this->decodePointer($ctrlByte, $offset);
// for unit testing
if ($this->pointerTestHack) {
return [$pointer];
}
- list($result) = $this->decode($pointer);
+ [$result] = $this->decode($pointer);
return [$result, $offset];
}
@@ -108,12 +113,12 @@ class Decoder
++$offset;
}
- list($size, $offset) = $this->sizeFromCtrlByte($ctrlByte, $offset);
+ [$size, $offset] = $this->sizeFromCtrlByte($ctrlByte, $offset);
return $this->decodeByType($type, $offset, $size);
}
- private function decodeByType($type, $offset, $size)
+ private function decodeByType(int $type, int $offset, int $size): array
{
switch ($type) {
case self::_MAP:
@@ -152,7 +157,7 @@ class Decoder
}
}
- private function verifySize($expected, $actual)
+ private function verifySize(int $expected, int $actual): void
{
if ($expected !== $actual) {
throw new InvalidDatabaseException(
@@ -161,50 +166,42 @@ class Decoder
}
}
- private function decodeArray($size, $offset)
+ private function decodeArray(int $size, int $offset): array
{
$array = [];
for ($i = 0; $i < $size; ++$i) {
- list($value, $offset) = $this->decode($offset);
- array_push($array, $value);
+ [$value, $offset] = $this->decode($offset);
+ $array[] = $value;
}
return [$array, $offset];
}
- private function decodeBoolean($size)
+ private function decodeBoolean(int $size): bool
{
- return $size === 0 ? false : true;
+ return $size !== 0;
}
- private function decodeDouble($bits)
+ private function decodeDouble(string $bytes): float
{
// This assumes IEEE 754 doubles, but most (all?) modern platforms
// use them.
- //
- // We are not using the "E" format as that was only added in
- // 7.0.15 and 7.1.1. As such, we must switch byte order on
- // little endian machines.
- list(, $double) = unpack('d', $this->maybeSwitchByteOrder($bits));
+ [, $double] = unpack('E', $bytes);
return $double;
}
- private function decodeFloat($bits)
+ private function decodeFloat(string $bytes): float
{
// This assumes IEEE 754 floats, but most (all?) modern platforms
// use them.
- //
- // We are not using the "G" format as that was only added in
- // 7.0.15 and 7.1.1. As such, we must switch byte order on
- // little endian machines.
- list(, $float) = unpack('f', $this->maybeSwitchByteOrder($bits));
+ [, $float] = unpack('G', $bytes);
return $float;
}
- private function decodeInt32($bytes, $size)
+ private function decodeInt32(string $bytes, int $size): int
{
switch ($size) {
case 0:
@@ -222,25 +219,25 @@ class Decoder
);
}
- list(, $int) = unpack('l', $this->maybeSwitchByteOrder($bytes));
+ [, $int] = unpack('l', $this->maybeSwitchByteOrder($bytes));
return $int;
}
- private function decodeMap($size, $offset)
+ private function decodeMap(int $size, int $offset): array
{
$map = [];
for ($i = 0; $i < $size; ++$i) {
- list($key, $offset) = $this->decode($offset);
- list($value, $offset) = $this->decode($offset);
+ [$key, $offset] = $this->decode($offset);
+ [$value, $offset] = $this->decode($offset);
$map[$key] = $value;
}
return [$map, $offset];
}
- private function decodePointer($ctrlByte, $offset)
+ private function decodePointer(int $ctrlByte, int $offset): array
{
$pointerSize = (($ctrlByte >> 3) & 0x3) + 1;
@@ -250,12 +247,12 @@ class Decoder
switch ($pointerSize) {
case 1:
$packed = \chr($ctrlByte & 0x7) . $buffer;
- list(, $pointer) = unpack('n', $packed);
+ [, $pointer] = unpack('n', $packed);
$pointer += $this->pointerBase;
break;
case 2:
$packed = "\x00" . \chr($ctrlByte & 0x7) . $buffer;
- list(, $pointer) = unpack('N', $packed);
+ [, $pointer] = unpack('N', $packed);
$pointer += $this->pointerBase + 2048;
break;
case 3:
@@ -263,7 +260,7 @@ class Decoder
// It is safe to use 'N' here, even on 32 bit machines as the
// first bit is 0.
- list(, $pointer) = unpack('N', $packed);
+ [, $pointer] = unpack('N', $packed);
$pointer += $this->pointerBase + 526336;
break;
case 4:
@@ -278,18 +275,23 @@ class Decoder
} elseif (\extension_loaded('gmp')) {
$pointer = gmp_strval(gmp_add($pointerOffset, $this->pointerBase));
} elseif (\extension_loaded('bcmath')) {
- $pointer = bcadd($pointerOffset, $this->pointerBase);
+ $pointer = bcadd($pointerOffset, (string) $this->pointerBase);
} else {
throw new RuntimeException(
'The gmp or bcmath extension must be installed to read this database.'
);
}
+ break;
+ default:
+ throw new InvalidDatabaseException(
+ 'Unexpected pointer size ' . $pointerSize
+ );
}
return [$pointer, $offset];
}
- private function decodeUint($bytes, $byteLength)
+ private function decodeUint(string $bytes, int $byteLength)
{
if ($byteLength === 0) {
return 0;
@@ -304,9 +306,9 @@ class Decoder
if ($byteLength <= _MM_MAX_INT_BYTES) {
$integer = ($integer << 8) + $part;
} elseif (\extension_loaded('gmp')) {
- $integer = gmp_strval(gmp_add(gmp_mul($integer, 256), $part));
+ $integer = gmp_strval(gmp_add(gmp_mul((string) $integer, '256'), $part));
} elseif (\extension_loaded('bcmath')) {
- $integer = bcadd(bcmul($integer, 256), $part);
+ $integer = bcadd(bcmul((string) $integer, '256'), (string) $part);
} else {
throw new RuntimeException(
'The gmp or bcmath extension must be installed to read this database.'
@@ -317,7 +319,7 @@ class Decoder
return $integer;
}
- private function sizeFromCtrlByte($ctrlByte, $offset)
+ private function sizeFromCtrlByte(int $ctrlByte, int $offset): array
{
$size = $ctrlByte & 0x1f;
@@ -331,22 +333,22 @@ class Decoder
if ($size === 29) {
$size = 29 + \ord($bytes);
} elseif ($size === 30) {
- list(, $adjust) = unpack('n', $bytes);
+ [, $adjust] = unpack('n', $bytes);
$size = 285 + $adjust;
- } elseif ($size > 30) {
- list(, $adjust) = unpack('N', "\x00" . $bytes);
+ } else {
+ [, $adjust] = unpack('N', "\x00" . $bytes);
$size = $adjust + 65821;
}
return [$size, $offset + $bytesToRead];
}
- private function maybeSwitchByteOrder($bytes)
+ private function maybeSwitchByteOrder(string $bytes): string
{
return $this->switchByteOrder ? strrev($bytes) : $bytes;
}
- private function isPlatformLittleEndian()
+ private function isPlatformLittleEndian(): bool
{
$testint = 0x00FF;
$packed = pack('S', $testint);
diff --git a/lib/maxmind/MaxMind/Db/Reader/InvalidDatabaseException.php b/lib/maxmind/MaxMind/Db/Reader/InvalidDatabaseException.php
index 478a22c5563..53231070329 100644
--- a/lib/maxmind/MaxMind/Db/Reader/InvalidDatabaseException.php
+++ b/lib/maxmind/MaxMind/Db/Reader/InvalidDatabaseException.php
@@ -1,5 +1,7 @@
binaryFormatMajorVersion =
$metadata['binary_format_major_version'];
$this->binaryFormatMinorVersion =
@@ -80,9 +109,4 @@ class Metadata
$this->nodeByteSize = $this->recordSize / 4;
$this->searchTreeSize = $this->nodeCount * $this->nodeByteSize;
}
-
- public function __get($var)
- {
- return $this->$var;
- }
}
diff --git a/lib/maxmind/MaxMind/Db/Reader/Util.php b/lib/maxmind/MaxMind/Db/Reader/Util.php
index 87ebbf133f3..15e6bc4d4d6 100644
--- a/lib/maxmind/MaxMind/Db/Reader/Util.php
+++ b/lib/maxmind/MaxMind/Db/Reader/Util.php
@@ -1,10 +1,15 @@
=5.6"
+ "php": ">=7.2"
},
"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"
},
+ "conflict": {
+ "ext-maxminddb": "<1.9.0,>=2.0.0"
+ },
"require-dev": {
- "friendsofphp/php-cs-fixer": "2.*",
- "phpunit/phpunit": "5.*",
+ "friendsofphp/php-cs-fixer": "*",
+ "phpunit/phpunit": ">=8.0.0,<10.0.0",
"php-coveralls/php-coveralls": "^2.1",
- "phpunit/phpcov": "^3.0",
+ "phpunit/phpcov": ">=6.0.0",
"squizlabs/php_codesniffer": "3.*"
},
"autoload": {
diff --git a/lib/maxmind/readme_moodle.txt b/lib/maxmind/readme_moodle.txt
index ad9b9039da2..ac76edcb850 100644
--- a/lib/maxmind/readme_moodle.txt
+++ b/lib/maxmind/readme_moodle.txt
@@ -16,15 +16,24 @@ Installation
------------
1) Download the latest versions of GeoIP2-php and MaxMind-DB-Reader-php
-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
+wget https://github.com/maxmind/GeoIP2-php/archive/vX.Y.Z.zip
+wget https://github.com/maxmind/MaxMind-DB-Reader-php/archive/vX.Y.Z.zip
2) Unzip the archives
-unzip v2.10.0.zip
-unzip v1.5.1.zip
+unzip vX.Y.Z.zip
+unzip vX.Y.Z.zip
3) Move the source code directories into place
-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/
+mv GeoIP2-php-X.Y.Z/src/ /path/to/moodle/lib/maxmind/GeoIp2/
+mv MaxMind-DB-Reader-php-X.Y.Z/src/MaxMind/ /path/to/moodle/lib/maxmind/MaxMind/
-4) Run unit tests on iplookup/tests/geoip_test.php.
+4) Update other MaxMind related files:
+mv MaxMind-DB-Reader-php-X.Y.Z/LICENSE /path/to/moodle/lib/maxmind/MaxMind/
+mv MaxMind-DB-Reader-php-X.Y.Z/CHANGELOG.md /path/to/moodle/lib/maxmind/MaxMind/
+mv MaxMind-DB-Reader-php-X.Y.Z/README.md /path/to/moodle/lib/maxmind/MaxMind/
+mv MaxMind-DB-Reader-php-X.Y.Z/composer.json /path/to/moodle/lib/maxmind/MaxMind/
+mv MaxMind-DB-Reader-php-X.Y.Z/autoload.php /path/to/moodle/lib/maxmind/MaxMind/
+
+5) Run unit tests on iplookup/tests/geoip_test.php.
+
+6) Update maxmind/GeoIp2 and maxmind/MaxMin versions in lib/thirdpartylibs.xml
diff --git a/lib/thirdpartylibs.xml b/lib/thirdpartylibs.xml
index 768a7af3d57..fa4dcc0f738 100644
--- a/lib/thirdpartylibs.xml
+++ b/lib/thirdpartylibs.xml
@@ -248,13 +248,13 @@
maxmind/GeoIp2
GeoIP2 PHP API
Apache 2.0
- 2.10.0
+ 2.11.0
maxmind/MaxMind
MaxMind DB Reader API
Apache 2.0
- 1.5.1
+ 1.9.0
ltiprovider