3 namespace BookStack\Activity\Tools;
8 protected int $precision;
10 public function __construct(string $ip, int $precision)
12 $this->ip = trim($ip);
13 $this->precision = max(0, min($precision, 4));
16 public function format(): string
18 if (empty($this->ip) || $this->precision === 4) {
22 return $this->isIpv6() ? $this->maskIpv6() : $this->maskIpv4();
25 protected function maskIpv4(): string
27 $exploded = $this->explodeAndExpandIp('.', 4);
28 $maskGroupCount = min(4 - $this->precision, count($exploded));
30 for ($i = 0; $i < $maskGroupCount; $i++) {
31 $exploded[3 - $i] = 'x';
34 return implode('.', $exploded);
37 protected function maskIpv6(): string
39 $exploded = $this->explodeAndExpandIp(':', 8);
40 $maskGroupCount = min(8 - ($this->precision * 2), count($exploded));
42 for ($i = 0; $i < $maskGroupCount; $i++) {
43 $exploded[7 - $i] = 'x';
46 return implode(':', $exploded);
49 protected function isIpv6(): bool
51 return strpos($this->ip, ':') !== false;
54 protected function explodeAndExpandIp(string $separator, int $targetLength): array
56 $exploded = explode($separator, $this->ip);
58 while (count($exploded) < $targetLength) {
59 $emptyIndex = array_search('', $exploded) ?: count($exploded) - 1;
60 array_splice($exploded, $emptyIndex, 0, '0');
63 $emptyIndex = array_search('', $exploded);
64 if ($emptyIndex !== false) {
65 $exploded[$emptyIndex] = '0';
71 public static function fromCurrentRequest(): self
73 $ip = request()->ip() ?? '';
75 if (config('app.env') === 'demo') {
79 return new self($ip, config('app.ip_address_precision'));