source: josm/trunk/src/org/openstreetmap/josm/data/validation/routines/EmailValidator.java@ 9853

Last change on this file since 9853 was 9853, checked in by Don-vip, 8 years ago

fix #12557 : update to Apache Commons Validator 1.5.0 + updates from trunk + unit/integration tests + anticipated patches to add missing TLDs and Country Codes from IANA

  • Property svn:eol-style set to native
File size: 7.6 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17package org.openstreetmap.josm.data.validation.routines;
18
19import static org.openstreetmap.josm.tools.I18n.tr;
20
21import java.util.regex.Matcher;
22import java.util.regex.Pattern;
23
24/**
25 * <p>Perform email validations.</p>
26 * <p>
27 * Based on a script by <a href="mailto:stamhankar@hotmail.com">Sandeep V. Tamhankar</a>
28 * http://javascript.internet.com
29 * </p>
30 * <p>
31 * This implementation is not guaranteed to catch all possible errors in an email address.
32 * </p>.
33 *
34 * @version $Revision: 1723573 $
35 * @since Validator 1.4
36 */
37public class EmailValidator extends AbstractValidator {
38
39 private static final String SPECIAL_CHARS = "\\p{Cntrl}\\(\\)<>@,;:'\\\\\\\"\\.\\[\\]";
40 private static final String VALID_CHARS = "(\\\\.)|[^\\s" + SPECIAL_CHARS + "]";
41 private static final String QUOTED_USER = "(\"(\\\\\"|[^\"])*\")";
42 private static final String WORD = "((" + VALID_CHARS + "|')+|" + QUOTED_USER + ")";
43
44 private static final String EMAIL_REGEX = "^\\s*?(.+)@(.+?)\\s*$";
45 private static final String IP_DOMAIN_REGEX = "^\\[(.*)\\]$";
46 private static final String USER_REGEX = "^\\s*" + WORD + "(\\." + WORD + ")*$";
47
48 private static final Pattern EMAIL_PATTERN = Pattern.compile(EMAIL_REGEX);
49 private static final Pattern IP_DOMAIN_PATTERN = Pattern.compile(IP_DOMAIN_REGEX);
50 private static final Pattern USER_PATTERN = Pattern.compile(USER_REGEX);
51
52 private static final int MAX_USERNAME_LEN = 64;
53
54 private final boolean allowLocal;
55 private final boolean allowTld;
56
57 /**
58 * Singleton instance of this class, which
59 * doesn't consider local addresses as valid.
60 */
61 private static final EmailValidator EMAIL_VALIDATOR = new EmailValidator(false, false);
62
63 /**
64 * Singleton instance of this class, which
65 * doesn't consider local addresses as valid.
66 */
67 private static final EmailValidator EMAIL_VALIDATOR_WITH_TLD = new EmailValidator(false, true);
68
69 /**
70 * Singleton instance of this class, which does
71 * consider local addresses valid.
72 */
73 private static final EmailValidator EMAIL_VALIDATOR_WITH_LOCAL = new EmailValidator(true, false);
74
75
76 /**
77 * Singleton instance of this class, which does
78 * consider local addresses valid.
79 */
80 private static final EmailValidator EMAIL_VALIDATOR_WITH_LOCAL_WITH_TLD = new EmailValidator(true, true);
81
82 /**
83 * Returns the Singleton instance of this validator.
84 *
85 * @return singleton instance of this validator.
86 */
87 public static EmailValidator getInstance() {
88 return EMAIL_VALIDATOR;
89 }
90
91 /**
92 * Returns the Singleton instance of this validator,
93 * with local validation as required.
94 *
95 * @param allowLocal Should local addresses be considered valid?
96 * @param allowTld Should TLDs be allowed?
97 * @return singleton instance of this validator
98 */
99 public static EmailValidator getInstance(boolean allowLocal, boolean allowTld) {
100 if (allowLocal) {
101 if (allowTld) {
102 return EMAIL_VALIDATOR_WITH_LOCAL_WITH_TLD;
103 } else {
104 return EMAIL_VALIDATOR_WITH_LOCAL;
105 }
106 } else {
107 if (allowTld) {
108 return EMAIL_VALIDATOR_WITH_TLD;
109 } else {
110 return EMAIL_VALIDATOR;
111 }
112 }
113 }
114
115 /**
116 * Returns the Singleton instance of this validator,
117 * with local validation as required.
118 *
119 * @param allowLocal Should local addresses be considered valid?
120 * @return singleton instance of this validator
121 */
122 public static EmailValidator getInstance(boolean allowLocal) {
123 return getInstance(allowLocal, false);
124 }
125
126 /**
127 * Protected constructor for subclasses to use.
128 *
129 * @param allowLocal Should local addresses be considered valid?
130 * @param allowTld Should TLDs be allowed?
131 */
132 protected EmailValidator(boolean allowLocal, boolean allowTld) {
133 super();
134 this.allowLocal = allowLocal;
135 this.allowTld = allowTld;
136 }
137
138 /**
139 * Protected constructor for subclasses to use.
140 *
141 * @param allowLocal Should local addresses be considered valid?
142 */
143 protected EmailValidator(boolean allowLocal) {
144 super();
145 this.allowLocal = allowLocal;
146 this.allowTld = false;
147 }
148
149 /**
150 * <p>Checks if a field has a valid e-mail address.</p>
151 *
152 * @param email The value validation is being performed on. A <code>null</code>
153 * value is considered invalid.
154 * @return true if the email address is valid.
155 */
156 @Override
157 public boolean isValid(String email) {
158 if (email == null) {
159 return false;
160 }
161
162 if (email.endsWith(".")) { // check this first - it's cheap!
163 setErrorMessage(tr("E-mail address is invalid"));
164 return false;
165 }
166
167 // Check the whole email address structure
168 Matcher emailMatcher = EMAIL_PATTERN.matcher(email);
169 if (!emailMatcher.matches()) {
170 setErrorMessage(tr("E-mail address is invalid"));
171 return false;
172 }
173
174 String username = emailMatcher.group(1);
175 if (!isValidUser(username)) {
176 setErrorMessage(tr("E-mail address contains an invalid username: {0}", username));
177 return false;
178 }
179
180 String domain = emailMatcher.group(2);
181 if (!isValidDomain(domain)) {
182 setErrorMessage(tr("E-mail address contains an invalid domain: {0}", domain));
183 return false;
184 }
185
186 return true;
187 }
188
189 /**
190 * Returns true if the domain component of an email address is valid.
191 *
192 * @param domain being validated, may be in IDN format
193 * @return true if the email address's domain is valid.
194 */
195 protected boolean isValidDomain(String domain) {
196 // see if domain is an IP address in brackets
197 Matcher ipDomainMatcher = IP_DOMAIN_PATTERN.matcher(domain);
198
199 if (ipDomainMatcher.matches()) {
200 InetAddressValidator inetAddressValidator =
201 InetAddressValidator.getInstance();
202 return inetAddressValidator.isValid(ipDomainMatcher.group(1));
203 }
204 // Domain is symbolic name
205 DomainValidator domainValidator =
206 DomainValidator.getInstance(allowLocal);
207 if (allowTld) {
208 return domainValidator.isValid(domain) || (!domain.startsWith(".") && domainValidator.isValidTld(domain));
209 } else {
210 return domainValidator.isValid(domain);
211 }
212 }
213
214 /**
215 * Returns true if the user component of an email address is valid.
216 *
217 * @param user being validated
218 * @return true if the user name is valid.
219 */
220 protected boolean isValidUser(String user) {
221
222 if (user == null || user.length() > MAX_USERNAME_LEN) {
223 return false;
224 }
225
226 return USER_PATTERN.matcher(user).matches();
227 }
228
229}
Note: See TracBrowser for help on using the repository browser.