| // Copyright (c) 2010 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 "net/base/host_mapping_rules.h" | |
| #include "base/logging.h" | |
| #include "base/strings/pattern.h" | |
| #include "base/strings/string_split.h" | |
| #include "base/strings/string_tokenizer.h" | |
| #include "base/strings/string_util.h" | |
| #include "net/base/host_port_pair.h" | |
| #include "net/base/url_util.h" | |
| namespace net { | |
| struct HostMappingRules::MapRule { | |
| MapRule() : replacement_port(-1) {} | |
| std::string hostname_pattern; | |
| std::string replacement_hostname; | |
| int replacement_port; | |
| }; | |
| struct HostMappingRules::ExclusionRule { | |
| std::string hostname_pattern; | |
| }; | |
| HostMappingRules::HostMappingRules() = default; | |
| HostMappingRules::HostMappingRules(const HostMappingRules& host_mapping_rules) = | |
| default; | |
| HostMappingRules::~HostMappingRules() = default; | |
| HostMappingRules& HostMappingRules::operator=( | |
| const HostMappingRules& host_mapping_rules) = default; | |
| bool HostMappingRules::RewriteHost(HostPortPair* host_port) const { | |
| // Check if the hostname was remapped. | |
| for (const auto& rule : map_rules_) { | |
| // The rule's hostname_pattern will be something like: | |
| // www.foo.com | |
| // *.foo.com | |
| // www.foo.com:1234 | |
| // *.foo.com:1234 | |
| // First, we'll check for a match just on hostname. | |
| // If that fails, we'll check for a match with both hostname and port. | |
| if (!base::MatchPattern(host_port->host(), rule.hostname_pattern)) { | |
| std::string host_port_string = host_port->ToString(); | |
| if (!base::MatchPattern(host_port_string, rule.hostname_pattern)) | |
| continue; // This rule doesn't apply. | |
| } | |
| // Check if the hostname was excluded. | |
| for (const auto& rule : exclusion_rules_) { | |
| if (base::MatchPattern(host_port->host(), rule.hostname_pattern)) | |
| return false; | |
| } | |
| host_port->set_host(rule.replacement_hostname); | |
| if (rule.replacement_port != -1) | |
| host_port->set_port(static_cast<uint16_t>(rule.replacement_port)); | |
| return true; | |
| } | |
| return false; | |
| } | |
| bool HostMappingRules::AddRuleFromString(const std::string& rule_string) { | |
| std::vector<std::string> parts = | |
| base::SplitString(base::TrimWhitespaceASCII(rule_string, base::TRIM_ALL), | |
| " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | |
| // Test for EXCLUSION rule. | |
| if (parts.size() == 2 && base::LowerCaseEqualsASCII(parts[0], "exclude")) { | |
| ExclusionRule rule; | |
| rule.hostname_pattern = base::ToLowerASCII(parts[1]); | |
| exclusion_rules_.push_back(rule); | |
| return true; | |
| } | |
| // Test for MAP rule. | |
| if (parts.size() == 3 && base::LowerCaseEqualsASCII(parts[0], "map")) { | |
| MapRule rule; | |
| rule.hostname_pattern = base::ToLowerASCII(parts[1]); | |
| if (!ParseHostAndPort(parts[2], &rule.replacement_hostname, | |
| &rule.replacement_port)) { | |
| return false; // Failed parsing the hostname/port. | |
| } | |
| map_rules_.push_back(rule); | |
| return true; | |
| } | |
| return false; | |
| } | |
| void HostMappingRules::SetRulesFromString(const std::string& rules_string) { | |
| exclusion_rules_.clear(); | |
| map_rules_.clear(); | |
| base::StringTokenizer rules(rules_string, ","); | |
| while (rules.GetNext()) { | |
| bool ok = AddRuleFromString(rules.token()); | |
| LOG_IF(ERROR, !ok) << "Failed parsing rule: " << rules.token(); | |
| } | |
| } | |
| } // namespace net |