]> BookStack Code Mirror - bookstack/blob - app/Activity/Tools/IpFormatter.php
Opensearch: Fixed XML declaration when php short tags enabled
[bookstack] / app / Activity / Tools / IpFormatter.php
1 <?php
2
3 namespace BookStack\Activity\Tools;
4
5 class IpFormatter
6 {
7     protected string $ip;
8     protected int $precision;
9
10     public function __construct(string $ip, int $precision)
11     {
12         $this->ip = trim($ip);
13         $this->precision = max(0, min($precision, 4));
14     }
15
16     public function format(): string
17     {
18         if (empty($this->ip) || $this->precision === 4) {
19             return $this->ip;
20         }
21
22         return $this->isIpv6() ? $this->maskIpv6() : $this->maskIpv4();
23     }
24
25     protected function maskIpv4(): string
26     {
27         $exploded = $this->explodeAndExpandIp('.', 4);
28         $maskGroupCount = min(4 - $this->precision, count($exploded));
29
30         for ($i = 0; $i < $maskGroupCount; $i++) {
31             $exploded[3 - $i] = 'x';
32         }
33
34         return implode('.', $exploded);
35     }
36
37     protected function maskIpv6(): string
38     {
39         $exploded = $this->explodeAndExpandIp(':', 8);
40         $maskGroupCount = min(8 - ($this->precision * 2), count($exploded));
41
42         for ($i = 0; $i < $maskGroupCount; $i++) {
43             $exploded[7 - $i] = 'x';
44         }
45
46         return implode(':', $exploded);
47     }
48
49     protected function isIpv6(): bool
50     {
51         return strpos($this->ip, ':') !== false;
52     }
53
54     protected function explodeAndExpandIp(string $separator, int $targetLength): array
55     {
56         $exploded = explode($separator, $this->ip);
57
58         while (count($exploded) < $targetLength) {
59             $emptyIndex = array_search('', $exploded) ?: count($exploded) - 1;
60             array_splice($exploded, $emptyIndex, 0, '0');
61         }
62
63         $emptyIndex = array_search('', $exploded);
64         if ($emptyIndex !== false) {
65             $exploded[$emptyIndex] = '0';
66         }
67
68         return $exploded;
69     }
70
71     public static function fromCurrentRequest(): self
72     {
73         $ip = request()->ip() ?? '';
74
75         if (config('app.env') === 'demo') {
76             $ip = '127.0.0.1';
77         }
78
79         return new self($ip, config('app.ip_address_precision'));
80     }
81 }