Version Description
- 2022-11-01 =
- Fixed: Fatal error due to missing vendor directory.
Download this release
Release Info
Developer | 10up |
Plugin | Restricted Site Access |
Version | 7.3.4 |
Comparing to | |
See all releases |
Code changes from version 7.3.3 to 7.3.4
- .gitattributes +28 -0
- assets/js/build/admin.min.asset.php +1 -0
- assets/js/build/admin.min.js +1 -0
- assets/js/build/settings.min.asset.php +1 -0
- assets/js/build/settings.min.js +1 -0
- phpcs.xml +0 -42
- phpunit.xml +28 -0
- readme.txt +4 -1
- restricted_site_access.php +2 -2
- vendor/autoload.php +25 -0
- vendor/composer/ClassLoader.php +572 -0
- vendor/composer/InstalledVersions.php +352 -0
- vendor/composer/LICENSE +21 -0
- vendor/composer/autoload_classmap.php +10 -0
- vendor/composer/autoload_namespaces.php +9 -0
- vendor/composer/autoload_psr4.php +10 -0
- vendor/composer/autoload_real.php +38 -0
- vendor/composer/autoload_static.php +36 -0
- vendor/composer/installed.json +81 -0
- vendor/composer/installed.php +34 -0
- vendor/composer/platform_check.php +26 -0
- vendor/mlocati/ip-lib/LICENSE.txt +20 -0
- vendor/mlocati/ip-lib/ip-lib.php +13 -0
- vendor/mlocati/ip-lib/src/Address/AddressInterface.php +156 -0
- vendor/mlocati/ip-lib/src/Address/AssignedRange.php +140 -0
- vendor/mlocati/ip-lib/src/Address/IPv4.php +515 -0
- vendor/mlocati/ip-lib/src/Address/IPv6.php +608 -0
- vendor/mlocati/ip-lib/src/Address/Type.php +44 -0
- vendor/mlocati/ip-lib/src/Factory.php +298 -0
- vendor/mlocati/ip-lib/src/ParseStringFlag.php +79 -0
- vendor/mlocati/ip-lib/src/Range/AbstractRange.php +125 -0
- vendor/mlocati/ip-lib/src/Range/Pattern.php +322 -0
- vendor/mlocati/ip-lib/src/Range/RangeInterface.php +160 -0
- vendor/mlocati/ip-lib/src/Range/Single.php +244 -0
- vendor/mlocati/ip-lib/src/Range/Subnet.php +354 -0
- vendor/mlocati/ip-lib/src/Range/Type.php +152 -0
- vendor/mlocati/ip-lib/src/Service/BinaryMath.php +120 -0
- vendor/mlocati/ip-lib/src/Service/RangesFromBoundaryCalculator.php +168 -0
- vendor/mlocati/ip-lib/src/Service/UnsignedIntegerMath.php +171 -0
- webpack.config.js +30 -0
.gitattributes
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Directories
|
2 |
+
/.git export-ignore
|
3 |
+
/.github export-ignore
|
4 |
+
/.wordpress-org export-ignore
|
5 |
+
/bin export-ignore
|
6 |
+
/tests export-ignore
|
7 |
+
|
8 |
+
# Files
|
9 |
+
/.editorconfig export-ignore
|
10 |
+
/.eslintrc.js export-ignore
|
11 |
+
/.gitattributes export-ignore
|
12 |
+
/.gitignore export-ignore
|
13 |
+
/.wp-env.json export-ignore
|
14 |
+
/CHANGELOG.md export-ignore
|
15 |
+
/CODE_OF_CONDUCT.md export-ignore
|
16 |
+
/composer.json export-ignore
|
17 |
+
/composer.lock export-ignore
|
18 |
+
/CONTRIBUTING.md export-ignore
|
19 |
+
/CREDITS.md export-ignore
|
20 |
+
/Gruntfile.js export-ignore
|
21 |
+
/LICENSE.md export-ignore
|
22 |
+
/package-lock.json export-ignore
|
23 |
+
/package.json export-ignore
|
24 |
+
/phpunit.xml export-ignore
|
25 |
+
/README.md export-ignore
|
26 |
+
/run-wpacceptance.sh export-ignore
|
27 |
+
/wpacceptance.json export-ignore
|
28 |
+
/webpack.config.js export-ignore
|
assets/js/build/admin.min.asset.php
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
<?php return array('dependencies' => array('jquery-ui-dialog'), 'version' => 'fac6f22fe4aafebab2d6');
|
assets/js/build/admin.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
!function(){"use strict";var e;window["jquery-ui-dialog"],window,(e=jQuery)(".notice").on("click",".notice-dismiss",(function(s){s.delegateTarget.getAttribute("data-rsa-notice")&&e.ajax({method:"post",data:{nonce:rsaAdmin.nonce,action:"rsa_notice_dismiss"},url:ajaxurl})})),function(e,s){s((()=>{({els:{dialog:document.getElementById("rsa-disable-dialog"),userMessage:document.getElementById("rsa-user-message")},variables:{expectedAnswer:rsaAdmin.strings.message.toLowerCase(),disablingURL:null},openDialog(e){e.preventDefault(),s(this.els.dialog).dialog("open")},isExpectedAnswer(){return this.els.userMessage.value.toLowerCase()===this.variables.expectedAnswer},dialogSettings(){const i=this;i.close=function(){s(i.els.dialog).dialog("close"),i.els.userMessage.style.border="1px solid #ddd",i.els.userMessage.value=""},s(this.els.dialog).dialog({dialogClass:"wp-dialog",autoOpen:!1,draggable:!1,width:"auto",modal:!0,resizable:!1,buttons:[{text:rsaAdmin.strings.confirm,click(){i.isExpectedAnswer()?e.location.href=i.variables.disablingURL:i.els.userMessage.style.border="1px solid red"}},{text:rsaAdmin.strings.cancel,click(){i.close()},class:"button-primary"}],open(){s(".ui-widget-overlay").bind("click",(function(){i.close()}))},create(){s(".ui-dialog-titlebar-close").addClass("ui-button"),s(this).siblings(".ui-dialog-titlebar").hide()}}),this.els.buttons=s(this.els.dialog).dialog("option","buttons")},maybeSubmit(e){"Enter"===e.key&&this.els.buttons[0].click()},bindEvents(){s('[data-slug="restricted-site-access"]').on("click",".deactivate a",this.openDialog.bind(this)),this.els.userMessage&&this.els.userMessage.addEventListener("keyup",this.maybeSubmit.bind(this))},init(){const e=document.getElementById("the-list");e&&(this.variables.disablingURL=e.querySelector('[data-slug="restricted-site-access"] .deactivate a').href),this.bindEvents(),this.dialogSettings()}}).init()}))}(window,jQuery)}();
|
assets/js/build/settings.min.asset.php
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
<?php return array('dependencies' => array('jquery-effects-shake'), 'version' => 'defa695edb268b3ceb12');
|
assets/js/build/settings.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
!function(){"use strict";window["jquery-effects-shake"],function(e,i){const t=e.document,c={add_btn:"",new_ip:"",ip_list_wrap:"",empty_ip:"",restrict_radio:"",table:"",redirect_choice:"",message_choice:"",page_choice:"",redirect_fields:"",message_field:"",page_field:"",error_field:"",submit_btn:""};i((function(){!function(){c.add_btn=i(t.getElementById("addip")),c.new_ip=t.getElementById("newip"),c.new_ip_comment=t.getElementById("newipcomment"),c.ip_list_wrap=t.getElementById("ip_list"),c.empty_ip=i(t.getElementById("ip_list_empty")),c.restrict_radio=t.getElementById("blog-restricted"),c.error_field=t.getElementById("rsa-error-container"),c.table=i(t.getElementById("rsa-send-to-login")).closest("table"),c.redirect_choice=t.getElementById("rsa-redirect-visitor"),c.message_choice=t.getElementById("rsa-display-message"),c.page_choice=t.getElementById("rsa-unblocked-page"),c.redirect_fields=i(t.querySelectorAll(".rsa_redirect_field")).closest("tr"),c.message_field=i(t.getElementById("rsa_message")).closest("tr"),c.page_field=i(t.getElementById("rsa_page")).closest("tr"),c.submit_btn=i("#submit"),c.restrict_radio&&!c.restrict_radio.checked&&c.table.hide(),c.redirect_choice&&!c.redirect_choice.checked&&c.redirect_fields.hide(),c.message_choice&&!c.message_choice.checked&&c.message_field.hide(),c.page_choice&&!c.page_choice.checked&&c.page_field.hide(),i(t.querySelectorAll("#rsa_handle_fields input")).on("change",(function(){c.redirect_choice.checked?c.redirect_fields.show():c.redirect_fields.hide(),c.message_choice.checked?c.message_field.show():c.message_field.hide(),c.page_choice.checked?c.page_field.show():c.page_field.hide()})),i(t.querySelectorAll(".option-site-visibility input")).on("change",(function(){c.restrict_radio.checked?c.table.show():c.table.hide()})),c.add_btn.on("click",(function(){c.empty_ip.clone().appendTo(c.ip_list_wrap).removeAttr("id").slideDown(250)})),i(c.ip_list_wrap).on("blur",".ip.code",(function(){!function(e,r,s){if(c.submit_btn.prop("disabled",!0),""===i.trim(e))return void c.submit_btn.prop("disabled",!1);const d=i(t.querySelectorAll("#ip_list input"));for(let t=0;t<d.length;t++)if(!s.is(d[t])&&d[t].value===e)return i(d[t]).parent().effect("shake",600),void i(s).focus();jQuery.post(ajaxurl,{action:"rsa_ip_check",ip_address:e,ip_address_comment:r,nonce:rsaSettings.nonce},(function(e){return e.success?(i(c.error_field).text(""),c.submit_btn.prop("disabled",!1),!0):(i(s).effect("shake",600).focus(),i(c.error_field).text(e.data),!1)}))}(i(this).val(),i(this).next().val(),i(this))}));const e=t.getElementById("rsa_myip");null!==e&&i(e).on("click",(function(){i(".ip.code:last").val(i(this).data("myip")).blur()})),i(c.ip_list_wrap).on("click",".remove_btn",(function(){i(this.parentNode).slideUp(250,(function(){i(this).remove()}))}))}()}))}(window,jQuery)}();
|
phpcs.xml
DELETED
@@ -1,42 +0,0 @@
|
|
1 |
-
<?xml version="1.0"?>
|
2 |
-
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Example Project" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/squizlabs/PHP_CodeSniffer/master/phpcs.xsd">
|
3 |
-
|
4 |
-
<description>A custom set of rules to check for the Restricted Site Access project.</description>
|
5 |
-
|
6 |
-
<arg name="extensions" value="php"/>
|
7 |
-
|
8 |
-
<!-- Exclude the Composer Vendor directory. -->
|
9 |
-
<exclude-pattern>/vendor/*</exclude-pattern>
|
10 |
-
|
11 |
-
<!-- Exclude the Node Modules directory. -->
|
12 |
-
<exclude-pattern>/node_modules/*</exclude-pattern>
|
13 |
-
|
14 |
-
<!-- Exclude minified Javascript files. -->
|
15 |
-
<exclude-pattern>*.min.js</exclude-pattern>
|
16 |
-
|
17 |
-
<!-- Exclude the assets directory. -->
|
18 |
-
<exclude-pattern>assets</exclude-pattern>
|
19 |
-
|
20 |
-
<exclude-pattern>tests/php/bootstrap.php</exclude-pattern>
|
21 |
-
|
22 |
-
<!-- Let's also check that everything is properly documented. -->
|
23 |
-
<rule ref="WordPress">
|
24 |
-
<exclude name="WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase" />
|
25 |
-
</rule>
|
26 |
-
|
27 |
-
<rule ref="Squiz.Commenting.FileComment.Missing">
|
28 |
-
<exclude-pattern>tests</exclude-pattern>
|
29 |
-
</rule>
|
30 |
-
|
31 |
-
<rule ref="Squiz.Commenting.ClassComment.Missing">
|
32 |
-
<exclude-pattern>tests</exclude-pattern>
|
33 |
-
</rule>
|
34 |
-
|
35 |
-
<rule ref="Squiz.Commenting.FunctionComment.Missing">
|
36 |
-
<exclude-pattern>tests</exclude-pattern>
|
37 |
-
</rule>
|
38 |
-
|
39 |
-
<!-- Add in some extra rules from other standards. -->
|
40 |
-
<config name="minimum_supported_wp_version" value="5.7"/>
|
41 |
-
|
42 |
-
</ruleset>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
phpunit.xml
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<phpunit
|
2 |
+
bootstrap="tests/php/bootstrap.php"
|
3 |
+
backupGlobals="false"
|
4 |
+
colors="true"
|
5 |
+
verbose="true"
|
6 |
+
>
|
7 |
+
<testsuites>
|
8 |
+
<testsuite name="restricted-site-access-unit-tests">
|
9 |
+
<directory suffix=".php">tests/php</directory>
|
10 |
+
<exclude>tests/php/code-coverage.php</exclude>
|
11 |
+
<exclude>tests/php/multisite</exclude>
|
12 |
+
<exclude>tests/php/whitelist</exclude>
|
13 |
+
</testsuite>
|
14 |
+
</testsuites>
|
15 |
+
<filter>
|
16 |
+
<whitelist>
|
17 |
+
<file>restricted_site_access.php</file>
|
18 |
+
</whitelist>
|
19 |
+
</filter>
|
20 |
+
<php>
|
21 |
+
<ini name="error_reporting" value="32767" />
|
22 |
+
<ini name="display_errors" value="1" />
|
23 |
+
<ini name="display_startup_errors" value="1" />
|
24 |
+
</php>
|
25 |
+
<logging>
|
26 |
+
<log type="coverage-php" target="test-coverage/coverage.serialized"/>
|
27 |
+
</logging>
|
28 |
+
</phpunit>
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Donate link: https://10up.com/plugins/restricted-site-access-wordpress/
|
|
4 |
Tags: privacy, restricted, restrict, privacy, limited, permissions, security, block
|
5 |
Requires at least: 5.7
|
6 |
Tested up to: 6.1
|
7 |
-
Stable tag: 7.3.
|
8 |
Requires PHP: 7.4
|
9 |
License: GPLv2 or later
|
10 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
@@ -198,6 +198,9 @@ Please note that setting `RSA_FORCE_RESTRICTION` will override `RSA_FORBID_RESTR
|
|
198 |
|
199 |
== Changelog ==
|
200 |
|
|
|
|
|
|
|
201 |
= 7.3.3 - 2022-10-31 =
|
202 |
* **Added:** Support for IPv6 addresses (props [@jeffpaul](https://github.com/jeffpaul), [@Sidsector9](https://github.com/Sidsector9), [@cadic](https://github.com/cadic)).
|
203 |
* **Added:** Support for subnet range and pattern formats for IPv4 and IPv6 addresses (props [@jeffpaul](https://github.com/jeffpaul), [@Sidsector9](https://github.com/Sidsector9), [@cadic](https://github.com/cadic)).
|
4 |
Tags: privacy, restricted, restrict, privacy, limited, permissions, security, block
|
5 |
Requires at least: 5.7
|
6 |
Tested up to: 6.1
|
7 |
+
Stable tag: 7.3.4
|
8 |
Requires PHP: 7.4
|
9 |
License: GPLv2 or later
|
10 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
198 |
|
199 |
== Changelog ==
|
200 |
|
201 |
+
= 7.3.4 - 2022-11-01 =
|
202 |
+
* **Fixed:** Fatal error due to missing vendor directory.
|
203 |
+
|
204 |
= 7.3.3 - 2022-10-31 =
|
205 |
* **Added:** Support for IPv6 addresses (props [@jeffpaul](https://github.com/jeffpaul), [@Sidsector9](https://github.com/Sidsector9), [@cadic](https://github.com/cadic)).
|
206 |
* **Added:** Support for subnet range and pattern formats for IPv4 and IPv6 addresses (props [@jeffpaul](https://github.com/jeffpaul), [@Sidsector9](https://github.com/Sidsector9), [@cadic](https://github.com/cadic)).
|
restricted_site_access.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: Restricted Site Access
|
4 |
* Plugin URI: https://10up.com/plugins/restricted-site-access-wordpress/
|
5 |
* Description: <strong>Limit access your site</strong> to visitors who are logged in or accessing the site from a set of specific IP addresses. Send restricted visitors to the log in page, redirect them, or display a message or page. <strong>Powerful control over redirection</strong>, including <strong>SEO friendly redirect headers</strong>. Great solution for Extranets, publicly hosted Intranets, or parallel development sites.
|
6 |
-
* Version: 7.3.
|
7 |
* Requires at least: 5.7
|
8 |
* Requires PHP: 7.4
|
9 |
* Author: Jake Goldman, 10up, Oomph
|
@@ -15,7 +15,7 @@
|
|
15 |
|
16 |
require_once 'vendor/autoload.php';
|
17 |
|
18 |
-
define( 'RSA_VERSION', '7.3.
|
19 |
|
20 |
/**
|
21 |
* Class responsible for all plugin funcitonality.
|
3 |
* Plugin Name: Restricted Site Access
|
4 |
* Plugin URI: https://10up.com/plugins/restricted-site-access-wordpress/
|
5 |
* Description: <strong>Limit access your site</strong> to visitors who are logged in or accessing the site from a set of specific IP addresses. Send restricted visitors to the log in page, redirect them, or display a message or page. <strong>Powerful control over redirection</strong>, including <strong>SEO friendly redirect headers</strong>. Great solution for Extranets, publicly hosted Intranets, or parallel development sites.
|
6 |
+
* Version: 7.3.4
|
7 |
* Requires at least: 5.7
|
8 |
* Requires PHP: 7.4
|
9 |
* Author: Jake Goldman, 10up, Oomph
|
15 |
|
16 |
require_once 'vendor/autoload.php';
|
17 |
|
18 |
+
define( 'RSA_VERSION', '7.3.4' );
|
19 |
|
20 |
/**
|
21 |
* Class responsible for all plugin funcitonality.
|
vendor/autoload.php
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload.php @generated by Composer
|
4 |
+
|
5 |
+
if (PHP_VERSION_ID < 50600) {
|
6 |
+
if (!headers_sent()) {
|
7 |
+
header('HTTP/1.1 500 Internal Server Error');
|
8 |
+
}
|
9 |
+
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
10 |
+
if (!ini_get('display_errors')) {
|
11 |
+
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
12 |
+
fwrite(STDERR, $err);
|
13 |
+
} elseif (!headers_sent()) {
|
14 |
+
echo $err;
|
15 |
+
}
|
16 |
+
}
|
17 |
+
trigger_error(
|
18 |
+
$err,
|
19 |
+
E_USER_ERROR
|
20 |
+
);
|
21 |
+
}
|
22 |
+
|
23 |
+
require_once __DIR__ . '/composer/autoload_real.php';
|
24 |
+
|
25 |
+
return ComposerAutoloaderInita3f7bfdb9e7229bdf95aaef37022fd47::getLoader();
|
vendor/composer/ClassLoader.php
ADDED
@@ -0,0 +1,572 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Composer.
|
5 |
+
*
|
6 |
+
* (c) Nils Adermann <naderman@naderman.de>
|
7 |
+
* Jordi Boggiano <j.boggiano@seld.be>
|
8 |
+
*
|
9 |
+
* For the full copyright and license information, please view the LICENSE
|
10 |
+
* file that was distributed with this source code.
|
11 |
+
*/
|
12 |
+
|
13 |
+
namespace Composer\Autoload;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
17 |
+
*
|
18 |
+
* $loader = new \Composer\Autoload\ClassLoader();
|
19 |
+
*
|
20 |
+
* // register classes with namespaces
|
21 |
+
* $loader->add('Symfony\Component', __DIR__.'/component');
|
22 |
+
* $loader->add('Symfony', __DIR__.'/framework');
|
23 |
+
*
|
24 |
+
* // activate the autoloader
|
25 |
+
* $loader->register();
|
26 |
+
*
|
27 |
+
* // to enable searching the include path (eg. for PEAR packages)
|
28 |
+
* $loader->setUseIncludePath(true);
|
29 |
+
*
|
30 |
+
* In this example, if you try to use a class in the Symfony\Component
|
31 |
+
* namespace or one of its children (Symfony\Component\Console for instance),
|
32 |
+
* the autoloader will first look for the class under the component/
|
33 |
+
* directory, and it will then fallback to the framework/ directory if not
|
34 |
+
* found before giving up.
|
35 |
+
*
|
36 |
+
* This class is loosely based on the Symfony UniversalClassLoader.
|
37 |
+
*
|
38 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
39 |
+
* @author Jordi Boggiano <j.boggiano@seld.be>
|
40 |
+
* @see https://www.php-fig.org/psr/psr-0/
|
41 |
+
* @see https://www.php-fig.org/psr/psr-4/
|
42 |
+
*/
|
43 |
+
class ClassLoader
|
44 |
+
{
|
45 |
+
/** @var ?string */
|
46 |
+
private $vendorDir;
|
47 |
+
|
48 |
+
// PSR-4
|
49 |
+
/**
|
50 |
+
* @var array[]
|
51 |
+
* @psalm-var array<string, array<string, int>>
|
52 |
+
*/
|
53 |
+
private $prefixLengthsPsr4 = array();
|
54 |
+
/**
|
55 |
+
* @var array[]
|
56 |
+
* @psalm-var array<string, array<int, string>>
|
57 |
+
*/
|
58 |
+
private $prefixDirsPsr4 = array();
|
59 |
+
/**
|
60 |
+
* @var array[]
|
61 |
+
* @psalm-var array<string, string>
|
62 |
+
*/
|
63 |
+
private $fallbackDirsPsr4 = array();
|
64 |
+
|
65 |
+
// PSR-0
|
66 |
+
/**
|
67 |
+
* @var array[]
|
68 |
+
* @psalm-var array<string, array<string, string[]>>
|
69 |
+
*/
|
70 |
+
private $prefixesPsr0 = array();
|
71 |
+
/**
|
72 |
+
* @var array[]
|
73 |
+
* @psalm-var array<string, string>
|
74 |
+
*/
|
75 |
+
private $fallbackDirsPsr0 = array();
|
76 |
+
|
77 |
+
/** @var bool */
|
78 |
+
private $useIncludePath = false;
|
79 |
+
|
80 |
+
/**
|
81 |
+
* @var string[]
|
82 |
+
* @psalm-var array<string, string>
|
83 |
+
*/
|
84 |
+
private $classMap = array();
|
85 |
+
|
86 |
+
/** @var bool */
|
87 |
+
private $classMapAuthoritative = false;
|
88 |
+
|
89 |
+
/**
|
90 |
+
* @var bool[]
|
91 |
+
* @psalm-var array<string, bool>
|
92 |
+
*/
|
93 |
+
private $missingClasses = array();
|
94 |
+
|
95 |
+
/** @var ?string */
|
96 |
+
private $apcuPrefix;
|
97 |
+
|
98 |
+
/**
|
99 |
+
* @var self[]
|
100 |
+
*/
|
101 |
+
private static $registeredLoaders = array();
|
102 |
+
|
103 |
+
/**
|
104 |
+
* @param ?string $vendorDir
|
105 |
+
*/
|
106 |
+
public function __construct($vendorDir = null)
|
107 |
+
{
|
108 |
+
$this->vendorDir = $vendorDir;
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* @return string[]
|
113 |
+
*/
|
114 |
+
public function getPrefixes()
|
115 |
+
{
|
116 |
+
if (!empty($this->prefixesPsr0)) {
|
117 |
+
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
118 |
+
}
|
119 |
+
|
120 |
+
return array();
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* @return array[]
|
125 |
+
* @psalm-return array<string, array<int, string>>
|
126 |
+
*/
|
127 |
+
public function getPrefixesPsr4()
|
128 |
+
{
|
129 |
+
return $this->prefixDirsPsr4;
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* @return array[]
|
134 |
+
* @psalm-return array<string, string>
|
135 |
+
*/
|
136 |
+
public function getFallbackDirs()
|
137 |
+
{
|
138 |
+
return $this->fallbackDirsPsr0;
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* @return array[]
|
143 |
+
* @psalm-return array<string, string>
|
144 |
+
*/
|
145 |
+
public function getFallbackDirsPsr4()
|
146 |
+
{
|
147 |
+
return $this->fallbackDirsPsr4;
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* @return string[] Array of classname => path
|
152 |
+
* @psalm-return array<string, string>
|
153 |
+
*/
|
154 |
+
public function getClassMap()
|
155 |
+
{
|
156 |
+
return $this->classMap;
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* @param string[] $classMap Class to filename map
|
161 |
+
* @psalm-param array<string, string> $classMap
|
162 |
+
*
|
163 |
+
* @return void
|
164 |
+
*/
|
165 |
+
public function addClassMap(array $classMap)
|
166 |
+
{
|
167 |
+
if ($this->classMap) {
|
168 |
+
$this->classMap = array_merge($this->classMap, $classMap);
|
169 |
+
} else {
|
170 |
+
$this->classMap = $classMap;
|
171 |
+
}
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Registers a set of PSR-0 directories for a given prefix, either
|
176 |
+
* appending or prepending to the ones previously set for this prefix.
|
177 |
+
*
|
178 |
+
* @param string $prefix The prefix
|
179 |
+
* @param string[]|string $paths The PSR-0 root directories
|
180 |
+
* @param bool $prepend Whether to prepend the directories
|
181 |
+
*
|
182 |
+
* @return void
|
183 |
+
*/
|
184 |
+
public function add($prefix, $paths, $prepend = false)
|
185 |
+
{
|
186 |
+
if (!$prefix) {
|
187 |
+
if ($prepend) {
|
188 |
+
$this->fallbackDirsPsr0 = array_merge(
|
189 |
+
(array) $paths,
|
190 |
+
$this->fallbackDirsPsr0
|
191 |
+
);
|
192 |
+
} else {
|
193 |
+
$this->fallbackDirsPsr0 = array_merge(
|
194 |
+
$this->fallbackDirsPsr0,
|
195 |
+
(array) $paths
|
196 |
+
);
|
197 |
+
}
|
198 |
+
|
199 |
+
return;
|
200 |
+
}
|
201 |
+
|
202 |
+
$first = $prefix[0];
|
203 |
+
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
204 |
+
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
205 |
+
|
206 |
+
return;
|
207 |
+
}
|
208 |
+
if ($prepend) {
|
209 |
+
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
210 |
+
(array) $paths,
|
211 |
+
$this->prefixesPsr0[$first][$prefix]
|
212 |
+
);
|
213 |
+
} else {
|
214 |
+
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
215 |
+
$this->prefixesPsr0[$first][$prefix],
|
216 |
+
(array) $paths
|
217 |
+
);
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Registers a set of PSR-4 directories for a given namespace, either
|
223 |
+
* appending or prepending to the ones previously set for this namespace.
|
224 |
+
*
|
225 |
+
* @param string $prefix The prefix/namespace, with trailing '\\'
|
226 |
+
* @param string[]|string $paths The PSR-4 base directories
|
227 |
+
* @param bool $prepend Whether to prepend the directories
|
228 |
+
*
|
229 |
+
* @throws \InvalidArgumentException
|
230 |
+
*
|
231 |
+
* @return void
|
232 |
+
*/
|
233 |
+
public function addPsr4($prefix, $paths, $prepend = false)
|
234 |
+
{
|
235 |
+
if (!$prefix) {
|
236 |
+
// Register directories for the root namespace.
|
237 |
+
if ($prepend) {
|
238 |
+
$this->fallbackDirsPsr4 = array_merge(
|
239 |
+
(array) $paths,
|
240 |
+
$this->fallbackDirsPsr4
|
241 |
+
);
|
242 |
+
} else {
|
243 |
+
$this->fallbackDirsPsr4 = array_merge(
|
244 |
+
$this->fallbackDirsPsr4,
|
245 |
+
(array) $paths
|
246 |
+
);
|
247 |
+
}
|
248 |
+
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
249 |
+
// Register directories for a new namespace.
|
250 |
+
$length = strlen($prefix);
|
251 |
+
if ('\\' !== $prefix[$length - 1]) {
|
252 |
+
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
253 |
+
}
|
254 |
+
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
255 |
+
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
256 |
+
} elseif ($prepend) {
|
257 |
+
// Prepend directories for an already registered namespace.
|
258 |
+
$this->prefixDirsPsr4[$prefix] = array_merge(
|
259 |
+
(array) $paths,
|
260 |
+
$this->prefixDirsPsr4[$prefix]
|
261 |
+
);
|
262 |
+
} else {
|
263 |
+
// Append directories for an already registered namespace.
|
264 |
+
$this->prefixDirsPsr4[$prefix] = array_merge(
|
265 |
+
$this->prefixDirsPsr4[$prefix],
|
266 |
+
(array) $paths
|
267 |
+
);
|
268 |
+
}
|
269 |
+
}
|
270 |
+
|
271 |
+
/**
|
272 |
+
* Registers a set of PSR-0 directories for a given prefix,
|
273 |
+
* replacing any others previously set for this prefix.
|
274 |
+
*
|
275 |
+
* @param string $prefix The prefix
|
276 |
+
* @param string[]|string $paths The PSR-0 base directories
|
277 |
+
*
|
278 |
+
* @return void
|
279 |
+
*/
|
280 |
+
public function set($prefix, $paths)
|
281 |
+
{
|
282 |
+
if (!$prefix) {
|
283 |
+
$this->fallbackDirsPsr0 = (array) $paths;
|
284 |
+
} else {
|
285 |
+
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
286 |
+
}
|
287 |
+
}
|
288 |
+
|
289 |
+
/**
|
290 |
+
* Registers a set of PSR-4 directories for a given namespace,
|
291 |
+
* replacing any others previously set for this namespace.
|
292 |
+
*
|
293 |
+
* @param string $prefix The prefix/namespace, with trailing '\\'
|
294 |
+
* @param string[]|string $paths The PSR-4 base directories
|
295 |
+
*
|
296 |
+
* @throws \InvalidArgumentException
|
297 |
+
*
|
298 |
+
* @return void
|
299 |
+
*/
|
300 |
+
public function setPsr4($prefix, $paths)
|
301 |
+
{
|
302 |
+
if (!$prefix) {
|
303 |
+
$this->fallbackDirsPsr4 = (array) $paths;
|
304 |
+
} else {
|
305 |
+
$length = strlen($prefix);
|
306 |
+
if ('\\' !== $prefix[$length - 1]) {
|
307 |
+
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
308 |
+
}
|
309 |
+
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
310 |
+
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
311 |
+
}
|
312 |
+
}
|
313 |
+
|
314 |
+
/**
|
315 |
+
* Turns on searching the include path for class files.
|
316 |
+
*
|
317 |
+
* @param bool $useIncludePath
|
318 |
+
*
|
319 |
+
* @return void
|
320 |
+
*/
|
321 |
+
public function setUseIncludePath($useIncludePath)
|
322 |
+
{
|
323 |
+
$this->useIncludePath = $useIncludePath;
|
324 |
+
}
|
325 |
+
|
326 |
+
/**
|
327 |
+
* Can be used to check if the autoloader uses the include path to check
|
328 |
+
* for classes.
|
329 |
+
*
|
330 |
+
* @return bool
|
331 |
+
*/
|
332 |
+
public function getUseIncludePath()
|
333 |
+
{
|
334 |
+
return $this->useIncludePath;
|
335 |
+
}
|
336 |
+
|
337 |
+
/**
|
338 |
+
* Turns off searching the prefix and fallback directories for classes
|
339 |
+
* that have not been registered with the class map.
|
340 |
+
*
|
341 |
+
* @param bool $classMapAuthoritative
|
342 |
+
*
|
343 |
+
* @return void
|
344 |
+
*/
|
345 |
+
public function setClassMapAuthoritative($classMapAuthoritative)
|
346 |
+
{
|
347 |
+
$this->classMapAuthoritative = $classMapAuthoritative;
|
348 |
+
}
|
349 |
+
|
350 |
+
/**
|
351 |
+
* Should class lookup fail if not found in the current class map?
|
352 |
+
*
|
353 |
+
* @return bool
|
354 |
+
*/
|
355 |
+
public function isClassMapAuthoritative()
|
356 |
+
{
|
357 |
+
return $this->classMapAuthoritative;
|
358 |
+
}
|
359 |
+
|
360 |
+
/**
|
361 |
+
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
362 |
+
*
|
363 |
+
* @param string|null $apcuPrefix
|
364 |
+
*
|
365 |
+
* @return void
|
366 |
+
*/
|
367 |
+
public function setApcuPrefix($apcuPrefix)
|
368 |
+
{
|
369 |
+
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
370 |
+
}
|
371 |
+
|
372 |
+
/**
|
373 |
+
* The APCu prefix in use, or null if APCu caching is not enabled.
|
374 |
+
*
|
375 |
+
* @return string|null
|
376 |
+
*/
|
377 |
+
public function getApcuPrefix()
|
378 |
+
{
|
379 |
+
return $this->apcuPrefix;
|
380 |
+
}
|
381 |
+
|
382 |
+
/**
|
383 |
+
* Registers this instance as an autoloader.
|
384 |
+
*
|
385 |
+
* @param bool $prepend Whether to prepend the autoloader or not
|
386 |
+
*
|
387 |
+
* @return void
|
388 |
+
*/
|
389 |
+
public function register($prepend = false)
|
390 |
+
{
|
391 |
+
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
392 |
+
|
393 |
+
if (null === $this->vendorDir) {
|
394 |
+
return;
|
395 |
+
}
|
396 |
+
|
397 |
+
if ($prepend) {
|
398 |
+
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
399 |
+
} else {
|
400 |
+
unset(self::$registeredLoaders[$this->vendorDir]);
|
401 |
+
self::$registeredLoaders[$this->vendorDir] = $this;
|
402 |
+
}
|
403 |
+
}
|
404 |
+
|
405 |
+
/**
|
406 |
+
* Unregisters this instance as an autoloader.
|
407 |
+
*
|
408 |
+
* @return void
|
409 |
+
*/
|
410 |
+
public function unregister()
|
411 |
+
{
|
412 |
+
spl_autoload_unregister(array($this, 'loadClass'));
|
413 |
+
|
414 |
+
if (null !== $this->vendorDir) {
|
415 |
+
unset(self::$registeredLoaders[$this->vendorDir]);
|
416 |
+
}
|
417 |
+
}
|
418 |
+
|
419 |
+
/**
|
420 |
+
* Loads the given class or interface.
|
421 |
+
*
|
422 |
+
* @param string $class The name of the class
|
423 |
+
* @return true|null True if loaded, null otherwise
|
424 |
+
*/
|
425 |
+
public function loadClass($class)
|
426 |
+
{
|
427 |
+
if ($file = $this->findFile($class)) {
|
428 |
+
includeFile($file);
|
429 |
+
|
430 |
+
return true;
|
431 |
+
}
|
432 |
+
|
433 |
+
return null;
|
434 |
+
}
|
435 |
+
|
436 |
+
/**
|
437 |
+
* Finds the path to the file where the class is defined.
|
438 |
+
*
|
439 |
+
* @param string $class The name of the class
|
440 |
+
*
|
441 |
+
* @return string|false The path if found, false otherwise
|
442 |
+
*/
|
443 |
+
public function findFile($class)
|
444 |
+
{
|
445 |
+
// class map lookup
|
446 |
+
if (isset($this->classMap[$class])) {
|
447 |
+
return $this->classMap[$class];
|
448 |
+
}
|
449 |
+
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
450 |
+
return false;
|
451 |
+
}
|
452 |
+
if (null !== $this->apcuPrefix) {
|
453 |
+
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
454 |
+
if ($hit) {
|
455 |
+
return $file;
|
456 |
+
}
|
457 |
+
}
|
458 |
+
|
459 |
+
$file = $this->findFileWithExtension($class, '.php');
|
460 |
+
|
461 |
+
// Search for Hack files if we are running on HHVM
|
462 |
+
if (false === $file && defined('HHVM_VERSION')) {
|
463 |
+
$file = $this->findFileWithExtension($class, '.hh');
|
464 |
+
}
|
465 |
+
|
466 |
+
if (null !== $this->apcuPrefix) {
|
467 |
+
apcu_add($this->apcuPrefix.$class, $file);
|
468 |
+
}
|
469 |
+
|
470 |
+
if (false === $file) {
|
471 |
+
// Remember that this class does not exist.
|
472 |
+
$this->missingClasses[$class] = true;
|
473 |
+
}
|
474 |
+
|
475 |
+
return $file;
|
476 |
+
}
|
477 |
+
|
478 |
+
/**
|
479 |
+
* Returns the currently registered loaders indexed by their corresponding vendor directories.
|
480 |
+
*
|
481 |
+
* @return self[]
|
482 |
+
*/
|
483 |
+
public static function getRegisteredLoaders()
|
484 |
+
{
|
485 |
+
return self::$registeredLoaders;
|
486 |
+
}
|
487 |
+
|
488 |
+
/**
|
489 |
+
* @param string $class
|
490 |
+
* @param string $ext
|
491 |
+
* @return string|false
|
492 |
+
*/
|
493 |
+
private function findFileWithExtension($class, $ext)
|
494 |
+
{
|
495 |
+
// PSR-4 lookup
|
496 |
+
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
497 |
+
|
498 |
+
$first = $class[0];
|
499 |
+
if (isset($this->prefixLengthsPsr4[$first])) {
|
500 |
+
$subPath = $class;
|
501 |
+
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
502 |
+
$subPath = substr($subPath, 0, $lastPos);
|
503 |
+
$search = $subPath . '\\';
|
504 |
+
if (isset($this->prefixDirsPsr4[$search])) {
|
505 |
+
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
506 |
+
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
507 |
+
if (file_exists($file = $dir . $pathEnd)) {
|
508 |
+
return $file;
|
509 |
+
}
|
510 |
+
}
|
511 |
+
}
|
512 |
+
}
|
513 |
+
}
|
514 |
+
|
515 |
+
// PSR-4 fallback dirs
|
516 |
+
foreach ($this->fallbackDirsPsr4 as $dir) {
|
517 |
+
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
518 |
+
return $file;
|
519 |
+
}
|
520 |
+
}
|
521 |
+
|
522 |
+
// PSR-0 lookup
|
523 |
+
if (false !== $pos = strrpos($class, '\\')) {
|
524 |
+
// namespaced class name
|
525 |
+
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
526 |
+
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
527 |
+
} else {
|
528 |
+
// PEAR-like class name
|
529 |
+
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
530 |
+
}
|
531 |
+
|
532 |
+
if (isset($this->prefixesPsr0[$first])) {
|
533 |
+
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
534 |
+
if (0 === strpos($class, $prefix)) {
|
535 |
+
foreach ($dirs as $dir) {
|
536 |
+
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
537 |
+
return $file;
|
538 |
+
}
|
539 |
+
}
|
540 |
+
}
|
541 |
+
}
|
542 |
+
}
|
543 |
+
|
544 |
+
// PSR-0 fallback dirs
|
545 |
+
foreach ($this->fallbackDirsPsr0 as $dir) {
|
546 |
+
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
547 |
+
return $file;
|
548 |
+
}
|
549 |
+
}
|
550 |
+
|
551 |
+
// PSR-0 include paths.
|
552 |
+
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
553 |
+
return $file;
|
554 |
+
}
|
555 |
+
|
556 |
+
return false;
|
557 |
+
}
|
558 |
+
}
|
559 |
+
|
560 |
+
/**
|
561 |
+
* Scope isolated include.
|
562 |
+
*
|
563 |
+
* Prevents access to $this/self from included files.
|
564 |
+
*
|
565 |
+
* @param string $file
|
566 |
+
* @return void
|
567 |
+
* @private
|
568 |
+
*/
|
569 |
+
function includeFile($file)
|
570 |
+
{
|
571 |
+
include $file;
|
572 |
+
}
|
vendor/composer/InstalledVersions.php
ADDED
@@ -0,0 +1,352 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Composer.
|
5 |
+
*
|
6 |
+
* (c) Nils Adermann <naderman@naderman.de>
|
7 |
+
* Jordi Boggiano <j.boggiano@seld.be>
|
8 |
+
*
|
9 |
+
* For the full copyright and license information, please view the LICENSE
|
10 |
+
* file that was distributed with this source code.
|
11 |
+
*/
|
12 |
+
|
13 |
+
namespace Composer;
|
14 |
+
|
15 |
+
use Composer\Autoload\ClassLoader;
|
16 |
+
use Composer\Semver\VersionParser;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* This class is copied in every Composer installed project and available to all
|
20 |
+
*
|
21 |
+
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
22 |
+
*
|
23 |
+
* To require its presence, you can require `composer-runtime-api ^2.0`
|
24 |
+
*
|
25 |
+
* @final
|
26 |
+
*/
|
27 |
+
class InstalledVersions
|
28 |
+
{
|
29 |
+
/**
|
30 |
+
* @var mixed[]|null
|
31 |
+
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
32 |
+
*/
|
33 |
+
private static $installed;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @var bool|null
|
37 |
+
*/
|
38 |
+
private static $canGetVendors;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @var array[]
|
42 |
+
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
43 |
+
*/
|
44 |
+
private static $installedByVendor = array();
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
48 |
+
*
|
49 |
+
* @return string[]
|
50 |
+
* @psalm-return list<string>
|
51 |
+
*/
|
52 |
+
public static function getInstalledPackages()
|
53 |
+
{
|
54 |
+
$packages = array();
|
55 |
+
foreach (self::getInstalled() as $installed) {
|
56 |
+
$packages[] = array_keys($installed['versions']);
|
57 |
+
}
|
58 |
+
|
59 |
+
if (1 === \count($packages)) {
|
60 |
+
return $packages[0];
|
61 |
+
}
|
62 |
+
|
63 |
+
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Returns a list of all package names with a specific type e.g. 'library'
|
68 |
+
*
|
69 |
+
* @param string $type
|
70 |
+
* @return string[]
|
71 |
+
* @psalm-return list<string>
|
72 |
+
*/
|
73 |
+
public static function getInstalledPackagesByType($type)
|
74 |
+
{
|
75 |
+
$packagesByType = array();
|
76 |
+
|
77 |
+
foreach (self::getInstalled() as $installed) {
|
78 |
+
foreach ($installed['versions'] as $name => $package) {
|
79 |
+
if (isset($package['type']) && $package['type'] === $type) {
|
80 |
+
$packagesByType[] = $name;
|
81 |
+
}
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
return $packagesByType;
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Checks whether the given package is installed
|
90 |
+
*
|
91 |
+
* This also returns true if the package name is provided or replaced by another package
|
92 |
+
*
|
93 |
+
* @param string $packageName
|
94 |
+
* @param bool $includeDevRequirements
|
95 |
+
* @return bool
|
96 |
+
*/
|
97 |
+
public static function isInstalled($packageName, $includeDevRequirements = true)
|
98 |
+
{
|
99 |
+
foreach (self::getInstalled() as $installed) {
|
100 |
+
if (isset($installed['versions'][$packageName])) {
|
101 |
+
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
return false;
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Checks whether the given package satisfies a version constraint
|
110 |
+
*
|
111 |
+
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
112 |
+
*
|
113 |
+
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
114 |
+
*
|
115 |
+
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
116 |
+
* @param string $packageName
|
117 |
+
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
118 |
+
* @return bool
|
119 |
+
*/
|
120 |
+
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
121 |
+
{
|
122 |
+
$constraint = $parser->parseConstraints($constraint);
|
123 |
+
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
124 |
+
|
125 |
+
return $provided->matches($constraint);
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Returns a version constraint representing all the range(s) which are installed for a given package
|
130 |
+
*
|
131 |
+
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
132 |
+
* whether a given version of a package is installed, and not just whether it exists
|
133 |
+
*
|
134 |
+
* @param string $packageName
|
135 |
+
* @return string Version constraint usable with composer/semver
|
136 |
+
*/
|
137 |
+
public static function getVersionRanges($packageName)
|
138 |
+
{
|
139 |
+
foreach (self::getInstalled() as $installed) {
|
140 |
+
if (!isset($installed['versions'][$packageName])) {
|
141 |
+
continue;
|
142 |
+
}
|
143 |
+
|
144 |
+
$ranges = array();
|
145 |
+
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
146 |
+
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
147 |
+
}
|
148 |
+
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
149 |
+
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
150 |
+
}
|
151 |
+
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
152 |
+
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
153 |
+
}
|
154 |
+
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
155 |
+
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
156 |
+
}
|
157 |
+
|
158 |
+
return implode(' || ', $ranges);
|
159 |
+
}
|
160 |
+
|
161 |
+
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* @param string $packageName
|
166 |
+
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
167 |
+
*/
|
168 |
+
public static function getVersion($packageName)
|
169 |
+
{
|
170 |
+
foreach (self::getInstalled() as $installed) {
|
171 |
+
if (!isset($installed['versions'][$packageName])) {
|
172 |
+
continue;
|
173 |
+
}
|
174 |
+
|
175 |
+
if (!isset($installed['versions'][$packageName]['version'])) {
|
176 |
+
return null;
|
177 |
+
}
|
178 |
+
|
179 |
+
return $installed['versions'][$packageName]['version'];
|
180 |
+
}
|
181 |
+
|
182 |
+
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* @param string $packageName
|
187 |
+
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
188 |
+
*/
|
189 |
+
public static function getPrettyVersion($packageName)
|
190 |
+
{
|
191 |
+
foreach (self::getInstalled() as $installed) {
|
192 |
+
if (!isset($installed['versions'][$packageName])) {
|
193 |
+
continue;
|
194 |
+
}
|
195 |
+
|
196 |
+
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
197 |
+
return null;
|
198 |
+
}
|
199 |
+
|
200 |
+
return $installed['versions'][$packageName]['pretty_version'];
|
201 |
+
}
|
202 |
+
|
203 |
+
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
204 |
+
}
|
205 |
+
|
206 |
+
/**
|
207 |
+
* @param string $packageName
|
208 |
+
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
209 |
+
*/
|
210 |
+
public static function getReference($packageName)
|
211 |
+
{
|
212 |
+
foreach (self::getInstalled() as $installed) {
|
213 |
+
if (!isset($installed['versions'][$packageName])) {
|
214 |
+
continue;
|
215 |
+
}
|
216 |
+
|
217 |
+
if (!isset($installed['versions'][$packageName]['reference'])) {
|
218 |
+
return null;
|
219 |
+
}
|
220 |
+
|
221 |
+
return $installed['versions'][$packageName]['reference'];
|
222 |
+
}
|
223 |
+
|
224 |
+
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* @param string $packageName
|
229 |
+
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
230 |
+
*/
|
231 |
+
public static function getInstallPath($packageName)
|
232 |
+
{
|
233 |
+
foreach (self::getInstalled() as $installed) {
|
234 |
+
if (!isset($installed['versions'][$packageName])) {
|
235 |
+
continue;
|
236 |
+
}
|
237 |
+
|
238 |
+
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
239 |
+
}
|
240 |
+
|
241 |
+
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* @return array
|
246 |
+
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
247 |
+
*/
|
248 |
+
public static function getRootPackage()
|
249 |
+
{
|
250 |
+
$installed = self::getInstalled();
|
251 |
+
|
252 |
+
return $installed[0]['root'];
|
253 |
+
}
|
254 |
+
|
255 |
+
/**
|
256 |
+
* Returns the raw installed.php data for custom implementations
|
257 |
+
*
|
258 |
+
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
259 |
+
* @return array[]
|
260 |
+
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
261 |
+
*/
|
262 |
+
public static function getRawData()
|
263 |
+
{
|
264 |
+
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
265 |
+
|
266 |
+
if (null === self::$installed) {
|
267 |
+
// only require the installed.php file if this file is loaded from its dumped location,
|
268 |
+
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
269 |
+
if (substr(__DIR__, -8, 1) !== 'C') {
|
270 |
+
self::$installed = include __DIR__ . '/installed.php';
|
271 |
+
} else {
|
272 |
+
self::$installed = array();
|
273 |
+
}
|
274 |
+
}
|
275 |
+
|
276 |
+
return self::$installed;
|
277 |
+
}
|
278 |
+
|
279 |
+
/**
|
280 |
+
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
281 |
+
*
|
282 |
+
* @return array[]
|
283 |
+
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
284 |
+
*/
|
285 |
+
public static function getAllRawData()
|
286 |
+
{
|
287 |
+
return self::getInstalled();
|
288 |
+
}
|
289 |
+
|
290 |
+
/**
|
291 |
+
* Lets you reload the static array from another file
|
292 |
+
*
|
293 |
+
* This is only useful for complex integrations in which a project needs to use
|
294 |
+
* this class but then also needs to execute another project's autoloader in process,
|
295 |
+
* and wants to ensure both projects have access to their version of installed.php.
|
296 |
+
*
|
297 |
+
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
298 |
+
* the data it needs from this class, then call reload() with
|
299 |
+
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
300 |
+
* the project in which it runs can then also use this class safely, without
|
301 |
+
* interference between PHPUnit's dependencies and the project's dependencies.
|
302 |
+
*
|
303 |
+
* @param array[] $data A vendor/composer/installed.php data set
|
304 |
+
* @return void
|
305 |
+
*
|
306 |
+
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
307 |
+
*/
|
308 |
+
public static function reload($data)
|
309 |
+
{
|
310 |
+
self::$installed = $data;
|
311 |
+
self::$installedByVendor = array();
|
312 |
+
}
|
313 |
+
|
314 |
+
/**
|
315 |
+
* @return array[]
|
316 |
+
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
317 |
+
*/
|
318 |
+
private static function getInstalled()
|
319 |
+
{
|
320 |
+
if (null === self::$canGetVendors) {
|
321 |
+
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
322 |
+
}
|
323 |
+
|
324 |
+
$installed = array();
|
325 |
+
|
326 |
+
if (self::$canGetVendors) {
|
327 |
+
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
328 |
+
if (isset(self::$installedByVendor[$vendorDir])) {
|
329 |
+
$installed[] = self::$installedByVendor[$vendorDir];
|
330 |
+
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
331 |
+
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
|
332 |
+
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
333 |
+
self::$installed = $installed[count($installed) - 1];
|
334 |
+
}
|
335 |
+
}
|
336 |
+
}
|
337 |
+
}
|
338 |
+
|
339 |
+
if (null === self::$installed) {
|
340 |
+
// only require the installed.php file if this file is loaded from its dumped location,
|
341 |
+
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
342 |
+
if (substr(__DIR__, -8, 1) !== 'C') {
|
343 |
+
self::$installed = require __DIR__ . '/installed.php';
|
344 |
+
} else {
|
345 |
+
self::$installed = array();
|
346 |
+
}
|
347 |
+
}
|
348 |
+
$installed[] = self::$installed;
|
349 |
+
|
350 |
+
return $installed;
|
351 |
+
}
|
352 |
+
}
|
vendor/composer/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
Copyright (c) Nils Adermann, Jordi Boggiano
|
3 |
+
|
4 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 |
+
of this software and associated documentation files (the "Software"), to deal
|
6 |
+
in the Software without restriction, including without limitation the rights
|
7 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8 |
+
copies of the Software, and to permit persons to whom the Software is furnished
|
9 |
+
to do so, subject to the following conditions:
|
10 |
+
|
11 |
+
The above copyright notice and this permission notice shall be included in all
|
12 |
+
copies or substantial portions of the Software.
|
13 |
+
|
14 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20 |
+
THE SOFTWARE.
|
21 |
+
|
vendor/composer/autoload_classmap.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_classmap.php @generated by Composer
|
4 |
+
|
5 |
+
$vendorDir = dirname(__DIR__);
|
6 |
+
$baseDir = dirname($vendorDir);
|
7 |
+
|
8 |
+
return array(
|
9 |
+
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
10 |
+
);
|
vendor/composer/autoload_namespaces.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_namespaces.php @generated by Composer
|
4 |
+
|
5 |
+
$vendorDir = dirname(__DIR__);
|
6 |
+
$baseDir = dirname($vendorDir);
|
7 |
+
|
8 |
+
return array(
|
9 |
+
);
|
vendor/composer/autoload_psr4.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_psr4.php @generated by Composer
|
4 |
+
|
5 |
+
$vendorDir = dirname(__DIR__);
|
6 |
+
$baseDir = dirname($vendorDir);
|
7 |
+
|
8 |
+
return array(
|
9 |
+
'IPLib\\' => array($vendorDir . '/mlocati/ip-lib/src'),
|
10 |
+
);
|
vendor/composer/autoload_real.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_real.php @generated by Composer
|
4 |
+
|
5 |
+
class ComposerAutoloaderInita3f7bfdb9e7229bdf95aaef37022fd47
|
6 |
+
{
|
7 |
+
private static $loader;
|
8 |
+
|
9 |
+
public static function loadClassLoader($class)
|
10 |
+
{
|
11 |
+
if ('Composer\Autoload\ClassLoader' === $class) {
|
12 |
+
require __DIR__ . '/ClassLoader.php';
|
13 |
+
}
|
14 |
+
}
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @return \Composer\Autoload\ClassLoader
|
18 |
+
*/
|
19 |
+
public static function getLoader()
|
20 |
+
{
|
21 |
+
if (null !== self::$loader) {
|
22 |
+
return self::$loader;
|
23 |
+
}
|
24 |
+
|
25 |
+
require __DIR__ . '/platform_check.php';
|
26 |
+
|
27 |
+
spl_autoload_register(array('ComposerAutoloaderInita3f7bfdb9e7229bdf95aaef37022fd47', 'loadClassLoader'), true, true);
|
28 |
+
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
29 |
+
spl_autoload_unregister(array('ComposerAutoloaderInita3f7bfdb9e7229bdf95aaef37022fd47', 'loadClassLoader'));
|
30 |
+
|
31 |
+
require __DIR__ . '/autoload_static.php';
|
32 |
+
call_user_func(\Composer\Autoload\ComposerStaticInita3f7bfdb9e7229bdf95aaef37022fd47::getInitializer($loader));
|
33 |
+
|
34 |
+
$loader->register(true);
|
35 |
+
|
36 |
+
return $loader;
|
37 |
+
}
|
38 |
+
}
|
vendor/composer/autoload_static.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_static.php @generated by Composer
|
4 |
+
|
5 |
+
namespace Composer\Autoload;
|
6 |
+
|
7 |
+
class ComposerStaticInita3f7bfdb9e7229bdf95aaef37022fd47
|
8 |
+
{
|
9 |
+
public static $prefixLengthsPsr4 = array (
|
10 |
+
'I' =>
|
11 |
+
array (
|
12 |
+
'IPLib\\' => 6,
|
13 |
+
),
|
14 |
+
);
|
15 |
+
|
16 |
+
public static $prefixDirsPsr4 = array (
|
17 |
+
'IPLib\\' =>
|
18 |
+
array (
|
19 |
+
0 => __DIR__ . '/..' . '/mlocati/ip-lib/src',
|
20 |
+
),
|
21 |
+
);
|
22 |
+
|
23 |
+
public static $classMap = array (
|
24 |
+
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
25 |
+
);
|
26 |
+
|
27 |
+
public static function getInitializer(ClassLoader $loader)
|
28 |
+
{
|
29 |
+
return \Closure::bind(function () use ($loader) {
|
30 |
+
$loader->prefixLengthsPsr4 = ComposerStaticInita3f7bfdb9e7229bdf95aaef37022fd47::$prefixLengthsPsr4;
|
31 |
+
$loader->prefixDirsPsr4 = ComposerStaticInita3f7bfdb9e7229bdf95aaef37022fd47::$prefixDirsPsr4;
|
32 |
+
$loader->classMap = ComposerStaticInita3f7bfdb9e7229bdf95aaef37022fd47::$classMap;
|
33 |
+
|
34 |
+
}, null, ClassLoader::class);
|
35 |
+
}
|
36 |
+
}
|
vendor/composer/installed.json
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"packages": [
|
3 |
+
{
|
4 |
+
"name": "mlocati/ip-lib",
|
5 |
+
"version": "dev-master",
|
6 |
+
"version_normalized": "dev-master",
|
7 |
+
"source": {
|
8 |
+
"type": "git",
|
9 |
+
"url": "https://github.com/mlocati/ip-lib.git",
|
10 |
+
"reference": "a6e4af68a4820f76444e31ddb8e7cc52bd61c549"
|
11 |
+
},
|
12 |
+
"dist": {
|
13 |
+
"type": "zip",
|
14 |
+
"url": "https://api.github.com/repos/mlocati/ip-lib/zipball/a6e4af68a4820f76444e31ddb8e7cc52bd61c549",
|
15 |
+
"reference": "a6e4af68a4820f76444e31ddb8e7cc52bd61c549",
|
16 |
+
"shasum": ""
|
17 |
+
},
|
18 |
+
"require": {
|
19 |
+
"php": ">=5.3.3"
|
20 |
+
},
|
21 |
+
"require-dev": {
|
22 |
+
"ext-pdo_sqlite": "*",
|
23 |
+
"phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.5 || ^8.5 || ^9.5"
|
24 |
+
},
|
25 |
+
"time": "2022-08-11T14:01:00+00:00",
|
26 |
+
"default-branch": true,
|
27 |
+
"type": "library",
|
28 |
+
"installation-source": "dist",
|
29 |
+
"autoload": {
|
30 |
+
"psr-4": {
|
31 |
+
"IPLib\\": "src/"
|
32 |
+
}
|
33 |
+
},
|
34 |
+
"notification-url": "https://packagist.org/downloads/",
|
35 |
+
"license": [
|
36 |
+
"MIT"
|
37 |
+
],
|
38 |
+
"authors": [
|
39 |
+
{
|
40 |
+
"name": "Michele Locati",
|
41 |
+
"email": "mlocati@gmail.com",
|
42 |
+
"homepage": "https://github.com/mlocati",
|
43 |
+
"role": "Author"
|
44 |
+
}
|
45 |
+
],
|
46 |
+
"description": "Handle IPv4, IPv6 addresses and ranges",
|
47 |
+
"homepage": "https://github.com/mlocati/ip-lib",
|
48 |
+
"keywords": [
|
49 |
+
"IP",
|
50 |
+
"address",
|
51 |
+
"addresses",
|
52 |
+
"ipv4",
|
53 |
+
"ipv6",
|
54 |
+
"manage",
|
55 |
+
"managing",
|
56 |
+
"matching",
|
57 |
+
"network",
|
58 |
+
"networking",
|
59 |
+
"range",
|
60 |
+
"subnet"
|
61 |
+
],
|
62 |
+
"support": {
|
63 |
+
"issues": "https://github.com/mlocati/ip-lib/issues",
|
64 |
+
"source": "https://github.com/mlocati/ip-lib/tree/master"
|
65 |
+
},
|
66 |
+
"funding": [
|
67 |
+
{
|
68 |
+
"url": "https://github.com/sponsors/mlocati",
|
69 |
+
"type": "github"
|
70 |
+
},
|
71 |
+
{
|
72 |
+
"url": "https://paypal.me/mlocati",
|
73 |
+
"type": "other"
|
74 |
+
}
|
75 |
+
],
|
76 |
+
"install-path": "../mlocati/ip-lib"
|
77 |
+
}
|
78 |
+
],
|
79 |
+
"dev": false,
|
80 |
+
"dev-package-names": []
|
81 |
+
}
|
vendor/composer/installed.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php return array(
|
2 |
+
'root' => array(
|
3 |
+
'name' => '10up/restricted-site-access',
|
4 |
+
'pretty_version' => '7.3.4',
|
5 |
+
'version' => '7.3.4.0',
|
6 |
+
'reference' => '4abd9aadf8d0626f89322559a3ca041c61214b63',
|
7 |
+
'type' => 'wordpress-plugin',
|
8 |
+
'install_path' => __DIR__ . '/../../',
|
9 |
+
'aliases' => array(),
|
10 |
+
'dev' => false,
|
11 |
+
),
|
12 |
+
'versions' => array(
|
13 |
+
'10up/restricted-site-access' => array(
|
14 |
+
'pretty_version' => '7.3.4',
|
15 |
+
'version' => '7.3.4.0',
|
16 |
+
'reference' => '4abd9aadf8d0626f89322559a3ca041c61214b63',
|
17 |
+
'type' => 'wordpress-plugin',
|
18 |
+
'install_path' => __DIR__ . '/../../',
|
19 |
+
'aliases' => array(),
|
20 |
+
'dev_requirement' => false,
|
21 |
+
),
|
22 |
+
'mlocati/ip-lib' => array(
|
23 |
+
'pretty_version' => 'dev-master',
|
24 |
+
'version' => 'dev-master',
|
25 |
+
'reference' => 'a6e4af68a4820f76444e31ddb8e7cc52bd61c549',
|
26 |
+
'type' => 'library',
|
27 |
+
'install_path' => __DIR__ . '/../mlocati/ip-lib',
|
28 |
+
'aliases' => array(
|
29 |
+
0 => '9999999-dev',
|
30 |
+
),
|
31 |
+
'dev_requirement' => false,
|
32 |
+
),
|
33 |
+
),
|
34 |
+
);
|
vendor/composer/platform_check.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// platform_check.php @generated by Composer
|
4 |
+
|
5 |
+
$issues = array();
|
6 |
+
|
7 |
+
if (!(PHP_VERSION_ID >= 50303)) {
|
8 |
+
$issues[] = 'Your Composer dependencies require a PHP version ">= 5.3.3". You are running ' . PHP_VERSION . '.';
|
9 |
+
}
|
10 |
+
|
11 |
+
if ($issues) {
|
12 |
+
if (!headers_sent()) {
|
13 |
+
header('HTTP/1.1 500 Internal Server Error');
|
14 |
+
}
|
15 |
+
if (!ini_get('display_errors')) {
|
16 |
+
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
17 |
+
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
|
18 |
+
} elseif (!headers_sent()) {
|
19 |
+
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
20 |
+
}
|
21 |
+
}
|
22 |
+
trigger_error(
|
23 |
+
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
24 |
+
E_USER_ERROR
|
25 |
+
);
|
26 |
+
}
|
vendor/mlocati/ip-lib/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
The MIT License (MIT)
|
2 |
+
Copyright (c) 2016 Michele Locati
|
3 |
+
|
4 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 |
+
of this software and associated documentation files (the "Software"), to deal
|
6 |
+
in the Software without restriction, including without limitation the rights
|
7 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8 |
+
copies of the Software, and to permit persons to whom the Software is furnished
|
9 |
+
to do so, subject to the following conditions:
|
10 |
+
|
11 |
+
The above copyright notice and this permission notice shall be included in all
|
12 |
+
copies or substantial portions of the Software.
|
13 |
+
|
14 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20 |
+
THE SOFTWARE.
|
vendor/mlocati/ip-lib/ip-lib.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
spl_autoload_register(
|
4 |
+
function ($class) {
|
5 |
+
if (strpos($class, 'IPLib\\') !== 0) {
|
6 |
+
return;
|
7 |
+
}
|
8 |
+
$file = __DIR__ . DIRECTORY_SEPARATOR . 'src' . str_replace('\\', DIRECTORY_SEPARATOR, substr($class, strlen('IPLib'))) . '.php';
|
9 |
+
if (is_file($file)) {
|
10 |
+
require_once $file;
|
11 |
+
}
|
12 |
+
}
|
13 |
+
);
|
vendor/mlocati/ip-lib/src/Address/AddressInterface.php
ADDED
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace IPLib\Address;
|
4 |
+
|
5 |
+
use IPLib\Range\RangeInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Interface of all the IP address types.
|
9 |
+
*/
|
10 |
+
interface AddressInterface
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Get the short string representation of this address.
|
14 |
+
*
|
15 |
+
* @return string
|
16 |
+
*/
|
17 |
+
public function __toString();
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Get the number of bits representing this address type.
|
21 |
+
*
|
22 |
+
* @return int
|
23 |
+
*
|
24 |
+
* @since 1.14.0
|
25 |
+
*
|
26 |
+
* @example 32 for IPv4
|
27 |
+
* @example 128 for IPv6
|
28 |
+
*/
|
29 |
+
public static function getNumberOfBits();
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Get the string representation of this address.
|
33 |
+
*
|
34 |
+
* @param bool $long set to true to have a long/full representation, false otherwise
|
35 |
+
*
|
36 |
+
* @return string
|
37 |
+
*
|
38 |
+
* @example If $long is true, you'll get '0000:0000:0000:0000:0000:0000:0000:0001', '::1' otherwise.
|
39 |
+
*/
|
40 |
+
public function toString($long = false);
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Get the byte list of the IP address.
|
44 |
+
*
|
45 |
+
* @return int[]
|
46 |
+
*
|
47 |
+
* @example For localhost: for IPv4 you'll get array(127, 0, 0, 1), for IPv6 array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)
|
48 |
+
*/
|
49 |
+
public function getBytes();
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Get the full bit list the IP address.
|
53 |
+
*
|
54 |
+
* @return string
|
55 |
+
*
|
56 |
+
* @since 1.14.0
|
57 |
+
*
|
58 |
+
* @example For localhost: For IPv4 you'll get '01111111000000000000000000000001' (32 digits), for IPv6 '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001' (128 digits)
|
59 |
+
*/
|
60 |
+
public function getBits();
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Get the type of the IP address.
|
64 |
+
*
|
65 |
+
* @return int One of the \IPLib\Address\Type::T_... constants
|
66 |
+
*/
|
67 |
+
public function getAddressType();
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Get the default RFC reserved range type.
|
71 |
+
*
|
72 |
+
* @return int One of the \IPLib\Range\Type::T_... constants
|
73 |
+
*
|
74 |
+
* @since 1.5.0
|
75 |
+
*/
|
76 |
+
public static function getDefaultReservedRangeType();
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Get the RFC reserved ranges (except the ones of type getDefaultReservedRangeType).
|
80 |
+
*
|
81 |
+
* @return \IPLib\Address\AssignedRange[] ranges are sorted
|
82 |
+
*
|
83 |
+
* @since 1.5.0
|
84 |
+
*/
|
85 |
+
public static function getReservedRanges();
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Get the type of range of the IP address.
|
89 |
+
*
|
90 |
+
* @return int One of the \IPLib\Range\Type::T_... constants
|
91 |
+
*/
|
92 |
+
public function getRangeType();
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Get a string representation of this address than can be used when comparing addresses and ranges.
|
96 |
+
*
|
97 |
+
* @return string
|
98 |
+
*/
|
99 |
+
public function getComparableString();
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Check if this address is contained in an range.
|
103 |
+
*
|
104 |
+
* @param \IPLib\Range\RangeInterface $range
|
105 |
+
*
|
106 |
+
* @return bool
|
107 |
+
*/
|
108 |
+
public function matches(RangeInterface $range);
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Get the address at a certain distance from this address.
|
112 |
+
*
|
113 |
+
* @param int $n the distance of the address (can be negative)
|
114 |
+
*
|
115 |
+
* @return \IPLib\Address\AddressInterface|null return NULL if $n is not an integer or if the final address would be invalid
|
116 |
+
*
|
117 |
+
* @since 1.15.0
|
118 |
+
*
|
119 |
+
* @example passing 1 to the address 127.0.0.1 will result in 127.0.0.2
|
120 |
+
* @example passing -1 to the address 127.0.0.1 will result in 127.0.0.0
|
121 |
+
* @example passing -1 to the address 0.0.0.0 will result in NULL
|
122 |
+
*/
|
123 |
+
public function getAddressAtOffset($n);
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Get the address right after this IP address (if available).
|
127 |
+
*
|
128 |
+
* @return \IPLib\Address\AddressInterface|null
|
129 |
+
*
|
130 |
+
* @see \IPLib\Address\AddressInterface::getAddressAtOffset()
|
131 |
+
* @since 1.4.0
|
132 |
+
*/
|
133 |
+
public function getNextAddress();
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Get the address right before this IP address (if available).
|
137 |
+
*
|
138 |
+
* @return \IPLib\Address\AddressInterface|null
|
139 |
+
*
|
140 |
+
* @see \IPLib\Address\AddressInterface::getAddressAtOffset()
|
141 |
+
* @since 1.4.0
|
142 |
+
*/
|
143 |
+
public function getPreviousAddress();
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Get the Reverse DNS Lookup Address of this IP address.
|
147 |
+
*
|
148 |
+
* @return string
|
149 |
+
*
|
150 |
+
* @since 1.12.0
|
151 |
+
*
|
152 |
+
* @example for IPv4 it returns something like x.x.x.x.in-addr.arpa
|
153 |
+
* @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
|
154 |
+
*/
|
155 |
+
public function getReverseDNSLookupName();
|
156 |
+
}
|
vendor/mlocati/ip-lib/src/Address/AssignedRange.php
ADDED
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace IPLib\Address;
|
4 |
+
|
5 |
+
use IPLib\Range\RangeInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Represents an IP address range with an assigned range type.
|
9 |
+
*
|
10 |
+
* @since 1.5.0
|
11 |
+
*/
|
12 |
+
class AssignedRange
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* The range definition.
|
16 |
+
*
|
17 |
+
* @var \IPLib\Range\RangeInterface
|
18 |
+
*/
|
19 |
+
protected $range;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* The range type.
|
23 |
+
*
|
24 |
+
* @var int one of the \IPLib\Range\Type::T_ constants
|
25 |
+
*/
|
26 |
+
protected $type;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* The list of exceptions for this range type.
|
30 |
+
*
|
31 |
+
* @var \IPLib\Address\AssignedRange[]
|
32 |
+
*/
|
33 |
+
protected $exceptions;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Initialize the instance.
|
37 |
+
*
|
38 |
+
* @param \IPLib\Range\RangeInterface $range the range definition
|
39 |
+
* @param int $type The range type (one of the \IPLib\Range\Type::T_ constants)
|
40 |
+
* @param \IPLib\Address\AssignedRange[] $exceptions the list of exceptions for this range type
|
41 |
+
*/
|
42 |
+
public function __construct(RangeInterface $range, $type, array $exceptions = array())
|
43 |
+
{
|
44 |
+
$this->range = $range;
|
45 |
+
$this->type = $type;
|
46 |
+
$this->exceptions = $exceptions;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Get the range definition.
|
51 |
+
*
|
52 |
+
* @return \IPLib\Range\RangeInterface
|
53 |
+
*/
|
54 |
+
public function getRange()
|
55 |
+
{
|
56 |
+
return $this->range;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Get the range type.
|
61 |
+
*
|
62 |
+
* @return int one of the \IPLib\Range\Type::T_ constants
|
63 |
+
*/
|
64 |
+
public function getType()
|
65 |
+
{
|
66 |
+
return $this->type;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Get the list of exceptions for this range type.
|
71 |
+
*
|
72 |
+
* @return \IPLib\Address\AssignedRange[]
|
73 |
+
*/
|
74 |
+
public function getExceptions()
|
75 |
+
{
|
76 |
+
return $this->exceptions;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Get the assigned type for a specific address.
|
81 |
+
*
|
82 |
+
* @param \IPLib\Address\AddressInterface $address
|
83 |
+
*
|
84 |
+
* @return int|null return NULL of the address is outside this address; a \IPLib\Range\Type::T_ constant otherwise
|
85 |
+
*/
|
86 |
+
public function getAddressType(AddressInterface $address)
|
87 |
+
{
|
88 |
+
$result = null;
|
89 |
+
if ($this->range->contains($address)) {
|
90 |
+
foreach ($this->exceptions as $exception) {
|
91 |
+
$result = $exception->getAddressType($address);
|
92 |
+
if ($result !== null) {
|
93 |
+
break;
|
94 |
+
}
|
95 |
+
}
|
96 |
+
if ($result === null) {
|
97 |
+
$result = $this->type;
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
return $result;
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Get the assigned type for a specific address range.
|
106 |
+
*
|
107 |
+
* @param \IPLib\Range\RangeInterface $range
|
108 |
+
*
|
109 |
+
* @return int|false|null return NULL of the range is fully outside this range; false if it's partly crosses this range (or it contains mixed types); a \IPLib\Range\Type::T_ constant otherwise
|
110 |
+
*/
|
111 |
+
public function getRangeType(RangeInterface $range)
|
112 |
+
{
|
113 |
+
$myStart = $this->range->getComparableStartString();
|
114 |
+
$rangeEnd = $range->getComparableEndString();
|
115 |
+
if ($myStart > $rangeEnd) {
|
116 |
+
$result = null;
|
117 |
+
} else {
|
118 |
+
$myEnd = $this->range->getComparableEndString();
|
119 |
+
$rangeStart = $range->getComparableStartString();
|
120 |
+
if ($myEnd < $rangeStart) {
|
121 |
+
$result = null;
|
122 |
+
} elseif ($rangeStart < $myStart || $rangeEnd > $myEnd) {
|
123 |
+
$result = false;
|
124 |
+
} else {
|
125 |
+
$result = null;
|
126 |
+
foreach ($this->exceptions as $exception) {
|
127 |
+
$result = $exception->getRangeType($range);
|
128 |
+
if ($result !== null) {
|
129 |
+
break;
|
130 |
+
}
|
131 |
+
}
|
132 |
+
if ($result === null) {
|
133 |
+
$result = $this->getType();
|
134 |
+
}
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
return $result;
|
139 |
+
}
|
140 |
+
}
|
vendor/mlocati/ip-lib/src/Address/IPv4.php
ADDED
@@ -0,0 +1,515 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace IPLib\Address;
|
4 |
+
|
5 |
+
use IPLib\ParseStringFlag;
|
6 |
+
use IPLib\Range\RangeInterface;
|
7 |
+
use IPLib\Range\Subnet;
|
8 |
+
use IPLib\Range\Type as RangeType;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* An IPv4 address.
|
12 |
+
*/
|
13 |
+
class IPv4 implements AddressInterface
|
14 |
+
{
|
15 |
+
/**
|
16 |
+
* The string representation of the address.
|
17 |
+
*
|
18 |
+
* @var string
|
19 |
+
*
|
20 |
+
* @example '127.0.0.1'
|
21 |
+
*/
|
22 |
+
protected $address;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* The byte list of the IP address.
|
26 |
+
*
|
27 |
+
* @var int[]|null
|
28 |
+
*/
|
29 |
+
protected $bytes;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* The type of the range of this IP address.
|
33 |
+
*
|
34 |
+
* @var int|null
|
35 |
+
*/
|
36 |
+
protected $rangeType;
|
37 |
+
|
38 |
+
/**
|
39 |
+
* A string representation of this address than can be used when comparing addresses and ranges.
|
40 |
+
*
|
41 |
+
* @var string
|
42 |
+
*/
|
43 |
+
protected $comparableString;
|
44 |
+
|
45 |
+
/**
|
46 |
+
* An array containing RFC designated address ranges.
|
47 |
+
*
|
48 |
+
* @var array|null
|
49 |
+
*/
|
50 |
+
private static $reservedRanges;
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Initializes the instance.
|
54 |
+
*
|
55 |
+
* @param string $address
|
56 |
+
*/
|
57 |
+
protected function __construct($address)
|
58 |
+
{
|
59 |
+
$this->address = $address;
|
60 |
+
$this->bytes = null;
|
61 |
+
$this->rangeType = null;
|
62 |
+
$this->comparableString = null;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* {@inheritdoc}
|
67 |
+
*
|
68 |
+
* @see \IPLib\Address\AddressInterface::__toString()
|
69 |
+
*/
|
70 |
+
public function __toString()
|
71 |
+
{
|
72 |
+
return $this->address;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* {@inheritdoc}
|
77 |
+
*
|
78 |
+
* @see \IPLib\Address\AddressInterface::getNumberOfBits()
|
79 |
+
*/
|
80 |
+
public static function getNumberOfBits()
|
81 |
+
{
|
82 |
+
return 32;
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* @deprecated since 1.17.0: use the parseString() method instead.
|
87 |
+
* For upgrading:
|
88 |
+
* - if $mayIncludePort is true, use the ParseStringFlag::MAY_INCLUDE_PORT flag
|
89 |
+
* - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
|
90 |
+
*
|
91 |
+
* @param string|mixed $address the address to parse
|
92 |
+
* @param bool $mayIncludePort
|
93 |
+
* @param bool $supportNonDecimalIPv4
|
94 |
+
*
|
95 |
+
* @return static|null
|
96 |
+
*
|
97 |
+
* @see \IPLib\Address\IPv4::parseString()
|
98 |
+
* @since 1.1.0 added the $mayIncludePort argument
|
99 |
+
* @since 1.10.0 added the $supportNonDecimalIPv4 argument
|
100 |
+
*/
|
101 |
+
public static function fromString($address, $mayIncludePort = true, $supportNonDecimalIPv4 = false)
|
102 |
+
{
|
103 |
+
return static::parseString($address, 0 | ($mayIncludePort ? ParseStringFlag::MAY_INCLUDE_PORT : 0) | ($supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0));
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Parse a string and returns an IPv4 instance if the string is valid, or null otherwise.
|
108 |
+
*
|
109 |
+
* @param string|mixed $address the address to parse
|
110 |
+
* @param int $flags A combination or zero or more flags
|
111 |
+
*
|
112 |
+
* @return static|null
|
113 |
+
*
|
114 |
+
* @see \IPLib\ParseStringFlag
|
115 |
+
* @since 1.17.0
|
116 |
+
*/
|
117 |
+
public static function parseString($address, $flags = 0)
|
118 |
+
{
|
119 |
+
if (!is_string($address)) {
|
120 |
+
return null;
|
121 |
+
}
|
122 |
+
$flags = (int) $flags;
|
123 |
+
$matches = null;
|
124 |
+
if ($flags & ParseStringFlag::ADDRESS_MAYBE_RDNS) {
|
125 |
+
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)) {
|
126 |
+
$address = implode('.', array_reverse(explode('.', $matches[1])));
|
127 |
+
$flags = $flags & ~(ParseStringFlag::IPV4_MAYBE_NON_DECIMAL | ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED);
|
128 |
+
}
|
129 |
+
}
|
130 |
+
if ($flags & ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED) {
|
131 |
+
if (strpos($address, '.') === 0) {
|
132 |
+
return null;
|
133 |
+
}
|
134 |
+
$lengthNonHex = '{1,11}';
|
135 |
+
$lengthHex = '{1,8}';
|
136 |
+
$chunk234Optional = true;
|
137 |
+
} else {
|
138 |
+
if (!strpos($address, '.')) {
|
139 |
+
return null;
|
140 |
+
}
|
141 |
+
$lengthNonHex = '{1,3}';
|
142 |
+
$lengthHex = '{1,2}';
|
143 |
+
$chunk234Optional = false;
|
144 |
+
}
|
145 |
+
$rxChunk1 = "0?[0-9]{$lengthNonHex}";
|
146 |
+
if ($flags & ParseStringFlag::IPV4_MAYBE_NON_DECIMAL) {
|
147 |
+
$rxChunk1 = "(?:0[Xx]0*[0-9A-Fa-f]{$lengthHex})|(?:{$rxChunk1})";
|
148 |
+
$onlyDecimal = false;
|
149 |
+
} else {
|
150 |
+
$onlyDecimal = true;
|
151 |
+
}
|
152 |
+
$rxChunk1 = "0*?({$rxChunk1})";
|
153 |
+
$rxChunk234 = "\.{$rxChunk1}";
|
154 |
+
if ($chunk234Optional) {
|
155 |
+
$rxChunk234 = "(?:{$rxChunk234})?";
|
156 |
+
}
|
157 |
+
$rx = "{$rxChunk1}{$rxChunk234}{$rxChunk234}{$rxChunk234}";
|
158 |
+
if ($flags & ParseStringFlag::MAY_INCLUDE_PORT) {
|
159 |
+
$rx .= '(?::\d+)?';
|
160 |
+
}
|
161 |
+
if (!preg_match('/^' . $rx . '$/', $address, $matches)) {
|
162 |
+
return null;
|
163 |
+
}
|
164 |
+
$math = new \IPLib\Service\UnsignedIntegerMath();
|
165 |
+
$nums = array();
|
166 |
+
$maxChunkIndex = count($matches) - 1;
|
167 |
+
for ($i = 1; $i <= $maxChunkIndex; $i++) {
|
168 |
+
$numBytes = $i === $maxChunkIndex ? 5 - $i : 1;
|
169 |
+
$chunkBytes = $math->getBytes($matches[$i], $numBytes, $onlyDecimal);
|
170 |
+
if ($chunkBytes === null) {
|
171 |
+
return null;
|
172 |
+
}
|
173 |
+
$nums = array_merge($nums, $chunkBytes);
|
174 |
+
}
|
175 |
+
|
176 |
+
return new static(implode('.', $nums));
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Parse an array of bytes and returns an IPv4 instance if the array is valid, or null otherwise.
|
181 |
+
*
|
182 |
+
* @param int[]|array $bytes
|
183 |
+
*
|
184 |
+
* @return static|null
|
185 |
+
*/
|
186 |
+
public static function fromBytes(array $bytes)
|
187 |
+
{
|
188 |
+
$result = null;
|
189 |
+
if (count($bytes) === 4) {
|
190 |
+
$chunks = array_map(
|
191 |
+
function ($byte) {
|
192 |
+
return (is_int($byte) && $byte >= 0 && $byte <= 255) ? (string) $byte : false;
|
193 |
+
},
|
194 |
+
$bytes
|
195 |
+
);
|
196 |
+
if (in_array(false, $chunks, true) === false) {
|
197 |
+
$result = new static(implode('.', $chunks));
|
198 |
+
}
|
199 |
+
}
|
200 |
+
|
201 |
+
return $result;
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* {@inheritdoc}
|
206 |
+
*
|
207 |
+
* @see \IPLib\Address\AddressInterface::toString()
|
208 |
+
*/
|
209 |
+
public function toString($long = false)
|
210 |
+
{
|
211 |
+
if ($long) {
|
212 |
+
return $this->getComparableString();
|
213 |
+
}
|
214 |
+
|
215 |
+
return $this->address;
|
216 |
+
}
|
217 |
+
|
218 |
+
/**
|
219 |
+
* Get the octal representation of this IP address.
|
220 |
+
*
|
221 |
+
* @param bool $long
|
222 |
+
*
|
223 |
+
* @return string
|
224 |
+
*
|
225 |
+
* @since 1.10.0
|
226 |
+
*
|
227 |
+
* @example if $long == false: if the decimal representation is '0.7.8.255': '0.7.010.0377'
|
228 |
+
* @example if $long == true: if the decimal representation is '0.7.8.255': '0000.0007.0010.0377'
|
229 |
+
*/
|
230 |
+
public function toOctal($long = false)
|
231 |
+
{
|
232 |
+
$chunks = array();
|
233 |
+
foreach ($this->getBytes() as $byte) {
|
234 |
+
if ($long) {
|
235 |
+
$chunks[] = sprintf('%04o', $byte);
|
236 |
+
} else {
|
237 |
+
$chunks[] = '0' . decoct($byte);
|
238 |
+
}
|
239 |
+
}
|
240 |
+
|
241 |
+
return implode('.', $chunks);
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* Get the hexadecimal representation of this IP address.
|
246 |
+
*
|
247 |
+
* @param bool $long
|
248 |
+
*
|
249 |
+
* @return string
|
250 |
+
*
|
251 |
+
* @since 1.10.0
|
252 |
+
*
|
253 |
+
* @example if $long == false: if the decimal representation is '0.9.10.255': '0.9.0xa.0xff'
|
254 |
+
* @example if $long == true: if the decimal representation is '0.9.10.255': '0x00.0x09.0x0a.0xff'
|
255 |
+
*/
|
256 |
+
public function toHexadecimal($long = false)
|
257 |
+
{
|
258 |
+
$chunks = array();
|
259 |
+
foreach ($this->getBytes() as $byte) {
|
260 |
+
if ($long) {
|
261 |
+
$chunks[] = sprintf('0x%02x', $byte);
|
262 |
+
} else {
|
263 |
+
$chunks[] = '0x' . dechex($byte);
|
264 |
+
}
|
265 |
+
}
|
266 |
+
|
267 |
+
return implode('.', $chunks);
|
268 |
+
}
|
269 |
+
|
270 |
+
/**
|
271 |
+
* {@inheritdoc}
|
272 |
+
*
|
273 |
+
* @see \IPLib\Address\AddressInterface::getBytes()
|
274 |
+
*/
|
275 |
+
public function getBytes()
|
276 |
+
{
|
277 |
+
if ($this->bytes === null) {
|
278 |
+
$this->bytes = array_map(
|
279 |
+
function ($chunk) {
|
280 |
+
return (int) $chunk;
|
281 |
+
},
|
282 |
+
explode('.', $this->address)
|
283 |
+
);
|
284 |
+
}
|
285 |
+
|
286 |
+
return $this->bytes;
|
287 |
+
}
|
288 |
+
|
289 |
+
/**
|
290 |
+
* {@inheritdoc}
|
291 |
+
*
|
292 |
+
* @see \IPLib\Address\AddressInterface::getBits()
|
293 |
+
*/
|
294 |
+
public function getBits()
|
295 |
+
{
|
296 |
+
$parts = array();
|
297 |
+
foreach ($this->getBytes() as $byte) {
|
298 |
+
$parts[] = sprintf('%08b', $byte);
|
299 |
+
}
|
300 |
+
|
301 |
+
return implode('', $parts);
|
302 |
+
}
|
303 |
+
|
304 |
+
/**
|
305 |
+
* {@inheritdoc}
|
306 |
+
*
|
307 |
+
* @see \IPLib\Address\AddressInterface::getAddressType()
|
308 |
+
*/
|
309 |
+
public function getAddressType()
|
310 |
+
{
|
311 |
+
return Type::T_IPv4;
|
312 |
+
}
|
313 |
+
|
314 |
+
/**
|
315 |
+
* {@inheritdoc}
|
316 |
+
*
|
317 |
+
* @see \IPLib\Address\AddressInterface::getDefaultReservedRangeType()
|
318 |
+
*/
|
319 |
+
public static function getDefaultReservedRangeType()
|
320 |
+
{
|
321 |
+
return RangeType::T_PUBLIC;
|
322 |
+
}
|
323 |
+
|
324 |
+
/**
|
325 |
+
* {@inheritdoc}
|
326 |
+
*
|
327 |
+
* @see \IPLib\Address\AddressInterface::getReservedRanges()
|
328 |
+
*/
|
329 |
+
public static function getReservedRanges()
|
330 |
+
{
|
331 |
+
if (self::$reservedRanges === null) {
|
332 |
+
$reservedRanges = array();
|
333 |
+
foreach (array(
|
334 |
+
// RFC 5735
|
335 |
+
'0.0.0.0/8' => array(RangeType::T_THISNETWORK, array('0.0.0.0/32' => RangeType::T_UNSPECIFIED)),
|
336 |
+
// RFC 5735
|
337 |
+
'10.0.0.0/8' => array(RangeType::T_PRIVATENETWORK),
|
338 |
+
// RFC 6598
|
339 |
+
'100.64.0.0/10' => array(RangeType::T_CGNAT),
|
340 |
+
// RFC 5735
|
341 |
+
'127.0.0.0/8' => array(RangeType::T_LOOPBACK),
|
342 |
+
// RFC 5735
|
343 |
+
'169.254.0.0/16' => array(RangeType::T_LINKLOCAL),
|
344 |
+
// RFC 5735
|
345 |
+
'172.16.0.0/12' => array(RangeType::T_PRIVATENETWORK),
|
346 |
+
// RFC 5735
|
347 |
+
'192.0.0.0/24' => array(RangeType::T_RESERVED),
|
348 |
+
// RFC 5735
|
349 |
+
'192.0.2.0/24' => array(RangeType::T_RESERVED),
|
350 |
+
// RFC 5735
|
351 |
+
'192.88.99.0/24' => array(RangeType::T_ANYCASTRELAY),
|
352 |
+
// RFC 5735
|
353 |
+
'192.168.0.0/16' => array(RangeType::T_PRIVATENETWORK),
|
354 |
+
// RFC 5735
|
355 |
+
'198.18.0.0/15' => array(RangeType::T_RESERVED),
|
356 |
+
// RFC 5735
|
357 |
+
'198.51.100.0/24' => array(RangeType::T_RESERVED),
|
358 |
+
// RFC 5735
|
359 |
+
'203.0.113.0/24' => array(RangeType::T_RESERVED),
|
360 |
+
// RFC 5735
|
361 |
+
'224.0.0.0/4' => array(RangeType::T_MULTICAST),
|
362 |
+
// RFC 5735
|
363 |
+
'240.0.0.0/4' => array(RangeType::T_RESERVED, array('255.255.255.255/32' => RangeType::T_LIMITEDBROADCAST)),
|
364 |
+
) as $range => $data) {
|
365 |
+
$exceptions = array();
|
366 |
+
if (isset($data[1])) {
|
367 |
+
foreach ($data[1] as $exceptionRange => $exceptionType) {
|
368 |
+
$exceptions[] = new AssignedRange(Subnet::parseString($exceptionRange), $exceptionType);
|
369 |
+
}
|
370 |
+
}
|
371 |
+
$reservedRanges[] = new AssignedRange(Subnet::parseString($range), $data[0], $exceptions);
|
372 |
+
}
|
373 |
+
self::$reservedRanges = $reservedRanges;
|
374 |
+
}
|
375 |
+
|
376 |
+
return self::$reservedRanges;
|
377 |
+
}
|
378 |
+
|
379 |
+
/**
|
380 |
+
* {@inheritdoc}
|
381 |
+
*
|
382 |
+
* @see \IPLib\Address\AddressInterface::getRangeType()
|
383 |
+
*/
|
384 |
+
public function getRangeType()
|
385 |
+
{
|
386 |
+
if ($this->rangeType === null) {
|
387 |
+
$rangeType = null;
|
388 |
+
foreach (static::getReservedRanges() as $reservedRange) {
|
389 |
+
$rangeType = $reservedRange->getAddressType($this);
|
390 |
+
if ($rangeType !== null) {
|
391 |
+
break;
|
392 |
+
}
|
393 |
+
}
|
394 |
+
$this->rangeType = $rangeType === null ? static::getDefaultReservedRangeType() : $rangeType;
|
395 |
+
}
|
396 |
+
|
397 |
+
return $this->rangeType;
|
398 |
+
}
|
399 |
+
|
400 |
+
/**
|
401 |
+
* Create an IPv6 representation of this address (in 6to4 notation).
|
402 |
+
*
|
403 |
+
* @return \IPLib\Address\IPv6
|
404 |
+
*/
|
405 |
+
public function toIPv6()
|
406 |
+
{
|
407 |
+
$myBytes = $this->getBytes();
|
408 |
+
|
409 |
+
return IPv6::parseString('2002:' . sprintf('%02x', $myBytes[0]) . sprintf('%02x', $myBytes[1]) . ':' . sprintf('%02x', $myBytes[2]) . sprintf('%02x', $myBytes[3]) . '::');
|
410 |
+
}
|
411 |
+
|
412 |
+
/**
|
413 |
+
* Create an IPv6 representation of this address (in IPv6 IPv4-mapped notation).
|
414 |
+
*
|
415 |
+
* @return \IPLib\Address\IPv6
|
416 |
+
*
|
417 |
+
* @since 1.11.0
|
418 |
+
*/
|
419 |
+
public function toIPv6IPv4Mapped()
|
420 |
+
{
|
421 |
+
return IPv6::fromBytes(array_merge(array(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff), $this->getBytes()));
|
422 |
+
}
|
423 |
+
|
424 |
+
/**
|
425 |
+
* {@inheritdoc}
|
426 |
+
*
|
427 |
+
* @see \IPLib\Address\AddressInterface::getComparableString()
|
428 |
+
*/
|
429 |
+
public function getComparableString()
|
430 |
+
{
|
431 |
+
if ($this->comparableString === null) {
|
432 |
+
$chunks = array();
|
433 |
+
foreach ($this->getBytes() as $byte) {
|
434 |
+
$chunks[] = sprintf('%03d', $byte);
|
435 |
+
}
|
436 |
+
$this->comparableString = implode('.', $chunks);
|
437 |
+
}
|
438 |
+
|
439 |
+
return $this->comparableString;
|
440 |
+
}
|
441 |
+
|
442 |
+
/**
|
443 |
+
* {@inheritdoc}
|
444 |
+
*
|
445 |
+
* @see \IPLib\Address\AddressInterface::matches()
|
446 |
+
*/
|
447 |
+
public function matches(RangeInterface $range)
|
448 |
+
{
|
449 |
+
return $range->contains($this);
|
450 |
+
}
|
451 |
+
|
452 |
+
/**
|
453 |
+
* {@inheritdoc}
|
454 |
+
*
|
455 |
+
* @see \IPLib\Address\AddressInterface::getAddressAtOffset()
|
456 |
+
*/
|
457 |
+
public function getAddressAtOffset($n)
|
458 |
+
{
|
459 |
+
if (!is_int($n)) {
|
460 |
+
return null;
|
461 |
+
}
|
462 |
+
|
463 |
+
$boundary = 256;
|
464 |
+
$mod = $n;
|
465 |
+
$bytes = $this->getBytes();
|
466 |
+
for ($i = count($bytes) - 1; $i >= 0; $i--) {
|
467 |
+
$tmp = ($bytes[$i] + $mod) % $boundary;
|
468 |
+
$mod = (int) floor(($bytes[$i] + $mod) / $boundary);
|
469 |
+
if ($tmp < 0) {
|
470 |
+
$tmp += $boundary;
|
471 |
+
}
|
472 |
+
|
473 |
+
$bytes[$i] = $tmp;
|
474 |
+
}
|
475 |
+
|
476 |
+
if ($mod !== 0) {
|
477 |
+
return null;
|
478 |
+
}
|
479 |
+
|
480 |
+
return static::fromBytes($bytes);
|
481 |
+
}
|
482 |
+
|
483 |
+
/**
|
484 |
+
* {@inheritdoc}
|
485 |
+
*
|
486 |
+
* @see \IPLib\Address\AddressInterface::getNextAddress()
|
487 |
+
*/
|
488 |
+
public function getNextAddress()
|
489 |
+
{
|
490 |
+
return $this->getAddressAtOffset(1);
|
491 |
+
}
|
492 |
+
|
493 |
+
/**
|
494 |
+
* {@inheritdoc}
|
495 |
+
*
|
496 |
+
* @see \IPLib\Address\AddressInterface::getPreviousAddress()
|
497 |
+
*/
|
498 |
+
public function getPreviousAddress()
|
499 |
+
{
|
500 |
+
return $this->getAddressAtOffset(-1);
|
501 |
+
}
|
502 |
+
|
503 |
+
/**
|
504 |
+
* {@inheritdoc}
|
505 |
+
*
|
506 |
+
* @see \IPLib\Address\AddressInterface::getReverseDNSLookupName()
|
507 |
+
*/
|
508 |
+
public function getReverseDNSLookupName()
|
509 |
+
{
|
510 |
+
return implode(
|
511 |
+
'.',
|
512 |
+
array_reverse($this->getBytes())
|
513 |
+
) . '.in-addr.arpa';
|
514 |
+
}
|
515 |
+
}
|
vendor/mlocati/ip-lib/src/Address/IPv6.php
ADDED
@@ -0,0 +1,608 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace IPLib\Address;
|
4 |
+
|
5 |
+
use IPLib\ParseStringFlag;
|
6 |
+
use IPLib\Range\RangeInterface;
|
7 |
+
use IPLib\Range\Subnet;
|
8 |
+
use IPLib\Range\Type as RangeType;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* An IPv6 address.
|
12 |
+
*/
|
13 |
+
class IPv6 implements AddressInterface
|
14 |
+
{
|
15 |
+
/**
|
16 |
+
* The long string representation of the address.
|
17 |
+
*
|
18 |
+
* @var string
|
19 |
+
*
|
20 |
+
* @example '0000:0000:0000:0000:0000:0000:0000:0001'
|
21 |
+
*/
|
22 |
+
protected $longAddress;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* The long string representation of the address.
|
26 |
+
*
|
27 |
+
* @var string|null
|
28 |
+
*
|
29 |
+
* @example '::1'
|
30 |
+
*/
|
31 |
+
protected $shortAddress;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* The byte list of the IP address.
|
35 |
+
*
|
36 |
+
* @var int[]|null
|
37 |
+
*/
|
38 |
+
protected $bytes;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* The word list of the IP address.
|
42 |
+
*
|
43 |
+
* @var int[]|null
|
44 |
+
*/
|
45 |
+
protected $words;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* The type of the range of this IP address.
|
49 |
+
*
|
50 |
+
* @var int|null
|
51 |
+
*/
|
52 |
+
protected $rangeType;
|
53 |
+
|
54 |
+
/**
|
55 |
+
* An array containing RFC designated address ranges.
|
56 |
+
*
|
57 |
+
* @var array|null
|
58 |
+
*/
|
59 |
+
private static $reservedRanges;
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Initializes the instance.
|
63 |
+
*
|
64 |
+
* @param string $longAddress
|
65 |
+
*/
|
66 |
+
public function __construct($longAddress)
|
67 |
+
{
|
68 |
+
$this->longAddress = $longAddress;
|
69 |
+
$this->shortAddress = null;
|
70 |
+
$this->bytes = null;
|
71 |
+
$this->words = null;
|
72 |
+
$this->rangeType = null;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* {@inheritdoc}
|
77 |
+
*
|
78 |
+
* @see \IPLib\Address\AddressInterface::__toString()
|
79 |
+
*/
|
80 |
+
public function __toString()
|
81 |
+
{
|
82 |
+
return $this->toString();
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* {@inheritdoc}
|
87 |
+
*
|
88 |
+
* @see \IPLib\Address\AddressInterface::getNumberOfBits()
|
89 |
+
*/
|
90 |
+
public static function getNumberOfBits()
|
91 |
+
{
|
92 |
+
return 128;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* @deprecated since 1.17.0: use the parseString() method instead.
|
97 |
+
* For upgrading:
|
98 |
+
* - if $mayIncludePort is true, use the ParseStringFlag::MAY_INCLUDE_PORT flag
|
99 |
+
* - if $mayIncludeZoneID is true, use the ParseStringFlag::MAY_INCLUDE_ZONEID flag
|
100 |
+
*
|
101 |
+
* @param string|mixed $address
|
102 |
+
* @param bool $mayIncludePort
|
103 |
+
* @param bool $mayIncludeZoneID
|
104 |
+
*
|
105 |
+
* @return static|null
|
106 |
+
*
|
107 |
+
* @see \IPLib\Address\IPv6::parseString()
|
108 |
+
* @since 1.1.0 added the $mayIncludePort argument
|
109 |
+
* @since 1.3.0 added the $mayIncludeZoneID argument
|
110 |
+
*/
|
111 |
+
public static function fromString($address, $mayIncludePort = true, $mayIncludeZoneID = true)
|
112 |
+
{
|
113 |
+
return static::parseString($address, 0 | ($mayIncludePort ? ParseStringFlag::MAY_INCLUDE_PORT : 0) | ($mayIncludeZoneID ? ParseStringFlag::MAY_INCLUDE_ZONEID : 0));
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Parse a string and returns an IPv6 instance if the string is valid, or null otherwise.
|
118 |
+
*
|
119 |
+
* @param string|mixed $address the address to parse
|
120 |
+
* @param int $flags A combination or zero or more flags
|
121 |
+
*
|
122 |
+
* @return static|null
|
123 |
+
*
|
124 |
+
* @see \IPLib\ParseStringFlag
|
125 |
+
* @since 1.17.0
|
126 |
+
*/
|
127 |
+
public static function parseString($address, $flags = 0)
|
128 |
+
{
|
129 |
+
if (!is_string($address)) {
|
130 |
+
return null;
|
131 |
+
}
|
132 |
+
$matches = null;
|
133 |
+
$flags = (int) $flags;
|
134 |
+
if ($flags & ParseStringFlag::ADDRESS_MAYBE_RDNS) {
|
135 |
+
if (preg_match('/^([0-9a-f](?:\.[0-9a-f]){31})\.ip6\.arpa\.?/i', $address, $matches)) {
|
136 |
+
$nibbles = array_reverse(explode('.', $matches[1]));
|
137 |
+
$quibbles = array();
|
138 |
+
foreach (array_chunk($nibbles, 4) as $n) {
|
139 |
+
$quibbles[] = implode('', $n);
|
140 |
+
}
|
141 |
+
$address = implode(':', $quibbles);
|
142 |
+
}
|
143 |
+
}
|
144 |
+
$result = null;
|
145 |
+
if (is_string($address) && strpos($address, ':') !== false && strpos($address, ':::') === false) {
|
146 |
+
if ($flags & ParseStringFlag::MAY_INCLUDE_PORT && $address[0] === '[' && preg_match('/^\[(.+)]:\d+$/', $address, $matches)) {
|
147 |
+
$address = $matches[1];
|
148 |
+
}
|
149 |
+
if ($flags & ParseStringFlag::MAY_INCLUDE_ZONEID) {
|
150 |
+
$percentagePos = strpos($address, '%');
|
151 |
+
if ($percentagePos > 0) {
|
152 |
+
$address = substr($address, 0, $percentagePos);
|
153 |
+
}
|
154 |
+
}
|
155 |
+
if (preg_match('/^((?:[0-9a-f]*:+)+)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/i', $address, $matches)) {
|
156 |
+
$address6 = static::parseString($matches[1] . '0:0');
|
157 |
+
if ($address6 !== null) {
|
158 |
+
$address4 = IPv4::parseString($matches[2]);
|
159 |
+
if ($address4 !== null) {
|
160 |
+
$bytes4 = $address4->getBytes();
|
161 |
+
$address6->longAddress = substr($address6->longAddress, 0, -9) . sprintf('%02x%02x:%02x%02x', $bytes4[0], $bytes4[1], $bytes4[2], $bytes4[3]);
|
162 |
+
$result = $address6;
|
163 |
+
}
|
164 |
+
}
|
165 |
+
} else {
|
166 |
+
if (strpos($address, '::') === false) {
|
167 |
+
$chunks = explode(':', $address);
|
168 |
+
} else {
|
169 |
+
$chunks = array();
|
170 |
+
$parts = explode('::', $address);
|
171 |
+
if (count($parts) === 2) {
|
172 |
+
$before = ($parts[0] === '') ? array() : explode(':', $parts[0]);
|
173 |
+
$after = ($parts[1] === '') ? array() : explode(':', $parts[1]);
|
174 |
+
$missing = 8 - count($before) - count($after);
|
175 |
+
if ($missing >= 0) {
|
176 |
+
$chunks = $before;
|
177 |
+
if ($missing !== 0) {
|
178 |
+
$chunks = array_merge($chunks, array_fill(0, $missing, '0'));
|
179 |
+
}
|
180 |
+
$chunks = array_merge($chunks, $after);
|
181 |
+
}
|
182 |
+
}
|
183 |
+
}
|
184 |
+
if (count($chunks) === 8) {
|
185 |
+
$nums = array_map(
|
186 |
+
function ($chunk) {
|
187 |
+
return preg_match('/^[0-9A-Fa-f]{1,4}$/', $chunk) ? hexdec($chunk) : false;
|
188 |
+
},
|
189 |
+
$chunks
|
190 |
+
);
|
191 |
+
if (!in_array(false, $nums, true)) {
|
192 |
+
$longAddress = implode(
|
193 |
+
':',
|
194 |
+
array_map(
|
195 |
+
function ($num) {
|
196 |
+
return sprintf('%04x', $num);
|
197 |
+
},
|
198 |
+
$nums
|
199 |
+
)
|
200 |
+
);
|
201 |
+
$result = new static($longAddress);
|
202 |
+
}
|
203 |
+
}
|
204 |
+
}
|
205 |
+
}
|
206 |
+
|
207 |
+
return $result;
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Parse an array of bytes and returns an IPv6 instance if the array is valid, or null otherwise.
|
212 |
+
*
|
213 |
+
* @param int[]|array $bytes
|
214 |
+
*
|
215 |
+
* @return static|null
|
216 |
+
*/
|
217 |
+
public static function fromBytes(array $bytes)
|
218 |
+
{
|
219 |
+
$result = null;
|
220 |
+
if (count($bytes) === 16) {
|
221 |
+
$address = '';
|
222 |
+
for ($i = 0; $i < 16; $i++) {
|
223 |
+
if ($i !== 0 && $i % 2 === 0) {
|
224 |
+
$address .= ':';
|
225 |
+
}
|
226 |
+
$byte = $bytes[$i];
|
227 |
+
if (is_int($byte) && $byte >= 0 && $byte <= 255) {
|
228 |
+
$address .= sprintf('%02x', $byte);
|
229 |
+
} else {
|
230 |
+
$address = null;
|
231 |
+
break;
|
232 |
+
}
|
233 |
+
}
|
234 |
+
if ($address !== null) {
|
235 |
+
$result = new static($address);
|
236 |
+
}
|
237 |
+
}
|
238 |
+
|
239 |
+
return $result;
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* Parse an array of words and returns an IPv6 instance if the array is valid, or null otherwise.
|
244 |
+
*
|
245 |
+
* @param int[]|array $words
|
246 |
+
*
|
247 |
+
* @return static|null
|
248 |
+
*/
|
249 |
+
public static function fromWords(array $words)
|
250 |
+
{
|
251 |
+
$result = null;
|
252 |
+
if (count($words) === 8) {
|
253 |
+
$chunks = array();
|
254 |
+
for ($i = 0; $i < 8; $i++) {
|
255 |
+
$word = $words[$i];
|
256 |
+
if (is_int($word) && $word >= 0 && $word <= 0xffff) {
|
257 |
+
$chunks[] = sprintf('%04x', $word);
|
258 |
+
} else {
|
259 |
+
$chunks = null;
|
260 |
+
break;
|
261 |
+
}
|
262 |
+
}
|
263 |
+
if ($chunks !== null) {
|
264 |
+
$result = new static(implode(':', $chunks));
|
265 |
+
}
|
266 |
+
}
|
267 |
+
|
268 |
+
return $result;
|
269 |
+
}
|
270 |
+
|
271 |
+
/**
|
272 |
+
* {@inheritdoc}
|
273 |
+
*
|
274 |
+
* @see \IPLib\Address\AddressInterface::toString()
|
275 |
+
*/
|
276 |
+
public function toString($long = false)
|
277 |
+
{
|
278 |
+
if ($long) {
|
279 |
+
$result = $this->longAddress;
|
280 |
+
} else {
|
281 |
+
if ($this->shortAddress === null) {
|
282 |
+
if (strpos($this->longAddress, '0000:0000:0000:0000:0000:ffff:') === 0) {
|
283 |
+
$lastBytes = array_slice($this->getBytes(), -4);
|
284 |
+
$this->shortAddress = '::ffff:' . implode('.', $lastBytes);
|
285 |
+
} else {
|
286 |
+
$chunks = array_map(
|
287 |
+
function ($word) {
|
288 |
+
return dechex($word);
|
289 |
+
},
|
290 |
+
$this->getWords()
|
291 |
+
);
|
292 |
+
$shortAddress = implode(':', $chunks);
|
293 |
+
$matches = null;
|
294 |
+
for ($i = 8; $i > 1; $i--) {
|
295 |
+
$search = '(?:^|:)' . rtrim(str_repeat('0:', $i), ':') . '(?:$|:)';
|
296 |
+
if (preg_match('/^(.*?)' . $search . '(.*)$/', $shortAddress, $matches)) {
|
297 |
+
$shortAddress = $matches[1] . '::' . $matches[2];
|
298 |
+
break;
|
299 |
+
}
|
300 |
+
}
|
301 |
+
$this->shortAddress = $shortAddress;
|
302 |
+
}
|
303 |
+
}
|
304 |
+
$result = $this->shortAddress;
|
305 |
+
}
|
306 |
+
|
307 |
+
return $result;
|
308 |
+
}
|
309 |
+
|
310 |
+
/**
|
311 |
+
* {@inheritdoc}
|
312 |
+
*
|
313 |
+
* @see \IPLib\Address\AddressInterface::getBytes()
|
314 |
+
*/
|
315 |
+
public function getBytes()
|
316 |
+
{
|
317 |
+
if ($this->bytes === null) {
|
318 |
+
$bytes = array();
|
319 |
+
foreach ($this->getWords() as $word) {
|
320 |
+
$bytes[] = $word >> 8;
|
321 |
+
$bytes[] = $word & 0xff;
|
322 |
+
}
|
323 |
+
$this->bytes = $bytes;
|
324 |
+
}
|
325 |
+
|
326 |
+
return $this->bytes;
|
327 |
+
}
|
328 |
+
|
329 |
+
/**
|
330 |
+
* {@inheritdoc}
|
331 |
+
*
|
332 |
+
* @see \IPLib\Address\AddressInterface::getBits()
|
333 |
+
*/
|
334 |
+
public function getBits()
|
335 |
+
{
|
336 |
+
$parts = array();
|
337 |
+
foreach ($this->getBytes() as $byte) {
|
338 |
+
$parts[] = sprintf('%08b', $byte);
|
339 |
+
}
|
340 |
+
|
341 |
+
return implode('', $parts);
|
342 |
+
}
|
343 |
+
|
344 |
+
/**
|
345 |
+
* Get the word list of the IP address.
|
346 |
+
*
|
347 |
+
* @return int[]
|
348 |
+
*/
|
349 |
+
public function getWords()
|
350 |
+
{
|
351 |
+
if ($this->words === null) {
|
352 |
+
$this->words = array_map(
|
353 |
+
function ($chunk) {
|
354 |
+
return hexdec($chunk);
|
355 |
+
},
|
356 |
+
explode(':', $this->longAddress)
|
357 |
+
);
|
358 |
+
}
|
359 |
+
|
360 |
+
return $this->words;
|
361 |
+
}
|
362 |
+
|
363 |
+
/**
|
364 |
+
* {@inheritdoc}
|
365 |
+
*
|
366 |
+
* @see \IPLib\Address\AddressInterface::getAddressType()
|
367 |
+
*/
|
368 |
+
public function getAddressType()
|
369 |
+
{
|
370 |
+
return Type::T_IPv6;
|
371 |
+
}
|
372 |
+
|
373 |
+
/**
|
374 |
+
* {@inheritdoc}
|
375 |
+
*
|
376 |
+
* @see \IPLib\Address\AddressInterface::getDefaultReservedRangeType()
|
377 |
+
*/
|
378 |
+
public static function getDefaultReservedRangeType()
|
379 |
+
{
|
380 |
+
return RangeType::T_RESERVED;
|
381 |
+
}
|
382 |
+
|
383 |
+
/**
|
384 |
+
* {@inheritdoc}
|
385 |
+
*
|
386 |
+
* @see \IPLib\Address\AddressInterface::getReservedRanges()
|
387 |
+
*/
|
388 |
+
public static function getReservedRanges()
|
389 |
+
{
|
390 |
+
if (self::$reservedRanges === null) {
|
391 |
+
$reservedRanges = array();
|
392 |
+
foreach (array(
|
393 |
+
// RFC 4291
|
394 |
+
'::/128' => array(RangeType::T_UNSPECIFIED),
|
395 |
+
// RFC 4291
|
396 |
+
'::1/128' => array(RangeType::T_LOOPBACK),
|
397 |
+
// RFC 4291
|
398 |
+
'100::/8' => array(RangeType::T_DISCARD, array('100::/64' => RangeType::T_DISCARDONLY)),
|
399 |
+
//'2002::/16' => array(RangeType::),
|
400 |
+
// RFC 4291
|
401 |
+
'2000::/3' => array(RangeType::T_PUBLIC),
|
402 |
+
// RFC 4193
|
403 |
+
'fc00::/7' => array(RangeType::T_PRIVATENETWORK),
|
404 |
+
// RFC 4291
|
405 |
+
'fe80::/10' => array(RangeType::T_LINKLOCAL_UNICAST),
|
406 |
+
// RFC 4291
|
407 |
+
'ff00::/8' => array(RangeType::T_MULTICAST),
|
408 |
+
// RFC 4291
|
409 |
+
//'::/8' => array(RangeType::T_RESERVED),
|
410 |
+
// RFC 4048
|
411 |
+
//'200::/7' => array(RangeType::T_RESERVED),
|
412 |
+
// RFC 4291
|
413 |
+
//'400::/6' => array(RangeType::T_RESERVED),
|
414 |
+
// RFC 4291
|
415 |
+
//'800::/5' => array(RangeType::T_RESERVED),
|
416 |
+
// RFC 4291
|
417 |
+
//'1000::/4' => array(RangeType::T_RESERVED),
|
418 |
+
// RFC 4291
|
419 |
+
//'4000::/3' => array(RangeType::T_RESERVED),
|
420 |
+
// RFC 4291
|
421 |
+
//'6000::/3' => array(RangeType::T_RESERVED),
|
422 |
+
// RFC 4291
|
423 |
+
//'8000::/3' => array(RangeType::T_RESERVED),
|
424 |
+
// RFC 4291
|
425 |
+
//'a000::/3' => array(RangeType::T_RESERVED),
|
426 |
+
// RFC 4291
|
427 |
+
//'c000::/3' => array(RangeType::T_RESERVED),
|
428 |
+
// RFC 4291
|
429 |
+
//'e000::/4' => array(RangeType::T_RESERVED),
|
430 |
+
// RFC 4291
|
431 |
+
//'f000::/5' => array(RangeType::T_RESERVED),
|
432 |
+
// RFC 4291
|
433 |
+
//'f800::/6' => array(RangeType::T_RESERVED),
|
434 |
+
// RFC 4291
|
435 |
+
//'fe00::/9' => array(RangeType::T_RESERVED),
|
436 |
+
// RFC 3879
|
437 |
+
//'fec0::/10' => array(RangeType::T_RESERVED),
|
438 |
+
) as $range => $data) {
|
439 |
+
$exceptions = array();
|
440 |
+
if (isset($data[1])) {
|
441 |
+
foreach ($data[1] as $exceptionRange => $exceptionType) {
|
442 |
+
$exceptions[] = new AssignedRange(Subnet::parseString($exceptionRange), $exceptionType);
|
443 |
+
}
|
444 |
+
}
|
445 |
+
$reservedRanges[] = new AssignedRange(Subnet::parseString($range), $data[0], $exceptions);
|
446 |
+
}
|
447 |
+
self::$reservedRanges = $reservedRanges;
|
448 |
+
}
|
449 |
+
|
450 |
+
return self::$reservedRanges;
|
451 |
+
}
|
452 |
+
|
453 |
+
/**
|
454 |
+
* {@inheritdoc}
|
455 |
+
*
|
456 |
+
* @see \IPLib\Address\AddressInterface::getRangeType()
|
457 |
+
*/
|
458 |
+
public function getRangeType()
|
459 |
+
{
|
460 |
+
if ($this->rangeType === null) {
|
461 |
+
$ipv4 = $this->toIPv4();
|
462 |
+
if ($ipv4 !== null) {
|
463 |
+
$this->rangeType = $ipv4->getRangeType();
|
464 |
+
} else {
|
465 |
+
$rangeType = null;
|
466 |
+
foreach (static::getReservedRanges() as $reservedRange) {
|
467 |
+
$rangeType = $reservedRange->getAddressType($this);
|
468 |
+
if ($rangeType !== null) {
|
469 |
+
break;
|
470 |
+
}
|
471 |
+
}
|
472 |
+
$this->rangeType = $rangeType === null ? static::getDefaultReservedRangeType() : $rangeType;
|
473 |
+
}
|
474 |
+
}
|
475 |
+
|
476 |
+
return $this->rangeType;
|
477 |
+
}
|
478 |
+
|
479 |
+
/**
|
480 |
+
* Create an IPv4 representation of this address (if possible, otherwise returns null).
|
481 |
+
*
|
482 |
+
* @return \IPLib\Address\IPv4|null
|
483 |
+
*/
|
484 |
+
public function toIPv4()
|
485 |
+
{
|
486 |
+
if (strpos($this->longAddress, '2002:') === 0) {
|
487 |
+
// 6to4
|
488 |
+
return IPv4::fromBytes(array_slice($this->getBytes(), 2, 4));
|
489 |
+
}
|
490 |
+
if (strpos($this->longAddress, '0000:0000:0000:0000:0000:ffff:') === 0) {
|
491 |
+
// IPv4-mapped IPv6 addresses
|
492 |
+
return IPv4::fromBytes(array_slice($this->getBytes(), -4));
|
493 |
+
}
|
494 |
+
|
495 |
+
return null;
|
496 |
+
}
|
497 |
+
|
498 |
+
/**
|
499 |
+
* Render this IPv6 address in the "mixed" IPv6 (first 12 bytes) + IPv4 (last 4 bytes) mixed syntax.
|
500 |
+
*
|
501 |
+
* @param bool $ipV6Long render the IPv6 part in "long" format?
|
502 |
+
* @param bool $ipV4Long render the IPv4 part in "long" format?
|
503 |
+
*
|
504 |
+
* @return string
|
505 |
+
*
|
506 |
+
* @example '::13.1.68.3'
|
507 |
+
* @example '0000:0000:0000:0000:0000:0000:13.1.68.3' when $ipV6Long is true
|
508 |
+
* @example '::013.001.068.003' when $ipV4Long is true
|
509 |
+
* @example '0000:0000:0000:0000:0000:0000:013.001.068.003' when $ipV6Long and $ipV4Long are true
|
510 |
+
*
|
511 |
+
* @see https://tools.ietf.org/html/rfc4291#section-2.2 point 3.
|
512 |
+
* @since 1.9.0
|
513 |
+
*/
|
514 |
+
public function toMixedIPv6IPv4String($ipV6Long = false, $ipV4Long = false)
|
515 |
+
{
|
516 |
+
$myBytes = $this->getBytes();
|
517 |
+
$ipv6Bytes = array_merge(array_slice($myBytes, 0, 12), array(0xff, 0xff, 0xff, 0xff));
|
518 |
+
$ipv6String = static::fromBytes($ipv6Bytes)->toString($ipV6Long);
|
519 |
+
$ipv4Bytes = array_slice($myBytes, 12, 4);
|
520 |
+
$ipv4String = IPv4::fromBytes($ipv4Bytes)->toString($ipV4Long);
|
521 |
+
|
522 |
+
return preg_replace('/((ffff:ffff)|(\d+(\.\d+){3}))$/i', $ipv4String, $ipv6String);
|
523 |
+
}
|
524 |
+
|
525 |
+
/**
|
526 |
+
* {@inheritdoc}
|
527 |
+
*
|
528 |
+
* @see \IPLib\Address\AddressInterface::getComparableString()
|
529 |
+
*/
|
530 |
+
public function getComparableString()
|
531 |
+
{
|
532 |
+
return $this->longAddress;
|
533 |
+
}
|
534 |
+
|
535 |
+
/**
|
536 |
+
* {@inheritdoc}
|
537 |
+
*
|
538 |
+
* @see \IPLib\Address\AddressInterface::matches()
|
539 |
+
*/
|
540 |
+
public function matches(RangeInterface $range)
|
541 |
+
{
|
542 |
+
return $range->contains($this);
|
543 |
+
}
|
544 |
+
|
545 |
+
/**
|
546 |
+
* {@inheritdoc}
|
547 |
+
*
|
548 |
+
* @see \IPLib\Address\AddressInterface::getAddressAtOffset()
|
549 |
+
*/
|
550 |
+
public function getAddressAtOffset($n)
|
551 |
+
{
|
552 |
+
if (!is_int($n)) {
|
553 |
+
return null;
|
554 |
+
}
|
555 |
+
|
556 |
+
$boundary = 0x10000;
|
557 |
+
$mod = $n;
|
558 |
+
$words = $this->getWords();
|
559 |
+
for ($i = count($words) - 1; $i >= 0; $i--) {
|
560 |
+
$tmp = ($words[$i] + $mod) % $boundary;
|
561 |
+
$mod = (int) floor(($words[$i] + $mod) / $boundary);
|
562 |
+
if ($tmp < 0) {
|
563 |
+
$tmp += $boundary;
|
564 |
+
}
|
565 |
+
|
566 |
+
$words[$i] = $tmp;
|
567 |
+
}
|
568 |
+
|
569 |
+
if ($mod !== 0) {
|
570 |
+
return null;
|
571 |
+
}
|
572 |
+
|
573 |
+
return static::fromWords($words);
|
574 |
+
}
|
575 |
+
|
576 |
+
/**
|
577 |
+
* {@inheritdoc}
|
578 |
+
*
|
579 |
+
* @see \IPLib\Address\AddressInterface::getNextAddress()
|
580 |
+
*/
|
581 |
+
public function getNextAddress()
|
582 |
+
{
|
583 |
+
return $this->getAddressAtOffset(1);
|
584 |
+
}
|
585 |
+
|
586 |
+
/**
|
587 |
+
* {@inheritdoc}
|
588 |
+
*
|
589 |
+
* @see \IPLib\Address\AddressInterface::getPreviousAddress()
|
590 |
+
*/
|
591 |
+
public function getPreviousAddress()
|
592 |
+
{
|
593 |
+
return $this->getAddressAtOffset(-1);
|
594 |
+
}
|
595 |
+
|
596 |
+
/**
|
597 |
+
* {@inheritdoc}
|
598 |
+
*
|
599 |
+
* @see \IPLib\Address\AddressInterface::getReverseDNSLookupName()
|
600 |
+
*/
|
601 |
+
public function getReverseDNSLookupName()
|
602 |
+
{
|
603 |
+
return implode(
|
604 |
+
'.',
|
605 |
+
array_reverse(str_split(str_replace(':', '', $this->toString(true)), 1))
|
606 |
+
) . '.ip6.arpa';
|
607 |
+
}
|
608 |
+
}
|
vendor/mlocati/ip-lib/src/Address/Type.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace IPLib\Address;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Types of IP addresses.
|
7 |
+
*/
|
8 |
+
class Type
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* IPv4 address.
|
12 |
+
*
|
13 |
+
* @var int
|
14 |
+
*/
|
15 |
+
const T_IPv4 = 4;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* IPv6 address.
|
19 |
+
*
|
20 |
+
* @var int
|
21 |
+
*/
|
22 |
+
const T_IPv6 = 6;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Get the name of a type.
|
26 |
+
*
|
27 |
+
* @param int $type
|
28 |
+
*
|
29 |
+
* @return string
|
30 |
+
*
|
31 |
+
* @since 1.1.0
|
32 |
+
*/
|
33 |
+
public static function getName($type)
|
34 |
+
{
|
35 |
+
switch ($type) {
|
36 |
+
case static::T_IPv4:
|
37 |
+
return 'IP v4';
|
38 |
+
case static::T_IPv6:
|
39 |
+
return 'IP v6';
|
40 |
+
default:
|
41 |
+
return sprintf('Unknown type (%s)', $type);
|
42 |
+
}
|
43 |
+
}
|
44 |
+
}
|
vendor/mlocati/ip-lib/src/Factory.php
ADDED
@@ -0,0 +1,298 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace IPLib;
|
4 |
+
|
5 |
+
use IPLib\Address\AddressInterface;
|
6 |
+
use IPLib\Range\Subnet;
|
7 |
+
use IPLib\Service\RangesFromBoundaryCalculator;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Factory methods to build class instances.
|
11 |
+
*/
|
12 |
+
class Factory
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* @deprecated since 1.17.0: use the parseAddressString() method instead.
|
16 |
+
* For upgrading:
|
17 |
+
* - if $mayIncludePort is true, use the ParseStringFlag::MAY_INCLUDE_PORT flag
|
18 |
+
* - if $mayIncludeZoneID is true, use the ParseStringFlag::MAY_INCLUDE_ZONEID flag
|
19 |
+
* - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
|
20 |
+
*
|
21 |
+
* @param string|mixed $address
|
22 |
+
* @param bool $mayIncludePort
|
23 |
+
* @param bool $mayIncludeZoneID
|
24 |
+
* @param bool $supportNonDecimalIPv4
|
25 |
+
*
|
26 |
+
* @return \IPLib\Address\AddressInterface|null
|
27 |
+
*
|
28 |
+
* @see \IPLib\Factory::parseAddressString()
|
29 |
+
* @since 1.1.0 added the $mayIncludePort argument
|
30 |
+
* @since 1.3.0 added the $mayIncludeZoneID argument
|
31 |
+
* @since 1.10.0 added the $supportNonDecimalIPv4 argument
|
32 |
+
*/
|
33 |
+
public static function addressFromString($address, $mayIncludePort = true, $mayIncludeZoneID = true, $supportNonDecimalIPv4 = false)
|
34 |
+
{
|
35 |
+
return static::parseAddressString($address, 0 + ($mayIncludePort ? ParseStringFlag::MAY_INCLUDE_PORT : 0) + ($mayIncludeZoneID ? ParseStringFlag::MAY_INCLUDE_ZONEID : 0) + ($supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0));
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Parse an IP address string.
|
40 |
+
*
|
41 |
+
* @param string|mixed $address the address to parse
|
42 |
+
* @param int $flags A combination or zero or more flags
|
43 |
+
*
|
44 |
+
* @return \IPLib\Address\AddressInterface|null
|
45 |
+
*
|
46 |
+
* @see \IPLib\ParseStringFlag
|
47 |
+
* @since 1.17.0
|
48 |
+
*/
|
49 |
+
public static function parseAddressString($address, $flags = 0)
|
50 |
+
{
|
51 |
+
$result = null;
|
52 |
+
if ($result === null) {
|
53 |
+
$result = Address\IPv4::parseString($address, $flags);
|
54 |
+
}
|
55 |
+
if ($result === null) {
|
56 |
+
$result = Address\IPv6::parseString($address, $flags);
|
57 |
+
}
|
58 |
+
|
59 |
+
return $result;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Convert a byte array to an address instance.
|
64 |
+
*
|
65 |
+
* @param int[]|array $bytes
|
66 |
+
*
|
67 |
+
* @return \IPLib\Address\AddressInterface|null
|
68 |
+
*/
|
69 |
+
public static function addressFromBytes(array $bytes)
|
70 |
+
{
|
71 |
+
$result = null;
|
72 |
+
if ($result === null) {
|
73 |
+
$result = Address\IPv4::fromBytes($bytes);
|
74 |
+
}
|
75 |
+
if ($result === null) {
|
76 |
+
$result = Address\IPv6::fromBytes($bytes);
|
77 |
+
}
|
78 |
+
|
79 |
+
return $result;
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* @deprecated since 1.17.0: use the parseRangeString() method instead.
|
84 |
+
* For upgrading:
|
85 |
+
* - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
|
86 |
+
*
|
87 |
+
* @param string|mixed $range
|
88 |
+
* @param bool $supportNonDecimalIPv4
|
89 |
+
*
|
90 |
+
* @return \IPLib\Range\RangeInterface|null
|
91 |
+
*
|
92 |
+
* @see \IPLib\Factory::parseRangeString()
|
93 |
+
* @since 1.10.0 added the $supportNonDecimalIPv4 argument
|
94 |
+
*/
|
95 |
+
public static function rangeFromString($range, $supportNonDecimalIPv4 = false)
|
96 |
+
{
|
97 |
+
return static::parseRangeString($range, $supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0);
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Parse an IP range string.
|
102 |
+
*
|
103 |
+
* @param string $range
|
104 |
+
* @param int $flags A combination or zero or more flags
|
105 |
+
*
|
106 |
+
* @return \IPLib\Range\RangeInterface|null
|
107 |
+
*
|
108 |
+
* @see \IPLib\ParseStringFlag
|
109 |
+
* @since 1.17.0
|
110 |
+
*/
|
111 |
+
public static function parseRangeString($range, $flags = 0)
|
112 |
+
{
|
113 |
+
$result = null;
|
114 |
+
if ($result === null) {
|
115 |
+
$result = Range\Subnet::parseString($range, $flags);
|
116 |
+
}
|
117 |
+
if ($result === null) {
|
118 |
+
$result = Range\Pattern::parseString($range, $flags);
|
119 |
+
}
|
120 |
+
if ($result === null) {
|
121 |
+
$result = Range\Single::parseString($range, $flags);
|
122 |
+
}
|
123 |
+
|
124 |
+
return $result;
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* @deprecated since 1.17.0: use the getRangeFromBoundaries() method instead.
|
129 |
+
* For upgrading:
|
130 |
+
* - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
|
131 |
+
*
|
132 |
+
* @param string|\IPLib\Address\AddressInterface|mixed $from
|
133 |
+
* @param string|\IPLib\Address\AddressInterface|mixed $to
|
134 |
+
* @param bool $supportNonDecimalIPv4
|
135 |
+
*
|
136 |
+
* @return \IPLib\Address\AddressInterface|null
|
137 |
+
*
|
138 |
+
* @see \IPLib\Factory::getRangeFromBoundaries()
|
139 |
+
* @since 1.2.0
|
140 |
+
* @since 1.10.0 added the $supportNonDecimalIPv4 argument
|
141 |
+
*/
|
142 |
+
public static function rangeFromBoundaries($from, $to, $supportNonDecimalIPv4 = false)
|
143 |
+
{
|
144 |
+
return static::getRangeFromBoundaries($from, $to, ParseStringFlag::MAY_INCLUDE_PORT | ParseStringFlag::MAY_INCLUDE_ZONEID | ($supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0));
|
145 |
+
}
|
146 |
+
|
147 |
+
/**
|
148 |
+
* Create the smallest address range that comprises two addresses.
|
149 |
+
*
|
150 |
+
* @param string|\IPLib\Address\AddressInterface|mixed $from
|
151 |
+
* @param string|\IPLib\Address\AddressInterface|mixed $to
|
152 |
+
* @param int $flags A combination or zero or more flags
|
153 |
+
*
|
154 |
+
* @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
|
155 |
+
*
|
156 |
+
* @see \IPLib\ParseStringFlag
|
157 |
+
* @since 1.17.0
|
158 |
+
*/
|
159 |
+
public static function getRangeFromBoundaries($from, $to, $flags = 0)
|
160 |
+
{
|
161 |
+
list($from, $to) = self::parseBoundaries($from, $to, $flags);
|
162 |
+
|
163 |
+
return $from === false || $to === false ? null : static::rangeFromBoundaryAddresses($from, $to);
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* @deprecated since 1.17.0: use the getRangesFromBoundaries() method instead.
|
168 |
+
* For upgrading:
|
169 |
+
* - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
|
170 |
+
*
|
171 |
+
* @param string|\IPLib\Address\AddressInterface|mixed $from
|
172 |
+
* @param string|\IPLib\Address\AddressInterface|mixed $to
|
173 |
+
* @param bool $supportNonDecimalIPv4
|
174 |
+
*
|
175 |
+
* @return \IPLib\Range\Subnet[]|null
|
176 |
+
*
|
177 |
+
* @see \IPLib\Factory::getRangesFromBoundaries()
|
178 |
+
* @since 1.14.0
|
179 |
+
*/
|
180 |
+
public static function rangesFromBoundaries($from, $to, $supportNonDecimalIPv4 = false)
|
181 |
+
{
|
182 |
+
return static::getRangesFromBoundaries($from, $to, ParseStringFlag::MAY_INCLUDE_PORT | ParseStringFlag::MAY_INCLUDE_ZONEID | ($supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0));
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Create a list of Range instances that exactly describes all the addresses between the two provided addresses.
|
187 |
+
*
|
188 |
+
* @param string|\IPLib\Address\AddressInterface $from
|
189 |
+
* @param string|\IPLib\Address\AddressInterface $to
|
190 |
+
* @param int $flags A combination or zero or more flags
|
191 |
+
*
|
192 |
+
* @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
|
193 |
+
*
|
194 |
+
* @see \IPLib\ParseStringFlag
|
195 |
+
* @since 1.17.0
|
196 |
+
*/
|
197 |
+
public static function getRangesFromBoundaries($from, $to, $flags = 0)
|
198 |
+
{
|
199 |
+
list($from, $to) = self::parseBoundaries($from, $to, $flags);
|
200 |
+
if ($from === false || $to === false || ($from === null && $to === null)) {
|
201 |
+
return null;
|
202 |
+
}
|
203 |
+
if ($from === null || $to === null) {
|
204 |
+
$address = $from ? $from : $to;
|
205 |
+
|
206 |
+
return array(new Subnet($address, $address, $address->getNumberOfBits()));
|
207 |
+
}
|
208 |
+
$numberOfBits = $from->getNumberOfBits();
|
209 |
+
if ($to->getNumberOfBits() !== $numberOfBits) {
|
210 |
+
return null;
|
211 |
+
}
|
212 |
+
$calculator = new RangesFromBoundaryCalculator($numberOfBits);
|
213 |
+
|
214 |
+
return $calculator->getRanges($from, $to);
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* @param \IPLib\Address\AddressInterface $from
|
219 |
+
* @param \IPLib\Address\AddressInterface $to
|
220 |
+
*
|
221 |
+
* @return \IPLib\Range\RangeInterface|null
|
222 |
+
*
|
223 |
+
* @since 1.2.0
|
224 |
+
*/
|
225 |
+
protected static function rangeFromBoundaryAddresses(AddressInterface $from = null, AddressInterface $to = null)
|
226 |
+
{
|
227 |
+
if ($from === null && $to === null) {
|
228 |
+
$result = null;
|
229 |
+
} elseif ($to === null) {
|
230 |
+
$result = Range\Single::fromAddress($from);
|
231 |
+
} elseif ($from === null) {
|
232 |
+
$result = Range\Single::fromAddress($to);
|
233 |
+
} else {
|
234 |
+
$result = null;
|
235 |
+
$addressType = $from->getAddressType();
|
236 |
+
if ($addressType === $to->getAddressType()) {
|
237 |
+
$cmp = strcmp($from->getComparableString(), $to->getComparableString());
|
238 |
+
if ($cmp === 0) {
|
239 |
+
$result = Range\Single::fromAddress($from);
|
240 |
+
} else {
|
241 |
+
if ($cmp > 0) {
|
242 |
+
list($from, $to) = array($to, $from);
|
243 |
+
}
|
244 |
+
$fromBytes = $from->getBytes();
|
245 |
+
$toBytes = $to->getBytes();
|
246 |
+
$numBytes = count($fromBytes);
|
247 |
+
$sameBits = 0;
|
248 |
+
for ($byteIndex = 0; $byteIndex < $numBytes; $byteIndex++) {
|
249 |
+
$fromByte = $fromBytes[$byteIndex];
|
250 |
+
$toByte = $toBytes[$byteIndex];
|
251 |
+
if ($fromByte === $toByte) {
|
252 |
+
$sameBits += 8;
|
253 |
+
} else {
|
254 |
+
$differentBitsInByte = decbin($fromByte ^ $toByte);
|
255 |
+
$sameBits += 8 - strlen($differentBitsInByte);
|
256 |
+
break;
|
257 |
+
}
|
258 |
+
}
|
259 |
+
$result = static::parseRangeString($from->toString() . '/' . (string) $sameBits);
|
260 |
+
}
|
261 |
+
}
|
262 |
+
}
|
263 |
+
|
264 |
+
return $result;
|
265 |
+
}
|
266 |
+
|
267 |
+
/**
|
268 |
+
* @param string|\IPLib\Address\AddressInterface $from
|
269 |
+
* @param string|\IPLib\Address\AddressInterface $to
|
270 |
+
* @param int $flags
|
271 |
+
*
|
272 |
+
* @return \IPLib\Address\AddressInterface[]|null[]|false[]
|
273 |
+
*/
|
274 |
+
private static function parseBoundaries($from, $to, $flags = 0)
|
275 |
+
{
|
276 |
+
$result = array();
|
277 |
+
foreach (array('from', 'to') as $param) {
|
278 |
+
$value = $$param;
|
279 |
+
if (!($value instanceof AddressInterface)) {
|
280 |
+
$value = (string) $value;
|
281 |
+
if ($value === '') {
|
282 |
+
$value = null;
|
283 |
+
} else {
|
284 |
+
$value = static::parseAddressString($value, $flags);
|
285 |
+
if ($value === null) {
|
286 |
+
$value = false;
|
287 |
+
}
|
288 |
+
}
|
289 |
+
}
|
290 |
+
$result[] = $value;
|
291 |
+
}
|
292 |
+
if ($result[0] && $result[1] && strcmp($result[0]->getComparableString(), $result[1]->getComparableString()) > 0) {
|
293 |
+
$result = array($result[1], $result[0]);
|
294 |
+
}
|
295 |
+
|
296 |
+
return $result;
|
297 |
+
}
|
298 |
+
}
|
vendor/mlocati/ip-lib/src/ParseStringFlag.php
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace IPLib;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Flags for the parseString() methods.
|
7 |
+
*
|
8 |
+
* @since 1.17.0
|
9 |
+
*/
|
10 |
+
class ParseStringFlag
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Use this flag if the input string may include the port.
|
14 |
+
*
|
15 |
+
* @var int
|
16 |
+
*/
|
17 |
+
const MAY_INCLUDE_PORT = 1;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Use this flag if the input string may include a zone ID.
|
21 |
+
*
|
22 |
+
* @var int
|
23 |
+
*/
|
24 |
+
const MAY_INCLUDE_ZONEID = 2;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Use this flag if IPv4 addresses may be in decimal/octal/hexadecimal format.
|
28 |
+
* 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.
|
29 |
+
*
|
30 |
+
* @var int
|
31 |
+
*
|
32 |
+
* @example 1.08.0x10.0 => 5.0.0.1
|
33 |
+
* @example 5.256 => 5.0.1.0
|
34 |
+
* @example 5.0.256 => 5.0.1.0
|
35 |
+
* @example 123456789 => 7.91.205.21
|
36 |
+
*/
|
37 |
+
const IPV4_MAYBE_NON_DECIMAL = 4;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Use this flag if IPv4 subnet ranges may be in compact form.
|
41 |
+
*
|
42 |
+
* @example 127/24 => 127.0.0.0/24
|
43 |
+
* @example 10/8 => 10.0.0.0/8
|
44 |
+
* @example 10/24 => 10.0.0.0/24
|
45 |
+
* @example 10.10.10/24 => 10.10.10.0/24
|
46 |
+
*
|
47 |
+
* @var int
|
48 |
+
*/
|
49 |
+
const IPV4SUBNET_MAYBE_COMPACT = 8;
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Use this flag if IPv4 addresses may be in non quad-dotted notation.
|
53 |
+
* 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.
|
54 |
+
*
|
55 |
+
* @var int
|
56 |
+
*
|
57 |
+
* @example 5.1 => 5.0.0.1
|
58 |
+
* @example 5.256 => 5.0.1.0
|
59 |
+
* @example 5.0.256 => 5.0.1.0
|
60 |
+
* @example 123456789 => 7.91.205.21
|
61 |
+
*
|
62 |
+
* @see https://man7.org/linux/man-pages/man3/inet_addr.3.html#DESCRIPTION
|
63 |
+
* @see https://www.freebsd.org/cgi/man.cgi?query=inet_net&sektion=3&apropos=0&manpath=FreeBSD+12.2-RELEASE+and+Ports#end
|
64 |
+
* @see http://git.musl-libc.org/cgit/musl/tree/src/network/inet_aton.c?h=v1.2.2
|
65 |
+
*/
|
66 |
+
const IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED = 16;
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Use this flag if you want to accept parsing IPv4/IPv6 addresses in Reverse DNS Lookup Address format.
|
70 |
+
*
|
71 |
+
* @var int
|
72 |
+
*
|
73 |
+
* @since 1.18.0
|
74 |
+
*
|
75 |
+
* @example 140.13.12.10.in-addr.arpa => 10.12.13.140
|
76 |
+
* @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
|
77 |
+
*/
|
78 |
+
const ADDRESS_MAYBE_RDNS = 32;
|
79 |
+
}
|
vendor/mlocati/ip-lib/src/Range/AbstractRange.php
ADDED
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace IPLib\Range;
|
4 |
+
|
5 |
+
use IPLib\Address\AddressInterface;
|
6 |
+
use IPLib\Address\IPv4;
|
7 |
+
use IPLib\Address\IPv6;
|
8 |
+
use IPLib\Address\Type as AddressType;
|
9 |
+
use IPLib\Factory;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Base class for range classes.
|
13 |
+
*/
|
14 |
+
abstract class AbstractRange implements RangeInterface
|
15 |
+
{
|
16 |
+
/**
|
17 |
+
* {@inheritdoc}
|
18 |
+
*
|
19 |
+
* @see \IPLib\Range\RangeInterface::getRangeType()
|
20 |
+
*/
|
21 |
+
public function getRangeType()
|
22 |
+
{
|
23 |
+
if ($this->rangeType === null) {
|
24 |
+
$addressType = $this->getAddressType();
|
25 |
+
if ($addressType === AddressType::T_IPv6 && Subnet::get6to4()->containsRange($this)) {
|
26 |
+
$this->rangeType = Factory::getRangeFromBoundaries($this->fromAddress->toIPv4(), $this->toAddress->toIPv4())->getRangeType();
|
27 |
+
} else {
|
28 |
+
switch ($addressType) {
|
29 |
+
case AddressType::T_IPv4:
|
30 |
+
$defaultType = IPv4::getDefaultReservedRangeType();
|
31 |
+
$reservedRanges = IPv4::getReservedRanges();
|
32 |
+
break;
|
33 |
+
case AddressType::T_IPv6:
|
34 |
+
$defaultType = IPv6::getDefaultReservedRangeType();
|
35 |
+
$reservedRanges = IPv6::getReservedRanges();
|
36 |
+
break;
|
37 |
+
default:
|
38 |
+
throw new \Exception('@todo'); // @codeCoverageIgnore
|
39 |
+
}
|
40 |
+
$rangeType = null;
|
41 |
+
foreach ($reservedRanges as $reservedRange) {
|
42 |
+
$rangeType = $reservedRange->getRangeType($this);
|
43 |
+
if ($rangeType !== null) {
|
44 |
+
break;
|
45 |
+
}
|
46 |
+
}
|
47 |
+
$this->rangeType = $rangeType === null ? $defaultType : $rangeType;
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
return $this->rangeType === false ? null : $this->rangeType;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* {@inheritdoc}
|
56 |
+
*
|
57 |
+
* @see \IPLib\Range\RangeInterface::getAddressAtOffset()
|
58 |
+
*/
|
59 |
+
public function getAddressAtOffset($n)
|
60 |
+
{
|
61 |
+
if (!is_int($n)) {
|
62 |
+
return null;
|
63 |
+
}
|
64 |
+
|
65 |
+
$address = null;
|
66 |
+
if ($n >= 0) {
|
67 |
+
$start = Factory::parseAddressString($this->getComparableStartString());
|
68 |
+
$address = $start->getAddressAtOffset($n);
|
69 |
+
} else {
|
70 |
+
$end = Factory::parseAddressString($this->getComparableEndString());
|
71 |
+
$address = $end->getAddressAtOffset($n + 1);
|
72 |
+
}
|
73 |
+
|
74 |
+
if ($address === null) {
|
75 |
+
return null;
|
76 |
+
}
|
77 |
+
|
78 |
+
return $this->contains($address) ? $address : null;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* {@inheritdoc}
|
83 |
+
*
|
84 |
+
* @see \IPLib\Range\RangeInterface::contains()
|
85 |
+
*/
|
86 |
+
public function contains(AddressInterface $address)
|
87 |
+
{
|
88 |
+
$result = false;
|
89 |
+
if ($address->getAddressType() === $this->getAddressType()) {
|
90 |
+
$cmp = $address->getComparableString();
|
91 |
+
$from = $this->getComparableStartString();
|
92 |
+
if ($cmp >= $from) {
|
93 |
+
$to = $this->getComparableEndString();
|
94 |
+
if ($cmp <= $to) {
|
95 |
+
$result = true;
|
96 |
+
}
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
return $result;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* {@inheritdoc}
|
105 |
+
*
|
106 |
+
* @see \IPLib\Range\RangeInterface::containsRange()
|
107 |
+
*/
|
108 |
+
public function containsRange(RangeInterface $range)
|
109 |
+
{
|
110 |
+
$result = false;
|
111 |
+
if ($range->getAddressType() === $this->getAddressType()) {
|
112 |
+
$myStart = $this->getComparableStartString();
|
113 |
+
$itsStart = $range->getComparableStartString();
|
114 |
+
if ($itsStart >= $myStart) {
|
115 |
+
$myEnd = $this->getComparableEndString();
|
116 |
+
$itsEnd = $range->getComparableEndString();
|
117 |
+
if ($itsEnd <= $myEnd) {
|
118 |
+
$result = true;
|
119 |
+
}
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
return $result;
|
124 |
+
}
|
125 |
+
}
|
vendor/mlocati/ip-lib/src/Range/Pattern.php
ADDED
@@ -0,0 +1,322 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace IPLib\Range;
|
4 |
+
|
5 |
+
use IPLib\Address\AddressInterface;
|
6 |
+
use IPLib\Address\IPv4;
|
7 |
+
use IPLib\Address\IPv6;
|
8 |
+
use IPLib\Address\Type as AddressType;
|
9 |
+
use IPLib\ParseStringFlag;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Represents an address range in pattern format (only ending asterisks are supported).
|
13 |
+
*
|
14 |
+
* @example 127.0.*.*
|
15 |
+
* @example ::/8
|
16 |
+
*/
|
17 |
+
class Pattern extends AbstractRange
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Starting address of the range.
|
21 |
+
*
|
22 |
+
* @var \IPLib\Address\AddressInterface
|
23 |
+
*/
|
24 |
+
protected $fromAddress;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Final address of the range.
|
28 |
+
*
|
29 |
+
* @var \IPLib\Address\AddressInterface
|
30 |
+
*/
|
31 |
+
protected $toAddress;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Number of ending asterisks.
|
35 |
+
*
|
36 |
+
* @var int
|
37 |
+
*/
|
38 |
+
protected $asterisksCount;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* The type of the range of this IP range.
|
42 |
+
*
|
43 |
+
* @var int|false|null false if this range crosses multiple range types, null if yet to be determined
|
44 |
+
*
|
45 |
+
* @since 1.5.0
|
46 |
+
*/
|
47 |
+
protected $rangeType;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Initializes the instance.
|
51 |
+
*
|
52 |
+
* @param \IPLib\Address\AddressInterface $fromAddress
|
53 |
+
* @param \IPLib\Address\AddressInterface $toAddress
|
54 |
+
* @param int $asterisksCount
|
55 |
+
*/
|
56 |
+
public function __construct(AddressInterface $fromAddress, AddressInterface $toAddress, $asterisksCount)
|
57 |
+
{
|
58 |
+
$this->fromAddress = $fromAddress;
|
59 |
+
$this->toAddress = $toAddress;
|
60 |
+
$this->asterisksCount = $asterisksCount;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* {@inheritdoc}
|
65 |
+
*
|
66 |
+
* @see \IPLib\Range\RangeInterface::__toString()
|
67 |
+
*/
|
68 |
+
public function __toString()
|
69 |
+
{
|
70 |
+
return $this->toString();
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* @deprecated since 1.17.0: use the parseString() method instead.
|
75 |
+
* For upgrading:
|
76 |
+
* - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
|
77 |
+
*
|
78 |
+
* @param string|mixed $range
|
79 |
+
* @param bool $supportNonDecimalIPv4
|
80 |
+
*
|
81 |
+
* @return static|null
|
82 |
+
*
|
83 |
+
* @see \IPLib\Range\Pattern::parseString()
|
84 |
+
* @since 1.10.0 added the $supportNonDecimalIPv4 argument
|
85 |
+
*/
|
86 |
+
public static function fromString($range, $supportNonDecimalIPv4 = false)
|
87 |
+
{
|
88 |
+
return static::parseString($range, ParseStringFlag::MAY_INCLUDE_PORT | ParseStringFlag::MAY_INCLUDE_ZONEID | ($supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0));
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Try get the range instance starting from its string representation.
|
93 |
+
*
|
94 |
+
* @param string|mixed $range
|
95 |
+
* @param int $flags A combination or zero or more flags
|
96 |
+
*
|
97 |
+
* @return static|null
|
98 |
+
*
|
99 |
+
* @since 1.17.0
|
100 |
+
* @see \IPLib\ParseStringFlag
|
101 |
+
*/
|
102 |
+
public static function parseString($range, $flags = 0)
|
103 |
+
{
|
104 |
+
if (!is_string($range) || strpos($range, '*') === false) {
|
105 |
+
return null;
|
106 |
+
}
|
107 |
+
if ($range === '*.*.*.*') {
|
108 |
+
return new static(IPv4::parseString('0.0.0.0'), IPv4::parseString('255.255.255.255'), 4);
|
109 |
+
}
|
110 |
+
if ($range === '*:*:*:*:*:*:*:*') {
|
111 |
+
return new static(IPv6::parseString('::'), IPv6::parseString('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'), 8);
|
112 |
+
}
|
113 |
+
$matches = null;
|
114 |
+
if (strpos($range, '.') !== false && preg_match('/^[^*]+((?:\.\*)+)$/', $range, $matches)) {
|
115 |
+
$asterisksCount = strlen($matches[1]) >> 1;
|
116 |
+
if ($asterisksCount > 0) {
|
117 |
+
$missingDots = 3 - substr_count($range, '.');
|
118 |
+
if ($missingDots > 0) {
|
119 |
+
$range .= str_repeat('.*', $missingDots);
|
120 |
+
$asterisksCount += $missingDots;
|
121 |
+
}
|
122 |
+
}
|
123 |
+
$fromAddress = IPv4::parseString(str_replace('*', '0', $range), $flags);
|
124 |
+
if ($fromAddress === null) {
|
125 |
+
return null;
|
126 |
+
}
|
127 |
+
$fixedBytes = array_slice($fromAddress->getBytes(), 0, -$asterisksCount);
|
128 |
+
$otherBytes = array_fill(0, $asterisksCount, 255);
|
129 |
+
$toAddress = IPv4::fromBytes(array_merge($fixedBytes, $otherBytes));
|
130 |
+
|
131 |
+
return new static($fromAddress, $toAddress, $asterisksCount);
|
132 |
+
}
|
133 |
+
if (strpos($range, ':') !== false && preg_match('/^[^*]+((?::\*)+)$/', $range, $matches)) {
|
134 |
+
$asterisksCount = strlen($matches[1]) >> 1;
|
135 |
+
$fromAddress = IPv6::parseString(str_replace('*', '0', $range));
|
136 |
+
if ($fromAddress === null) {
|
137 |
+
return null;
|
138 |
+
}
|
139 |
+
$fixedWords = array_slice($fromAddress->getWords(), 0, -$asterisksCount);
|
140 |
+
$otherWords = array_fill(0, $asterisksCount, 0xffff);
|
141 |
+
$toAddress = IPv6::fromWords(array_merge($fixedWords, $otherWords));
|
142 |
+
|
143 |
+
return new static($fromAddress, $toAddress, $asterisksCount);
|
144 |
+
}
|
145 |
+
|
146 |
+
return null;
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* {@inheritdoc}
|
151 |
+
*
|
152 |
+
* @see \IPLib\Range\RangeInterface::toString()
|
153 |
+
*/
|
154 |
+
public function toString($long = false)
|
155 |
+
{
|
156 |
+
if ($this->asterisksCount === 0) {
|
157 |
+
return $this->fromAddress->toString($long);
|
158 |
+
}
|
159 |
+
switch (true) {
|
160 |
+
case $this->fromAddress instanceof \IPLib\Address\IPv4:
|
161 |
+
$chunks = explode('.', $this->fromAddress->toString());
|
162 |
+
$chunks = array_slice($chunks, 0, -$this->asterisksCount);
|
163 |
+
$chunks = array_pad($chunks, 4, '*');
|
164 |
+
$result = implode('.', $chunks);
|
165 |
+
break;
|
166 |
+
case $this->fromAddress instanceof \IPLib\Address\IPv6:
|
167 |
+
if ($long) {
|
168 |
+
$chunks = explode(':', $this->fromAddress->toString(true));
|
169 |
+
$chunks = array_slice($chunks, 0, -$this->asterisksCount);
|
170 |
+
$chunks = array_pad($chunks, 8, '*');
|
171 |
+
$result = implode(':', $chunks);
|
172 |
+
} elseif ($this->asterisksCount === 8) {
|
173 |
+
$result = '*:*:*:*:*:*:*:*';
|
174 |
+
} else {
|
175 |
+
$bytes = $this->toAddress->getBytes();
|
176 |
+
$bytes = array_slice($bytes, 0, -$this->asterisksCount * 2);
|
177 |
+
$bytes = array_pad($bytes, 16, 1);
|
178 |
+
$address = IPv6::fromBytes($bytes);
|
179 |
+
$before = substr($address->toString(false), 0, -strlen(':101') * $this->asterisksCount);
|
180 |
+
$result = $before . str_repeat(':*', $this->asterisksCount);
|
181 |
+
}
|
182 |
+
break;
|
183 |
+
default:
|
184 |
+
throw new \Exception('@todo'); // @codeCoverageIgnore
|
185 |
+
}
|
186 |
+
|
187 |
+
return $result;
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* {@inheritdoc}
|
192 |
+
*
|
193 |
+
* @see \IPLib\Range\RangeInterface::getAddressType()
|
194 |
+
*/
|
195 |
+
public function getAddressType()
|
196 |
+
{
|
197 |
+
return $this->fromAddress->getAddressType();
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* {@inheritdoc}
|
202 |
+
*
|
203 |
+
* @see \IPLib\Range\RangeInterface::getStartAddress()
|
204 |
+
*/
|
205 |
+
public function getStartAddress()
|
206 |
+
{
|
207 |
+
return $this->fromAddress;
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* {@inheritdoc}
|
212 |
+
*
|
213 |
+
* @see \IPLib\Range\RangeInterface::getEndAddress()
|
214 |
+
*/
|
215 |
+
public function getEndAddress()
|
216 |
+
{
|
217 |
+
return $this->toAddress;
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* {@inheritdoc}
|
222 |
+
*
|
223 |
+
* @see \IPLib\Range\RangeInterface::getComparableStartString()
|
224 |
+
*/
|
225 |
+
public function getComparableStartString()
|
226 |
+
{
|
227 |
+
return $this->fromAddress->getComparableString();
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* {@inheritdoc}
|
232 |
+
*
|
233 |
+
* @see \IPLib\Range\RangeInterface::getComparableEndString()
|
234 |
+
*/
|
235 |
+
public function getComparableEndString()
|
236 |
+
{
|
237 |
+
return $this->toAddress->getComparableString();
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* {@inheritdoc}
|
242 |
+
*
|
243 |
+
* @see \IPLib\Range\RangeInterface::asSubnet()
|
244 |
+
* @since 1.8.0
|
245 |
+
*/
|
246 |
+
public function asSubnet()
|
247 |
+
{
|
248 |
+
return new Subnet($this->getStartAddress(), $this->getEndAddress(), $this->getNetworkPrefix());
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* {@inheritdoc}
|
253 |
+
*
|
254 |
+
* @see \IPLib\Range\RangeInterface::asPattern()
|
255 |
+
*/
|
256 |
+
public function asPattern()
|
257 |
+
{
|
258 |
+
return $this;
|
259 |
+
}
|
260 |
+
|
261 |
+
/**
|
262 |
+
* {@inheritdoc}
|
263 |
+
*
|
264 |
+
* @see \IPLib\Range\RangeInterface::getSubnetMask()
|
265 |
+
*/
|
266 |
+
public function getSubnetMask()
|
267 |
+
{
|
268 |
+
if ($this->getAddressType() !== AddressType::T_IPv4) {
|
269 |
+
return null;
|
270 |
+
}
|
271 |
+
switch ($this->asterisksCount) {
|
272 |
+
case 0:
|
273 |
+
$bytes = array(255, 255, 255, 255);
|
274 |
+
break;
|
275 |
+
case 4:
|
276 |
+
$bytes = array(0, 0, 0, 0);
|
277 |
+
break;
|
278 |
+
default:
|
279 |
+
$bytes = array_pad(array_fill(0, 4 - $this->asterisksCount, 255), 4, 0);
|
280 |
+
break;
|
281 |
+
}
|
282 |
+
|
283 |
+
return IPv4::fromBytes($bytes);
|
284 |
+
}
|
285 |
+
|
286 |
+
/**
|
287 |
+
* {@inheritdoc}
|
288 |
+
*
|
289 |
+
* @see \IPLib\Range\RangeInterface::getReverseDNSLookupName()
|
290 |
+
*/
|
291 |
+
public function getReverseDNSLookupName()
|
292 |
+
{
|
293 |
+
return $this->asterisksCount === 0 ? array($this->getStartAddress()->getReverseDNSLookupName()) : $this->asSubnet()->getReverseDNSLookupName();
|
294 |
+
}
|
295 |
+
|
296 |
+
/**
|
297 |
+
* {@inheritdoc}
|
298 |
+
*
|
299 |
+
* @see \IPLib\Range\RangeInterface::getSize()
|
300 |
+
*/
|
301 |
+
public function getSize()
|
302 |
+
{
|
303 |
+
$fromAddress = $this->fromAddress;
|
304 |
+
$maxPrefix = $fromAddress::getNumberOfBits();
|
305 |
+
$prefix = $this->getNetworkPrefix();
|
306 |
+
|
307 |
+
return pow(2, ($maxPrefix - $prefix));
|
308 |
+
}
|
309 |
+
|
310 |
+
/**
|
311 |
+
* @return float|int
|
312 |
+
*/
|
313 |
+
private function getNetworkPrefix()
|
314 |
+
{
|
315 |
+
switch ($this->getAddressType()) {
|
316 |
+
case AddressType::T_IPv4:
|
317 |
+
return 8 * (4 - $this->asterisksCount);
|
318 |
+
case AddressType::T_IPv6:
|
319 |
+
return 16 * (8 - $this->asterisksCount);
|
320 |
+
}
|
321 |
+
}
|
322 |
+
}
|
vendor/mlocati/ip-lib/src/Range/RangeInterface.php
ADDED
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace IPLib\Range;
|
4 |
+
|
5 |
+
use IPLib\Address\AddressInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Interface of all the range types.
|
9 |
+
*/
|
10 |
+
interface RangeInterface
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Get the short string representation of this address.
|
14 |
+
*
|
15 |
+
* @return string
|
16 |
+
*/
|
17 |
+
public function __toString();
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Get the string representation of this address.
|
21 |
+
*
|
22 |
+
* @param bool $long set to true to have a long/full representation, false otherwise
|
23 |
+
*
|
24 |
+
* @return string
|
25 |
+
*
|
26 |
+
* @example If $long is true, you'll get '0000:0000:0000:0000:0000:0000:0000:0001/128', '::1/128' otherwise.
|
27 |
+
*/
|
28 |
+
public function toString($long = false);
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Get the type of the IP addresses contained in this range.
|
32 |
+
*
|
33 |
+
* @return int One of the \IPLib\Address\Type::T_... constants
|
34 |
+
*/
|
35 |
+
public function getAddressType();
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Get the type of range of the IP address.
|
39 |
+
*
|
40 |
+
* @return int One of the \IPLib\Range\Type::T_... constants
|
41 |
+
*
|
42 |
+
* @since 1.5.0
|
43 |
+
*/
|
44 |
+
public function getRangeType();
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Get the address at a certain offset of this range.
|
48 |
+
*
|
49 |
+
* @param int $n the offset of the address (support negative offset)
|
50 |
+
*
|
51 |
+
* @return \IPLib\Address\AddressInterface|null return NULL if $n is not an integer or if the offset out of range
|
52 |
+
*
|
53 |
+
* @since 1.15.0
|
54 |
+
*
|
55 |
+
* @example passing 256 to the range 127.0.0.0/16 will result in 127.0.1.0
|
56 |
+
* @example passing -1 to the range 127.0.1.0/16 will result in 127.0.255.255
|
57 |
+
* @example passing 256 to the range 127.0.0.0/24 will result in NULL
|
58 |
+
*/
|
59 |
+
public function getAddressAtOffset($n);
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Check if this range contains an IP address.
|
63 |
+
*
|
64 |
+
* @param \IPLib\Address\AddressInterface $address
|
65 |
+
*
|
66 |
+
* @return bool
|
67 |
+
*/
|
68 |
+
public function contains(AddressInterface $address);
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Check if this range contains another range.
|
72 |
+
*
|
73 |
+
* @param \IPLib\Range\RangeInterface $range
|
74 |
+
*
|
75 |
+
* @return bool
|
76 |
+
*
|
77 |
+
* @since 1.5.0
|
78 |
+
*/
|
79 |
+
public function containsRange(RangeInterface $range);
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Get the initial address contained in this range.
|
83 |
+
*
|
84 |
+
* @return \IPLib\Address\AddressInterface
|
85 |
+
*
|
86 |
+
* @since 1.4.0
|
87 |
+
*/
|
88 |
+
public function getStartAddress();
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Get the final address contained in this range.
|
92 |
+
*
|
93 |
+
* @return \IPLib\Address\AddressInterface
|
94 |
+
*
|
95 |
+
* @since 1.4.0
|
96 |
+
*/
|
97 |
+
public function getEndAddress();
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Get a string representation of the starting address of this range than can be used when comparing addresses and ranges.
|
101 |
+
*
|
102 |
+
* @return string
|
103 |
+
*/
|
104 |
+
public function getComparableStartString();
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Get a string representation of the final address of this range than can be used when comparing addresses and ranges.
|
108 |
+
*
|
109 |
+
* @return string
|
110 |
+
*/
|
111 |
+
public function getComparableEndString();
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Get the subnet mask representing this range (only for IPv4 ranges).
|
115 |
+
*
|
116 |
+
* @return \IPLib\Address\IPv4|null return NULL if the range is an IPv6 range, the subnet mask otherwise
|
117 |
+
*
|
118 |
+
* @since 1.8.0
|
119 |
+
*/
|
120 |
+
public function getSubnetMask();
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Get the subnet/CIDR representation of this range.
|
124 |
+
*
|
125 |
+
* @return \IPLib\Range\Subnet
|
126 |
+
*
|
127 |
+
* @since 1.13.0
|
128 |
+
*/
|
129 |
+
public function asSubnet();
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Get the pattern/asterisk representation (if applicable) of this range.
|
133 |
+
*
|
134 |
+
* @return \IPLib\Range\Pattern|null return NULL if this range can't be represented by a pattern notation
|
135 |
+
*
|
136 |
+
* @since 1.13.0
|
137 |
+
*/
|
138 |
+
public function asPattern();
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Get the Reverse DNS Lookup Addresses of this IP range.
|
142 |
+
*
|
143 |
+
* @return string[]
|
144 |
+
*
|
145 |
+
* @since 1.13.0
|
146 |
+
*
|
147 |
+
* @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)
|
148 |
+
* @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)
|
149 |
+
*/
|
150 |
+
public function getReverseDNSLookupName();
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Get the count of addresses this IP range contains.
|
154 |
+
*
|
155 |
+
* @return int|float Return float as for huge IPv6 networks, int is not enough
|
156 |
+
*
|
157 |
+
* @since 1.16.0
|
158 |
+
*/
|
159 |
+
public function getSize();
|
160 |
+
}
|
vendor/mlocati/ip-lib/src/Range/Single.php
ADDED
@@ -0,0 +1,244 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace IPLib\Range;
|
4 |
+
|
5 |
+
use IPLib\Address\AddressInterface;
|
6 |
+
use IPLib\Address\IPv4;
|
7 |
+
use IPLib\Address\Type as AddressType;
|
8 |
+
use IPLib\Factory;
|
9 |
+
use IPLib\ParseStringFlag;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Represents a single address (eg a range that contains just one address).
|
13 |
+
*
|
14 |
+
* @example 127.0.0.1
|
15 |
+
* @example ::1
|
16 |
+
*/
|
17 |
+
class Single extends AbstractRange
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* @var \IPLib\Address\AddressInterface
|
21 |
+
*/
|
22 |
+
protected $address;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Initializes the instance.
|
26 |
+
*
|
27 |
+
* @param \IPLib\Address\AddressInterface $address
|
28 |
+
*/
|
29 |
+
protected function __construct(AddressInterface $address)
|
30 |
+
{
|
31 |
+
$this->address = $address;
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* {@inheritdoc}
|
36 |
+
*
|
37 |
+
* @see \IPLib\Range\RangeInterface::__toString()
|
38 |
+
*/
|
39 |
+
public function __toString()
|
40 |
+
{
|
41 |
+
return $this->address->__toString();
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @deprecated since 1.17.0: use the parseString() method instead.
|
46 |
+
* For upgrading:
|
47 |
+
* - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
|
48 |
+
*
|
49 |
+
* @param string|mixed $range
|
50 |
+
* @param bool $supportNonDecimalIPv4
|
51 |
+
*
|
52 |
+
* @return static|null
|
53 |
+
*
|
54 |
+
* @see \IPLib\Range\Single::parseString()
|
55 |
+
* @since 1.10.0 added the $supportNonDecimalIPv4 argument
|
56 |
+
*/
|
57 |
+
public static function fromString($range, $supportNonDecimalIPv4 = false)
|
58 |
+
{
|
59 |
+
return static::parseString($range, ParseStringFlag::MAY_INCLUDE_PORT | ParseStringFlag::MAY_INCLUDE_ZONEID | ($supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0));
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Try get the range instance starting from its string representation.
|
64 |
+
*
|
65 |
+
* @param string|mixed $range
|
66 |
+
* @param int $flags A combination or zero or more flags
|
67 |
+
*
|
68 |
+
* @return static|null
|
69 |
+
*
|
70 |
+
* @see \IPLib\ParseStringFlag
|
71 |
+
* @since 1.17.0
|
72 |
+
*/
|
73 |
+
public static function parseString($range, $flags = 0)
|
74 |
+
{
|
75 |
+
$result = null;
|
76 |
+
$flags = (int) $flags;
|
77 |
+
$address = Factory::parseAddressString($range, $flags);
|
78 |
+
if ($address !== null) {
|
79 |
+
$result = new static($address);
|
80 |
+
}
|
81 |
+
|
82 |
+
return $result;
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Create the range instance starting from an address instance.
|
87 |
+
*
|
88 |
+
* @param \IPLib\Address\AddressInterface $address
|
89 |
+
*
|
90 |
+
* @return static
|
91 |
+
*
|
92 |
+
* @since 1.2.0
|
93 |
+
*/
|
94 |
+
public static function fromAddress(AddressInterface $address)
|
95 |
+
{
|
96 |
+
return new static($address);
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* {@inheritdoc}
|
101 |
+
*
|
102 |
+
* @see \IPLib\Range\RangeInterface::toString()
|
103 |
+
*/
|
104 |
+
public function toString($long = false)
|
105 |
+
{
|
106 |
+
return $this->address->toString($long);
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* {@inheritdoc}
|
111 |
+
*
|
112 |
+
* @see \IPLib\Range\RangeInterface::getAddressType()
|
113 |
+
*/
|
114 |
+
public function getAddressType()
|
115 |
+
{
|
116 |
+
return $this->address->getAddressType();
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* {@inheritdoc}
|
121 |
+
*
|
122 |
+
* @see \IPLib\Range\RangeInterface::getRangeType()
|
123 |
+
*/
|
124 |
+
public function getRangeType()
|
125 |
+
{
|
126 |
+
return $this->address->getRangeType();
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* {@inheritdoc}
|
131 |
+
*
|
132 |
+
* @see \IPLib\Range\RangeInterface::contains()
|
133 |
+
*/
|
134 |
+
public function contains(AddressInterface $address)
|
135 |
+
{
|
136 |
+
$result = false;
|
137 |
+
if ($address->getAddressType() === $this->getAddressType()) {
|
138 |
+
if ($address->toString(false) === $this->address->toString(false)) {
|
139 |
+
$result = true;
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
return $result;
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* {@inheritdoc}
|
148 |
+
*
|
149 |
+
* @see \IPLib\Range\RangeInterface::getStartAddress()
|
150 |
+
*/
|
151 |
+
public function getStartAddress()
|
152 |
+
{
|
153 |
+
return $this->address;
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* {@inheritdoc}
|
158 |
+
*
|
159 |
+
* @see \IPLib\Range\RangeInterface::getEndAddress()
|
160 |
+
*/
|
161 |
+
public function getEndAddress()
|
162 |
+
{
|
163 |
+
return $this->address;
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* {@inheritdoc}
|
168 |
+
*
|
169 |
+
* @see \IPLib\Range\RangeInterface::getComparableStartString()
|
170 |
+
*/
|
171 |
+
public function getComparableStartString()
|
172 |
+
{
|
173 |
+
return $this->address->getComparableString();
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* {@inheritdoc}
|
178 |
+
*
|
179 |
+
* @see \IPLib\Range\RangeInterface::getComparableEndString()
|
180 |
+
*/
|
181 |
+
public function getComparableEndString()
|
182 |
+
{
|
183 |
+
return $this->address->getComparableString();
|
184 |
+
}
|
185 |
+
|
186 |
+
/**
|
187 |
+
* {@inheritdoc}
|
188 |
+
*
|
189 |
+
* @see \IPLib\Range\RangeInterface::asSubnet()
|
190 |
+
*/
|
191 |
+
public function asSubnet()
|
192 |
+
{
|
193 |
+
$networkPrefixes = array(
|
194 |
+
AddressType::T_IPv4 => 32,
|
195 |
+
AddressType::T_IPv6 => 128,
|
196 |
+
);
|
197 |
+
|
198 |
+
return new Subnet($this->address, $this->address, $networkPrefixes[$this->address->getAddressType()]);
|
199 |
+
}
|
200 |
+
|
201 |
+
/**
|
202 |
+
* {@inheritdoc}
|
203 |
+
*
|
204 |
+
* @see \IPLib\Range\RangeInterface::asPattern()
|
205 |
+
*/
|
206 |
+
public function asPattern()
|
207 |
+
{
|
208 |
+
return new Pattern($this->address, $this->address, 0);
|
209 |
+
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* {@inheritdoc}
|
213 |
+
*
|
214 |
+
* @see \IPLib\Range\RangeInterface::getSubnetMask()
|
215 |
+
*/
|
216 |
+
public function getSubnetMask()
|
217 |
+
{
|
218 |
+
if ($this->getAddressType() !== AddressType::T_IPv4) {
|
219 |
+
return null;
|
220 |
+
}
|
221 |
+
|
222 |
+
return IPv4::fromBytes(array(255, 255, 255, 255));
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* {@inheritdoc}
|
227 |
+
*
|
228 |
+
* @see \IPLib\Range\RangeInterface::getReverseDNSLookupName()
|
229 |
+
*/
|
230 |
+
public function getReverseDNSLookupName()
|
231 |
+
{
|
232 |
+
return array($this->getStartAddress()->getReverseDNSLookupName());
|
233 |
+
}
|
234 |
+
|
235 |
+
/**
|
236 |
+
* {@inheritdoc}
|
237 |
+
*
|
238 |
+
* @see \IPLib\Range\RangeInterface::getSize()
|
239 |
+
*/
|
240 |
+
public function getSize()
|
241 |
+
{
|
242 |
+
return 1;
|
243 |
+
}
|
244 |
+
}
|
vendor/mlocati/ip-lib/src/Range/Subnet.php
ADDED
@@ -0,0 +1,354 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace IPLib\Range;
|
4 |
+
|
5 |
+
use IPLib\Address\AddressInterface;
|
6 |
+
use IPLib\Address\IPv4;
|
7 |
+
use IPLib\Address\Type as AddressType;
|
8 |
+
use IPLib\Factory;
|
9 |
+
use IPLib\ParseStringFlag;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Represents an address range in subnet format (eg CIDR).
|
13 |
+
*
|
14 |
+
* @example 127.0.0.1/32
|
15 |
+
* @example ::/8
|
16 |
+
*/
|
17 |
+
class Subnet extends AbstractRange
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Starting address of the range.
|
21 |
+
*
|
22 |
+
* @var \IPLib\Address\AddressInterface
|
23 |
+
*/
|
24 |
+
protected $fromAddress;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Final address of the range.
|
28 |
+
*
|
29 |
+
* @var \IPLib\Address\AddressInterface
|
30 |
+
*/
|
31 |
+
protected $toAddress;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Number of the same bits of the range.
|
35 |
+
*
|
36 |
+
* @var int
|
37 |
+
*/
|
38 |
+
protected $networkPrefix;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* The type of the range of this IP range.
|
42 |
+
*
|
43 |
+
* @var int|null
|
44 |
+
*
|
45 |
+
* @since 1.5.0
|
46 |
+
*/
|
47 |
+
protected $rangeType;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* The 6to4 address IPv6 address range.
|
51 |
+
*
|
52 |
+
* @var self|null
|
53 |
+
*/
|
54 |
+
private static $sixToFour;
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Initializes the instance.
|
58 |
+
*
|
59 |
+
* @param \IPLib\Address\AddressInterface $fromAddress
|
60 |
+
* @param \IPLib\Address\AddressInterface $toAddress
|
61 |
+
* @param int $networkPrefix
|
62 |
+
*
|
63 |
+
* @internal
|
64 |
+
*/
|
65 |
+
public function __construct(AddressInterface $fromAddress, AddressInterface $toAddress, $networkPrefix)
|
66 |
+
{
|
67 |
+
$this->fromAddress = $fromAddress;
|
68 |
+
$this->toAddress = $toAddress;
|
69 |
+
$this->networkPrefix = $networkPrefix;
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* {@inheritdoc}
|
74 |
+
*
|
75 |
+
* @see \IPLib\Range\RangeInterface::__toString()
|
76 |
+
*/
|
77 |
+
public function __toString()
|
78 |
+
{
|
79 |
+
return $this->toString();
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* @deprecated since 1.17.0: use the parseString() method instead.
|
84 |
+
* For upgrading:
|
85 |
+
* - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
|
86 |
+
*
|
87 |
+
* @param string|mixed $range
|
88 |
+
* @param bool $supportNonDecimalIPv4
|
89 |
+
*
|
90 |
+
* @return static|null
|
91 |
+
*
|
92 |
+
* @see \IPLib\Range\Subnet::parseString()
|
93 |
+
* @since 1.10.0 added the $supportNonDecimalIPv4 argument
|
94 |
+
*/
|
95 |
+
public static function fromString($range, $supportNonDecimalIPv4 = false)
|
96 |
+
{
|
97 |
+
return static::parseString($range, ParseStringFlag::MAY_INCLUDE_PORT | ParseStringFlag::MAY_INCLUDE_ZONEID | ($supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0));
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Try get the range instance starting from its string representation.
|
102 |
+
*
|
103 |
+
* @param string|mixed $range
|
104 |
+
* @param int $flags A combination or zero or more flags
|
105 |
+
*
|
106 |
+
* @return static|null
|
107 |
+
*
|
108 |
+
* @see \IPLib\ParseStringFlag
|
109 |
+
* @since 1.17.0
|
110 |
+
*/
|
111 |
+
public static function parseString($range, $flags = 0)
|
112 |
+
{
|
113 |
+
if (!is_string($range)) {
|
114 |
+
return null;
|
115 |
+
}
|
116 |
+
$parts = explode('/', $range);
|
117 |
+
if (count($parts) !== 2) {
|
118 |
+
return null;
|
119 |
+
}
|
120 |
+
$flags = (int) $flags;
|
121 |
+
if (strpos($parts[0], ':') === false && $flags & ParseStringFlag::IPV4SUBNET_MAYBE_COMPACT) {
|
122 |
+
$missingDots = 3 - substr_count($parts[0], '.');
|
123 |
+
if ($missingDots > 0) {
|
124 |
+
$parts[0] .= str_repeat('.0', $missingDots);
|
125 |
+
}
|
126 |
+
}
|
127 |
+
$address = Factory::parseAddressString($parts[0], $flags);
|
128 |
+
if ($address === null) {
|
129 |
+
return null;
|
130 |
+
}
|
131 |
+
if (!preg_match('/^[0-9]{1,9}$/', $parts[1])) {
|
132 |
+
return null;
|
133 |
+
}
|
134 |
+
$networkPrefix = (int) $parts[1];
|
135 |
+
$addressBytes = $address->getBytes();
|
136 |
+
$totalBytes = count($addressBytes);
|
137 |
+
$numDifferentBits = $totalBytes * 8 - $networkPrefix;
|
138 |
+
if ($numDifferentBits < 0) {
|
139 |
+
return null;
|
140 |
+
}
|
141 |
+
$numSameBytes = $networkPrefix >> 3;
|
142 |
+
$sameBytes = array_slice($addressBytes, 0, $numSameBytes);
|
143 |
+
$differentBytesStart = ($totalBytes === $numSameBytes) ? array() : array_fill(0, $totalBytes - $numSameBytes, 0);
|
144 |
+
$differentBytesEnd = ($totalBytes === $numSameBytes) ? array() : array_fill(0, $totalBytes - $numSameBytes, 255);
|
145 |
+
$startSameBits = $networkPrefix % 8;
|
146 |
+
if ($startSameBits !== 0) {
|
147 |
+
$varyingByte = $addressBytes[$numSameBytes];
|
148 |
+
$differentBytesStart[0] = $varyingByte & bindec(str_pad(str_repeat('1', $startSameBits), 8, '0', STR_PAD_RIGHT));
|
149 |
+
$differentBytesEnd[0] = $differentBytesStart[0] + bindec(str_repeat('1', 8 - $startSameBits));
|
150 |
+
}
|
151 |
+
|
152 |
+
return new static(
|
153 |
+
Factory::addressFromBytes(array_merge($sameBytes, $differentBytesStart)),
|
154 |
+
Factory::addressFromBytes(array_merge($sameBytes, $differentBytesEnd)),
|
155 |
+
$networkPrefix
|
156 |
+
);
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* {@inheritdoc}
|
161 |
+
*
|
162 |
+
* @see \IPLib\Range\RangeInterface::toString()
|
163 |
+
*/
|
164 |
+
public function toString($long = false)
|
165 |
+
{
|
166 |
+
return $this->fromAddress->toString($long) . '/' . $this->networkPrefix;
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* {@inheritdoc}
|
171 |
+
*
|
172 |
+
* @see \IPLib\Range\RangeInterface::getAddressType()
|
173 |
+
*/
|
174 |
+
public function getAddressType()
|
175 |
+
{
|
176 |
+
return $this->fromAddress->getAddressType();
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* {@inheritdoc}
|
181 |
+
*
|
182 |
+
* @see \IPLib\Range\RangeInterface::getStartAddress()
|
183 |
+
*/
|
184 |
+
public function getStartAddress()
|
185 |
+
{
|
186 |
+
return $this->fromAddress;
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* {@inheritdoc}
|
191 |
+
*
|
192 |
+
* @see \IPLib\Range\RangeInterface::getEndAddress()
|
193 |
+
*/
|
194 |
+
public function getEndAddress()
|
195 |
+
{
|
196 |
+
return $this->toAddress;
|
197 |
+
}
|
198 |
+
|
199 |
+
/**
|
200 |
+
* {@inheritdoc}
|
201 |
+
*
|
202 |
+
* @see \IPLib\Range\RangeInterface::getComparableStartString()
|
203 |
+
*/
|
204 |
+
public function getComparableStartString()
|
205 |
+
{
|
206 |
+
return $this->fromAddress->getComparableString();
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* {@inheritdoc}
|
211 |
+
*
|
212 |
+
* @see \IPLib\Range\RangeInterface::getComparableEndString()
|
213 |
+
*/
|
214 |
+
public function getComparableEndString()
|
215 |
+
{
|
216 |
+
return $this->toAddress->getComparableString();
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* {@inheritdoc}
|
221 |
+
*
|
222 |
+
* @see \IPLib\Range\RangeInterface::asSubnet()
|
223 |
+
*/
|
224 |
+
public function asSubnet()
|
225 |
+
{
|
226 |
+
return $this;
|
227 |
+
}
|
228 |
+
|
229 |
+
/**
|
230 |
+
* {@inheritdoc}
|
231 |
+
*
|
232 |
+
* @see \IPLib\Range\RangeInterface::asPattern()
|
233 |
+
* @since 1.8.0
|
234 |
+
*/
|
235 |
+
public function asPattern()
|
236 |
+
{
|
237 |
+
$address = $this->getStartAddress();
|
238 |
+
$networkPrefix = $this->getNetworkPrefix();
|
239 |
+
switch ($address->getAddressType()) {
|
240 |
+
case AddressType::T_IPv4:
|
241 |
+
return $networkPrefix % 8 === 0 ? new Pattern($address, $address, 4 - $networkPrefix / 8) : null;
|
242 |
+
case AddressType::T_IPv6:
|
243 |
+
return $networkPrefix % 16 === 0 ? new Pattern($address, $address, 8 - $networkPrefix / 16) : null;
|
244 |
+
}
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* Get the 6to4 address IPv6 address range.
|
249 |
+
*
|
250 |
+
* @return self
|
251 |
+
*
|
252 |
+
* @since 1.5.0
|
253 |
+
*/
|
254 |
+
public static function get6to4()
|
255 |
+
{
|
256 |
+
if (self::$sixToFour === null) {
|
257 |
+
self::$sixToFour = self::parseString('2002::/16');
|
258 |
+
}
|
259 |
+
|
260 |
+
return self::$sixToFour;
|
261 |
+
}
|
262 |
+
|
263 |
+
/**
|
264 |
+
* Get subnet prefix.
|
265 |
+
*
|
266 |
+
* @return int
|
267 |
+
*
|
268 |
+
* @since 1.7.0
|
269 |
+
*/
|
270 |
+
public function getNetworkPrefix()
|
271 |
+
{
|
272 |
+
return $this->networkPrefix;
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* {@inheritdoc}
|
277 |
+
*
|
278 |
+
* @see \IPLib\Range\RangeInterface::getSubnetMask()
|
279 |
+
*/
|
280 |
+
public function getSubnetMask()
|
281 |
+
{
|
282 |
+
if ($this->getAddressType() !== AddressType::T_IPv4) {
|
283 |
+
return null;
|
284 |
+
}
|
285 |
+
$bytes = array();
|
286 |
+
$prefix = $this->getNetworkPrefix();
|
287 |
+
while ($prefix >= 8) {
|
288 |
+
$bytes[] = 255;
|
289 |
+
$prefix -= 8;
|
290 |
+
}
|
291 |
+
if ($prefix !== 0) {
|
292 |
+
$bytes[] = bindec(str_pad(str_repeat('1', $prefix), 8, '0'));
|
293 |
+
}
|
294 |
+
$bytes = array_pad($bytes, 4, 0);
|
295 |
+
|
296 |
+
return IPv4::fromBytes($bytes);
|
297 |
+
}
|
298 |
+
|
299 |
+
/**
|
300 |
+
* {@inheritdoc}
|
301 |
+
*
|
302 |
+
* @see \IPLib\Range\RangeInterface::getReverseDNSLookupName()
|
303 |
+
*/
|
304 |
+
public function getReverseDNSLookupName()
|
305 |
+
{
|
306 |
+
switch ($this->getAddressType()) {
|
307 |
+
case AddressType::T_IPv4:
|
308 |
+
$unitSize = 8; // bytes
|
309 |
+
$maxUnits = 4;
|
310 |
+
$isHex = false;
|
311 |
+
$rxUnit = '\d+';
|
312 |
+
break;
|
313 |
+
case AddressType::T_IPv6:
|
314 |
+
$unitSize = 4; // nibbles
|
315 |
+
$maxUnits = 32;
|
316 |
+
$isHex = true;
|
317 |
+
$rxUnit = '[0-9A-Fa-f]';
|
318 |
+
break;
|
319 |
+
}
|
320 |
+
$totBits = $unitSize * $maxUnits;
|
321 |
+
$prefixUnits = (int) ($this->networkPrefix / $unitSize);
|
322 |
+
$extraBits = ($totBits - $this->networkPrefix) % $unitSize;
|
323 |
+
if ($extraBits !== 0) {
|
324 |
+
$prefixUnits += 1;
|
325 |
+
}
|
326 |
+
$numVariants = 1 << $extraBits;
|
327 |
+
$result = array();
|
328 |
+
$unitsToRemove = $maxUnits - $prefixUnits;
|
329 |
+
$initialPointer = preg_replace("/^(({$rxUnit})\.){{$unitsToRemove}}/", '', $this->getStartAddress()->getReverseDNSLookupName());
|
330 |
+
$chunks = explode('.', $initialPointer, 2);
|
331 |
+
for ($index = 0; $index < $numVariants; $index++) {
|
332 |
+
if ($index !== 0) {
|
333 |
+
$chunks[0] = $isHex ? dechex(1 + hexdec($chunks[0])) : (string) (1 + (int) $chunks[0]);
|
334 |
+
}
|
335 |
+
$result[] = implode('.', $chunks);
|
336 |
+
}
|
337 |
+
|
338 |
+
return $result;
|
339 |
+
}
|
340 |
+
|
341 |
+
/**
|
342 |
+
* {@inheritdoc}
|
343 |
+
*
|
344 |
+
* @see \IPLib\Range\RangeInterface::getSize()
|
345 |
+
*/
|
346 |
+
public function getSize()
|
347 |
+
{
|
348 |
+
$fromAddress = $this->fromAddress;
|
349 |
+
$maxPrefix = $fromAddress::getNumberOfBits();
|
350 |
+
$prefix = $this->getNetworkPrefix();
|
351 |
+
|
352 |
+
return pow(2, ($maxPrefix - $prefix));
|
353 |
+
}
|
354 |
+
}
|
vendor/mlocati/ip-lib/src/Range/Type.php
ADDED
@@ -0,0 +1,152 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace IPLib\Range;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Types of IP address classes.
|
7 |
+
*/
|
8 |
+
class Type
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Unspecified/unknown address.
|
12 |
+
*
|
13 |
+
* @var int
|
14 |
+
*/
|
15 |
+
const T_UNSPECIFIED = 1;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Reserved/internal use only.
|
19 |
+
*
|
20 |
+
* @var int
|
21 |
+
*/
|
22 |
+
const T_RESERVED = 2;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Refer to source hosts on "this" network.
|
26 |
+
*
|
27 |
+
* @var int
|
28 |
+
*/
|
29 |
+
const T_THISNETWORK = 3;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Internet host loopback address.
|
33 |
+
*
|
34 |
+
* @var int
|
35 |
+
*/
|
36 |
+
const T_LOOPBACK = 4;
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Relay anycast address.
|
40 |
+
*
|
41 |
+
* @var int
|
42 |
+
*/
|
43 |
+
const T_ANYCASTRELAY = 5;
|
44 |
+
|
45 |
+
/**
|
46 |
+
* "Limited broadcast" destination address.
|
47 |
+
*
|
48 |
+
* @var int
|
49 |
+
*/
|
50 |
+
const T_LIMITEDBROADCAST = 6;
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Multicast address assignments - Indentify a group of interfaces.
|
54 |
+
*
|
55 |
+
* @var int
|
56 |
+
*/
|
57 |
+
const T_MULTICAST = 7;
|
58 |
+
|
59 |
+
/**
|
60 |
+
* "Link local" address, allocated for communication between hosts on a single link.
|
61 |
+
*
|
62 |
+
* @var int
|
63 |
+
*/
|
64 |
+
const T_LINKLOCAL = 8;
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Link local unicast / Linked-scoped unicast.
|
68 |
+
*
|
69 |
+
* @var int
|
70 |
+
*/
|
71 |
+
const T_LINKLOCAL_UNICAST = 9;
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Discard-Only address.
|
75 |
+
*
|
76 |
+
* @var int
|
77 |
+
*/
|
78 |
+
const T_DISCARDONLY = 10;
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Discard address.
|
82 |
+
*
|
83 |
+
* @var int
|
84 |
+
*/
|
85 |
+
const T_DISCARD = 11;
|
86 |
+
|
87 |
+
/**
|
88 |
+
* For use in private networks.
|
89 |
+
*
|
90 |
+
* @var int
|
91 |
+
*/
|
92 |
+
const T_PRIVATENETWORK = 12;
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Public address.
|
96 |
+
*
|
97 |
+
* @var int
|
98 |
+
*/
|
99 |
+
const T_PUBLIC = 13;
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Carrier-grade NAT address.
|
103 |
+
*
|
104 |
+
* @var int
|
105 |
+
*
|
106 |
+
* @since 1.10.0
|
107 |
+
*/
|
108 |
+
const T_CGNAT = 14;
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Get the name of a type.
|
112 |
+
*
|
113 |
+
* @param int $type
|
114 |
+
*
|
115 |
+
* @return string
|
116 |
+
*/
|
117 |
+
public static function getName($type)
|
118 |
+
{
|
119 |
+
switch ($type) {
|
120 |
+
case static::T_UNSPECIFIED:
|
121 |
+
return 'Unspecified/unknown address';
|
122 |
+
case static::T_RESERVED:
|
123 |
+
return 'Reserved/internal use only';
|
124 |
+
case static::T_THISNETWORK:
|
125 |
+
return 'Refer to source hosts on "this" network';
|
126 |
+
case static::T_LOOPBACK:
|
127 |
+
return 'Internet host loopback address';
|
128 |
+
case static::T_ANYCASTRELAY:
|
129 |
+
return 'Relay anycast address';
|
130 |
+
case static::T_LIMITEDBROADCAST:
|
131 |
+
return '"Limited broadcast" destination address';
|
132 |
+
case static::T_MULTICAST:
|
133 |
+
return 'Multicast address assignments - Indentify a group of interfaces';
|
134 |
+
case static::T_LINKLOCAL:
|
135 |
+
return '"Link local" address, allocated for communication between hosts on a single link';
|
136 |
+
case static::T_LINKLOCAL_UNICAST:
|
137 |
+
return 'Link local unicast / Linked-scoped unicast';
|
138 |
+
case static::T_DISCARDONLY:
|
139 |
+
return 'Discard only';
|
140 |
+
case static::T_DISCARD:
|
141 |
+
return 'Discard';
|
142 |
+
case static::T_PRIVATENETWORK:
|
143 |
+
return 'For use in private networks';
|
144 |
+
case static::T_PUBLIC:
|
145 |
+
return 'Public address';
|
146 |
+
case static::T_CGNAT:
|
147 |
+
return 'Carrier-grade NAT';
|
148 |
+
default:
|
149 |
+
return $type === null ? 'Unknown type' : sprintf('Unknown type (%s)', $type);
|
150 |
+
}
|
151 |
+
}
|
152 |
+
}
|
vendor/mlocati/ip-lib/src/Service/BinaryMath.php
ADDED
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace IPLib\Service;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Helper class to work with unsigned binary integers.
|
7 |
+
*
|
8 |
+
* @internal
|
9 |
+
*/
|
10 |
+
class BinaryMath
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Trim the leading zeroes from a non-negative integer represented in binary form.
|
14 |
+
*
|
15 |
+
* @param string $value
|
16 |
+
*
|
17 |
+
* @return string
|
18 |
+
*/
|
19 |
+
public function reduce($value)
|
20 |
+
{
|
21 |
+
$value = ltrim($value, '0');
|
22 |
+
|
23 |
+
return $value === '' ? '0' : $value;
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Compare two non-negative integers represented in binary form.
|
28 |
+
*
|
29 |
+
* @param string $a
|
30 |
+
* @param string $b
|
31 |
+
*
|
32 |
+
* @return int 1 if $a is greater than $b, -1 if $b is greater than $b, 0 if they are the same
|
33 |
+
*/
|
34 |
+
public function compare($a, $b)
|
35 |
+
{
|
36 |
+
list($a, $b) = $this->toSameLength($a, $b);
|
37 |
+
|
38 |
+
return $a < $b ? -1 : ($a > $b ? 1 : 0);
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Add 1 to a non-negative integer represented in binary form.
|
43 |
+
*
|
44 |
+
* @param string $value
|
45 |
+
*
|
46 |
+
* @return string
|
47 |
+
*/
|
48 |
+
public function increment($value)
|
49 |
+
{
|
50 |
+
$lastZeroIndex = strrpos($value, '0');
|
51 |
+
if ($lastZeroIndex === false) {
|
52 |
+
return '1' . str_repeat('0', strlen($value));
|
53 |
+
}
|
54 |
+
|
55 |
+
return ltrim(substr($value, 0, $lastZeroIndex), '0') . '1' . str_repeat('0', strlen($value) - $lastZeroIndex - 1);
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Calculate the bitwise AND of two non-negative integers represented in binary form.
|
60 |
+
*
|
61 |
+
* @param string $operand1
|
62 |
+
* @param string $operand2
|
63 |
+
*
|
64 |
+
* @return string
|
65 |
+
*/
|
66 |
+
public function andX($operand1, $operand2)
|
67 |
+
{
|
68 |
+
$operand1 = $this->reduce($operand1);
|
69 |
+
$operand2 = $this->reduce($operand2);
|
70 |
+
$numBits = min(strlen($operand1), strlen($operand2));
|
71 |
+
$operand1 = substr(str_pad($operand1, $numBits, '0', STR_PAD_LEFT), -$numBits);
|
72 |
+
$operand2 = substr(str_pad($operand2, $numBits, '0', STR_PAD_LEFT), -$numBits);
|
73 |
+
$result = '';
|
74 |
+
for ($index = 0; $index < $numBits; $index++) {
|
75 |
+
$result .= $operand1[$index] === '1' && $operand2[$index] === '1' ? '1' : '0';
|
76 |
+
}
|
77 |
+
|
78 |
+
return $this->reduce($result);
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Calculate the bitwise OR of two non-negative integers represented in binary form.
|
83 |
+
*
|
84 |
+
* @param string $operand1
|
85 |
+
* @param string $operand2
|
86 |
+
*
|
87 |
+
* @return string
|
88 |
+
*/
|
89 |
+
public function orX($operand1, $operand2)
|
90 |
+
{
|
91 |
+
list($operand1, $operand2, $numBits) = $this->toSameLength($operand1, $operand2);
|
92 |
+
$result = '';
|
93 |
+
for ($index = 0; $index < $numBits; $index++) {
|
94 |
+
$result .= $operand1[$index] === '1' || $operand2[$index] === '1' ? '1' : '0';
|
95 |
+
}
|
96 |
+
|
97 |
+
return $result;
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Zero-padding of two non-negative integers represented in binary form, so that they have the same length.
|
102 |
+
*
|
103 |
+
* @param string $num1
|
104 |
+
* @param string $num2
|
105 |
+
*
|
106 |
+
* @return string[],int[] The first array element is $num1 (padded), the first array element is $num2 (padded), the third array element is the number of bits
|
107 |
+
*/
|
108 |
+
private function toSameLength($num1, $num2)
|
109 |
+
{
|
110 |
+
$num1 = $this->reduce($num1);
|
111 |
+
$num2 = $this->reduce($num2);
|
112 |
+
$numBits = max(strlen($num1), strlen($num2));
|
113 |
+
|
114 |
+
return array(
|
115 |
+
str_pad($num1, $numBits, '0', STR_PAD_LEFT),
|
116 |
+
str_pad($num2, $numBits, '0', STR_PAD_LEFT),
|
117 |
+
$numBits,
|
118 |
+
);
|
119 |
+
}
|
120 |
+
}
|
vendor/mlocati/ip-lib/src/Service/RangesFromBoundaryCalculator.php
ADDED
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace IPLib\Service;
|
4 |
+
|
5 |
+
use IPLib\Address\AddressInterface;
|
6 |
+
use IPLib\Factory;
|
7 |
+
use IPLib\Range\Subnet;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Helper class to calculate the subnets describing all (and only all) the addresses between two boundaries.
|
11 |
+
*
|
12 |
+
* @internal
|
13 |
+
*/
|
14 |
+
class RangesFromBoundaryCalculator
|
15 |
+
{
|
16 |
+
/**
|
17 |
+
* The BinaryMath instance to be used to perform bitwise operations.
|
18 |
+
*
|
19 |
+
* @var \IPLib\Service\BinaryMath
|
20 |
+
*/
|
21 |
+
private $math;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* The number of bits used to represent addresses.
|
25 |
+
*
|
26 |
+
* @var int
|
27 |
+
*
|
28 |
+
* @example 32 for IPv4, 128 for IPv6
|
29 |
+
*/
|
30 |
+
private $numBits;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* The bit masks for every bit index.
|
34 |
+
*
|
35 |
+
* @var string[]
|
36 |
+
*/
|
37 |
+
private $masks;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* The bit unmasks for every bit index.
|
41 |
+
*
|
42 |
+
* @var string[]
|
43 |
+
*/
|
44 |
+
private $unmasks;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Initializes the instance.
|
48 |
+
*
|
49 |
+
* @param int $numBits the number of bits used to represent addresses (32 for IPv4, 128 for IPv6)
|
50 |
+
*/
|
51 |
+
public function __construct($numBits)
|
52 |
+
{
|
53 |
+
$this->math = new BinaryMath();
|
54 |
+
$this->setNumBits($numBits);
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Calculate the subnets describing all (and only all) the addresses between two boundaries.
|
59 |
+
*
|
60 |
+
* @param \IPLib\Address\AddressInterface $from
|
61 |
+
* @param \IPLib\Address\AddressInterface $to
|
62 |
+
*
|
63 |
+
* @return \IPLib\Range\Subnet[]|null return NULL if the two addresses have an invalid number of bits (that is, different from the one passed to the constructor of this class)
|
64 |
+
*/
|
65 |
+
public function getRanges(AddressInterface $from, AddressInterface $to)
|
66 |
+
{
|
67 |
+
if ($from->getNumberOfBits() !== $this->numBits || $to->getNumberOfBits() !== $this->numBits) {
|
68 |
+
return null;
|
69 |
+
}
|
70 |
+
if ($from->getComparableString() > $to->getComparableString()) {
|
71 |
+
list($from, $to) = array($to, $from);
|
72 |
+
}
|
73 |
+
$result = array();
|
74 |
+
$this->calculate($this->math->reduce($from->getBits()), $this->math->reduce($to->getBits()), $this->numBits, $result);
|
75 |
+
|
76 |
+
return $result;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Set the number of bits used to represent addresses (32 for IPv4, 128 for IPv6).
|
81 |
+
*
|
82 |
+
* @param int $numBits
|
83 |
+
*/
|
84 |
+
private function setNumBits($numBits)
|
85 |
+
{
|
86 |
+
$numBits = (int) $numBits;
|
87 |
+
$masks = array();
|
88 |
+
$unmasks = array();
|
89 |
+
for ($bit = 0; $bit < $numBits; $bit++) {
|
90 |
+
$masks[$bit] = str_repeat('1', $numBits - $bit) . str_repeat('0', $bit);
|
91 |
+
$unmasks[$bit] = $bit === 0 ? '0' : str_repeat('1', $bit);
|
92 |
+
}
|
93 |
+
$this->numBits = $numBits;
|
94 |
+
$this->masks = $masks;
|
95 |
+
$this->unmasks = $unmasks;
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Calculate the subnets.
|
100 |
+
*
|
101 |
+
* @param string $start the start address (represented in reduced bit form)
|
102 |
+
* @param string $end the end address (represented in reduced bit form)
|
103 |
+
* @param int $position the number of bits in the mask we are comparing at this cycle
|
104 |
+
* @param \IPLib\Range\Subnet[] $result found ranges will be added to this variable
|
105 |
+
*/
|
106 |
+
private function calculate($start, $end, $position, array &$result)
|
107 |
+
{
|
108 |
+
if ($start === $end) {
|
109 |
+
$result[] = $this->subnetFromBits($start, $this->numBits);
|
110 |
+
|
111 |
+
return;
|
112 |
+
}
|
113 |
+
for ($index = $position - 1; $index >= 0; $index--) {
|
114 |
+
$startMasked = $this->math->andX($start, $this->masks[$index]);
|
115 |
+
$endMasked = $this->math->andX($end, $this->masks[$index]);
|
116 |
+
if ($startMasked !== $endMasked) {
|
117 |
+
$position = $index;
|
118 |
+
break;
|
119 |
+
}
|
120 |
+
}
|
121 |
+
if ($startMasked === $start && $this->math->andX($this->math->increment($end), $this->unmasks[$position]) === '0') {
|
122 |
+
$result[] = $this->subnetFromBits($start, $this->numBits - 1 - $position);
|
123 |
+
|
124 |
+
return;
|
125 |
+
}
|
126 |
+
$middleAddress = $this->math->orX($start, $this->unmasks[$position]);
|
127 |
+
$this->calculate($start, $middleAddress, $position, $result);
|
128 |
+
$this->calculate($this->math->increment($middleAddress), $end, $position, $result);
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Create an address instance starting from its bits.
|
133 |
+
*
|
134 |
+
* @param string $bits the bits of the address (represented in reduced bit form)
|
135 |
+
*
|
136 |
+
* @return \IPLib\Address\AddressInterface
|
137 |
+
*/
|
138 |
+
private function addressFromBits($bits)
|
139 |
+
{
|
140 |
+
$bits = str_pad($bits, $this->numBits, '0', STR_PAD_LEFT);
|
141 |
+
$bytes = array();
|
142 |
+
foreach (explode("\n", trim(chunk_split($bits, 8, "\n"))) as $byteBits) {
|
143 |
+
$bytes[] = bindec($byteBits);
|
144 |
+
}
|
145 |
+
|
146 |
+
return Factory::addressFromBytes($bytes);
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Create an range instance starting from the bits if the address and the length of the network prefix.
|
151 |
+
*
|
152 |
+
* @param string $bits the bits of the address (represented in reduced bit form)
|
153 |
+
* @param int $networkPrefix the length of the network prefix
|
154 |
+
*
|
155 |
+
* @return \IPLib\Range\Subnet
|
156 |
+
*/
|
157 |
+
private function subnetFromBits($bits, $networkPrefix)
|
158 |
+
{
|
159 |
+
$startAddress = $this->addressFromBits($bits);
|
160 |
+
$numOnes = $this->numBits - $networkPrefix;
|
161 |
+
if ($numOnes === 0) {
|
162 |
+
return new Subnet($startAddress, $startAddress, $networkPrefix);
|
163 |
+
}
|
164 |
+
$endAddress = $this->addressFromBits(substr($bits, 0, -$numOnes) . str_repeat('1', $numOnes));
|
165 |
+
|
166 |
+
return new Subnet($startAddress, $endAddress, $networkPrefix);
|
167 |
+
}
|
168 |
+
}
|
vendor/mlocati/ip-lib/src/Service/UnsignedIntegerMath.php
ADDED
@@ -0,0 +1,171 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace IPLib\Service;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Helper class to work with unsigned integers.
|
7 |
+
*
|
8 |
+
* @internal
|
9 |
+
*/
|
10 |
+
class UnsignedIntegerMath
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Convert a string containing a decimal, octal or hexadecimal number into its bytes.
|
14 |
+
*
|
15 |
+
* @param string $value
|
16 |
+
* @param int $numBytes the wanted number of bytes
|
17 |
+
* @param bool $onlyDecimal Only parse decimal numbers
|
18 |
+
*
|
19 |
+
* @return int[]|null
|
20 |
+
*/
|
21 |
+
public function getBytes($value, $numBytes, $onlyDecimal = false)
|
22 |
+
{
|
23 |
+
$m = null;
|
24 |
+
if ($onlyDecimal) {
|
25 |
+
if (preg_match('/^0*(\d+)$/', $value, $m)) {
|
26 |
+
return $this->getBytesFromDecimal($m[1], $numBytes);
|
27 |
+
}
|
28 |
+
} else {
|
29 |
+
if (preg_match('/^0[Xx]0*([0-9A-Fa-f]+)$/', $value, $m)) {
|
30 |
+
return $this->getBytesFromHexadecimal($m[1], $numBytes);
|
31 |
+
}
|
32 |
+
if (preg_match('/^0+([0-7]*)$/', $value, $m)) {
|
33 |
+
return $this->getBytesFromOctal($m[1], $numBytes);
|
34 |
+
}
|
35 |
+
if (preg_match('/^[1-9][0-9]*$/', $value)) {
|
36 |
+
return $this->getBytesFromDecimal($value, $numBytes);
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
// Not a valid number
|
41 |
+
return null;
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @return int
|
46 |
+
*/
|
47 |
+
protected function getMaxSignedInt()
|
48 |
+
{
|
49 |
+
return PHP_INT_MAX;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* @param string $value never zero-length, never extra leading zeroes
|
54 |
+
* @param int $numBytes
|
55 |
+
*
|
56 |
+
* @return int[]|null
|
57 |
+
*/
|
58 |
+
private function getBytesFromBits($value, $numBytes)
|
59 |
+
{
|
60 |
+
$valueLength = strlen($value);
|
61 |
+
if ($valueLength > $numBytes << 3) {
|
62 |
+
// overflow
|
63 |
+
return null;
|
64 |
+
}
|
65 |
+
$remainderBits = $valueLength % 8;
|
66 |
+
if ($remainderBits !== 0) {
|
67 |
+
$value = str_pad($value, $valueLength + 8 - $remainderBits, '0', STR_PAD_LEFT);
|
68 |
+
}
|
69 |
+
$bytes = array_map('bindec', str_split($value, 8));
|
70 |
+
|
71 |
+
return array_pad($bytes, -$numBytes, 0);
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* @param string $value may be zero-length, never extra leading zeroes
|
76 |
+
* @param int $numBytes
|
77 |
+
*
|
78 |
+
* @return int[]|null
|
79 |
+
*/
|
80 |
+
private function getBytesFromOctal($value, $numBytes)
|
81 |
+
{
|
82 |
+
if ($value === '') {
|
83 |
+
return array_fill(0, $numBytes, 0);
|
84 |
+
}
|
85 |
+
$bits = implode(
|
86 |
+
'',
|
87 |
+
array_map(
|
88 |
+
function ($octalDigit) {
|
89 |
+
return str_pad(decbin(octdec($octalDigit)), 3, '0', STR_PAD_LEFT);
|
90 |
+
},
|
91 |
+
str_split($value, 1)
|
92 |
+
)
|
93 |
+
);
|
94 |
+
$bits = ltrim($bits, '0');
|
95 |
+
|
96 |
+
return $bits === '' ? array_fill(0, $numBytes, 0) : static::getBytesFromBits($bits, $numBytes);
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* @param string $value never zero-length, never extra leading zeroes
|
101 |
+
* @param int $numBytes
|
102 |
+
*
|
103 |
+
* @return int[]|null
|
104 |
+
*/
|
105 |
+
private function getBytesFromDecimal($value, $numBytes)
|
106 |
+
{
|
107 |
+
$valueLength = strlen($value);
|
108 |
+
$maxSignedIntLength = strlen((string) $this->getMaxSignedInt());
|
109 |
+
if ($valueLength < $maxSignedIntLength) {
|
110 |
+
return $this->getBytesFromBits(decbin((int) $value), $numBytes);
|
111 |
+
}
|
112 |
+
// Divide by two, so that we have 1 less bit
|
113 |
+
$carry = 0;
|
114 |
+
$halfValue = ltrim(
|
115 |
+
implode(
|
116 |
+
'',
|
117 |
+
array_map(
|
118 |
+
function ($digit) use (&$carry) {
|
119 |
+
$number = $carry + (int) $digit;
|
120 |
+
$carry = ($number % 2) * 10;
|
121 |
+
|
122 |
+
return (string) $number >> 1;
|
123 |
+
},
|
124 |
+
str_split($value, 1)
|
125 |
+
)
|
126 |
+
),
|
127 |
+
'0'
|
128 |
+
);
|
129 |
+
$halfValueBytes = $this->getBytesFromDecimal($halfValue, $numBytes);
|
130 |
+
if ($halfValueBytes === null) {
|
131 |
+
return null;
|
132 |
+
}
|
133 |
+
$carry = $carry === 0 ? 0 : 1;
|
134 |
+
$result = array_fill(0, $numBytes, 0);
|
135 |
+
for ($index = $numBytes - 1; $index >= 0; $index--) {
|
136 |
+
$byte = $carry + ($halfValueBytes[$index] << 1);
|
137 |
+
if ($byte <= 0xFF) {
|
138 |
+
$carry = 0;
|
139 |
+
} else {
|
140 |
+
$carry = ($byte & ~0xFF) >> 8;
|
141 |
+
$byte -= 0x100;
|
142 |
+
}
|
143 |
+
$result[$index] = $byte;
|
144 |
+
}
|
145 |
+
if ($carry !== 0) {
|
146 |
+
// Overflow
|
147 |
+
return null;
|
148 |
+
}
|
149 |
+
|
150 |
+
return $result;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* @param string $value never zero-length, never extra leading zeroes
|
155 |
+
* @param int $numBytes
|
156 |
+
*
|
157 |
+
* @return int[]|null
|
158 |
+
*/
|
159 |
+
private function getBytesFromHexadecimal($value, $numBytes)
|
160 |
+
{
|
161 |
+
$valueLength = strlen($value);
|
162 |
+
if ($valueLength > $numBytes << 1) {
|
163 |
+
// overflow
|
164 |
+
return null;
|
165 |
+
}
|
166 |
+
$value = str_pad($value, $valueLength + $valueLength % 2, '0', STR_PAD_LEFT);
|
167 |
+
$bytes = array_map('hexdec', str_split($value, 2));
|
168 |
+
|
169 |
+
return array_pad($bytes, -$numBytes, 0);
|
170 |
+
}
|
171 |
+
}
|
webpack.config.js
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' );
|
2 |
+
const defaultConfig = require( '@wordpress/scripts/config/webpack.config' );
|
3 |
+
const path = require( 'path' );
|
4 |
+
|
5 |
+
module.exports = {
|
6 |
+
...defaultConfig,
|
7 |
+
entry: {
|
8 |
+
...defaultConfig.entry,
|
9 |
+
admin: './assets/js/src/admin.js',
|
10 |
+
settings: './assets/js/src/settings.js',
|
11 |
+
},
|
12 |
+
output: {
|
13 |
+
path: path.resolve( __dirname, 'assets/js/build' ),
|
14 |
+
filename: '[name].min.js',
|
15 |
+
},
|
16 |
+
plugins: [
|
17 |
+
...defaultConfig.plugins,
|
18 |
+
new DependencyExtractionWebpackPlugin( {
|
19 |
+
requestToExternal( request ) {
|
20 |
+
if ( 'jquery-effects-shake' === request ) {
|
21 |
+
return 'jquery-effects-shake';
|
22 |
+
}
|
23 |
+
|
24 |
+
if ( 'jquery-ui-dialog' === request ) {
|
25 |
+
return 'jquery-ui-dialog';
|
26 |
+
}
|
27 |
+
},
|
28 |
+
} ),
|
29 |
+
],
|
30 |
+
};
|