~ubuntu-branches/ubuntu/oneiric/libcommons-validator-java/oneiric

« back to all changes in this revision

Viewing changes to src/share/org/apache/commons/validator/EmailValidator.java

  • Committer: Bazaar Package Importer
  • Author(s): Varun Hiremath, Kumar Appaiah, Varun Hiremath
  • Date: 2007-09-16 00:57:46 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20070916005746-r5xwnjm12ng9fbdf
Tags: 1:1.3.1-1
[ Kumar Appaiah ]
* New upstream release.
* New uploaders: Varun Hiremath and Kumar Appaiah, removed Wolfgang Baer
* Use upstream's conf directory for configuration and DTDs.
* Use a custom ant.properties to avoid downloads.
* Use DEB_UPSTREAM_VERSION in rules instead of versions in rules for symlinking.

[ Varun Hiremath ]
* debian/control:
  + Add rhino to Build-Depends-Indep and Depends.
  + Add XS-Vcs-{Svn, Browser} headers.
  + Depend on java-gcj-compat instead of kaffe.
* debian/compat: switch to 5
* Remove debian/patches and remove RELEASE-NOTES.txt in debian/rules.
* Add debian/orig-tar.sh to remove CRLF line terminators from upstream files.
* debian/rules: implement get-orig-source
* debian/watch: switch to version 3 and call debian/orig-tar.sh

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * $Header: /home/cvs/jakarta-commons/validator/src/share/org/apache/commons/validator/EmailValidator.java,v 1.12 2004/02/21 17:10:29 rleland Exp $
3
 
 * $Revision: 1.12 $
4
 
 * $Date: 2004/02/21 17:10:29 $
5
 
 *
6
 
 * ====================================================================
7
 
 * Copyright 2001-2004 The Apache Software Foundation
8
 
 *
9
 
 * Licensed under the Apache License, Version 2.0 (the "License");
10
 
 * you may not use this file except in compliance with the License.
11
 
 * You may obtain a copy of the License at
12
 
 *
13
 
 *     http://www.apache.org/licenses/LICENSE-2.0
14
 
 *
15
 
 * Unless required by applicable law or agreed to in writing, software
16
 
 * distributed under the License is distributed on an "AS IS" BASIS,
17
 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
 
 * See the License for the specific language governing permissions and
19
 
 * limitations under the License.
20
 
 */
21
 
 
22
 
package org.apache.commons.validator;
23
 
 
24
 
import org.apache.oro.text.perl.Perl5Util;
25
 
 
26
 
/**
27
 
 * <p>Perform email validations.</p>
28
 
 * <p>
29
 
 * This class is a Singleton; you can retrieve the instance via the getInstance() method.
30
 
 * </p>
31
 
 * <p>
32
 
 * Based on a script by <a href="mailto:stamhankar@hotmail.com">Sandeep V. Tamhankar</a>
33
 
 * http://javascript.internet.com
34
 
 * </p>
35
 
 *
36
 
 * @since Validator 1.1
37
 
 */
38
 
public class EmailValidator {
39
 
 
40
 
    private static final String SPECIAL_CHARS = "\\(\\)<>@,;:\\\\\\\"\\.\\[\\]";
41
 
    private static final String VALID_CHARS = "[^\\s" + SPECIAL_CHARS + "]";
42
 
    private static final String QUOTED_USER = "(\"[^\"]*\")";
43
 
    private static final String ATOM = VALID_CHARS + '+';
44
 
    private static final String WORD = "(" + ATOM + "|" + QUOTED_USER + ")";
45
 
 
46
 
    // Each pattern must be surrounded by /
47
 
    private static final String LEGAL_ASCII_PATTERN = "/^[\\000-\\177]+$/";
48
 
    private static final String EMAIL_PATTERN = "/^(.+)@(.+)$/";
49
 
    private static final String IP_DOMAIN_PATTERN =
50
 
            "/^(\\d{1,3})[.](\\d{1,3})[.](\\d{1,3})[.](\\d{1,3})$/";
51
 
 
52
 
    private static final String USER_PATTERN = "/^" + WORD + "(\\." + WORD + ")*$/";
53
 
    private static final String DOMAIN_PATTERN = "/^" + ATOM + "(\\." + ATOM + ")*$/";
54
 
    private static final String ATOM_PATTERN = "/(" + ATOM + ")/";
55
 
 
56
 
    /**
57
 
     * Singleton instance of this class.
58
 
     */
59
 
    private static final EmailValidator instance = new EmailValidator();
60
 
 
61
 
    /**
62
 
     * Returns the Singleton instance of this validator.
63
 
     */
64
 
    public static EmailValidator getInstance() {
65
 
        return instance;
66
 
    }
67
 
 
68
 
    /**
69
 
     * Protected constructor for subclasses to use.
70
 
     */
71
 
    protected EmailValidator() {
72
 
        super();
73
 
    }
74
 
 
75
 
    /**
76
 
     * <p>Checks if a field has a valid e-mail address.</p>
77
 
     *
78
 
     * @param email The value validation is being performed on.  A <code>null</code>
79
 
     * value is considered invalid.
80
 
     */
81
 
    public boolean isValid(String email) {
82
 
        if (email == null) {
83
 
            return false;
84
 
        }
85
 
 
86
 
        Perl5Util matchAsciiPat = new Perl5Util();
87
 
        if (!matchAsciiPat.match(LEGAL_ASCII_PATTERN, email)) {
88
 
            return false;
89
 
        }
90
 
 
91
 
        // Check the whole email address structure
92
 
        Perl5Util emailMatcher = new Perl5Util();
93
 
        if (!emailMatcher.match(EMAIL_PATTERN, email)) {
94
 
            return false;
95
 
        }
96
 
 
97
 
        if (email.endsWith(".")) {
98
 
            return false;
99
 
        }
100
 
 
101
 
        if (!isValidUser(emailMatcher.group(1))) {
102
 
            return false;
103
 
        }
104
 
 
105
 
        if (!isValidDomain(emailMatcher.group(2))) {
106
 
            return false;
107
 
        }
108
 
 
109
 
        return true;
110
 
    }
111
 
 
112
 
    /**
113
 
     * Returns true if the domain component of an email address is valid.
114
 
     * @param domain being validatied.
115
 
     */
116
 
    protected boolean isValidDomain(String domain) {
117
 
        boolean symbolic = false;
118
 
        Perl5Util ipAddressMatcher = new Perl5Util();
119
 
 
120
 
        if (ipAddressMatcher.match(IP_DOMAIN_PATTERN, domain)) {
121
 
            if (!isValidIpAddress(ipAddressMatcher)) {
122
 
                return false;
123
 
            }
124
 
        } else {
125
 
            // Domain is symbolic name
126
 
            Perl5Util domainMatcher = new Perl5Util();
127
 
            symbolic = domainMatcher.match(DOMAIN_PATTERN, domain);
128
 
        }
129
 
 
130
 
        if (symbolic) {
131
 
            if (!isValidSymbolicDomain(domain)) {
132
 
                return false;
133
 
            }
134
 
        } else {
135
 
            return false;
136
 
        }
137
 
 
138
 
        return true;
139
 
    }
140
 
 
141
 
    /**
142
 
     * Returns true if the user component of an email address is valid.
143
 
     * @param user being validated
144
 
     */
145
 
    protected boolean isValidUser(String user) {
146
 
        Perl5Util userMatcher = new Perl5Util();
147
 
        return userMatcher.match(USER_PATTERN, user);
148
 
    }
149
 
 
150
 
    /**
151
 
     * Validates an IP address. Returns true if valid.
152
 
     * @param ipAddressMatcher Pattren matcher
153
 
     */
154
 
    protected boolean isValidIpAddress(Perl5Util ipAddressMatcher) {
155
 
        for (int i = 1; i <= 4; i++) {
156
 
            String ipSegment = ipAddressMatcher.group(i);
157
 
            if (ipSegment == null || ipSegment.length() <= 0) {
158
 
                return false;
159
 
            }
160
 
 
161
 
            int iIpSegment = 0;
162
 
 
163
 
            try {
164
 
                iIpSegment = Integer.parseInt(ipSegment);
165
 
            } catch(NumberFormatException e) {
166
 
                return false;
167
 
            }
168
 
 
169
 
            if (iIpSegment > 255) {
170
 
                return false;
171
 
            }
172
 
 
173
 
        }
174
 
        return true;
175
 
    }
176
 
 
177
 
    /**
178
 
     * Validates a symbolic domain name.  Returns true if it's valid.
179
 
     * @param domain symbolic domain name
180
 
     */
181
 
    protected boolean isValidSymbolicDomain(String domain) {
182
 
        String[] domainSegment = new String[10];
183
 
        boolean match = true;
184
 
        int i = 0;
185
 
        Perl5Util atomMatcher = new Perl5Util();
186
 
 
187
 
        while (match) {
188
 
            match = atomMatcher.match(ATOM_PATTERN, domain);
189
 
            if (match) {
190
 
                domainSegment[i] = atomMatcher.group(1);
191
 
                int l = domainSegment[i].length() + 1;
192
 
                domain =
193
 
                        (l >= domain.length())
194
 
                        ? ""
195
 
                        : domain.substring(l);
196
 
 
197
 
                i++;
198
 
            }
199
 
        }
200
 
 
201
 
        int len = i;
202
 
        if (domainSegment[len - 1].length() < 2
203
 
                || domainSegment[len - 1].length() > 4) {
204
 
 
205
 
            return false;
206
 
        }
207
 
 
208
 
        // Make sure there's a host name preceding the domain.
209
 
        if (len < 2) {
210
 
            return false;
211
 
        }
212
 
 
213
 
        return true;
214
 
    }
215
 
 
216
 
}
 
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
 */
 
17
package org.apache.commons.validator;
 
18
 
 
19
import org.apache.oro.text.perl.Perl5Util;
 
20
 
 
21
/**
 
22
 * <p>Perform email validations.</p>
 
23
 * <p>
 
24
 * This class is a Singleton; you can retrieve the instance via the getInstance() method.
 
25
 * </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
 * For example, an address like nobody@noplace.somedog will pass validator, even though there
 
33
 * is no TLD "somedog"
 
34
 * </p>.
 
35
 *
 
36
 * @version $Revision: 478560 $ $Date: 2006-11-23 13:09:27 +0000 (Thu, 23 Nov 2006) $
 
37
 * @since Validator 1.1
 
38
 */
 
39
public class EmailValidator {
 
40
 
 
41
    private static final String SPECIAL_CHARS = "\\000-\\037\\(\\)<>@,;:'\\\\\\\"\\.\\[\\]\\177";
 
42
    private static final String VALID_CHARS = "[^\\s" + SPECIAL_CHARS + "]";
 
43
    private static final String QUOTED_USER = "(\"[^\"]*\")";
 
44
    private static final String ATOM = VALID_CHARS + '+';
 
45
    private static final String WORD = "((" + VALID_CHARS + "|')+|" + QUOTED_USER + ")";
 
46
 
 
47
    // Each pattern must be surrounded by /
 
48
    private static final String LEGAL_ASCII_PATTERN = "/^[\\000-\\177]+$/";
 
49
    private static final String EMAIL_PATTERN = "/^(.+)@(.+)$/";
 
50
    private static final String IP_DOMAIN_PATTERN =
 
51
            "/^\\[(\\d{1,3})[.](\\d{1,3})[.](\\d{1,3})[.](\\d{1,3})\\]$/";
 
52
    private static final String TLD_PATTERN = "/^([a-zA-Z]+)$/";
 
53
            
 
54
    private static final String USER_PATTERN = "/^\\s*" + WORD + "(\\." + WORD + ")*$/";
 
55
    private static final String DOMAIN_PATTERN = "/^" + ATOM + "(\\." + ATOM + ")*\\s*$/";
 
56
    private static final String ATOM_PATTERN = "/(" + ATOM + ")/";
 
57
 
 
58
    /**
 
59
     * Singleton instance of this class.
 
60
     */
 
61
    private static final EmailValidator EMAIL_VALIDATOR = new EmailValidator();
 
62
 
 
63
    /**
 
64
     * Returns the Singleton instance of this validator.
 
65
     * @return singleton instance of this validator.
 
66
     */
 
67
    public static EmailValidator getInstance() {
 
68
        return EMAIL_VALIDATOR;
 
69
    }
 
70
 
 
71
    /**
 
72
     * Protected constructor for subclasses to use.
 
73
     */
 
74
    protected EmailValidator() {
 
75
        super();
 
76
    }
 
77
 
 
78
    /**
 
79
     * <p>Checks if a field has a valid e-mail address.</p>
 
80
     *
 
81
     * @param email The value validation is being performed on.  A <code>null</code>
 
82
     * value is considered invalid.
 
83
     * @return true if the email address is valid.
 
84
     */
 
85
    public boolean isValid(String email) {
 
86
        if (email == null) {
 
87
            return false;
 
88
        }
 
89
 
 
90
        Perl5Util matchAsciiPat = new Perl5Util();
 
91
        if (!matchAsciiPat.match(LEGAL_ASCII_PATTERN, email)) {
 
92
            return false;
 
93
        }
 
94
 
 
95
        email = stripComments(email);
 
96
 
 
97
        // Check the whole email address structure
 
98
        Perl5Util emailMatcher = new Perl5Util();
 
99
        if (!emailMatcher.match(EMAIL_PATTERN, email)) {
 
100
            return false;
 
101
        }
 
102
 
 
103
        if (email.endsWith(".")) {
 
104
            return false;
 
105
        }
 
106
 
 
107
        if (!isValidUser(emailMatcher.group(1))) {
 
108
            return false;
 
109
        }
 
110
 
 
111
        if (!isValidDomain(emailMatcher.group(2))) {
 
112
            return false;
 
113
        }
 
114
 
 
115
        return true;
 
116
    }
 
117
 
 
118
    /**
 
119
     * Returns true if the domain component of an email address is valid.
 
120
     * @param domain being validatied.
 
121
     * @return true if the email address's domain is valid.
 
122
     */
 
123
    protected boolean isValidDomain(String domain) {
 
124
        boolean symbolic = false;
 
125
        Perl5Util ipAddressMatcher = new Perl5Util();
 
126
 
 
127
        if (ipAddressMatcher.match(IP_DOMAIN_PATTERN, domain)) {
 
128
            if (!isValidIpAddress(ipAddressMatcher)) {
 
129
                return false;
 
130
            } else {
 
131
                return true;
 
132
            }
 
133
        } else {
 
134
            // Domain is symbolic name
 
135
            Perl5Util domainMatcher = new Perl5Util();
 
136
            symbolic = domainMatcher.match(DOMAIN_PATTERN, domain);
 
137
        }
 
138
 
 
139
        if (symbolic) {
 
140
            if (!isValidSymbolicDomain(domain)) {
 
141
                return false;
 
142
            }
 
143
        } else {
 
144
            return false;
 
145
        }
 
146
 
 
147
        return true;
 
148
    }
 
149
 
 
150
    /**
 
151
     * Returns true if the user component of an email address is valid.
 
152
     * @param user being validated
 
153
     * @return true if the user name is valid.
 
154
     */
 
155
    protected boolean isValidUser(String user) {
 
156
        Perl5Util userMatcher = new Perl5Util();
 
157
        return userMatcher.match(USER_PATTERN, user);
 
158
    }
 
159
 
 
160
    /**
 
161
     * Validates an IP address. Returns true if valid.
 
162
     * @param ipAddressMatcher Pattren matcher
 
163
     * @return true if the ip address is valid.
 
164
     */
 
165
    protected boolean isValidIpAddress(Perl5Util ipAddressMatcher) {
 
166
        for (int i = 1; i <= 4; i++) {
 
167
            String ipSegment = ipAddressMatcher.group(i);
 
168
            if (ipSegment == null || ipSegment.length() <= 0) {
 
169
                return false;
 
170
            }
 
171
 
 
172
            int iIpSegment = 0;
 
173
 
 
174
            try {
 
175
                iIpSegment = Integer.parseInt(ipSegment);
 
176
            } catch(NumberFormatException e) {
 
177
                return false;
 
178
            }
 
179
 
 
180
            if (iIpSegment > 255) {
 
181
                return false;
 
182
            }
 
183
 
 
184
        }
 
185
        return true;
 
186
    }
 
187
 
 
188
    /**
 
189
     * Validates a symbolic domain name.  Returns true if it's valid.
 
190
     * @param domain symbolic domain name
 
191
     * @return true if the symbolic domain name is valid.
 
192
     */
 
193
    protected boolean isValidSymbolicDomain(String domain) {
 
194
        String[] domainSegment = new String[10];
 
195
        boolean match = true;
 
196
        int i = 0;
 
197
        Perl5Util atomMatcher = new Perl5Util();
 
198
        while (match) {
 
199
            match = atomMatcher.match(ATOM_PATTERN, domain);
 
200
            if (match) {
 
201
                domainSegment[i] = atomMatcher.group(1);
 
202
                int l = domainSegment[i].length() + 1;
 
203
                domain =
 
204
                        (l >= domain.length())
 
205
                        ? ""
 
206
                        : domain.substring(l);
 
207
 
 
208
                i++;
 
209
            } 
 
210
        }
 
211
 
 
212
        int len = i;
 
213
        
 
214
        // Make sure there's a host name preceding the domain.
 
215
        if (len < 2) {
 
216
            return false;
 
217
        }
 
218
        
 
219
        // TODO: the tld should be checked against some sort of configurable 
 
220
        // list
 
221
        String tld = domainSegment[len - 1];
 
222
        if (tld.length() > 1) {
 
223
            Perl5Util matchTldPat = new Perl5Util();
 
224
            if (!matchTldPat.match(TLD_PATTERN, tld)) {
 
225
                return false;
 
226
            }
 
227
        } else {
 
228
            return false;
 
229
        }
 
230
 
 
231
        return true;
 
232
    }
 
233
    /**
 
234
     *   Recursively remove comments, and replace with a single space.  The simpler
 
235
     *   regexps in the Email Addressing FAQ are imperfect - they will miss escaped
 
236
     *   chars in atoms, for example.
 
237
     *   Derived From    Mail::RFC822::Address
 
238
     * @param emailStr The email address
 
239
     * @return address with comments removed.
 
240
    */
 
241
    protected String stripComments(String emailStr)  {
 
242
     String input = emailStr;
 
243
     String result = emailStr;
 
244
     String commentPat = "s/^((?:[^\"\\\\]|\\\\.)*(?:\"(?:[^\"\\\\]|\\\\.)*\"(?:[^\"\\\\]|\111111\\\\.)*)*)\\((?:[^()\\\\]|\\\\.)*\\)/$1 /osx";
 
245
     Perl5Util commentMatcher = new Perl5Util();
 
246
     result = commentMatcher.substitute(commentPat,input);
 
247
     // This really needs to be =~ or Perl5Matcher comparison
 
248
     while (!result.equals(input)) {
 
249
        input = result;
 
250
        result = commentMatcher.substitute(commentPat,input);
 
251
     }
 
252
     return result;
 
253
 
 
254
    }
 
255
}