Completed
Push — master ( c3b626...7e83bb )
by Julián
04:41
created

IP::getIpFromServerParams()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 11
rs 9.4285
cc 3
eloc 6
nc 2
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
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
87
     */
88
    protected function determineCurrentIp(ServerRequestInterface $request)
89
    {
90
        $inspectionHeaders = [
91
            'X-Forwarded-For',
92
            'X-Forwarded',
93
            'X-Cluster-Client-Ip',
94
            'Client-Ip',
95
        ];
96
97
        $currentIp = $this->getIpFromServerParams($request);
98
99
        if (!count($this->trustedProxies) || in_array($currentIp, $this->trustedProxies, true)) {
100
            $trustedIp = null;
101
102
            $headers = $inspectionHeaders;
103
            while ($trustedIp === null && $header = array_shift($headers)) {
104
                if ($request->hasHeader($header)) {
105
                    $ipAddress = trim(array_shift(explode(',', $request->getHeaderLine($header))));
0 ignored issues
show
Bug introduced by
explode(',', $request->getHeaderLine($header)) cannot be passed to array_shift() as the parameter $array expects a reference.
Loading history...
106
107
                    if ($this->isValidIp($ipAddress)) {
108
                        $trustedIp = $ipAddress;
109
                    }
110
                }
111
            }
112
113
            if ($trustedIp !== null) {
114
                $currentIp = $trustedIp;
115
            }
116
        }
117
118
        return $currentIp;
119
    }
120
121
    /**
122
     * Return current IP retrieved from server parameters.
123
     *
124
     * @param ServerRequestInterface $request
125
     *
126
     * @return string|null
127
     */
128
    private function getIpFromServerParams(ServerRequestInterface $request)
129
    {
130
        $currentIp = null;
131
132
        $serverParams = $request->getServerParams();
133
        if (isset($serverParams['REMOTE_ADDR']) && $this->isValidIp($serverParams['REMOTE_ADDR'])) {
134
            $currentIp = $serverParams['REMOTE_ADDR'];
135
        }
136
137
        return $currentIp;
138
    }
139
140
    /**
141
     * Check IP validity.
142
     *
143
     * @param string $ipAddress
144
     *
145
     * @return bool
146
     */
147
    private function isValidIp($ipAddress)
148
    {
149
        return filter_var($ipAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6) !== false;
150
    }
151
}
152