Completed
Push — master ( ba7c5d...c3b626 )
by Julián
02:08
created

IP::determineCurrentIp()   C

Complexity

Conditions 8
Paths 10

Size

Total Lines 29
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 29
rs 5.3846
cc 8
eloc 18
nc 10
nop 1
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
     * Allowe proxies.
29
     *
30
     * @var array
31
     */
32
    protected $trustedProxies;
33
34
    /**
35
     * @param array $ips
36
     * @param array $trustedProxies
37
     */
38
    public function __construct(array $ips = [], array $trustedProxies = [])
39
    {
40
        foreach ($ips as $ipAddress) {
41
            $this->addIP($ipAddress);
42
        }
43
44
        $this->trustedProxies = $trustedProxies;
45
    }
46
47
    /**
48
     * Add IP.
49
     *
50
     * @param string $ipAddress
51
     *
52
     * @throws \InvalidArgumentException
53
     */
54
    public function addIP($ipAddress)
55
    {
56
        if (!$this->isValidIp($ipAddress)) {
57
            throw new \InvalidArgumentException(sprintf('"%s" is not a valid IP address', $ipAddress));
58
        }
59
60
        $this->ips[] = $ipAddress;
61
62
        return $this;
63
    }
64
65
    /**
66
     * {@inheritdoc}
67
     */
68
    public function isExcluded(ServerRequestInterface $request)
69
    {
70
        $currentIP = $this->determineCurrentIp($request);
71
72
        foreach ($this->ips as $ipAddress) {
73
            if ($ipAddress === $currentIP) {
74
                return true;
75
            }
76
        }
77
78
        return false;
79
    }
80
81
    /**
82
     * Find client's IP.
83
     *
84
     * @param ServerRequestInterface $request
85
     *
86
     * @return string
87
     */
88
    protected function determineCurrentIp($request)
89
    {
90
        $inspectionHeaders = [
91
            'X-Forwarded-For',
92
            'X-Forwarded',
93
            'X-Cluster-Client-Ip',
94
            'Client-Ip',
95
        ];
96
97
        $currentIp = null;
98
        $serverParams = $request->getServerParams();
99
        if (isset($serverParams['REMOTE_ADDR']) && $this->isValidIp($serverParams['REMOTE_ADDR'])) {
100
            $currentIp = $serverParams['REMOTE_ADDR'];
101
        }
102
103
        if (empty($this->trustedProxies) || in_array($currentIp, $this->trustedProxies)) {
104
            foreach ($inspectionHeaders as $header) {
105
                if ($request->hasHeader($header)) {
106
                    $ipAddress = trim(current(explode(',', $request->getHeaderLine($header))));
107
                    if ($this->isValidIp($ipAddress)) {
108
                        $currentIp = $ipAddress;
109
                        break;
110
                    }
111
                }
112
            }
113
        }
114
115
        return $currentIp;
116
    }
117
118
    /**
119
     * Check IP validity.
120
     *
121
     * @param string $ipAddress
122
     *
123
     * @return bool
124
     */
125
    private function isValidIp($ipAddress)
126
    {
127
        return filter_var($ipAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6) !== false;
128
    }
129
}
130