| 
									
										
										
										
											2022-07-23 20:41:29 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 00:56:55 +08:00
										 |  |  | namespace BookStack\Activity\Tools; | 
					
						
							| 
									
										
										
										
											2022-07-23 20:41:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class IpFormatter | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     protected string $ip; | 
					
						
							|  |  |  |     protected int $precision; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function __construct(string $ip, int $precision) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->ip = trim($ip); | 
					
						
							|  |  |  |         $this->precision = max(0, min($precision, 4)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function format(): string | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (empty($this->ip) || $this->precision === 4) { | 
					
						
							|  |  |  |             return $this->ip; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $this->isIpv6() ? $this->maskIpv6() : $this->maskIpv4(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     protected function maskIpv4(): string | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $exploded = $this->explodeAndExpandIp('.', 4); | 
					
						
							| 
									
										
										
										
											2022-07-23 22:11:06 +08:00
										 |  |  |         $maskGroupCount = min(4 - $this->precision, count($exploded)); | 
					
						
							| 
									
										
										
										
											2022-07-23 20:41:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for ($i = 0; $i < $maskGroupCount; $i++) { | 
					
						
							|  |  |  |             $exploded[3 - $i] = 'x'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return implode('.', $exploded); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     protected function maskIpv6(): string | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $exploded = $this->explodeAndExpandIp(':', 8); | 
					
						
							|  |  |  |         $maskGroupCount = min(8 - ($this->precision * 2), count($exploded)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for ($i = 0; $i < $maskGroupCount; $i++) { | 
					
						
							|  |  |  |             $exploded[7 - $i] = 'x'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return implode(':', $exploded); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     protected function isIpv6(): bool | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return strpos($this->ip, ':') !== false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     protected function explodeAndExpandIp(string $separator, int $targetLength): array | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $exploded = explode($separator, $this->ip); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         while (count($exploded) < $targetLength) { | 
					
						
							|  |  |  |             $emptyIndex = array_search('', $exploded) ?: count($exploded) - 1; | 
					
						
							|  |  |  |             array_splice($exploded, $emptyIndex, 0, '0'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $emptyIndex = array_search('', $exploded); | 
					
						
							|  |  |  |         if ($emptyIndex !== false) { | 
					
						
							|  |  |  |             $exploded[$emptyIndex] = '0'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $exploded; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public static function fromCurrentRequest(): self | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $ip = request()->ip() ?? ''; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (config('app.env') === 'demo') { | 
					
						
							|  |  |  |             $ip = '127.0.0.1'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return new self($ip, config('app.ip_address_precision')); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-07-23 22:11:06 +08:00
										 |  |  | } |