PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.14.6
Independent Analytics – WordPress Analytics Plugin v2.14.6
2.15.5 2.15.4 2.15.3 2.15.2 2.15.1 2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / vendor / mlocati / ip-lib / src / Address / IPv4.php
independent-analytics / vendor / mlocati / ip-lib / src / Address Last commit date
AddressInterface.php 1 year ago AssignedRange.php 1 year ago IPv4.php 1 year ago IPv6.php 1 year ago Type.php 1 year ago
IPv4.php
465 lines
1 <?php
2
3 namespace IAWPSCOPED\IPLib\Address;
4
5 use IAWPSCOPED\IPLib\ParseStringFlag;
6 use IAWPSCOPED\IPLib\Range\RangeInterface;
7 use IAWPSCOPED\IPLib\Range\Subnet;
8 use IAWPSCOPED\IPLib\Range\Type as RangeType;
9 /**
10 * An IPv4 address.
11 * @internal
12 */
13 class IPv4 implements AddressInterface
14 {
15 /**
16 * The string representation of the address.
17 *
18 * @var string
19 *
20 * @example '127.0.0.1'
21 */
22 protected $address;
23 /**
24 * The byte list of the IP address.
25 *
26 * @var int[]|null
27 */
28 protected $bytes;
29 /**
30 * The type of the range of this IP address.
31 *
32 * @var int|null
33 */
34 protected $rangeType;
35 /**
36 * A string representation of this address than can be used when comparing addresses and ranges.
37 *
38 * @var string
39 */
40 protected $comparableString;
41 /**
42 * An array containing RFC designated address ranges.
43 *
44 * @var array|null
45 */
46 private static $reservedRanges;
47 /**
48 * Initializes the instance.
49 *
50 * @param string $address
51 */
52 protected function __construct($address)
53 {
54 $this->address = $address;
55 $this->bytes = null;
56 $this->rangeType = null;
57 $this->comparableString = null;
58 }
59 /**
60 * {@inheritdoc}
61 *
62 * @see \IPLib\Address\AddressInterface::__toString()
63 */
64 public function __toString()
65 {
66 return $this->address;
67 }
68 /**
69 * {@inheritdoc}
70 *
71 * @see \IPLib\Address\AddressInterface::getNumberOfBits()
72 */
73 public static function getNumberOfBits()
74 {
75 return 32;
76 }
77 /**
78 * @deprecated since 1.17.0: use the parseString() method instead.
79 * For upgrading:
80 * - if $mayIncludePort is true, use the ParseStringFlag::MAY_INCLUDE_PORT flag
81 * - if $supportNonDecimalIPv4 is true, use the ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag
82 *
83 * @param string|mixed $address the address to parse
84 * @param bool $mayIncludePort
85 * @param bool $supportNonDecimalIPv4
86 *
87 * @return static|null
88 *
89 * @see \IPLib\Address\IPv4::parseString()
90 * @since 1.1.0 added the $mayIncludePort argument
91 * @since 1.10.0 added the $supportNonDecimalIPv4 argument
92 */
93 public static function fromString($address, $mayIncludePort = \true, $supportNonDecimalIPv4 = \false)
94 {
95 return static::parseString($address, 0 | ($mayIncludePort ? ParseStringFlag::MAY_INCLUDE_PORT : 0) | ($supportNonDecimalIPv4 ? ParseStringFlag::IPV4_MAYBE_NON_DECIMAL : 0));
96 }
97 /**
98 * Parse a string and returns an IPv4 instance if the string is valid, or null otherwise.
99 *
100 * @param string|mixed $address the address to parse
101 * @param int $flags A combination or zero or more flags
102 *
103 * @return static|null
104 *
105 * @see \IPLib\ParseStringFlag
106 * @since 1.17.0
107 */
108 public static function parseString($address, $flags = 0)
109 {
110 if (!\is_string($address)) {
111 return null;
112 }
113 $flags = (int) $flags;
114 $matches = null;
115 if ($flags & ParseStringFlag::ADDRESS_MAYBE_RDNS) {
116 if (\preg_match('/^([12]?[0-9]{1,2}\\.[12]?[0-9]{1,2}\\.[12]?[0-9]{1,2}\\.[12]?[0-9]{1,2})\\.in-addr\\.arpa\\.?$/i', $address, $matches)) {
117 $address = \implode('.', \array_reverse(\explode('.', $matches[1])));
118 $flags = $flags & ~(ParseStringFlag::IPV4_MAYBE_NON_DECIMAL | ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED);
119 }
120 }
121 if ($flags & ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED) {
122 if (\strpos($address, '.') === 0) {
123 return null;
124 }
125 $lengthNonHex = '{1,11}';
126 $lengthHex = '{1,8}';
127 $chunk234Optional = \true;
128 } else {
129 if (!\strpos($address, '.')) {
130 return null;
131 }
132 $lengthNonHex = '{1,3}';
133 $lengthHex = '{1,2}';
134 $chunk234Optional = \false;
135 }
136 $rxChunk1 = "0?[0-9]{$lengthNonHex}";
137 if ($flags & ParseStringFlag::IPV4_MAYBE_NON_DECIMAL) {
138 $rxChunk1 = "(?:0[Xx]0*[0-9A-Fa-f]{$lengthHex})|(?:{$rxChunk1})";
139 $onlyDecimal = \false;
140 } else {
141 $onlyDecimal = \true;
142 }
143 $rxChunk1 = "0*?({$rxChunk1})";
144 $rxChunk234 = "\\.{$rxChunk1}";
145 if ($chunk234Optional) {
146 $rxChunk234 = "(?:{$rxChunk234})?";
147 }
148 $rx = "{$rxChunk1}{$rxChunk234}{$rxChunk234}{$rxChunk234}";
149 if ($flags & ParseStringFlag::MAY_INCLUDE_PORT) {
150 $rx .= '(?::\\d+)?';
151 }
152 if (!\preg_match('/^' . $rx . '$/', $address, $matches)) {
153 return null;
154 }
155 $math = new \IAWPSCOPED\IPLib\Service\UnsignedIntegerMath();
156 $nums = array();
157 $maxChunkIndex = \count($matches) - 1;
158 for ($i = 1; $i <= $maxChunkIndex; $i++) {
159 $numBytes = $i === $maxChunkIndex ? 5 - $i : 1;
160 $chunkBytes = $math->getBytes($matches[$i], $numBytes, $onlyDecimal);
161 if ($chunkBytes === null) {
162 return null;
163 }
164 $nums = \array_merge($nums, $chunkBytes);
165 }
166 return new static(\implode('.', $nums));
167 }
168 /**
169 * Parse an array of bytes and returns an IPv4 instance if the array is valid, or null otherwise.
170 *
171 * @param int[]|array $bytes
172 *
173 * @return static|null
174 */
175 public static function fromBytes(array $bytes)
176 {
177 $result = null;
178 if (\count($bytes) === 4) {
179 $chunks = \array_map(function ($byte) {
180 return \is_int($byte) && $byte >= 0 && $byte <= 255 ? (string) $byte : \false;
181 }, $bytes);
182 if (\in_array(\false, $chunks, \true) === \false) {
183 $result = new static(\implode('.', $chunks));
184 }
185 }
186 return $result;
187 }
188 /**
189 * {@inheritdoc}
190 *
191 * @see \IPLib\Address\AddressInterface::toString()
192 */
193 public function toString($long = \false)
194 {
195 if ($long) {
196 return $this->getComparableString();
197 }
198 return $this->address;
199 }
200 /**
201 * Get the octal representation of this IP address.
202 *
203 * @param bool $long
204 *
205 * @return string
206 *
207 * @since 1.10.0
208 *
209 * @example if $long == false: if the decimal representation is '0.7.8.255': '0.7.010.0377'
210 * @example if $long == true: if the decimal representation is '0.7.8.255': '0000.0007.0010.0377'
211 */
212 public function toOctal($long = \false)
213 {
214 $chunks = array();
215 foreach ($this->getBytes() as $byte) {
216 if ($long) {
217 $chunks[] = \sprintf('%04o', $byte);
218 } else {
219 $chunks[] = '0' . \decoct($byte);
220 }
221 }
222 return \implode('.', $chunks);
223 }
224 /**
225 * Get the hexadecimal representation of this IP address.
226 *
227 * @param bool $long
228 *
229 * @return string
230 *
231 * @since 1.10.0
232 *
233 * @example if $long == false: if the decimal representation is '0.9.10.255': '0.9.0xa.0xff'
234 * @example if $long == true: if the decimal representation is '0.9.10.255': '0x00.0x09.0x0a.0xff'
235 */
236 public function toHexadecimal($long = \false)
237 {
238 $chunks = array();
239 foreach ($this->getBytes() as $byte) {
240 if ($long) {
241 $chunks[] = \sprintf('0x%02x', $byte);
242 } else {
243 $chunks[] = '0x' . \dechex($byte);
244 }
245 }
246 return \implode('.', $chunks);
247 }
248 /**
249 * {@inheritdoc}
250 *
251 * @see \IPLib\Address\AddressInterface::getBytes()
252 */
253 public function getBytes()
254 {
255 if ($this->bytes === null) {
256 $this->bytes = \array_map(function ($chunk) {
257 return (int) $chunk;
258 }, \explode('.', $this->address));
259 }
260 return $this->bytes;
261 }
262 /**
263 * {@inheritdoc}
264 *
265 * @see \IPLib\Address\AddressInterface::getBits()
266 */
267 public function getBits()
268 {
269 $parts = array();
270 foreach ($this->getBytes() as $byte) {
271 $parts[] = \sprintf('%08b', $byte);
272 }
273 return \implode('', $parts);
274 }
275 /**
276 * {@inheritdoc}
277 *
278 * @see \IPLib\Address\AddressInterface::getAddressType()
279 */
280 public function getAddressType()
281 {
282 return Type::T_IPv4;
283 }
284 /**
285 * {@inheritdoc}
286 *
287 * @see \IPLib\Address\AddressInterface::getDefaultReservedRangeType()
288 */
289 public static function getDefaultReservedRangeType()
290 {
291 return RangeType::T_PUBLIC;
292 }
293 /**
294 * {@inheritdoc}
295 *
296 * @see \IPLib\Address\AddressInterface::getReservedRanges()
297 */
298 public static function getReservedRanges()
299 {
300 if (self::$reservedRanges === null) {
301 $reservedRanges = array();
302 foreach (array(
303 // RFC 5735
304 '0.0.0.0/8' => array(RangeType::T_THISNETWORK, array('0.0.0.0/32' => RangeType::T_UNSPECIFIED)),
305 // RFC 5735
306 '10.0.0.0/8' => array(RangeType::T_PRIVATENETWORK),
307 // RFC 6598
308 '100.64.0.0/10' => array(RangeType::T_CGNAT),
309 // RFC 5735
310 '127.0.0.0/8' => array(RangeType::T_LOOPBACK),
311 // RFC 5735
312 '169.254.0.0/16' => array(RangeType::T_LINKLOCAL),
313 // RFC 5735
314 '172.16.0.0/12' => array(RangeType::T_PRIVATENETWORK),
315 // RFC 5735
316 '192.0.0.0/24' => array(RangeType::T_RESERVED),
317 // RFC 5735
318 '192.0.2.0/24' => array(RangeType::T_RESERVED),
319 // RFC 5735
320 '192.88.99.0/24' => array(RangeType::T_ANYCASTRELAY),
321 // RFC 5735
322 '192.168.0.0/16' => array(RangeType::T_PRIVATENETWORK),
323 // RFC 5735
324 '198.18.0.0/15' => array(RangeType::T_RESERVED),
325 // RFC 5735
326 '198.51.100.0/24' => array(RangeType::T_RESERVED),
327 // RFC 5735
328 '203.0.113.0/24' => array(RangeType::T_RESERVED),
329 // RFC 5735
330 '224.0.0.0/4' => array(RangeType::T_MULTICAST),
331 // RFC 5735
332 '240.0.0.0/4' => array(RangeType::T_RESERVED, array('255.255.255.255/32' => RangeType::T_LIMITEDBROADCAST)),
333 ) as $range => $data) {
334 $exceptions = array();
335 if (isset($data[1])) {
336 foreach ($data[1] as $exceptionRange => $exceptionType) {
337 $exceptions[] = new AssignedRange(Subnet::parseString($exceptionRange), $exceptionType);
338 }
339 }
340 $reservedRanges[] = new AssignedRange(Subnet::parseString($range), $data[0], $exceptions);
341 }
342 self::$reservedRanges = $reservedRanges;
343 }
344 return self::$reservedRanges;
345 }
346 /**
347 * {@inheritdoc}
348 *
349 * @see \IPLib\Address\AddressInterface::getRangeType()
350 */
351 public function getRangeType()
352 {
353 if ($this->rangeType === null) {
354 $rangeType = null;
355 foreach (static::getReservedRanges() as $reservedRange) {
356 $rangeType = $reservedRange->getAddressType($this);
357 if ($rangeType !== null) {
358 break;
359 }
360 }
361 $this->rangeType = $rangeType === null ? static::getDefaultReservedRangeType() : $rangeType;
362 }
363 return $this->rangeType;
364 }
365 /**
366 * Create an IPv6 representation of this address (in 6to4 notation).
367 *
368 * @return \IPLib\Address\IPv6
369 */
370 public function toIPv6()
371 {
372 $myBytes = $this->getBytes();
373 return IPv6::parseString('2002:' . \sprintf('%02x', $myBytes[0]) . \sprintf('%02x', $myBytes[1]) . ':' . \sprintf('%02x', $myBytes[2]) . \sprintf('%02x', $myBytes[3]) . '::');
374 }
375 /**
376 * Create an IPv6 representation of this address (in IPv6 IPv4-mapped notation).
377 *
378 * @return \IPLib\Address\IPv6
379 *
380 * @since 1.11.0
381 */
382 public function toIPv6IPv4Mapped()
383 {
384 return IPv6::fromBytes(\array_merge(array(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff), $this->getBytes()));
385 }
386 /**
387 * {@inheritdoc}
388 *
389 * @see \IPLib\Address\AddressInterface::getComparableString()
390 */
391 public function getComparableString()
392 {
393 if ($this->comparableString === null) {
394 $chunks = array();
395 foreach ($this->getBytes() as $byte) {
396 $chunks[] = \sprintf('%03d', $byte);
397 }
398 $this->comparableString = \implode('.', $chunks);
399 }
400 return $this->comparableString;
401 }
402 /**
403 * {@inheritdoc}
404 *
405 * @see \IPLib\Address\AddressInterface::matches()
406 */
407 public function matches(RangeInterface $range)
408 {
409 return $range->contains($this);
410 }
411 /**
412 * {@inheritdoc}
413 *
414 * @see \IPLib\Address\AddressInterface::getAddressAtOffset()
415 */
416 public function getAddressAtOffset($n)
417 {
418 if (!\is_int($n)) {
419 return null;
420 }
421 $boundary = 256;
422 $mod = $n;
423 $bytes = $this->getBytes();
424 for ($i = \count($bytes) - 1; $i >= 0; $i--) {
425 $tmp = ($bytes[$i] + $mod) % $boundary;
426 $mod = (int) \floor(($bytes[$i] + $mod) / $boundary);
427 if ($tmp < 0) {
428 $tmp += $boundary;
429 }
430 $bytes[$i] = $tmp;
431 }
432 if ($mod !== 0) {
433 return null;
434 }
435 return static::fromBytes($bytes);
436 }
437 /**
438 * {@inheritdoc}
439 *
440 * @see \IPLib\Address\AddressInterface::getNextAddress()
441 */
442 public function getNextAddress()
443 {
444 return $this->getAddressAtOffset(1);
445 }
446 /**
447 * {@inheritdoc}
448 *
449 * @see \IPLib\Address\AddressInterface::getPreviousAddress()
450 */
451 public function getPreviousAddress()
452 {
453 return $this->getAddressAtOffset(-1);
454 }
455 /**
456 * {@inheritdoc}
457 *
458 * @see \IPLib\Address\AddressInterface::getReverseDNSLookupName()
459 */
460 public function getReverseDNSLookupName()
461 {
462 return \implode('.', \array_reverse($this->getBytes())) . '.in-addr.arpa';
463 }
464 }
465