Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Completed
Pull Request — master (#957)
by Henrique
02:45
created

Ip   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 145
Duplicated Lines 0 %

Test Coverage

Coverage 98.44%

Importance

Changes 0
Metric Value
wmc 33
dl 0
loc 145
ccs 63
cts 64
cp 0.9844
rs 9.3999
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A fillAddress() 0 4 2
B parseRangeUsingCidr() 0 19 6
A validate() 0 3 2
A __construct() 0 10 2
A createRange() 0 16 3
A parseRangeUsingWildcards() 0 6 1
A belongsToSubnet() 0 7 1
A verifyAddress() 0 7 1
A verifyNetwork() 0 14 4
C parseRange() 0 28 11
1
<?php
2
3
/*
4
 * This file is part of Respect/Validation.
5
 *
6
 * (c) Alexandre Gomes Gaigalas <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the "LICENSE.md"
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Respect\Validation\Rules;
15
16
use Respect\Validation\Exceptions\ComponentException;
17
18
class Ip extends AbstractRule
19
{
20
    public $ipOptions;
21
22
    public $range;
23
    public $networkRange;
24 46
25
    public function __construct($ipOptions = null)
26 46
    {
27 1
        if (is_int($ipOptions)) {
28
            $this->ipOptions = $ipOptions;
29 1
30
            return;
31
        }
32 45
33 37
        $this->networkRange = $this->parseRange($ipOptions);
34
        $this->range = $this->createRange();
35 45
    }
36
37 45
    /**
38 45
     * {@inheritdoc}
39 13
     */
40
    public function createRange(): ?string
41
    {
42 33
        if (!$this->networkRange) {
43
            return null;
44 33
        }
45 9
46 24
        $range = $this->networkRange;
47 12
        $message = $range['min'];
48 12
49 9
        if (isset($range['max'])) {
50
            $message .= '-'.$range['max'];
51 3
        } else {
52
            $message .= '/'.long2ip((int) $range['mask']);
53
        }
54 27
55
        return $message;
56
    }
57
58 27
    protected function parseRange($input)
59 2
    {
60
        if (null === $input || '*' == $input || '*.*.*.*' == $input
61
            || '0.0.0.0-255.255.255.255' == $input) {
62 25
            return;
63
        }
64
65 21
        $range = ['min' => null, 'max' => null, 'mask' => null];
66
67 21
        if (false !== mb_strpos($input, '-')) {
68 5
            list($range['min'], $range['max']) = explode('-', $input);
69
        } elseif (false !== mb_strpos($input, '*')) {
70 21
            $this->parseRangeUsingWildcards($input, $range);
71
        } elseif (false !== mb_strpos($input, '/')) {
72 12
            $this->parseRangeUsingCidr($input, $range);
73
        } else {
74 12
            throw new ComponentException('Invalid network range');
75
        }
76 12
77 12
        if (!$this->verifyAddress($range['min'])) {
78 12
            throw new ComponentException('Invalid network range');
79
        }
80 9
81
        if (isset($range['max']) && !$this->verifyAddress($range['max'])) {
82 9
            throw new ComponentException('Invalid network range');
83 9
        }
84
85 9
        return $range;
86 9
    }
87
88 9
    protected function fillAddress(&$input, $char = '*'): void
89 2
    {
90
        while (mb_substr_count($input, '.') < 3) {
91 2
            $input .= '.'.$char;
92
        }
93
    }
94 7
95 3
    protected function parseRangeUsingWildcards($input, &$range): void
96
    {
97
        $this->fillAddress($input);
98 4
99 4
        $range['min'] = strtr($input, '*', '0');
100
        $range['max'] = str_replace('*', '255', $input);
101 38
    }
102
103 38
    protected function parseRangeUsingCidr($input, &$range): void
104
    {
105
        $input = explode('/', $input);
106 42
        $this->fillAddress($input[0], '0');
107
108 42
        $range['min'] = $input[0];
109 42
        $isAddressMask = false !== mb_strpos($input[1], '.');
110 42
111
        if ($isAddressMask && $this->verifyAddress($input[1])) {
112 42
            $range['mask'] = sprintf('%032b', ip2long($input[1]));
113
114
            return;
115
        }
116
117 31
        if ($isAddressMask || $input[1] < 8 || $input[1] > 30) {
118
            throw new ComponentException('Invalid network mask');
119 31
        }
120 7
121
        $range['mask'] = sprintf('%032b', ip2long(long2ip(~(2 ** (32 - $input[1]) - 1))));
122
    }
123 25
124 6
    public function validate($input): bool
125
    {
126
        return $this->verifyAddress($input) && $this->verifyNetwork($input);
127 19
    }
128
129 19
    protected function verifyAddress($address)
130 19
    {
131
        return (bool) filter_var(
132
            $address,
133 6
            FILTER_VALIDATE_IP,
134
            [
135 6
                'flags' => $this->ipOptions,
136 6
            ]
137 6
        );
138
    }
139 6
140
    protected function verifyNetwork($input)
141
    {
142
        if (null === $this->networkRange) {
143
            return true;
144
        }
145
146
        if (isset($this->networkRange['mask'])) {
147
            return $this->belongsToSubnet($input);
148
        }
149
150
        $input = sprintf('%u', ip2long($input));
151
152
        return bccomp($input, sprintf('%u', ip2long($this->networkRange['min']))) >= 0
153
               && bccomp($input, sprintf('%u', ip2long($this->networkRange['max']))) <= 0;
154
    }
155
156
    protected function belongsToSubnet($input)
157
    {
158
        $range = $this->networkRange;
159
        $min = sprintf('%032b', ip2long($range['min']));
160
        $input = sprintf('%032b', ip2long($input));
161
162
        return ($input & $range['mask']) === ($min & $range['mask']);
163
    }
164
}
165