Index: third_party/libaddressinput/chromium/cpp/src/address_validator.cc |
diff --git a/third_party/libaddressinput/chromium/cpp/src/address_validator.cc b/third_party/libaddressinput/chromium/cpp/src/address_validator.cc |
index 4c9353f99045824ffe01751ef5232bdbc299fdaa..765c2a5bc880977830b0e1d581447b11962f2cd7 100644 |
--- a/third_party/libaddressinput/chromium/cpp/src/address_validator.cc |
+++ b/third_party/libaddressinput/chromium/cpp/src/address_validator.cc |
@@ -14,6 +14,7 @@ |
#include <libaddressinput/address_validator.h> |
+#include <libaddressinput/address_data.h> |
#include <libaddressinput/downloader.h> |
#include <libaddressinput/load_rules_delegate.h> |
#include <libaddressinput/localization.h> |
@@ -21,13 +22,19 @@ |
#include <libaddressinput/util/basictypes.h> |
#include <libaddressinput/util/scoped_ptr.h> |
+#include <algorithm> |
#include <cassert> |
+#include <cstddef> |
#include <map> |
#include <string> |
#include <utility> |
+#include <re2/re2.h> |
+ |
#include "country_rules_retriever.h" |
+#include "messages.h" |
#include "retriever.h" |
+#include "rule.h" |
#include "ruleset.h" |
#include "util/stl_util.h" |
#include "validating_storage.h" |
@@ -37,6 +44,25 @@ namespace addressinput { |
namespace { |
+// Returns true if the filter is empty (all problems allowed) or contains the |
+// |field|->|problem| mapping (explicitly allowed). |
+bool FilterAllows(const AddressProblemFilter& filter, |
+ AddressField field, |
+ AddressProblem::Type problem) { |
+ if (filter.empty()) { |
+ return true; |
+ } |
+ |
+ for (AddressProblemFilter::const_iterator it = filter.begin(); |
+ it != filter.end(); ++it) { |
+ if (it->first == field && it->second == problem) { |
+ return true; |
+ } |
+ } |
+ |
+ return false; |
+} |
+ |
// Validates AddressData structure. |
class AddressValidatorImpl : public AddressValidator { |
public: |
@@ -76,7 +102,102 @@ class AddressValidatorImpl : public AddressValidator { |
const AddressProblemFilter& filter, |
const Localization& localization, |
AddressProblems* problems) const { |
- return RULES_UNAVAILABLE; |
+ std::map<std::string, Status>::const_iterator status_it = |
+ status_.find(address.country_code); |
+ if (status_it == status_.end()) { |
+ return RULES_UNAVAILABLE; |
+ } else if (status_it->second == RULES_NOT_READY) { |
+ return RULES_NOT_READY; |
+ } |
+ |
+ std::map<std::string, Ruleset*>::const_iterator ruleset_it = |
+ rules_.find(address.country_code); |
+ assert(ruleset_it != rules_.end()); |
+ Ruleset* ruleset = ruleset_it->second; |
+ assert(ruleset != NULL); |
+ |
+ std::map<AddressField, const Rule*> rules = |
+ ruleset->BuildRulesForAddress(address); |
+ const Rule& country_rule = *rules[COUNTRY]; |
+ |
+ // Validate required fields. |
+ for (std::vector<AddressField>::const_iterator |
+ field_it = country_rule.GetRequired().begin(); |
+ field_it != country_rule.GetRequired().end(); |
+ ++field_it) { |
+ if (address.GetField(*field_it).empty() && |
+ FilterAllows( |
+ filter, *field_it, AddressProblem::MISSING_REQUIRED_FIELD)) { |
+ problems->push_back(AddressProblem( |
+ *field_it, |
+ AddressProblem::MISSING_REQUIRED_FIELD, |
+ localization.GetString( |
+ IDS_LIBADDRESSINPUT_I18N_MISSING_REQUIRED_FIELD))); |
+ } |
+ } |
+ |
+ // Validate general postal code format. A country-level rule specifies the |
+ // regular expression for the whole postal code. |
+ if (!address.postal_code.empty() && |
+ !country_rule.GetPostalCodeFormat().empty() && |
+ FilterAllows(filter, |
+ POSTAL_CODE, |
+ AddressProblem::UNRECOGNIZED_FORMAT) && |
+ !RE2::FullMatch( |
+ address.postal_code, country_rule.GetPostalCodeFormat())) { |
+ problems->push_back(AddressProblem( |
+ POSTAL_CODE, |
+ AddressProblem::UNRECOGNIZED_FORMAT, |
+ localization.GetString( |
+ country_rule.GetInvalidPostalCodeMessageId()))); |
+ } |
+ |
+ for (std::map<AddressField, const Rule*>::const_iterator |
+ rule_it = rules.begin(); |
+ rule_it != rules.end(); |
+ ++rule_it) { |
+ AddressField field_type = rule_it->first; |
+ const Rule* rule = rule_it->second; |
+ assert(rule != NULL); |
+ |
+ // Validate the field values, e.g. state names in US. |
+ AddressField sub_field_type = static_cast<AddressField>(field_type + 1); |
+ const std::string& sub_field = address.GetField(sub_field_type); |
+ const std::vector<std::string>& sub_keys = rule->GetSubKeys(); |
+ if (!sub_field.empty() && |
+ !sub_keys.empty() && |
+ FilterAllows(filter, sub_field_type, AddressProblem::UNKNOWN_VALUE) && |
+ std::find(sub_keys.begin(), sub_keys.end(), sub_field) == |
+ sub_keys.end()) { |
+ problems->push_back(AddressProblem( |
+ sub_field_type, |
+ AddressProblem::UNKNOWN_VALUE, |
+ localization.GetString( |
+ country_rule.GetInvalidFieldMessageId(sub_field_type)))); |
+ } |
+ |
+ // Validate sub-region specific postal code format. A sub-region specifies |
+ // the regular expression for a prefix of the postal code. |
+ int match_position = -1; |
+ if (field_type > COUNTRY && |
+ !address.postal_code.empty() && |
+ !rule->GetPostalCodeFormat().empty() && |
+ FilterAllows(filter, |
+ POSTAL_CODE, |
+ AddressProblem::MISMATCHING_VALUE) && |
+ (!RE2::PartialMatch(address.postal_code, |
+ rule->GetPostalCodeFormat(), |
+ &match_position) || |
+ match_position != 0)) { |
+ problems->push_back(AddressProblem( |
+ POSTAL_CODE, |
+ AddressProblem::MISMATCHING_VALUE, |
+ localization.GetString( |
+ country_rule.GetInvalidPostalCodeMessageId()))); |
+ } |
+ } |
+ |
+ return SUCCESS; |
} |
private: |