Page MenuHomeDevCentral

No OneTemporary

diff --git a/src/HTTP/Requests/RemoteAddress.php b/src/HTTP/Requests/RemoteAddress.php
index eb2a5fe..2d8dbee 100644
--- a/src/HTTP/Requests/RemoteAddress.php
+++ b/src/HTTP/Requests/RemoteAddress.php
@@ -1,83 +1,92 @@
<?php
declare(strict_types=1);
namespace Keruald\OmniTools\HTTP\Requests;
class RemoteAddress {
/**
* @var string
*/
private $remoteAddress;
///
/// Constructor
///
public function __construct (string $remoteAddress = '') {
$this->remoteAddress = $remoteAddress;
}
public static function fromServer () : self {
return new self(self::extractRemoteAddressesFromHeaders());
}
///
/// Format methods
///
- public function has () : bool {
- return $this->remoteAddress !== "";
- }
-
public function getClientAddress () : string {
// Header contains 'clientIP, proxyIP, anotherProxyIP'
// or 'clientIP proxyIP anotherProxyIP'
// The first value is so the one to return.
// See draft-ietf-appsawg-http-forwarded-10.
$ips = preg_split("/[\s,]+/", $this->remoteAddress, 2);
return trim($ips[0]);
}
+ public function isFromLocalHost () : bool {
+ return IP::isLoopBack($this->getClientAddress());
+ }
+
public function getAll () : string {
return $this->remoteAddress;
}
+
+ public function has () : bool {
+ return $this->remoteAddress !== "";
+ }
+
+ ///
+ /// Information methods
+ ///
+
///
/// Helper methods to determine the remote address
///
/**
* Allows to get all the remote addresses from relevant headers
*/
public static function extractRemoteAddressesFromHeaders () : string {
foreach (self::listRemoteAddressHeaders() as $candidate) {
if (isset($_SERVER[$candidate])) {
return $_SERVER[$candidate];
}
}
return "";
}
///
/// Data sources
///
public static function listRemoteAddressHeaders () : array {
return [
// Standard header provided by draft-ietf-appsawg-http-forwarded-10
'HTTP_X_FORWARDED_FOR',
// Legacy headers
'HTTP_CLIENT_IP',
'HTTP_FORWARDED',
'HTTP_FORWARDED_FOR',
'HTTP_X_CLUSTER_CLIENT_IP',
'HTTP_X_FORWARDED',
// Default header if no proxy information could be detected
'REMOTE_ADDR',
];
}
}
diff --git a/src/HTTP/Requests/WithRemoteAddress.php b/src/HTTP/Requests/WithRemoteAddress.php
index b6bb13c..97ba082 100644
--- a/src/HTTP/Requests/WithRemoteAddress.php
+++ b/src/HTTP/Requests/WithRemoteAddress.php
@@ -1,25 +1,29 @@
<?php
declare(strict_types=1);
namespace Keruald\OmniTools\HTTP\Requests;
trait WithRemoteAddress {
/**
* Gets remote IP address.
*
* This is intended as a drop-in replacement for $_SERVER['REMOTE_ADDR'],
* which takes in consideration proxy values, blindly trusted.
*
* This method should is only for environment where headers are controlled,
* like nginx + php_fpm, where HTTP_ headers are reserved for the server
* information, and where the headers sent by the web server to nginx are
* checked or populated by nginx itself.
*
* @return string the remote address
*/
public static function getRemoteAddress () : string {
return RemoteAddress::fromServer()->getClientAddress();
}
+ public static function isFromLocalHost () : bool {
+ return RemoteAddress::fromServer()->isFromLocalHost();
+ }
+
}
diff --git a/src/Network/IP.php b/src/Network/IP.php
index 8682ecb..e6d0f39 100644
--- a/src/Network/IP.php
+++ b/src/Network/IP.php
@@ -1,20 +1,31 @@
<?php
declare(strict_types=1);
namespace Keruald\OmniTools\Network;
class IP {
public static function isIP (string $ip) : bool {
return self::isIPv4($ip) || self::isIPv6($ip);
}
public static function isIPv4 (string $ip) : bool {
return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false;
}
public static function isIPv6 (string $ip) : bool {
return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false;
}
+ public static function isLoopback (string $ip) : bool {
+ $ranges = IPRange::getLoopbackRanges();
+ foreach ($ranges as $range) {
+ if ($range->contains($ip)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
}
diff --git a/tests/Network/IPTest.php b/tests/Network/IPTest.php
index 80afb28..e169a29 100644
--- a/tests/Network/IPTest.php
+++ b/tests/Network/IPTest.php
@@ -1,120 +1,148 @@
<?php
declare(strict_types=1);
namespace Keruald\OmniTools\Tests\Network;
use Keruald\OmniTools\Network\IP;
use PHPUnit\Framework\TestCase;
class IPTest extends TestCase {
///
/// Data providers for IP addresses
///
/// These data providers methods allow to provide IP addresses
/// to validate or invalidate.
///
/// The advanced IPv6 tests have been curated by Stephen Ryan
/// Source: https://web.archive.org/web/20110515134717/http://forums.dartware.com/viewtopic.php?t=452
///
public function provideValidIP () : iterable {
yield ["0.0.0.0"];
yield ["17.17.17.17"];
yield ["fe80:0000:0000:0000:0204:61ff:fe9d:f156"];
}
public function provideInvalidIP () : iterable {
yield [""];
yield ["1"];
yield ["17.17"];
yield ["17.17.17.256"];
}
public function provideValidIPv4 () : iterable {
return [["0.0.0.0"], ["17.17.17.17"]];
}
public function provideInvalidIPv4 () : iterable {
yield [""];
yield ["1"];
yield ["17.17"];
yield ["17.17.17.256"];
yield ["fe80:0000:0000:0000:0204:61ff:fe9d:f156"];
}
public function provideValidIPv6 () : iterable {
yield ["::1"];
yield ["::ffff:192.0.2.128"];
yield ["fe80:0000:0000:0000:0204:61ff:fe9d:f156"];
yield ["::ffff:192.0.2.128", "IPv4 represented as dotted-quads"];
}
public function provideInvalidIPv6 () : iterable {
yield ["0.0.0.0"];
yield [""];
yield ["1"];
yield ["17.17"];
yield ["17.17.17.17"];
yield ["::fg", "Valid IPv6 digits are 0-f, ie 0-9 and a-f"];
yield ["02001:0000:1234:0000:0000:C1C0:ABCD:0876", "Extra 0"];
yield ["2001:0000:1234:0000:00001:C1C0:ABCD:0876", "Extra 0"];
yield ["1.2.3.4:1111:2222:3333:4444::5555"];
}
+ public function provideValidLoopblackIP () : iterable {
+ yield ["127.0.0.1"];
+ yield ["127.0.0.3"];
+ yield ["::1"];
+ }
+
+ public function provideInvalidLoopblackIP () : iterable {
+ yield ["0.0.0.0"];
+ yield ["1.2.3.4"];
+ yield ["192.168.1.1"];
+ yield ["::2"];
+ }
+
///
/// Test cases
///
/**
* @covers \Keruald\OmniTools\Network\IP::isIP
* @dataProvider provideValidIP
*/
public function testIsIP ($ip) {
$this->assertTrue(IP::isIP($ip));
}
/**
* @covers \Keruald\OmniTools\Network\IP::isIP
* @dataProvider provideInvalidIP
*/
public function testIsIPWhenItIsNot ($ip) {
$this->assertFalse(IP::isIP($ip));
}
/**
* @covers \Keruald\OmniTools\Network\IP::isIPv4
* @dataProvider provideValidIPv4
*/
public function testIsIPv4 ($ip) {
$this->assertTrue(IP::isIPv4($ip));
}
/**
* @covers \Keruald\OmniTools\Network\IP::isIPv4
* @dataProvider provideInvalidIPv4
*/
public function testIsIPv4WhenItIsNot ($ip) {
$this->assertFalse(IP::isIPv4($ip));
}
/**
* @covers \Keruald\OmniTools\Network\IP::isIPv6
* @dataProvider provideValidIPv6
*/
public function testIsIPv6 (string $ip, string $message = "") {
$this->assertTrue(IP::isIPv6($ip), $message);
}
/**
* @covers \Keruald\OmniTools\Network\IP::isIPv6
* @dataProvider provideInvalidIPv6
*/
public function testIsIPv6WhenItIsNot (string $ip, string $message = "") : void {
$this->assertFalse(IP::isIPv6($ip), $message);
}
+ /**
+ * @covers \Keruald\OmniTools\Network\IP::isLoopback
+ * @dataProvider provideValidLoopblackIP
+ */
+ public function testIsLoopback (string $ip) : void {
+ $this->assertTrue(IP::isLoopback($ip));
+ }
+
+ /**
+ * @covers \Keruald\OmniTools\Network\IP::isLoopback
+ * @dataProvider provideInvalidLoopblackIP
+ */
+ public function testIsLoopbackWhenItIsNot (string $ip) : void {
+ $this->assertFalse(IP::isLoopback($ip));
+ }
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Sep 18, 11:22 (19 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2989247
Default Alt Text
(8 KB)

Event Timeline