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. 4 5#include "net/base/host_mapping_rules.h" 6 7#include "base/logging.h" 8#include "base/string_split.h" 9#include "base/string_tokenizer.h" 10#include "base/string_util.h" 11#include "net/base/host_port_pair.h" 12#include "net/base/net_util.h" 13 14namespace net { 15 16struct HostMappingRules::MapRule { 17 MapRule() : replacement_port(-1) {} 18 19 std::string hostname_pattern; 20 std::string replacement_hostname; 21 int replacement_port; 22}; 23 24struct HostMappingRules::ExclusionRule { 25 std::string hostname_pattern; 26}; 27 28HostMappingRules::HostMappingRules() {} 29 30HostMappingRules::~HostMappingRules() {} 31 32bool HostMappingRules::RewriteHost(HostPortPair* host_port) const { 33 // Check if the hostname was excluded. 34 for (ExclusionRuleList::const_iterator it = exclusion_rules_.begin(); 35 it != exclusion_rules_.end(); ++it) { 36 const ExclusionRule& rule = *it; 37 if (MatchPattern(host_port->host(), rule.hostname_pattern)) 38 return false; 39 } 40 41 // Check if the hostname was remapped. 42 for (MapRuleList::const_iterator it = map_rules_.begin(); 43 it != map_rules_.end(); ++it) { 44 const MapRule& rule = *it; 45 46 // The rule's hostname_pattern will be something like: 47 // www.foo.com 48 // *.foo.com 49 // www.foo.com:1234 50 // *.foo.com:1234 51 // First, we'll check for a match just on hostname. 52 // If that fails, we'll check for a match with both hostname and port. 53 if (!MatchPattern(host_port->host(), rule.hostname_pattern)) { 54 std::string host_port_string = host_port->ToString(); 55 if (!MatchPattern(host_port_string, rule.hostname_pattern)) 56 continue; // This rule doesn't apply. 57 } 58 59 host_port->set_host(rule.replacement_hostname); 60 if (rule.replacement_port != -1) 61 host_port->set_port(rule.replacement_port); 62 return true; 63 } 64 65 return false; 66} 67 68bool HostMappingRules::AddRuleFromString(const std::string& rule_string) { 69 std::string trimmed; 70 TrimWhitespaceASCII(rule_string, TRIM_ALL, &trimmed); 71 std::vector<std::string> parts; 72 base::SplitString(trimmed, ' ', &parts); 73 74 // Test for EXCLUSION rule. 75 if (parts.size() == 2 && LowerCaseEqualsASCII(parts[0], "exclude")) { 76 ExclusionRule rule; 77 rule.hostname_pattern = StringToLowerASCII(parts[1]); 78 exclusion_rules_.push_back(rule); 79 return true; 80 } 81 82 // Test for MAP rule. 83 if (parts.size() == 3 && LowerCaseEqualsASCII(parts[0], "map")) { 84 MapRule rule; 85 rule.hostname_pattern = StringToLowerASCII(parts[1]); 86 87 if (!ParseHostAndPort(parts[2], &rule.replacement_hostname, 88 &rule.replacement_port)) { 89 return false; // Failed parsing the hostname/port. 90 } 91 92 map_rules_.push_back(rule); 93 return true; 94 } 95 96 return false; 97} 98 99void HostMappingRules::SetRulesFromString(const std::string& rules_string) { 100 exclusion_rules_.clear(); 101 map_rules_.clear(); 102 103 StringTokenizer rules(rules_string, ","); 104 while (rules.GetNext()) { 105 bool ok = AddRuleFromString(rules.token()); 106 LOG_IF(ERROR, !ok) << "Failed parsing rule: " << rules.token(); 107 } 108} 109 110} // namespace net 111