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
27
28
29
30
31
32
33
34
35
36
37 public class InetAddressValidator implements Serializable {
38
39 private static final int MAX_BYTE = 128;
40
41 private static final int IPV4_MAX_OCTET_VALUE = 255;
42
43 private static final int MAX_UNSIGNED_SHORT = 0xffff;
44
45 private static final int BASE_16 = 16;
46
47 private static final long serialVersionUID = -919201640201914789L;
48
49 private static final String IPV4_REGEX =
50 "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";
51
52
53 private static final int IPV6_MAX_HEX_GROUPS = 8;
54
55
56 private static final int IPV6_MAX_HEX_DIGITS_PER_GROUP = 4;
57
58
59
60
61 private static final InetAddressValidator VALIDATOR = new InetAddressValidator();
62
63 private static final Pattern DIGITS_PATTERN = Pattern.compile("\\d{1,3}");
64
65 private static final Pattern ID_CHECK_PATTERN = Pattern.compile("[^\\s/%]+");
66
67
68
69
70 public static InetAddressValidator getInstance() {
71 return VALIDATOR;
72 }
73
74
75 private final RegexValidator ipv4Validator = new RegexValidator(IPV4_REGEX);
76
77
78
79
80
81
82 public boolean isValid(final String inetAddress) {
83 return isValidInet4Address(inetAddress) || isValidInet6Address(inetAddress);
84 }
85
86
87
88
89
90
91 public boolean isValidInet4Address(final String inet4Address) {
92
93 final String[] groups = ipv4Validator.match(inet4Address);
94
95 if (groups == null) {
96 return false;
97 }
98
99
100 for (final String ipSegment : groups) {
101 if (ipSegment == null || ipSegment.isEmpty()) {
102 return false;
103 }
104
105 int iIpSegment = 0;
106
107 try {
108 iIpSegment = Integer.parseInt(ipSegment);
109 } catch (final NumberFormatException e) {
110 return false;
111 }
112
113 if (iIpSegment > IPV4_MAX_OCTET_VALUE) {
114 return false;
115 }
116
117 if (ipSegment.length() > 1 && ipSegment.startsWith("0")) {
118 return false;
119 }
120
121 }
122
123 return true;
124 }
125
126
127
128
129
130
131
132
133 public boolean isValidInet6Address(String inet6Address) {
134 String[] parts;
135
136 parts = inet6Address.split("/", -1);
137 if (parts.length > 2) {
138 return false;
139 }
140 if (parts.length == 2) {
141 if (!DIGITS_PATTERN.matcher(parts[1]).matches()) {
142 return false;
143 }
144 final int bits = Integer.parseInt(parts[1]);
145 if (bits < 0 || bits > MAX_BYTE) {
146 return false;
147 }
148 }
149
150 parts = parts[0].split("%", -1);
151 if (parts.length > 2) {
152 return false;
153 }
154
155
156 if (parts.length == 2 && !ID_CHECK_PATTERN.matcher(parts[1]).matches()) {
157 return false;
158 }
159 inet6Address = parts[0];
160 final boolean containsCompressedZeroes = inet6Address.contains("::");
161 if (containsCompressedZeroes && inet6Address.indexOf("::") != inet6Address.lastIndexOf("::")) {
162 return false;
163 }
164 if (inet6Address.startsWith(":") && !inet6Address.startsWith("::")
165 || inet6Address.endsWith(":") && !inet6Address.endsWith("::")) {
166 return false;
167 }
168 String[] octets = inet6Address.split(":");
169 if (containsCompressedZeroes) {
170 final List<String> octetList = new ArrayList<>(Arrays.asList(octets));
171 if (inet6Address.endsWith("::")) {
172
173 octetList.add("");
174 } else if (inet6Address.startsWith("::") && !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 (octet.isEmpty()) {
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 }