// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/proxy/proxy_bypass_rules.h"

#include "base/stl_util.h"
#include "base/strings/pattern.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_util.h"

namespace net {

namespace {

class HostnamePatternRule : public ProxyBypassRules::Rule {
 public:
  HostnamePatternRule(const std::string& optional_scheme,
                      const std::string& hostname_pattern,
                      int optional_port)
      : optional_scheme_(base::StringToLowerASCII(optional_scheme)),
        hostname_pattern_(base::StringToLowerASCII(hostname_pattern)),
        optional_port_(optional_port) {
  }

  bool Matches(const GURL& url) const override {
    if (optional_port_ != -1 && url.EffectiveIntPort() != optional_port_)
      return false;  // Didn't match port expectation.

    if (!optional_scheme_.empty() && url.scheme() != optional_scheme_)
      return false;  // Didn't match scheme expectation.

    // Note it is necessary to lower-case the host, since GURL uses capital
    // letters for percent-escaped characters.
    return base::MatchPattern(base::StringToLowerASCII(url.host()),
                              hostname_pattern_);
  }

  std::string ToString() const override {
    std::string str;
    if (!optional_scheme_.empty())
      base::StringAppendF(&str, "%s://", optional_scheme_.c_str());
    str += hostname_pattern_;
    if (optional_port_ != -1)
      base::StringAppendF(&str, ":%d", optional_port_);
    return str;
  }

  Rule* Clone() const override {
    return new HostnamePatternRule(optional_scheme_,
                                   hostname_pattern_,
                                   optional_port_);
  }

 private:
  const std::string optional_scheme_;
  const std::string hostname_pattern_;
  const int optional_port_;
};

class BypassLocalRule : public ProxyBypassRules::Rule {
 public:
  bool Matches(const GURL& url) const override {
    const std::string& host = url.host();
    if (host == "127.0.0.1" || host == "[::1]")
      return true;
    return host.find('.') == std::string::npos;
  }

  std::string ToString() const override { return "<local>"; }

  Rule* Clone() const override { return new BypassLocalRule(); }
};

// Rule for matching a URL that is an IP address, if that IP address falls
// within a certain numeric range. For example, you could use this rule to
// match all the IPs in the CIDR block 10.10.3.4/24.
class BypassIPBlockRule : public ProxyBypassRules::Rule {
 public:
  // |ip_prefix| + |prefix_length| define the IP block to match.
  BypassIPBlockRule(const std::string& description,
                    const std::string& optional_scheme,
                    const IPAddressNumber& ip_prefix,
                    size_t prefix_length_in_bits)
      : description_(description),
        optional_scheme_(optional_scheme),
        ip_prefix_(ip_prefix),
        prefix_length_in_bits_(prefix_length_in_bits) {
  }

  bool Matches(const GURL& url) const override {
    if (!url.HostIsIPAddress())
      return false;

    if (!optional_scheme_.empty() && url.scheme() != optional_scheme_)
      return false;  // Didn't match scheme expectation.

    // Parse the input IP literal to a number.
    IPAddressNumber ip_number;
    if (!ParseIPLiteralToNumber(url.HostNoBrackets(), &ip_number))
      return false;

    // Test if it has the expected prefix.
    return IPNumberMatchesPrefix(ip_number, ip_prefix_,
                                 prefix_length_in_bits_);
  }

  std::string ToString() const override { return description_; }

  Rule* Clone() const override {
    return new BypassIPBlockRule(description_,
                                 optional_scheme_,
                                 ip_prefix_,
                                 prefix_length_in_bits_);
  }

 private:
  const std::string description_;
  const std::string optional_scheme_;
  const IPAddressNumber ip_prefix_;
  const size_t prefix_length_in_bits_;
};

// Returns true if the given string represents an IP address.
// IPv6 addresses are expected to be bracketed.
bool IsIPAddress(const std::string& domain) {
  // From GURL::HostIsIPAddress()
  url::RawCanonOutputT<char, 128> ignored_output;
  url::CanonHostInfo host_info;
  url::Component domain_comp(0, domain.size());
  url::CanonicalizeIPAddress(domain.c_str(), domain_comp, &ignored_output,
                             &host_info);
  return host_info.IsIPAddress();
}

}  // namespace

ProxyBypassRules::Rule::Rule() {
}

ProxyBypassRules::Rule::~Rule() {
}

bool ProxyBypassRules::Rule::Equals(const Rule& rule) const {
  return ToString() == rule.ToString();
}

ProxyBypassRules::ProxyBypassRules() {
}

ProxyBypassRules::ProxyBypassRules(const ProxyBypassRules& rhs) {
  AssignFrom(rhs);
}

ProxyBypassRules::~ProxyBypassRules() {
  Clear();
}

ProxyBypassRules& ProxyBypassRules::operator=(const ProxyBypassRules& rhs) {
  AssignFrom(rhs);
  return *this;
}

bool ProxyBypassRules::Matches(const GURL& url) const {
  for (RuleList::const_iterator it = rules_.begin(); it != rules_.end(); ++it) {
    if ((*it)->Matches(url))
      return true;
  }
  return false;
}

bool ProxyBypassRules::Equals(const ProxyBypassRules& other) const {
  if (rules_.size() != other.rules_.size())
    return false;

  for (size_t i = 0; i < rules_.size(); ++i) {
    if (!rules_[i]->Equals(*other.rules_[i]))
      return false;
  }
  return true;
}

void ProxyBypassRules::ParseFromString(const std::string& raw) {
  ParseFromStringInternal(raw, false);
}

void ProxyBypassRules::ParseFromStringUsingSuffixMatching(
    const std::string& raw) {
  ParseFromStringInternal(raw, true);
}

bool ProxyBypassRules::AddRuleForHostname(const std::string& optional_scheme,
                                          const std::string& hostname_pattern,
                                          int optional_port) {
  if (hostname_pattern.empty())
    return false;

  rules_.push_back(new HostnamePatternRule(optional_scheme,
                                           hostname_pattern,
                                           optional_port));
  return true;
}

void ProxyBypassRules::AddRuleToBypassLocal() {
  rules_.push_back(new BypassLocalRule);
}

bool ProxyBypassRules::AddRuleFromString(const std::string& raw) {
  return AddRuleFromStringInternalWithLogging(raw, false);
}

bool ProxyBypassRules::AddRuleFromStringUsingSuffixMatching(
    const std::string& raw) {
  return AddRuleFromStringInternalWithLogging(raw, true);
}

std::string ProxyBypassRules::ToString() const {
  std::string result;
  for (RuleList::const_iterator rule(rules_.begin());
       rule != rules_.end();
       ++rule) {
    result += (*rule)->ToString();
    result += ";";
  }
  return result;
}

void ProxyBypassRules::Clear() {
  STLDeleteElements(&rules_);
}

void ProxyBypassRules::AssignFrom(const ProxyBypassRules& other) {
  Clear();

  // Make a copy of the rules list.
  for (RuleList::const_iterator it = other.rules_.begin();
       it != other.rules_.end(); ++it) {
    rules_.push_back((*it)->Clone());
  }
}

void ProxyBypassRules::ParseFromStringInternal(
    const std::string& raw,
    bool use_hostname_suffix_matching) {
  Clear();

  base::StringTokenizer entries(raw, ",;");
  while (entries.GetNext()) {
    AddRuleFromStringInternalWithLogging(entries.token(),
                                         use_hostname_suffix_matching);
  }
}

bool ProxyBypassRules::AddRuleFromStringInternal(
    const std::string& raw_untrimmed,
    bool use_hostname_suffix_matching) {
  std::string raw;
  base::TrimWhitespaceASCII(raw_untrimmed, base::TRIM_ALL, &raw);

  // This is the special syntax used by WinInet's bypass list -- we allow it
  // on all platforms and interpret it the same way.
  if (base::LowerCaseEqualsASCII(raw, "<local>")) {
    AddRuleToBypassLocal();
    return true;
  }

  // Extract any scheme-restriction.
  std::string::size_type scheme_pos = raw.find("://");
  std::string scheme;
  if (scheme_pos != std::string::npos) {
    scheme = raw.substr(0, scheme_pos);
    raw = raw.substr(scheme_pos + 3);
    if (scheme.empty())
      return false;
  }

  if (raw.empty())
    return false;

  // If there is a forward slash in the input, it is probably a CIDR style
  // mask.
  if (raw.find('/') != std::string::npos) {
    IPAddressNumber ip_prefix;
    size_t prefix_length_in_bits;

    if (!ParseCIDRBlock(raw, &ip_prefix, &prefix_length_in_bits))
      return false;

    rules_.push_back(
        new BypassIPBlockRule(raw, scheme, ip_prefix, prefix_length_in_bits));

    return true;
  }

  // Check if we have an <ip-address>[:port] input. We need to treat this
  // separately since the IP literal may not be in a canonical form.
  std::string host;
  int port;
  if (ParseHostAndPort(raw, &host, &port)) {
    // Note that HostPortPair is used to merely to convert any IPv6 literals to
    // a URL-safe format that can be used by canonicalization below.
    std::string bracketed_host = HostPortPair(host, 80).HostForURL();
    if (IsIPAddress(bracketed_host)) {
      // Canonicalize the IP literal before adding it as a string pattern.
      GURL tmp_url("http://" + bracketed_host);
      return AddRuleForHostname(scheme, tmp_url.host(), port);
    }
  }

  // Otherwise assume we have <hostname-pattern>[:port].
  std::string::size_type pos_colon = raw.rfind(':');
  host = raw;
  port = -1;
  if (pos_colon != std::string::npos) {
    if (!base::StringToInt(base::StringPiece(raw.begin() + pos_colon + 1,
                                             raw.end()),
                           &port) ||
        (port < 0 || port > 0xFFFF)) {
      return false;  // Port was invalid.
    }
    raw = raw.substr(0, pos_colon);
  }

  // Special-case hostnames that begin with a period.
  // For example, we remap ".google.com" --> "*.google.com".
  if (base::StartsWith(raw, ".", base::CompareCase::SENSITIVE))
    raw = "*" + raw;

  // If suffix matching was asked for, make sure the pattern starts with a
  // wildcard.
  if (use_hostname_suffix_matching &&
      !base::StartsWith(raw, "*", base::CompareCase::SENSITIVE))
    raw = "*" + raw;

  return AddRuleForHostname(scheme, raw, port);
}

bool ProxyBypassRules::AddRuleFromStringInternalWithLogging(
    const std::string& raw,
    bool use_hostname_suffix_matching) {
  return AddRuleFromStringInternal(raw, use_hostname_suffix_matching);
}

}  // namespace net
