*/ /** Manage the IP addresses conversions */ class ipaddresses { /** Return true if the provided IP address is valid (IPv4 or IPv6) */ public function validIPAddress ($ip) { if (!is_string ($ip) || $ip === "") throw new \Exception (dgettext("domframework", "Invalid IP address"), 500); $rc = $this->validIPv4Address ($ip); if ($rc === TRUE) return TRUE; $rc = $this->validIPv6Address ($ip); return $rc; } /** Return true if the provided IP address is valid and is IPv4 */ public function validIPv4Address ($ip) { if (!is_string ($ip) || $ip === "") throw new \Exception (dgettext("domframework", "Invalid IPv4 address"), 500); $rc = filter_var ($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); if ($rc ===FALSE) return FALSE; return TRUE; } /** Return true if the provided IP address is valid and is IPv6 */ public function validIPv6Address ($ip) { if (!is_string ($ip) || $ip === "") throw new \Exception (dgettext("domframework", "Invalid IPv6 address"), 500); $rc = filter_var ($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6); if ($rc ===FALSE) return FALSE; return TRUE; } /** Return the IPv6 uncompressed (all the fields exists). They are not filled by zeros If the provided IP is IPv4, there is no change applied Return False if the parameter is invalid Based on http://www.weberdev.com/get_example.php3?ExampleID=3921 */ public function uncompressIPv6 ($ip) { if (! is_string ($ip) || $ip === "") throw new \Exception (dgettext("domframework", "Invalid IP address"), 500); if (strstr ($ip,"::")) { $e = explode (":", $ip); // Case where :: is in start if ($e[0] === "") $e[0] = "0"; // Case where :: is in end if ($e[count ($e)-1] === "") $e[count ($e)-1] = "0"; $s = 8 - count ($e); foreach ($e as $key=>$val) { if ($val === "") { for ($i=0 ; $i<=$s ; $i++) $newipv6[] = 0; } else { $newipv6[] = $val; } } $ip = implode (":", $newipv6); } return $ip; } /* Get an IPv6 address with the format x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x and return it with format xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx Return false if the IP provided is not complete */ public function groupIPv6 ($ipv6) { if (! is_string ($ipv6) || $ipv6 === "") throw new \Exception (dgettext("domframework", "Invalid IPv6 address"), 500); if (substr_count ($ipv6, ".") !== 31) throw new \Exception (dgettext("domframework", "Invalid IPv6 address"), 500); $ipv6 = str_replace (".", "", $ipv6); $new = ""; for ($i = 0 ; $i < 32 ; $i++) { if ($i % 4 === 0 && $i !== 0) { $new .= ":"; } $new .= $ipv6[$i]; } return $new; } /* Return the IP adddress with filling the fields with the missing zeros. Valid only on IPv6 (but don't change anything if the provided address is IPv4) */ public function completeAddressWithZero ($ip) { if (! is_string ($ip) || $ip === "") throw new \Exception (dgettext("domframework", "Invalid IP address"), 500); $ip = $this->uncompressIPv6 ($ip); if (substr_count ($ip, ":") === 7) { // IPv6 $ips = explode (":", $ip); $ipnew = array(); foreach ($ips as $iptmp) { $ipnew[] = sprintf ("%04x", hexdec ($iptmp)); } return implode (":", $ipnew); } elseif (substr_count ($ip, ".") === 3) { // IPv4 return $ip; } throw new \Exception (dgettext("domframework", "Invalid IP address"), 500); } /* Return the provided CIDR in binary. Length must be in bytes. Return FALSE if the parameters are invalid */ public function cidrToBin ($cidr, $length) { if (! is_numeric ($cidr) || $cidr < 0 || $cidr > 128) throw new \Exception (dgettext("domframework", "Invalid CIDR"), 500); if (! is_numeric ($length) || $length < 1 || $length > 16) throw new \Exception (dgettext("domframework", "Invalid length"), 500); $val=""; for ( $i=0 ; $i<$length*8 ; $i++ ) { if ($i < $cidr) $val.="1"; else $val.="0"; } return pack ('H*', $this->str_base_convert ($val, 2, 16)); } /* Base conversion with 128 bits support for IPv6 Based on http://fr2.php.net/manual/en/function.base-convert.php#109660 */ public function str_base_convert($str, $frombase=10, $tobase=36) { $str = trim ($str); if (intval ($frombase) != 10) { $len = strlen ($str); $q = 0; for ($i=0; $i<$len; $i++) { $r = base_convert ($str[$i], $frombase, 10); $q = bcadd (bcmul ($q, $frombase), $r); } } else { $q = $str; } if (intval ($tobase) != 10) { $s = ''; while (bccomp ($q, '0', 0) > 0) { $r = intval (bcmod($q, $tobase)); $s = base_convert ($r, 10, $tobase) . $s; $q = bcdiv ($q, $tobase, 0); } } else { $s = $q; } return $s; } /* Reverse the provided IP address The IPv6 are returned in format : x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x */ function reverseIPAddress ($ipReverse) { if (!is_string ($ipReverse) || $ipReverse === "") throw new \Exception (dgettext("domframework", "Invalid IP address"), 500); $ipReverse = $this->completeAddressWithZero ($ipReverse); if (substr_count ($ipReverse, ":") === 7 && strlen ($ipReverse) == 39) { // Complete IPv6 with quadruplets and colon $ip = str_replace (":", "", $ipReverse); $tmp2 = array_reverse (str_split ($ip)); return implode (".", $tmp2); } elseif (substr_count ($ipReverse, ".") === 31) { // IPv6 with dots $tmp2 = explode (".", $ipReverse); $tmp2 = array_reverse ($tmp2); $ipnew = implode (".", $tmp2); return $ipnew; } elseif (substr_count ($ipReverse, ".") === 3) { // IPv4 $tmp2 = explode (".", $ipReverse); $tmp2 = array_reverse ($tmp2); $ipnew = implode (".", $tmp2); return $ipnew; } throw new \Exception (dgettext("domframework", "Invalid IP address"), 500); } /* This function return the CIDR associated to the provided netmask Ex. Return 24 for a mask 255.255.255.0 Work only in IPv4 Return FALSE if the provided IP is invalid */ public function netmask2cidr ($netmask) { $netmask = ip2long ($netmask); if ($netmask === FALSE) throw new \Exception (dgettext("domframework", "Invalid netmask"), 500); $netmask = decbin ($netmask); for ($i=0 ; $i<32 ; $i++) { if ($netmask{$i} == 0) { break; } } return $i; } }