// Copyright 2010 The Chromium Authors
// 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 <string>

#include "base/logging.h"
#include "base/strings/pattern.h"
#include "base/strings/string_number_conversions.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"
#include "url/gurl.h"
#include "url/third_party/mozilla/url_parse.h"
#include "url/url_canon.h"

namespace net {

struct HostMappingRules::MapRule {
  MapRule() = default;

  std::string hostname_pattern;
  std::string replacement_hostname;
  int replacement_port = -1;
};

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& map_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(), map_rule.hostname_pattern)) {
      std::string host_port_string = host_port->ToString();
      if (!base::MatchPattern(host_port_string, map_rule.hostname_pattern))
        continue;  // This rule doesn't apply.
    }

    // Check if the hostname was excluded.
    for (const auto& exclusion_rule : exclusion_rules_) {
      if (base::MatchPattern(host_port->host(),
                             exclusion_rule.hostname_pattern))
        return false;
    }

    host_port->set_host(map_rule.replacement_hostname);
    if (map_rule.replacement_port != -1)
      host_port->set_port(static_cast<uint16_t>(map_rule.replacement_port));
    return true;
  }

  return false;
}

HostMappingRules::RewriteResult HostMappingRules::RewriteUrl(GURL& url) const {
  // Must be a valid and standard URL. Otherwise, Chrome might not know how to
  // find/replace the contained host or port.
  DCHECK(url.is_valid());
  DCHECK(url.IsStandard());
  DCHECK(url.has_host());

  HostPortPair host_port_pair = HostPortPair::FromURL(url);
  if (!RewriteHost(&host_port_pair))
    return RewriteResult::kNoMatchingRule;

  GURL::Replacements replacements;
  std::string port_str = base::NumberToString(host_port_pair.port());
  replacements.SetPortStr(port_str);
  std::string host_str = host_port_pair.HostForURL();
  replacements.SetHostStr(host_str);
  GURL new_url = url.ReplaceComponents(replacements);

  if (!new_url.is_valid())
    return RewriteResult::kInvalidRewrite;

  DCHECK(new_url.IsStandard());
  DCHECK(new_url.has_host());
  DCHECK_EQ(url.EffectiveIntPort() == url::PORT_UNSPECIFIED,
            new_url.EffectiveIntPort() == url::PORT_UNSPECIFIED);

  url = std::move(new_url);
  return RewriteResult::kRewritten;
}

bool HostMappingRules::AddRuleFromString(base::StringPiece rule_string) {
  std::vector<base::StringPiece> parts = base::SplitStringPiece(
      base::TrimWhitespaceASCII(rule_string, base::TRIM_ALL), " ",
      base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);

  // Test for EXCLUSION rule.
  if (parts.size() == 2 &&
      base::EqualsCaseInsensitiveASCII(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::EqualsCaseInsensitiveASCII(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(base::StringPiece rules_string) {
  exclusion_rules_.clear();
  map_rules_.clear();

  std::vector<base::StringPiece> rules = base::SplitStringPiece(
      rules_string, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  for (base::StringPiece rule : rules) {
    bool ok = AddRuleFromString(rule);
    LOG_IF(ERROR, !ok) << "Failed parsing rule: " << rule;
  }
}

}  // namespace net
