15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2010 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/host_mapping_rules.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_tokenizer.h"
105e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/host_port_pair.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct HostMappingRules::MapRule {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MapRule() : replacement_port(-1) {}
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string hostname_pattern;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string replacement_hostname;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int replacement_port;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct HostMappingRules::ExclusionRule {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string hostname_pattern;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HostMappingRules::HostMappingRules() {}
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HostMappingRules::~HostMappingRules() {}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HostMappingRules::RewriteHost(HostPortPair* host_port) const {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if the hostname was excluded.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ExclusionRuleList::const_iterator it = exclusion_rules_.begin();
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != exclusion_rules_.end(); ++it) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ExclusionRule& rule = *it;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (MatchPattern(host_port->host(), rule.hostname_pattern))
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if the hostname was remapped.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (MapRuleList::const_iterator it = map_rules_.begin();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != map_rules_.end(); ++it) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const MapRule& rule = *it;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The rule's hostname_pattern will be something like:
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     www.foo.com
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     *.foo.com
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     www.foo.com:1234
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     *.foo.com:1234
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // First, we'll check for a match just on hostname.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If that fails, we'll check for a match with both hostname and port.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!MatchPattern(host_port->host(), rule.hostname_pattern)) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string host_port_string = host_port->ToString();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!MatchPattern(host_port_string, rule.hostname_pattern))
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;  // This rule doesn't apply.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_port->set_host(rule.replacement_hostname);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rule.replacement_port != -1)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_port->set_port(rule.replacement_port);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HostMappingRules::AddRuleFromString(const std::string& rule_string) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string trimmed;
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::TrimWhitespaceASCII(rule_string, base::TRIM_ALL, &trimmed);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> parts;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SplitString(trimmed, ' ', &parts);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test for EXCLUSION rule.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parts.size() == 2 && LowerCaseEqualsASCII(parts[0], "exclude")) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExclusionRule rule;
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    rule.hostname_pattern = base::StringToLowerASCII(parts[1]);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exclusion_rules_.push_back(rule);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test for MAP rule.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parts.size() == 3 && LowerCaseEqualsASCII(parts[0], "map")) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MapRule rule;
856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    rule.hostname_pattern = base::StringToLowerASCII(parts[1]);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ParseHostAndPort(parts[2], &rule.replacement_hostname,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          &rule.replacement_port)) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;  // Failed parsing the hostname/port.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    map_rules_.push_back(rule);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HostMappingRules::SetRulesFromString(const std::string& rules_string) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  exclusion_rules_.clear();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map_rules_.clear();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::StringTokenizer rules(rules_string, ",");
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (rules.GetNext()) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool ok = AddRuleFromString(rules.token());
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG_IF(ERROR, !ok) << "Failed parsing rule: " << rules.token();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
111