8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The contents of this file are subject to the terms
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * of the Common Development and Distribution License
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * (the License). You may not use this file except in
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * compliance with the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * You can obtain a copy of the License at
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * opensso/legal/CDDLv1.0.txt
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * See the License for the specific language governing
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * permission and limitations under the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * When distributing Covered Code, include this CDDL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Header Notice in each file and include the License file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * at opensso/legal/CDDLv1.0.txt.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * If applicable, add the following below the CDDL Header,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * with the fields enclosed by brackets [] replaced by
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * your own identifying information:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * $Id: EmailValidator.java,v 1.2 2008/06/25 05:44:04 qcheng Exp $
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpackage com.sun.identity.sm;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.Iterator;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.Set;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.StringTokenizer;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.Vector;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The class <code>EmailValidator</code> is used to check if the Email address
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * is syntactically correct according to valid format defined in RFC 822. Email
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * address must contain an @ symbol as well as syntactically correct username
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * and domain information e.g. name@domain.com
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpublic class EmailValidator implements ServiceAttributeValidator {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Default Constructor.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public EmailValidator() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Validates a set of email address.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param values
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the set of string email address to validate
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return true if all of the email addresses are valid; false otherwise
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public boolean validate(Set values) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Iterator it = values.iterator();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while (it.hasNext()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String value = (String) it.next();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!validate(value)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Validates an email address.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param value
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * an email address
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return true if the email address is valid; false otherwise
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public boolean validate(String value) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int index = value.indexOf('@');
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (index == -1) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String name = value.substring(0, index);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String domain = value.substring(index + 1, value.length());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (validateName(name) && validateDomain(domain)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private boolean validateName(String name) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster StringTokenizer tok = new StringTokenizer(name, ".");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (tok.countTokens() < 1) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while (tok.hasMoreTokens()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!isValidNamePart(tok.nextToken())) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private boolean isValidNamePart(String name) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int length = name.length();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (int i = 0; i < length; i++) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster char ch = name.charAt(i);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int val = ch;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Character character = new Character(ch);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // The character can be any ASCII character except:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // a) ASCII control character and DEL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // b) space
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // c) RFC 822 specials
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (val < 33 || val > 126
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster || inValidChars.contains(character.toString())) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private boolean validateDomain(String domain) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster StringTokenizer tok = new StringTokenizer(domain, ".");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (tok.countTokens() <= 1) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while (tok.hasMoreTokens()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!isValidDomainPart(tok.nextToken())) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private boolean isValidDomainPart(String domain) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int length = domain.length();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // subdomain can not start or end with a hyphen
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (domain.charAt(0) == '-' || domain.charAt(length - 1) == '-') {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // subdomain or "label" can not be longer than 63 chars
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (length > 63) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (int i = 0; i < length; i++) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster char ch = domain.charAt(i);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!Character.isLetter(ch) && !Character.isDigit(ch) && ch != '-')
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static Vector inValidChars = new Vector();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster static {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // RFC 822 special characters
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inValidChars.addElement("(");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inValidChars.addElement(")");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inValidChars.addElement("<");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inValidChars.addElement(">");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inValidChars.addElement("@");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inValidChars.addElement(",");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inValidChars.addElement(";");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inValidChars.addElement(":");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inValidChars.addElement("\\");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inValidChars.addElement("\"");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inValidChars.addElement(".");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inValidChars.addElement("[");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inValidChars.addElement("]");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}