Merge branch 'master' into stevenandres-master
This commit is contained in:
commit
288cf3f005
|
@ -10,7 +10,7 @@
|
||||||
* ADDED: Oracle database support (#868)
|
* ADDED: Oracle database support (#868)
|
||||||
* ADDED: Configuration option to limit paste creation and commenting to certain IPs (#883)
|
* ADDED: Configuration option to limit paste creation and commenting to certain IPs (#883)
|
||||||
* CHANGED: Language selection cookie only transmitted over HTTPS (#472)
|
* CHANGED: Language selection cookie only transmitted over HTTPS (#472)
|
||||||
* CHANGED: Upgrading libraries to: random_compat 2.0.20
|
* CHANGED: Upgrading libraries to: base-x 4.0.0, bootstrap 3.4.1 (JS), DOMpurify 2.3.6, ip-lib 1.18.0, jQuery 3.6.0, random_compat 2.0.21 & Showdown 2.0.0
|
||||||
* CHANGED: Removed automatic `.ini` configuration file migration (#808)
|
* CHANGED: Removed automatic `.ini` configuration file migration (#808)
|
||||||
* CHANGED: Removed configurable `dir` for `traffic` & `purge` limiters (#419)
|
* CHANGED: Removed configurable `dir` for `traffic` & `purge` limiters (#419)
|
||||||
* CHANGED: Server salt, traffic and purge limiter now stored in the storage backend (#419)
|
* CHANGED: Server salt, traffic and purge limiter now stored in the storage backend (#419)
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
* FIXED: HTML injection via unescaped attachment filename (#554)
|
* FIXED: HTML injection via unescaped attachment filename (#554)
|
||||||
* FIXED: Password disabling option (#527)
|
* FIXED: Password disabling option (#527)
|
||||||
* **1.2.2 (2020-01-11)**
|
* **1.2.2 (2020-01-11)**
|
||||||
* CHANGED: Upgrading libraries to: bootstrap 3.4.1, DOMpurify 2.0.7, jQuery 3.4.1, kjua 0.6.0, Showdown 1.9.1 & SJCL 1.0.8
|
* CHANGED: Upgrading libraries to: bootstrap 3.4.1 (CSS), DOMpurify 2.0.7, jQuery 3.4.1, kjua 0.6.0, Showdown 1.9.1 & SJCL 1.0.8
|
||||||
* FIXED: HTML injection via unescaped attachment filename (#554)
|
* FIXED: HTML injection via unescaped attachment filename (#554)
|
||||||
* **1.3.1 (2019-09-22)**
|
* **1.3.1 (2019-09-22)**
|
||||||
* ADDED: Translation for Bulgarian (#455)
|
* ADDED: Translation for Bulgarian (#455)
|
||||||
|
|
|
@ -87,7 +87,7 @@ languageselection = false
|
||||||
; async functions and display an error if not and for Chrome to enable
|
; async functions and display an error if not and for Chrome to enable
|
||||||
; webassembly support (used for zlib compression). You can remove it if Chrome
|
; webassembly support (used for zlib compression). You can remove it if Chrome
|
||||||
; doesn't need to be supported and old browsers don't need to be warned.
|
; doesn't need to be supported and old browsers don't need to be warned.
|
||||||
; cspheader = "default-src 'none'; base-uri 'self'; form-action 'none'; manifest-src 'self'; connect-src * blob:; script-src 'self' 'unsafe-eval' resource:; style-src 'self'; font-src 'self'; img-src 'self' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads"
|
; cspheader = "default-src 'none'; base-uri 'self'; form-action 'none'; manifest-src 'self'; connect-src * blob:; script-src 'self' 'unsafe-eval' resource:; style-src 'self'; font-src 'self'; frame-ancestors 'none'; img-src 'self' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads"
|
||||||
|
|
||||||
; stay compatible with PrivateBin Alpha 0.19, less secure
|
; stay compatible with PrivateBin Alpha 0.19, less secure
|
||||||
; if enabled will use base64.js version 1.7 instead of 2.1.9 and sha1 instead of
|
; if enabled will use base64.js version 1.7 instead of 2.1.9 and sha1 instead of
|
||||||
|
|
|
@ -25,12 +25,12 @@
|
||||||
},
|
},
|
||||||
"require" : {
|
"require" : {
|
||||||
"php" : "^5.6.0 || ^7.0 || ^8.0",
|
"php" : "^5.6.0 || ^7.0 || ^8.0",
|
||||||
"paragonie/random_compat" : "2.0.20",
|
"paragonie/random_compat" : "2.0.21",
|
||||||
"yzalis/identicon" : "2.0.0",
|
"yzalis/identicon" : "2.0.0",
|
||||||
"mlocati/ip-lib" : "1.14.0"
|
"mlocati/ip-lib" : "1.18.0"
|
||||||
},
|
},
|
||||||
"suggest" : {
|
"suggest" : {
|
||||||
"google/cloud-storage" : "1.23.1"
|
"google/cloud-storage" : "1.26.1"
|
||||||
},
|
},
|
||||||
"require-dev" : {
|
"require-dev" : {
|
||||||
"phpunit/phpunit" : "^4.6 || ^5.0"
|
"phpunit/phpunit" : "^4.6 || ^5.0"
|
||||||
|
|
|
@ -4,20 +4,20 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "217f0ba9bdac1014a332a8ba390be949",
|
"content-hash": "fa52d4988bfe17d4b27e3a4789a1ec49",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "mlocati/ip-lib",
|
"name": "mlocati/ip-lib",
|
||||||
"version": "1.14.0",
|
"version": "1.18.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/mlocati/ip-lib.git",
|
"url": "https://github.com/mlocati/ip-lib.git",
|
||||||
"reference": "882bc0e115970a536b13bcfa59f312783fce08c8"
|
"reference": "c77bd0b1f3e3956c7e9661e75cb1f54ed67d95d2"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/mlocati/ip-lib/zipball/882bc0e115970a536b13bcfa59f312783fce08c8",
|
"url": "https://api.github.com/repos/mlocati/ip-lib/zipball/c77bd0b1f3e3956c7e9661e75cb1f54ed67d95d2",
|
||||||
"reference": "882bc0e115970a536b13bcfa59f312783fce08c8",
|
"reference": "c77bd0b1f3e3956c7e9661e75cb1f54ed67d95d2",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -25,8 +25,7 @@
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"ext-pdo_sqlite": "*",
|
"ext-pdo_sqlite": "*",
|
||||||
"phpunit/dbunit": "^1.4 || ^2 || ^3 || ^4",
|
"phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.5 || ^8.5 || ^9.5"
|
||||||
"phpunit/phpunit": "^4.8 || ^5.7 || ^6.5"
|
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -72,27 +71,27 @@
|
||||||
"type": "other"
|
"type": "other"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2020-12-31T11:30:02+00:00"
|
"time": "2022-01-13T18:05:33+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "paragonie/random_compat",
|
"name": "paragonie/random_compat",
|
||||||
"version": "v2.0.20",
|
"version": "v2.0.21",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/paragonie/random_compat.git",
|
"url": "https://github.com/paragonie/random_compat.git",
|
||||||
"reference": "0f1f60250fccffeaf5dda91eea1c018aed1adc2a"
|
"reference": "96c132c7f2f7bc3230723b66e89f8f150b29d5ae"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/0f1f60250fccffeaf5dda91eea1c018aed1adc2a",
|
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/96c132c7f2f7bc3230723b66e89f8f150b29d5ae",
|
||||||
"reference": "0f1f60250fccffeaf5dda91eea1c018aed1adc2a",
|
"reference": "96c132c7f2f7bc3230723b66e89f8f150b29d5ae",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.2.0"
|
"php": ">=5.2.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "4.*|5.*"
|
"phpunit/phpunit": "*"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
|
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
|
||||||
|
@ -121,7 +120,7 @@
|
||||||
"pseudorandom",
|
"pseudorandom",
|
||||||
"random"
|
"random"
|
||||||
],
|
],
|
||||||
"time": "2021-04-17T09:33:01+00:00"
|
"time": "2022-02-16T17:07:03+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "yzalis/identicon",
|
"name": "yzalis/identicon",
|
||||||
|
@ -270,12 +269,12 @@
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
|
||||||
"DeepCopy\\": "src/DeepCopy/"
|
|
||||||
},
|
|
||||||
"files": [
|
"files": [
|
||||||
"src/DeepCopy/deep_copy.php"
|
"src/DeepCopy/deep_copy.php"
|
||||||
]
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"DeepCopy\\": "src/DeepCopy/"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
"license": [
|
"license": [
|
||||||
|
@ -348,16 +347,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpdocumentor/reflection-docblock",
|
"name": "phpdocumentor/reflection-docblock",
|
||||||
"version": "5.2.2",
|
"version": "5.3.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
|
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
|
||||||
"reference": "069a785b2141f5bcf49f3e353548dc1cce6df556"
|
"reference": "622548b623e81ca6d78b721c5e029f4ce664f170"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556",
|
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170",
|
||||||
"reference": "069a785b2141f5bcf49f3e353548dc1cce6df556",
|
"reference": "622548b623e81ca6d78b721c5e029f4ce664f170",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -368,7 +367,8 @@
|
||||||
"webmozart/assert": "^1.9.1"
|
"webmozart/assert": "^1.9.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"mockery/mockery": "~1.3.2"
|
"mockery/mockery": "~1.3.2",
|
||||||
|
"psalm/phar": "^4.8"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
|
@ -396,20 +396,20 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
|
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
|
||||||
"time": "2020-09-03T19:13:55+00:00"
|
"time": "2021-10-19T17:43:47+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpdocumentor/type-resolver",
|
"name": "phpdocumentor/type-resolver",
|
||||||
"version": "1.4.0",
|
"version": "1.6.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpDocumentor/TypeResolver.git",
|
"url": "https://github.com/phpDocumentor/TypeResolver.git",
|
||||||
"reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0"
|
"reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0",
|
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/93ebd0014cab80c4ea9f5e297ea48672f1b87706",
|
||||||
"reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0",
|
"reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -417,7 +417,8 @@
|
||||||
"phpdocumentor/reflection-common": "^2.0"
|
"phpdocumentor/reflection-common": "^2.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"ext-tokenizer": "*"
|
"ext-tokenizer": "*",
|
||||||
|
"psalm/phar": "^4.8"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
|
@ -441,7 +442,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
|
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
|
||||||
"time": "2020-09-17T18:55:26+00:00"
|
"time": "2022-01-04T19:58:01+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpspec/prophecy",
|
"name": "phpspec/prophecy",
|
||||||
|
@ -1419,21 +1420,24 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-ctype",
|
"name": "symfony/polyfill-ctype",
|
||||||
"version": "v1.23.0",
|
"version": "v1.24.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||||
"reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce"
|
"reference": "30885182c981ab175d4d034db0f6f469898070ab"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce",
|
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
|
||||||
"reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce",
|
"reference": "30885182c981ab175d4d034db0f6f469898070ab",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.1"
|
"php": ">=7.1"
|
||||||
},
|
},
|
||||||
|
"provide": {
|
||||||
|
"ext-ctype": "*"
|
||||||
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-ctype": "For best performance"
|
"ext-ctype": "For best performance"
|
||||||
},
|
},
|
||||||
|
@ -1491,20 +1495,20 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2021-02-19T12:13:01+00:00"
|
"time": "2021-10-20T20:35:02+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/yaml",
|
"name": "symfony/yaml",
|
||||||
"version": "v4.4.24",
|
"version": "v4.4.37",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/yaml.git",
|
"url": "https://github.com/symfony/yaml.git",
|
||||||
"reference": "8b6d1b97521e2f125039b3fcb4747584c6dfa0ef"
|
"reference": "d7f637cc0f0cc14beb0984f2bb50da560b271311"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/8b6d1b97521e2f125039b3fcb4747584c6dfa0ef",
|
"url": "https://api.github.com/repos/symfony/yaml/zipball/d7f637cc0f0cc14beb0984f2bb50da560b271311",
|
||||||
"reference": "8b6d1b97521e2f125039b3fcb4747584c6dfa0ef",
|
"reference": "d7f637cc0f0cc14beb0984f2bb50da560b271311",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -1559,7 +1563,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2021-05-16T09:52:47+00:00"
|
"time": "2022-01-24T20:11:01+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "webmozart/assert",
|
"name": "webmozart/assert",
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
// base-x encoding / decoding
|
// base-x encoding / decoding
|
||||||
// based on https://github.com/cryptocoinjs/base-x 3.0.7
|
|
||||||
// modification: removed Buffer dependency and node.modules entry
|
|
||||||
// Copyright (c) 2018 base-x contributors
|
// Copyright (c) 2018 base-x contributors
|
||||||
// Copyright (c) 2014-2018 The Bitcoin Core developers (base58.cpp)
|
// Copyright (c) 2014-2018 The Bitcoin Core developers (base58.cpp)
|
||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
// file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
(function(){
|
(function(){
|
||||||
this.baseX = function base (ALPHABET) {
|
this.baseX = function base (ALPHABET) {
|
||||||
if (ALPHABET.length >= 255) { throw new TypeError('Alphabet too long') }
|
if (ALPHABET.length >= 255) { throw new TypeError('Alphabet too long') }
|
||||||
var BASE_MAP = new Uint8Array(256)
|
var BASE_MAP = new Uint8Array(256)
|
||||||
BASE_MAP.fill(255)
|
for (var j = 0; j < BASE_MAP.length; j++) {
|
||||||
|
BASE_MAP[j] = 255
|
||||||
|
}
|
||||||
for (var i = 0; i < ALPHABET.length; i++) {
|
for (var i = 0; i < ALPHABET.length; i++) {
|
||||||
var x = ALPHABET.charAt(i)
|
var x = ALPHABET.charAt(i)
|
||||||
var xc = x.charCodeAt(0)
|
var xc = x.charCodeAt(0)
|
||||||
|
@ -23,6 +22,13 @@ this.baseX = function base (ALPHABET) {
|
||||||
var FACTOR = Math.log(BASE) / Math.log(256) // log(BASE) / log(256), rounded up
|
var FACTOR = Math.log(BASE) / Math.log(256) // log(BASE) / log(256), rounded up
|
||||||
var iFACTOR = Math.log(256) / Math.log(BASE) // log(256) / log(BASE), rounded up
|
var iFACTOR = Math.log(256) / Math.log(BASE) // log(256) / log(BASE), rounded up
|
||||||
function encode (source) {
|
function encode (source) {
|
||||||
|
if (source instanceof Uint8Array) {
|
||||||
|
} else if (ArrayBuffer.isView(source)) {
|
||||||
|
source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength)
|
||||||
|
} else if (Array.isArray(source)) {
|
||||||
|
source = Uint8Array.from(source)
|
||||||
|
}
|
||||||
|
if (!(source instanceof Uint8Array)) { throw new TypeError('Expected Uint8Array') }
|
||||||
if (source.length === 0) { return '' }
|
if (source.length === 0) { return '' }
|
||||||
// Skip & count leading zeroes.
|
// Skip & count leading zeroes.
|
||||||
var zeroes = 0
|
var zeroes = 0
|
||||||
|
@ -62,10 +68,8 @@ this.baseX = function base (ALPHABET) {
|
||||||
}
|
}
|
||||||
function decodeUnsafe (source) {
|
function decodeUnsafe (source) {
|
||||||
if (typeof source !== 'string') { throw new TypeError('Expected String') }
|
if (typeof source !== 'string') { throw new TypeError('Expected String') }
|
||||||
if (source.length === 0) { return '' }
|
if (source.length === 0) { return new Uint8Array() }
|
||||||
var psz = 0
|
var psz = 0
|
||||||
// Skip leading spaces.
|
|
||||||
if (source[psz] === ' ') { return }
|
|
||||||
// Skip and count leading '1's.
|
// Skip and count leading '1's.
|
||||||
var zeroes = 0
|
var zeroes = 0
|
||||||
var length = 0
|
var length = 0
|
||||||
|
@ -92,14 +96,12 @@ this.baseX = function base (ALPHABET) {
|
||||||
length = i
|
length = i
|
||||||
psz++
|
psz++
|
||||||
}
|
}
|
||||||
// Skip trailing spaces.
|
|
||||||
if (source[psz] === ' ') { return }
|
|
||||||
// Skip leading zeroes in b256.
|
// Skip leading zeroes in b256.
|
||||||
var it4 = size - length
|
var it4 = size - length
|
||||||
while (it4 !== size && b256[it4] === 0) {
|
while (it4 !== size && b256[it4] === 0) {
|
||||||
it4++
|
it4++
|
||||||
}
|
}
|
||||||
var vch = []
|
var vch = new Uint8Array(zeroes + (size - it4))
|
||||||
var j = zeroes
|
var j = zeroes
|
||||||
while (it4 !== size) {
|
while (it4 !== size) {
|
||||||
vch[j++] = b256[it4++]
|
vch[j++] = b256[it4++]
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -16,11 +16,11 @@ global.zlib = require('./zlib-1.2.11').zlib;
|
||||||
require('./prettify');
|
require('./prettify');
|
||||||
global.prettyPrint = window.PR.prettyPrint;
|
global.prettyPrint = window.PR.prettyPrint;
|
||||||
global.prettyPrintOne = window.PR.prettyPrintOne;
|
global.prettyPrintOne = window.PR.prettyPrintOne;
|
||||||
global.showdown = require('./showdown-1.9.1');
|
global.showdown = require('./showdown-2.0.0');
|
||||||
global.DOMPurify = require('./purify-2.2.7');
|
global.DOMPurify = require('./purify-2.3.6');
|
||||||
global.baseX = require('./base-x-3.0.7').baseX;
|
global.baseX = require('./base-x-4.0.0').baseX;
|
||||||
global.Legacy = require('./legacy').Legacy;
|
global.Legacy = require('./legacy').Legacy;
|
||||||
require('./bootstrap-3.3.7');
|
require('./bootstrap-3.4.1');
|
||||||
require('./privatebin');
|
require('./privatebin');
|
||||||
|
|
||||||
// internal variables
|
// internal variables
|
||||||
|
@ -131,4 +131,3 @@ exports.jscMimeTypes = function() {
|
||||||
exports.jscFormats = function() {
|
exports.jscFormats = function() {
|
||||||
return jsc.elements(formats);
|
return jsc.elements(formats);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -110,4 +110,3 @@ describe('DiscussionViewer', function () {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -52,12 +52,12 @@ describe('Editor', function () {
|
||||||
!$.PrivateBin.Editor.isPreview() &&
|
!$.PrivateBin.Editor.isPreview() &&
|
||||||
!$('#message').hasClass('hidden')
|
!$('#message').hasClass('hidden')
|
||||||
);
|
);
|
||||||
$('#messagepreview').click();
|
$('#messagepreview').trigger('click');
|
||||||
results.push(
|
results.push(
|
||||||
$.PrivateBin.Editor.isPreview() &&
|
$.PrivateBin.Editor.isPreview() &&
|
||||||
$('#message').hasClass('hidden')
|
$('#message').hasClass('hidden')
|
||||||
);
|
);
|
||||||
$('#messageedit').click();
|
$('#messageedit').trigger('click');
|
||||||
results.push(
|
results.push(
|
||||||
!$.PrivateBin.Editor.isPreview() &&
|
!$.PrivateBin.Editor.isPreview() &&
|
||||||
!$('#message').hasClass('hidden')
|
!$('#message').hasClass('hidden')
|
||||||
|
@ -68,4 +68,3 @@ describe('Editor', function () {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -280,7 +280,8 @@ describe('TopNav', function () {
|
||||||
it(
|
it(
|
||||||
'collapses the navigation when displayed on a small screen',
|
'collapses the navigation when displayed on a small screen',
|
||||||
function () {
|
function () {
|
||||||
var results = [];
|
var clean = jsdom(),
|
||||||
|
results = [];
|
||||||
$('body').html(
|
$('body').html(
|
||||||
'<nav><div class="navbar-header"><button type="button" ' +
|
'<nav><div class="navbar-header"><button type="button" ' +
|
||||||
'class="navbar-toggle collapsed" data-toggle="collapse" ' +
|
'class="navbar-toggle collapsed" data-toggle="collapse" ' +
|
||||||
|
@ -301,7 +302,11 @@ describe('TopNav', function () {
|
||||||
$('.navbar-toggle').hasClass('collapsed') &&
|
$('.navbar-toggle').hasClass('collapsed') &&
|
||||||
$('#navbar').attr('aria-expanded') != 'true'
|
$('#navbar').attr('aria-expanded') != 'true'
|
||||||
);
|
);
|
||||||
$('.navbar-toggle').click();
|
/*
|
||||||
|
with the upgrade for bootstrap-3.3.7.js to bootstrap-3.4.1.js
|
||||||
|
the mobile interface detection changed to check if the
|
||||||
|
ontouchstart event exists, which broke this section of the test
|
||||||
|
$('.navbar-toggle').trigger('click');
|
||||||
results.push(
|
results.push(
|
||||||
!$('.navbar-toggle').hasClass('collapsed') &&
|
!$('.navbar-toggle').hasClass('collapsed') &&
|
||||||
$('#navbar').attr('aria-expanded') == 'true'
|
$('#navbar').attr('aria-expanded') == 'true'
|
||||||
|
@ -311,7 +316,8 @@ describe('TopNav', function () {
|
||||||
$('.navbar-toggle').hasClass('collapsed') &&
|
$('.navbar-toggle').hasClass('collapsed') &&
|
||||||
$('#navbar').attr('aria-expanded') == 'false'
|
$('#navbar').attr('aria-expanded') == 'false'
|
||||||
);
|
);
|
||||||
cleanup();
|
*/
|
||||||
|
clean();
|
||||||
assert.ok(results.every(element => element));
|
assert.ok(results.every(element => element));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -670,4 +676,3 @@ describe('TopNav', function () {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ class Configuration
|
||||||
'urlshortener' => '',
|
'urlshortener' => '',
|
||||||
'qrcode' => true,
|
'qrcode' => true,
|
||||||
'icon' => 'identicon',
|
'icon' => 'identicon',
|
||||||
'cspheader' => 'default-src \'none\'; base-uri \'self\'; form-action \'none\'; manifest-src \'self\'; connect-src * blob:; script-src \'self\' \'unsafe-eval\' resource:; style-src \'self\'; font-src \'self\'; img-src \'self\' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads',
|
'cspheader' => 'default-src \'none\'; base-uri \'self\'; form-action \'none\'; manifest-src \'self\'; connect-src * blob:; script-src \'self\' \'unsafe-eval\' resource:; style-src \'self\'; font-src \'self\'; frame-ancestors \'none\'; img-src \'self\' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads',
|
||||||
'zerobincompatibility' => false,
|
'zerobincompatibility' => false,
|
||||||
'httpwarning' => true,
|
'httpwarning' => true,
|
||||||
'compression' => 'zlib',
|
'compression' => 'zlib',
|
||||||
|
|
|
@ -41,7 +41,7 @@ if ($SYNTAXHIGHLIGHTING) :
|
||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
<noscript><link type="text/css" rel="stylesheet" href="css/noscript.css" /></noscript>
|
<noscript><link type="text/css" rel="stylesheet" href="css/noscript.css" /></noscript>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/jquery-3.6.0.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/jquery-3.6.0.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous"></script>
|
||||||
<?php
|
<?php
|
||||||
if ($QRCODE) :
|
if ($QRCODE) :
|
||||||
?>
|
?>
|
||||||
|
@ -55,9 +55,9 @@ if ($ZEROBINCOMPATIBILITY) :
|
||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/zlib-1.2.11.js" integrity="sha512-Yey/0yoaVmSbqMEyyff3DIu8kCPwpHvHf7tY1AuZ1lrX9NPCMg87PwzngMi+VNbe4ilCApmePeuKT869RTcyCQ==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/zlib-1.2.11.js" integrity="sha512-Yey/0yoaVmSbqMEyyff3DIu8kCPwpHvHf7tY1AuZ1lrX9NPCMg87PwzngMi+VNbe4ilCApmePeuKT869RTcyCQ==" crossorigin="anonymous"></script>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/base-x-3.0.7.js" integrity="sha512-/Bi1AJIP0TtxEB+Jh6Hk809H1G7vn4iJV80qagslf0+Hm0UjUi1s3qNrn1kZULjzUYuaf6ck0ndLGJ7MxWLmgQ==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/base-x-4.0.0.js" integrity="sha512-nNPg5IGCwwrveZ8cA/yMGr5HiRS5Ps2H+s0J/mKTPjCPWUgFGGw7M5nqdnPD3VsRwCVysUh3Y8OWjeSKGkEQJQ==" crossorigin="anonymous"></script>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/bootstrap-3.3.7.js" integrity="sha512-iztkobsvnjKfAtTNdHkGVjAYTrrtlC7mGp/54c40wowO7LhURYl3gVzzcEqGl/qKXQltJ2HwMrdLcNUdo+N/RQ==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/bootstrap-3.4.1.js" integrity="sha512-oBTprMeNEKCnqfuqKd6sbvFzmFQtlXS3e0C/RGFV0hD6QzhHV+ODfaQbAlmY6/q0ubbwlAM/nCJjkrgA3waLzg==" crossorigin="anonymous"></script>
|
||||||
<?php
|
<?php
|
||||||
if ($SYNTAXHIGHLIGHTING) :
|
if ($SYNTAXHIGHLIGHTING) :
|
||||||
?>
|
?>
|
||||||
|
@ -66,11 +66,11 @@ if ($SYNTAXHIGHLIGHTING) :
|
||||||
endif;
|
endif;
|
||||||
if ($MARKDOWN) :
|
if ($MARKDOWN) :
|
||||||
?>
|
?>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/showdown-1.9.1.js" integrity="sha512-nRri7kqh3iRLdHbhtjfe8w9eAQPmt+ubH5U88UZyKbz6O9Q0q4haaXF0krOUclKmRJou/kKZYulgBHvHXPqOvg==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/showdown-2.0.0.js" integrity="sha512-UB9jpMTOJLSnVzePuqlSGT34G70wEGqtIWabMeAh+Drnj4/uQ8rFkFn1zkN9vkWp/7nA51U2LmP23H5MJvBXsw==" crossorigin="anonymous"></script>
|
||||||
<?php
|
<?php
|
||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/purify-2.2.7.js" integrity="sha512-7Ka1I/nJuR2CL8wzIS5PJS4HgEMd0HJ6kfAl6fFhwFBB27rhztFbe0tS+Ex+Qg+5n4nZIT4lty4k4Di3+X9T4A==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/purify-2.3.6.js" integrity="sha512-N1GGPjbqLbwK821ZN7C925WuTwU4aDxz2CEEOXQ6/s6m6MBwVj8fh5fugiE2hzsm0xud3q7jpjZQ4ILnpMREYQ==" crossorigin="anonymous"></script>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-PTOcxIWIPWCnb5vC4fmQDMqYGerwsu3AndVyPxn9NlQffIWYMPf/p28Z9SIygXsmcYjmTRmUiW5y7df63mNTfg==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-PTOcxIWIPWCnb5vC4fmQDMqYGerwsu3AndVyPxn9NlQffIWYMPf/p28Z9SIygXsmcYjmTRmUiW5y7df63mNTfg==" crossorigin="anonymous"></script>
|
||||||
<!-- icon -->
|
<!-- icon -->
|
||||||
|
|
|
@ -20,7 +20,7 @@ if ($SYNTAXHIGHLIGHTING):
|
||||||
endif;
|
endif;
|
||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/jquery-3.6.0.js" integrity="sha512-bnIvzh6FU75ZKxp0GXLH9bewza/OIw6dLVh9ICg0gogclmYGguQJWl8U30WpbsGTqbIiAwxTsbe76DErLq5EDQ==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/jquery-3.6.0.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous"></script>
|
||||||
<?php
|
<?php
|
||||||
if ($QRCODE):
|
if ($QRCODE):
|
||||||
?>
|
?>
|
||||||
|
@ -34,7 +34,7 @@ if ($ZEROBINCOMPATIBILITY):
|
||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/zlib-1.2.11.js" integrity="sha512-Yey/0yoaVmSbqMEyyff3DIu8kCPwpHvHf7tY1AuZ1lrX9NPCMg87PwzngMi+VNbe4ilCApmePeuKT869RTcyCQ==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/zlib-1.2.11.js" integrity="sha512-Yey/0yoaVmSbqMEyyff3DIu8kCPwpHvHf7tY1AuZ1lrX9NPCMg87PwzngMi+VNbe4ilCApmePeuKT869RTcyCQ==" crossorigin="anonymous"></script>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/base-x-3.0.7.js" integrity="sha512-/Bi1AJIP0TtxEB+Jh6Hk809H1G7vn4iJV80qagslf0+Hm0UjUi1s3qNrn1kZULjzUYuaf6ck0ndLGJ7MxWLmgQ==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/base-x-4.0.0.js" integrity="sha512-nNPg5IGCwwrveZ8cA/yMGr5HiRS5Ps2H+s0J/mKTPjCPWUgFGGw7M5nqdnPD3VsRwCVysUh3Y8OWjeSKGkEQJQ==" crossorigin="anonymous"></script>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
|
||||||
<?php
|
<?php
|
||||||
if ($SYNTAXHIGHLIGHTING):
|
if ($SYNTAXHIGHLIGHTING):
|
||||||
|
@ -44,11 +44,11 @@ if ($SYNTAXHIGHLIGHTING):
|
||||||
endif;
|
endif;
|
||||||
if ($MARKDOWN):
|
if ($MARKDOWN):
|
||||||
?>
|
?>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/showdown-1.9.1.js" integrity="sha512-nRri7kqh3iRLdHbhtjfe8w9eAQPmt+ubH5U88UZyKbz6O9Q0q4haaXF0krOUclKmRJou/kKZYulgBHvHXPqOvg==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/showdown-2.0.0.js" integrity="sha512-UB9jpMTOJLSnVzePuqlSGT34G70wEGqtIWabMeAh+Drnj4/uQ8rFkFn1zkN9vkWp/7nA51U2LmP23H5MJvBXsw==" crossorigin="anonymous"></script>
|
||||||
<?php
|
<?php
|
||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/purify-2.2.7.js" integrity="sha512-7Ka1I/nJuR2CL8wzIS5PJS4HgEMd0HJ6kfAl6fFhwFBB27rhztFbe0tS+Ex+Qg+5n4nZIT4lty4k4Di3+X9T4A==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/purify-2.3.6.js" integrity="sha512-N1GGPjbqLbwK821ZN7C925WuTwU4aDxz2CEEOXQ6/s6m6MBwVj8fh5fugiE2hzsm0xud3q7jpjZQ4ILnpMREYQ==" crossorigin="anonymous"></script>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-PTOcxIWIPWCnb5vC4fmQDMqYGerwsu3AndVyPxn9NlQffIWYMPf/p28Z9SIygXsmcYjmTRmUiW5y7df63mNTfg==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-PTOcxIWIPWCnb5vC4fmQDMqYGerwsu3AndVyPxn9NlQffIWYMPf/p28Z9SIygXsmcYjmTRmUiW5y7df63mNTfg==" crossorigin="anonymous"></script>
|
||||||
<!-- icon -->
|
<!-- icon -->
|
||||||
|
|
|
@ -12,6 +12,7 @@ return array(
|
||||||
'IPLib\\Address\\IPv6' => $vendorDir . '/mlocati/ip-lib/src/Address/IPv6.php',
|
'IPLib\\Address\\IPv6' => $vendorDir . '/mlocati/ip-lib/src/Address/IPv6.php',
|
||||||
'IPLib\\Address\\Type' => $vendorDir . '/mlocati/ip-lib/src/Address/Type.php',
|
'IPLib\\Address\\Type' => $vendorDir . '/mlocati/ip-lib/src/Address/Type.php',
|
||||||
'IPLib\\Factory' => $vendorDir . '/mlocati/ip-lib/src/Factory.php',
|
'IPLib\\Factory' => $vendorDir . '/mlocati/ip-lib/src/Factory.php',
|
||||||
|
'IPLib\\ParseStringFlag' => $vendorDir . '/mlocati/ip-lib/src/ParseStringFlag.php',
|
||||||
'IPLib\\Range\\AbstractRange' => $vendorDir . '/mlocati/ip-lib/src/Range/AbstractRange.php',
|
'IPLib\\Range\\AbstractRange' => $vendorDir . '/mlocati/ip-lib/src/Range/AbstractRange.php',
|
||||||
'IPLib\\Range\\Pattern' => $vendorDir . '/mlocati/ip-lib/src/Range/Pattern.php',
|
'IPLib\\Range\\Pattern' => $vendorDir . '/mlocati/ip-lib/src/Range/Pattern.php',
|
||||||
'IPLib\\Range\\RangeInterface' => $vendorDir . '/mlocati/ip-lib/src/Range/RangeInterface.php',
|
'IPLib\\Range\\RangeInterface' => $vendorDir . '/mlocati/ip-lib/src/Range/RangeInterface.php',
|
||||||
|
@ -19,7 +20,8 @@ return array(
|
||||||
'IPLib\\Range\\Subnet' => $vendorDir . '/mlocati/ip-lib/src/Range/Subnet.php',
|
'IPLib\\Range\\Subnet' => $vendorDir . '/mlocati/ip-lib/src/Range/Subnet.php',
|
||||||
'IPLib\\Range\\Type' => $vendorDir . '/mlocati/ip-lib/src/Range/Type.php',
|
'IPLib\\Range\\Type' => $vendorDir . '/mlocati/ip-lib/src/Range/Type.php',
|
||||||
'IPLib\\Service\\BinaryMath' => $vendorDir . '/mlocati/ip-lib/src/Service/BinaryMath.php',
|
'IPLib\\Service\\BinaryMath' => $vendorDir . '/mlocati/ip-lib/src/Service/BinaryMath.php',
|
||||||
'IPLib\\Service\\RangesFromBounradyCalculator' => $vendorDir . '/mlocati/ip-lib/src/Service/RangesFromBounradyCalculator.php',
|
'IPLib\\Service\\RangesFromBoundaryCalculator' => $vendorDir . '/mlocati/ip-lib/src/Service/RangesFromBoundaryCalculator.php',
|
||||||
|
'IPLib\\Service\\UnsignedIntegerMath' => $vendorDir . '/mlocati/ip-lib/src/Service/UnsignedIntegerMath.php',
|
||||||
'Identicon\\Generator\\BaseGenerator' => $vendorDir . '/yzalis/identicon/src/Identicon/Generator/BaseGenerator.php',
|
'Identicon\\Generator\\BaseGenerator' => $vendorDir . '/yzalis/identicon/src/Identicon/Generator/BaseGenerator.php',
|
||||||
'Identicon\\Generator\\GdGenerator' => $vendorDir . '/yzalis/identicon/src/Identicon/Generator/GdGenerator.php',
|
'Identicon\\Generator\\GdGenerator' => $vendorDir . '/yzalis/identicon/src/Identicon/Generator/GdGenerator.php',
|
||||||
'Identicon\\Generator\\GeneratorInterface' => $vendorDir . '/yzalis/identicon/src/Identicon/Generator/GeneratorInterface.php',
|
'Identicon\\Generator\\GeneratorInterface' => $vendorDir . '/yzalis/identicon/src/Identicon/Generator/GeneratorInterface.php',
|
||||||
|
@ -41,7 +43,6 @@ return array(
|
||||||
'PrivateBin\\Model\\Comment' => $baseDir . '/lib/Model/Comment.php',
|
'PrivateBin\\Model\\Comment' => $baseDir . '/lib/Model/Comment.php',
|
||||||
'PrivateBin\\Model\\Paste' => $baseDir . '/lib/Model/Paste.php',
|
'PrivateBin\\Model\\Paste' => $baseDir . '/lib/Model/Paste.php',
|
||||||
'PrivateBin\\Persistence\\AbstractPersistence' => $baseDir . '/lib/Persistence/AbstractPersistence.php',
|
'PrivateBin\\Persistence\\AbstractPersistence' => $baseDir . '/lib/Persistence/AbstractPersistence.php',
|
||||||
'PrivateBin\\Persistence\\DataStore' => $baseDir . '/lib/Persistence/DataStore.php',
|
|
||||||
'PrivateBin\\Persistence\\PurgeLimiter' => $baseDir . '/lib/Persistence/PurgeLimiter.php',
|
'PrivateBin\\Persistence\\PurgeLimiter' => $baseDir . '/lib/Persistence/PurgeLimiter.php',
|
||||||
'PrivateBin\\Persistence\\ServerSalt' => $baseDir . '/lib/Persistence/ServerSalt.php',
|
'PrivateBin\\Persistence\\ServerSalt' => $baseDir . '/lib/Persistence/ServerSalt.php',
|
||||||
'PrivateBin\\Persistence\\TrafficLimiter' => $baseDir . '/lib/Persistence/TrafficLimiter.php',
|
'PrivateBin\\Persistence\\TrafficLimiter' => $baseDir . '/lib/Persistence/TrafficLimiter.php',
|
||||||
|
|
|
@ -44,6 +44,7 @@ class ComposerStaticInitDontChange
|
||||||
'IPLib\\Address\\IPv6' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/IPv6.php',
|
'IPLib\\Address\\IPv6' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/IPv6.php',
|
||||||
'IPLib\\Address\\Type' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/Type.php',
|
'IPLib\\Address\\Type' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/Type.php',
|
||||||
'IPLib\\Factory' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Factory.php',
|
'IPLib\\Factory' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Factory.php',
|
||||||
|
'IPLib\\ParseStringFlag' => __DIR__ . '/..' . '/mlocati/ip-lib/src/ParseStringFlag.php',
|
||||||
'IPLib\\Range\\AbstractRange' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Range/AbstractRange.php',
|
'IPLib\\Range\\AbstractRange' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Range/AbstractRange.php',
|
||||||
'IPLib\\Range\\Pattern' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Range/Pattern.php',
|
'IPLib\\Range\\Pattern' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Range/Pattern.php',
|
||||||
'IPLib\\Range\\RangeInterface' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Range/RangeInterface.php',
|
'IPLib\\Range\\RangeInterface' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Range/RangeInterface.php',
|
||||||
|
@ -51,7 +52,8 @@ class ComposerStaticInitDontChange
|
||||||
'IPLib\\Range\\Subnet' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Range/Subnet.php',
|
'IPLib\\Range\\Subnet' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Range/Subnet.php',
|
||||||
'IPLib\\Range\\Type' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Range/Type.php',
|
'IPLib\\Range\\Type' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Range/Type.php',
|
||||||
'IPLib\\Service\\BinaryMath' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Service/BinaryMath.php',
|
'IPLib\\Service\\BinaryMath' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Service/BinaryMath.php',
|
||||||
'IPLib\\Service\\RangesFromBounradyCalculator' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Service/RangesFromBounradyCalculator.php',
|
'IPLib\\Service\\RangesFromBoundaryCalculator' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Service/RangesFromBoundaryCalculator.php',
|
||||||
|
'IPLib\\Service\\UnsignedIntegerMath' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Service/UnsignedIntegerMath.php',
|
||||||
'Identicon\\Generator\\BaseGenerator' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Generator/BaseGenerator.php',
|
'Identicon\\Generator\\BaseGenerator' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Generator/BaseGenerator.php',
|
||||||
'Identicon\\Generator\\GdGenerator' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Generator/GdGenerator.php',
|
'Identicon\\Generator\\GdGenerator' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Generator/GdGenerator.php',
|
||||||
'Identicon\\Generator\\GeneratorInterface' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Generator/GeneratorInterface.php',
|
'Identicon\\Generator\\GeneratorInterface' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Generator/GeneratorInterface.php',
|
||||||
|
@ -73,7 +75,6 @@ class ComposerStaticInitDontChange
|
||||||
'PrivateBin\\Model\\Comment' => __DIR__ . '/../..' . '/lib/Model/Comment.php',
|
'PrivateBin\\Model\\Comment' => __DIR__ . '/../..' . '/lib/Model/Comment.php',
|
||||||
'PrivateBin\\Model\\Paste' => __DIR__ . '/../..' . '/lib/Model/Paste.php',
|
'PrivateBin\\Model\\Paste' => __DIR__ . '/../..' . '/lib/Model/Paste.php',
|
||||||
'PrivateBin\\Persistence\\AbstractPersistence' => __DIR__ . '/../..' . '/lib/Persistence/AbstractPersistence.php',
|
'PrivateBin\\Persistence\\AbstractPersistence' => __DIR__ . '/../..' . '/lib/Persistence/AbstractPersistence.php',
|
||||||
'PrivateBin\\Persistence\\DataStore' => __DIR__ . '/../..' . '/lib/Persistence/DataStore.php',
|
|
||||||
'PrivateBin\\Persistence\\PurgeLimiter' => __DIR__ . '/../..' . '/lib/Persistence/PurgeLimiter.php',
|
'PrivateBin\\Persistence\\PurgeLimiter' => __DIR__ . '/../..' . '/lib/Persistence/PurgeLimiter.php',
|
||||||
'PrivateBin\\Persistence\\ServerSalt' => __DIR__ . '/../..' . '/lib/Persistence/ServerSalt.php',
|
'PrivateBin\\Persistence\\ServerSalt' => __DIR__ . '/../..' . '/lib/Persistence/ServerSalt.php',
|
||||||
'PrivateBin\\Persistence\\TrafficLimiter' => __DIR__ . '/../..' . '/lib/Persistence/TrafficLimiter.php',
|
'PrivateBin\\Persistence\\TrafficLimiter' => __DIR__ . '/../..' . '/lib/Persistence/TrafficLimiter.php',
|
||||||
|
|
|
@ -21,6 +21,8 @@ interface AddressInterface
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
*
|
*
|
||||||
|
* @since 1.14.0
|
||||||
|
*
|
||||||
* @example 32 for IPv4
|
* @example 32 for IPv4
|
||||||
* @example 128 for IPv6
|
* @example 128 for IPv6
|
||||||
*/
|
*/
|
||||||
|
@ -51,6 +53,8 @@ interface AddressInterface
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*
|
*
|
||||||
|
* @since 1.14.0
|
||||||
|
*
|
||||||
* @example For localhost: For IPv4 you'll get '01111111000000000000000000000001' (32 digits), for IPv6 '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001' (128 digits)
|
* @example For localhost: For IPv4 you'll get '01111111000000000000000000000001' (32 digits), for IPv6 '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001' (128 digits)
|
||||||
*/
|
*/
|
||||||
public function getBits();
|
public function getBits();
|
||||||
|
@ -66,6 +70,8 @@ interface AddressInterface
|
||||||
* Get the default RFC reserved range type.
|
* Get the default RFC reserved range type.
|
||||||
*
|
*
|
||||||
* @return int One of the \IPLib\Range\Type::T_... constants
|
* @return int One of the \IPLib\Range\Type::T_... constants
|
||||||
|
*
|
||||||
|
* @since 1.5.0
|
||||||
*/
|
*/
|
||||||
public static function getDefaultReservedRangeType();
|
public static function getDefaultReservedRangeType();
|
||||||
|
|
||||||
|
@ -73,6 +79,8 @@ interface AddressInterface
|
||||||
* Get the RFC reserved ranges (except the ones of type getDefaultReservedRangeType).
|
* Get the RFC reserved ranges (except the ones of type getDefaultReservedRangeType).
|
||||||
*
|
*
|
||||||
* @return \IPLib\Address\AssignedRange[] ranges are sorted
|
* @return \IPLib\Address\AssignedRange[] ranges are sorted
|
||||||
|
*
|
||||||
|
* @since 1.5.0
|
||||||
*/
|
*/
|
||||||
public static function getReservedRanges();
|
public static function getReservedRanges();
|
||||||
|
|
||||||
|
@ -99,10 +107,28 @@ interface AddressInterface
|
||||||
*/
|
*/
|
||||||
public function matches(RangeInterface $range);
|
public function matches(RangeInterface $range);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the address at a certain distance from this address.
|
||||||
|
*
|
||||||
|
* @param int $n the distance of the address (can be negative)
|
||||||
|
*
|
||||||
|
* @return \IPLib\Address\AddressInterface|null return NULL if $n is not an integer or if the final address would be invalid
|
||||||
|
*
|
||||||
|
* @since 1.15.0
|
||||||
|
*
|
||||||
|
* @example passing 1 to the address 127.0.0.1 will result in 127.0.0.2
|
||||||
|
* @example passing -1 to the address 127.0.0.1 will result in 127.0.0.0
|
||||||
|
* @example passing -1 to the address 0.0.0.0 will result in NULL
|
||||||
|
*/
|
||||||
|
public function getAddressAtOffset($n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the address right after this IP address (if available).
|
* Get the address right after this IP address (if available).
|
||||||
*
|
*
|
||||||
* @return \IPLib\Address\AddressInterface|null
|
* @return \IPLib\Address\AddressInterface|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\Address\AddressInterface::getAddressAtOffset()
|
||||||
|
* @since 1.4.0
|
||||||
*/
|
*/
|
||||||
public function getNextAddress();
|
public function getNextAddress();
|
||||||
|
|
||||||
|
@ -110,6 +136,9 @@ interface AddressInterface
|
||||||
* Get the address right before this IP address (if available).
|
* Get the address right before this IP address (if available).
|
||||||
*
|
*
|
||||||
* @return \IPLib\Address\AddressInterface|null
|
* @return \IPLib\Address\AddressInterface|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\Address\AddressInterface::getAddressAtOffset()
|
||||||
|
* @since 1.4.0
|
||||||
*/
|
*/
|
||||||
public function getPreviousAddress();
|
public function getPreviousAddress();
|
||||||
|
|
||||||
|
@ -118,6 +147,8 @@ interface AddressInterface
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*
|
*
|
||||||
|
* @since 1.12.0
|
||||||
|
*
|
||||||
* @example for IPv4 it returns something like x.x.x.x.in-addr.arpa
|
* @example for IPv4 it returns something like x.x.x.x.in-addr.arpa
|
||||||
* @example for IPv6 it returns something like x.x.x.x..x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.ip6.arpa
|
* @example for IPv6 it returns something like x.x.x.x..x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.ip6.arpa
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -6,6 +6,8 @@ use IPLib\Range\RangeInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an IP address range with an assigned range type.
|
* Represents an IP address range with an assigned range type.
|
||||||
|
*
|
||||||
|
* @since 1.5.0
|
||||||
*/
|
*/
|
||||||
class AssignedRange
|
class AssignedRange
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace IPLib\Address;
|
namespace IPLib\Address;
|
||||||
|
|
||||||
|
use IPLib\ParseStringFlag;
|
||||||
use IPLib\Range\RangeInterface;
|
use IPLib\Range\RangeInterface;
|
||||||
use IPLib\Range\Subnet;
|
use IPLib\Range\Subnet;
|
||||||
use IPLib\Range\Type as RangeType;
|
use IPLib\Range\Type as RangeType;
|
||||||
|
@ -46,7 +47,7 @@ class IPv4 implements AddressInterface
|
||||||
*
|
*
|
||||||
* @var array|null
|
* @var array|null
|
||||||
*/
|
*/
|
||||||
private static $reservedRanges = null;
|
private static $reservedRanges;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the instance.
|
* Initializes the instance.
|
||||||
|
@ -82,52 +83,94 @@ class IPv4 implements AddressInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a string and returns an IPv4 instance if the string is valid, or null otherwise.
|
* @deprecated since 1.17.0: use the parseString() method instead.
|
||||||
|
* For upgrading:
|
||||||
|
* - if $mayIncludePort is true, use the ParseStringFlag::MAY_INCLUDE_PORT flag
|
||||||
|
* - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
|
||||||
*
|
*
|
||||||
* @param string|mixed $address the address to parse
|
* @param string|mixed $address the address to parse
|
||||||
* @param bool $mayIncludePort set to false to avoid parsing addresses with ports
|
* @param bool $mayIncludePort
|
||||||
* @param bool $supportNonDecimalIPv4 set to true to support parsing non decimal (that is, octal and hexadecimal) IPv4 addresses
|
* @param bool $supportNonDecimalIPv4
|
||||||
*
|
*
|
||||||
* @return static|null
|
* @return static|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\Address\IPv4::parseString()
|
||||||
|
* @since 1.1.0 added the $mayIncludePort argument
|
||||||
|
* @since 1.10.0 added the $supportNonDecimalIPv4 argument
|
||||||
*/
|
*/
|
||||||
public static function fromString($address, $mayIncludePort = true, $supportNonDecimalIPv4 = false)
|
public static function fromString($address, $mayIncludePort = true, $supportNonDecimalIPv4 = false)
|
||||||
{
|
{
|
||||||
if (!is_string($address) || !strpos($address, '.')) {
|
return static::parseString($address, 0 | ($mayIncludePort ? ParseStringFlag::MAY_INCLUDE_PORT : 0) | ($supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 int $flags A combination or zero or more flags
|
||||||
|
*
|
||||||
|
* @return static|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\ParseStringFlag
|
||||||
|
* @since 1.17.0
|
||||||
|
*/
|
||||||
|
public static function parseString($address, $flags = 0)
|
||||||
|
{
|
||||||
|
if (!is_string($address)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$rxChunk = '0?[0-9]{1,3}';
|
$flags = (int) $flags;
|
||||||
if ($supportNonDecimalIPv4) {
|
$matches = null;
|
||||||
$rxChunk = "(?:0[Xx]0*[0-9A-Fa-f]{1,2})|(?:{$rxChunk})";
|
if ($flags & ParseStringFlag::ADDRESS_MAYBE_RDNS) {
|
||||||
|
if (preg_match('/^([12]?[0-9]{1,2}\.[12]?[0-9]{1,2}\.[12]?[0-9]{1,2}\.[12]?[0-9]{1,2})\.in-addr\.arpa\.?$/i', $address, $matches)) {
|
||||||
|
$address = implode('.', array_reverse(explode('.', $matches[1])));
|
||||||
|
$flags = $flags & ~(ParseStringFlag::IPV4_MAYBE_NON_DECIMAL | ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$rx = "0*?({$rxChunk})\.0*?({$rxChunk})\.0*?({$rxChunk})\.0*?({$rxChunk})";
|
if ($flags & ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED) {
|
||||||
if ($mayIncludePort) {
|
if (strpos($address, '.') === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$lengthNonHex = '{1,11}';
|
||||||
|
$lengthHex = '{1,8}';
|
||||||
|
$chunk234Optional = true;
|
||||||
|
} else {
|
||||||
|
if (!strpos($address, '.')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$lengthNonHex = '{1,3}';
|
||||||
|
$lengthHex = '{1,2}';
|
||||||
|
$chunk234Optional = false;
|
||||||
|
}
|
||||||
|
$rxChunk1 = "0?[0-9]{$lengthNonHex}";
|
||||||
|
if ($flags & ParseStringFlag::IPV4_MAYBE_NON_DECIMAL) {
|
||||||
|
$rxChunk1 = "(?:0[Xx]0*[0-9A-Fa-f]{$lengthHex})|(?:{$rxChunk1})";
|
||||||
|
$onlyDecimal = false;
|
||||||
|
} else {
|
||||||
|
$onlyDecimal = true;
|
||||||
|
}
|
||||||
|
$rxChunk1 = "0*?({$rxChunk1})";
|
||||||
|
$rxChunk234 = "\.{$rxChunk1}";
|
||||||
|
if ($chunk234Optional) {
|
||||||
|
$rxChunk234 = "(?:{$rxChunk234})?";
|
||||||
|
}
|
||||||
|
$rx = "{$rxChunk1}{$rxChunk234}{$rxChunk234}{$rxChunk234}";
|
||||||
|
if ($flags & ParseStringFlag::MAY_INCLUDE_PORT) {
|
||||||
$rx .= '(?::\d+)?';
|
$rx .= '(?::\d+)?';
|
||||||
}
|
}
|
||||||
$matches = null;
|
|
||||||
if (!preg_match('/^' . $rx . '$/', $address, $matches)) {
|
if (!preg_match('/^' . $rx . '$/', $address, $matches)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
$math = new \IPLib\Service\UnsignedIntegerMath();
|
||||||
$nums = array();
|
$nums = array();
|
||||||
for ($i = 1; $i <= 4; $i++) {
|
$maxChunkIndex = count($matches) - 1;
|
||||||
$s = $matches[$i];
|
for ($i = 1; $i <= $maxChunkIndex; $i++) {
|
||||||
if ($supportNonDecimalIPv4) {
|
$numBytes = $i === $maxChunkIndex ? 5 - $i : 1;
|
||||||
if (stripos($s, '0x') === 0) {
|
$chunkBytes = $math->getBytes($matches[$i], $numBytes, $onlyDecimal);
|
||||||
$n = hexdec(substr($s, 2));
|
if ($chunkBytes === null) {
|
||||||
} elseif ($s[0] === '0') {
|
|
||||||
if (!preg_match('/^[0-7]+$/', $s)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
$n = octdec(substr($s, 1));
|
|
||||||
} else {
|
|
||||||
$n = (int) $s;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$n = (int) $s;
|
|
||||||
}
|
|
||||||
if ($n < 0 || $n > 255) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$nums[] = (string) $n;
|
$nums = array_merge($nums, $chunkBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new static(implode('.', $nums));
|
return new static(implode('.', $nums));
|
||||||
|
@ -179,6 +222,8 @@ class IPv4 implements AddressInterface
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*
|
*
|
||||||
|
* @since 1.10.0
|
||||||
|
*
|
||||||
* @example if $long == false: if the decimal representation is '0.7.8.255': '0.7.010.0377'
|
* @example if $long == false: if the decimal representation is '0.7.8.255': '0.7.010.0377'
|
||||||
* @example if $long == true: if the decimal representation is '0.7.8.255': '0000.0007.0010.0377'
|
* @example if $long == true: if the decimal representation is '0.7.8.255': '0000.0007.0010.0377'
|
||||||
*/
|
*/
|
||||||
|
@ -203,6 +248,8 @@ class IPv4 implements AddressInterface
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*
|
*
|
||||||
|
* @since 1.10.0
|
||||||
|
*
|
||||||
* @example if $long == false: if the decimal representation is '0.9.10.255': '0.9.0xa.0xff'
|
* @example if $long == false: if the decimal representation is '0.9.10.255': '0.9.0xa.0xff'
|
||||||
* @example if $long == true: if the decimal representation is '0.9.10.255': '0x00.0x09.0x0a.0xff'
|
* @example if $long == true: if the decimal representation is '0.9.10.255': '0x00.0x09.0x0a.0xff'
|
||||||
*/
|
*/
|
||||||
|
@ -318,10 +365,10 @@ class IPv4 implements AddressInterface
|
||||||
$exceptions = array();
|
$exceptions = array();
|
||||||
if (isset($data[1])) {
|
if (isset($data[1])) {
|
||||||
foreach ($data[1] as $exceptionRange => $exceptionType) {
|
foreach ($data[1] as $exceptionRange => $exceptionType) {
|
||||||
$exceptions[] = new AssignedRange(Subnet::fromString($exceptionRange), $exceptionType);
|
$exceptions[] = new AssignedRange(Subnet::parseString($exceptionRange), $exceptionType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$reservedRanges[] = new AssignedRange(Subnet::fromString($range), $data[0], $exceptions);
|
$reservedRanges[] = new AssignedRange(Subnet::parseString($range), $data[0], $exceptions);
|
||||||
}
|
}
|
||||||
self::$reservedRanges = $reservedRanges;
|
self::$reservedRanges = $reservedRanges;
|
||||||
}
|
}
|
||||||
|
@ -359,13 +406,15 @@ class IPv4 implements AddressInterface
|
||||||
{
|
{
|
||||||
$myBytes = $this->getBytes();
|
$myBytes = $this->getBytes();
|
||||||
|
|
||||||
return IPv6::fromString('2002:' . sprintf('%02x', $myBytes[0]) . sprintf('%02x', $myBytes[1]) . ':' . sprintf('%02x', $myBytes[2]) . sprintf('%02x', $myBytes[3]) . '::');
|
return IPv6::parseString('2002:' . sprintf('%02x', $myBytes[0]) . sprintf('%02x', $myBytes[1]) . ':' . sprintf('%02x', $myBytes[2]) . sprintf('%02x', $myBytes[3]) . '::');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an IPv6 representation of this address (in IPv6 IPv4-mapped notation).
|
* Create an IPv6 representation of this address (in IPv6 IPv4-mapped notation).
|
||||||
*
|
*
|
||||||
* @return \IPLib\Address\IPv6
|
* @return \IPLib\Address\IPv6
|
||||||
|
*
|
||||||
|
* @since 1.11.0
|
||||||
*/
|
*/
|
||||||
public function toIPv6IPv4Mapped()
|
public function toIPv6IPv4Mapped()
|
||||||
{
|
{
|
||||||
|
@ -400,6 +449,37 @@ class IPv4 implements AddressInterface
|
||||||
return $range->contains($this);
|
return $range->contains($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @see \IPLib\Address\AddressInterface::getAddressAtOffset()
|
||||||
|
*/
|
||||||
|
public function getAddressAtOffset($n)
|
||||||
|
{
|
||||||
|
if (!is_int($n)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$boundary = 256;
|
||||||
|
$mod = $n;
|
||||||
|
$bytes = $this->getBytes();
|
||||||
|
for ($i = count($bytes) - 1; $i >= 0; $i--) {
|
||||||
|
$tmp = ($bytes[$i] + $mod) % $boundary;
|
||||||
|
$mod = (int) floor(($bytes[$i] + $mod) / $boundary);
|
||||||
|
if ($tmp < 0) {
|
||||||
|
$tmp += $boundary;
|
||||||
|
}
|
||||||
|
|
||||||
|
$bytes[$i] = $tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($mod !== 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static::fromBytes($bytes);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*
|
*
|
||||||
|
@ -407,22 +487,7 @@ class IPv4 implements AddressInterface
|
||||||
*/
|
*/
|
||||||
public function getNextAddress()
|
public function getNextAddress()
|
||||||
{
|
{
|
||||||
$overflow = false;
|
return $this->getAddressAtOffset(1);
|
||||||
$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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -432,22 +497,7 @@ class IPv4 implements AddressInterface
|
||||||
*/
|
*/
|
||||||
public function getPreviousAddress()
|
public function getPreviousAddress()
|
||||||
{
|
{
|
||||||
$overflow = false;
|
return $this->getAddressAtOffset(-1);
|
||||||
$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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace IPLib\Address;
|
namespace IPLib\Address;
|
||||||
|
|
||||||
|
use IPLib\ParseStringFlag;
|
||||||
use IPLib\Range\RangeInterface;
|
use IPLib\Range\RangeInterface;
|
||||||
use IPLib\Range\Subnet;
|
use IPLib\Range\Subnet;
|
||||||
use IPLib\Range\Type as RangeType;
|
use IPLib\Range\Type as RangeType;
|
||||||
|
@ -55,7 +56,7 @@ class IPv6 implements AddressInterface
|
||||||
*
|
*
|
||||||
* @var array|null
|
* @var array|null
|
||||||
*/
|
*/
|
||||||
private static $reservedRanges = null;
|
private static $reservedRanges;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the instance.
|
* Initializes the instance.
|
||||||
|
@ -92,32 +93,69 @@ class IPv6 implements AddressInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a string and returns an IPv6 instance if the string is valid, or null otherwise.
|
* @deprecated since 1.17.0: use the parseString() method instead.
|
||||||
|
* For upgrading:
|
||||||
|
* - if $mayIncludePort is true, use the ParseStringFlag::MAY_INCLUDE_PORT flag
|
||||||
|
* - if $mayIncludeZoneID is true, use the ParseStringFlag::MAY_INCLUDE_ZONEID flag
|
||||||
*
|
*
|
||||||
* @param string|mixed $address the address to parse
|
* @param string|mixed $address
|
||||||
* @param bool $mayIncludePort set to false to avoid parsing addresses with ports
|
* @param bool $mayIncludePort
|
||||||
* @param bool $mayIncludeZoneID set to false to avoid parsing addresses with zone IDs (see RFC 4007)
|
* @param bool $mayIncludeZoneID
|
||||||
*
|
*
|
||||||
* @return static|null
|
* @return static|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\Address\IPv6::parseString()
|
||||||
|
* @since 1.1.0 added the $mayIncludePort argument
|
||||||
|
* @since 1.3.0 added the $mayIncludeZoneID argument
|
||||||
*/
|
*/
|
||||||
public static function fromString($address, $mayIncludePort = true, $mayIncludeZoneID = true)
|
public static function fromString($address, $mayIncludePort = true, $mayIncludeZoneID = true)
|
||||||
{
|
{
|
||||||
|
return static::parseString($address, 0 | ($mayIncludePort ? ParseStringFlag::MAY_INCLUDE_PORT : 0) | ($mayIncludeZoneID ? ParseStringFlag::MAY_INCLUDE_ZONEID : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 int $flags A combination or zero or more flags
|
||||||
|
*
|
||||||
|
* @return static|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\ParseStringFlag
|
||||||
|
* @since 1.17.0
|
||||||
|
*/
|
||||||
|
public static function parseString($address, $flags = 0)
|
||||||
|
{
|
||||||
|
if (!is_string($address)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$matches = null;
|
||||||
|
$flags = (int) $flags;
|
||||||
|
if ($flags & ParseStringFlag::ADDRESS_MAYBE_RDNS) {
|
||||||
|
if (preg_match('/^([0-9a-f](?:\.[0-9a-f]){31})\.ip6\.arpa\.?/i', $address, $matches)) {
|
||||||
|
$nibbles = array_reverse(explode('.', $matches[1]));
|
||||||
|
$quibbles = array();
|
||||||
|
foreach (array_chunk($nibbles, 4) as $n) {
|
||||||
|
$quibbles[] = implode('', $n);
|
||||||
|
}
|
||||||
|
$address = implode(':', $quibbles);
|
||||||
|
}
|
||||||
|
}
|
||||||
$result = null;
|
$result = null;
|
||||||
if (is_string($address) && strpos($address, ':') !== false && strpos($address, ':::') === false) {
|
if (is_string($address) && strpos($address, ':') !== false && strpos($address, ':::') === false) {
|
||||||
$matches = null;
|
if ($flags & ParseStringFlag::MAY_INCLUDE_PORT && $address[0] === '[' && preg_match('/^\[(.+)]:\d+$/', $address, $matches)) {
|
||||||
if ($mayIncludePort && $address[0] === '[' && preg_match('/^\[(.+)]:\d+$/', $address, $matches)) {
|
|
||||||
$address = $matches[1];
|
$address = $matches[1];
|
||||||
}
|
}
|
||||||
if ($mayIncludeZoneID) {
|
if ($flags & ParseStringFlag::MAY_INCLUDE_ZONEID) {
|
||||||
$percentagePos = strpos($address, '%');
|
$percentagePos = strpos($address, '%');
|
||||||
if ($percentagePos > 0) {
|
if ($percentagePos > 0) {
|
||||||
$address = substr($address, 0, $percentagePos);
|
$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)) {
|
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);
|
$address6 = static::parseString($matches[1] . '0:0');
|
||||||
if ($address6 !== null) {
|
if ($address6 !== null) {
|
||||||
$address4 = IPv4::fromString($matches[2], false);
|
$address4 = IPv4::parseString($matches[2]);
|
||||||
if ($address4 !== null) {
|
if ($address4 !== null) {
|
||||||
$bytes4 = $address4->getBytes();
|
$bytes4 = $address4->getBytes();
|
||||||
$address6->longAddress = substr($address6->longAddress, 0, -9) . sprintf('%02x%02x:%02x%02x', $bytes4[0], $bytes4[1], $bytes4[2], $bytes4[3]);
|
$address6->longAddress = substr($address6->longAddress, 0, -9) . sprintf('%02x%02x:%02x%02x', $bytes4[0], $bytes4[1], $bytes4[2], $bytes4[3]);
|
||||||
|
@ -401,10 +439,10 @@ class IPv6 implements AddressInterface
|
||||||
$exceptions = array();
|
$exceptions = array();
|
||||||
if (isset($data[1])) {
|
if (isset($data[1])) {
|
||||||
foreach ($data[1] as $exceptionRange => $exceptionType) {
|
foreach ($data[1] as $exceptionRange => $exceptionType) {
|
||||||
$exceptions[] = new AssignedRange(Subnet::fromString($exceptionRange), $exceptionType);
|
$exceptions[] = new AssignedRange(Subnet::parseString($exceptionRange), $exceptionType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$reservedRanges[] = new AssignedRange(Subnet::fromString($range), $data[0], $exceptions);
|
$reservedRanges[] = new AssignedRange(Subnet::parseString($range), $data[0], $exceptions);
|
||||||
}
|
}
|
||||||
self::$reservedRanges = $reservedRanges;
|
self::$reservedRanges = $reservedRanges;
|
||||||
}
|
}
|
||||||
|
@ -471,6 +509,7 @@ class IPv6 implements AddressInterface
|
||||||
* @example '0000:0000:0000:0000:0000:0000:013.001.068.003' when $ipV6Long and $ipV4Long are 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.
|
* @see https://tools.ietf.org/html/rfc4291#section-2.2 point 3.
|
||||||
|
* @since 1.9.0
|
||||||
*/
|
*/
|
||||||
public function toMixedIPv6IPv4String($ipV6Long = false, $ipV4Long = false)
|
public function toMixedIPv6IPv4String($ipV6Long = false, $ipV4Long = false)
|
||||||
{
|
{
|
||||||
|
@ -503,6 +542,37 @@ class IPv6 implements AddressInterface
|
||||||
return $range->contains($this);
|
return $range->contains($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @see \IPLib\Address\AddressInterface::getAddressAtOffset()
|
||||||
|
*/
|
||||||
|
public function getAddressAtOffset($n)
|
||||||
|
{
|
||||||
|
if (!is_int($n)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$boundary = 0x10000;
|
||||||
|
$mod = $n;
|
||||||
|
$words = $this->getWords();
|
||||||
|
for ($i = count($words) - 1; $i >= 0; $i--) {
|
||||||
|
$tmp = ($words[$i] + $mod) % $boundary;
|
||||||
|
$mod = (int) floor(($words[$i] + $mod) / $boundary);
|
||||||
|
if ($tmp < 0) {
|
||||||
|
$tmp += $boundary;
|
||||||
|
}
|
||||||
|
|
||||||
|
$words[$i] = $tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($mod !== 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static::fromWords($words);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*
|
*
|
||||||
|
@ -510,22 +580,7 @@ class IPv6 implements AddressInterface
|
||||||
*/
|
*/
|
||||||
public function getNextAddress()
|
public function getNextAddress()
|
||||||
{
|
{
|
||||||
$overflow = false;
|
return $this->getAddressAtOffset(1);
|
||||||
$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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -535,22 +590,7 @@ class IPv6 implements AddressInterface
|
||||||
*/
|
*/
|
||||||
public function getPreviousAddress()
|
public function getPreviousAddress()
|
||||||
{
|
{
|
||||||
$overflow = false;
|
return $this->getAddressAtOffset(-1);
|
||||||
$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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -27,6 +27,8 @@ class Type
|
||||||
* @param int $type
|
* @param int $type
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
|
*
|
||||||
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public static function getName($type)
|
public static function getName($type)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace IPLib;
|
||||||
|
|
||||||
use IPLib\Address\AddressInterface;
|
use IPLib\Address\AddressInterface;
|
||||||
use IPLib\Range\Subnet;
|
use IPLib\Range\Subnet;
|
||||||
use IPLib\Service\RangesFromBounradyCalculator;
|
use IPLib\Service\RangesFromBoundaryCalculator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory methods to build class instances.
|
* Factory methods to build class instances.
|
||||||
|
@ -12,23 +12,48 @@ use IPLib\Service\RangesFromBounradyCalculator;
|
||||||
class Factory
|
class Factory
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Parse an IP address string.
|
* @deprecated since 1.17.0: use the parseAddressString() method instead.
|
||||||
|
* For upgrading:
|
||||||
|
* - if $mayIncludePort is true, use the ParseStringFlag::MAY_INCLUDE_PORT flag
|
||||||
|
* - if $mayIncludeZoneID is true, use the ParseStringFlag::MAY_INCLUDE_ZONEID flag
|
||||||
|
* - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
|
||||||
*
|
*
|
||||||
* @param string $address the address to parse
|
* @param string|mixed $address
|
||||||
* @param bool $mayIncludePort set to false to avoid parsing addresses with ports
|
* @param bool $mayIncludePort
|
||||||
* @param bool $mayIncludeZoneID set to false to avoid parsing IPv6 addresses with zone IDs (see RFC 4007)
|
* @param bool $mayIncludeZoneID
|
||||||
* @param bool $supportNonDecimalIPv4 set to true to support parsing non decimal (that is, octal and hexadecimal) IPv4 addresses
|
* @param bool $supportNonDecimalIPv4
|
||||||
*
|
*
|
||||||
* @return \IPLib\Address\AddressInterface|null
|
* @return \IPLib\Address\AddressInterface|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\Factory::parseAddressString()
|
||||||
|
* @since 1.1.0 added the $mayIncludePort argument
|
||||||
|
* @since 1.3.0 added the $mayIncludeZoneID argument
|
||||||
|
* @since 1.10.0 added the $supportNonDecimalIPv4 argument
|
||||||
*/
|
*/
|
||||||
public static function addressFromString($address, $mayIncludePort = true, $mayIncludeZoneID = true, $supportNonDecimalIPv4 = false)
|
public static function addressFromString($address, $mayIncludePort = true, $mayIncludeZoneID = true, $supportNonDecimalIPv4 = false)
|
||||||
|
{
|
||||||
|
return static::parseAddressString($address, 0 + ($mayIncludePort ? ParseStringFlag::MAY_INCLUDE_PORT : 0) + ($mayIncludeZoneID ? ParseStringFlag::MAY_INCLUDE_ZONEID : 0) + ($supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse an IP address string.
|
||||||
|
*
|
||||||
|
* @param string|mixed $address the address to parse
|
||||||
|
* @param int $flags A combination or zero or more flags
|
||||||
|
*
|
||||||
|
* @return \IPLib\Address\AddressInterface|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\ParseStringFlag
|
||||||
|
* @since 1.17.0
|
||||||
|
*/
|
||||||
|
public static function parseAddressString($address, $flags = 0)
|
||||||
{
|
{
|
||||||
$result = null;
|
$result = null;
|
||||||
if ($result === null) {
|
if ($result === null) {
|
||||||
$result = Address\IPv4::fromString($address, $mayIncludePort, $supportNonDecimalIPv4);
|
$result = Address\IPv4::parseString($address, $flags);
|
||||||
}
|
}
|
||||||
if ($result === null) {
|
if ($result === null) {
|
||||||
$result = Address\IPv6::fromString($address, $mayIncludePort, $mayIncludeZoneID);
|
$result = Address\IPv6::parseString($address, $flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
|
@ -54,59 +79,125 @@ class Factory
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated since 1.17.0: use the parseRangeString() method instead.
|
||||||
|
* For upgrading:
|
||||||
|
* - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
|
||||||
|
*
|
||||||
|
* @param string|mixed $address
|
||||||
|
* @param bool $supportNonDecimalIPv4
|
||||||
|
*
|
||||||
|
* @return \IPLib\Address\AddressInterface|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\Factory::parseRangeString()
|
||||||
|
* @since 1.10.0 added the $supportNonDecimalIPv4 argument
|
||||||
|
*/
|
||||||
|
public static function rangeFromString($address, $supportNonDecimalIPv4 = false)
|
||||||
|
{
|
||||||
|
return static::parseRangeString($address, $supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse an IP range string.
|
* Parse an IP range string.
|
||||||
*
|
*
|
||||||
* @param string $range
|
* @param string $range
|
||||||
* @param bool $supportNonDecimalIPv4 set to true to support parsing non decimal (that is, octal and hexadecimal) IPv4 addresses
|
* @param int $flags A combination or zero or more flags
|
||||||
*
|
*
|
||||||
* @return \IPLib\Range\RangeInterface|null
|
* @return \IPLib\Range\RangeInterface|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\ParseStringFlag
|
||||||
|
* @since 1.17.0
|
||||||
*/
|
*/
|
||||||
public static function rangeFromString($range, $supportNonDecimalIPv4 = false)
|
public static function parseRangeString($range, $flags = 0)
|
||||||
{
|
{
|
||||||
$result = null;
|
$result = null;
|
||||||
if ($result === null) {
|
if ($result === null) {
|
||||||
$result = Range\Subnet::fromString($range, $supportNonDecimalIPv4);
|
$result = Range\Subnet::parseString($range, $flags);
|
||||||
}
|
}
|
||||||
if ($result === null) {
|
if ($result === null) {
|
||||||
$result = Range\Pattern::fromString($range, $supportNonDecimalIPv4);
|
$result = Range\Pattern::parseString($range, $flags);
|
||||||
}
|
}
|
||||||
if ($result === null) {
|
if ($result === null) {
|
||||||
$result = Range\Single::fromString($range, $supportNonDecimalIPv4);
|
$result = Range\Single::parseString($range, $flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the smallest address range that comprises two addresses.
|
* @deprecated since 1.17.0: use the getRangeFromBoundaries() method instead.
|
||||||
|
* For upgrading:
|
||||||
|
* - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
|
||||||
*
|
*
|
||||||
* @param string|\IPLib\Address\AddressInterface $from
|
* @param string|\IPLib\Address\AddressInterface|mixed $from
|
||||||
* @param string|\IPLib\Address\AddressInterface $to
|
* @param string|\IPLib\Address\AddressInterface|mixed $to
|
||||||
* @param bool $supportNonDecimalIPv4 set to true to support parsing non decimal (that is, octal and hexadecimal) IPv4 addresses
|
* @param bool $supportNonDecimalIPv4
|
||||||
*
|
*
|
||||||
* @return \IPLib\Range\RangeInterface|null return NULL if $from and/or $to are invalid addresses, or if both are NULL or empty strings, or if they are addresses of different types
|
* @return \IPLib\Address\AddressInterface|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\Factory::getRangeFromBoundaries()
|
||||||
|
* @since 1.2.0
|
||||||
|
* @since 1.10.0 added the $supportNonDecimalIPv4 argument
|
||||||
*/
|
*/
|
||||||
public static function rangeFromBoundaries($from, $to, $supportNonDecimalIPv4 = false)
|
public static function rangeFromBoundaries($from, $to, $supportNonDecimalIPv4 = false)
|
||||||
{
|
{
|
||||||
list($from, $to) = self::parseBoundaries($from, $to, $supportNonDecimalIPv4);
|
return static::getRangeFromBoundaries($from, $to, ParseStringFlag::MAY_INCLUDE_PORT | ParseStringFlag::MAY_INCLUDE_ZONEID | ($supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the smallest address range that comprises two addresses.
|
||||||
|
*
|
||||||
|
* @param string|\IPLib\Address\AddressInterface|mixed $from
|
||||||
|
* @param string|\IPLib\Address\AddressInterface|mixed $to
|
||||||
|
* @param int $flags A combination or zero or more flags
|
||||||
|
*
|
||||||
|
* @return \IPLib\Range\RangeInterface|null return NULL if $from and/or $to are invalid addresses, or if both are NULL or empty strings, or if they are addresses of different types
|
||||||
|
*
|
||||||
|
* @see \IPLib\ParseStringFlag
|
||||||
|
* @since 1.17.0
|
||||||
|
*/
|
||||||
|
public static function getRangeFromBoundaries($from, $to, $flags = 0)
|
||||||
|
{
|
||||||
|
list($from, $to) = self::parseBoundaries($from, $to, $flags);
|
||||||
|
|
||||||
return $from === false || $to === false ? null : static::rangeFromBoundaryAddresses($from, $to);
|
return $from === false || $to === false ? null : static::rangeFromBoundaryAddresses($from, $to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated since 1.17.0: use the getRangesFromBoundaries() method instead.
|
||||||
|
* For upgrading:
|
||||||
|
* - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
|
||||||
|
*
|
||||||
|
* @param string|\IPLib\Address\AddressInterface|mixed $from
|
||||||
|
* @param string|\IPLib\Address\AddressInterface|mixed $to
|
||||||
|
* @param bool $supportNonDecimalIPv4
|
||||||
|
*
|
||||||
|
* @return \IPLib\Range\Subnet[]|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\Factory::getRangesFromBoundaries()
|
||||||
|
* @since 1.14.0
|
||||||
|
*/
|
||||||
|
public static function rangesFromBoundaries($from, $to, $supportNonDecimalIPv4 = false)
|
||||||
|
{
|
||||||
|
return static::getRangesFromBoundaries($from, $to, ParseStringFlag::MAY_INCLUDE_PORT | ParseStringFlag::MAY_INCLUDE_ZONEID | ($supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a list of Range instances that exactly describes all the addresses between the two provided addresses.
|
* Create a list of Range instances that exactly describes all the addresses between the two provided addresses.
|
||||||
*
|
*
|
||||||
* @param string|\IPLib\Address\AddressInterface $from
|
* @param string|\IPLib\Address\AddressInterface $from
|
||||||
* @param string|\IPLib\Address\AddressInterface $to
|
* @param string|\IPLib\Address\AddressInterface $to
|
||||||
* @param bool $supportNonDecimalIPv4 set to true to support parsing non decimal (that is, octal and hexadecimal) IPv4 addresses
|
* @param int $flags A combination or zero or more flags
|
||||||
*
|
*
|
||||||
* @return \IPLib\Range\Subnet[]|null return NULL if $from and/or $to are invalid addresses, or if both are NULL or empty strings, or if they are addresses of different types
|
* @return \IPLib\Range\Subnet[]|null return NULL if $from and/or $to are invalid addresses, or if both are NULL or empty strings, or if they are addresses of different types
|
||||||
|
*
|
||||||
|
* @see \IPLib\ParseStringFlag
|
||||||
|
* @since 1.17.0
|
||||||
*/
|
*/
|
||||||
public static function rangesFromBoundaries($from, $to, $supportNonDecimalIPv4 = false)
|
public static function getRangesFromBoundaries($from, $to, $flags = 0)
|
||||||
{
|
{
|
||||||
list($from, $to) = self::parseBoundaries($from, $to, $supportNonDecimalIPv4);
|
list($from, $to) = self::parseBoundaries($from, $to, $flags);
|
||||||
if (($from === false || $to === false) || ($from === null && $to === null)) {
|
if ($from === false || $to === false || ($from === null && $to === null)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if ($from === null || $to === null) {
|
if ($from === null || $to === null) {
|
||||||
|
@ -118,7 +209,7 @@ class Factory
|
||||||
if ($to->getNumberOfBits() !== $numberOfBits) {
|
if ($to->getNumberOfBits() !== $numberOfBits) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$calculator = new RangesFromBounradyCalculator($numberOfBits);
|
$calculator = new RangesFromBoundaryCalculator($numberOfBits);
|
||||||
|
|
||||||
return $calculator->getRanges($from, $to);
|
return $calculator->getRanges($from, $to);
|
||||||
}
|
}
|
||||||
|
@ -128,6 +219,8 @@ class Factory
|
||||||
* @param \IPLib\Address\AddressInterface $to
|
* @param \IPLib\Address\AddressInterface $to
|
||||||
*
|
*
|
||||||
* @return \IPLib\Range\RangeInterface|null
|
* @return \IPLib\Range\RangeInterface|null
|
||||||
|
*
|
||||||
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
protected static function rangeFromBoundaryAddresses(AddressInterface $from = null, AddressInterface $to = null)
|
protected static function rangeFromBoundaryAddresses(AddressInterface $from = null, AddressInterface $to = null)
|
||||||
{
|
{
|
||||||
|
@ -163,7 +256,7 @@ class Factory
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$result = static::rangeFromString($from->toString(true) . '/' . (string) $sameBits);
|
$result = static::parseRangeString($from->toString() . '/' . (string) $sameBits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,11 +267,11 @@ class Factory
|
||||||
/**
|
/**
|
||||||
* @param string|\IPLib\Address\AddressInterface $from
|
* @param string|\IPLib\Address\AddressInterface $from
|
||||||
* @param string|\IPLib\Address\AddressInterface $to
|
* @param string|\IPLib\Address\AddressInterface $to
|
||||||
* @param bool $supportNonDecimalIPv4
|
* @param int $flags
|
||||||
*
|
*
|
||||||
* @return \IPLib\Address\AddressInterface[]|null[]|false[]
|
* @return \IPLib\Address\AddressInterface[]|null[]|false[]
|
||||||
*/
|
*/
|
||||||
private static function parseBoundaries($from, $to, $supportNonDecimalIPv4 = false)
|
private static function parseBoundaries($from, $to, $flags = 0)
|
||||||
{
|
{
|
||||||
$result = array();
|
$result = array();
|
||||||
foreach (array('from', 'to') as $param) {
|
foreach (array('from', 'to') as $param) {
|
||||||
|
@ -188,7 +281,7 @@ class Factory
|
||||||
if ($value === '') {
|
if ($value === '') {
|
||||||
$value = null;
|
$value = null;
|
||||||
} else {
|
} else {
|
||||||
$value = static::addressFromString($value, true, true, $supportNonDecimalIPv4);
|
$value = static::parseAddressString($value, $flags);
|
||||||
if ($value === null) {
|
if ($value === null) {
|
||||||
$value = false;
|
$value = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace IPLib;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags for the parseString() methods.
|
||||||
|
*
|
||||||
|
* @since 1.17.0
|
||||||
|
*/
|
||||||
|
class ParseStringFlag
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Use this flag if the input string may include the port.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
const MAY_INCLUDE_PORT = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this flag if the input string may include a zone ID.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
const MAY_INCLUDE_ZONEID = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this flag if IPv4 addresses may be in decimal/octal/hexadecimal format.
|
||||||
|
* This notation is accepted by the implementation of inet_aton and inet_addr of the libc implementation of GNU, Windows and Mac (but not Musl), but not by inet_pton and ip2long.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*
|
||||||
|
* @example 1.08.0x10.0 => 5.0.0.1
|
||||||
|
* @example 5.256 => 5.0.1.0
|
||||||
|
* @example 5.0.256 => 5.0.1.0
|
||||||
|
* @example 123456789 => 7.91.205.21
|
||||||
|
*/
|
||||||
|
const IPV4_MAYBE_NON_DECIMAL = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this flag if IPv4 subnet ranges may be in compact form.
|
||||||
|
*
|
||||||
|
* @example 127/24 => 127.0.0.0/24
|
||||||
|
* @example 10/8 => 10.0.0.0/8
|
||||||
|
* @example 10/24 => 10.0.0.0/24
|
||||||
|
* @example 10.10.10/24 => 10.10.10.0/24
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
const IPV4SUBNET_MAYBE_COMPACT = 8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this flag if IPv4 addresses may be in non quad-dotted notation.
|
||||||
|
* This notation is accepted by the implementation of inet_aton and inet_addr of the libc implementation of GNU, Windows and Mac (but not Musl), but not by inet_pton and ip2long.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*
|
||||||
|
* @example 5.1 => 5.0.0.1
|
||||||
|
* @example 5.256 => 5.0.1.0
|
||||||
|
* @example 5.0.256 => 5.0.1.0
|
||||||
|
* @example 123456789 => 7.91.205.21
|
||||||
|
*
|
||||||
|
* @see https://man7.org/linux/man-pages/man3/inet_addr.3.html#DESCRIPTION
|
||||||
|
* @see https://www.freebsd.org/cgi/man.cgi?query=inet_net&sektion=3&apropos=0&manpath=FreeBSD+12.2-RELEASE+and+Ports#end
|
||||||
|
* @see http://git.musl-libc.org/cgit/musl/tree/src/network/inet_aton.c?h=v1.2.2
|
||||||
|
*/
|
||||||
|
const IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED = 16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this flag if you want to accept parsing IPv4/IPv6 addresses in Reverse DNS Lookup Address format.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*
|
||||||
|
* @since 1.18.0
|
||||||
|
*
|
||||||
|
* @example 140.13.12.10.in-addr.arpa => 10.12.13.140
|
||||||
|
* @example b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.ip6.arpa => 4321:0:1:2:3:4:567:89ab
|
||||||
|
*/
|
||||||
|
const ADDRESS_MAYBE_RDNS = 32;
|
||||||
|
}
|
|
@ -8,6 +8,9 @@ use IPLib\Address\IPv6;
|
||||||
use IPLib\Address\Type as AddressType;
|
use IPLib\Address\Type as AddressType;
|
||||||
use IPLib\Factory;
|
use IPLib\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for range classes.
|
||||||
|
*/
|
||||||
abstract class AbstractRange implements RangeInterface
|
abstract class AbstractRange implements RangeInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -20,7 +23,7 @@ abstract class AbstractRange implements RangeInterface
|
||||||
if ($this->rangeType === null) {
|
if ($this->rangeType === null) {
|
||||||
$addressType = $this->getAddressType();
|
$addressType = $this->getAddressType();
|
||||||
if ($addressType === AddressType::T_IPv6 && Subnet::get6to4()->containsRange($this)) {
|
if ($addressType === AddressType::T_IPv6 && Subnet::get6to4()->containsRange($this)) {
|
||||||
$this->rangeType = Factory::rangeFromBoundaries($this->fromAddress->toIPv4(), $this->toAddress->toIPv4())->getRangeType();
|
$this->rangeType = Factory::getRangeFromBoundaries($this->fromAddress->toIPv4(), $this->toAddress->toIPv4())->getRangeType();
|
||||||
} else {
|
} else {
|
||||||
switch ($addressType) {
|
switch ($addressType) {
|
||||||
case AddressType::T_IPv4:
|
case AddressType::T_IPv4:
|
||||||
|
@ -48,6 +51,33 @@ abstract class AbstractRange implements RangeInterface
|
||||||
return $this->rangeType === false ? null : $this->rangeType;
|
return $this->rangeType === false ? null : $this->rangeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @see \IPLib\Range\RangeInterface::getAddressAtOffset()
|
||||||
|
*/
|
||||||
|
public function getAddressAtOffset($n)
|
||||||
|
{
|
||||||
|
if (!is_int($n)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$address = null;
|
||||||
|
if ($n >= 0) {
|
||||||
|
$start = Factory::parseAddressString($this->getComparableStartString());
|
||||||
|
$address = $start->getAddressAtOffset($n);
|
||||||
|
} else {
|
||||||
|
$end = Factory::parseAddressString($this->getComparableEndString());
|
||||||
|
$address = $end->getAddressAtOffset($n + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($address === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->contains($address) ? $address : null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*
|
*
|
||||||
|
|
|
@ -6,6 +6,7 @@ use IPLib\Address\AddressInterface;
|
||||||
use IPLib\Address\IPv4;
|
use IPLib\Address\IPv4;
|
||||||
use IPLib\Address\IPv6;
|
use IPLib\Address\IPv6;
|
||||||
use IPLib\Address\Type as AddressType;
|
use IPLib\Address\Type as AddressType;
|
||||||
|
use IPLib\ParseStringFlag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an address range in pattern format (only ending asterisks are supported).
|
* Represents an address range in pattern format (only ending asterisks are supported).
|
||||||
|
@ -40,6 +41,8 @@ class Pattern extends AbstractRange
|
||||||
* The type of the range of this IP range.
|
* The type of the range of this IP range.
|
||||||
*
|
*
|
||||||
* @var int|false|null false if this range crosses multiple range types, null if yet to be determined
|
* @var int|false|null false if this range crosses multiple range types, null if yet to be determined
|
||||||
|
*
|
||||||
|
* @since 1.5.0
|
||||||
*/
|
*/
|
||||||
protected $rangeType;
|
protected $rangeType;
|
||||||
|
|
||||||
|
@ -67,24 +70,45 @@ class Pattern extends AbstractRange
|
||||||
return $this->toString();
|
return $this->toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated since 1.17.0: use the parseString() method instead.
|
||||||
|
* For upgrading:
|
||||||
|
* - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
|
||||||
|
*
|
||||||
|
* @param string|mixed $range
|
||||||
|
* @param bool $supportNonDecimalIPv4
|
||||||
|
*
|
||||||
|
* @return static|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\Range\Pattern::parseString()
|
||||||
|
* @since 1.10.0 added the $supportNonDecimalIPv4 argument
|
||||||
|
*/
|
||||||
|
public static function fromString($range, $supportNonDecimalIPv4 = false)
|
||||||
|
{
|
||||||
|
return static::parseString($range, ParseStringFlag::MAY_INCLUDE_PORT | ParseStringFlag::MAY_INCLUDE_ZONEID | ($supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try get the range instance starting from its string representation.
|
* Try get the range instance starting from its string representation.
|
||||||
*
|
*
|
||||||
* @param string|mixed $range
|
* @param string|mixed $range
|
||||||
* @param bool $supportNonDecimalIPv4 set to true to support parsing non decimal (that is, octal and hexadecimal) IPv4 addresses
|
* @param int $flags A combination or zero or more flags
|
||||||
*
|
*
|
||||||
* @return static|null
|
* @return static|null
|
||||||
|
*
|
||||||
|
* @since 1.17.0
|
||||||
|
* @see \IPLib\ParseStringFlag
|
||||||
*/
|
*/
|
||||||
public static function fromString($range, $supportNonDecimalIPv4 = false)
|
public static function parseString($range, $flags = 0)
|
||||||
{
|
{
|
||||||
if (!is_string($range) || strpos($range, '*') === false) {
|
if (!is_string($range) || strpos($range, '*') === false) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if ($range === '*.*.*.*') {
|
if ($range === '*.*.*.*') {
|
||||||
return new static(IPv4::fromString('0.0.0.0'), IPv4::fromString('255.255.255.255'), 4);
|
return new static(IPv4::parseString('0.0.0.0'), IPv4::parseString('255.255.255.255'), 4);
|
||||||
}
|
}
|
||||||
if ($range === '*:*:*:*:*:*:*:*') {
|
if ($range === '*:*:*:*:*:*:*:*') {
|
||||||
return new static(IPv6::fromString('::'), IPv6::fromString('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'), 8);
|
return new static(IPv6::parseString('::'), IPv6::parseString('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'), 8);
|
||||||
}
|
}
|
||||||
$matches = null;
|
$matches = null;
|
||||||
if (strpos($range, '.') !== false && preg_match('/^[^*]+((?:\.\*)+)$/', $range, $matches)) {
|
if (strpos($range, '.') !== false && preg_match('/^[^*]+((?:\.\*)+)$/', $range, $matches)) {
|
||||||
|
@ -96,7 +120,7 @@ class Pattern extends AbstractRange
|
||||||
$asterisksCount += $missingDots;
|
$asterisksCount += $missingDots;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$fromAddress = IPv4::fromString(str_replace('*', '0', $range), true, $supportNonDecimalIPv4);
|
$fromAddress = IPv4::parseString(str_replace('*', '0', $range), $flags);
|
||||||
if ($fromAddress === null) {
|
if ($fromAddress === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -108,7 +132,7 @@ class Pattern extends AbstractRange
|
||||||
}
|
}
|
||||||
if (strpos($range, ':') !== false && preg_match('/^[^*]+((?::\*)+)$/', $range, $matches)) {
|
if (strpos($range, ':') !== false && preg_match('/^[^*]+((?::\*)+)$/', $range, $matches)) {
|
||||||
$asterisksCount = strlen($matches[1]) >> 1;
|
$asterisksCount = strlen($matches[1]) >> 1;
|
||||||
$fromAddress = IPv6::fromString(str_replace('*', '0', $range));
|
$fromAddress = IPv6::parseString(str_replace('*', '0', $range));
|
||||||
if ($fromAddress === null) {
|
if ($fromAddress === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -217,15 +241,11 @@ class Pattern extends AbstractRange
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*
|
*
|
||||||
* @see \IPLib\Range\RangeInterface::asSubnet()
|
* @see \IPLib\Range\RangeInterface::asSubnet()
|
||||||
|
* @since 1.8.0
|
||||||
*/
|
*/
|
||||||
public function asSubnet()
|
public function asSubnet()
|
||||||
{
|
{
|
||||||
switch ($this->getAddressType()) {
|
return new Subnet($this->getStartAddress(), $this->getEndAddress(), $this->getNetworkPrefix());
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -272,4 +292,31 @@ class Pattern extends AbstractRange
|
||||||
{
|
{
|
||||||
return $this->asterisksCount === 0 ? array($this->getStartAddress()->getReverseDNSLookupName()) : $this->asSubnet()->getReverseDNSLookupName();
|
return $this->asterisksCount === 0 ? array($this->getStartAddress()->getReverseDNSLookupName()) : $this->asSubnet()->getReverseDNSLookupName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @see \IPLib\Range\RangeInterface::getSize()
|
||||||
|
*/
|
||||||
|
public function getSize()
|
||||||
|
{
|
||||||
|
$fromAddress = $this->fromAddress;
|
||||||
|
$maxPrefix = $fromAddress::getNumberOfBits();
|
||||||
|
$prefix = $this->getNetworkPrefix();
|
||||||
|
|
||||||
|
return pow(2, ($maxPrefix - $prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return float|int
|
||||||
|
*/
|
||||||
|
private function getNetworkPrefix()
|
||||||
|
{
|
||||||
|
switch ($this->getAddressType()) {
|
||||||
|
case AddressType::T_IPv4:
|
||||||
|
return 8 * (4 - $this->asterisksCount);
|
||||||
|
case AddressType::T_IPv6:
|
||||||
|
return 16 * (8 - $this->asterisksCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,9 +38,26 @@ interface RangeInterface
|
||||||
* Get the type of range of the IP address.
|
* Get the type of range of the IP address.
|
||||||
*
|
*
|
||||||
* @return int One of the \IPLib\Range\Type::T_... constants
|
* @return int One of the \IPLib\Range\Type::T_... constants
|
||||||
|
*
|
||||||
|
* @since 1.5.0
|
||||||
*/
|
*/
|
||||||
public function getRangeType();
|
public function getRangeType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the address at a certain offset of this range.
|
||||||
|
*
|
||||||
|
* @param int $n the offset of the address (support negative offset)
|
||||||
|
*
|
||||||
|
* @return \IPLib\Address\AddressInterface|null return NULL if $n is not an integer or if the offset out of range
|
||||||
|
*
|
||||||
|
* @since 1.15.0
|
||||||
|
*
|
||||||
|
* @example passing 256 to the range 127.0.0.0/16 will result in 127.0.1.0
|
||||||
|
* @example passing -1 to the range 127.0.1.0/16 will result in 127.0.255.255
|
||||||
|
* @example passing 256 to the range 127.0.0.0/24 will result in NULL
|
||||||
|
*/
|
||||||
|
public function getAddressAtOffset($n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if this range contains an IP address.
|
* Check if this range contains an IP address.
|
||||||
*
|
*
|
||||||
|
@ -56,6 +73,8 @@ interface RangeInterface
|
||||||
* @param \IPLib\Range\RangeInterface $range
|
* @param \IPLib\Range\RangeInterface $range
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
|
*
|
||||||
|
* @since 1.5.0
|
||||||
*/
|
*/
|
||||||
public function containsRange(RangeInterface $range);
|
public function containsRange(RangeInterface $range);
|
||||||
|
|
||||||
|
@ -63,6 +82,8 @@ interface RangeInterface
|
||||||
* Get the initial address contained in this range.
|
* Get the initial address contained in this range.
|
||||||
*
|
*
|
||||||
* @return \IPLib\Address\AddressInterface
|
* @return \IPLib\Address\AddressInterface
|
||||||
|
*
|
||||||
|
* @since 1.4.0
|
||||||
*/
|
*/
|
||||||
public function getStartAddress();
|
public function getStartAddress();
|
||||||
|
|
||||||
|
@ -70,6 +91,8 @@ interface RangeInterface
|
||||||
* Get the final address contained in this range.
|
* Get the final address contained in this range.
|
||||||
*
|
*
|
||||||
* @return \IPLib\Address\AddressInterface
|
* @return \IPLib\Address\AddressInterface
|
||||||
|
*
|
||||||
|
* @since 1.4.0
|
||||||
*/
|
*/
|
||||||
public function getEndAddress();
|
public function getEndAddress();
|
||||||
|
|
||||||
|
@ -91,6 +114,8 @@ interface RangeInterface
|
||||||
* Get the subnet mask representing this range (only for IPv4 ranges).
|
* 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
|
* @return \IPLib\Address\IPv4|null return NULL if the range is an IPv6 range, the subnet mask otherwise
|
||||||
|
*
|
||||||
|
* @since 1.8.0
|
||||||
*/
|
*/
|
||||||
public function getSubnetMask();
|
public function getSubnetMask();
|
||||||
|
|
||||||
|
@ -98,6 +123,8 @@ interface RangeInterface
|
||||||
* Get the subnet/CIDR representation of this range.
|
* Get the subnet/CIDR representation of this range.
|
||||||
*
|
*
|
||||||
* @return \IPLib\Range\Subnet
|
* @return \IPLib\Range\Subnet
|
||||||
|
*
|
||||||
|
* @since 1.13.0
|
||||||
*/
|
*/
|
||||||
public function asSubnet();
|
public function asSubnet();
|
||||||
|
|
||||||
|
@ -105,6 +132,8 @@ interface RangeInterface
|
||||||
* Get the pattern/asterisk representation (if applicable) of this range.
|
* Get the pattern/asterisk representation (if applicable) of this range.
|
||||||
*
|
*
|
||||||
* @return \IPLib\Range\Pattern|null return NULL if this range can't be represented by a pattern notation
|
* @return \IPLib\Range\Pattern|null return NULL if this range can't be represented by a pattern notation
|
||||||
|
*
|
||||||
|
* @since 1.13.0
|
||||||
*/
|
*/
|
||||||
public function asPattern();
|
public function asPattern();
|
||||||
|
|
||||||
|
@ -113,8 +142,19 @@ interface RangeInterface
|
||||||
*
|
*
|
||||||
* @return string[]
|
* @return string[]
|
||||||
*
|
*
|
||||||
|
* @since 1.13.0
|
||||||
|
*
|
||||||
* @example for IPv4 it returns something like array('x.x.x.x.in-addr.arpa', 'x.x.x.x.in-addr.arpa') (where the number of 'x.' ranges from 1 to 4)
|
* @example for IPv4 it returns something like array('x.x.x.x.in-addr.arpa', 'x.x.x.x.in-addr.arpa') (where the number of 'x.' ranges from 1 to 4)
|
||||||
* @example for IPv6 it returns something like array('x.x.x.x..x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.ip6.arpa', 'x.x.x.x..x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.ip6.arpa') (where the number of 'x.' ranges from 1 to 32)
|
* @example for IPv6 it returns something like array('x.x.x.x..x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.ip6.arpa', 'x.x.x.x..x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.ip6.arpa') (where the number of 'x.' ranges from 1 to 32)
|
||||||
*/
|
*/
|
||||||
public function getReverseDNSLookupName();
|
public function getReverseDNSLookupName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the count of addresses this IP range contains.
|
||||||
|
*
|
||||||
|
* @return int|float Return float as for huge IPv6 networks, int is not enough
|
||||||
|
*
|
||||||
|
* @since 1.16.0
|
||||||
|
*/
|
||||||
|
public function getSize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use IPLib\Address\AddressInterface;
|
||||||
use IPLib\Address\IPv4;
|
use IPLib\Address\IPv4;
|
||||||
use IPLib\Address\Type as AddressType;
|
use IPLib\Address\Type as AddressType;
|
||||||
use IPLib\Factory;
|
use IPLib\Factory;
|
||||||
|
use IPLib\ParseStringFlag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a single address (eg a range that contains just one address).
|
* Represents a single address (eg a range that contains just one address).
|
||||||
|
@ -41,17 +42,39 @@ class Single extends AbstractRange
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try get the range instance starting from its string representation.
|
* @deprecated since 1.17.0: use the parseString() method instead.
|
||||||
|
* For upgrading:
|
||||||
|
* - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
|
||||||
*
|
*
|
||||||
* @param string|mixed $range
|
* @param string|mixed $range
|
||||||
* @param bool $supportNonDecimalIPv4 set to true to support parsing non decimal (that is, octal and hexadecimal) IPv4 addresses
|
* @param bool $supportNonDecimalIPv4
|
||||||
*
|
*
|
||||||
* @return static|null
|
* @return static|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\Range\Single::parseString()
|
||||||
|
* @since 1.10.0 added the $supportNonDecimalIPv4 argument
|
||||||
*/
|
*/
|
||||||
public static function fromString($range, $supportNonDecimalIPv4 = false)
|
public static function fromString($range, $supportNonDecimalIPv4 = false)
|
||||||
|
{
|
||||||
|
return static::parseString($range, ParseStringFlag::MAY_INCLUDE_PORT | ParseStringFlag::MAY_INCLUDE_ZONEID | ($supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try get the range instance starting from its string representation.
|
||||||
|
*
|
||||||
|
* @param string|mixed $range
|
||||||
|
* @param int $flags A combination or zero or more flags
|
||||||
|
*
|
||||||
|
* @return static|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\ParseStringFlag
|
||||||
|
* @since 1.17.0
|
||||||
|
*/
|
||||||
|
public static function parseString($range, $flags = 0)
|
||||||
{
|
{
|
||||||
$result = null;
|
$result = null;
|
||||||
$address = Factory::addressFromString($range, true, true, $supportNonDecimalIPv4);
|
$flags = (int) $flags;
|
||||||
|
$address = Factory::parseAddressString($range, $flags);
|
||||||
if ($address !== null) {
|
if ($address !== null) {
|
||||||
$result = new static($address);
|
$result = new static($address);
|
||||||
}
|
}
|
||||||
|
@ -65,6 +88,8 @@ class Single extends AbstractRange
|
||||||
* @param \IPLib\Address\AddressInterface $address
|
* @param \IPLib\Address\AddressInterface $address
|
||||||
*
|
*
|
||||||
* @return static
|
* @return static
|
||||||
|
*
|
||||||
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
public static function fromAddress(AddressInterface $address)
|
public static function fromAddress(AddressInterface $address)
|
||||||
{
|
{
|
||||||
|
@ -118,23 +143,6 @@ class Single extends AbstractRange
|
||||||
return $result;
|
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}
|
* {@inheritdoc}
|
||||||
*
|
*
|
||||||
|
@ -223,4 +231,14 @@ class Single extends AbstractRange
|
||||||
{
|
{
|
||||||
return array($this->getStartAddress()->getReverseDNSLookupName());
|
return array($this->getStartAddress()->getReverseDNSLookupName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @see \IPLib\Range\RangeInterface::getSize()
|
||||||
|
*/
|
||||||
|
public function getSize()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@ namespace IPLib\Range;
|
||||||
|
|
||||||
use IPLib\Address\AddressInterface;
|
use IPLib\Address\AddressInterface;
|
||||||
use IPLib\Address\IPv4;
|
use IPLib\Address\IPv4;
|
||||||
use IPLib\Address\IPv6;
|
|
||||||
use IPLib\Address\Type as AddressType;
|
use IPLib\Address\Type as AddressType;
|
||||||
use IPLib\Factory;
|
use IPLib\Factory;
|
||||||
|
use IPLib\ParseStringFlag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an address range in subnet format (eg CIDR).
|
* Represents an address range in subnet format (eg CIDR).
|
||||||
|
@ -41,6 +41,8 @@ class Subnet extends AbstractRange
|
||||||
* The type of the range of this IP range.
|
* The type of the range of this IP range.
|
||||||
*
|
*
|
||||||
* @var int|null
|
* @var int|null
|
||||||
|
*
|
||||||
|
* @since 1.5.0
|
||||||
*/
|
*/
|
||||||
protected $rangeType;
|
protected $rangeType;
|
||||||
|
|
||||||
|
@ -77,15 +79,36 @@ class Subnet extends AbstractRange
|
||||||
return $this->toString();
|
return $this->toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated since 1.17.0: use the parseString() method instead.
|
||||||
|
* For upgrading:
|
||||||
|
* - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
|
||||||
|
*
|
||||||
|
* @param string|mixed $range
|
||||||
|
* @param bool $supportNonDecimalIPv4
|
||||||
|
*
|
||||||
|
* @return static|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\Range\Subnet::parseString()
|
||||||
|
* @since 1.10.0 added the $supportNonDecimalIPv4 argument
|
||||||
|
*/
|
||||||
|
public static function fromString($range, $supportNonDecimalIPv4 = false)
|
||||||
|
{
|
||||||
|
return static::parseString($range, ParseStringFlag::MAY_INCLUDE_PORT | ParseStringFlag::MAY_INCLUDE_ZONEID | ($supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try get the range instance starting from its string representation.
|
* Try get the range instance starting from its string representation.
|
||||||
*
|
*
|
||||||
* @param string|mixed $range
|
* @param string|mixed $range
|
||||||
* @param bool $supportNonDecimalIPv4 set to true to support parsing non decimal (that is, octal and hexadecimal) IPv4 addresses
|
* @param int $flags A combination or zero or more flags
|
||||||
*
|
*
|
||||||
* @return static|null
|
* @return static|null
|
||||||
|
*
|
||||||
|
* @see \IPLib\ParseStringFlag
|
||||||
|
* @since 1.17.0
|
||||||
*/
|
*/
|
||||||
public static function fromString($range, $supportNonDecimalIPv4 = false)
|
public static function parseString($range, $flags = 0)
|
||||||
{
|
{
|
||||||
if (!is_string($range)) {
|
if (!is_string($range)) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -94,7 +117,14 @@ class Subnet extends AbstractRange
|
||||||
if (count($parts) !== 2) {
|
if (count($parts) !== 2) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$address = Factory::addressFromString($parts[0], true, true, $supportNonDecimalIPv4);
|
$flags = (int) $flags;
|
||||||
|
if (strpos($parts[0], ':') === false && $flags & ParseStringFlag::IPV4SUBNET_MAYBE_COMPACT) {
|
||||||
|
$missingDots = 3 - substr_count($parts[0], '.');
|
||||||
|
if ($missingDots > 0) {
|
||||||
|
$parts[0] .= str_repeat('.0', $missingDots);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$address = Factory::parseAddressString($parts[0], $flags);
|
||||||
if ($address === null) {
|
if ($address === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -197,9 +227,10 @@ class Subnet extends AbstractRange
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the pattern (asterisk) representation (if applicable) of this range.
|
* {@inheritdoc}
|
||||||
*
|
*
|
||||||
* @return \IPLib\Range\Pattern|null return NULL if this range can't be represented by a pattern notation
|
* @see \IPLib\Range\RangeInterface::asPattern()
|
||||||
|
* @since 1.8.0
|
||||||
*/
|
*/
|
||||||
public function asPattern()
|
public function asPattern()
|
||||||
{
|
{
|
||||||
|
@ -217,11 +248,13 @@ class Subnet extends AbstractRange
|
||||||
* Get the 6to4 address IPv6 address range.
|
* Get the 6to4 address IPv6 address range.
|
||||||
*
|
*
|
||||||
* @return self
|
* @return self
|
||||||
|
*
|
||||||
|
* @since 1.5.0
|
||||||
*/
|
*/
|
||||||
public static function get6to4()
|
public static function get6to4()
|
||||||
{
|
{
|
||||||
if (self::$sixToFour === null) {
|
if (self::$sixToFour === null) {
|
||||||
self::$sixToFour = self::fromString('2002::/16');
|
self::$sixToFour = self::parseString('2002::/16');
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$sixToFour;
|
return self::$sixToFour;
|
||||||
|
@ -231,6 +264,8 @@ class Subnet extends AbstractRange
|
||||||
* Get subnet prefix.
|
* Get subnet prefix.
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
*/
|
*/
|
||||||
public function getNetworkPrefix()
|
public function getNetworkPrefix()
|
||||||
{
|
{
|
||||||
|
@ -302,4 +337,18 @@ class Subnet extends AbstractRange
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @see \IPLib\Range\RangeInterface::getSize()
|
||||||
|
*/
|
||||||
|
public function getSize()
|
||||||
|
{
|
||||||
|
$fromAddress = $this->fromAddress;
|
||||||
|
$maxPrefix = $fromAddress::getNumberOfBits();
|
||||||
|
$prefix = $this->getNetworkPrefix();
|
||||||
|
|
||||||
|
return pow(2, ($maxPrefix - $prefix));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,8 @@ class Type
|
||||||
* Carrier-grade NAT address.
|
* Carrier-grade NAT address.
|
||||||
*
|
*
|
||||||
* @var int
|
* @var int
|
||||||
|
*
|
||||||
|
* @since 1.10.0
|
||||||
*/
|
*/
|
||||||
const T_CGNAT = 14;
|
const T_CGNAT = 14;
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ namespace IPLib\Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class to work with unsigned binary integers.
|
* Helper class to work with unsigned binary integers.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class BinaryMath
|
class BinaryMath
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,12 +7,14 @@ use IPLib\Factory;
|
||||||
use IPLib\Range\Subnet;
|
use IPLib\Range\Subnet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class to calculate the subnets describing all (and only all) the addresses between two bouundaries.
|
* Helper class to calculate the subnets describing all (and only all) the addresses between two boundaries.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class RangesFromBounradyCalculator
|
class RangesFromBoundaryCalculator
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The BinaryMath instance to be used to perform bitwise poerations.
|
* The BinaryMath instance to be used to perform bitwise operations.
|
||||||
*
|
*
|
||||||
* @var \IPLib\Service\BinaryMath
|
* @var \IPLib\Service\BinaryMath
|
||||||
*/
|
*/
|
||||||
|
@ -53,7 +55,7 @@ class RangesFromBounradyCalculator
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the subnets describing all (and only all) the addresses between two bouundaries.
|
* Calculate the subnets describing all (and only all) the addresses between two boundaries.
|
||||||
*
|
*
|
||||||
* @param \IPLib\Address\AddressInterface $from
|
* @param \IPLib\Address\AddressInterface $from
|
||||||
* @param \IPLib\Address\AddressInterface $to
|
* @param \IPLib\Address\AddressInterface $to
|
||||||
|
@ -154,8 +156,13 @@ class RangesFromBounradyCalculator
|
||||||
*/
|
*/
|
||||||
private function subnetFromBits($bits, $networkPrefix)
|
private function subnetFromBits($bits, $networkPrefix)
|
||||||
{
|
{
|
||||||
$address = $this->addressFromBits($bits);
|
$startAddress = $this->addressFromBits($bits);
|
||||||
|
$numOnes = $this->numBits - $networkPrefix;
|
||||||
|
if ($numOnes === 0) {
|
||||||
|
return new Subnet($startAddress, $startAddress, $networkPrefix);
|
||||||
|
}
|
||||||
|
$endAddress = $this->addressFromBits(substr($bits, 0, -$numOnes) . str_repeat('1', $numOnes));
|
||||||
|
|
||||||
return new Subnet($address, $address, $networkPrefix);
|
return new Subnet($startAddress, $endAddress, $networkPrefix);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,171 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace IPLib\Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to work with unsigned integers.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class UnsignedIntegerMath
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Convert a string containing a decimal, octal or hexadecimal number into its bytes.
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @param int $numBytes the wanted number of bytes
|
||||||
|
* @param bool $onlyDecimal Only parse decimal numbers
|
||||||
|
*
|
||||||
|
* @return int[]|null
|
||||||
|
*/
|
||||||
|
public function getBytes($value, $numBytes, $onlyDecimal = false)
|
||||||
|
{
|
||||||
|
$m = null;
|
||||||
|
if ($onlyDecimal) {
|
||||||
|
if (preg_match('/^0*(\d+)$/', $value, $m)) {
|
||||||
|
return $this->getBytesFromDecimal($m[1], $numBytes);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (preg_match('/^0[Xx]0*([0-9A-Fa-f]+)$/', $value, $m)) {
|
||||||
|
return $this->getBytesFromHexadecimal($m[1], $numBytes);
|
||||||
|
}
|
||||||
|
if (preg_match('/^0+([0-7]*)$/', $value, $m)) {
|
||||||
|
return $this->getBytesFromOctal($m[1], $numBytes);
|
||||||
|
}
|
||||||
|
if (preg_match('/^[1-9][0-9]*$/', $value)) {
|
||||||
|
return $this->getBytesFromDecimal($value, $numBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not a valid number
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
protected function getMaxSignedInt()
|
||||||
|
{
|
||||||
|
return PHP_INT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $value never zero-length, never extra leading zeroes
|
||||||
|
* @param int $numBytes
|
||||||
|
*
|
||||||
|
* @return int[]|null
|
||||||
|
*/
|
||||||
|
private function getBytesFromBits($value, $numBytes)
|
||||||
|
{
|
||||||
|
$valueLength = strlen($value);
|
||||||
|
if ($valueLength > $numBytes << 3) {
|
||||||
|
// overflow
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$remainderBits = $valueLength % 8;
|
||||||
|
if ($remainderBits !== 0) {
|
||||||
|
$value = str_pad($value, $valueLength + 8 - $remainderBits, '0', STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
$bytes = array_map('bindec', str_split($value, 8));
|
||||||
|
|
||||||
|
return array_pad($bytes, -$numBytes, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $value may be zero-length, never extra leading zeroes
|
||||||
|
* @param int $numBytes
|
||||||
|
*
|
||||||
|
* @return int[]|null
|
||||||
|
*/
|
||||||
|
private function getBytesFromOctal($value, $numBytes)
|
||||||
|
{
|
||||||
|
if ($value === '') {
|
||||||
|
return array_fill(0, $numBytes, 0);
|
||||||
|
}
|
||||||
|
$bits = implode(
|
||||||
|
'',
|
||||||
|
array_map(
|
||||||
|
function ($octalDigit) {
|
||||||
|
return str_pad(decbin(octdec($octalDigit)), 3, '0', STR_PAD_LEFT);
|
||||||
|
},
|
||||||
|
str_split($value, 1)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$bits = ltrim($bits, '0');
|
||||||
|
|
||||||
|
return $bits === '' ? array_fill(0, $numBytes, 0) : static::getBytesFromBits($bits, $numBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $value never zero-length, never extra leading zeroes
|
||||||
|
* @param int $numBytes
|
||||||
|
*
|
||||||
|
* @return int[]|null
|
||||||
|
*/
|
||||||
|
private function getBytesFromDecimal($value, $numBytes)
|
||||||
|
{
|
||||||
|
$valueLength = strlen($value);
|
||||||
|
$maxSignedIntLength = strlen((string) $this->getMaxSignedInt());
|
||||||
|
if ($valueLength < $maxSignedIntLength) {
|
||||||
|
return $this->getBytesFromBits(decbin((int) $value), $numBytes);
|
||||||
|
}
|
||||||
|
// Divide by two, so that we have 1 less bit
|
||||||
|
$carry = 0;
|
||||||
|
$halfValue = ltrim(
|
||||||
|
implode(
|
||||||
|
'',
|
||||||
|
array_map(
|
||||||
|
function ($digit) use (&$carry) {
|
||||||
|
$number = $carry + (int) $digit;
|
||||||
|
$carry = ($number % 2) * 10;
|
||||||
|
|
||||||
|
return (string) $number >> 1;
|
||||||
|
},
|
||||||
|
str_split($value, 1)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'0'
|
||||||
|
);
|
||||||
|
$halfValueBytes = $this->getBytesFromDecimal($halfValue, $numBytes);
|
||||||
|
if ($halfValueBytes === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$carry = $carry === 0 ? 0 : 1;
|
||||||
|
$result = array_fill(0, $numBytes, 0);
|
||||||
|
for ($index = $numBytes - 1; $index >= 0; $index--) {
|
||||||
|
$byte = $carry + ($halfValueBytes[$index] << 1);
|
||||||
|
if ($byte <= 0xFF) {
|
||||||
|
$carry = 0;
|
||||||
|
} else {
|
||||||
|
$carry = ($byte & ~0xFF) >> 8;
|
||||||
|
$byte -= 0x100;
|
||||||
|
}
|
||||||
|
$result[$index] = $byte;
|
||||||
|
}
|
||||||
|
if ($carry !== 0) {
|
||||||
|
// Overflow
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $value never zero-length, never extra leading zeroes
|
||||||
|
* @param int $numBytes
|
||||||
|
*
|
||||||
|
* @return int[]|null
|
||||||
|
*/
|
||||||
|
private function getBytesFromHexadecimal($value, $numBytes)
|
||||||
|
{
|
||||||
|
$valueLength = strlen($value);
|
||||||
|
if ($valueLength > $numBytes << 1) {
|
||||||
|
// overflow
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$value = str_pad($value, $valueLength + $valueLength % 2, '0', STR_PAD_LEFT);
|
||||||
|
$bytes = array_map('hexdec', str_split($value, 2));
|
||||||
|
|
||||||
|
return array_pad($bytes, -$numBytes, 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -183,7 +183,7 @@ if (!is_callable('random_bytes')) {
|
||||||
try {
|
try {
|
||||||
$RandomCompatCOMtest = new COM('CAPICOM.Utilities.1');
|
$RandomCompatCOMtest = new COM('CAPICOM.Utilities.1');
|
||||||
/** @psalm-suppress TypeDoesNotContainType */
|
/** @psalm-suppress TypeDoesNotContainType */
|
||||||
if (method_exists($RandomCompatCOMtest, 'GetRandom')) {
|
if (is_callable(array($RandomCompatCOMtest, 'GetRandom'))) {
|
||||||
// See random_bytes_com_dotnet.php
|
// See random_bytes_com_dotnet.php
|
||||||
require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_com_dotnet.php';
|
require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_com_dotnet.php';
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue