Для проверки IP-адреса (формата) я в настоящее время использую это как часть чего-то, над чем я работаю - не уверен на 100%, что это все еще правильно - нужно добавить больше данных (и я неМне не нравится соглашение об именах, которое я использовал для закрытых членов - но это легко исправить с помощью рефакторинга):
class IPAddress {
//IP Address string
private $ip_address;
//IPv4 verification (RegExp insert)
private $match_ipv4;
//IPv6 verification (RegExp insert)
private $match_ipv6;
/**
* Constructor function
*
* The $sIPAddress parameter is optional -
* it allows you to set the IP address in
* the object at creation.
*
* @param string $sIPAddress
* @return void
*/
public function __construct($sIPAddress=null) {
//setup regexp inserts
//IPv4 decimal octets match
$sDecOctet = "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])";
//IPv4 match
$this->match_ipv4 = "({$sDecOctet}\.){3}{$sDecOctet}";
//Hex 16 match
$sH16 = "[0-9a-fA-F]{1,4}";
//Char32 match
$sLS32 = "({$sH16}:{$sH16}|{$this->match_ipv4})";
//IPv6 match
$this->match_ipv6 = "((({$sH16}:){6}"
. "|::({$sH16}:){5}"
. "|({$sH16})?::({$sH16}:){4}"
. "|(({$sH16}:){0,1}{$sH16})?::({$sH16}:){3}"
. "|(({$sH16}:){0,2}{$sH16})?::({$sH16}:){2}"
. "|(({$sH16}:){0,3}{$sH16})?::{$sH16}:"
. "|(({$sH16}:){0,4}{$sH16})?::"
. "){$sLS32}"
. "|((({$sH16}:){0,5}{$sH16})?::{$sH16}"
. "|(({$sH16}:){0,6}{$sH16})?::"
. "))";
//set the IP address if required
if(!is_null($sIPAddress)) {
$this->setIPAddress($sIPAddress);
}
}
/**
* IP Address setter
*
* Sets the IP address string - this can
* be either IPv4 or IPv6 format.
*
* @param string $sIPAddress
* @return void
*/
public function setIPAddress($sIPAddress) {
$this->ip_address = $sIPAddress;
}
/**
* IP Address getter
*
* Returns the IP address string - this
* can be either IPv4 or IPv6 format.
*
* @return string
*/
public function getIPAddress() {
return $this->ip_address;
}
/**
* IPv4 RegExp getter
*
* Returns Regular Expression used to
* validate IPv4 addresses.
*
* @return string
*/
public function getIPv4RegExp() {
return '/^' . $this->match_ipv4 . '$/';
}
/**
* IPv6 RegExp getter
*
* Returns the Regular Expression used to
* validate IPv6 addresses.
*
* @return string
*/
public function getIPv6RegExp() {
return '/^' . $this->match_ipv6 . '$/i';
}
/**
* IPv4 validation
*
* Validates the stored IP address
* against the IPv4 pattern and returns
* a boolean denoting whether the address
* if of IPv4 format or not.
*
* @return bool
*/
public function validateIPv4() {
return ip2long($this->ip_address) && ip2long($this->ip_address) !== -1 ? true : false;
}
/**
* IPv6 validation
*
* Validates the stored IP address
* against the IPv6 pattern and returns
* a boolean denoting whether the address
* if of IPv6 format or not.
*
* @return bool
*/
public function validateIPv6() {
return preg_match($this->getIPv6RegExp(), $this->ip_address) ? true : false;
}
/**
* General validity check
*
* Validates the stored IP address against
* both the IPv4 and IPv6 patterns - if
* EITHER matches then true is returned
* (it's a correctly formatted IP address).
*
* Otherwise it's not a valid IP address
* and false is returned.
*
* @return bool
*/
public function isValid() {
return $this->validateIPv4() || $this->validateIPv6() ? true : false;
}
/**
* Reserved state checker
*
* This method checks wheter the stored IP address
* is part of the local network range (i.e. it's in
* the private reserved IP address range)
*
* A boolean is returned denoting this reserved state
* unless the IP address itself is invalid - in which
* case null is returned.
*
* @return bool
*/
public function isReserved() {
//IPv4 format
if($this->validateIPv4()) {
return $this->_getIPv4IsReserved($this->ip_address);
}
//IPv6 format
elseif($this->validateIPv6()) {
//IPv4 masking
// this falls over if the IPv4 part is short-handed
// for instance ::ffff:192.0.2.128 can be written as ::ffff:c000:280
$reIPv4Masking = '/^((0{1,4}:){6}|(0{1,4}:){1,5}ffff:|::ffff:)(([0-9]{1,3}\.){3}[0-9]{1,3})/';
//standard reserved IPv6 addresses
//local loopback = 0:0:0:0:0:0:0:1 || ::1
if(preg_match('/^(0{1,4}:){1,7}1|::1|fc00:.*$/i', $this->ip_address)) {
return true;
}
//if this is really an IPv4 address stacked in IPv6...
elseif(preg_match($reIPv4Masking, $this->ip_address)) {
$sIPv4Address = preg_replace($reIPv4Masking, "$2", $this->ip_address);
return $this->_getIPv4IsReserved($sIPv4Address);
}
//not reserved
else {
return false;
}
}
//invalid format
else {
return null;
}
}
/**
* IPv4 reserved state checker
*
* Private method to determine whether an IPv4 address is in
* one of the reserved private brackets (e.g. it's probably local)
*
* Returns a boolean denoting whether it's a reserved IPv4 address
* or null should the IP address fail validation
*
* @param string $sIPv4Address
* @return bool
*/
private function _getIPv4IsReserved($sIPv4Address) {
$sIP = long2ip(ip2long($sIPv4Address));
$reIPv4 = '/([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/$'; //just a quick and dirty RegExp without sanity checking since we've already done that
if(preg_match($reIPv4, $sIP)) {
//break the IP address into parts and cast to integers
$iIPp1 = VParse::toInt(preg_replace($reIPv4, "$1", $sIP));
$iIPp2 = VParse::toInt(preg_replace($reIPv4, "$2", $sIP));
$iIPp3 = VParse::toInt(preg_replace($reIPv4, "$3", $sIP));
$iIPp4 = VParse::toInt(preg_replace($reIPv4, "$4", $sIP));
//check for reserved IP addresses
// 127.0.0.1 (local loopback)
// 10.0.0.0 - 10.255.255.255
// 172.16.0.0 - 172.31.255.255
// 192.168.0.0 - 192.168.255.255
if( ($iIPp1 == 127 && $iIPp2 == 0 && $iIPp3 == 0 && $iIPp4 == 1) || $iIPp1 == 10 || ($iIPp1 == 172 && $iIP2 >= 16 && $iIP2 <= 31) || ($iIPp1 == 192 && $iIPp2 == 168) ) {
return true;
}
//not part of the standard private IP address ranges
else {
return false;
}
}
//invalid format
else {
return null;
}
}
//end class
}
РЕДАКТИРОВАТЬ: только что заметил, что это зависит от моего класса синтаксического анализа VParse - вы можете в значительной степенизамените любой экземпляр VParse::toInt()
стандартными функциями приведения типа (int)
в PHP.