├── .gitignore
├── .scrutinizer.yml
├── nbproject
├── project.xml
└── project.properties
├── src
└── Whitelist
│ ├── Definition
│ ├── IPv6CIDR.php
│ ├── IPv4Address.php
│ ├── IPv6Address.php
│ ├── IDefinition.php
│ ├── WildcardDomain.php
│ ├── IPAddress.php
│ ├── Definition.php
│ ├── IPv4CIDR.php
│ ├── Domain.php
│ └── IPCIDR.php
│ └── Check.php
├── composer.json
├── tests
├── Definition
│ ├── DefinitionTest.php
│ ├── IPv6CIDRTest.php
│ ├── IPv4AddressTest.php
│ ├── IPv4CIDRTest.php
│ └── DomainTest.php
└── CheckTest.php
├── phpunit.xml
├── LICENSE
├── .github
└── workflows
│ └── tests.yml
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/
2 | build/
3 | /nbproject/private/
4 | .idea
5 | composer.phar
6 | composer.lock
7 |
--------------------------------------------------------------------------------
/.scrutinizer.yml:
--------------------------------------------------------------------------------
1 | build:
2 | nodes:
3 | analysis:
4 | tests:
5 | override:
6 | - php-scrutinizer-run
7 | environment:
8 | php: 7.4
9 |
10 | checks:
11 | php: true
12 |
--------------------------------------------------------------------------------
/nbproject/project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | org.netbeans.modules.php.project
4 |
5 |
6 | php-whitelist-check
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/Whitelist/Definition/IPv6CIDR.php:
--------------------------------------------------------------------------------
1 |
9 | * @copyright Copyright © Sam Stenvall 2014-
10 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
11 | */
12 | class IPv6CIDR extends IPCIDR
13 | {
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/Whitelist/Definition/IPv4Address.php:
--------------------------------------------------------------------------------
1 |
11 | * @copyright Copyright © Sam Stenvall 2014-
12 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
13 | */
14 | class IPv4Address extends IPAddress
15 | {
16 |
17 | public function validate()
18 | {
19 | return IPv4::isValid($this->_definition);
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/Whitelist/Definition/IPv6Address.php:
--------------------------------------------------------------------------------
1 |
11 | * @copyright Copyright © Sam Stenvall 2014-
12 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
13 | */
14 | class IPv6Address extends IPAddress
15 | {
16 |
17 | public function validate()
18 | {
19 | return IPv6::isValid($this->_definition);
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jalle19/php-whitelist-check",
3 | "type": "library",
4 | "description": "Provides a simple way to check whether an address or domain is on a whitelist",
5 | "keywords": ["whitelist", "ipv4", "cidr", "ipv6"],
6 | "homepage": "https://github.com/Jalle19/php-whitelist-check",
7 | "license": "BSD-2-Clause",
8 | "require": {
9 | "php": ">=5.5.2",
10 | "jycr753/ip-utils": "^2.0.1 | ^3.0.0"
11 | },
12 | "require-dev": {
13 | "phpunit/phpunit": "^4.8"
14 | },
15 | "autoload": {
16 | "psr-0": {
17 | "Whitelist\\": "src/"
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Whitelist/Definition/IDefinition.php:
--------------------------------------------------------------------------------
1 |
9 | * @copyright Copyright © Sam Stenvall 2014-
10 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
11 | */
12 | interface IDefinition
13 | {
14 | /**
15 | * Validates the definition and returns false if the definition is
16 | * invalid
17 | * @return boolean
18 | */
19 | public function validate();
20 |
21 | /**
22 | * Returns true if the value matches the definition
23 | *
24 | * @param string $value
25 | *
26 | * @return boolean
27 | */
28 | public function match($value);
29 | }
30 |
--------------------------------------------------------------------------------
/src/Whitelist/Definition/WildcardDomain.php:
--------------------------------------------------------------------------------
1 |
9 | * @copyright Copyright © Sam Stenvall 2014-
10 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
11 | */
12 | class WildcardDomain extends Definition
13 | {
14 |
15 | public function validate()
16 | {
17 | return true;
18 | }
19 |
20 | public function match($value)
21 | {
22 | // Remove the wildcard part and check if it matches the end of $value
23 | $domain = substr($this->_definition, 1);
24 |
25 | return substr($value, -strlen($domain)) === $domain;
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/Whitelist/Definition/IPAddress.php:
--------------------------------------------------------------------------------
1 |
12 | * @copyright Copyright © Sam Stenvall 2014-
13 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
14 | */
15 | abstract class IPAddress extends Definition
16 | {
17 |
18 | public function match($value)
19 | {
20 | try {
21 | $address = Factory::getAddress($this->_definition);
22 | $otherAddress = Factory::getExpression($value);
23 |
24 | return $address->matches($otherAddress);
25 | } catch (Exception $e) {
26 | unset($e);
27 |
28 | return false;
29 | }
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/tests/Definition/DefinitionTest.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright Copyright © Sam Stenvall 2014-
11 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
12 | */
13 | abstract class DefinitionTest extends \PHPUnit_Framework_TestCase
14 | {
15 |
16 | /**
17 | * @var IDefinition the definition class
18 | */
19 | protected $_definition;
20 |
21 | /**
22 | * Should test for exception when the constructor is called with an
23 | * empty string
24 | */
25 | abstract public function testEmptyDefinition();
26 |
27 | /**
28 | * Should test for exception when constructor is called with an invalid
29 | * definition string
30 | */
31 | abstract public function testValidate();
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/tests/Definition/IPv6CIDRTest.php:
--------------------------------------------------------------------------------
1 |
7 | * @copyright Copyright © Sam Stenvall 2016-
8 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
9 | */
10 | class IPv6CIDRTest extends DefinitionTest
11 | {
12 |
13 |
14 | /**
15 | * @expectedException InvalidArgumentException
16 | */
17 | public function testEmptyDefinition()
18 | {
19 | new \Whitelist\Definition\IPv6CIDR('');
20 | }
21 |
22 |
23 | /**
24 | * @expectedException InvalidArgumentException
25 | */
26 | public function testValidate()
27 | {
28 | $cidr = new \Whitelist\Definition\IPv6CIDR('2001::/129');
29 |
30 | $this->assertFalse($cidr->validate());
31 | }
32 |
33 |
34 | /**
35 | *
36 | */
37 | public function testValidateTrue() {
38 | $cidr = new \Whitelist\Definition\IPv6CIDR('2001::/3');
39 |
40 | $this->assertTrue($cidr->validate());
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 |
18 | ./tests/
19 |
20 |
21 |
22 |
23 | ./src
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/Whitelist/Definition/Definition.php:
--------------------------------------------------------------------------------
1 |
11 | * @copyright Copyright © Sam Stenvall 2014-
12 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
13 | */
14 | abstract class Definition implements IDefinition
15 | {
16 |
17 | /**
18 | * @var string the actual definition
19 | */
20 | protected $_definition;
21 |
22 | /**
23 | * Class constructor. It stores the definition string and validates it.
24 | *
25 | * @param string $definition the definition
26 | *
27 | * @throws \InvalidArgumentException if the definition is invalid
28 | */
29 | public function __construct($definition)
30 | {
31 | $this->_definition = $definition;
32 |
33 | if (! $this->validate()) {
34 | throw new InvalidArgumentException('The definition "'.$this->_definition.'" is invalid');
35 | }
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/Whitelist/Definition/IPv4CIDR.php:
--------------------------------------------------------------------------------
1 |
9 | * @copyright Copyright © Marc Seiler 2015-
10 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
11 | */
12 | class IPv4CIDR extends Definition
13 | {
14 | private $regexp = "/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/([0-9]{1,2})?$/";
15 |
16 | public function validate()
17 | {
18 | return preg_match($this->regexp, $this->_definition) === 1;
19 | }
20 |
21 | public function match($value)
22 | {
23 | // Adapted from https://gist.github.com/tott/7684443
24 |
25 | list($range, $netmask) = explode('/', $this->_definition, 2);
26 | $rangeDecimal = ip2long($range);
27 | $ipDecimal = ip2long($value);
28 | $wildcardDecimal = pow(2, (32 - $netmask)) - 1;
29 | $netmaskDecimal = ~$wildcardDecimal;
30 |
31 | return (($ipDecimal & $netmaskDecimal) == ($rangeDecimal & $netmaskDecimal));
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Whitelist/Definition/Domain.php:
--------------------------------------------------------------------------------
1 |
9 | * @copyright Copyright © Sam Stenvall 2014-
10 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
11 | */
12 | class Domain extends Definition
13 | {
14 |
15 | public function validate()
16 | {
17 | // The domain name cannot be empty
18 | if (strlen($this->_definition) === 0) {
19 | return false;
20 | }
21 |
22 | // None of the parts in the domain name can contain invalid characters
23 | // or begin/end with a dash
24 | foreach (explode('.', $this->_definition) as $part) {
25 | if (! preg_match('/^[a-zA-Z0-9-\.]+$/', $part) ||
26 | substr($part, 0, 1) === '-' ||
27 | substr($part, -1) === '-') {
28 | return false;
29 | }
30 | }
31 |
32 | return true;
33 | }
34 |
35 | public function match($value)
36 | {
37 | return $this->_definition === $value;
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/tests/Definition/IPv4AddressTest.php:
--------------------------------------------------------------------------------
1 |
7 | * @copyright Copyright © Sam Stenvall 2014-
8 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
9 | */
10 | class IPv4AddressTest extends DefinitionTest
11 | {
12 |
13 | /**
14 | * @expectedException InvalidArgumentException
15 | */
16 | public function testEmptyDefinition()
17 | {
18 | $this->_definition = new \Whitelist\Definition\IPv4Address('');
19 | }
20 |
21 | /**
22 | * @expectedException InvalidArgumentException
23 | */
24 | public function testValidate()
25 | {
26 | $this->_definition = new \Whitelist\Definition\IPv4Address('not.an.ipv4.address');
27 | }
28 |
29 | /**
30 | * @dataProvider provider
31 | */
32 | public function testMatch($expected, $address)
33 | {
34 | $this->_definition = new \Whitelist\Definition\IPv4Address('192.168.1.1');
35 | $this->assertEquals($expected, $this->_definition->match($address));
36 | }
37 |
38 | public function provider()
39 | {
40 | return array(
41 | array(true, '192.168.1.1'),
42 | array(false, '192.168.1.2'),
43 | );
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014, Sam Stenvall
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without modification,
5 | are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice, this
11 | list of conditions and the following disclaimer in the documentation and/or
12 | other materials provided with the distribution.
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/src/Whitelist/Definition/IPCIDR.php:
--------------------------------------------------------------------------------
1 |
14 | * @copyright Copyright © Sam Stenvall 2014-
15 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
16 | */
17 | abstract class IPCIDR extends Definition
18 | {
19 |
20 | /**
21 | * @var ExpressionInterface
22 | */
23 | protected $_subnet;
24 |
25 | public function validate()
26 | {
27 | try {
28 | $this->_subnet = Factory::getExpression($this->_definition);
29 |
30 | // Check that we got a subnet expression and not something else
31 | if (! $this->_subnet instanceof Subnet) {
32 | return false;
33 | }
34 | } catch (Exception $e) {
35 | unset($e);
36 |
37 | return false;
38 | }
39 |
40 | return true;
41 | }
42 |
43 | public function match($value)
44 | {
45 | try {
46 | $address = Factory::getAddress($value);
47 |
48 | return $this->_subnet->matches($address);
49 | } catch (Exception $e) {
50 | unset($e);
51 |
52 | return false;
53 | }
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: Run test suite
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | test:
13 | name: Run test suite
14 | runs-on: ubuntu-latest
15 | strategy:
16 | matrix:
17 | php-version: ['5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4']
18 | steps:
19 | - uses: actions/checkout@v2
20 | - name: Setup PHP ${{ matrix.php-version }}
21 | uses: shivammathur/setup-php@v2
22 | with:
23 | php-version: ${{ matrix.php-version }}
24 | tools: composer
25 | - name: Install dependencies
26 | run: composer install
27 | - name: Run tests
28 | run: |
29 | mkdir -p build/logs
30 | vendor/bin/phpunit
31 |
32 | coverage:
33 | name: Generate test coverage
34 | runs-on: ubuntu-latest
35 | steps:
36 | - uses: actions/checkout@v2
37 | - name: Setup PHP
38 | uses: shivammathur/setup-php@v2
39 | with:
40 | php-version: 7.4
41 | tools: composer
42 | - name: Install dependencies
43 | run: composer install
44 | - name: Run tests
45 | run: |
46 | mkdir -p build/logs
47 | vendor/bin/phpunit
48 | - name: Upload coverage to Coveralls
49 | env:
50 | COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
51 | run: |
52 | composer global require php-coveralls/php-coveralls
53 | php-coveralls --coverage_clover=build/logs/clover.xml -v
54 |
--------------------------------------------------------------------------------
/tests/Definition/IPv4CIDRTest.php:
--------------------------------------------------------------------------------
1 |
7 | * @copyright Copyright © Sam Stenvall 2014-
8 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
9 | */
10 | class IPv4CIDRTest extends DefinitionTest
11 | {
12 |
13 | /**
14 | * @expectedException InvalidArgumentException
15 | */
16 | public function testEmptyDefinition()
17 | {
18 | $this->_definition = new \Whitelist\Definition\IPv4CIDR('');
19 | }
20 |
21 | /**
22 | * Test various combinations of CIDR's (valid and invalid)
23 | *
24 | * @return null
25 | */
26 | public function testValidate()
27 | {
28 | $pass = false;
29 |
30 | // Sorry have to do this instead of using @dataProvider to avoid breaking the contract.
31 | foreach ($this->cidrProvider() as $cidr) {
32 | list ($expected, $address) = $cidr;
33 | try {
34 | $this->_definition = new \Whitelist\Definition\IPv4CIDR($address);
35 | $pass = true;
36 | } catch (Exception $e) {
37 | $pass = false;
38 | }
39 | $this->assertEquals($expected, $pass);
40 | }
41 |
42 | }
43 |
44 | public function cidrProvider()
45 | {
46 | return array(
47 | array(false, '10.10.0.3'),
48 | array(false, '10.10.0.0/23445'),
49 | array(true, '10.10.0.0/16'),
50 | array(true, '0.0.0.0/0'),
51 | );
52 | }
53 |
54 | /**
55 | * @dataProvider provider
56 | */
57 | public function testMatch($expected, $address)
58 | {
59 | // testing if address matches CIDR
60 | $this->_definition = new \Whitelist\Definition\IPv4CIDR('10.10.0.0/16');
61 | $this->assertEquals($expected, $this->_definition->match($address));
62 |
63 | // testing that all of them pass zero CIDR
64 | $this->_definition = new \Whitelist\Definition\IPv4CIDR('0.0.0.0/0');
65 | $this->assertEquals(true, $this->_definition->match($address));
66 | }
67 |
68 | public function provider()
69 | {
70 | return array(
71 | array(true, '10.10.1.1'),
72 | array(true, '10.10.76.1'),
73 | array(false, '110.1.76.1'),
74 | );
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/tests/Definition/DomainTest.php:
--------------------------------------------------------------------------------
1 |
7 | * @copyright Copyright © Sam Stenvall 2014-
8 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
9 | */
10 | class DomainTest extends DefinitionTest
11 | {
12 |
13 | /**
14 | * @expectedException InvalidArgumentException
15 | */
16 | public function testEmptyDefinition()
17 | {
18 | $this->_definition = new Whitelist\Definition\Domain('');
19 | }
20 |
21 | public function testValidate()
22 | {
23 | // do nothing here
24 | }
25 |
26 | /**
27 | * @expectedException InvalidArgumentException
28 | */
29 | public function testValidateInvalidCharacters()
30 | {
31 | $this->_definition = new Whitelist\Definition\Domain('ag*');
32 | }
33 |
34 | /**
35 | * @expectedException InvalidArgumentException
36 | */
37 | public function testValidateInvalidBeginning()
38 | {
39 | $this->_definition = new Whitelist\Definition\Domain('-otherwise-valid.com');
40 | }
41 |
42 | /**
43 | * @expectedException InvalidArgumentException
44 | */
45 | public function testValidateInvalidEnd()
46 | {
47 | $this->_definition = new Whitelist\Definition\Domain('otherwise-valid-.com');
48 | }
49 |
50 | /**
51 | * @dataProvider provider
52 | */
53 | public function testMatch($expected, $definition, $value)
54 | {
55 | $this->assertEquals($expected, $definition->match($value));
56 | }
57 |
58 | public function provider()
59 | {
60 | return array(
61 | array(true, new Whitelist\Definition\WildcardDomain('*.example.com'), 'sub.example.com'),
62 | array(true, new Whitelist\Definition\WildcardDomain('*.example.com'), 'anothersub.example.com'),
63 | array(false, new Whitelist\Definition\WildcardDomain('*.example.com'), 'sub.example.net'),
64 | array(false, new Whitelist\Definition\WildcardDomain('*.example.com'), 'sub.anotherexample.com'),
65 | array(false, new Whitelist\Definition\WildcardDomain('*.example.com'), 'localhost'),
66 | array(true, new Whitelist\Definition\Domain('localhost'), 'localhost'),
67 | array(true, new Whitelist\Definition\Domain('example.com'), 'example.com'),
68 | array(false, new Whitelist\Definition\Domain('example.com'), 'sub.example.com'),
69 | array(false, new Whitelist\Definition\Domain('example.com'), 'example2.com'),
70 | );
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/Jalle19/php-whitelist-check/actions/workflows/tests.yml)
2 | [](https://coveralls.io/github/Jalle19/php-whitelist-check?branch=master)
3 | [](https://scrutinizer-ci.com/g/Jalle19/php-whitelist-check/?branch=master)
4 |
5 | php-whitelist-check
6 | ===================
7 |
8 | A modern and simple approach to validating IP addresses and domains against a whitelist. It supports both IPv4 and IPv6 addresses and CIDR subnets in addition to domain names and wild-card domains.
9 |
10 | ## Requirements
11 |
12 | * PHP 5.3 or newer
13 |
14 | ## Usage
15 |
16 | The `Check::whitelist()` method takes an array of definitions which will constitute the whitelist. The definitions can either be strings (which will be parsed to their respective objects) or objects.
17 |
18 | The `Check::check($value)` method is used to check the specified value against the current whitelist. The method will return true if the value matches any of the definitions.
19 |
20 | To create your own definition classes just extended `Whitelist\Definition\Definition` and implement `Whitelist\Definition\IDefinition`
21 |
22 | Example usage:
23 |
24 | ```php
25 | require_once("vendor/autoload.php");
26 |
27 | $checker = new Whitelist\Check();
28 |
29 | try {
30 | $checker->whitelist(array(
31 | '10.0.3.1',
32 | '10.0.0.0/16',
33 | '2001:db8:100:934b::3:1',
34 | '2001:db8:100:934b::/64',
35 | '*.example.com',
36 | 'localhost',
37 | new Whitelist\Definition\Domain('vpn.work.com'),
38 | ));
39 | }
40 | catch (InvalidArgumentException $e) {
41 | // thrown when an invalid definition is encountered
42 | }
43 |
44 | $checker->check('10.0.1.1'); // true
45 | $checker->check('10.1.1.1'); // false
46 | $checker->check('2001:db8:100:934b::210:2'); // true
47 | $checker->check('another.example.com'); // true
48 |
49 | ```
50 |
51 | ## License
52 |
53 | This library is licensed under the BSD 2-Clause License
54 |
55 | ## Credits
56 |
57 | This library depends on `xrstf/ip-utils` for the IP-related functionality. It also assumes that ip-utils's test cases are sufficient, which is why only trivial testing on these functions have been made for this library.
58 |
--------------------------------------------------------------------------------
/tests/CheckTest.php:
--------------------------------------------------------------------------------
1 |
7 | * @copyright Copyright © Sam Stenvall 2014-
8 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
9 | */
10 | class CheckTest extends PHPUnit_Framework_TestCase
11 | {
12 |
13 | /**
14 | * @var Whitelist\Check the check instance
15 | */
16 | protected $_checker;
17 |
18 | /**
19 | * Initialize the checker
20 | */
21 | protected function setUp()
22 | {
23 | $this->_checker = new \Whitelist\Check();
24 | }
25 |
26 | /**
27 | * Test invalid objects passed to whitelist()
28 | * @expectedException InvalidArgumentException
29 | */
30 | public function testInvalidDefinitionObject()
31 | {
32 | $this->_checker->whitelist(array(
33 | new stdClass(),
34 | ));
35 | }
36 |
37 | /**
38 | * Test unparsable definition passed to whitelist()
39 | * @expectedException InvalidArgumentException
40 | */
41 | public function testUnknownDefinition()
42 | {
43 | $this->_checker->whitelist(array(
44 | 'ag?', // definition class should not be able to be determined
45 | ));
46 | }
47 |
48 | /**
49 | * This test also tests that the whitelist definitions are valid, ie. they
50 | * don't throw an exception
51 | * @dataProvider matchDataprovider
52 | */
53 | public function testMatch($expected, $expression)
54 | {
55 | $this->_checker->whitelist(array(
56 | '10.2.3.1',
57 | '10.0.0.0/16',
58 | '2001:14d8:100:934b::3:1',
59 | '2001:14b8:100:934b::/64',
60 | 'test.com',
61 | 'example-domain.com',
62 | '*.another-example-domain.com',
63 | '*.example.com',
64 | new Whitelist\Definition\Domain('sub.example.com'),
65 | ));
66 |
67 | $this->assertEquals($expected, $this->_checker->check($expression));
68 | }
69 |
70 | public function matchDataProvider()
71 | {
72 | return array(
73 | array(true, '10.2.3.1'),
74 | array(false, '10.2.3.2'),
75 | array(true, '10.0.1.1'),
76 | array(false, '10.1.1.1'),
77 | array(true, '2001:14d8:100:934b::3:1'),
78 | array(false, '2001:14d8:100:934b::3:2'),
79 | array(true, '2001:14b8:100:934b::12b1:1'),
80 | array(false, '2001:14c8:100:934b::12b1:1'),
81 | array(true, 'test.com'),
82 | array(true, 'anything.goes.example.com'),
83 | array(true, 'sub.example.com'),
84 | array(false, 'test.example2.com'),
85 | array(true, 'example-domain.com'),
86 | array(true, 'test.another-example-domain.com')
87 | );
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/nbproject/project.properties:
--------------------------------------------------------------------------------
1 | auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs=false
2 | auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.indent-shift-width=4
3 | auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.spaces-per-tab=4
4 | auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=4
5 | auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=80
6 | auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-line-wrap=none
7 | auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=project
8 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.catchBracePlacement=NEW_LINE
9 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.classDeclBracePlacement=NEW_LINE
10 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.expand-tabs=false
11 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.forBracePlacement=NEW_LINE
12 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.ifBracePlacement=NEW_LINE
13 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.indent-shift-width=4
14 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.methodDeclBracePlacement=NEW_LINE
15 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.otherBracePlacement=NEW_LINE
16 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.placeCatchOnNewLine=true
17 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.placeElseOnNewLine=true
18 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.placeFinallyOnNewLine=true
19 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.placeWhileOnNewLine=true
20 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.spaceAroundStringConcatOps=false
21 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.spaces-per-tab=4
22 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.switchBracePlacement=NEW_LINE
23 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.tab-size=4
24 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.text-limit-width=80
25 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.text-line-wrap=none
26 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.useTraitBodyBracePlacement=NEW_LINE
27 | auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.whileBracePlacement=NEW_LINE
28 | code.analysis.excludes=
29 | ignore.path=
30 | include.path=\
31 | ${php.global.include.path}
32 | php.version=PHP_53
33 | source.encoding=UTF-8
34 | src.dir=.
35 | tags.asp=false
36 | tags.short=false
37 | web.root=.
38 |
--------------------------------------------------------------------------------
/src/Whitelist/Check.php:
--------------------------------------------------------------------------------
1 |
14 | * @copyright Copyright © Sam Stenvall 2014-
15 | * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
16 | */
17 | class Check
18 | {
19 |
20 | /**
21 | * @var IDefinition[] the whitelist definitions
22 | */
23 | private $_definitions = [];
24 |
25 | /**
26 | * Parses the whitelist definitions into respective objects
27 | *
28 | * @param array $whitelist list of definition strings
29 | *
30 | * @throws \InvalidArgumentException if the definition type couldn't be
31 | * determined
32 | */
33 | public function whitelist(array $whitelist)
34 | {
35 | $this->_definitions = [];
36 |
37 | foreach ($whitelist as $definition) {
38 | // Pre-configured object
39 | if (is_object($definition)) {
40 | if ($definition instanceof Definition\IDefinition) {
41 | $definitionObject = $definition;
42 | } else {
43 | throw new InvalidArgumentException('Definition objects must implement IDefinition');
44 | }
45 | } // IPv4 address
46 | elseif (preg_match('/[a-z:\/]/', $definition) === 0) {
47 | $definitionObject = new Definition\IPv4Address($definition);
48 | } // IPv4 CIDR notation
49 | elseif (preg_match('/[a-z:]/', $definition) === 0) {
50 | $definitionObject = new Definition\IPv4CIDR($definition);
51 | } // IPv6 address
52 | elseif (preg_match('/^[0-9a-f:]+$/', $definition)) {
53 | $definitionObject = new Definition\IPv6Address($definition);
54 | } // IPv6 CIDR notation
55 | elseif (preg_match('/^[0-9a-f:\/]+$/', $definition)) {
56 | $definitionObject = new Definition\IPv6CIDR($definition);
57 | } // Wildcard domain
58 | elseif (preg_match('/^\*\.[\w\.\-]+$/', $definition)) {
59 | $definitionObject = new Definition\WildcardDomain($definition);
60 | } // Domain
61 | elseif (preg_match('/^[\w\.\-]+$/', $definition)) {
62 | $definitionObject = new Definition\Domain($definition);
63 | } else {
64 | throw new InvalidArgumentException('Unable to parse definition "'.$definition.'"');
65 | }
66 |
67 | $this->_definitions[] = $definitionObject;
68 | }
69 | }
70 |
71 | /**
72 | * Checks the specified value against all configured definitions and
73 | * returns true if at least one definition considers it a match
74 | *
75 | * @param string $value the value to be checked
76 | *
77 | * @return boolean
78 | */
79 | public function check($value)
80 | {
81 | foreach ($this->_definitions as $definition) {
82 | if ($definition->match($value)) {
83 | return true;
84 | }
85 | }
86 |
87 | return false;
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------