Completed
Push — master ( 0a1570...913ef0 )
by Julián
02:27 queued 10s
created

IP::__construct()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
c 5
b 0
f 0
dl 0
loc 18
rs 8.8571
cc 5
eloc 9
nc 16
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
            $this->addIP($ipAddress);
48
        }
49
50
        if (!is_array($trustedProxies)) {
51
            $trustedProxies = [$trustedProxies];
52
        }
53
54
        foreach ($trustedProxies as $ipAddress) {
55
            $this->addTrustedProxy($ipAddress);
56
        }
57
    }
58
59
    /**
60
     * Add IP.
61
     *
62
     * @param string $ipAddress
63
     *
64
     * @throws \InvalidArgumentException
65
     *
66
     * @return $this
67
     */
68
    public function addIP($ipAddress)
69
    {
70
        if (trim($ipAddress) !== '') {
71
            if (!$this->isValidIp($ipAddress)) {
72
                throw new \InvalidArgumentException(sprintf('"%s" is not a valid IP address', $ipAddress));
73
            }
74
75
            $this->ips[] = $ipAddress;
76
        }
77
78
        return $this;
79
    }
80
81
    /**
82
     * Add Trusted proxy.
83
     *
84
     * @param string $ipAddress
85
     *
86
     * @throws \InvalidArgumentException
87
     *
88
     * @return $this
89
     */
90
    public function addTrustedProxy($ipAddress)
91
    {
92
        if (trim($ipAddress) !== '') {
93
            if (!$this->isValidIp($ipAddress)) {
94
                throw new \InvalidArgumentException(sprintf('"%s" is not a valid IP address', $ipAddress));
95
            }
96
97
            $this->trustedProxies[] = $ipAddress;
98
        }
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