Completed
Push — master ( 6a6e14...e9047f )
by Julián
02:21
created

IP::__construct()   C

Complexity

Conditions 7
Paths 36

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 22
rs 6.9811
cc 7
eloc 11
nc 36
nop 2
1
<?php
2
/**
3
 * Effortless maintenance management (http://juliangut.com/janitor)
4
 *
5
 * @link https://github.com/juliangut/janitor for the canonical source repository
6
 *
7
 * @license https://github.com/juliangut/janitor/blob/master/LICENSE
8
 */
9
10
namespace Janitor\Excluder;
11
12
use Janitor\Excluder as ExcluderInterface;
13
use Psr\Http\Message\ServerRequestInterface;
14
15
/**
16
 * Maintenance excluder by route
17
 */
18
class IP implements ExcluderInterface
19
{
20
    /**
21
     * List of IPs to be excluded.
22
     *
23
     * @var array
24
     */
25
    protected $ips = [];
26
27
    /**
28
     * Allowed proxies.
29
     *
30
     * @var array
31
     */
32
    protected $trustedProxies = [];
33
34
    /**
35
     * @param string|array|null $ips
36
     * @param string|array|null $trustedProxies
37
     *
38
     * @throws \InvalidArgumentException
39
     */
40
    public function __construct($ips = null, $trustedProxies = null)
41
    {
42
        if (!is_array($ips)) {
43
            $ips = [$ips];
44
        }
45
46
        foreach ($ips as $ipAddress) {
47
            if (trim($ipAddress) !== '') {
48
                $this->addIP($ipAddress);
49
            }
50
        }
51
52
        if (!is_array($trustedProxies)) {
53
            $trustedProxies = [$trustedProxies];
54
        }
55
56
        foreach ($trustedProxies as $ipAddress) {
57
            if (trim($ipAddress) !== '') {
58
                $this->addTrustedProxy($ipAddress);
59
            }
60
        }
61
    }
62
63
    /**
64
     * Add IP.
65
     *
66
     * @param string $ipAddress
67
     *
68
     * @throws \InvalidArgumentException
69
     *
70
     * @return $this
71
     */
72
    public function addIP($ipAddress)
73
    {
74
        if (!$this->isValidIp($ipAddress)) {
75
            throw new \InvalidArgumentException(sprintf('"%s" is not a valid IP address', $ipAddress));
76
        }
77
78
        $this->ips[] = $ipAddress;
79
80
        return $this;
81
    }
82
83
    /**
84
     * Add Trusted proxy.
85
     *
86
     * @param string $ipAddress
87
     *
88
     * @throws \InvalidArgumentException
89
     *
90
     * @return $this
91
     */
92
    public function addTrustedProxy($ipAddress)
93
    {
94
        if (!$this->isValidIp($ipAddress)) {
95
            throw new \InvalidArgumentException(sprintf('"%s" is not a valid IP address', $ipAddress));
96
        }
97
98
        $this->trustedProxies[] = $ipAddress;
99
100
        return $this;
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    public function isExcluded(ServerRequestInterface $request)
107
    {
108
        $currentIP = $this->determineCurrentIp($request);
109
110
        foreach ($this->ips as $ipAddress) {
111
            if ($ipAddress === $currentIP) {
112
                return true;
113
            }
114
        }
115
116
        return false;
117
    }
118
119
    /**
120
     * Find client's IP.
121
     *
122
     * @param ServerRequestInterface $request
123
     *
124
     * @return string|null
125
     */
126
    protected function determineCurrentIp(ServerRequestInterface $request)
127
    {
128
        $inspectionHeaders = [
129
            'X-Forwarded-For',
130
            'X-Forwarded',
131
            'X-Cluster-Client-Ip',
132
            'Client-Ip',
133
        ];
134
135
        $currentIp = $this->getIpFromServerParams($request);
136
137
        if (!count($this->trustedProxies) || in_array($currentIp, $this->trustedProxies, true)) {
138
            $trustedIp = null;
139
140
            $headers = $inspectionHeaders;
141
            while ($trustedIp === null && $header = array_shift($headers)) {
142
                if ($request->hasHeader($header)) {
143
                    $ipAddress = trim(current(explode(',', $request->getHeaderLine($header))));
144
145
                    if ($this->isValidIp($ipAddress)) {
146
                        $trustedIp = $ipAddress;
147
                    }
148
                }
149
            }
150
151
            if ($trustedIp !== null) {
152
                $currentIp = $trustedIp;
153
            }
154
        }
155
156
        return $currentIp;
157
    }
158
159
    /**
160
     * Return current IP retrieved from server parameters.
161
     *
162
     * @param ServerRequestInterface $request
163
     *
164
     * @return string|null
165
     */
166
    private function getIpFromServerParams(ServerRequestInterface $request)
167
    {
168
        $currentIp = null;
169
170
        $serverParams = $request->getServerParams();
171
        if (isset($serverParams['REMOTE_ADDR']) && $this->isValidIp($serverParams['REMOTE_ADDR'])) {
172
            $currentIp = $serverParams['REMOTE_ADDR'];
173
        }
174
175
        return $currentIp;
176
    }
177
178
    /**
179
     * Check IP validity.
180
     *
181
     * @param string $ipAddress
182
     *
183
     * @return bool
184
     */
185
    private function isValidIp($ipAddress)
186
    {
187
        return filter_var($ipAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6) !== false;
188
    }
189
}
190