| 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 |