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