in src/main/java/org/apache/commons/validator/routines/InetAddressValidator.java [134:220]
public boolean isValidInet6Address(String inet6Address) {
String[] parts;
// remove prefix size. This will appear after the zone id (if any)
parts = inet6Address.split("/", -1);
if (parts.length > 2) {
return false; // can only have one prefix specifier
}
if (parts.length == 2) {
if (!DIGITS_PATTERN.matcher(parts[1]).matches()) {
return false; // not a valid number
}
final int bits = Integer.parseInt(parts[1]); // cannot fail because of RE check
if (bits < 0 || bits > MAX_BYTE) {
return false; // out of range
}
}
// remove zone-id
parts = parts[0].split("%", -1);
// The id syntax is implementation independent, but it presumably cannot allow:
// whitespace, '/' or '%'
if ((parts.length > 2) || (parts.length == 2 && !ID_CHECK_PATTERN.matcher(parts[1]).matches())) {
return false; // invalid id
}
inet6Address = parts[0];
final boolean containsCompressedZeroes = inet6Address.contains("::");
if (containsCompressedZeroes && inet6Address.indexOf("::") != inet6Address.lastIndexOf("::")) {
return false;
}
final boolean startsWithCompressed = inet6Address.startsWith("::");
final boolean endsWithCompressed = inet6Address.endsWith("::");
final boolean endsWithSep = inet6Address.endsWith(":");
if (inet6Address.startsWith(":") && !startsWithCompressed || endsWithSep && !endsWithCompressed) {
return false;
}
String[] octets = inet6Address.split(":");
if (containsCompressedZeroes) {
final List<String> octetList = new ArrayList<>(Arrays.asList(octets));
if (endsWithCompressed) {
// String.split() drops ending empty segments
octetList.add("");
} else if (startsWithCompressed && !octetList.isEmpty()) {
octetList.remove(0);
}
octets = octetList.toArray(new String[0]);
}
if (octets.length > IPV6_MAX_HEX_GROUPS) {
return false;
}
int validOctets = 0;
int emptyOctets = 0; // consecutive empty chunks
for (int index = 0; index < octets.length; index++) {
final String octet = octets[index];
if (GenericValidator.isBlankOrNull(octet)) {
emptyOctets++;
if (emptyOctets > 1) {
return false;
}
} else {
emptyOctets = 0;
// Is last chunk an IPv4 address?
if (index == octets.length - 1 && octet.contains(".")) {
if (!isValidInet4Address(octet)) {
return false;
}
validOctets += 2;
continue;
}
if (octet.length() > IPV6_MAX_HEX_DIGITS_PER_GROUP) {
return false;
}
int octetInt = 0;
try {
octetInt = Integer.parseInt(octet, BASE_16);
} catch (final NumberFormatException e) {
return false;
}
if (octetInt < 0 || octetInt > MAX_UNSIGNED_SHORT) {
return false;
}
}
validOctets++;
}
if (validOctets > IPV6_MAX_HEX_GROUPS || validOctets < IPV6_MAX_HEX_GROUPS && !containsCompressedZeroes) {
return false;
}
return true;
}