Home | History | Annotate | Download | only in base
      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 
     14 namespace net {
     15 
     16 struct HostMappingRules::MapRule {
     17   MapRule() : replacement_port(-1) {}
     18 
     19   std::string hostname_pattern;
     20   std::string replacement_hostname;
     21   int replacement_port;
     22 };
     23 
     24 struct HostMappingRules::ExclusionRule {
     25   std::string hostname_pattern;
     26 };
     27 
     28 HostMappingRules::HostMappingRules() {}
     29 
     30 HostMappingRules::~HostMappingRules() {}
     31 
     32 bool 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 
     68 bool 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 
     99 void 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