duanqin7791 2016-01-19 17:38
浏览 97
已采纳

通过PHP缩短以0结尾的IPv6地址

I'm using an IPv6 class found on GitHub to do some IP manipulation but I noticed that there is an issue with shortening certain address, typically ending in 0.

When I enter the address 2001::6dcd:8c74:0:0:0:0, it results in 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::::
  • 写回答

1条回答 默认 最新

  • douwen3362 2016-01-19 17:38
    关注

    Without that problem line at the bottom you get 2001::6dcd:8c74:0:0:0:0. Now, before the leading 0's are all replaced, the function checks to see if the address ends in :0 before removing all leading 0's.

    if (substr($address, -2) != ':0') {
        $new_address = preg_replace("/:0{1,3}/", ":", $address);
    } else {
        $new_address = $address;
    }
    

    Another check is added to catch other possible valid IPv6 addresses from being malformed.

    if (isset($new_parts)) {
        if (count($new_parts) < 8 && array_pop($new_parts) == '') {
            $new_address .= ':0';
        }
    }
    

    The new full function looks like this:

    // 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
    

    It's not the cleanest solution and could possibly have holes in its logic depending on what the address is. If I find any other issues with it I will update this question/answer.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 训练的多模态特征融合模型准确度很低怎么办
  • ¥15 kylin启动报错log4j类冲突
  • ¥15 超声波模块测距控制点灯,灯的闪烁很不稳定,经过调试发现测的距离偏大
  • ¥15 import arcpy出现importing _arcgisscripting 找不到相关程序
  • ¥15 onvif+openssl,vs2022编译openssl64
  • ¥15 iOS 自定义输入法-第三方输入法
  • ¥15 很想要一个很好的答案或提示
  • ¥15 扫描项目中发现AndroidOS.Agent、Android/SmsThief.LI!tr
  • ¥15 怀疑手机被监控,请问怎么解决和防止
  • ¥15 Qt下使用tcp获取数据的详细操作