15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 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/proxy/proxy_bypass_rules.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
85e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
95e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
105e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_tokenizer.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HostnamePatternRule : public ProxyBypassRules::Rule {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostnamePatternRule(const std::string& optional_scheme,
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const std::string& hostname_pattern,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      int optional_port)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : optional_scheme_(StringToLowerASCII(optional_scheme)),
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hostname_pattern_(StringToLowerASCII(hostname_pattern)),
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        optional_port_(optional_port) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Matches(const GURL& url) const OVERRIDE {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (optional_port_ != -1 && url.EffectiveIntPort() != optional_port_)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;  // Didn't match port expectation.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!optional_scheme_.empty() && url.scheme() != optional_scheme_)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;  // Didn't match scheme expectation.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note it is necessary to lower-case the host, since GURL uses capital
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // letters for percent-escaped characters.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MatchPattern(StringToLowerASCII(url.host()), hostname_pattern_);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual std::string ToString() const OVERRIDE {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string str;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!optional_scheme_.empty())
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringAppendF(&str, "%s://", optional_scheme_.c_str());
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    str += hostname_pattern_;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (optional_port_ != -1)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringAppendF(&str, ":%d", optional_port_);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return str;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Rule* Clone() const OVERRIDE {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new HostnamePatternRule(optional_scheme_,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   hostname_pattern_,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   optional_port_);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string optional_scheme_;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string hostname_pattern_;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int optional_port_;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BypassLocalRule : public ProxyBypassRules::Rule {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Matches(const GURL& url) const OVERRIDE {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& host = url.host();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (host == "127.0.0.1" || host == "[::1]")
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return host.find('.') == std::string::npos;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual std::string ToString() const OVERRIDE {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "<local>";
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Rule* Clone() const OVERRIDE {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new BypassLocalRule();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Rule for matching a URL that is an IP address, if that IP address falls
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// within a certain numeric range. For example, you could use this rule to
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// match all the IPs in the CIDR block 10.10.3.4/24.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BypassIPBlockRule : public ProxyBypassRules::Rule {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |ip_prefix| + |prefix_length| define the IP block to match.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BypassIPBlockRule(const std::string& description,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& optional_scheme,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const IPAddressNumber& ip_prefix,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    size_t prefix_length_in_bits)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : description_(description),
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        optional_scheme_(optional_scheme),
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ip_prefix_(ip_prefix),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        prefix_length_in_bits_(prefix_length_in_bits) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Matches(const GURL& url) const OVERRIDE {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!url.HostIsIPAddress())
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!optional_scheme_.empty() && url.scheme() != optional_scheme_)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;  // Didn't match scheme expectation.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Parse the input IP literal to a number.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPAddressNumber ip_number;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ParseIPLiteralToNumber(url.HostNoBrackets(), &ip_number))
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Test if it has the expected prefix.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return IPNumberMatchesPrefix(ip_number, ip_prefix_,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 prefix_length_in_bits_);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual std::string ToString() const OVERRIDE {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return description_;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Rule* Clone() const OVERRIDE {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new BypassIPBlockRule(description_,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 optional_scheme_,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 ip_prefix_,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 prefix_length_in_bits_);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string description_;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string optional_scheme_;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const IPAddressNumber ip_prefix_;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t prefix_length_in_bits_;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if the given string represents an IP address.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsIPAddress(const std::string& domain) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // From GURL::HostIsIPAddress()
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_canon::RawCanonOutputT<char, 128> ignored_output;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_canon::CanonHostInfo host_info;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_parse::Component domain_comp(0, domain.size());
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_canon::CanonicalizeIPAddress(domain.c_str(), domain_comp,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   &ignored_output, &host_info);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return host_info.IsIPAddress();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyBypassRules::Rule::Rule() {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyBypassRules::Rule::~Rule() {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProxyBypassRules::Rule::Equals(const Rule& rule) const {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ToString() == rule.ToString();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyBypassRules::ProxyBypassRules() {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyBypassRules::ProxyBypassRules(const ProxyBypassRules& rhs) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssignFrom(rhs);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyBypassRules::~ProxyBypassRules() {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Clear();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyBypassRules& ProxyBypassRules::operator=(const ProxyBypassRules& rhs) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssignFrom(rhs);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *this;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProxyBypassRules::Matches(const GURL& url) const {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (RuleList::const_iterator it = rules_.begin(); it != rules_.end(); ++it) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*it)->Matches(url))
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProxyBypassRules::Equals(const ProxyBypassRules& other) const {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rules_.size() != other.rules_.size())
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < rules_.size(); ++i) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!rules_[i]->Equals(*other.rules_[i]))
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyBypassRules::ParseFromString(const std::string& raw) {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParseFromStringInternal(raw, false);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyBypassRules::ParseFromStringUsingSuffixMatching(
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& raw) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParseFromStringInternal(raw, true);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProxyBypassRules::AddRuleForHostname(const std::string& optional_scheme,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const std::string& hostname_pattern,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int optional_port) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (hostname_pattern.empty())
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rules_.push_back(new HostnamePatternRule(optional_scheme,
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           hostname_pattern,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           optional_port));
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyBypassRules::AddRuleToBypassLocal() {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rules_.push_back(new BypassLocalRule);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProxyBypassRules::AddRuleFromString(const std::string& raw) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AddRuleFromStringInternalWithLogging(raw, false);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProxyBypassRules::AddRuleFromStringUsingSuffixMatching(
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& raw) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AddRuleFromStringInternalWithLogging(raw, true);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ProxyBypassRules::ToString() const {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string result;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (RuleList::const_iterator rule(rules_.begin());
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       rule != rules_.end();
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++rule) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result += (*rule)->ToString();
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result += ";";
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyBypassRules::Clear() {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&rules_);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyBypassRules::AssignFrom(const ProxyBypassRules& other) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Clear();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make a copy of the rules list.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (RuleList::const_iterator it = other.rules_.begin();
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != other.rules_.end(); ++it) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rules_.push_back((*it)->Clone());
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyBypassRules::ParseFromStringInternal(
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& raw,
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool use_hostname_suffix_matching) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Clear();
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::StringTokenizer entries(raw, ",;");
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (entries.GetNext()) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddRuleFromStringInternalWithLogging(entries.token(),
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         use_hostname_suffix_matching);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProxyBypassRules::AddRuleFromStringInternal(
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& raw_untrimmed,
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool use_hostname_suffix_matching) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string raw;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TrimWhitespaceASCII(raw_untrimmed, TRIM_ALL, &raw);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the special syntax used by WinInet's bypass list -- we allow it
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on all platforms and interpret it the same way.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (LowerCaseEqualsASCII(raw, "<local>")) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddRuleToBypassLocal();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extract any scheme-restriction.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::size_type scheme_pos = raw.find("://");
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string scheme;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (scheme_pos != std::string::npos) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scheme = raw.substr(0, scheme_pos);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raw = raw.substr(scheme_pos + 3);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (scheme.empty())
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (raw.empty())
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there is a forward slash in the input, it is probably a CIDR style
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // mask.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (raw.find('/') != std::string::npos) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPAddressNumber ip_prefix;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t prefix_length_in_bits;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ParseCIDRBlock(raw, &ip_prefix, &prefix_length_in_bits))
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rules_.push_back(
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new BypassIPBlockRule(raw, scheme, ip_prefix, prefix_length_in_bits));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if we have an <ip-address>[:port] input. We need to treat this
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // separately since the IP literal may not be in a canonical form.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string host;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int port;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ParseHostAndPort(raw, &host, &port)) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsIPAddress(host)) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Canonicalize the IP literal before adding it as a string pattern.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL tmp_url("http://" + host);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return AddRuleForHostname(scheme, tmp_url.host(), port);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise assume we have <hostname-pattern>[:port].
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::size_type pos_colon = raw.rfind(':');
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  host = raw;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  port = -1;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pos_colon != std::string::npos) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!base::StringToInt(base::StringPiece(raw.begin() + pos_colon + 1,
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             raw.end()),
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &port) ||
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (port < 0 || port > 0xFFFF)) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;  // Port was invalid.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raw = raw.substr(0, pos_colon);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Special-case hostnames that begin with a period.
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For example, we remap ".google.com" --> "*.google.com".
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (StartsWithASCII(raw, ".", false))
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raw = "*" + raw;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If suffix matching was asked for, make sure the pattern starts with a
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // wildcard.
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_hostname_suffix_matching && !StartsWithASCII(raw, "*", false))
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raw = "*" + raw;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AddRuleForHostname(scheme, raw, port);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProxyBypassRules::AddRuleFromStringInternalWithLogging(
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& raw,
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool use_hostname_suffix_matching) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AddRuleFromStringInternal(raw, use_hostname_suffix_matching);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
348