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 = "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";
52
53
54 private static final int IPV6_MAX_HEX_GROUPS = 8;
55
56
57 private static final int IPV6_MAX_HEX_DIGITS_PER_GROUP = 4;
58
59
60
61
62 private static final InetAddressValidator VALIDATOR = new InetAddressValidator();
63
64 private static final Pattern DIGITS_PATTERN = Pattern.compile("\\d{1,3}");
65
66 private static final Pattern ID_CHECK_PATTERN = Pattern.compile("[^\\s/%]+");
67
68
69 private static final RegexValidator IPV4_VALIDATOR = new RegexValidator(IPV4_REGEX);
70
71
72
73
74
75
76 public static InetAddressValidator getInstance() {
77 return VALIDATOR;
78 }
79
80
81
82
83 public InetAddressValidator() {
84
85 }
86
87
88
89
90
91
92
93 public boolean isValid(final String inetAddress) {
94 return isValidInet4Address(inetAddress) || isValidInet6Address(inetAddress);
95 }
96
97
98
99
100
101
102
103 public boolean isValidInet4Address(final String inet4Address) {
104
105 final String[] groups = IPV4_VALIDATOR.match(inet4Address);
106 if (groups == null) {
107 return false;
108 }
109
110 for (final String ipSegment : groups) {
111 if (GenericValidator.isBlankOrNull(ipSegment)) {
112 return false;
113 }
114 int iIpSegment = 0;
115 try {
116 iIpSegment = Integer.parseInt(ipSegment);
117 } catch (final NumberFormatException e) {
118 return false;
119 }
120 if (iIpSegment > IPV4_MAX_OCTET_VALUE || ipSegment.length() > 1 && ipSegment.startsWith("0")) {
121 return false;
122 }
123 }
124 return true;
125 }
126
127
128
129
130
131
132
133
134 public boolean isValidInet6Address(String inet6Address) {
135 String[] parts;
136
137 parts = inet6Address.split("/", -1);
138 if (parts.length > 2) {
139 return false;
140 }
141 if (parts.length == 2) {
142 if (!DIGITS_PATTERN.matcher(parts[1]).matches()) {
143 return false;
144 }
145 final int bits = Integer.parseInt(parts[1]);
146 if (bits < 0 || bits > MAX_BYTE) {
147 return false;
148 }
149 }
150
151 parts = parts[0].split("%", -1);
152
153
154 if (parts.length > 2 || parts.length == 2 && !ID_CHECK_PATTERN.matcher(parts[1]).matches()) {
155 return false;
156 }
157 inet6Address = parts[0];
158 final boolean containsCompressedZeroes = inet6Address.contains("::");
159 if (containsCompressedZeroes && inet6Address.indexOf("::") != inet6Address.lastIndexOf("::")) {
160 return false;
161 }
162 final boolean startsWithCompressed = inet6Address.startsWith("::");
163 final boolean endsWithCompressed = inet6Address.endsWith("::");
164 final boolean endsWithSep = inet6Address.endsWith(":");
165 if (inet6Address.startsWith(":") && !startsWithCompressed || endsWithSep && !endsWithCompressed) {
166 return false;
167 }
168 String[] octets = inet6Address.split(":");
169 if (containsCompressedZeroes) {
170 final List<String> octetList = new ArrayList<>(Arrays.asList(octets));
171 if (endsWithCompressed) {
172
173 octetList.add("");
174 } else if (startsWithCompressed && !octetList.isEmpty()) {
175 octetList.remove(0);
176 }
177 octets = octetList.toArray(new String[0]);
178 }
179 if (octets.length > IPV6_MAX_HEX_GROUPS) {
180 return false;
181 }
182 int validOctets = 0;
183 int emptyOctets = 0;
184 for (int index = 0; index < octets.length; index++) {
185 final String octet = octets[index];
186 if (GenericValidator.isBlankOrNull(octet)) {
187 emptyOctets++;
188 if (emptyOctets > 1) {
189 return false;
190 }
191 } else {
192 emptyOctets = 0;
193
194 if (index == octets.length - 1 && octet.contains(".")) {
195 if (!isValidInet4Address(octet)) {
196 return false;
197 }
198 validOctets += 2;
199 continue;
200 }
201 if (octet.length() > IPV6_MAX_HEX_DIGITS_PER_GROUP) {
202 return false;
203 }
204 int octetInt = 0;
205 try {
206 octetInt = Integer.parseInt(octet, BASE_16);
207 } catch (final NumberFormatException e) {
208 return false;
209 }
210 if (octetInt < 0 || octetInt > MAX_UNSIGNED_SHORT) {
211 return false;
212 }
213 }
214 validOctets++;
215 }
216 if (validOctets > IPV6_MAX_HEX_GROUPS || validOctets < IPV6_MAX_HEX_GROUPS && !containsCompressedZeroes) {
217 return false;
218 }
219 return true;
220 }
221 }