Commit 7c7b0ed3 authored by Martynas Sinkievic's avatar Martynas Sinkievic Committed by Commit Bot

[Autofill] Add the pattern configuration parser

Add functions which support validating and parsing the
JSON matching pattern configuration string into a format
supported by |PatternProvider|. Also provide support for
versioning and replacing the configuration in
|PatternProvider|. Due to the nature of the change,
|PatternProvider| was changed to support testing with a
synchronously loaded configuration.

Change-Id: I662ecb933a4067c0ee6d188defe5e982b85469a7
Bug: 1121990
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2359990Reviewed-by: default avatarMatthias Körber <koerber@google.com>
Reviewed-by: default avatarChristoph Schwering <schwering@google.com>
Reviewed-by: default avatarColin Blundell <blundell@chromium.org>
Commit-Queue: Martynas Sinkievič <marsin@google.com>
Cr-Commit-Position: refs/heads/master@{#813097}
parent 0a01915d
...@@ -183,6 +183,8 @@ static_library("browser") { ...@@ -183,6 +183,8 @@ static_library("browser") {
"metrics/form_event_logger_base.cc", "metrics/form_event_logger_base.cc",
"metrics/form_event_logger_base.h", "metrics/form_event_logger_base.h",
"metrics/form_events.h", "metrics/form_events.h",
"pattern_provider/pattern_configuration_parser.cc",
"pattern_provider/pattern_configuration_parser.h",
"pattern_provider/pattern_provider.cc", "pattern_provider/pattern_provider.cc",
"pattern_provider/pattern_provider.h", "pattern_provider/pattern_provider.h",
"payments/account_info_getter.h", "payments/account_info_getter.h",
...@@ -390,6 +392,7 @@ static_library("browser") { ...@@ -390,6 +392,7 @@ static_library("browser") {
"//crypto", "//crypto",
"//google_apis", "//google_apis",
"//net", "//net",
"//services/data_decoder/public/cpp:cpp",
"//services/metrics/public/cpp:metrics_cpp", "//services/metrics/public/cpp:metrics_cpp",
"//services/metrics/public/cpp:ukm_builders", "//services/metrics/public/cpp:ukm_builders",
"//services/network/public/cpp", "//services/network/public/cpp",
...@@ -446,6 +449,8 @@ static_library("test_support") { ...@@ -446,6 +449,8 @@ static_library("test_support") {
"logging/stub_log_manager.h", "logging/stub_log_manager.h",
"mock_autocomplete_history_manager.cc", "mock_autocomplete_history_manager.cc",
"mock_autocomplete_history_manager.h", "mock_autocomplete_history_manager.h",
"pattern_provider/test_pattern_provider.cc",
"pattern_provider/test_pattern_provider.h",
"payments/test_authentication_requester.cc", "payments/test_authentication_requester.cc",
"payments/test_authentication_requester.h", "payments/test_authentication_requester.h",
"payments/test_credit_card_save_manager.cc", "payments/test_credit_card_save_manager.cc",
...@@ -628,6 +633,7 @@ source_set("unit_tests") { ...@@ -628,6 +633,7 @@ source_set("unit_tests") {
"logging/log_buffer_submitter_unittest.cc", "logging/log_buffer_submitter_unittest.cc",
"logging/log_manager_unittest.cc", "logging/log_manager_unittest.cc",
"logging/log_router_unittest.cc", "logging/log_router_unittest.cc",
"pattern_provider/pattern_configuration_parser_unittest.cc",
"pattern_provider/pattern_provider_unittest.cc", "pattern_provider/pattern_provider_unittest.cc",
"payments/autofill_offer_manager_unittest.cc", "payments/autofill_offer_manager_unittest.cc",
"payments/credit_card_access_manager_unittest.cc", "payments/credit_card_access_manager_unittest.cc",
...@@ -727,6 +733,7 @@ source_set("unit_tests") { ...@@ -727,6 +733,7 @@ source_set("unit_tests") {
"//google_apis", "//google_apis",
"//google_apis:test_support", "//google_apis:test_support",
"//net:test_support", "//net:test_support",
"//services/data_decoder/public/cpp:test_support",
"//services/metrics/public/cpp:ukm_builders", "//services/metrics/public/cpp:ukm_builders",
"//services/network:test_support", "//services/network:test_support",
"//services/network/public/cpp", "//services/network/public/cpp",
......
include_rules = [
"+components/grit/components_resources.h",
"+services/data_decoder/public/cpp:cpp",
"+services/data_decoder/public",
]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/autofill/core/browser/pattern_provider/pattern_configuration_parser.h"
#include "base/bind.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/values.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/grit/components_resources.h"
#include "ui/base/resource/resource_bundle.h"
namespace autofill {
namespace field_type_parsing {
namespace {
const char kPatternIdentifierKey[] = "pattern_identifier";
const char kPositivePatternKey[] = "positive_pattern";
const char kNegativePatternKey[] = "negative_pattern";
const char kPositiveScoreKey[] = "positive_score";
const char kMatchFieldAttributesKey[] = "match_field_attributes";
const char kMatchFieldInputTypesKey[] = "match_field_input_types";
const char kVersionKey[] = "version";
bool ParseMatchingPattern(PatternProvider::Map& patterns,
const std::string& field_type,
const std::string& language,
const base::Value& value) {
if (!value.is_dict())
return false;
const std::string* pattern_identifier =
value.FindStringKey(kPatternIdentifierKey);
const std::string* positive_pattern =
value.FindStringKey(kPositivePatternKey);
const std::string* negative_pattern =
value.FindStringKey(kNegativePatternKey);
base::Optional<double> positive_score =
value.FindDoubleKey(kPositiveScoreKey);
base::Optional<int> match_field_attributes =
value.FindIntKey(kMatchFieldAttributesKey);
base::Optional<int> match_field_input_types =
value.FindIntKey(kMatchFieldInputTypesKey);
if (!pattern_identifier || !positive_pattern || !negative_pattern ||
!positive_score || !match_field_attributes || !match_field_input_types)
return false;
autofill::MatchingPattern new_pattern;
new_pattern.pattern_identifier = *pattern_identifier;
new_pattern.positive_pattern = *positive_pattern;
new_pattern.positive_score = *positive_score;
new_pattern.negative_pattern = *negative_pattern;
new_pattern.match_field_attributes = match_field_attributes.value();
new_pattern.match_field_input_types = match_field_input_types.value();
new_pattern.language = language;
std::vector<MatchingPattern>* pattern_list = &patterns[field_type][language];
pattern_list->push_back(new_pattern);
DVLOG(2) << "Correctly parsed MatchingPattern with identifier |"
<< new_pattern.pattern_identifier << "|.";
return true;
}
// Callback which is used once the JSON is parsed.
// |overwrite_equal_version| should be true when loading a remote
// configuration. If the configuration versions are equal or
// both unspecified (i.e. set to 0) this prioritizes the remote
// configuration over the local one.
void OnJsonParsed(bool overwrite_equal_version,
base::OnceClosure done_callback,
data_decoder::DataDecoder::ValueOrError result) {
// Skip any processing in case of an error.
if (!result.value) {
DVLOG(1) << "Failed to parse PatternProvider configuration JSON string.";
std::move(done_callback).Run();
return;
}
base::Version version = ExtractVersionFromJsonObject(result.value.value());
base::Optional<PatternProvider::Map> patterns =
GetConfigurationFromJsonObject(result.value.value());
if (patterns && version.IsValid()) {
DVLOG(1) << "Successfully parsed PatternProvider configuration.";
PatternProvider& pattern_provider = PatternProvider::GetInstance();
pattern_provider.SetPatterns(std::move(patterns.value()),
std::move(version), overwrite_equal_version);
} else {
DVLOG(1) << "Failed to parse PatternProvider configuration JSON object.";
}
std::move(done_callback).Run();
}
} // namespace
base::Optional<PatternProvider::Map> GetConfigurationFromJsonObject(
const base::Value& root) {
PatternProvider::Map patterns;
if (!root.is_dict()) {
DVLOG(1) << "JSON object is not a dictionary.";
return base::nullopt;
}
for (const auto& kv : root.DictItems()) {
const std::string& field_type = kv.first;
const base::Value* field_type_dict = &kv.second;
if (!field_type_dict->is_dict()) {
DVLOG(1) << "|" << field_type << "| does not contain a dictionary.";
return base::nullopt;
}
for (const auto& value : field_type_dict->DictItems()) {
const std::string& language = value.first;
const base::Value* inner_list = &value.second;
if (!inner_list->is_list()) {
DVLOG(1) << "Language |" << language << "| in |" << field_type
<< "| does not contain a list.";
return base::nullopt;
}
for (const auto& matchingPatternObj : inner_list->GetList()) {
bool success = ParseMatchingPattern(patterns, field_type, language,
matchingPatternObj);
if (!success) {
DVLOG(1) << "Found incorrect |MatchingPattern| object in list |"
<< field_type << "|, language |" << language << "|.";
return base::nullopt;
}
}
}
}
return base::make_optional(patterns);
}
base::Version ExtractVersionFromJsonObject(base::Value& root) {
if (!root.is_dict())
return base::Version("0");
base::Optional<base::Value> version_str = root.ExtractKey(kVersionKey);
if (!version_str || !version_str.value().is_string())
return base::Version("0");
base::Version version = base::Version(version_str.value().GetString());
if (!version.IsValid())
return base::Version("0");
return version;
}
void PopulateFromJsonString(std::string json_string) {
data_decoder::DataDecoder::ParseJsonIsolated(
std::move(json_string),
base::BindOnce(&OnJsonParsed, true, base::DoNothing::Once()));
}
void PopulateFromResourceBundle(base::OnceClosure done_callback) {
if (!ui::ResourceBundle::HasSharedInstance()) {
VLOG(1) << "Resource Bundle unavailable to load Autofill Matching Pattern "
"definitions.";
std::move(done_callback).Run();
return;
}
ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
// Load the string from the Resource Bundle on a worker thread, then
// securely parse the JSON in a separate process and call |OnJsonParsed|
// with the result.
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock()},
base::BindOnce(&ui::ResourceBundle::LoadDataResourceString,
base::Unretained(&bundle), IDR_AUTOFILL_REGEX_JSON),
base::BindOnce(
[](base::OnceClosure done_callback, std::string resource_string) {
data_decoder::DataDecoder::ParseJsonIsolated(
std::move(resource_string),
base::BindOnce(&OnJsonParsed, false, std::move(done_callback)));
},
std::move(done_callback)));
}
base::Optional<PatternProvider::Map>
GetPatternsFromResourceBundleSynchronously() {
if (!ui::ResourceBundle::HasSharedInstance()) {
VLOG(1) << "Resource Bundle unavailable to load Autofill Matching Pattern "
"definitions.";
return base::nullopt;
}
ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
std::string resource_string =
bundle.LoadDataResourceString(IDR_AUTOFILL_REGEX_JSON);
base::Optional<base::Value> json_object =
base::JSONReader::Read(resource_string);
// Discard version, since this is the only getter used in unit tests.
base::Version version = ExtractVersionFromJsonObject(json_object.value());
base::Optional<PatternProvider::Map> configuration_map =
GetConfigurationFromJsonObject(json_object.value());
return configuration_map;
}
} // namespace field_type_parsing
} // namespace autofill
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PATTERN_PROVIDER_PATTERN_CONFIGURATION_PARSER_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_PATTERN_PROVIDER_PATTERN_CONFIGURATION_PARSER_H_
#include <string>
#include "base/json/json_reader.h"
#include "base/version.h"
#include "components/autofill/core/browser/form_parsing/autofill_parsing_utils.h"
#include "components/autofill/core/browser/pattern_provider/pattern_provider.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
namespace autofill {
namespace field_type_parsing {
// Tries to extract the configuration version from the JSON base::Value tree.
// This removes the key if found, so that validation is easier later on.
// If not found, default to version 0.
base::Version ExtractVersionFromJsonObject(base::Value& root);
// Transforms the parsed JSON base::Value tree into the map used in
// |PatternProvider|. Requires the version key to already be extracted.
// The root is expected to be a dictionary with keys corresponding to
// strings representing |ServerFieldType|. Then there should be
// second level dictionaries with keys describing the language. These
// should point to a list of objects representing |MatchingPattern|.
// {
// "FIELD_NAME": {
// "language":[
// {MatchingPatternFields}
// ]
// }
// }
// An example can be found in the relative resources folder.
base::Optional<PatternProvider::Map> GetConfigurationFromJsonObject(
const base::Value& root);
// Tries to get and parse the default configuration in the resource bundle
// into a valid map used in |PatternProvider| and swap it in for further use.
// The callback is used as a signal for testing.
void PopulateFromResourceBundle(
base::OnceClosure done_callback = base::DoNothing::Once());
// Tries to parse the given JSON string into a valid map used in the
// |PatternProvider| and swap it in for further use.
void PopulateFromJsonString(std::string json_string);
// Synchronous getter used to set up a test fixture.
base::Optional<PatternProvider::Map>
GetPatternsFromResourceBundleSynchronously();
} // namespace field_type_parsing
} // namespace autofill
#endif
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/autofill/core/browser/pattern_provider/pattern_configuration_parser.h"
#include <stddef.h>
#include "base/json/json_reader.h"
#include "base/test/gtest_util.h"
#include "base/version.h"
#include "components/grit/components_resources.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/resource/resource_bundle.h"
namespace autofill {
namespace field_type_parsing {
// Test that the |base::Value| object of the configuration is
// parsed to the map structure used by |PatternProvider| as
// expected, given the input is valid.
TEST(PatternConfigurationParserTest, WellFormedParsedCorrectly) {
std::string JSON_message = R"(
{
"version": "1.0",
"FULL_NAME": {
"en_us": [
{
"pattern_identifier": "Name_en",
"positive_pattern": "name|full name",
"positive_score": 2.0,
"negative_pattern": "company",
"match_field_attributes": 2,
"match_field_input_types": 3
}
],
"fr": [
{
"pattern_identifier": "Name_fr",
"positive_pattern": "nom|prenom",
"positive_score": 2.0,
"negative_pattern": "compagne",
"match_field_attributes": 2,
"match_field_input_types": 3
}
]
},
"ADDRESS": {
"en_us": [
{
"pattern_identifier": "Address",
"positive_pattern": "address",
"positive_score": 2.0,
"negative_pattern": "email",
"match_field_attributes": 4,
"match_field_input_types": 3
}
]
}
})";
base::Optional<base::Value> JSON_object =
base::JSONReader::Read(JSON_message);
ASSERT_TRUE(JSON_object) << "Incorrectly formatted JSON string.";
base::Version version = ExtractVersionFromJsonObject(JSON_object.value());
base::Optional<PatternProvider::Map> optional_patterns =
GetConfigurationFromJsonObject(JSON_object.value());
ASSERT_TRUE(version.IsValid());
ASSERT_TRUE(optional_patterns);
ASSERT_EQ(base::Version("1.0"), version);
PatternProvider::Map patterns = optional_patterns.value();
ASSERT_EQ(2U, patterns.size());
ASSERT_TRUE(patterns.count("FULL_NAME"));
ASSERT_EQ(2U, patterns["FULL_NAME"].size());
ASSERT_TRUE(patterns["FULL_NAME"].count("en_us"));
ASSERT_TRUE(patterns["FULL_NAME"].count("fr"));
ASSERT_TRUE(patterns.count("ADDRESS"));
ASSERT_EQ(1U, patterns["ADDRESS"].size());
ASSERT_TRUE(patterns["ADDRESS"].count("en_us"));
// Test one |MatchingPattern| to check that they are parsed correctly.
MatchingPattern* pattern = &patterns["FULL_NAME"]["fr"][0];
ASSERT_EQ("Name_fr", pattern->pattern_identifier);
ASSERT_EQ("nom|prenom", pattern->positive_pattern);
ASSERT_EQ("compagne", pattern->negative_pattern);
ASSERT_EQ("fr", pattern->language);
ASSERT_NEAR(2.0, pattern->positive_score, 1e-6);
ASSERT_EQ(2, pattern->match_field_attributes);
ASSERT_EQ(3, pattern->match_field_input_types);
}
// Test that the parser does not return anything if some |MatchingPattern|
// object is missing a property.
TEST(PatternConfigurationParserTest, MalformedMissingProperty) {
std::string JSON_message = R"(
{
"version": "1.0",
"FULL_NAME": {
"en_us": [
{
"pattern_identifier": "Name_en",
"positive_pattern": "name|full name",
"positive_score": 2.0,
"negative_pattern": "company",
"match_field_attributes": 2,
"match_field_input_types": 3
}
],
"fr": [
{
"pattern_identifier": "Name_fr",
"positive_pattern": "nom|prenom",
"negative_pattern": "compagne",
"match_field_attributes": 2,
"match_field_input_types": 3
}
]
}
})";
base::Optional<base::Value> JSON_object =
base::JSONReader::Read(JSON_message);
ASSERT_TRUE(JSON_object) << "Incorrectly formatted JSON string.";
base::Optional<PatternProvider::Map> optional_patterns =
GetConfigurationFromJsonObject(JSON_object.value());
ASSERT_FALSE(optional_patterns);
}
// Test that the parser correctly sets the default version if
// it is not present in the configuration.
TEST(PatternConfigurationParserTest, MalformedMissingVersion) {
std::string JSON_message = R"(
{
"FULL_NAME": {
"en_us": [
{
"pattern_identifier": "Name_en",
"positive_pattern": "name|full name",
"positive_score": 2.0,
"negative_pattern": "company",
"match_field_attributes": 2,
"match_field_input_types": 3
}
]
}
})";
base::Optional<base::Value> JSON_object =
base::JSONReader::Read(JSON_message);
ASSERT_TRUE(JSON_object) << "Incorrectly formatted JSON string.";
base::Version version = ExtractVersionFromJsonObject(JSON_object.value());
ASSERT_EQ(base::Version("0"), version);
}
// Test that the parser does not return anything if the inner key points
// to a single object instead of a list.
TEST(PatternConfigurationParserTest, MalformedNotList) {
std::string JSON_message = R"(
{
"FULL_NAME": {
"en_us": {
"pattern_identifier": "Name_en",
"positive_pattern": "name|full name",
"positive_score": 2.0,
"negative_pattern": "company",
"match_field_attributes": 2,
"match_field_input_types": 3
}
}
})";
base::Optional<base::Value> JSON_object =
base::JSONReader::Read(JSON_message);
ASSERT_TRUE(JSON_object) << "Incorrectly formatted JSON string.";
base::Optional<PatternProvider::Map> optional_patterns =
GetConfigurationFromJsonObject(JSON_object.value());
ASSERT_FALSE(optional_patterns);
}
} // namespace field_type_parsing
} // namespace autofill
...@@ -8,29 +8,36 @@ ...@@ -8,29 +8,36 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
#include "base/bind.h"
#include "base/no_destructor.h"
#include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/pattern_provider/pattern_configuration_parser.h"
namespace autofill { namespace autofill {
PatternProvider::PatternProvider() { namespace {
auto& company_patterns = patterns_[AutofillType(COMPANY_NAME).ToString()]; PatternProvider* g_pattern_provider = nullptr;
company_patterns["EN"].push_back(GetCompanyPatternEn());
company_patterns["DE"].push_back(GetCompanyPatternDe());
} }
PatternProvider::~PatternProvider() { PatternProvider::PatternProvider() = default;
patterns_.clear(); PatternProvider::~PatternProvider() = default;
}
void PatternProvider::SetPatterns(PatternProvider::Map patterns,
const base::Version version,
const bool overwrite_equal_version) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
void PatternProvider::SetPatterns( if (!pattern_version_.IsValid() || pattern_version_ < version ||
const std::map<std::string, (overwrite_equal_version && pattern_version_ == version)) {
std::map<std::string, std::vector<MatchingPattern>>>& patterns_ = patterns;
patterns) { pattern_version_ = version;
patterns_ = patterns; }
} }
const std::vector<MatchingPattern>& PatternProvider::GetMatchPatterns( const std::vector<MatchingPattern>& PatternProvider::GetMatchPatterns(
const std::string& pattern_name, const std::string& pattern_name,
const std::string& page_language) { const std::string& page_language) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return patterns_[pattern_name][page_language]; return patterns_[pattern_name][page_language];
} }
...@@ -41,9 +48,26 @@ const std::vector<MatchingPattern>& PatternProvider::GetMatchPatterns( ...@@ -41,9 +48,26 @@ const std::vector<MatchingPattern>& PatternProvider::GetMatchPatterns(
return GetMatchPatterns(pattern_name, page_language); return GetMatchPatterns(pattern_name, page_language);
} }
PatternProvider* PatternProvider::getInstance() { // static.
static base::NoDestructor<PatternProvider> instance; PatternProvider& PatternProvider::GetInstance() {
return instance.get(); if (!g_pattern_provider) {
static base::NoDestructor<PatternProvider> instance;
g_pattern_provider = instance.get();
field_type_parsing::PopulateFromResourceBundle();
}
return *g_pattern_provider;
}
// static.
void PatternProvider::SetPatternProviderForTesting(
PatternProvider* pattern_provider) {
DCHECK(pattern_provider);
g_pattern_provider = pattern_provider;
}
// static.
void PatternProvider::ResetPatternProvider() {
g_pattern_provider = nullptr;
} }
} // namespace autofill } // namespace autofill
...@@ -7,24 +7,33 @@ ...@@ -7,24 +7,33 @@
#include <string> #include <string>
#include "base/gtest_prod_util.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/no_destructor.h" #include "base/no_destructor.h"
#include "base/sequence_checker.h"
#include "base/version.h"
#include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/form_parsing/autofill_parsing_utils.h" #include "components/autofill/core/browser/form_parsing/autofill_parsing_utils.h"
#include "components/autofill/core/common/autofill_regex_constants.h" #include "components/autofill/core/common/autofill_regex_constants.h"
#include "third_party/re2/src/re2/re2.h"
namespace autofill { namespace autofill {
// Base class for the Pattern Provider. This class contains the implementation
// for providing the matching patterns. Different subclasses provide different
// ways to load the data in for further use.
class PatternProvider { class PatternProvider {
public: public:
static PatternProvider* getInstance(); // Shorthand for the map structure used to store patterns.
using Map = std::map<std::string,
std::map<std::string, std::vector<MatchingPattern>>>;
// Setter for loaded patterns from external storage. // Returns a reference to the global Pattern Provider.
void SetPatterns( static PatternProvider& GetInstance();
const std::map<std::string,
std::map<std::string, std::vector<MatchingPattern>>>& // Setter for loading patterns from external storage.
patterns); void SetPatterns(const Map patterns,
const base::Version version,
const bool overwrite_equal_version);
// Provides us with all patterns that can match our field type and page // Provides us with all patterns that can match our field type and page
// language. // language.
...@@ -40,19 +49,38 @@ class PatternProvider { ...@@ -40,19 +49,38 @@ class PatternProvider {
const std::vector<MatchingPattern>& GetAllPatternsBaseOnType( const std::vector<MatchingPattern>& GetAllPatternsBaseOnType(
ServerFieldType type); ServerFieldType type);
private: protected:
PatternProvider(); PatternProvider();
~PatternProvider(); ~PatternProvider();
// Local map to store a vector of patterns keyed by field type and
// page language.
Map patterns_;
// Version for keeping track which pattern set is in use.
base::Version pattern_version_;
// Sets a provider to be used for tests.
static void SetPatternProviderForTesting(PatternProvider* pattern_provider);
// Resets the provider pointer if the object behind it gets deleted.
static void ResetPatternProvider();
private:
// Func to sort the incoming map by score. // Func to sort the incoming map by score.
void SortPatternsByScore(std::vector<MatchingPattern>& patterns); void SortPatternsByScore(std::vector<MatchingPattern>& patterns);
// Local map to store a vector of patterns keyed by field type and // Sequence checker to ensure thread-safety for pattern swapping.
// page language. // All functions accessing the |patterns_| member variable are
std::map<std::string, std::map<std::string, std::vector<MatchingPattern>>> // expected to be called from the UI thread.
patterns_; SEQUENCE_CHECKER(sequence_checker_);
FRIEND_TEST_ALL_PREFIXES(AutofillPatternProviderPipelineTest,
TestParsingEquivalent);
FRIEND_TEST_ALL_PREFIXES(AutofillPatternProviderPipelineTest,
DefaultPatternProviderLoads);
friend class base::NoDestructor<PatternProvider>; friend class base::NoDestructor<PatternProvider>;
}; };
} // namespace autofill } // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PATTERN_PROVIDER_PATTERN_PROVIDER_H_ #endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PATTERN_PROVIDER_PATTERN_PROVIDER_H_
\ No newline at end of file
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "components/autofill/core/browser/pattern_provider/pattern_provider.h"
#include <stddef.h> #include <stddef.h>
#include <map> #include <map>
...@@ -11,10 +9,46 @@ ...@@ -11,10 +9,46 @@
#include <vector> #include <vector>
#include "base/test/gtest_util.h" #include "base/test/gtest_util.h"
#include "base/test/task_environment.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/pattern_provider/pattern_configuration_parser.h"
#include "components/autofill/core/browser/pattern_provider/pattern_provider.h"
#include "components/autofill/core/browser/pattern_provider/test_pattern_provider.h"
#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace autofill { namespace autofill {
namespace {
// Pattern Provider with custom values set for testing.
class UnitTestPatternProvider : public PatternProvider {
public:
UnitTestPatternProvider();
~UnitTestPatternProvider();
};
UnitTestPatternProvider::UnitTestPatternProvider() {
auto& company_patterns = patterns_[AutofillType(COMPANY_NAME).ToString()];
company_patterns["EN"].push_back(GetCompanyPatternEn());
company_patterns["DE"].push_back(GetCompanyPatternDe());
PatternProvider::SetPatternProviderForTesting(this);
}
UnitTestPatternProvider::~UnitTestPatternProvider() {
PatternProvider::ResetPatternProvider();
}
} // namespace
class AutofillPatternProviderTest : public testing::Test {
protected:
UnitTestPatternProvider pattern_provider_;
~AutofillPatternProviderTest() override = default;
};
bool operator==(const MatchingPattern& mp1, const MatchingPattern& mp2) { bool operator==(const MatchingPattern& mp1, const MatchingPattern& mp2) {
return (mp1.language == mp2.language && return (mp1.language == mp2.language &&
mp1.match_field_attributes == mp2.match_field_attributes && mp1.match_field_attributes == mp2.match_field_attributes &&
...@@ -25,15 +59,50 @@ bool operator==(const MatchingPattern& mp1, const MatchingPattern& mp2) { ...@@ -25,15 +59,50 @@ bool operator==(const MatchingPattern& mp1, const MatchingPattern& mp2) {
mp1.positive_score == mp2.positive_score); mp1.positive_score == mp2.positive_score);
} }
TEST(AutofillPatternProvider, Single_Match) { TEST_F(AutofillPatternProviderTest, Single_Match) {
MatchingPattern kCompanyPatternEn = GetCompanyPatternEn(); MatchingPattern kCompanyPatternEn = GetCompanyPatternEn();
MatchingPattern kCompanyPatternDe = GetCompanyPatternDe(); MatchingPattern kCompanyPatternDe = GetCompanyPatternDe();
PatternProvider* pattern_provider = PatternProvider::getInstance(); PatternProvider& pattern_provider = PatternProvider::GetInstance();
ASSERT_TRUE(pattern_provider->GetMatchPatterns("COMPANY_NAME", "EN").size() > ASSERT_TRUE(pattern_provider.GetMatchPatterns("COMPANY_NAME", "EN").size() >
0); 0);
EXPECT_EQ(pattern_provider->GetMatchPatterns("COMPANY_NAME", "EN")[0], EXPECT_EQ(pattern_provider.GetMatchPatterns("COMPANY_NAME", "EN")[0],
kCompanyPatternEn); kCompanyPatternEn);
} }
} // namespace autofill // Test that the default pattern provider loads without crashing.
\ No newline at end of file TEST(AutofillPatternProviderPipelineTest, DefaultPatternProviderLoads) {
base::test::TaskEnvironment task_environment_;
data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
base::RunLoop run_loop;
field_type_parsing::PopulateFromResourceBundle(run_loop.QuitClosure());
run_loop.Run();
PatternProvider& default_pattern_provider = PatternProvider::GetInstance();
EXPECT_FALSE(default_pattern_provider.patterns_.empty());
// Call the getter to ensure sequence checks work correctly.
default_pattern_provider.GetMatchPatterns("EMAIL_ADDRESS", "en");
}
// Test that the TestPatternProvider class uses a PatternProvider::Map
// equivalent to the DefaultPatternProvider. This is also an example of what is
// needed to test the DefaultPatternProvider. Warning: If this crashes, check
// that no state carried over from other tests using the singleton.
TEST(AutofillPatternProviderPipelineTest, TestParsingEquivalent) {
base::test::TaskEnvironment task_environment_;
data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
base::RunLoop run_loop;
field_type_parsing::PopulateFromResourceBundle(run_loop.QuitClosure());
run_loop.Run();
PatternProvider& default_pattern_provider = PatternProvider::GetInstance();
TestPatternProvider test_pattern_provider;
EXPECT_EQ(default_pattern_provider.patterns_,
test_pattern_provider.patterns_);
}
} // namespace autofill
{
"ATTENTION_IGNORED": {
"en": [
{
"pattern_identifier": "en_attention_ignored_preserving",
"positive_pattern": "attention|attn",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"REGION_IGNORED": {
"en": [
{
"pattern_identifier": "en_region_ignored_preserving",
"positive_pattern": "province|region|other",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"es": [
{
"pattern_identifier": "es_region_ignored_preserving",
"positive_pattern": "provincia",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"pt": [
{
"pattern_identifier": "pt_region_ignored_preserving",
"positive_pattern": "bairro|suburb",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"ADDRESS_NAME_IGNORED": {
"en": [
{
"pattern_identifier": "en_address_name_ignored_preserving",
"positive_pattern": "address.*nickname|address.*label",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"COMPANY": {
"en": [
{
"pattern_identifier": "en_company_preserving",
"positive_pattern": "company|business|organization|organisation",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"de": [
{
"pattern_identifier": "de_company_preserving",
"positive_pattern": "(?<!con)firma|firmenname",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"es": [
{
"pattern_identifier": "es_company_preserving",
"positive_pattern": "empresa",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"fr": [
{
"pattern_identifier": "fr_company_preserving",
"positive_pattern": "societe|société",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"it": [
{
"pattern_identifier": "it_company_preserving",
"positive_pattern": "ragione.?sociale",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ja": [
{
"pattern_identifier": "ja_company_preserving",
"positive_pattern": "会社",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ru": [
{
"pattern_identifier": "ru_company_preserving",
"positive_pattern": "название.?компании",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"zh": [
{
"pattern_identifier": "zh_company_preserving",
"positive_pattern": "单位|公司",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"fa": [
{
"pattern_identifier": "fa_company_preserving",
"positive_pattern": "شرکت",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ko": [
{
"pattern_identifier": "ko_company_preserving",
"positive_pattern": "회사|직장",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"ADDRESS_LINE_1": {
"en": [
{
"pattern_identifier": "en_address_line_1_preserving",
"positive_pattern": "^address$|address[_-]?line(one)?|address1|addr1|street|(?:shipping|billing)address$|house.?name",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 68
}
],
"de": [
{
"pattern_identifier": "de_address_line_1_preserving",
"positive_pattern": "strasse|straße",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 68
}
],
"es": [
{
"pattern_identifier": "es_address_line_1_preserving",
"positive_pattern": "direccion|dirección",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 68
}
],
"fr": [
{
"pattern_identifier": "fr_address_line_1_preserving",
"positive_pattern": "adresse",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 68
}
],
"it": [
{
"pattern_identifier": "it_address_line_1_preserving",
"positive_pattern": "indirizzo",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 68
}
],
"ja": [
{
"pattern_identifier": "ja_address_line_1_preserving",
"positive_pattern": "^住所$|住所1",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 68
}
],
"pt": [
{
"pattern_identifier": "pt_address_line_1_preserving",
"positive_pattern": "morada|((?<!identificação do )endereço)",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 68
}
],
"ru": [
{
"pattern_identifier": "ru_address_line_1_preserving",
"positive_pattern": "Адрес",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 68
}
],
"zh": [
{
"pattern_identifier": "zh_address_line_1_preserving",
"positive_pattern": "地址",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 68
}
],
"tr": [
{
"pattern_identifier": "tr_address_line_1_preserving",
"positive_pattern": "(\\b|_)adres(?! (başlığı(nız)?|tarifi))(\\b|_)",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 68
}
],
"ko": [
{
"pattern_identifier": "ko_address_line_1_preserving",
"positive_pattern": "^주소.?$|주소.?1",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 68
}
]
},
"ADDRESS_LINE_1_LABEL": {
"en": [
{
"pattern_identifier": "en_address_line_1_label_preserving",
"positive_pattern": "(^\\W*address)|(address\\W*$)|(?:shipping|billing|mailing|pick.?up|drop.?off|delivery|sender|postal|recipient|home|work|office|school|business|mail)[\\s\\-]+address|address\\s+(of|for|to|from)",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 1,
"match_field_input_types": 68
}
],
"fr": [
{
"pattern_identifier": "fr_address_line_1_label_preserving",
"positive_pattern": "adresse",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 1,
"match_field_input_types": 68
}
],
"it": [
{
"pattern_identifier": "it_address_line_1_label_preserving",
"positive_pattern": "indirizzo",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 1,
"match_field_input_types": 68
}
],
"ja": [
{
"pattern_identifier": "ja_address_line_1_label_preserving",
"positive_pattern": "住所",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 1,
"match_field_input_types": 68
}
],
"zh": [
{
"pattern_identifier": "zh_address_line_1_label_preserving",
"positive_pattern": "地址",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 1,
"match_field_input_types": 68
}
],
"tr": [
{
"pattern_identifier": "tr_address_line_1_label_preserving",
"positive_pattern": "(\\b|_)adres(?! (başlığı(nız)?|tarifi))(\\b|_)",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 1,
"match_field_input_types": 68
}
],
"ko": [
{
"pattern_identifier": "ko_address_line_1_label_preserving",
"positive_pattern": "주소",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 1,
"match_field_input_types": 68
}
]
},
"ADDRESS_LINE_2": {
"en": [
{
"pattern_identifier": "en_address_line_2_preserving",
"positive_pattern": "address[_-]?line(2|two)|address2|addr2|street|suite|unit",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"de": [
{
"pattern_identifier": "de_address_line_2_preserving",
"positive_pattern": "adresszusatz|ergänzende.?angaben",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"es": [
{
"pattern_identifier": "es_address_line_2_preserving",
"positive_pattern": "direccion2|colonia|adicional",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"fr": [
{
"pattern_identifier": "fr_address_line_2_preserving",
"positive_pattern": "addresssuppl|complementnom|appartement",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"it": [
{
"pattern_identifier": "it_address_line_2_preserving",
"positive_pattern": "indirizzo2",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ja": [
{
"pattern_identifier": "ja_address_line_2_preserving",
"positive_pattern": "住所2",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"pt": [
{
"pattern_identifier": "pt_address_line_2_preserving",
"positive_pattern": "complemento|addrcomplement",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ru": [
{
"pattern_identifier": "ru_address_line_2_preserving",
"positive_pattern": "Улица",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"zh": [
{
"pattern_identifier": "zh_address_line_2_preserving",
"positive_pattern": "地址2",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ko": [
{
"pattern_identifier": "ko_address_line_2_preserving",
"positive_pattern": "주소.?2",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"ADDRESS_LINE_2_LABEL": {
"en": [
{
"pattern_identifier": "en_address_line_2_label_preserving",
"positive_pattern": "address|line",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 1,
"match_field_input_types": 4
}
],
"fr": [
{
"pattern_identifier": "fr_address_line_2_label_preserving",
"positive_pattern": "adresse",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 1,
"match_field_input_types": 4
}
],
"it": [
{
"pattern_identifier": "it_address_line_2_label_preserving",
"positive_pattern": "indirizzo",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 1,
"match_field_input_types": 4
}
],
"zh": [
{
"pattern_identifier": "zh_address_line_2_label_preserving",
"positive_pattern": "地址",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 1,
"match_field_input_types": 4
}
],
"ko": [
{
"pattern_identifier": "ko_address_line_2_label_preserving",
"positive_pattern": "주소",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 1,
"match_field_input_types": 4
}
]
},
"ADDRESS_LINE_EXTRA": {
"en": [
{
"pattern_identifier": "en_address_line_extra_preserving",
"positive_pattern": "address.*line[3-9]|address[3-9]|addr[3-9]|street|line[3-9]",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"es": [
{
"pattern_identifier": "es_address_line_extra_preserving",
"positive_pattern": "municipio",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"fr": [
{
"pattern_identifier": "fr_address_line_extra_preserving",
"positive_pattern": "batiment|residence",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"it": [
{
"pattern_identifier": "it_address_line_extra_preserving",
"positive_pattern": "indirizzo[3-9]",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"ADDRESS_LOOKUP": {
"en": [
{
"pattern_identifier": "en_address_lookup_preserving",
"positive_pattern": "lookup",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"COUNTRY": {
"en": [
{
"pattern_identifier": "en_country_preserving",
"positive_pattern": "country|countries",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"es": [
{
"pattern_identifier": "es_country_preserving",
"positive_pattern": "país|pais",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"de": [
{
"pattern_identifier": "de_country_preserving",
"positive_pattern": "(\\b|_)land(\\b|_)(?!.*(mark.*))",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"ja": [
{
"pattern_identifier": "ja_country_preserving",
"positive_pattern": "(?<!(入|出))国",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"zh": [
{
"pattern_identifier": "zh_country_preserving",
"positive_pattern": "国家",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"ko": [
{
"pattern_identifier": "ko_country_preserving",
"positive_pattern": "국가|나라",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"tr": [
{
"pattern_identifier": "tr_country_preserving",
"positive_pattern": "(\\b|_)(ülke|ulce|ulke)(\\b|_)",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"fa": [
{
"pattern_identifier": "fa_country_preserving",
"positive_pattern": "کشور",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
]
},
"COUNTRY_LOCATION": {
"en": [
{
"pattern_identifier": "en_country_location_preserving",
"positive_pattern": "location",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 544
}
]
},
"ZIP_CODE": {
"en": [
{
"pattern_identifier": "en_zip_code_preserving",
"positive_pattern": "zip|postal|post.*code|pcode|pin.?code",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"de": [
{
"pattern_identifier": "de_zip_code_preserving",
"positive_pattern": "postleitzahl",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"es": [
{
"pattern_identifier": "es_zip_code_preserving",
"positive_pattern": "\\bcp\\b",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"fr": [
{
"pattern_identifier": "fr_zip_code_preserving",
"positive_pattern": "\\bcdp\\b",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"it": [
{
"pattern_identifier": "it_zip_code_preserving",
"positive_pattern": "\\bcap\\b",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"ja": [
{
"pattern_identifier": "ja_zip_code_preserving",
"positive_pattern": "郵便番号",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"pt": [
{
"pattern_identifier": "pt_zip_code_preserving",
"positive_pattern": "codigo|codpos|\\bcep\\b",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"ru": [
{
"pattern_identifier": "ru_zip_code_preserving",
"positive_pattern": "Почтовый.?Индекс",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"hi": [
{
"pattern_identifier": "hi_zip_code_preserving",
"positive_pattern": "पिन.?कोड",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"ml": [
{
"pattern_identifier": "ml_zip_code_preserving",
"positive_pattern": "പിന്‍കോഡ്",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"zh": [
{
"pattern_identifier": "zh_zip_code_preserving",
"positive_pattern": "邮政编码|邮编|郵遞區號",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"tr": [
{
"pattern_identifier": "tr_zip_code_preserving",
"positive_pattern": "(\\b|_)posta kodu(\\b|_)",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"ko": [
{
"pattern_identifier": "ko_zip_code_preserving",
"positive_pattern": "우편.?번호",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
]
},
"ZIP_4": {
"en": [
{
"pattern_identifier": "en_zip_4_preserving",
"positive_pattern": "zip|^-$|post2",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"pt": [
{
"pattern_identifier": "pt_zip_4_preserving",
"positive_pattern": "codpos2",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
]
},
"CITY": {
"en": [
{
"pattern_identifier": "en_city_preserving",
"positive_pattern": "city|town|suburb",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"de": [
{
"pattern_identifier": "de_city_preserving",
"positive_pattern": "\\bort\\b|stadt",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"es": [
{
"pattern_identifier": "es_city_preserving",
"positive_pattern": "ciudad|provincia|localidad|poblacion",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"fr": [
{
"pattern_identifier": "fr_city_preserving",
"positive_pattern": "ville|commune",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"it": [
{
"pattern_identifier": "it_city_preserving",
"positive_pattern": "localita",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"ja": [
{
"pattern_identifier": "ja_city_preserving",
"positive_pattern": "市区町村",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"pt": [
{
"pattern_identifier": "pt_city_preserving",
"positive_pattern": "cidade",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"ru": [
{
"pattern_identifier": "ru_city_preserving",
"positive_pattern": "Город",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"zh": [
{
"pattern_identifier": "zh_city_preserving",
"positive_pattern": "市|分區",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"fa": [
{
"pattern_identifier": "fa_city_preserving",
"positive_pattern": "شهر",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"hi": [
{
"pattern_identifier": "hi_city_preserving",
"positive_pattern": "शहर|ग्राम|गाँव",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"ml": [
{
"pattern_identifier": "ml_city_preserving",
"positive_pattern": "നഗരം|ഗ്രാമം",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"tr": [
{
"pattern_identifier": "tr_city_preserving",
"positive_pattern": "((\\b|_|\\*)([İii̇]l[cç]e(miz|niz)?)(\\b|_|\\*))",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"ko": [
{
"pattern_identifier": "ko_city_preserving",
"positive_pattern": "^시[^도·・]|시[·・]?군[·・]?구",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
]
},
"STATE": {
"en": [
{
"pattern_identifier": "en_state_preserving",
"positive_pattern": "(?<!(united|hist|history).?)state|county|region|province|county|principality",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"ja": [
{
"pattern_identifier": "ja_state_preserving",
"positive_pattern": "都道府県",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"pt": [
{
"pattern_identifier": "pt_state_preserving",
"positive_pattern": "estado|provincia",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"ru": [
{
"pattern_identifier": "ru_state_preserving",
"positive_pattern": "область",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"zh": [
{
"pattern_identifier": "zh_state_preserving",
"positive_pattern": "省|地區",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"ml": [
{
"pattern_identifier": "ml_state_preserving",
"positive_pattern": "സംസ്ഥാനം",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"fa": [
{
"pattern_identifier": "fa_state_preserving",
"positive_pattern": "استان",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"hi": [
{
"pattern_identifier": "hi_state_preserving",
"positive_pattern": "राज्य",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"tr": [
{
"pattern_identifier": "tr_state_preserving",
"positive_pattern": "((\\b|_|\\*)(eyalet|[şs]ehir|[İii̇]l(imiz)?|kent)(\\b|_|\\*))",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
],
"ko": [
{
"pattern_identifier": "ko_state_preserving",
"positive_pattern": "^시[·・]?도",
"positive_score": 1.1,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 548
}
]
},
"SEARCH_TERM": {
"en": [
{
"pattern_identifier": "en_search_term_preserving",
"positive_pattern": "^q$|search|query|qry",
"positive_score": 0.8,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 580
}
],
"de": [
{
"pattern_identifier": "de_search_term_preserving",
"positive_pattern": "suche.*",
"positive_score": 0.8,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 580
}
],
"zh": [
{
"pattern_identifier": "zh_search_term_preserving",
"positive_pattern": "搜索",
"positive_score": 0.8,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 580
}
],
"ja": [
{
"pattern_identifier": "ja_search_term_preserving",
"positive_pattern": "探す|検索",
"positive_score": 0.8,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 580
}
],
"fr": [
{
"pattern_identifier": "fr_search_term_preserving",
"positive_pattern": "recherch.*",
"positive_score": 0.8,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 580
}
],
"pt": [
{
"pattern_identifier": "pt_search_term_preserving",
"positive_pattern": "busca",
"positive_score": 0.8,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 580
}
],
"fa": [
{
"pattern_identifier": "fa_search_term_preserving",
"positive_pattern": "جستجو",
"positive_score": 0.8,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 580
}
],
"ru": [
{
"pattern_identifier": "ru_search_term_preserving",
"positive_pattern": "искать|найти|поиск",
"positive_score": 0.8,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 580
}
]
},
"PRICE": {
"en": [
{
"pattern_identifier": "en_price_preserving",
"positive_pattern": "\\bprice\\b|\\brate\\b|\\bcost\\b",
"positive_score": 0.95,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 868
}
],
"ar": [
{
"pattern_identifier": "ar_price_preserving",
"positive_pattern": "قیمة‎|سعر‎",
"positive_score": 0.95,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 868
}
],
"fa": [
{
"pattern_identifier": "fa_price_preserving",
"positive_pattern": "قیمت",
"positive_score": 0.95,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 868
}
],
"fr": [
{
"pattern_identifier": "fr_price_preserving",
"positive_pattern": "\\bprix\\b|\\bcoût\\b|\\bcout\\b|\\btarif\\b",
"positive_score": 0.95,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 868
}
]
},
"NAME_ON_CARD": {
"en": [
{
"pattern_identifier": "en_name_on_card_preserving",
"positive_pattern": "card.?(?:holder|owner)|name.*(\\b)?on(\\b)?.*card|(?:card|cc).?name|cc.?full.?name",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"de": [
{
"pattern_identifier": "de_name_on_card_preserving",
"positive_pattern": "karteninhaber",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"es": [
{
"pattern_identifier": "es_name_on_card_preserving",
"positive_pattern": "nombre.*tarjeta",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"fr": [
{
"pattern_identifier": "fr_name_on_card_preserving",
"positive_pattern": "nom.*carte",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"it": [
{
"pattern_identifier": "it_name_on_card_preserving",
"positive_pattern": "nome.*cart",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ja": [
{
"pattern_identifier": "ja_name_on_card_preserving",
"positive_pattern": "名前",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ru": [
{
"pattern_identifier": "ru_name_on_card_preserving",
"positive_pattern": "Имя.*карты",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"zh": [
{
"pattern_identifier": "zh_name_on_card_preserving",
"positive_pattern": "信用卡开户名|开户名|持卡人姓名|持卡人姓名",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"NAME_ON_CARD_CONTEXTUAL": {
"en": [
{
"pattern_identifier": "en_name_on_card_contextual_preserving",
"positive_pattern": "name",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"CARD_NUMBER": {
"en": [
{
"pattern_identifier": "en_card_number_preserving",
"positive_pattern": "(add)?(?:card|cc|acct).?(?:number|#|no|num|field)",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 404
}
],
"de": [
{
"pattern_identifier": "de_card_number_preserving",
"positive_pattern": "(?<!telefon|haus|person|fødsels)nummer",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 404
}
],
"ja": [
{
"pattern_identifier": "ja_card_number_preserving",
"positive_pattern": "カード番号",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 404
}
],
"ru": [
{
"pattern_identifier": "ru_card_number_preserving",
"positive_pattern": "Номер.*карты",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 404
}
],
"zh": [
{
"pattern_identifier": "zh_card_number_preserving",
"positive_pattern": "信用卡号|信用卡号码|信用卡卡號",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 404
}
],
"ko": [
{
"pattern_identifier": "ko_card_number_preserving",
"positive_pattern": "카드",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 404
}
],
"es": [
{
"pattern_identifier": "es_card_number_preserving",
"positive_pattern": "(numero|número|numéro)(?!.*(document|fono|phone|réservation))",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 404
}
],
"pt": [
{
"pattern_identifier": "pt_card_number_preserving",
"positive_pattern": "(numero|número|numéro)(?!.*(document|fono|phone|réservation))",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 404
}
],
"fr": [
{
"pattern_identifier": "fr_card_number_preserving",
"positive_pattern": "(numero|número|numéro)(?!.*(document|fono|phone|réservation))",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 404
}
]
},
"CARD_CVC": {
"en": [
{
"pattern_identifier": "en_card_cvc_preserving",
"positive_pattern": "verification|card.?identification|security.?code|card.?code|security.?value|security.?number|card.?pin|c-v-v|(cvn|cvv|cvc|csc|cvd|cid|ccv)(field)?|\\bcid\\b",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 404
}
]
},
"CARD_EXP_MONTH": {
"en": [
{
"pattern_identifier": "en_card_exp_month_preserving",
"positive_pattern": "expir|exp.*mo|exp.*date|ccmonth|cardmonth|addmonth",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"de": [
{
"pattern_identifier": "de_card_exp_month_preserving",
"positive_pattern": "gueltig|gültig|monat",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"es": [
{
"pattern_identifier": "es_card_exp_month_preserving",
"positive_pattern": "fecha",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"fr": [
{
"pattern_identifier": "fr_card_exp_month_preserving",
"positive_pattern": "date.*exp",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"it": [
{
"pattern_identifier": "it_card_exp_month_preserving",
"positive_pattern": "scadenza",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"ja": [
{
"pattern_identifier": "ja_card_exp_month_preserving",
"positive_pattern": "有効期限",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"pt": [
{
"pattern_identifier": "pt_card_exp_month_preserving",
"positive_pattern": "validade",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"ru": [
{
"pattern_identifier": "ru_card_exp_month_preserving",
"positive_pattern": "Срок действия карты",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"zh": [
{
"pattern_identifier": "zh_card_exp_month_preserving",
"positive_pattern": "月",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
]
},
"CARD_EXP_YEAR": {
"en": [
{
"pattern_identifier": "en_card_exp_year_preserving",
"positive_pattern": "exp|^/|(add)?year",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"de": [
{
"pattern_identifier": "de_card_exp_year_preserving",
"positive_pattern": "ablaufdatum|gueltig|gültig|jahr",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"es": [
{
"pattern_identifier": "es_card_exp_year_preserving",
"positive_pattern": "fecha",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"it": [
{
"pattern_identifier": "it_card_exp_year_preserving",
"positive_pattern": "scadenza",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"ja": [
{
"pattern_identifier": "ja_card_exp_year_preserving",
"positive_pattern": "有効期限",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"pt": [
{
"pattern_identifier": "pt_card_exp_year_preserving",
"positive_pattern": "validade",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"ru": [
{
"pattern_identifier": "ru_card_exp_year_preserving",
"positive_pattern": "Срок действия карты",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"zh": [
{
"pattern_identifier": "zh_card_exp_year_preserving",
"positive_pattern": "年|有效期",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
]
},
"CARD_EXP_DATE_2_DIGIT_YEAR": {
"en": [
{
"pattern_identifier": "en_card_exp_date_2_digit_year_preserving",
"positive_pattern": "(?:exp.*date[^y\\n\\r]*|mm\\s*[-/]?\\s*)yy(?:[^y]|$)",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
]
},
"CARD_EXP_DATE_4_DIGIT_YEAR": {
"en": [
{
"pattern_identifier": "en_card_exp_date_4_digit_year_preserving",
"positive_pattern": "(?:exp.*date[^y\\n\\r]*|mm\\s*[-/]?\\s*)yyyy(?:[^y]|$)",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
]
},
"CARD_EXP_DATE": {
"en": [
{
"pattern_identifier": "en_card_exp_date_preserving",
"positive_pattern": "expir|exp.*date|^expfield$",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"de": [
{
"pattern_identifier": "de_card_exp_date_preserving",
"positive_pattern": "gueltig|gültig",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"es": [
{
"pattern_identifier": "es_card_exp_date_preserving",
"positive_pattern": "fecha",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"fr": [
{
"pattern_identifier": "fr_card_exp_date_preserving",
"positive_pattern": "date.*exp",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"it": [
{
"pattern_identifier": "it_card_exp_date_preserving",
"positive_pattern": "scadenza",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"ja": [
{
"pattern_identifier": "ja_card_exp_date_preserving",
"positive_pattern": "有効期限",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"pt": [
{
"pattern_identifier": "pt_card_exp_date_preserving",
"positive_pattern": "validade",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
],
"ru": [
{
"pattern_identifier": "ru_card_exp_date_preserving",
"positive_pattern": "Срок действия карты",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 948
}
]
},
"GIFT_CARD": {
"en": [
{
"pattern_identifier": "en_gift_card_preserving",
"positive_pattern": "gift.?(card|cert)",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 788
}
]
},
"DEBIT_GIFT_CARD": {
"en": [
{
"pattern_identifier": "en_debit_gift_card_preserving",
"positive_pattern": "(?:visa|mastercard|discover|amex|american express).*gift.?card",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 788
}
]
},
"DEBIT_CARD": {
"en": [
{
"pattern_identifier": "en_debit_card_preserving",
"positive_pattern": "debit.*card",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 788
}
]
},
"DAY": {
"en": [
{
"pattern_identifier": "en_day_preserving",
"positive_pattern": "day",
"positive_score": 1.0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 36
}
]
},
"EMAIL_ADDRESS": {
"en": [
{
"pattern_identifier": "en_email_preserving",
"positive_pattern": "e.?mail",
"positive_score": 1.4,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 12
}
],
"fr": [
{
"pattern_identifier": "fr_email_preserving",
"positive_pattern": "courriel",
"positive_score": 1.4,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 12
}
],
"es": [
{
"pattern_identifier": "es_email_preserving",
"positive_pattern": "correo.*electr(o|ó)nico",
"positive_score": 1.4,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 12
}
],
"ja": [
{
"pattern_identifier": "ja_email_preserving",
"positive_pattern": "メールアドレス",
"positive_score": 1.4,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 12
}
],
"ru": [
{
"pattern_identifier": "ru_email_preserving",
"positive_pattern": "Электронной.?Почты",
"positive_score": 1.4,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 12
}
],
"zh": [
{
"pattern_identifier": "zh_email_preserving",
"positive_pattern": "邮件|邮箱|電郵地址",
"positive_score": 1.4,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 12
}
],
"ml": [
{
"pattern_identifier": "ml_email_preserving",
"positive_pattern": "ഇ-മെയില്‍|ഇലക്ട്രോണിക്.?മെയിൽ",
"positive_score": 1.4,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 12
}
],
"fa": [
{
"pattern_identifier": "fa_email_preserving",
"positive_pattern": "ایمیل|پست.*الکترونیک",
"positive_score": 1.4,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 12
}
],
"hi": [
{
"pattern_identifier": "hi_email_preserving",
"positive_pattern": "ईमेल|इलॅक्ट्रॉनिक.?मेल",
"positive_score": 1.4,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 12
}
],
"tr": [
{
"pattern_identifier": "tr_email_preserving",
"positive_pattern": "(\\b|_)eposta(\\b|_)",
"positive_score": 1.4,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 12
}
],
"ko": [
{
"pattern_identifier": "ko_email_preserving",
"positive_pattern": "(?:이메일|전자.?우편|[Ee]-?mail)(.?주소)?",
"positive_score": 1.4,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 12
}
]
},
"NAME_IGNORED": {
"en": [
{
"pattern_identifier": "en_name_ignored_preserving",
"positive_pattern": "user.?name|user.?id|nickname|maiden name|title|prefix|suffix",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"tr": [
{
"pattern_identifier": "tr_name_ignored_preserving",
"positive_pattern": "adres başlığınız",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"de": [
{
"pattern_identifier": "de_name_ignored_preserving",
"positive_pattern": "vollständiger.?name",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"zh": [
{
"pattern_identifier": "zh_name_ignored_preserving",
"positive_pattern": "用户名",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ko": [
{
"pattern_identifier": "ko_name_ignored_preserving",
"positive_pattern": "(?:사용자.?)?아이디|사용자.?ID",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"FULL_NAME": {
"en": [
{
"pattern_identifier": "en_full_name_preserving",
"positive_pattern": "^name|full.?name|your.?name|customer.?name|bill.?name|ship.?name|name.*first.*last|firstandlastname",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"es": [
{
"pattern_identifier": "es_full_name_preserving",
"positive_pattern": "nombre.*y.*apellidos",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"fr": [
{
"pattern_identifier": "fr_full_name_preserving",
"positive_pattern": "^nom(?!bre)",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ja": [
{
"pattern_identifier": "ja_full_name_preserving",
"positive_pattern": "お名前|氏名",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"pt": [
{
"pattern_identifier": "pt_full_name_preserving",
"positive_pattern": "^nome",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"fa": [
{
"pattern_identifier": "fa_full_name_preserving",
"positive_pattern": "نام.*نام.*خانوادگی",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"zh": [
{
"pattern_identifier": "zh_full_name_preserving",
"positive_pattern": "姓名",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"tr": [
{
"pattern_identifier": "tr_full_name_preserving",
"positive_pattern": "(\\b|_|\\*)ad[ı]? soyad[ı]?(\\b|_|\\*)",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ko": [
{
"pattern_identifier": "ko_full_name_preserving",
"positive_pattern": "성명",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"NAME_SPECIFIC": {
"en": [
{
"pattern_identifier": "en_name_specific_preserving",
"positive_pattern": "^name",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"fr": [
{
"pattern_identifier": "fr_name_specific_preserving",
"positive_pattern": "^nom",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"pt": [
{
"pattern_identifier": "pt_name_specific_preserving",
"positive_pattern": "^nome",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"FIRST_NAME": {
"en": [
{
"pattern_identifier": "en_first_name_preserving",
"positive_pattern": "first.*name|initials|fname|first$|given.*name",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"de": [
{
"pattern_identifier": "de_first_name_preserving",
"positive_pattern": "vorname",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"es": [
{
"pattern_identifier": "es_first_name_preserving",
"positive_pattern": "nombre",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"fr": [
{
"pattern_identifier": "fr_first_name_preserving",
"positive_pattern": "forename|prénom|prenom",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ja": [
{
"pattern_identifier": "ja_first_name_preserving",
"positive_pattern": "名",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"pt": [
{
"pattern_identifier": "pt_first_name_preserving",
"positive_pattern": "nome",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ru": [
{
"pattern_identifier": "ru_first_name_preserving",
"positive_pattern": "Имя",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"fa": [
{
"pattern_identifier": "fa_first_name_preserving",
"positive_pattern": "نام",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ko": [
{
"pattern_identifier": "ko_first_name_preserving",
"positive_pattern": "이름",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ml": [
{
"pattern_identifier": "ml_first_name_preserving",
"positive_pattern": "പേര്",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"tr": [
{
"pattern_identifier": "tr_first_name_preserving",
"positive_pattern": "(\\b|_|\\*)(isim|ad|ad(i|ı|iniz|ınız)?)(\\b|_|\\*)",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"hi": [
{
"pattern_identifier": "hi_first_name_preserving",
"positive_pattern": "नाम",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"MIDDLE_INITIAL": {
"en": [
{
"pattern_identifier": "en_middle_initial_preserving",
"positive_pattern": "middle.*initial|m\\.i\\.|mi$|\\bmi\\b",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"MIDDLE_NAME": {
"en": [
{
"pattern_identifier": "en_middle_name_preserving",
"positive_pattern": "middle.*name|mname|middle$",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"LAST_NAME": {
"en": [
{
"pattern_identifier": "en_last_name_preserving",
"positive_pattern": "last.*name|lname|surname(?!\\d)|last$|secondname|family.*name",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"de": [
{
"pattern_identifier": "de_last_name_preserving",
"positive_pattern": "nachname",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"es": [
{
"pattern_identifier": "es_last_name_preserving",
"positive_pattern": "apellidos?",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"fr": [
{
"pattern_identifier": "fr_last_name_preserving",
"positive_pattern": "famille|^nom(?!bre)",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"it": [
{
"pattern_identifier": "it_last_name_preserving",
"positive_pattern": "cognome",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ja": [
{
"pattern_identifier": "ja_last_name_preserving",
"positive_pattern": "姓",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"pt": [
{
"pattern_identifier": "pt_last_name_preserving",
"positive_pattern": "apelidos|surename|sobrenome",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ru": [
{
"pattern_identifier": "ru_last_name_preserving",
"positive_pattern": "Фамилия",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"fa": [
{
"pattern_identifier": "fa_last_name_preserving",
"positive_pattern": "نام.*خانوادگی",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"hi": [
{
"pattern_identifier": "hi_last_name_preserving",
"positive_pattern": "उपनाम",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ml": [
{
"pattern_identifier": "ml_last_name_preserving",
"positive_pattern": "മറുപേര്",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"tr": [
{
"pattern_identifier": "tr_last_name_preserving",
"positive_pattern": "(\\b|_|\\*)(soyisim|soyad(i|ı|iniz|ınız)?)(\\b|_|\\*)",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ko": [
{
"pattern_identifier": "ko_last_name_preserving",
"positive_pattern": "\\b성(?:[^명]|\\b)",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"LAST_NAME_FIRST": {
"es": [
{
"pattern_identifier": "es_last_name_first_preserving",
"positive_pattern": "(primer.*apellido)|(apellido1)|(apellido.*paterno)|surname_?1|first(\\s|_)?surname",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"LAST_NAME_SECOND": {
"es": [
{
"pattern_identifier": "es_last_name_second_preserving",
"positive_pattern": "(segund.*apellido)|(apellido2)|(apellido.*materno)|surname_?2|second(\\s|_)?surname",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"HONORIFIC_PREFIX": {
"en": [
{
"pattern_identifier": "en_honorific_prefix_preserving",
"positive_pattern": "^title:?$|(salutation(?! and given name))",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"de": [
{
"pattern_identifier": "de_honorific_prefix_preserving",
"positive_pattern": "anrede|titel",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"es": [
{
"pattern_identifier": "es_honorific_prefix_preserving",
"positive_pattern": "tratamiento|encabezamiento",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"it": [
{
"pattern_identifier": "it_honorific_prefix_preserving",
"positive_pattern": "titolo",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"fr": [
{
"pattern_identifier": "fr_honorific_prefix_preserving",
"positive_pattern": "titre",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ru": [
{
"pattern_identifier": "ru_honorific_prefix_preserving",
"positive_pattern": "обраще́ние|зва́ние",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"el": [
{
"pattern_identifier": "el_honorific_prefix_preserving",
"positive_pattern": "προσφώνηση",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"tr": [
{
"pattern_identifier": "tr_honorific_prefix_preserving",
"positive_pattern": "hitap",
"positive_score": 0.9,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"PHONE": {
"en": [
{
"pattern_identifier": "en_phone_preserving",
"positive_pattern": "phone|mobile|contact.?number",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"de": [
{
"pattern_identifier": "de_phone_preserving",
"positive_pattern": "telefonnummer",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"es": [
{
"pattern_identifier": "es_phone_preserving",
"positive_pattern": "telefono|teléfono",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"fr": [
{
"pattern_identifier": "fr_phone_preserving",
"positive_pattern": "telfixe",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"ja": [
{
"pattern_identifier": "ja_phone_preserving",
"positive_pattern": "電話",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"pt": [
{
"pattern_identifier": "pt_phone_preserving",
"positive_pattern": "telefone|telemovel",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"ru": [
{
"pattern_identifier": "ru_phone_preserving",
"positive_pattern": "телефон",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"hi": [
{
"pattern_identifier": "hi_phone_preserving",
"positive_pattern": "मोबाइल",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"tr": [
{
"pattern_identifier": "tr_phone_preserving",
"positive_pattern": "(\\b|_|\\*)telefon(\\b|_|\\*)",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"zh": [
{
"pattern_identifier": "zh_phone_preserving",
"positive_pattern": "电话",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"ml": [
{
"pattern_identifier": "ml_phone_preserving",
"positive_pattern": "മൊബൈല്‍",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"ko": [
{
"pattern_identifier": "ko_phone_preserving",
"positive_pattern": "(?:전화|핸드폰|휴대폰|휴대전화)(?:.?번호)?",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
]
},
"AUGMENTED_PHONE_COUNTRY_CODE": {
"en": [
{
"pattern_identifier": "en_augmented_phone_country_code_preserving",
"positive_pattern": "^[^0-9+]*(?:\\+|00)\\s*([1-9]\\d{0,3})\\D*$",
"positive_score": 1.3,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"PHONE_COUNTRY_CODE": {
"en": [
{
"pattern_identifier": "en_phone_country_code_preserving",
"positive_pattern": "country.*code|ccode|_cc|phone.*code|user.*phone.*code",
"positive_score": 1.3,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 308
}
]
},
"PHONE_AREA_CODE_NO_TEXT": {
"en": [
{
"pattern_identifier": "en_phone_area_code_no_text_preserving",
"positive_pattern": "^\\($",
"positive_score": 1.3,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
]
},
"PHONE_AREA_CODE": {
"en": [
{
"pattern_identifier": "en_phone_area_code_preserving",
"positive_pattern": "area.*code|acode|area",
"positive_score": 1.3,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"ko": [
{
"pattern_identifier": "ko_phone_area_code_preserving",
"positive_pattern": "지역.?번호",
"positive_score": 1.3,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
]
},
"PHONE_PREFIX_SEPARATOR": {
"en": [
{
"pattern_identifier": "en_phone_prefix_separator_preserving",
"positive_pattern": "^-$|^\\)$",
"positive_score": 1.3,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
]
},
"PHONE_SUFFIX_SEPARATOR": {
"en": [
{
"pattern_identifier": "en_phone_suffix_separator_preserving",
"positive_pattern": "^-$",
"positive_score": 1.3,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
]
},
"PHONE_PREFIX": {
"en": [
{
"pattern_identifier": "en_phone_prefix_preserving",
"positive_pattern": "prefix|exchange",
"positive_score": 1.3,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"fr": [
{
"pattern_identifier": "fr_phone_prefix_preserving",
"positive_pattern": "preselection",
"positive_score": 1.3,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"pt": [
{
"pattern_identifier": "pt_phone_prefix_preserving",
"positive_pattern": "ddd",
"positive_score": 1.3,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
]
},
"PHONE_SUFFIX": {
"en": [
{
"pattern_identifier": "en_phone_suffix_preserving",
"positive_pattern": "suffix",
"positive_score": 1.3,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
]
},
"PHONE_EXTENSION": {
"en": [
{
"pattern_identifier": "en_phone_extension_preserving",
"positive_pattern": "\\bext|ext\\b|extension",
"positive_score": 1.3,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
],
"pt": [
{
"pattern_identifier": "pt_phone_extension_preserving",
"positive_pattern": "ramal",
"positive_score": 1.3,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 276
}
]
},
"PASSPORT": {
"en": [
{
"pattern_identifier": "en_passport_preserving",
"positive_pattern": "document.*number|passport",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"fr": [
{
"pattern_identifier": "fr_passport_preserving",
"positive_pattern": "passeport",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"es": [
{
"pattern_identifier": "es_passport_preserving",
"positive_pattern": "numero.*documento|pasaporte",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ja": [
{
"pattern_identifier": "ja_passport_preserving",
"positive_pattern": "書類",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"TRAVEL_ORIGIN": {
"en": [
{
"pattern_identifier": "en_travel_origin_preserving",
"positive_pattern": "point.*of.*entry|arrival",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"es": [
{
"pattern_identifier": "es_travel_origin_preserving",
"positive_pattern": "punto.*internaci(o|ó)n|fecha.*llegada",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ja": [
{
"pattern_identifier": "ja_travel_origin_preserving",
"positive_pattern": "入国",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"TRAVEL_DESTINATION": {
"en": [
{
"pattern_identifier": "en_travel_destination_preserving",
"positive_pattern": "departure",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"es": [
{
"pattern_identifier": "es_travel_destination_preserving",
"positive_pattern": "fecha.*salida|destino",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ja": [
{
"pattern_identifier": "ja_travel_destination_preserving",
"positive_pattern": "出国",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"FLIGHT": {
"en": [
{
"pattern_identifier": "en_flight_preserving",
"positive_pattern": "airline|flight",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"es": [
{
"pattern_identifier": "es_flight_preserving",
"positive_pattern": "aerol(i|í)nea|n(u|ú)mero.*vuelo",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
],
"ja": [
{
"pattern_identifier": "ja_flight_preserving",
"positive_pattern": "便名|航空会社",
"positive_score": 1.2,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"UPI_VIRTUAL_PAYMENT_ADDRESS": {
"en": [
{
"pattern_identifier": "en_upi_virtual_payment_address_user@(IFSC/Aadhaar/Mobile/RuPay)_preserving",
"positive_pattern": "^[\\w.+-_]+@(\\w+\\.ifsc\\.npci|aadhaar\\.npci|mobile\\.npci|rupay\\.npci)$",
"positive_score": 0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
},
{
"pattern_identifier": "en_upi_virtual_payment_address_user@(bank_list)_preserving",
"positive_pattern": "^[\\w.+-_]+@(airtel|airtelpaymentsbank|albk|allahabadbank|allbank|andb|apb|apl|axis|axisbank|axisgo|bandhan|barodampay|birla|boi|cbin|cboi|centralbank|cmsidfc|cnrb|csbcash|csbpay|cub|dbs|dcb|dcbbank|denabank|dlb|eazypay|equitas|ezeepay|fbl|federal|finobank|hdfcbank|hsbc|icici|idbi|idbibank|idfc|idfcbank|idfcnetc|ikwik|imobile|indbank|indianbank|indianbk|indus|iob|jkb|jsb|jsbp|karb|karurvysyabank|kaypay|kbl|kbl052|kmb|kmbl|kotak|kvb|kvbank|lime|lvb|lvbank|mahb|obc|okaxis|okbizaxis|okhdfcbank|okicici|oksbi|paytm|payzapp|pingpay|pnb|pockets|psb|purz|rajgovhdfcbank|rbl|sbi|sc|scb|scbl|scmobile|sib|srcb|synd|syndbank|syndicate|tjsb|tjsp|ubi|uboi|uco|unionbank|unionbankofindia|united|upi|utbi|vijayabank|vijb|vjb|ybl|yesbank|yesbankltd)$",
"positive_score": 0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"INTERNATIONAL_BANK_ACCOUNT_NUMBER": {
"en": [
{
"pattern_identifier": "en_international_bank_account_number_preserving",
"positive_pattern": "^[a-zA-Z]{2}[0-9]{2}[a-zA-Z0-9]{4}[0-9]{7}([a-zA-Z0-9]?){0,16}$",
"positive_score": 0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"CREDIT_CARD_CVC": {
"en": [
{
"pattern_identifier": "en_credit_card_cvc_preserving",
"positive_pattern": "^\\d{3,4}$",
"positive_score": 0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"CREDIT_CARD_EXP_YEAR": {
"en": [
{
"pattern_identifier": "en_credit_card_exp_year_preserving",
"positive_pattern": "^[2][0][1-9][0-9]$",
"positive_score": 0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"URL_SEARCH_ACTION": {
"en": [
{
"pattern_identifier": "en_url_search_action_preserving",
"positive_pattern": "/search(/|((\\w*\\.\\w+)?$))",
"positive_score": 0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"SOCIAL_SECURITY": {
"en": [
{
"pattern_identifier": "en_social_security_preserving",
"positive_pattern": "ssn|social.?security.?(num(ber)?|#)*",
"positive_score": 0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
},
"ONE_TIME_PASSWORD": {
"en": [
{
"pattern_identifier": "en_one_time_password_preserving",
"positive_pattern": "one.?time|sms.?(code|token|password|pwd|pass)",
"positive_score": 0,
"negative_pattern": "",
"match_field_attributes": 3,
"match_field_input_types": 4
}
]
}
}
\ No newline at end of file
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/autofill/core/browser/pattern_provider/test_pattern_provider.h"
#include "components/autofill/core/browser/pattern_provider/pattern_configuration_parser.h"
namespace autofill {
TestPatternProvider::TestPatternProvider() {
base::Optional<PatternProvider::Map> patterns =
field_type_parsing::GetPatternsFromResourceBundleSynchronously();
if (patterns)
patterns_ = patterns.value();
PatternProvider::SetPatternProviderForTesting(this);
}
TestPatternProvider::~TestPatternProvider() {
PatternProvider::ResetPatternProvider();
}
} // namespace autofill
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PATTERN_PROVIDER_TEST_PATTERN_PROVIDER_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_PATTERN_PROVIDER_TEST_PATTERN_PROVIDER_H_
#include "components/autofill/core/browser/pattern_provider/pattern_provider.h"
namespace autofill {
// The pattern provider to be used in tests. Loads the MatchingPattern
// configuration synchronously from the Resource Bundle and sets itself as the
// global PatternProvider.
class TestPatternProvider : public PatternProvider {
public:
TestPatternProvider();
~TestPatternProvider();
};
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PATTERN_PROVIDER_TEST_PATTERN_PROVIDER_H_
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
<include name="IDR_AUTOFILL_REGEX_JSON" file="../autofill/core/browser/pattern_provider/resources/regex_patterns.json" type="BINDATA" compress="gzip" />
</grit-part>
...@@ -14,6 +14,7 @@ dev_ui_components_resources.grd. ...@@ -14,6 +14,7 @@ dev_ui_components_resources.grd.
<release seq="1"> <release seq="1">
<includes> <includes>
<part file="about_ui_resources.grdp" /> <part file="about_ui_resources.grdp" />
<part file="autofill_regex_resources.grdp" />
<part file="dom_distiller_resources.grdp" /> <part file="dom_distiller_resources.grdp" />
<part file="flags_ui_resources.grdp" /> <part file="flags_ui_resources.grdp" />
<part file="management_resources.grdp" /> <part file="management_resources.grdp" />
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment