我正在使用an IPv6 class found on GitHub进行一些IP操作,但我注意到缩短某些地址存在问题,通常以0结尾。
当我输入地址2001::6dcd:8c74:0:0:0:0
时,会产生2001::6dcd:8c74::::
。
$address = '2001::6dcd:8c74:0:0:0:0';
// Check to see if address is already compacted
if (strpos($address, '::') === FALSE) {
$parts = explode(':', $address);
$new_parts = array();
$ignore = FALSE;
$done = FALSE;
for ($i = 0; $i < count($parts); $i++) {
if (intval(hexdec($parts[$i])) === 0 && $ignore == FALSE && $done == FALSE) {
$ignore = TRUE;
$new_parts[] = '';
if ($i == 0) {
$new_parts = '';
}
} else if (intval(hexdec($parts[$i])) === 0 && $ignore == TRUE && $done == FALSE) {
continue;
} else if (intval(hexdec($parts[$i])) !== 0 && $ignore == TRUE) {
$done = TRUE;
$ignore = FALSE;
$new_parts[] = $parts[$i];
} else {
$new_parts[] = $parts[$i];
}
}
// Glue everything back together
$address = implode(':', $new_parts);
}
// Remove the leading 0's
$new_address = preg_replace("/:0{1,3}/", ":", $address);
// $this->compact = $new_address;
// return $this->compact;
echo $new_address; // Outputs: 2001::6dcd:8c74::::
答案 0 :(得分:0)
如果没有底部的问题行,您会获得2001::6dcd:8c74:0:0:0:0
。
现在,在前导0全部被替换之前,函数检查地址是否以0结尾,然后删除所有前导0。
if (substr($address, -2) != ':0') {
$new_address = preg_replace("/:0{1,3}/", ":", $address);
} else {
$new_address = $address;
}
添加了另一项检查以捕获其他可能的有效IPv6地址格式错误。
if (isset($new_parts)) {
if (count($new_parts) < 8 && array_pop($new_parts) == '') {
$new_address .= ':0';
}
}
新的完整功能如下所示:
// Check to see if address is already compacted
if (strpos($address, '::') === FALSE) {
$parts = explode(':', $address);
$new_parts = array();
$ignore = FALSE;
$done = FALSE;
for ($i = 0; $i < count($parts); $i++) {
if (intval(hexdec($parts[$i])) === 0 && $ignore == FALSE && $done == FALSE) {
$ignore = TRUE;
$new_parts[] = '';
if ($i == 0) {
$new_parts = '';
}
} else if (intval(hexdec($parts[$i])) === 0 && $ignore == TRUE && $done == FALSE) {
continue;
} else if (intval(hexdec($parts[$i])) !== 0 && $ignore == TRUE) {
$done = TRUE;
$ignore = FALSE;
$new_parts[] = $parts[$i];
} else {
$new_parts[] = $parts[$i];
}
}
// Glue everything back together
$address = implode(':', $new_parts);
}
// Check to see if this ends in a shortened :0 before replacing all
// leading 0's
if (substr($address, -2) != ':0') {
// Remove the leading 0's
$new_address = preg_replace("/:0{1,3}/", ":", $address);
} else {
$new_address = $address;
}
// Since new_parts isn't always set, check to see if it's set before
// trying to fix possibly broken shortened addresses ending in 0.
// (Ex: Trying to shorten 2001:19f0::0 will result in unset array)
if (isset($new_parts)) {
// Some addresses (Ex: starting addresses for a range) can end in
// all 0's resulting in the last value in the new parts array to be
// an empty string. Catch that case here and add the remaining :0
// for a complete shortened address.
if (count($new_parts) < 8 && array_pop($new_parts) == '') {
$new_address .= ':0';
}
}
// $this->compact = $new_address;
// return $this->compact;
echo $new_address; // Outputs: 2001::6dcd:8c74:0:0:0:0
这不是最干净的解决方案,并且可能在其逻辑中有漏洞,具体取决于地址。如果我发现任何其他问题,我会更新这个问题/答案。