1/*
2 * This file is part of the WebKit project.
3 *
4 * Copyright (C) 2009 Michelangelo De Simone <micdesim@gmail.com>
5 * Copyright (C) 2010 Google Inc. All rights reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB.  If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#include "config.h"
25#include "EmailInputType.h"
26
27#include "HTMLInputElement.h"
28#include "HTMLParserIdioms.h"
29#include "InputTypeNames.h"
30#include "LocalizedStrings.h"
31#include "RegularExpression.h"
32#include <wtf/PassOwnPtr.h>
33#include <wtf/text/StringBuilder.h>
34
35namespace WebCore {
36
37static const char emailPattern[] =
38    "[a-z0-9!#$%&'*+/=?^_`{|}~.-]+" // local part
39    "@"
40    "[a-z0-9-]+(\\.[a-z0-9-]+)*"; // domain part
41
42static bool isValidEmailAddress(const String& address)
43{
44    int addressLength = address.length();
45    if (!addressLength)
46        return false;
47
48    DEFINE_STATIC_LOCAL(const RegularExpression, regExp, (emailPattern, TextCaseInsensitive));
49
50    int matchLength;
51    int matchOffset = regExp.match(address, 0, &matchLength);
52
53    return !matchOffset && matchLength == addressLength;
54}
55
56PassOwnPtr<InputType> EmailInputType::create(HTMLInputElement* element)
57{
58    return adoptPtr(new EmailInputType(element));
59}
60
61void EmailInputType::attach()
62{
63    TextFieldInputType::attach();
64    observeFeatureIfVisible(FeatureObserver::InputTypeEmail);
65}
66
67const AtomicString& EmailInputType::formControlType() const
68{
69    return InputTypeNames::email();
70}
71
72bool EmailInputType::typeMismatchFor(const String& value) const
73{
74    if (value.isEmpty())
75        return false;
76    if (!element()->multiple())
77        return !isValidEmailAddress(value);
78    Vector<String> addresses;
79    value.split(',', true, addresses);
80    for (unsigned i = 0; i < addresses.size(); ++i) {
81        if (!isValidEmailAddress(stripLeadingAndTrailingHTMLSpaces(addresses[i])))
82            return true;
83    }
84    return false;
85}
86
87bool EmailInputType::typeMismatch() const
88{
89    return typeMismatchFor(element()->value());
90}
91
92String EmailInputType::typeMismatchText() const
93{
94    return element()->multiple() ? validationMessageTypeMismatchForMultipleEmailText() : validationMessageTypeMismatchForEmailText();
95}
96
97bool EmailInputType::isEmailField() const
98{
99    return true;
100}
101
102bool EmailInputType::supportsSelectionAPI() const
103{
104    return false;
105}
106
107String EmailInputType::sanitizeValue(const String& proposedValue) const
108{
109    String noLineBreakValue = proposedValue.removeCharacters(isHTMLLineBreak);
110    if (!element()->multiple())
111        return stripLeadingAndTrailingHTMLSpaces(noLineBreakValue);
112    Vector<String> addresses;
113    noLineBreakValue.split(',', true, addresses);
114    StringBuilder strippedValue;
115    for (unsigned i = 0; i < addresses.size(); ++i) {
116        if (i > 0)
117            strippedValue.append(",");
118        strippedValue.append(stripLeadingAndTrailingHTMLSpaces(addresses[i]));
119    }
120    return strippedValue.toString();
121}
122
123} // namespace WebCore
124