I was recently asked how one might compare a given IP address against a range of IP addresses (assumedly in an elegant manner). I can’t really see why one would ever really need to do this kind of thing in php, but the chap in question explained that it was for the management of an IP address block-list.
anyway, here’s the code I wrote for it. After having done so, I wonder whether a natural text based comparison would have done the trick just as well (you’d still need the validation of course). It seems to work ok but i have not thought it through fully…
–edit–
my tek-tips colleague feherke, pointed out to me that there’s an even easier way of converting ip addresses to decimal notation. the script is accordingly edited
–/edit–
The code : …
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | <?php /** * class to compare an ip address against a given range of IPs * * sample usage * <code> $ipRangeCompare = new IPRangeCompare; $result = $ipRangeCompare->compare('212.143.142.1', '212.142.142.1', '212.143.140.255'); if ($ipRangeCompare->isError){ echo $ipRangeCompare->getErrorMessages(); exit; } else { if ($result){ echo "Confirmed that $ipRangeCompare->ip is within the range $ipRangeCompare->startIP - $ipRangeCompare->endIP"; } else { echo "Confirmed that $ipRangeCompare->ip is NOT within the range $ipRangeCompare->startIP - $ipRangeCompare->endIP"; } } * </code> */ class IPRangeCompare{ public $endIP; public $startIP; public $ip; public $errors; public $isError; /** * constructor method * @return */ public function __construct(){ $this->flush(); } /** * public method that kick starts the engine. * * @return bool - true if the IP is in the provided range, false otherwise * * @param object $startIP * @param object $endIP * @param object $ip */ public function compare ($startIP, $endIP, $ip){ $this->flush(); $this->startIP = $startIP; $this->endIP = $endIP; $this->ip = $ip; if (!$this->isValidIP($this->startIP) || !$this->isValidIP($this->endIP) || !$this->isValidIP($this->ip)){ $this->setError('IP address provided is not valid'); return false; } $this->startIPDecimal = $this->getDecimalIP($this->startIP); $this->endIPDecimal = $this->getDecimalIP($this->endIP); $this->ipDecimal = $this->getDecimalIP($this->ip); $this->checkIPDirection(); $match = ($this->ipDecimal >= $this->startIPDecimal) && ($this->ipDecimal <= $this->endIPDecimal); return $match; } /** * public function to return the error messages * * @return string */ public function getErrorMessage(){ $return = ''; if ($this->isError){ foreach ($this->errors as $e){ $return .= "\r\n<div class=\"errorMessage\">$e</div>\r\n"; } } return $return; } /** * method to invert start and end ip addresses if they have been entered the wrong way around * * @return void */ private function checkIPDirection(){ if ($this->startIPDecimal > $this->endIPDecimal){ $temp = $this->endIPDecimal; $this->endIPDecimal = $this->startIPDecimal; $this->startIPDecimal = $temp; $temp = $this->endIP; $this->endIP = $this->startIP; $this->startIP = $temp; } } /** * private method to convert an octet based IP address to a decimal * * @return decimal IP address * @param string $ip */ private function getDecimalIP($ip){ return ip2long($ip); /* left in for historic reasons only $bits = explode ('.', $ip); //convert the octets to binary foreach ($bits as $bit){ $_bits[] = str_pad(decbin($bit), 8, '0', STR_PAD_LEFT); } //now implode the _bits $bin = implode('', $_bits); //convert to decimal $dec = bindec($bin); return $dec; */ } /** * private method for determining whether the ip address provided is in the right format * * @return bool: true for the right format, false otherwise * @param object $ip */ private function isValidIP($ip){ $pattern = '/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/ims'; $result = preg_match($pattern, $ip, $matches); if (!$result){ return false; } for($i=1; $i<=4; $i++){ if ($matches[$i] < 0 || $matches[$i] > 255){ return false; } } return true; } /** * private helper method to set error messages * * @return void * @param object $error */ private function setError($error){ $this->errors[] = $error; $this->isError = true; } /** * private method for zeroing the variables * @return */ private function flush(){ $this->errors = array(); $this->startIP = $this->endIP = $this->ip = null; $this->isError= false; } } ?> |