1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.seasar.cubby.validator.validators;
17
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
22
23 import org.seasar.cubby.validator.MessageHelper;
24 import org.seasar.cubby.validator.ScalarFieldValidator;
25 import org.seasar.cubby.validator.ValidationContext;
26 import org.seasar.framework.util.StringUtil;
27
28
29
30
31
32
33
34
35
36
37 public class EmailValidator implements ScalarFieldValidator {
38
39 private static final String SPECIAL_CHARS = "\\(\\)<>@,;:\\\\\\\"\\.\\[\\]";
40 private static final String VALID_CHARS = "[^\\s" + SPECIAL_CHARS + "]";
41 private static final String QUOTED_USER = "(\"[^\"]*\")";
42 private static final String ATOM = VALID_CHARS + '+';
43 private static final String WORD = "(" + ATOM + "|" + QUOTED_USER + ")";
44
45 private static final String LEGAL_ASCII_PATTERN = "^[\\x00-\\x7F]+$";
46 private static final String EMAIL_PATTERN = "^(.+)@(.+)$";
47 private static final String IP_DOMAIN_PATTERN = "^(\\d{1,3})[.](\\d{1,3})[.](\\d{1,3})[.](\\d{1,3})$";
48
49 private static final String USER_PATTERN = "^" + WORD + "(\\." + WORD
50 + ")*$";
51 private static final String DOMAIN_PATTERN = "^" + ATOM + "(\\." + ATOM
52 + ")*$";
53 private static final String ATOM_PATTERN = "(" + ATOM + ")";
54
55
56
57
58 private final MessageHelper messageHelper;
59
60
61
62
63 public EmailValidator() {
64 this("valid.email");
65 }
66
67
68
69
70
71
72 public EmailValidator(final String messageKey) {
73 this.messageHelper = new MessageHelper(messageKey);
74 }
75
76 public void validate(final ValidationContext context, final Object value) {
77 if (value == null) {
78 return;
79 }
80 if (value instanceof String) {
81 final String email = (String) value;
82 if (StringUtil.isEmpty(email)) {
83 return;
84 }
85
86 boolean match = !email.endsWith(".");
87 if (match) {
88 final Pattern pattern = Pattern.compile(LEGAL_ASCII_PATTERN);
89 final Matcher matchAsciiPat = pattern.matcher(email);
90 match = matchAsciiPat.matches();
91 }
92
93 if (match) {
94 final Pattern pattern = Pattern.compile(EMAIL_PATTERN);
95 final Matcher matcher = pattern.matcher(email);
96 match = matcher.find();
97 if (match) {
98 if (isValidUser(matcher.group(1))
99 && isValidDomain(matcher.group(2))) {
100 return;
101 }
102 }
103 }
104 }
105
106 context.addMessageInfo(this.messageHelper.createMessageInfo());
107 }
108
109 private boolean isValidDomain(final String domain) {
110 Pattern pattern = Pattern.compile(IP_DOMAIN_PATTERN);
111 final Matcher ipAddressMatcher = pattern.matcher(domain);
112
113 if (ipAddressMatcher.find()) {
114 if (isValidIpAddress(ipAddressMatcher)) {
115 return true;
116 }
117 } else {
118 pattern = Pattern.compile(DOMAIN_PATTERN);
119 final Matcher domainMatcher = pattern.matcher(domain);
120 if (domainMatcher.matches()) {
121 if (isValidSymbolicDomain(domain)) {
122 return true;
123 }
124 }
125 }
126 return false;
127 }
128
129 private boolean isValidUser(final String user) {
130 final Pattern pattern = Pattern.compile(USER_PATTERN);
131 final Matcher userMatcher = pattern.matcher(user);
132 return userMatcher.matches();
133 }
134
135 private boolean isValidIpAddress(final Matcher ipAddressMatcher) {
136 for (int i = 1; i <= 4; i++) {
137 final String ipSegment = ipAddressMatcher.group(i);
138 if (ipSegment == null || ipSegment.length() <= 0) {
139 return false;
140 }
141
142 int iIpSegment = 0;
143
144 try {
145 iIpSegment = Integer.parseInt(ipSegment);
146 } catch (final NumberFormatException e) {
147 return false;
148 }
149
150 if (iIpSegment > 255) {
151 return false;
152 }
153
154 }
155 return true;
156 }
157
158 private boolean isValidSymbolicDomain(String domain) {
159 final List<String> domainSegments = new ArrayList<String>();
160 boolean match = true;
161 int i = 0;
162
163 final Pattern pattern = Pattern.compile(ATOM_PATTERN);
164 Matcher atomMatcher;
165 String ds;
166 while (match) {
167 atomMatcher = pattern.matcher(domain);
168 match = atomMatcher.find();
169 if (match) {
170 ds = atomMatcher.group(1);
171 domainSegments.add(ds);
172 final int l = ds.length() + 1;
173 domain = l >= domain.length() ? "" : domain.substring(l);
174
175 i++;
176 }
177 }
178
179 final int size = domainSegments.size();
180 if (size > 0) {
181 final String end = domainSegments.get(size - 1);
182 if (end.length() < 2 || end.length() > 4) {
183 return false;
184 }
185 }
186
187 if (domainSegments.size() < 2) {
188 return false;
189 }
190
191 return true;
192 }
193
194 }