我正在写一个HTTP解析库(因为我在纯D中找不到好的),我需要能够验证IP地址(对于URI字段),所以我写了几个函数来验证IP地址:
对于IPv4:
bool isIPv4(string addr) {
int parts;
ulong idx;
foreach (i, c; addr) {
if (c == '.') {
if (i == 0) {
return false;
}
if (to!int(addr[idx..i]) > 255) {
return false;
}
parts++;
if (parts > 3) {
return false;
}
idx = i + 1;
} else if (!isDigit(c)) {
return false;
}
}
if (to!int(addr[idx..addr.length]) > 255) {
return false;
}
if (parts != 3) {
return false;
}
return true;
}
对于IPv6:
bool isIPv6(string addr) {
bool isColon, hasSeparator, hasIPv4;
int leftChunks, rightChunks, digits;
foreach (i, c; addr) {
if (isHexDigit(c)) {
digits = isColon ? 1 : digits + 1;
isColon = false;
if (digits == 1) {
if (hasSeparator) {
rightChunks++;
} else {
leftChunks++;
}
} else if (digits > 4) {
return false;
}
} else if (c == ':') {
if (isColon) {
// multiple :: separators not allowed
// as is :::
if (hasSeparator) {
return false;
}
hasSeparator = true;
} else {
isColon = true;
}
} else if (c == '.') {
if (hasSeparator) {
rightChunks--;
} else {
leftChunks--;
}
if (!isIPv4(addr[i - digits .. addr.length])) {
return false;
}
hasIPv4 = true;
break;
}
}
if (hasIPv4) {
if (hasSeparator) {
if (rightChunks + leftChunks > 5) {
return false;
}
} else if (leftChunks != 6) {
return false;
}
} else if (digits > 0) {
if (hasSeparator) {
if (rightChunks + leftChunks > 7) {
return false;
}
} else if (leftChunks != 8) {
return false;
}
}
return true;
}
我最初尝试为IPv6制作一个正则表达式,但这很痛苦,特别是因为有很多特殊情况(::
),我想我遇到了一个正则表达式编译错误,因为它太长了。显然,我想用一些标准函数为我做这个。
FWIW,我使用std.arrays.split实现了IPv4验证器,然后我决定这样做,因为否则我将不得不检测或捕获std.conv.to!int中的异常。
非常感谢!
注意
我最终想尝试获取一些我写入Phobos的代码,所以我希望代码尽可能的稳定。
答案 0 :(得分:2)
答案 1 :(得分:1)
@tjameson:很久以前,我已经攻击了我自己的uri
模块。以下是代码:http://codepad.org/PBm5BEVP。我一直想回到那个模块,改进它,并在GitHub上提交一个pull请求,但从来没有时间去做... URI RFC也有一个正则表达式来解析URI中的IPv6地址,这绝对是一些东西我会输入这段代码。
答案 2 :(得分:0)
您可以使用OS提供的inet_pton()函数。它将解析一个地址并告诉你它是否错误。见http://www.kernel.org/doc/man-pages/online/pages/man3/inet_pton.3.html
它将解析IPv4和IPv6地址,并且inet_ntop()可用于将解析后的地址转换回其规范表示法。
答案 3 :(得分:0)
尝试:
的IPv4
/^(((2[0-4]|1\d|[1-9])?\d|25[0-5])(\.(?!$)|$)){4}$
的IPv6
/^((?=(?=(.*?::))\2(?!.+::))(::)?([\dA-F]{1,4}:(:|(?!$))|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:(?!$)|$))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])(\.(?!$)|$)){4})$/i
(使用ECMAscript语法)