RemoteIp::validate()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 16
rs 9.2
cc 4
eloc 7
nc 4
nop 0
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Session
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Session\Validator;
16
17
use Phossa2\Shared\Base\ObjectAbstract;
18
use Phossa2\Session\Interfaces\ValidatorInterface;
19
20
/**
21
 * RemoteIp
22
 *
23
 * Check remote ip is allowed or not
24
 *
25
 * @package Phossa2\package
26
 * @author  Hong Zhang <[email protected]>
27
 * @see     ObjectAbstract
28
 * @see     ValidatorInterface
29
 * @version 2.1.0
30
 * @since   2.1.0 added
31
 */
32
class RemoteIp extends ObjectAbstract implements ValidatorInterface
33
{
34
    /**
35
     * Allowed ip patterns
36
     *
37
     * @var    array
38
     * @access protected
39
     */
40
    protected $allowed;
41
42
    /**
43
     * Denied ip patterns
44
     *
45
     * @var    array
46
     * @access protected
47
     */
48
    protected $denied;
49
50
    /**
51
     * Inject allowed or denied ip patterns like '216.110.124.0/24' etc.
52
     *
53
     * @param  array $denied
54
     * @param  array $allowed
55
     * @access protected
56
     */
57
    public function __construct(array $denied = [], array $allowed = [])
58
    {
59
        $this->setAllowed($allowed)->setDenied($denied);
60
    }
61
62
    /**
63
     * {@inheritDoc}
64
     */
65
    public function validate()/*# : bool */
66
    {
67
        $ip = $_SERVER['REMOTE_ADDR'];
68
69
        // allowed ?
70
        if ($this->matchIp($ip, $this->allowed)) {
71
            return true;
72
        }
73
74
        // blocked ?
75
        if ($this->matchIp($ip, $this->denied)) {
76
            return false;
77
        }
78
79
        return empty($this->allowed) ? true : false;
80
    }
81
82
    /**
83
     * Set allowed patterns
84
     *
85
     * @param  array $patterns
86
     * @return $this
87
     * @access public
88
     */
89
    public function setAllowed(array $patterns)
90
    {
91
        $this->allowed = $this->processPattern($patterns);
92
        return $this;
93
    }
94
95
    /**
96
     * Set denied patterns
97
     *
98
     * @param  array $patterns
99
     * @return $this
100
     * @access public
101
     */
102
    public function setDenied(array $patterns)
103
    {
104
        $this->denied = $this->processPattern($patterns);
105
        return $this;
106
    }
107
108
    /**
109
     * Match ip with patterns
110
     *
111
     * @param  string $ip
112
     * @param  array $patterns
113
     * @return boolean
114
     * @access protected
115
     */
116
    protected function matchIp(/*# string */ $ip, array $patterns)/*# : bool */
117
    {
118
        $num = ip2long($ip);
119
        foreach ($patterns as $pat) {
120
            if (($num & $pat[1]) == $pat[0]) {
121
                return true;
122
            }
123
        }
124
        return false;
125
    }
126
127
    /**
128
     * Pre-process ip matching pattern
129
     *
130
     * @param  array $patterns
131
     * @return array
132
     * @access protected
133
     */
134
    protected function processPattern(array $patterns)/*# : array */
135
    {
136
        $result = [];
137
        foreach ($patterns as $pat) {
138
            $part = explode('/', $pat);
139
            $addr = ip2long($part[0]);
140
            $mask = isset($part[1]) ? ((int) $part[1]) : 32;
141
142
            // fix
143
            $mask = $this->getMask($mask);
144
            $addr = $addr & $mask;
145
146
            $result[] = [$addr, $mask];
147
        }
148
        return $result;
149
    }
150
151
    /**
152
     * Convert mask length to mask in decimal
153
     *
154
     * @param  int $length
155
     * @return int
156
     * @access protected
157
     */
158
    protected function getMask(/*# int */ $length = 32)/*# : int */
159
    {
160
        $bin = substr(str_repeat('1', $length) . str_repeat('0', 32), 0, 32);
161
        return ip2long(long2ip(bindec($bin)));
162
    }
163
}
164