forked from BookStackApp/BookStack
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added ability to adjust stored IP address precision
Included tests to cover. For BookStackApp#3560
- Loading branch information
1 parent
67d12cc
commit 4e8995c
Showing
7 changed files
with
150 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
<?php | ||
|
||
namespace BookStack\Actions; | ||
|
||
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); | ||
$maskGroupCount = min( 4 - $this->precision, count($exploded)); | ||
|
||
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')); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php | ||
|
||
namespace Tests\Unit; | ||
|
||
use BookStack\Actions\IpFormatter; | ||
use Tests\TestCase; | ||
|
||
class IpFormatterTest extends TestCase | ||
{ | ||
public function test_ips_formatted_as_expected() | ||
{ | ||
$this->assertEquals('192.123.45.5', (new IpFormatter('192.123.45.5', 4))->format()); | ||
$this->assertEquals('192.123.45.x', (new IpFormatter('192.123.45.5', 3))->format()); | ||
$this->assertEquals('192.123.x.x', (new IpFormatter('192.123.45.5', 2))->format()); | ||
$this->assertEquals('192.x.x.x', (new IpFormatter('192.123.45.5', 1))->format()); | ||
$this->assertEquals('x.x.x.x', (new IpFormatter('192.123.45.5', 0))->format()); | ||
|
||
$ipv6 = '2001:db8:85a3:8d3:1319:8a2e:370:7348'; | ||
$this->assertEquals($ipv6, (new IpFormatter($ipv6, 4))->format()); | ||
$this->assertEquals('2001:db8:85a3:8d3:1319:8a2e:x:x', (new IpFormatter($ipv6, 3))->format()); | ||
$this->assertEquals('2001:db8:85a3:8d3:x:x:x:x', (new IpFormatter($ipv6, 2))->format()); | ||
$this->assertEquals('2001:db8:x:x:x:x:x:x', (new IpFormatter($ipv6, 1))->format()); | ||
$this->assertEquals('x:x:x:x:x:x:x:x', (new IpFormatter($ipv6, 0))->format()); | ||
} | ||
|
||
public function test_shortened_ipv6_addresses_expands_as_expected() | ||
{ | ||
$this->assertEquals('2001:0:0:0:0:0:x:x', (new IpFormatter('2001::370:7348', 3))->format()); | ||
$this->assertEquals('2001:0:0:0:0:85a3:x:x', (new IpFormatter('2001::85a3:370:7348', 3))->format()); | ||
$this->assertEquals('2001:0:x:x:x:x:x:x', (new IpFormatter('2001::', 1))->format()); | ||
} | ||
} |