OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "components/autofill/browser/validation.h" | |
6 | |
7 #include "base/strings/string_number_conversions.h" | |
8 #include "base/strings/string_piece.h" | |
9 #include "base/strings/string_util.h" | |
10 #include "base/strings/utf_string_conversions.h" | |
11 #include "base/time.h" | |
12 #include "components/autofill/browser/autofill_regexes.h" | |
13 #include "components/autofill/browser/credit_card.h" | |
14 #include "components/autofill/browser/state_names.h" | |
15 | |
16 using base::StringPiece16; | |
17 | |
18 namespace { | |
19 | |
20 // The separator characters for SSNs. | |
21 const char16 kSSNSeparators[] = {' ', '-', 0}; | |
22 | |
23 } // namespace | |
24 | |
25 namespace autofill { | |
26 | |
27 bool IsValidCreditCardExpirationDate(const base::string16& year, | |
28 const base::string16& month, | |
29 const base::Time& now) { | |
30 base::string16 year_cleaned, month_cleaned; | |
31 TrimWhitespace(year, TRIM_ALL, &year_cleaned); | |
32 TrimWhitespace(month, TRIM_ALL, &month_cleaned); | |
33 if (year_cleaned.length() != 4) | |
34 return false; | |
35 | |
36 base::Time::Exploded now_exploded; | |
37 now.LocalExplode(&now_exploded); | |
38 size_t current_year = size_t(now_exploded.year); | |
39 size_t current_month = size_t(now_exploded.month); | |
40 | |
41 size_t cc_year; | |
42 if (!base::StringToSizeT(year_cleaned, &cc_year)) | |
43 return false; | |
44 if (cc_year < current_year) | |
45 return false; | |
46 | |
47 size_t cc_month; | |
48 if (!base::StringToSizeT(month_cleaned, &cc_month)) | |
49 return false; | |
50 if (cc_year == current_year && cc_month < current_month) | |
51 return false; | |
52 | |
53 return true; | |
54 } | |
55 | |
56 bool IsValidCreditCardNumber(const base::string16& text) { | |
57 base::string16 number = CreditCard::StripSeparators(text); | |
58 | |
59 // Credit card numbers are at most 19 digits in length [1]. 12 digits seems to | |
60 // be a fairly safe lower-bound [2]. | |
61 // [1] http://www.merriampark.com/anatomycc.htm | |
62 // [2] http://en.wikipedia.org/wiki/Bank_card_number | |
63 const size_t kMinCreditCardDigits = 12; | |
64 const size_t kMaxCreditCardDigits = 19; | |
65 if (number.size() < kMinCreditCardDigits || | |
66 number.size() > kMaxCreditCardDigits) | |
67 return false; | |
68 | |
69 // Use the Luhn formula [3] to validate the number. | |
70 // [3] http://en.wikipedia.org/wiki/Luhn_algorithm | |
71 int sum = 0; | |
72 bool odd = false; | |
73 for (base::string16::reverse_iterator iter = number.rbegin(); | |
74 iter != number.rend(); | |
75 ++iter) { | |
76 if (!IsAsciiDigit(*iter)) | |
77 return false; | |
78 | |
79 int digit = *iter - '0'; | |
80 if (odd) { | |
81 digit *= 2; | |
82 sum += digit / 10 + digit % 10; | |
83 } else { | |
84 sum += digit; | |
85 } | |
86 odd = !odd; | |
87 } | |
88 | |
89 return (sum % 10) == 0; | |
90 } | |
91 | |
92 bool IsValidCreditCardSecurityCode(const base::string16& text) { | |
93 if (text.size() < 3U || text.size() > 4U) | |
94 return false; | |
95 | |
96 for (base::string16::const_iterator iter = text.begin(); | |
97 iter != text.end(); | |
98 ++iter) { | |
99 if (!IsAsciiDigit(*iter)) | |
100 return false; | |
101 } | |
102 return true; | |
103 } | |
104 | |
105 bool IsValidCreditCardSecurityCode(const base::string16& code, | |
106 const base::string16& number) { | |
107 CreditCard card; | |
108 card.SetRawInfo(CREDIT_CARD_NUMBER, number); | |
109 size_t required_length = 3; | |
110 if (card.type() == kAmericanExpressCard) | |
111 required_length = 4; | |
112 | |
113 return code.length() == required_length; | |
114 } | |
115 | |
116 bool IsValidEmailAddress(const base::string16& text) { | |
117 // E-Mail pattern as defined by the WhatWG. (4.10.7.1.5 E-Mail state) | |
118 const base::string16 kEmailPattern = ASCIIToUTF16( | |
119 "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@" | |
120 "[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$"); | |
121 return MatchesPattern(text, kEmailPattern); | |
122 } | |
123 | |
124 bool IsValidState(const base::string16& text) { | |
125 return !state_names::GetAbbreviationForName(text).empty() || | |
126 !state_names::GetNameForAbbreviation(text).empty(); | |
127 } | |
128 | |
129 bool IsValidZip(const base::string16& text) { | |
130 const base::string16 kZipPattern = ASCIIToUTF16("^\\d{5}(-\\d{4})?$"); | |
131 return MatchesPattern(text, kZipPattern); | |
132 } | |
133 | |
134 bool IsSSN(const string16& text) { | |
135 string16 number_string; | |
136 RemoveChars(text, kSSNSeparators, &number_string); | |
137 | |
138 // A SSN is of the form AAA-GG-SSSS (A = area number, G = group number, S = | |
139 // serial number). The validation we do here is simply checking if the area, | |
140 // group, and serial numbers are valid. | |
141 // | |
142 // Historically, the area number was assigned per state, with the group number | |
143 // ascending in an alternating even/odd sequence. With that scheme it was | |
144 // possible to check for validity by referencing a table that had the highest | |
145 // group number assigned for a given area number. (This was something that | |
146 // Chromium never did though, because the "high group" values were constantly | |
147 // changing.) | |
148 // | |
149 // However, starting on 25 June 2011 the SSA began issuing SSNs randomly from | |
150 // all areas and groups. Group numbers and serial numbers of zero remain | |
151 // invalid, and areas 000, 666, and 900-999 remain invalid. | |
152 // | |
153 // References for current practices: | |
154 // http://www.socialsecurity.gov/employer/randomization.html | |
155 // http://www.socialsecurity.gov/employer/randomizationfaqs.html | |
156 // | |
157 // References for historic practices: | |
158 // http://www.socialsecurity.gov/history/ssn/geocard.html | |
159 // http://www.socialsecurity.gov/employer/stateweb.htm | |
160 // http://www.socialsecurity.gov/employer/ssnvhighgroup.htm | |
161 | |
162 if (number_string.length() != 9 || !IsStringASCII(number_string)) | |
163 return false; | |
164 | |
165 int area; | |
166 if (!base::StringToInt(StringPiece16(number_string.begin(), | |
167 number_string.begin() + 3), | |
168 &area)) { | |
169 return false; | |
170 } | |
171 if (area < 1 || | |
172 area == 666 || | |
173 area >= 900) { | |
174 return false; | |
175 } | |
176 | |
177 int group; | |
178 if (!base::StringToInt(StringPiece16(number_string.begin() + 3, | |
179 number_string.begin() + 5), | |
180 &group) | |
181 || group == 0) { | |
182 return false; | |
183 } | |
184 | |
185 int serial; | |
186 if (!base::StringToInt(StringPiece16(number_string.begin() + 5, | |
187 number_string.begin() + 9), | |
188 &serial) | |
189 || serial == 0) { | |
190 return false; | |
191 } | |
192 | |
193 return true; | |
194 } | |
195 | |
196 } // namespace autofill | |
OLD | NEW |