diff options
| author | Greg Roach <fisharebest@webtrees.net> | 2020-02-13 16:40:38 +0000 |
|---|---|---|
| committer | Greg Roach <fisharebest@webtrees.net> | 2020-02-17 15:16:43 +0000 |
| commit | 089dadac9f029a2c2e920aab5c38c35029818ae2 (patch) | |
| tree | 15e9e02ee6fb4ead8f1aa1e69643fae293d441f3 /vendor/mlocati | |
| parent | f376f6d21758a47a239124a2664a6bef0fbcc699 (diff) | |
| download | webtrees-089dadac9f029a2c2e920aab5c38c35029818ae2.tar.gz webtrees-089dadac9f029a2c2e920aab5c38c35029818ae2.tar.bz2 webtrees-089dadac9f029a2c2e920aab5c38c35029818ae2.zip | |
Check for bad robots
Diffstat (limited to 'vendor/mlocati')
| -rw-r--r-- | vendor/mlocati/ip-lib/LICENSE.txt | 20 | ||||
| -rw-r--r-- | vendor/mlocati/ip-lib/README.md | 311 | ||||
| -rw-r--r-- | vendor/mlocati/ip-lib/composer.json | 48 | ||||
| -rw-r--r-- | vendor/mlocati/ip-lib/ip-lib.php | 13 | ||||
| -rw-r--r-- | vendor/mlocati/ip-lib/src/Address/AddressInterface.php | 96 | ||||
| -rw-r--r-- | vendor/mlocati/ip-lib/src/Address/AssignedRange.php | 138 | ||||
| -rw-r--r-- | vendor/mlocati/ip-lib/src/Address/IPv4.php | 352 | ||||
| -rw-r--r-- | vendor/mlocati/ip-lib/src/Address/IPv6.php | 526 | ||||
| -rw-r--r-- | vendor/mlocati/ip-lib/src/Address/Type.php | 42 | ||||
| -rw-r--r-- | vendor/mlocati/ip-lib/src/Factory.php | 156 | ||||
| -rw-r--r-- | vendor/mlocati/ip-lib/src/Range/Pattern.php | 331 | ||||
| -rw-r--r-- | vendor/mlocati/ip-lib/src/Range/RangeInterface.php | 96 | ||||
| -rw-r--r-- | vendor/mlocati/ip-lib/src/Range/Single.php | 190 | ||||
| -rw-r--r-- | vendor/mlocati/ip-lib/src/Range/Subnet.php | 334 | ||||
| -rw-r--r-- | vendor/mlocati/ip-lib/src/Range/Type.php | 141 |
15 files changed, 2794 insertions, 0 deletions
diff --git a/vendor/mlocati/ip-lib/LICENSE.txt b/vendor/mlocati/ip-lib/LICENSE.txt new file mode 100644 index 0000000000..5c21e47cf5 --- /dev/null +++ b/vendor/mlocati/ip-lib/LICENSE.txt @@ -0,0 +1,20 @@ +The MIT License (MIT) +Copyright (c) 2016 Michele Locati + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.
\ No newline at end of file diff --git a/vendor/mlocati/ip-lib/README.md b/vendor/mlocati/ip-lib/README.md new file mode 100644 index 0000000000..729cd4c255 --- /dev/null +++ b/vendor/mlocati/ip-lib/README.md @@ -0,0 +1,311 @@ +[](https://travis-ci.org/mlocati/ip-lib) +[](https://ci.appveyor.com/project/mlocati/ip-lib) +[](https://styleci.io/repos/54139375) +[](https://coveralls.io/github/mlocati/ip-lib?branch=master) +[](https://scrutinizer-ci.com/g/mlocati/ip-lib/?branch=master) + +# IPLib - Handle IPv4, IPv6 and IP ranges + + +## Introduction + +This library can handle IPv4, IPv6 addresses, as well as IP ranges, in CIDR formats (like `::1/128` or `127.0.0.1/32`) and in pattern format (like `::*:*` or `127.0.*.*`). + + +## Requirements + +The only requirement is PHP 5.3.3. +__No external dependencies__ and __no special PHP configuration__ are needed (yes, it will __always work__ even if PHP has not been built with IPv6 support!). + + +## Manual installation + +[Download](https://github.com/mlocati/ip-lib/releases) the latest version, unzip it and add these lines in our PHP files: + +```php +require_once 'path/to/iplib/ip-lib.php'; +``` + + +## Installation with Composer + +Simply run `composer require mlocati/ip-lib`, or add these lines to your `composer.json` file: + +```json +"require": { + "mlocati/ip-lib": "1.*" +} +``` + + +## Sample usage + + +### Parse an address + +To parse an IPv4 address: + +```php +$address = \IPLib\Address\IPv4::fromString('127.0.0.1'); +``` + +To parse an IPv6 address: + +```php +$address = \IPLib\Address\IPv6::fromString('::1'); +``` + +To parse an address in any format (IPv4 or IPv6): + +```php +$address = \IPLib\Factory::addressFromString('::1'); +$address = \IPLib\Factory::addressFromString('127.0.0.1'); +``` + + +### Get the next/previous addresses + +```php +$address = \IPLib\Factory::addressFromString('::1'); +echo (string) $address->getPreviousAddress(); +// prints :: +echo (string) $address->getNextAddress(); +// prints ::2 +``` + + +### Parse an IP address range + +To parse a subnet (CIDR) range: + +```php +$range = \IPLib\Range\Subnet::fromString('127.0.0.1/24'); +$range = \IPLib\Range\Subnet::fromString('::1/128'); +``` + +To parse a pattern (asterisk notation) range: + +```php +$range = \IPLib\Range\Pattern::fromString('127.0.0.*'); +$range = \IPLib\Range\Pattern::fromString('::*'); +``` + +To parse an andress as a range: + +```php +$range = \IPLib\Range\Single::fromString('127.0.0.1'); +$range = \IPLib\Range\Single::fromString('::1'); +``` + +To parse a range in any format: + +```php +$range = \IPLib\Factory::rangeFromString('127.0.0.*'); +$range = \IPLib\Factory::rangeFromString('::1/128'); +$range = \IPLib\Factory::rangeFromString('::'); +``` + + +### Retrive a range from its boundaries + +```php +$range = \IPLib\Factory::rangeFromBoundaries('192.168.0.1', '192.168.255.255'); +echo (string) $range; +// prints 192.168.0.0/16 +``` + + +### Retrive the boundaries of a range + +```php +$range = \IPLib\Factory::rangeFromString('127.0.0.*'); +echo (string) $range->getStartAddress(); +// prints 127.0.0.0 +echo (string) $range->getEndAddress(); +// prints 127.0.0.255 +``` + + +### Format addresses and ranges + +Both IP addresses and ranges have a `toString` method that you can use to retrieve a textual representation: + +```php +echo \IPLib\Factory::addressFromString('127.0.0.1')->toString(); +// prints 127.0.0.1 +echo \IPLib\Factory::addressFromString('127.000.000.001')->toString(); +// prints 127.0.0.1 +echo \IPLib\Factory::addressFromString('::1')->toString(); +// prints ::1 +echo \IPLib\Factory::addressFromString('0:0::1')->toString(); +// prints ::1 +echo \IPLib\Factory::rangeFromString('0:0::1/64')->toString(); +// prints ::1/64 +``` + +When working with IPv6, you may want the full (expanded) representation of the addresses. In this case, simply use a `true` parameter for the `toString` method: + +```php +echo \IPLib\Factory::addressFromString('::')->toString(true); +// prints 0000:0000:0000:0000:0000:0000:0000:0000 +echo \IPLib\Factory::addressFromString('::1')->toString(true); +// prints 0000:0000:0000:0000:0000:0000:0000:0001 +echo \IPLib\Factory::addressFromString('fff::')->toString(true); +// prints 0fff:0000:0000:0000:0000:0000:0000:0000 +echo \IPLib\Factory::addressFromString('::0:0')->toString(true); +// prints 0000:0000:0000:0000:0000:0000:0000:0000 +echo \IPLib\Factory::addressFromString('1:2:3:4:5:6:7:8')->toString(true); +// prints 0001:0002:0003:0004:0005:0006:0007:0008 +echo \IPLib\Factory::rangeFromString('0:0::1/64')->toString(); +// prints 0000:0000:0000:0000:0000:0000:0000:0001/64 +``` + + +### Check if an address is contained in a range + +All the range types offer a `contains` method, and all the IP address types offer a `matches` method: you can call them to check if an address is contained in a range: + +```php +$address = \IPLib\Factory::addressFromString('1:2:3:4:5:6:7:8'); +$range = \IPLib\Factory::rangeFromString('0:0::1/64'); + +$contained = $address->matches($range); +// that's equivalent to +$contained = $range->contains($address); +``` + +Please remark that if the address is IPv4 and the range is IPv6 (or vice-versa), the result will always be `false`. + + +### Check if a range contains another range + +All the range types offer a `containsRange` method: you can call them to check if an address range fully contains another range: + +```php +$range1 = \IPLib\Factory::rangeFromString('0:0::1/64'); +$range2 = \IPLib\Factory::rangeFromString('0:0::1/65'); +$contained = $range1->containsRange($range2); +``` + + +### Getting the type of an IP address + +If you want to know if an address is within a private network, or if it's a public IP, or whatever you want, you can use the `getRangeType` method: + +```php +$address = \IPLib\Factory::addressFromString('::'); + +$typeID = $address->getRangeType(); + +$typeName = \IPLib\Range\Type::getName(); +``` + +The most notable values of the range type ID are: +- `\IPLib\Range\Type::T_UNSPECIFIED` if the address is all zeros (`0.0.0.0` or `::`) +- `\IPLib\Range\Type::T_LOOPBACK` if the address is the localhost (usually `127.0.0.1` or `::1`) +- `\IPLib\Range\Type::T_PRIVATENETWORK` if the address is in the local network (for instance `192.168.0.1` or `fc00::1`) +- `\IPLib\Range\Type::T_PUBLIC` if the address is for public usage (for instance `104.25.25.33` or `2001:503:ba3e::2:30`) + + +### Getting the type of an IP address range + +If you want to know the type of an address range, you can use the `getRangeType` method: + +```php +$range = \IPLib\Factory::rangeFromString('2000:0::1/64'); +$type = $range->getRangeType(); +// $type is \IPLib\Range\Type::T_PUBLIC +echo \IPLib\Range\Type::getName($type); +// 'Public address' +``` + +Please remark that if a range spans across multiple range types, you'll get NULL as the range type: + +```php +$range = \IPLib\Factory::rangeFromString('::/127'); +$type = $range->getRangeType(); +// $type is null +echo \IPLib\Range\Type::getName($type); +// 'Unknown type' +``` + +### Converting IP ranges + +This library supports IPv4/IPv6 ranges in pattern format (eg. `192.168.*.*`) and in CIDR/subnet format (eg. `192.168.0.0/16`), and it offers a way to convert between the two formats: + +```php +// This will print ::*:*:*:* +echo \IPLib\Factory::rangeFromString('::/64')->asPattern()->toString(); + +// This will print 1:2::/96 +echo \IPLib\Factory::rangeFromString('1:2::*:*')->asSubnet()->toString(); + +// This will print 192.168.0.0/24 +echo \IPLib\Factory::rangeFromString('192.168.0.*')->asSubnet()->toString(); + +// This will print 10.*.*.* +echo \IPLib\Factory::rangeFromString('10.0.0.0/8')->asPattern()->toString(); +``` + +### Getting the subnet mask for IPv4 ranges + +You can use the `getSubnetMask()` to get the subnet mask for IPv4 ranges: + +```php +// This will print 255.255.255.0 +echo \IPLib\Factory::rangeFromString('192.168.0.*')->getSubnetMask()->toString(); + +// This will print 255.255.255.252 +echo \IPLib\Factory::rangeFromString('192.168.0.12/30')->getSubnetMask()->toString(); +``` + +### Using a database + +This package offers a great feature: you can store address ranges in a database table, and check if an address is contained in one of the saved ranges with a simple query. + +To save a range, you need to store the address type (for IPv4 it's `4`, for IPv6 it's `6`), as well as two values representing the start and the end of the range. +These methods are: +```php +$range->getAddressType(); +$range->getComparableStartString(); +$range->getComparableEndString(); +``` + +Let's assume that you saved the type in a field called `addressType`, and the range boundaries in two fields called `rangeFrom` and `rangeTo`. + +When you want to check if an address is within a stored range, simply use the `getComparableString` method of the address and check if it's between the fields `rangeFrom` and `rangeTo`, and check if the stored `addressType` is the same as the one of the address instance you want to check. + +Here's a sample code: + +```php +/* + * Let's assume that: + * - $pdo is a PDO instance + * - $range is a range object + * - $address is an address object + */ + +// Save the $range object +$insertQuery = $pdo->prepare(' + insert into ranges (addressType, rangeFrom, rangeTo) + values (:addressType, :rangeFrom, :rangeTo) +'); +$insertQuery->execute(array( + ':addressType' => $range->getAddressType(), + ':rangeFrom' => $range->getComparableStartString(), + ':rangeTo' => $range->getComparableEndString(), +)); + +// Retrieve the saved ranges where an address $address falls: +$searchQuery = $pdo->prepare(' + select * from ranges + where addressType = :addressType + and :address between rangeFrom and rangeTo +'); +$searchQuery->execute(array( + ':addressType' => $address->getAddressType(), + ':address' => $address->getComparableString(), +)); +$rows = $searchQuery->fetchAll(); +$searchQuery->closeCursor(); +``` diff --git a/vendor/mlocati/ip-lib/composer.json b/vendor/mlocati/ip-lib/composer.json new file mode 100644 index 0000000000..579147c760 --- /dev/null +++ b/vendor/mlocati/ip-lib/composer.json @@ -0,0 +1,48 @@ +{ + "name": "mlocati/ip-lib", + "type": "library", + "description": "Handle IPv4, IPv6 addresses and ranges", + "keywords": [ + "ip", + "ipv4", + "ipv6", + "range", + "network", + "networking", + "address", + "addresses", + "subnet", + "matching" + ], + "homepage": "https://github.com/mlocati/ip-lib", + "license": "MIT", + "authors": [ + { + "name": "Michele Locati", + "homepage": "https://github.com/mlocati", + "email": "mlocati@gmail.com", + "role": "Author" + } + ], + "autoload": { + "psr-4": { + "IPLib\\": "src/" + } + }, + "require": { + "php": ">=5.3.3" + }, + "autoload-dev": { + "psr-4": { + "IPLib\\Test\\": "test/tests/" + } + }, + "require-dev": { + "ext-pdo_sqlite": "*", + "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5", + "phpunit/dbunit": "^1.4 || ^2 || ^3 || ^4" + }, + "scripts": { + "test": "phpunit" + } +} diff --git a/vendor/mlocati/ip-lib/ip-lib.php b/vendor/mlocati/ip-lib/ip-lib.php new file mode 100644 index 0000000000..c1590ef067 --- /dev/null +++ b/vendor/mlocati/ip-lib/ip-lib.php @@ -0,0 +1,13 @@ +<?php + +spl_autoload_register( + function ($class) { + if (strpos($class, 'IPLib\\') !== 0) { + return; + } + $file = __DIR__.DIRECTORY_SEPARATOR.'src'.str_replace('\\', DIRECTORY_SEPARATOR, substr($class, strlen('IPLib'))).'.php'; + if (is_file($file)) { + require_once $file; + } + } +); diff --git a/vendor/mlocati/ip-lib/src/Address/AddressInterface.php b/vendor/mlocati/ip-lib/src/Address/AddressInterface.php new file mode 100644 index 0000000000..1a73f21f8e --- /dev/null +++ b/vendor/mlocati/ip-lib/src/Address/AddressInterface.php @@ -0,0 +1,96 @@ +<?php + +namespace IPLib\Address; + +use IPLib\Range\RangeInterface; + +/** + * Interface of all the IP address types. + */ +interface AddressInterface +{ + /** + * Get the string representation of this address. + * + * @param bool $long set to true to have a long/full representation, false otherwise + * + * @return string + * + * @example If $long is true, you'll get '0000:0000:0000:0000:0000:0000:0000:0001', '::1' otherwise. + */ + public function toString($long = false); + + /** + * Get the short string representation of this address. + * + * @return string + */ + public function __toString(); + + /** + * Get the byte list of the IP address. + * + * @return int[] + * + * @example For IPv4 you'll get array(127, 0, 0, 1), for IPv6 array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1) + */ + public function getBytes(); + + /** + * Get the type of the IP address. + * + * @return int One of the \IPLib\Address\Type::T_... constants + */ + public function getAddressType(); + + /** + * Get the default RFC reserved range type. + * + * @return int One of the \IPLib\Range\Type::T_... constants + */ + public static function getDefaultReservedRangeType(); + + /** + * Get the RFC reserved ranges (except the ones of type getDefaultReservedRangeType). + * + * @return \IPLib\Address\AssignedRange[] ranges are sorted + */ + public static function getReservedRanges(); + + /** + * Get the type of range of the IP address. + * + * @return int One of the \IPLib\Range\Type::T_... constants + */ + public function getRangeType(); + + /** + * Get a string representation of this address than can be used when comparing addresses and ranges. + * + * @return string + */ + public function getComparableString(); + + /** + * Check if this address is contained in an range. + * + * @param \IPLib\Range\RangeInterface $range + * + * @return bool + */ + public function matches(RangeInterface $range); + + /** + * Get the address right after this IP address (if available). + * + * @return \IPLib\Address\AddressInterface|null + */ + public function getNextAddress(); + + /** + * Get the address right before this IP address (if available). + * + * @return \IPLib\Address\AddressInterface|null + */ + public function getPreviousAddress(); +} diff --git a/vendor/mlocati/ip-lib/src/Address/AssignedRange.php b/vendor/mlocati/ip-lib/src/Address/AssignedRange.php new file mode 100644 index 0000000000..39dfec63d4 --- /dev/null +++ b/vendor/mlocati/ip-lib/src/Address/AssignedRange.php @@ -0,0 +1,138 @@ +<?php + +namespace IPLib\Address; + +use IPLib\Range\RangeInterface; + +/** + * Represents an IP address range with an assigned range type. + */ +class AssignedRange +{ + /** + * The range definition. + * + * @var \IPLib\Range\RangeInterface + */ + protected $range; + + /** + * The range type. + * + * @var int one of the \IPLib\Range\Type::T_ constants + */ + protected $type; + + /** + * The list of exceptions for this range type. + * + * @var \IPLib\Address\AssignedRange[] + */ + protected $exceptions; + + /** + * Initialize the instance. + * + * @param \IPLib\Range\RangeInterface $range the range definition + * @param int $type The range type (one of the \IPLib\Range\Type::T_ constants) + * @param \IPLib\Address\AssignedRange[] $exceptions the list of exceptions for this range type + */ + public function __construct(RangeInterface $range, $type, array $exceptions = array()) + { + $this->range = $range; + $this->type = $type; + $this->exceptions = $exceptions; + } + + /** + * Get the range definition. + * + * @return \IPLib\Range\RangeInterface + */ + public function getRange() + { + return $this->range; + } + + /** + * Get the range type. + * + * @return int one of the \IPLib\Range\Type::T_ constants + */ + public function getType() + { + return $this->type; + } + + /** + * Get the list of exceptions for this range type. + * + * @return \IPLib\Address\AssignedRange[] + */ + public function getExceptions() + { + return $this->exceptions; + } + + /** + * Get the assigned type for a specific address. + * + * @param \IPLib\Address\AddressInterface $address + * + * @return int|null return NULL of the address is outside this address; a \IPLib\Range\Type::T_ constant otherwise + */ + public function getAddressType(AddressInterface $address) + { + $result = null; + if ($this->range->contains($address)) { + foreach ($this->exceptions as $exception) { + $result = $exception->getAddressType($address); + if ($result !== null) { + break; + } + } + if ($result === null) { + $result = $this->type; + } + } + + return $result; + } + + /** + * Get the assigned type for a specific address range. + * + * @param \IPLib\Range\RangeInterface $range + * + * @return int|null|false return NULL of the range is fully outside this range; false if it's partly crosses this range (or it contains mixed types); a \IPLib\Range\Type::T_ constant otherwise + */ + public function getRangeType(RangeInterface $range) + { + $myStart = $this->range->getComparableStartString(); + $rangeEnd = $range->getComparableEndString(); + if ($myStart > $rangeEnd) { + $result = null; + } else { + $myEnd = $this->range->getComparableEndString(); + $rangeStart = $range->getComparableStartString(); + if ($myEnd < $rangeStart) { + $result = null; + } elseif ($rangeStart < $myStart || $rangeEnd > $myEnd) { + $result = false; + } else { + $result = null; + foreach ($this->exceptions as $exception) { + $result = $exception->getRangeType($range); + if ($result !== null) { + break; + } + } + if ($result === null) { + $result = $this->getType(); + } + } + } + + return $result; + } +} diff --git a/vendor/mlocati/ip-lib/src/Address/IPv4.php b/vendor/mlocati/ip-lib/src/Address/IPv4.php new file mode 100644 index 0000000000..272dc1d08f --- /dev/null +++ b/vendor/mlocati/ip-lib/src/Address/IPv4.php @@ -0,0 +1,352 @@ +<?php + +namespace IPLib\Address; + +use IPLib\Range\RangeInterface; +use IPLib\Range\Subnet; +use IPLib\Range\Type as RangeType; + +/** + * An IPv4 address. + */ +class IPv4 implements AddressInterface +{ + /** + * The string representation of the address. + * + * @var string + * + * @example '127.0.0.1' + */ + protected $address; + + /** + * The byte list of the IP address. + * + * @var int[]|null + */ + protected $bytes; + + /** + * The type of the range of this IP address. + * + * @var int|null + */ + protected $rangeType; + + /** + * A string representation of this address than can be used when comparing addresses and ranges. + * + * @var string + */ + protected $comparableString; + + /** + * An array containing RFC designated address ranges. + * + * @var array|null + */ + private static $reservedRanges = null; + + /** + * Initializes the instance. + * + * @param string $address + */ + protected function __construct($address) + { + $this->address = $address; + $this->bytes = null; + $this->rangeType = null; + $this->comparableString = null; + } + + /** + * Parse a string and returns an IPv4 instance if the string is valid, or null otherwise. + * + * @param string|mixed $address the address to parse + * @param bool $mayIncludePort set to false to avoid parsing addresses with ports + * + * @return static|null + */ + public static function fromString($address, $mayIncludePort = true) + { + $result = null; + if (is_string($address) && strpos($address, '.')) { + $rx = '([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})'; + if ($mayIncludePort) { + $rx .= '(?::\d+)?'; + } + $matches = null; + if (preg_match('/^'.$rx.'$/', $address, $matches)) { + $ok = true; + $nums = array(); + for ($i = 1; $ok && $i <= 4; ++$i) { + $ok = false; + $n = (int) $matches[$i]; + if ($n >= 0 && $n <= 255) { + $ok = true; + $nums[] = (string) $n; + } + } + if ($ok) { + $result = new static(implode('.', $nums)); + } + } + } + + return $result; + } + + /** + * Parse an array of bytes and returns an IPv4 instance if the array is valid, or null otherwise. + * + * @param int[]|array $bytes + * + * @return static|null + */ + public static function fromBytes(array $bytes) + { + $result = null; + if (count($bytes) === 4) { + $chunks = array_map( + function ($byte) { + return (is_int($byte) && $byte >= 0 && $byte <= 255) ? (string) $byte : false; + }, + $bytes + ); + if (in_array(false, $chunks, true) === false) { + $result = new static(implode('.', $chunks)); + } + } + + return $result; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::toString() + */ + public function toString($long = false) + { + if ($long) { + return $this->getComparableString(); + } + + return $this->address; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::__toString() + */ + public function __toString() + { + return $this->address; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::getBytes() + */ + public function getBytes() + { + if ($this->bytes === null) { + $this->bytes = array_map( + function ($chunk) { + return (int) $chunk; + }, + explode('.', $this->address) + ); + } + + return $this->bytes; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::getAddressType() + */ + public function getAddressType() + { + return Type::T_IPv4; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::getDefaultReservedRangeType() + */ + public static function getDefaultReservedRangeType() + { + return RangeType::T_PUBLIC; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::getReservedRanges() + */ + public static function getReservedRanges() + { + if (self::$reservedRanges === null) { + $reservedRanges = array(); + foreach (array( + // RFC 5735 + '0.0.0.0/8' => array(RangeType::T_THISNETWORK, array('0.0.0.0/32' => RangeType::T_UNSPECIFIED)), + // RFC 5735 + '10.0.0.0/8' => array(RangeType::T_PRIVATENETWORK), + // RFC 5735 + '127.0.0.0/8' => array(RangeType::T_LOOPBACK), + // RFC 5735 + '169.254.0.0/16' => array(RangeType::T_LINKLOCAL), + // RFC 5735 + '172.16.0.0/12' => array(RangeType::T_PRIVATENETWORK), + // RFC 5735 + '192.0.0.0/24' => array(RangeType::T_RESERVED), + // RFC 5735 + '192.0.2.0/24' => array(RangeType::T_RESERVED), + // RFC 5735 + '192.88.99.0/24' => array(RangeType::T_ANYCASTRELAY), + // RFC 5735 + '192.168.0.0/16' => array(RangeType::T_PRIVATENETWORK), + // RFC 5735 + '198.18.0.0/15' => array(RangeType::T_RESERVED), + // RFC 5735 + '198.51.100.0/24' => array(RangeType::T_RESERVED), + // RFC 5735 + '203.0.113.0/24' => array(RangeType::T_RESERVED), + // RFC 5735 + '224.0.0.0/4' => array(RangeType::T_MULTICAST), + // RFC 5735 + '240.0.0.0/4' => array(RangeType::T_RESERVED, array('255.255.255.255/32' => RangeType::T_LIMITEDBROADCAST)), + ) as $range => $data) { + $exceptions = array(); + if (isset($data[1])) { + foreach ($data[1] as $exceptionRange => $exceptionType) { + $exceptions[] = new AssignedRange(Subnet::fromString($exceptionRange), $exceptionType); + } + } + $reservedRanges[] = new AssignedRange(Subnet::fromString($range), $data[0], $exceptions); + } + self::$reservedRanges = $reservedRanges; + } + + return self::$reservedRanges; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::getRangeType() + */ + public function getRangeType() + { + if ($this->rangeType === null) { + $rangeType = null; + foreach (static::getReservedRanges() as $reservedRange) { + $rangeType = $reservedRange->getAddressType($this); + if ($rangeType !== null) { + break; + } + } + $this->rangeType = $rangeType === null ? static::getDefaultReservedRangeType() : $rangeType; + } + + return $this->rangeType; + } + + /** + * Create an IPv6 representation of this address. + * + * @return \IPLib\Address\IPv6 + */ + public function toIPv6() + { + $myBytes = $this->getBytes(); + + return IPv6::fromString('2002:'.sprintf('%02x', $myBytes[0]).sprintf('%02x', $myBytes[1]).':'.sprintf('%02x', $myBytes[2]).sprintf('%02x', $myBytes[3]).'::'); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::getComparableString() + */ + public function getComparableString() + { + if ($this->comparableString === null) { + $chunks = array(); + foreach ($this->getBytes() as $byte) { + $chunks[] = sprintf('%03d', $byte); + } + $this->comparableString = implode('.', $chunks); + } + + return $this->comparableString; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::matches() + */ + public function matches(RangeInterface $range) + { + return $range->contains($this); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::getNextAddress() + */ + public function getNextAddress() + { + $overflow = false; + $bytes = $this->getBytes(); + for ($i = count($bytes) - 1; $i >= 0; --$i) { + if ($bytes[$i] === 255) { + if ($i === 0) { + $overflow = true; + break; + } + $bytes[$i] = 0; + } else { + ++$bytes[$i]; + break; + } + } + + return $overflow ? null : static::fromBytes($bytes); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::getPreviousAddress() + */ + public function getPreviousAddress() + { + $overflow = false; + $bytes = $this->getBytes(); + for ($i = count($bytes) - 1; $i >= 0; --$i) { + if ($bytes[$i] === 0) { + if ($i === 0) { + $overflow = true; + break; + } + $bytes[$i] = 255; + } else { + --$bytes[$i]; + break; + } + } + + return $overflow ? null : static::fromBytes($bytes); + } +} diff --git a/vendor/mlocati/ip-lib/src/Address/IPv6.php b/vendor/mlocati/ip-lib/src/Address/IPv6.php new file mode 100644 index 0000000000..170af8bb50 --- /dev/null +++ b/vendor/mlocati/ip-lib/src/Address/IPv6.php @@ -0,0 +1,526 @@ +<?php + +namespace IPLib\Address; + +use IPLib\Range\RangeInterface; +use IPLib\Range\Subnet; +use IPLib\Range\Type as RangeType; + +/** + * An IPv6 address. + */ +class IPv6 implements AddressInterface +{ + /** + * The long string representation of the address. + * + * @var string + * + * @example '0000:0000:0000:0000:0000:0000:0000:0001' + */ + protected $longAddress; + + /** + * The long string representation of the address. + * + * @var string|null + * + * @example '::1' + */ + protected $shortAddress; + + /** + * The byte list of the IP address. + * + * @var int[]|null + */ + protected $bytes; + + /** + * The word list of the IP address. + * + * @var int[]|null + */ + protected $words; + + /** + * The type of the range of this IP address. + * + * @var int|null + */ + protected $rangeType; + + /** + * An array containing RFC designated address ranges. + * + * @var array|null + */ + private static $reservedRanges = null; + + /** + * Initializes the instance. + * + * @param string $longAddress + */ + public function __construct($longAddress) + { + $this->longAddress = $longAddress; + $this->shortAddress = null; + $this->bytes = null; + $this->words = null; + $this->rangeType = null; + } + + /** + * Parse a string and returns an IPv6 instance if the string is valid, or null otherwise. + * + * @param string|mixed $address the address to parse + * @param bool $mayIncludePort set to false to avoid parsing addresses with ports + * @param bool $mayIncludeZoneID set to false to avoid parsing addresses with zone IDs (see RFC 4007) + * + * @return static|null + */ + public static function fromString($address, $mayIncludePort = true, $mayIncludeZoneID = true) + { + $result = null; + if (is_string($address) && strpos($address, ':') !== false && strpos($address, ':::') === false) { + $matches = null; + if ($mayIncludePort && $address[0] === '[' && preg_match('/^\[(.+)\]:\d+$/', $address, $matches)) { + $address = $matches[1]; + } + if ($mayIncludeZoneID) { + $percentagePos = strpos($address, '%'); + if ($percentagePos > 0) { + $address = substr($address, 0, $percentagePos); + } + } + if (preg_match('/^((?:[0-9a-f]*:+)+)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/i', $address, $matches)) { + $address6 = static::fromString($matches[1].'0:0', false); + if ($address6 !== null) { + $address4 = IPv4::fromString($matches[2], false); + if ($address4 !== null) { + $bytes4 = $address4->getBytes(); + $address6->longAddress = substr($address6->longAddress, 0, -9).sprintf('%02x%02x:%02x%02x', $bytes4[0], $bytes4[1], $bytes4[2], $bytes4[3]); + $result = $address6; + } + } + } else { + if (strpos($address, '::') === false) { + $chunks = explode(':', $address); + } else { + $chunks = array(); + $parts = explode('::', $address); + if (count($parts) === 2) { + $before = ($parts[0] === '') ? array() : explode(':', $parts[0]); + $after = ($parts[1] === '') ? array() : explode(':', $parts[1]); + $missing = 8 - count($before) - count($after); + if ($missing >= 0) { + $chunks = $before; + if ($missing !== 0) { + $chunks = array_merge($chunks, array_fill(0, $missing, '0')); + } + $chunks = array_merge($chunks, $after); + } + } + } + if (count($chunks) === 8) { + $nums = array_map( + function ($chunk) { + return preg_match('/^[0-9A-Fa-f]{1,4}$/', $chunk) ? hexdec($chunk) : false; + }, + $chunks + ); + if (!in_array(false, $nums, true)) { + $longAddress = implode( + ':', + array_map( + function ($num) { + return sprintf('%04x', $num); + }, + $nums + ) + ); + $result = new static($longAddress); + } + } + } + } + + return $result; + } + + /** + * Parse an array of bytes and returns an IPv6 instance if the array is valid, or null otherwise. + * + * @param int[]|array $bytes + * + * @return static|null + */ + public static function fromBytes(array $bytes) + { + $result = null; + if (count($bytes) === 16) { + $address = ''; + for ($i = 0; $i < 16; ++$i) { + if ($i !== 0 && $i % 2 === 0) { + $address .= ':'; + } + $byte = $bytes[$i]; + if (is_int($byte) && $byte >= 0 && $byte <= 255) { + $address .= sprintf('%02x', $byte); + } else { + $address = null; + break; + } + } + if ($address !== null) { + $result = new static($address); + } + } + + return $result; + } + + /** + * Parse an array of words and returns an IPv6 instance if the array is valid, or null otherwise. + * + * @param int[]|array $words + * + * @return static|null + */ + public static function fromWords(array $words) + { + $result = null; + if (count($words) === 8) { + $chunks = array(); + for ($i = 0; $i < 8; ++$i) { + $word = $words[$i]; + if (is_int($word) && $word >= 0 && $word <= 0xffff) { + $chunks[] = sprintf('%04x', $word); + } else { + $chunks = null; + break; + } + } + if ($chunks !== null) { + $result = new static(implode(':', $chunks)); + } + } + + return $result; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::toString() + */ + public function toString($long = false) + { + if ($long) { + $result = $this->longAddress; + } else { + if ($this->shortAddress === null) { + if (strpos($this->longAddress, '0000:0000:0000:0000:0000:ffff:') === 0) { + $lastBytes = array_slice($this->getBytes(), -4); + $this->shortAddress = '::ffff:'.implode('.', $lastBytes); + } else { + $chunks = array_map( + function ($word) { + return dechex($word); + }, + $this->getWords() + ); + $shortAddress = implode(':', $chunks); + $matches = null; + for ($i = 8; $i > 1; --$i) { + $search = '(?:^|:)'.rtrim(str_repeat('0:', $i), ':').'(?:$|:)'; + if (preg_match('/^(.*?)'.$search.'(.*)$/', $shortAddress, $matches)) { + $shortAddress = $matches[1].'::'.$matches[2]; + break; + } + } + $this->shortAddress = $shortAddress; + } + } + $result = $this->shortAddress; + } + + return $result; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::__toString() + */ + public function __toString() + { + return $this->toString(); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::getBytes() + */ + public function getBytes() + { + if ($this->bytes === null) { + $bytes = array(); + foreach ($this->getWords() as $word) { + $bytes[] = $word >> 8; + $bytes[] = $word & 0xff; + } + $this->bytes = $bytes; + } + + return $this->bytes; + } + + /** + * Get the word list of the IP address. + * + * @return int[] + */ + public function getWords() + { + if ($this->words === null) { + $this->words = array_map( + function ($chunk) { + return hexdec($chunk); + }, + explode(':', $this->longAddress) + ); + } + + return $this->words; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::getAddressType() + */ + public function getAddressType() + { + return Type::T_IPv6; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::getDefaultReservedRangeType() + */ + public static function getDefaultReservedRangeType() + { + return RangeType::T_RESERVED; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::getReservedRanges() + */ + public static function getReservedRanges() + { + if (self::$reservedRanges === null) { + $reservedRanges = array(); + foreach (array( + // RFC 4291 + '::/128' => array(RangeType::T_UNSPECIFIED), + // RFC 4291 + '::1/128' => array(RangeType::T_LOOPBACK), + // RFC 4291 + '100::/8' => array(RangeType::T_DISCARD, array('100::/64' => RangeType::T_DISCARDONLY)), + //'2002::/16' => array(RangeType::), + // RFC 4291 + '2000::/3' => array(RangeType::T_PUBLIC), + // RFC 4193 + 'fc00::/7' => array(RangeType::T_PRIVATENETWORK), + // RFC 4291 + 'fe80::/10' => array(RangeType::T_LINKLOCAL_UNICAST), + // RFC 4291 + 'ff00::/8' => array(RangeType::T_MULTICAST), + // RFC 4291 + //'::/8' => array(RangeType::T_RESERVED), + // RFC 4048 + //'200::/7' => array(RangeType::T_RESERVED), + // RFC 4291 + //'400::/6' => array(RangeType::T_RESERVED), + // RFC 4291 + //'800::/5' => array(RangeType::T_RESERVED), + // RFC 4291 + //'1000::/4' => array(RangeType::T_RESERVED), + // RFC 4291 + //'4000::/3' => array(RangeType::T_RESERVED), + // RFC 4291 + //'6000::/3' => array(RangeType::T_RESERVED), + // RFC 4291 + //'8000::/3' => array(RangeType::T_RESERVED), + // RFC 4291 + //'a000::/3' => array(RangeType::T_RESERVED), + // RFC 4291 + //'c000::/3' => array(RangeType::T_RESERVED), + // RFC 4291 + //'e000::/4' => array(RangeType::T_RESERVED), + // RFC 4291 + //'f000::/5' => array(RangeType::T_RESERVED), + // RFC 4291 + //'f800::/6' => array(RangeType::T_RESERVED), + // RFC 4291 + //'fe00::/9' => array(RangeType::T_RESERVED), + // RFC 3879 + //'fec0::/10' => array(RangeType::T_RESERVED), + ) as $range => $data) { + $exceptions = array(); + if (isset($data[1])) { + foreach ($data[1] as $exceptionRange => $exceptionType) { + $exceptions[] = new AssignedRange(Subnet::fromString($exceptionRange), $exceptionType); + } + } + $reservedRanges[] = new AssignedRange(Subnet::fromString($range), $data[0], $exceptions); + } + self::$reservedRanges = $reservedRanges; + } + + return self::$reservedRanges; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::getRangeType() + */ + public function getRangeType() + { + if ($this->rangeType === null) { + $ipv4 = $this->toIPv4(); + if ($ipv4 !== null) { + $this->rangeType = $ipv4->getRangeType(); + } else { + $rangeType = null; + foreach (static::getReservedRanges() as $reservedRange) { + $rangeType = $reservedRange->getAddressType($this); + if ($rangeType !== null) { + break; + } + } + $this->rangeType = $rangeType === null ? static::getDefaultReservedRangeType() : $rangeType; + } + } + + return $this->rangeType; + } + + /** + * Create an IPv4 representation of this address (if possible, otherwise returns null). + * + * @return \IPLib\Address\IPv4|null + */ + public function toIPv4() + { + $result = null; + if (strpos($this->longAddress, '2002:') === 0) { + $result = IPv4::fromBytes(array_slice($this->getBytes(), 2, 4)); + } + + return $result; + } + + /** + * Render this IPv6 address in the "mixed" IPv6 (first 12 bytes) + IPv4 (last 4 bytes) mixed syntax. + * + * @param bool $ipV6Long render the IPv6 part in "long" format? + * @param bool $ipV4Long render the IPv4 part in "long" format? + * + * @return string + * + * @example '::13.1.68.3' + * @example '0000:0000:0000:0000:0000:0000:13.1.68.3' when $ipV6Long is true + * @example '::013.001.068.003' when $ipV4Long is true + * @example '0000:0000:0000:0000:0000:0000:013.001.068.003' when $ipV6Long and $ipV4Long are true + * + * @see https://tools.ietf.org/html/rfc4291#section-2.2 point 3. + */ + public function toMixedIPv6IPv4String($ipV6Long = false, $ipV4Long = false) + { + $myBytes = $this->getBytes(); + $ipv6Bytes = array_merge(array_slice($myBytes, 0, 12), array(0xff, 0xff, 0xff, 0xff)); + $ipv6String = static::fromBytes($ipv6Bytes)->toString($ipV6Long); + $ipv4Bytes = array_slice($myBytes, 12, 4); + $ipv4String = IPv4::fromBytes($ipv4Bytes)->toString($ipV4Long); + + return preg_replace('/((ffff:ffff)|(\d+(\.\d+){3}))$/i', $ipv4String, $ipv6String); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::getComparableString() + */ + public function getComparableString() + { + return $this->longAddress; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::matches() + */ + public function matches(RangeInterface $range) + { + return $range->contains($this); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::getNextAddress() + */ + public function getNextAddress() + { + $overflow = false; + $words = $this->getWords(); + for ($i = count($words) - 1; $i >= 0; --$i) { + if ($words[$i] === 0xffff) { + if ($i === 0) { + $overflow = true; + break; + } + $words[$i] = 0; + } else { + ++$words[$i]; + break; + } + } + + return $overflow ? null : static::fromWords($words); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Address\AddressInterface::getPreviousAddress() + */ + public function getPreviousAddress() + { + $overflow = false; + $words = $this->getWords(); + for ($i = count($words) - 1; $i >= 0; --$i) { + if ($words[$i] === 0) { + if ($i === 0) { + $overflow = true; + break; + } + $words[$i] = 0xffff; + } else { + --$words[$i]; + break; + } + } + + return $overflow ? null : static::fromWords($words); + } +} diff --git a/vendor/mlocati/ip-lib/src/Address/Type.php b/vendor/mlocati/ip-lib/src/Address/Type.php new file mode 100644 index 0000000000..06b07535d7 --- /dev/null +++ b/vendor/mlocati/ip-lib/src/Address/Type.php @@ -0,0 +1,42 @@ +<?php + +namespace IPLib\Address; + +/** + * Types of IP addresses. + */ +class Type +{ + /** + * IPv4 address. + * + * @var int + */ + const T_IPv4 = 4; + + /** + * IPv6 address. + * + * @var int + */ + const T_IPv6 = 6; + + /** + * Get the name of a type. + * + * @param int $type + * + * @return string + */ + public static function getName($type) + { + switch ($type) { + case static::T_IPv4: + return 'IP v4'; + case static::T_IPv6: + return 'IP v6'; + default: + return sprintf('Unknown type (%s)', $type); + } + } +} diff --git a/vendor/mlocati/ip-lib/src/Factory.php b/vendor/mlocati/ip-lib/src/Factory.php new file mode 100644 index 0000000000..947655998b --- /dev/null +++ b/vendor/mlocati/ip-lib/src/Factory.php @@ -0,0 +1,156 @@ +<?php + +namespace IPLib; + +use IPLib\Address\AddressInterface; + +/** + * Factory methods to build class instances. + */ +class Factory +{ + /** + * Parse an IP address string. + * + * @param string $address the address to parse + * @param bool $mayIncludePort set to false to avoid parsing addresses with ports + * @param bool $mayIncludeZoneID set to false to avoid parsing IPv6 addresses with zone IDs (see RFC 4007) + * + * @return \IPLib\Address\AddressInterface|null + */ + public static function addressFromString($address, $mayIncludePort = true, $mayIncludeZoneID = true) + { + $result = null; + if ($result === null) { + $result = Address\IPv4::fromString($address, $mayIncludePort); + } + if ($result === null) { + $result = Address\IPv6::fromString($address, $mayIncludePort, $mayIncludeZoneID); + } + + return $result; + } + + /** + * Convert a byte array to an address instance. + * + * @param int[]|array $bytes + * + * @return \IPLib\Address\AddressInterface|null + */ + public static function addressFromBytes(array $bytes) + { + $result = null; + if ($result === null) { + $result = Address\IPv4::fromBytes($bytes); + } + if ($result === null) { + $result = Address\IPv6::fromBytes($bytes); + } + + return $result; + } + + /** + * Parse an IP range string. + * + * @param string $range + * + * @return \IPLib\Range\RangeInterface|null + */ + public static function rangeFromString($range) + { + $result = null; + if ($result === null) { + $result = Range\Subnet::fromString($range); + } + if ($result === null) { + $result = Range\Pattern::fromString($range); + } + if ($result === null) { + $result = Range\Single::fromString($range); + } + + return $result; + } + + /** + * Create a Range instance starting from its boundaries. + * + * @param string|\IPLib\Address\AddressInterface $from + * @param string|\IPLib\Address\AddressInterface $to + * + * @return \IPLib\Range\RangeInterface|null + */ + public static function rangeFromBoundaries($from, $to) + { + $result = null; + $invalid = false; + foreach (array('from', 'to') as $param) { + if (!($$param instanceof AddressInterface)) { + $$param = (string) $$param; + if ($$param === '') { + $$param = null; + } else { + $$param = static::addressFromString($$param); + if ($$param === null) { + $invalid = true; + } + } + } + } + if ($invalid === false) { + $result = static::rangeFromBoundaryAddresses($from, $to); + } + + return $result; + } + + /** + * @param \IPLib\Address\AddressInterface $from + * @param \IPLib\Address\AddressInterface $to + * + * @return \IPLib\Range\RangeInterface|null + */ + protected static function rangeFromBoundaryAddresses(AddressInterface $from = null, AddressInterface $to = null) + { + if ($from === null && $to === null) { + $result = null; + } elseif ($to === null) { + $result = Range\Single::fromAddress($from); + } elseif ($from === null) { + $result = Range\Single::fromAddress($to); + } else { + $result = null; + $addressType = $from->getAddressType(); + if ($addressType === $to->getAddressType()) { + $cmp = strcmp($from->getComparableString(), $to->getComparableString()); + if ($cmp === 0) { + $result = Range\Single::fromAddress($from); + } else { + if ($cmp > 0) { + list($from, $to) = array($to, $from); + } + $fromBytes = $from->getBytes(); + $toBytes = $to->getBytes(); + $numBytes = count($fromBytes); + $sameBits = 0; + for ($byteIndex = 0; $byteIndex < $numBytes; ++$byteIndex) { + $fromByte = $fromBytes[$byteIndex]; + $toByte = $toBytes[$byteIndex]; + if ($fromByte === $toByte) { + $sameBits += 8; + } else { + $differentBitsInByte = decbin($fromByte ^ $toByte); + $sameBits += 8 - strlen($differentBitsInByte); + break; + } + } + $result = static::rangeFromString($from->toString(true).'/'.(string) $sameBits); + } + } + } + + return $result; + } +} diff --git a/vendor/mlocati/ip-lib/src/Range/Pattern.php b/vendor/mlocati/ip-lib/src/Range/Pattern.php new file mode 100644 index 0000000000..32a7864519 --- /dev/null +++ b/vendor/mlocati/ip-lib/src/Range/Pattern.php @@ -0,0 +1,331 @@ +<?php + +namespace IPLib\Range; + +use IPLib\Address\AddressInterface; +use IPLib\Address\IPv4; +use IPLib\Address\IPv6; +use IPLib\Address\Type as AddressType; +use IPLib\Factory; + +/** + * Represents an address range in pattern format (only ending asterisks are supported). + * + * @example 127.0.*.* + * @example ::/8 + */ +class Pattern implements RangeInterface +{ + /** + * Starting address of the range. + * + * @var \IPLib\Address\AddressInterface + */ + protected $fromAddress; + + /** + * Final address of the range. + * + * @var \IPLib\Address\AddressInterface + */ + protected $toAddress; + + /** + * Number of ending asterisks. + * + * @var int + */ + protected $asterisksCount; + + /** + * The type of the range of this IP range. + * + * @var int|null|false false if this range crosses multiple range types, null if yet to be determined + */ + protected $rangeType; + + /** + * Initializes the instance. + * + * @param \IPLib\Address\AddressInterface $fromAddress + * @param \IPLib\Address\AddressInterface $toAddress + * @param int $asterisksCount + */ + public function __construct(AddressInterface $fromAddress, AddressInterface $toAddress, $asterisksCount) + { + $this->fromAddress = $fromAddress; + $this->toAddress = $toAddress; + $this->asterisksCount = $asterisksCount; + } + + /** + * Try get the range instance starting from its string representation. + * + * @param string|mixed $range + * + * @return static|null + */ + public static function fromString($range) + { + $result = null; + if (is_string($range) && strpos($range, '*') !== false) { + $matches = null; + if ($range === '*.*.*.*') { + $result = new static(IPv4::fromString('0.0.0.0'), IPv4::fromString('255.255.255.255'), 4); + } elseif (strpos($range, '.') !== false && preg_match('/^[^*]+((?:\.\*)+)$/', $range, $matches)) { + $asterisksCount = strlen($matches[1]) >> 1; + if ($asterisksCount > 0) { + $missingDots = 3 - substr_count($range, '.'); + if ($missingDots > 0) { + $range .= str_repeat('.*', $missingDots); + $asterisksCount += $missingDots; + } + } + $fromAddress = IPv4::fromString(str_replace('*', '0', $range)); + if ($fromAddress !== null) { + $fixedBytes = array_slice($fromAddress->getBytes(), 0, -$asterisksCount); + $otherBytes = array_fill(0, $asterisksCount, 255); + $toAddress = IPv4::fromBytes(array_merge($fixedBytes, $otherBytes)); + $result = new static($fromAddress, $toAddress, $asterisksCount); + } + } elseif ($range === '*:*:*:*:*:*:*:*') { + $result = new static(IPv6::fromString('::'), IPv6::fromString('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'), 8); + } elseif (strpos($range, ':') !== false && preg_match('/^[^*]+((?::\*)+)$/', $range, $matches)) { + $asterisksCount = strlen($matches[1]) >> 1; + $fromAddress = IPv6::fromString(str_replace('*', '0', $range)); + if ($fromAddress !== null) { + $fixedWords = array_slice($fromAddress->getWords(), 0, -$asterisksCount); + $otherWords = array_fill(0, $asterisksCount, 0xffff); + $toAddress = IPv6::fromWords(array_merge($fixedWords, $otherWords)); + $result = new static($fromAddress, $toAddress, $asterisksCount); + } + } + } + + return $result; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::toString() + */ + public function toString($long = false) + { + if ($this->asterisksCount === 0) { + return $this->fromAddress->toString($long); + } + switch (true) { + case $this->fromAddress instanceof \IPLib\Address\IPv4: + $chunks = explode('.', $this->fromAddress->toString()); + $chunks = array_slice($chunks, 0, -$this->asterisksCount); + $chunks = array_pad($chunks, 4, '*'); + $result = implode('.', $chunks); + break; + case $this->fromAddress instanceof \IPLib\Address\IPv6: + if ($long) { + $chunks = explode(':', $this->fromAddress->toString(true)); + $chunks = array_slice($chunks, 0, -$this->asterisksCount); + $chunks = array_pad($chunks, 8, '*'); + $result = implode(':', $chunks); + } elseif ($this->asterisksCount === 8) { + $result = '*:*:*:*:*:*:*:*'; + } else { + $bytes = $this->toAddress->getBytes(); + $bytes = array_slice($bytes, 0, -$this->asterisksCount * 2); + $bytes = array_pad($bytes, 16, 1); + $address = IPv6::fromBytes($bytes); + $before = substr($address->toString(false), 0, -strlen(':101') * $this->asterisksCount); + $result = $before.str_repeat(':*', $this->asterisksCount); + } + break; + default: + throw new \Exception('@todo'); // @codeCoverageIgnore + } + + return $result; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::__toString() + */ + public function __toString() + { + return $this->toString(); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getAddressType() + */ + public function getAddressType() + { + return $this->fromAddress->getAddressType(); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getRangeType() + */ + public function getRangeType() + { + if ($this->rangeType === null) { + $addressType = $this->getAddressType(); + if ($addressType === AddressType::T_IPv6 && Subnet::get6to4()->containsRange($this)) { + $this->rangeType = Factory::rangeFromBoundaries($this->fromAddress->toIPv4(), $this->toAddress->toIPv4())->getRangeType(); + } else { + switch ($addressType) { + case AddressType::T_IPv4: + $defaultType = IPv4::getDefaultReservedRangeType(); + $reservedRanges = IPv4::getReservedRanges(); + break; + case AddressType::T_IPv6: + $defaultType = IPv6::getDefaultReservedRangeType(); + $reservedRanges = IPv6::getReservedRanges(); + break; + default: + throw new \Exception('@todo'); // @codeCoverageIgnore + } + $rangeType = null; + foreach ($reservedRanges as $reservedRange) { + $rangeType = $reservedRange->getRangeType($this); + if ($rangeType !== null) { + break; + } + } + $this->rangeType = $rangeType === null ? $defaultType : $rangeType; + } + } + + return $this->rangeType === false ? null : $this->rangeType; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::contains() + */ + public function contains(AddressInterface $address) + { + $result = false; + if ($address->getAddressType() === $this->getAddressType()) { + $cmp = $address->getComparableString(); + $from = $this->getComparableStartString(); + if ($cmp >= $from) { + $to = $this->getComparableEndString(); + if ($cmp <= $to) { + $result = true; + } + } + } + + return $result; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::containsRange() + */ + public function containsRange(RangeInterface $range) + { + $result = false; + if ($range->getAddressType() === $this->getAddressType()) { + $myStart = $this->getComparableStartString(); + $itsStart = $range->getComparableStartString(); + if ($itsStart >= $myStart) { + $myEnd = $this->getComparableEndString(); + $itsEnd = $range->getComparableEndString(); + if ($itsEnd <= $myEnd) { + $result = true; + } + } + } + + return $result; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getStartAddress() + */ + public function getStartAddress() + { + return $this->fromAddress; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getEndAddress() + */ + public function getEndAddress() + { + return $this->toAddress; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getComparableStartString() + */ + public function getComparableStartString() + { + return $this->fromAddress->getComparableString(); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getComparableEndString() + */ + public function getComparableEndString() + { + return $this->toAddress->getComparableString(); + } + + /** + * Get the subnet/CIDR representation of this range. + * + * @return \IPLib\Range\Subnet + */ + public function asSubnet() + { + switch ($this->getAddressType()) { + case AddressType::T_IPv4: + return new Subnet($this->getStartAddress(), $this->getEndAddress(), 8 * (4 - $this->asterisksCount)); + case AddressType::T_IPv6: + return new Subnet($this->getStartAddress(), $this->getEndAddress(), 16 * (8 - $this->asterisksCount)); + } + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getSubnetMask() + */ + public function getSubnetMask() + { + if ($this->getAddressType() !== AddressType::T_IPv4) { + return null; + } + switch ($this->asterisksCount) { + case 0: + $bytes = array(255, 255, 255, 255); + break; + case 4: + $bytes = array(0, 0, 0, 0); + break; + default: + $bytes = array_pad(array_fill(0, 4 - $this->asterisksCount, 255), 4, 0); + break; + } + + return IPv4::fromBytes($bytes); + } +} diff --git a/vendor/mlocati/ip-lib/src/Range/RangeInterface.php b/vendor/mlocati/ip-lib/src/Range/RangeInterface.php new file mode 100644 index 0000000000..1ddd9d6878 --- /dev/null +++ b/vendor/mlocati/ip-lib/src/Range/RangeInterface.php @@ -0,0 +1,96 @@ +<?php + +namespace IPLib\Range; + +use IPLib\Address\AddressInterface; + +/** + * Interface of all the range types. + */ +interface RangeInterface +{ + /** + * Get the string representation of this address. + * + * @param bool $long set to true to have a long/full representation, false otherwise + * + * @return string + * + * @example If $long is true, you'll get '0000:0000:0000:0000:0000:0000:0000:0001/128', '::1/128' otherwise. + */ + public function toString($long = false); + + /** + * Get the short string representation of this address. + * + * @return string + */ + public function __toString(); + + /** + * Get the type of the IP addresses contained in this range. + * + * @return int One of the \IPLib\Address\Type::T_... constants + */ + public function getAddressType(); + + /** + * Get the type of range of the IP address. + * + * @return int One of the \IPLib\Range\Type::T_... constants + */ + public function getRangeType(); + + /** + * Check if this range contains an IP address. + * + * @param \IPLib\Address\AddressInterface $address + * + * @return bool + */ + public function contains(AddressInterface $address); + + /** + * Check if this range contains another range. + * + * @param \IPLib\Range\RangeInterface $range + * + * @return bool + */ + public function containsRange(RangeInterface $range); + + /** + * Get the initial address contained in this range. + * + * @return \IPLib\Address\AddressInterface + */ + public function getStartAddress(); + + /** + * Get the final address contained in this range. + * + * @return \IPLib\Address\AddressInterface + */ + public function getEndAddress(); + + /** + * Get a string representation of the starting address of this range than can be used when comparing addresses and ranges. + * + * @return string + */ + public function getComparableStartString(); + + /** + * Get a string representation of the final address of this range than can be used when comparing addresses and ranges. + * + * @return string + */ + public function getComparableEndString(); + + /** + * Get the subnet mask representing this range (only for IPv4 ranges). + * + * @return \IPLib\Address\IPv4|null return NULL if the range is an IPv6 range, the subnet mask otherwise + */ + public function getSubnetMask(); +} diff --git a/vendor/mlocati/ip-lib/src/Range/Single.php b/vendor/mlocati/ip-lib/src/Range/Single.php new file mode 100644 index 0000000000..5bbd437838 --- /dev/null +++ b/vendor/mlocati/ip-lib/src/Range/Single.php @@ -0,0 +1,190 @@ +<?php + +namespace IPLib\Range; + +use IPLib\Address\AddressInterface; +use IPLib\Address\IPv4; +use IPLib\Address\Type as AddressType; +use IPLib\Factory; + +/** + * Represents a single address (eg a range that contains just one address). + * + * @example 127.0.0.1 + * @example ::1 + */ +class Single implements RangeInterface +{ + /** + * @var \IPLib\Address\AddressInterface + */ + protected $address; + + /** + * Initializes the instance. + * + * @param \IPLib\Address\AddressInterface $address + */ + protected function __construct(AddressInterface $address) + { + $this->address = $address; + } + + /** + * Try get the range instance starting from its string representation. + * + * @param string|mixed $range + * + * @return static|null + */ + public static function fromString($range) + { + $result = null; + $address = Factory::addressFromString($range); + if ($address !== null) { + $result = new static($address); + } + + return $result; + } + + /** + * Create the range instance starting from an address instance. + * + * @param \IPLib\Address\AddressInterface $address + * + * @return static + */ + public static function fromAddress(AddressInterface $address) + { + return new static($address); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::toString() + */ + public function toString($long = false) + { + return $this->address->toString($long); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::__toString() + */ + public function __toString() + { + return $this->address->__toString(); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getAddressType() + */ + public function getAddressType() + { + return $this->address->getAddressType(); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getRangeType() + */ + public function getRangeType() + { + return $this->address->getRangeType(); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::contains() + */ + public function contains(AddressInterface $address) + { + $result = false; + if ($address->getAddressType() === $this->getAddressType()) { + if ($address->toString(false) === $this->address->toString(false)) { + $result = true; + } + } + + return $result; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::containsRange() + */ + public function containsRange(RangeInterface $range) + { + $result = false; + if ($range->getAddressType() === $this->getAddressType()) { + if ($range->toString(false) === $this->toString(false)) { + $result = true; + } + } + + return $result; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getStartAddress() + */ + public function getStartAddress() + { + return $this->address; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getEndAddress() + */ + public function getEndAddress() + { + return $this->address; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getComparableStartString() + */ + public function getComparableStartString() + { + return $this->address->getComparableString(); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getComparableEndString() + */ + public function getComparableEndString() + { + return $this->address->getComparableString(); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getSubnetMask() + */ + public function getSubnetMask() + { + if ($this->getAddressType() !== AddressType::T_IPv4) { + return null; + } + + return IPv4::fromBytes(array(255, 255, 255, 255)); + } +} diff --git a/vendor/mlocati/ip-lib/src/Range/Subnet.php b/vendor/mlocati/ip-lib/src/Range/Subnet.php new file mode 100644 index 0000000000..6f4aebdebc --- /dev/null +++ b/vendor/mlocati/ip-lib/src/Range/Subnet.php @@ -0,0 +1,334 @@ +<?php + +namespace IPLib\Range; + +use IPLib\Address\AddressInterface; +use IPLib\Address\IPv4; +use IPLib\Address\IPv6; +use IPLib\Address\Type as AddressType; +use IPLib\Factory; + +/** + * Represents an address range in subnet format (eg CIDR). + * + * @example 127.0.0.1/32 + * @example ::/8 + */ +class Subnet implements RangeInterface +{ + /** + * Starting address of the range. + * + * @var \IPLib\Address\AddressInterface + */ + protected $fromAddress; + + /** + * Final address of the range. + * + * @var \IPLib\Address\AddressInterface + */ + protected $toAddress; + + /** + * Number of the same bits of the range. + * + * @var int + */ + protected $networkPrefix; + + /** + * The type of the range of this IP range. + * + * @var int|null + */ + protected $rangeType; + + /** + * The 6to4 address IPv6 address range. + * + * @var self|null + */ + private static $sixToFour; + + /** + * Initializes the instance. + * + * @param \IPLib\Address\AddressInterface $fromAddress + * @param \IPLib\Address\AddressInterface $toAddress + * @param int $networkPrefix + * + * @internal + */ + public function __construct(AddressInterface $fromAddress, AddressInterface $toAddress, $networkPrefix) + { + $this->fromAddress = $fromAddress; + $this->toAddress = $toAddress; + $this->networkPrefix = $networkPrefix; + } + + /** + * Try get the range instance starting from its string representation. + * + * @param string|mixed $range + * + * @return static|null + */ + public static function fromString($range) + { + $result = null; + if (is_string($range)) { + $parts = explode('/', $range); + if (count($parts) === 2) { + $address = Factory::addressFromString($parts[0]); + if ($address !== null) { + if (preg_match('/^[0-9]{1,9}$/', $parts[1])) { + $networkPrefix = (int) $parts[1]; + if ($networkPrefix >= 0) { + $addressBytes = $address->getBytes(); + $totalBytes = count($addressBytes); + $numDifferentBits = $totalBytes * 8 - $networkPrefix; + if ($numDifferentBits >= 0) { + $numSameBytes = $networkPrefix >> 3; + $sameBytes = array_slice($addressBytes, 0, $numSameBytes); + $differentBytesStart = ($totalBytes === $numSameBytes) ? array() : array_fill(0, $totalBytes - $numSameBytes, 0); + $differentBytesEnd = ($totalBytes === $numSameBytes) ? array() : array_fill(0, $totalBytes - $numSameBytes, 255); + $startSameBits = $networkPrefix % 8; + if ($startSameBits !== 0) { + $varyingByte = $addressBytes[$numSameBytes]; + $differentBytesStart[0] = $varyingByte & bindec(str_pad(str_repeat('1', $startSameBits), 8, '0', STR_PAD_RIGHT)); + $differentBytesEnd[0] = $differentBytesStart[0] + bindec(str_repeat('1', 8 - $startSameBits)); + } + $result = new static( + Factory::addressFromBytes(array_merge($sameBytes, $differentBytesStart)), + Factory::addressFromBytes(array_merge($sameBytes, $differentBytesEnd)), + $networkPrefix + ); + } + } + } + } + } + } + + return $result; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::toString() + */ + public function toString($long = false) + { + return $this->fromAddress->toString($long).'/'.$this->networkPrefix; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::__toString() + */ + public function __toString() + { + return $this->toString(); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getAddressType() + */ + public function getAddressType() + { + return $this->fromAddress->getAddressType(); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getRangeType() + */ + public function getRangeType() + { + if ($this->rangeType === null) { + $addressType = $this->getAddressType(); + if ($addressType === AddressType::T_IPv6 && static::get6to4()->containsRange($this)) { + $this->rangeType = Factory::rangeFromBoundaries($this->fromAddress->toIPv4(), $this->toAddress->toIPv4())->getRangeType(); + } else { + switch ($addressType) { + case AddressType::T_IPv4: + $defaultType = IPv4::getDefaultReservedRangeType(); + $reservedRanges = IPv4::getReservedRanges(); + break; + case AddressType::T_IPv6: + $defaultType = IPv6::getDefaultReservedRangeType(); + $reservedRanges = IPv6::getReservedRanges(); + break; + default: + throw new \Exception('@todo'); // @codeCoverageIgnore + } + $rangeType = null; + foreach ($reservedRanges as $reservedRange) { + $rangeType = $reservedRange->getRangeType($this); + if ($rangeType !== null) { + break; + } + } + $this->rangeType = $rangeType === null ? $defaultType : $rangeType; + } + } + + return $this->rangeType === false ? null : $this->rangeType; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::contains() + */ + public function contains(AddressInterface $address) + { + $result = false; + if ($address->getAddressType() === $this->getAddressType()) { + $cmp = $address->getComparableString(); + $from = $this->getComparableStartString(); + if ($cmp >= $from) { + $to = $this->getComparableEndString(); + if ($cmp <= $to) { + $result = true; + } + } + } + + return $result; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::containsRange() + */ + public function containsRange(RangeInterface $range) + { + $result = false; + if ($range->getAddressType() === $this->getAddressType()) { + $myStart = $this->getComparableStartString(); + $itsStart = $range->getComparableStartString(); + if ($itsStart >= $myStart) { + $myEnd = $this->getComparableEndString(); + $itsEnd = $range->getComparableEndString(); + if ($itsEnd <= $myEnd) { + $result = true; + } + } + } + + return $result; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getStartAddress() + */ + public function getStartAddress() + { + return $this->fromAddress; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getEndAddress() + */ + public function getEndAddress() + { + return $this->toAddress; + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getComparableStartString() + */ + public function getComparableStartString() + { + return $this->fromAddress->getComparableString(); + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getComparableEndString() + */ + public function getComparableEndString() + { + return $this->toAddress->getComparableString(); + } + + /** + * Get the 6to4 address IPv6 address range. + * + * @return self + */ + public static function get6to4() + { + if (self::$sixToFour === null) { + self::$sixToFour = self::fromString('2002::/16'); + } + + return self::$sixToFour; + } + + /** + * Get subnet prefix. + * + * @return int + */ + public function getNetworkPrefix() + { + return $this->networkPrefix; + } + + /** + * Get the pattern representation (if applicable) of this range. + * + * @return \IPLib\Range\Pattern|null return NULL if this range can't be represented by a pattern notation + */ + public function asPattern() + { + $address = $this->getStartAddress(); + $networkPrefix = $this->getNetworkPrefix(); + switch ($address->getAddressType()) { + case AddressType::T_IPv4: + return $networkPrefix % 8 === 0 ? new Pattern($address, $address, 4 - $networkPrefix / 8) : null; + case AddressType::T_IPv6: + return $networkPrefix % 16 === 0 ? new Pattern($address, $address, 8 - $networkPrefix / 16) : null; + } + } + + /** + * {@inheritdoc} + * + * @see \IPLib\Range\RangeInterface::getSubnetMask() + */ + public function getSubnetMask() + { + if ($this->getAddressType() !== AddressType::T_IPv4) { + return null; + } + $bytes = array(); + $prefix = $this->getNetworkPrefix(); + while ($prefix >= 8) { + $bytes[] = 255; + $prefix -= 8; + } + if ($prefix !== 0) { + $bytes[] = bindec(str_pad(str_repeat('1', $prefix), 8, '0')); + } + $bytes = array_pad($bytes, 4, 0); + + return IPv4::fromBytes($bytes); + } +} diff --git a/vendor/mlocati/ip-lib/src/Range/Type.php b/vendor/mlocati/ip-lib/src/Range/Type.php new file mode 100644 index 0000000000..503178bb77 --- /dev/null +++ b/vendor/mlocati/ip-lib/src/Range/Type.php @@ -0,0 +1,141 @@ +<?php + +namespace IPLib\Range; + +/** + * Types of IP address classes. + */ +class Type +{ + /** + * Unspecified/unknown address. + * + * @var int + */ + const T_UNSPECIFIED = 1; + + /** + * Reserved/internal use only. + * + * @var int + */ + const T_RESERVED = 2; + + /** + * Refer to source hosts on "this" network. + * + * @var int + */ + const T_THISNETWORK = 3; + + /** + * Internet host loopback address. + * + * @var int + */ + const T_LOOPBACK = 4; + + /** + * Relay anycast address. + * + * @var int + */ + const T_ANYCASTRELAY = 5; + + /** + * "Limited broadcast" destination address. + * + * @var int + */ + const T_LIMITEDBROADCAST = 6; + + /** + * Multicast address assignments - Indentify a group of interfaces. + * + * @var int + */ + const T_MULTICAST = 7; + + /** + * "Link local" address, allocated for communication between hosts on a single link. + * + * @var int + */ + const T_LINKLOCAL = 8; + + /** + * Link local unicast / Linked-scoped unicast. + * + * @var int + */ + const T_LINKLOCAL_UNICAST = 9; + + /** + * Discard-Only address. + * + * @var int + */ + const T_DISCARDONLY = 10; + + /** + * Discard address. + * + * @var int + */ + const T_DISCARD = 11; + + /** + * For use in private networks. + * + * @var int + */ + const T_PRIVATENETWORK = 12; + + /** + * Public address. + * + * @var int + */ + const T_PUBLIC = 13; + + /** + * Get the name of a type. + * + * @param int $type + * + * @return string + */ + public static function getName($type) + { + switch ($type) { + case static::T_UNSPECIFIED: + return 'Unspecified/unknown address'; + case static::T_RESERVED: + return 'Reserved/internal use only'; + case static::T_THISNETWORK: + return 'Refer to source hosts on "this" network'; + case static::T_LOOPBACK: + return 'Internet host loopback address'; + case static::T_ANYCASTRELAY: + return 'Relay anycast address'; + case static::T_LIMITEDBROADCAST: + return '"Limited broadcast" destination address'; + case static::T_MULTICAST: + return 'Multicast address assignments - Indentify a group of interfaces'; + case static::T_LINKLOCAL: + return '"Link local" address, allocated for communication between hosts on a single link'; + case static::T_LINKLOCAL_UNICAST: + return 'Link local unicast / Linked-scoped unicast'; + case static::T_DISCARDONLY: + return 'Discard only'; + case static::T_DISCARD: + return 'Discard'; + case static::T_PRIVATENETWORK: + return 'For use in private networks'; + case static::T_PUBLIC: + return 'Public address'; + default: + return $type === null ? 'Unknown type' : sprintf('Unknown type (%s)', $type); + } + } +} |
