-
-
Save miken32/f402317ce71bf7156e4a4a645e6a500b to your computer and use it in GitHub Desktop.
<?php | |
namespace App\Rules; | |
use Closure; | |
use Illuminate\Contracts\Validation\ValidationRule; | |
use const FILTER_FLAG_IPV4; | |
use const FILTER_FLAG_IPV6; | |
use const FILTER_VALIDATE_INT; | |
use const FILTER_VALIDATE_IP; | |
class Cidr implements ValidationRule | |
{ | |
/** @var bool whether or not the rule has been called with network constraints */ | |
private bool $has_bits; | |
/** | |
* @param int|null $ipv4minbits The minimum number of bits allowed in an IPv4 network | |
* @param int|null $ipv4maxbits The maximum number of bits allowed in an IPv4 network | |
* @param int|null $ipv6minbits The minimum number of bits allowed in an IPv6 network | |
* @param int|null $ipv6maxbits The maximum number of bits allowed in an IPv6 network | |
*/ | |
public function __construct( | |
public ?int $ipv4minbits = null, | |
public ?int $ipv4maxbits = null, | |
public ?int $ipv6minbits = null, | |
public ?int $ipv6maxbits = null, | |
) | |
{ | |
$this->has_bits = func_num_args() > 0; | |
} | |
/** | |
* @param string $attribute The attribute being validated | |
* @param mixed $value The current value of the attribute | |
* @param Closure $fail Closure to be run in case of failure | |
* @return void | |
*/ | |
public function validate(string $attribute, mixed $value, Closure $fail): void | |
{ | |
$mask = null; | |
$valid_mask = true; | |
if (str_contains($value, "/")) { | |
[$value, $mask] = explode("/", $value); | |
} elseif ($this->has_bits) { | |
// if we specify a bit constraint, assume the bits are required | |
$fail($this->message()); | |
} | |
if (str_contains($value, ":")) { | |
// ipv6 | |
if ($mask !== null) { | |
$valid_mask = filter_var( | |
$mask, | |
FILTER_VALIDATE_INT, | |
["options" => ["min_range" => $this->ipv6minbits ?? 0, "max_range" => $this->ipv6maxbits ?? 128]] | |
); | |
} | |
$valid_address = filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6); | |
} else { | |
// ipv4 | |
if ($mask !== null) { | |
$valid_mask = filter_var( | |
$mask, | |
FILTER_VALIDATE_INT, | |
["options" => ["min_range" => $this->ipv4minbits ?? 0, "max_range" => $this->ipv4maxbits ?? 32]] | |
); | |
if ($valid_mask) { | |
$long = ip2long($value); | |
$mask = -1 << (32 - $mask); | |
$valid_mask = long2ip($long & $mask) === $value; | |
} | |
} | |
$valid_address = filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); | |
} | |
if (!$valid_address || !$valid_mask) { | |
$fail($this->message()); | |
} | |
} | |
public function message(): string | |
{ | |
return !$this->has_bits | |
? __("The :attribute must be a valid IP address or CIDR subnet.") | |
: sprintf( | |
__("The :attribute must be a valid CIDR subnet with a mask of %d-%d (IPv4) or %d-%d (IPv6) bits."), | |
$this->ipv4minbits ?? 0, | |
$this->ipv4maxbits ?? 32, | |
$this->ipv6minbits ?? 0, | |
$this->ipv6maxbits ?? 128 | |
); | |
} | |
} |
Appreciate this, I've used the basis but have a version/rule to check if an IP is in one or more CIDR subnets, not sure if it'd be useful to chuck a link on here or if you'd find that useful.
I think this could be cool as a little package like https://github.com/Propaganistas/Laravel-Phone
@miken32 would you be up for collab on this? i.e. if I turned it into a similar package + co-maintain .. ?
how is it going to put it into a repo guys?
how is it going to put it into a repo guys?
Are you keen for a package then?
how is it going to put it into a repo guys?
Are you keen for a package then?
sure
wait did we move anywhere with a repo? @miken32 since you are the author that would makes sense for you to do it...
Yeah I can do that @justasSendrauskas give me a couple of days
@justasSendrauskas @jonnott @lrljoe I put up a package miken32/network-rules
if you want to have a look. Consolidated a bunch of one-off code I was using internally and added a bunch of new validations as well. Still marked as pre-release for now.
@miken32 brilliant! thank you very much
Very excited for this!
Sweet, I've grabbed your new version. Thnx!