// Copyright (c) 2012 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_config.h"

#include "base/logging.h"
#include "base/string_tokenizer.h"
#include "base/string_util.h"
#include "base/values.h"
#include "net/proxy/proxy_info.h"

namespace net {

namespace {

// If |proxy| is valid, sets it in |dict| under the key |name|.
void AddProxyToValue(const char* name,
                     const ProxyServer& proxy,
                     DictionaryValue* dict) {
  if (proxy.is_valid())
    dict->SetString(name, proxy.ToURI());
}

}  // namespace

ProxyConfig::ProxyRules::ProxyRules()
    : reverse_bypass(false),
      type(TYPE_NO_RULES) {
}

ProxyConfig::ProxyRules::~ProxyRules() {
}

void ProxyConfig::ProxyRules::Apply(const GURL& url, ProxyInfo* result) const {
  if (empty()) {
    result->UseDirect();
    return;
  }

  bool bypass_proxy = bypass_rules.Matches(url);
  if (reverse_bypass)
    bypass_proxy = !bypass_proxy;
  if (bypass_proxy) {
    result->UseDirectWithBypassedProxy();
    return;
  }

  switch (type) {
    case ProxyRules::TYPE_SINGLE_PROXY: {
      result->UseProxyServer(single_proxy);
      return;
    }
    case ProxyRules::TYPE_PROXY_PER_SCHEME: {
      const ProxyServer* entry = MapUrlSchemeToProxy(url.scheme());
      if (entry) {
        result->UseProxyServer(*entry);
      } else {
        // We failed to find a matching proxy server for the current URL
        // scheme. Default to direct.
        result->UseDirect();
      }
      return;
    }
    default: {
      result->UseDirect();
      NOTREACHED();
      return;
    }
  }
}

void ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) {
  // Reset.
  type = TYPE_NO_RULES;
  single_proxy = ProxyServer();
  proxy_for_http = ProxyServer();
  proxy_for_https = ProxyServer();
  proxy_for_ftp = ProxyServer();
  fallback_proxy = ProxyServer();

  StringTokenizer proxy_server_list(proxy_rules, ";");
  while (proxy_server_list.GetNext()) {
    StringTokenizer proxy_server_for_scheme(
        proxy_server_list.token_begin(), proxy_server_list.token_end(), "=");

    while (proxy_server_for_scheme.GetNext()) {
      std::string url_scheme = proxy_server_for_scheme.token();

      // If we fail to get the proxy server here, it means that
      // this is a regular proxy server configuration, i.e. proxies
      // are not configured per protocol.
      if (!proxy_server_for_scheme.GetNext()) {
        if (type == TYPE_PROXY_PER_SCHEME)
          continue;  // Unexpected.
        single_proxy = ProxyServer::FromURI(url_scheme,
                                            ProxyServer::SCHEME_HTTP);
        type = TYPE_SINGLE_PROXY;
        return;
      }

      // Trim whitespace off the url scheme.
      TrimWhitespaceASCII(url_scheme, TRIM_ALL, &url_scheme);

      // Add it to the per-scheme mappings (if supported scheme).
      type = TYPE_PROXY_PER_SCHEME;
      ProxyServer* entry = MapUrlSchemeToProxyNoFallback(url_scheme);
      ProxyServer::Scheme default_scheme = ProxyServer::SCHEME_HTTP;

      // socks=XXX is inconsistent with the other formats, since "socks"
      // is not a URL scheme. Rather this means "for everything else, send
      // it to the SOCKS proxy server XXX".
      if (url_scheme == "socks") {
        DCHECK(!entry);
        entry = &fallback_proxy;
        default_scheme = ProxyServer::SCHEME_SOCKS4;
      }

      if (entry) {
        *entry = ProxyServer::FromURI(proxy_server_for_scheme.token(),
                                      default_scheme);
      }
    }
  }
}

const ProxyServer* ProxyConfig::ProxyRules::MapUrlSchemeToProxy(
    const std::string& url_scheme) const {
  const ProxyServer* proxy_server =
      const_cast<ProxyRules*>(this)->MapUrlSchemeToProxyNoFallback(url_scheme);
  if (proxy_server && proxy_server->is_valid())
    return proxy_server;
  if (fallback_proxy.is_valid())
    return &fallback_proxy;
  return NULL;  // No mapping for this scheme. Use direct.
}

bool ProxyConfig::ProxyRules::Equals(const ProxyRules& other) const {
  return type == other.type &&
         single_proxy == other.single_proxy &&
         proxy_for_http == other.proxy_for_http &&
         proxy_for_https == other.proxy_for_https &&
         proxy_for_ftp == other.proxy_for_ftp &&
         fallback_proxy == other.fallback_proxy &&
         bypass_rules.Equals(other.bypass_rules) &&
         reverse_bypass == other.reverse_bypass;
}

ProxyServer* ProxyConfig::ProxyRules::MapUrlSchemeToProxyNoFallback(
    const std::string& scheme) {
  DCHECK_EQ(TYPE_PROXY_PER_SCHEME, type);
  if (scheme == "http")
    return &proxy_for_http;
  if (scheme == "https")
    return &proxy_for_https;
  if (scheme == "ftp")
    return &proxy_for_ftp;
  return NULL;  // No mapping for this scheme.
}

ProxyConfig::ProxyConfig()
    : auto_detect_(false), pac_mandatory_(false),
      source_(PROXY_CONFIG_SOURCE_UNKNOWN), id_(kInvalidConfigID)  {
}

ProxyConfig::ProxyConfig(const ProxyConfig& config)
    : auto_detect_(config.auto_detect_),
      pac_url_(config.pac_url_),
      pac_mandatory_(config.pac_mandatory_),
      proxy_rules_(config.proxy_rules_),
      source_(config.source_),
      id_(config.id_) {
}

ProxyConfig::~ProxyConfig() {
}

ProxyConfig& ProxyConfig::operator=(const ProxyConfig& config) {
  auto_detect_ = config.auto_detect_;
  pac_url_ = config.pac_url_;
  pac_mandatory_ = config.pac_mandatory_;
  proxy_rules_ = config.proxy_rules_;
  source_ = config.source_;
  id_ = config.id_;
  return *this;
}

bool ProxyConfig::Equals(const ProxyConfig& other) const {
  // The two configs can have different IDs and sources.  We are just interested
  // in if they have the same settings.
  return auto_detect_ == other.auto_detect_ &&
         pac_url_ == other.pac_url_ &&
         pac_mandatory_ == other.pac_mandatory_ &&
         proxy_rules_.Equals(other.proxy_rules());
}

bool ProxyConfig::HasAutomaticSettings() const {
  return auto_detect_ || has_pac_url();
}

void ProxyConfig::ClearAutomaticSettings() {
  auto_detect_ = false;
  pac_url_ = GURL();
}

Value* ProxyConfig::ToValue() const {
  DictionaryValue* dict = new DictionaryValue();

  // Output the automatic settings.
  if (auto_detect_)
    dict->SetBoolean("auto_detect", auto_detect_);
  if (has_pac_url()) {
    dict->SetString("pac_url", pac_url_.possibly_invalid_spec());
    if (pac_mandatory_)
      dict->SetBoolean("pac_mandatory", pac_mandatory_);
  }

  // Output the manual settings.
  if (proxy_rules_.type != ProxyRules::TYPE_NO_RULES) {
    switch (proxy_rules_.type) {
      case ProxyRules::TYPE_SINGLE_PROXY:
        AddProxyToValue("single_proxy", proxy_rules_.single_proxy, dict);
        break;
      case ProxyRules::TYPE_PROXY_PER_SCHEME: {
        DictionaryValue* dict2 = new DictionaryValue();
        AddProxyToValue("http", proxy_rules_.proxy_for_http, dict2);
        AddProxyToValue("https", proxy_rules_.proxy_for_https, dict2);
        AddProxyToValue("ftp", proxy_rules_.proxy_for_ftp, dict2);
        AddProxyToValue("fallback", proxy_rules_.fallback_proxy, dict2);
        dict->Set("proxy_per_scheme", dict2);
        break;
      }
      default:
        NOTREACHED();
    }

    // Output the bypass rules.
    const ProxyBypassRules& bypass = proxy_rules_.bypass_rules;
    if (!bypass.rules().empty()) {
      if (proxy_rules_.reverse_bypass)
        dict->SetBoolean("reverse_bypass", true);

      ListValue* list = new ListValue();

      for (ProxyBypassRules::RuleList::const_iterator it =
              bypass.rules().begin();
           it != bypass.rules().end(); ++it) {
        list->Append(Value::CreateStringValue((*it)->ToString()));
      }

      dict->Set("bypass_list", list);
    }
  }

  // Output the source.
  dict->SetString("source", ProxyConfigSourceToString(source_));

  return dict;
}

}  // namespace net
