forked from symfony/symfony
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
merged branch vicb/httputils (PR symfony#6005)
This PR was squashed before being merged into the master branch (closes symfony#6005). Commits ------- 577ee80 [HttpFoundation] Move IP check methods to a HttpUtils class for reuse Discussion ---------- [HttpFoundation] Move IP check methods to a HttpUtils class for reuse --------------------------------------------------------------------------- by vicb at 2012-11-13T18:05:18Z Thanks @stof ! (didn't get my copy paste error as PHP allow calling non static method w/o a warning). --------------------------------------------------------------------------- by GromNaN at 2012-11-17T23:19:29Z Having an `Utils` class with mixed functions doesn't seem to be a good practice. I think the class should be called something like `Symfony\Component\HttpFoundation\IpAddress`. --------------------------------------------------------------------------- by vicb at 2012-11-27T09:37:20Z @fabpot could this be merged if `HttpUtils` is renamed to `IpUtils` ? --------------------------------------------------------------------------- by fabpot at 2012-12-06T13:35:28Z Renaming the class to `IpUtils` is indeed a good idea. --------------------------------------------------------------------------- by vicb at 2012-12-06T14:07:59Z ready ! --------------------------------------------------------------------------- by fabpot at 2012-12-06T14:39:19Z Can you add an entry in the CHANGELOG? --------------------------------------------------------------------------- by vicb at 2012-12-06T14:53:09Z done, thanks for the reminder !
- Loading branch information
Showing
5 changed files
with
184 additions
and
159 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\HttpFoundation; | ||
|
||
/** | ||
* Http utility functions. | ||
* | ||
* @author Fabien Potencier <fabien@symfony.com> | ||
*/ | ||
class IpUtils | ||
{ | ||
/** | ||
* This class should not be instantiated | ||
*/ | ||
private function __construct() {} | ||
|
||
/** | ||
* Validates an IPv4 or IPv6 address. | ||
* | ||
* @param string $requestIp | ||
* @param string $ip | ||
* | ||
* @return boolean Whether the IP is valid | ||
*/ | ||
public static function checkIp($requestIp, $ip) | ||
{ | ||
if (false !== strpos($requestIp, ':')) { | ||
return self::checkIp6($requestIp, $ip); | ||
} | ||
|
||
return self::checkIp4($requestIp, $ip); | ||
} | ||
|
||
/** | ||
* Validates an IPv4 address. | ||
* | ||
* @param string $requestIp | ||
* @param string $ip | ||
* | ||
* @return boolean Whether the IP is valid | ||
*/ | ||
public static function checkIp4($requestIp, $ip) | ||
{ | ||
if (false !== strpos($ip, '/')) { | ||
list($address, $netmask) = explode('/', $ip, 2); | ||
|
||
if ($netmask < 1 || $netmask > 32) { | ||
return false; | ||
} | ||
} else { | ||
$address = $ip; | ||
$netmask = 32; | ||
} | ||
|
||
return 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask); | ||
} | ||
|
||
/** | ||
* Validates an IPv6 address. | ||
* | ||
* @author David Soria Parra <dsp at php dot net> | ||
* @see https://github.com/dsp/v6tools | ||
* | ||
* @param string $requestIp | ||
* @param string $ip | ||
* | ||
* @return boolean Whether the IP is valid | ||
* | ||
* @throws \RuntimeException When IPV6 support is not enabled | ||
*/ | ||
public static function checkIp6($requestIp, $ip) | ||
{ | ||
if (!((extension_loaded('sockets') && defined('AF_INET6')) || @inet_pton('::1'))) { | ||
throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".'); | ||
} | ||
|
||
if (false !== strpos($ip, '/')) { | ||
list($address, $netmask) = explode('/', $ip, 2); | ||
|
||
if ($netmask < 1 || $netmask > 128) { | ||
return false; | ||
} | ||
} else { | ||
$address = $ip; | ||
$netmask = 128; | ||
} | ||
|
||
$bytesAddr = unpack("n*", inet_pton($address)); | ||
$bytesTest = unpack("n*", inet_pton($requestIp)); | ||
|
||
for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; $i++) { | ||
$left = $netmask - 16 * ($i-1); | ||
$left = ($left <= 16) ? $left : 16; | ||
$mask = ~(0xffff >> $left) & 0xffff; | ||
if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) { | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
} |
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
71 changes: 71 additions & 0 deletions
71
src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php
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,71 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\HttpFoundation\Tests; | ||
|
||
use Symfony\Component\HttpFoundation\IpUtils; | ||
|
||
class IpUtilsTest extends \PHPUnit_Framework_TestCase | ||
{ | ||
/** | ||
* @dataProvider testIpv4Provider | ||
*/ | ||
public function testIpv4($matches, $remoteAddr, $cidr) | ||
{ | ||
$this->assertSame($matches, IpUtils::checkIp($remoteAddr, $cidr)); | ||
} | ||
|
||
public function testIpv4Provider() | ||
{ | ||
return array( | ||
array(true, '192.168.1.1', '192.168.1.1'), | ||
array(true, '192.168.1.1', '192.168.1.1/1'), | ||
array(true, '192.168.1.1', '192.168.1.0/24'), | ||
array(false, '192.168.1.1', '1.2.3.4/1'), | ||
array(false, '192.168.1.1', '192.168.1/33'), | ||
); | ||
} | ||
|
||
/** | ||
* @dataProvider testIpv6Provider | ||
*/ | ||
public function testIpv6($matches, $remoteAddr, $cidr) | ||
{ | ||
if (!defined('AF_INET6')) { | ||
$this->markTestSkipped('Only works when PHP is compiled without the option "disable-ipv6".'); | ||
} | ||
|
||
$this->assertSame($matches, IpUtils::checkIp($remoteAddr, $cidr)); | ||
} | ||
|
||
public function testIpv6Provider() | ||
{ | ||
return array( | ||
array(true, '2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'), | ||
array(false, '2a00:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'), | ||
array(false, '2a01:198:603:0:396e:4789:8e99:890f', '::1'), | ||
array(true, '0:0:0:0:0:0:0:1', '::1'), | ||
array(false, '0:0:603:0:396e:4789:8e99:0001', '::1'), | ||
); | ||
} | ||
|
||
/** | ||
* @expectedException \RuntimeException | ||
*/ | ||
public function testAnIpv6WithOptionDisabledIpv6() | ||
{ | ||
if (defined('AF_INET6')) { | ||
$this->markTestSkipped('Only works when PHP is compiled with the option "disable-ipv6".'); | ||
} | ||
|
||
IpUtils::checkIp('2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'); | ||
} | ||
} |
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