1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.validator.routines;
19
20 import java.io.Serializable;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.List;
24 import java.util.regex.Pattern;
25
26 import org.apache.commons.validator.GenericValidator;
27
28
29
30
31
32
33
34
35
36
37
38
39 public class InetAddressValidator implements Serializable {
40
41 private static final int MAX_BYTE = 128;
42
43 private static final int IPV4_MAX_OCTET_VALUE = 255;
44
45 private static final int MAX_UNSIGNED_SHORT = 0xffff;
46
47 private static final int BASE_16 = 16;
48
49 private static final long serialVersionUID = -919201640201914789L;
50
51 private static final String IPV4_REGEX =
52 "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";
53
54
55 private static final int IPV6_MAX_HEX_GROUPS = 8;
56
57
58 private static final int IPV6_MAX_HEX_DIGITS_PER_GROUP = 4;
59
60
61
62
63 private static final InetAddressValidator VALIDATOR = new InetAddressValidator();
64
65 private static final Pattern DIGITS_PATTERN = Pattern.compile("\\d{1,3}");
66
67 private static final Pattern ID_CHECK_PATTERN = Pattern.compile("[^\\s/%]+");
68
69
70
71
72 public static InetAddressValidator getInstance() {
73 return VALIDATOR;
74 }
75
76
77 private final RegexValidator ipv4Validator = new RegexValidator(IPV4_REGEX);
78
79
80
81
82
83
84 public boolean isValid(final String inetAddress) {
85 return isValidInet4Address(inetAddress) || isValidInet6Address(inetAddress);
86 }
87
88
89
90
91
92
93 public boolean isValidInet4Address(final String inet4Address) {
94
95 final String[] groups = ipv4Validator.match(inet4Address);
96 if (groups == null) {
97 return false;
98 }
99
100 for (final String ipSegment : groups) {
101 if (GenericValidator.isBlankOrNull(ipSegment)) {
102 return false;
103 }
104 int iIpSegment = 0;
105 try {
106 iIpSegment = Integer.parseInt(ipSegment);
107 } catch (final NumberFormatException e) {
108 return false;
109 }
110 if (iIpSegment > IPV4_MAX_OCTET_VALUE) {
111 return false;
112 }
113 if (ipSegment.length() > 1 && ipSegment.startsWith("0")) {
114 return false;
115 }
116 }
117 return true;
118 }
119
120
121
122
123
124
125
126
127 public boolean isValidInet6Address(String inet6Address) {
128 String[] parts;
129
130 parts = inet6Address.split("/", -1);
131 if (parts.length > 2) {
132 return false;
133 }
134 if (parts.length == 2) {
135 if (!DIGITS_PATTERN.matcher(parts[1]).matches()) {
136 return false;
137 }
138 final int bits = Integer.parseInt(parts[1]);
139 if (bits < 0 || bits > MAX_BYTE) {
140 return false;
141 }
142 }
143
144 parts = parts[0].split("%", -1);
145 if (parts.length > 2) {
146 return false;
147 }
148
149
150 if (parts.length == 2 && !ID_CHECK_PATTERN.matcher(parts[1]).matches()) {
151 return false;
152 }
153 inet6Address = parts[0];
154 final boolean containsCompressedZeroes = inet6Address.contains("::");
155 if (containsCompressedZeroes && inet6Address.indexOf("::") != inet6Address.lastIndexOf("::")) {
156 return false;
157 }
158 if (inet6Address.startsWith(":") && !inet6Address.startsWith("::")
159 || inet6Address.endsWith(":") && !inet6Address.endsWith("::")) {
160 return false;
161 }
162 String[] octets = inet6Address.split(":");
163 if (containsCompressedZeroes) {
164 final List<String> octetList = new ArrayList<>(Arrays.asList(octets));
165 if (inet6Address.endsWith("::")) {
166
167 octetList.add("");
168 } else if (inet6Address.startsWith("::") && !octetList.isEmpty()) {
169 octetList.remove(0);
170 }
171 octets = octetList.toArray(new String[0]);
172 }
173 if (octets.length > IPV6_MAX_HEX_GROUPS) {
174 return false;
175 }
176 int validOctets = 0;
177 int emptyOctets = 0;
178 for (int index = 0; index < octets.length; index++) {
179 final String octet = octets[index];
180 if (GenericValidator.isBlankOrNull(octet)) {
181 emptyOctets++;
182 if (emptyOctets > 1) {
183 return false;
184 }
185 } else {
186 emptyOctets = 0;
187
188 if (index == octets.length - 1 && octet.contains(".")) {
189 if (!isValidInet4Address(octet)) {
190 return false;
191 }
192 validOctets += 2;
193 continue;
194 }
195 if (octet.length() > IPV6_MAX_HEX_DIGITS_PER_GROUP) {
196 return false;
197 }
198 int octetInt = 0;
199 try {
200 octetInt = Integer.parseInt(octet, BASE_16);
201 } catch (final NumberFormatException e) {
202 return false;
203 }
204 if (octetInt < 0 || octetInt > MAX_UNSIGNED_SHORT) {
205 return false;
206 }
207 }
208 validOctets++;
209 }
210 if (validOctets > IPV6_MAX_HEX_GROUPS || validOctets < IPV6_MAX_HEX_GROUPS && !containsCompressedZeroes) {
211 return false;
212 }
213 return true;
214 }
215 }