Restricted Site Access - Version 7.3.4

Version Description

  • 2022-11-01 =
  • Fixed: Fatal error due to missing vendor directory.
Download this release

Release Info

Developer 10up
Plugin Icon 128x128 Restricted Site Access
Version 7.3.4
Comparing to
See all releases

Code changes from version 7.3.3 to 7.3.4

Files changed (40) hide show
  1. .gitattributes +28 -0
  2. assets/js/build/admin.min.asset.php +1 -0
  3. assets/js/build/admin.min.js +1 -0
  4. assets/js/build/settings.min.asset.php +1 -0
  5. assets/js/build/settings.min.js +1 -0
  6. phpcs.xml +0 -42
  7. phpunit.xml +28 -0
  8. readme.txt +4 -1
  9. restricted_site_access.php +2 -2
  10. vendor/autoload.php +25 -0
  11. vendor/composer/ClassLoader.php +572 -0
  12. vendor/composer/InstalledVersions.php +352 -0
  13. vendor/composer/LICENSE +21 -0
  14. vendor/composer/autoload_classmap.php +10 -0
  15. vendor/composer/autoload_namespaces.php +9 -0
  16. vendor/composer/autoload_psr4.php +10 -0
  17. vendor/composer/autoload_real.php +38 -0
  18. vendor/composer/autoload_static.php +36 -0
  19. vendor/composer/installed.json +81 -0
  20. vendor/composer/installed.php +34 -0
  21. vendor/composer/platform_check.php +26 -0
  22. vendor/mlocati/ip-lib/LICENSE.txt +20 -0
  23. vendor/mlocati/ip-lib/ip-lib.php +13 -0
  24. vendor/mlocati/ip-lib/src/Address/AddressInterface.php +156 -0
  25. vendor/mlocati/ip-lib/src/Address/AssignedRange.php +140 -0
  26. vendor/mlocati/ip-lib/src/Address/IPv4.php +515 -0
  27. vendor/mlocati/ip-lib/src/Address/IPv6.php +608 -0
  28. vendor/mlocati/ip-lib/src/Address/Type.php +44 -0
  29. vendor/mlocati/ip-lib/src/Factory.php +298 -0
  30. vendor/mlocati/ip-lib/src/ParseStringFlag.php +79 -0
  31. vendor/mlocati/ip-lib/src/Range/AbstractRange.php +125 -0
  32. vendor/mlocati/ip-lib/src/Range/Pattern.php +322 -0
  33. vendor/mlocati/ip-lib/src/Range/RangeInterface.php +160 -0
  34. vendor/mlocati/ip-lib/src/Range/Single.php +244 -0
  35. vendor/mlocati/ip-lib/src/Range/Subnet.php +354 -0
  36. vendor/mlocati/ip-lib/src/Range/Type.php +152 -0
  37. vendor/mlocati/ip-lib/src/Service/BinaryMath.php +120 -0
  38. vendor/mlocati/ip-lib/src/Service/RangesFromBoundaryCalculator.php +168 -0
  39. vendor/mlocati/ip-lib/src/Service/UnsignedIntegerMath.php +171 -0
  40. 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.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.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.2' );
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
+ };