1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/base/host_mapping_rules.h"
7 #include "base/logging.h"
8 #include "base/strings/pattern.h"
9 #include "base/strings/string_split.h"
10 #include "base/strings/string_tokenizer.h"
11 #include "base/strings/string_util.h"
12 #include "net/base/host_port_pair.h"
13 #include "net/base/net_util.h"
17 struct HostMappingRules::MapRule
{
18 MapRule() : replacement_port(-1) {}
20 std::string hostname_pattern
;
21 std::string replacement_hostname
;
25 struct HostMappingRules::ExclusionRule
{
26 std::string hostname_pattern
;
29 HostMappingRules::HostMappingRules() {}
31 HostMappingRules::~HostMappingRules() {}
33 bool HostMappingRules::RewriteHost(HostPortPair
* host_port
) const {
34 // Check if the hostname was excluded.
35 for (ExclusionRuleList::const_iterator it
= exclusion_rules_
.begin();
36 it
!= exclusion_rules_
.end(); ++it
) {
37 const ExclusionRule
& rule
= *it
;
38 if (base::MatchPattern(host_port
->host(), rule
.hostname_pattern
))
42 // Check if the hostname was remapped.
43 for (MapRuleList::const_iterator it
= map_rules_
.begin();
44 it
!= map_rules_
.end(); ++it
) {
45 const MapRule
& rule
= *it
;
47 // The rule's hostname_pattern will be something like:
52 // First, we'll check for a match just on hostname.
53 // If that fails, we'll check for a match with both hostname and port.
54 if (!base::MatchPattern(host_port
->host(), rule
.hostname_pattern
)) {
55 std::string host_port_string
= host_port
->ToString();
56 if (!base::MatchPattern(host_port_string
, rule
.hostname_pattern
))
57 continue; // This rule doesn't apply.
60 host_port
->set_host(rule
.replacement_hostname
);
61 if (rule
.replacement_port
!= -1)
62 host_port
->set_port(static_cast<uint16_t>(rule
.replacement_port
));
69 bool HostMappingRules::AddRuleFromString(const std::string
& rule_string
) {
70 std::vector
<std::string
> parts
=
71 base::SplitString(base::TrimWhitespaceASCII(rule_string
, base::TRIM_ALL
),
72 " ", base::TRIM_WHITESPACE
, base::SPLIT_WANT_ALL
);
74 // Test for EXCLUSION rule.
75 if (parts
.size() == 2 && base::LowerCaseEqualsASCII(parts
[0], "exclude")) {
77 rule
.hostname_pattern
= base::StringToLowerASCII(parts
[1]);
78 exclusion_rules_
.push_back(rule
);
83 if (parts
.size() == 3 && base::LowerCaseEqualsASCII(parts
[0], "map")) {
85 rule
.hostname_pattern
= base::StringToLowerASCII(parts
[1]);
87 if (!ParseHostAndPort(parts
[2], &rule
.replacement_hostname
,
88 &rule
.replacement_port
)) {
89 return false; // Failed parsing the hostname/port.
92 map_rules_
.push_back(rule
);
99 void HostMappingRules::SetRulesFromString(const std::string
& rules_string
) {
100 exclusion_rules_
.clear();
103 base::StringTokenizer
rules(rules_string
, ",");
104 while (rules
.GetNext()) {
105 bool ok
= AddRuleFromString(rules
.token());
106 LOG_IF(ERROR
, !ok
) << "Failed parsing rule: " << rules
.token();