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