diff options
| author | Simon Rettberg | 2026-04-29 14:12:46 +0200 |
|---|---|---|
| committer | Simon Rettberg | 2026-04-29 14:12:46 +0200 |
| commit | e9dd3b47e64f43d967a08cfc78efdffa95130a95 (patch) | |
| tree | 7320ae4709724ccd769ebf9a6368565640afe85d /inc/iputil.inc.php | |
| parent | [runmode] Add UUID to selected clients, close dropdown on select (diff) | |
| parent | [locationinfo] Use dedicated list permission for extdevices (diff) | |
| download | slx-admin-e9dd3b47e64f43d967a08cfc78efdffa95130a95.tar.gz slx-admin-e9dd3b47e64f43d967a08cfc78efdffa95130a95.tar.xz slx-admin-e9dd3b47e64f43d967a08cfc78efdffa95130a95.zip | |
Merge branch 'master' of git.openslx.org:openslx-ng/slx-admin
Diffstat (limited to 'inc/iputil.inc.php')
| -rw-r--r-- | inc/iputil.inc.php | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/inc/iputil.inc.php b/inc/iputil.inc.php index 9ec78f50..a9b79573 100644 --- a/inc/iputil.inc.php +++ b/inc/iputil.inc.php @@ -75,4 +75,95 @@ class IpUtil return ['start' => $ip & ~$bits, 'end' => $ip | $bits]; } + /** + * Normalizes an IP address to the canonical form. + * This supports all numeric IPv4, IPv6 and IPv4-mapped IPv6 addresses. + * As well as odd formats like IPv4 with multiple octets collapsed into a single one. + * Returns null if the address is invalid. + */ + public static function normalizeIp(string $ip): ?string + { + $ip = trim($ip); + if ($ip === '') + return null; + + // Check simple case first + $addr = @inet_pton($ip); + if ($addr !== false) { + $ret = inet_ntop($addr); + if (substr($ret, 0, 7) === '::ffff:') + return substr($ret, 7); + return $ret; + } + if (strpos($ip, ':') !== false) + return null; + + // IPv4 handling + // Support octal, hex and shorthand notations + $parts = explode('.', $ip); + $numParts = count($parts); + if ($numParts > 4) + return null; + + $values = []; + foreach ($parts as $part) { + $part = trim($part); + if ($part === '') + return null; + // Check for hex (0x...) + if (strncasecmp($part, '0x', 2) === 0) { + if (!ctype_xdigit(substr($part, 2))) + return null; + $values[] = hexdec($part); + } elseif ($part[0] === '0' && strlen($part) > 1) { + // Octal (starts with 0, but not just 0) + if (!preg_match('/^[0-7]+$/', $part)) + return null; + $values[] = octdec($part); + } else { + // Decimal + if (!preg_match('/^[0-9]+$/', $part)) + return null; + $values[] = (int)$part; + } + } + + if (empty($values)) + return null; + + // Validate values and handle shorthands + // Rules: + // 1 part: a (32 bits) + // 2 parts: a.b (a: 8 bits, b: 24 bits) + // 3 parts: a.b.c (a: 8 bits, b: 8 bits, c: 16 bits) + // 4 parts: a.b.c.d (a: 8 bits, b: 8 bits, c: 8 bits, d: 8 bits) + $ipv4int = 0; + for ($i = 0; $i < $numParts; $i++) { + $val = $values[$i]; + if ($i === $numParts - 1) { + // Last part + $max = (2 ** (8 * (4 - $i))) - 1; + if ($val < 0 || $val > $max) + return null; + $ipv4int = ($ipv4int << (8 * (4 - $i))) | (int)$val; + } else { + if ($val < 0 || $val > 255) + return null; + $ipv4int = ($ipv4int << 8) | (int)$val; + } + } + + return long2ip($ipv4int); + } + + /** + * Check if given string is a valid IP address. + * Supports all kinds of IP address formats that PHP supports, + * including IPv6, IPv4-mapped IPv6, IPv4-in-IPv6, etc. + */ + public static function isValidIp(string $ip): bool + { + return self::normalizeIp($ip) !== null; + } + } |
