// 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/dns/dns_hosts.h"

#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"

using base::StringPiece;

namespace net {

namespace {

// Parses the contents of a hosts file.  Returns one token (IP or hostname) at
// a time.  Doesn't copy anything; accepts the file as a StringPiece and
// returns tokens as StringPieces.
class HostsParser {
 public:
  explicit HostsParser(const StringPiece& text, ParseHostsCommaMode comma_mode)
      : text_(text),
        data_(text.data()),
        end_(text.size()),
        pos_(0),
        token_is_ip_(false),
        comma_mode_(comma_mode) {}

  // Advances to the next token (IP or hostname).  Returns whether another
  // token was available.  |token_is_ip| and |token| can be used to find out
  // the type and text of the token.
  bool Advance() {
    bool next_is_ip = (pos_ == 0);
    while (pos_ < end_ && pos_ != std::string::npos) {
      switch (text_[pos_]) {
        case ' ':
        case '\t':
          SkipWhitespace();
          break;

        case '\r':
        case '\n':
          next_is_ip = true;
          pos_++;
          break;

        case '#':
          SkipRestOfLine();
          break;

        case ',':
          if (comma_mode_ == PARSE_HOSTS_COMMA_IS_WHITESPACE) {
            SkipWhitespace();
            break;
          }

          // If comma_mode_ is COMMA_IS_TOKEN, fall through:

        default: {
          size_t token_start = pos_;
          SkipToken();
          size_t token_end = (pos_ == std::string::npos) ? end_ : pos_;

          token_ = StringPiece(data_ + token_start, token_end - token_start);
          token_is_ip_ = next_is_ip;

          return true;
        }
      }
    }

    return false;
  }

  // Fast-forwards the parser to the next line.  Should be called if an IP
  // address doesn't parse, to avoid wasting time tokenizing hostnames that
  // will be ignored.
  void SkipRestOfLine() {
    pos_ = text_.find("\n", pos_);
  }

  // Returns whether the last-parsed token is an IP address (true) or a
  // hostname (false).
  bool token_is_ip() { return token_is_ip_; }

  // Returns the text of the last-parsed token as a StringPiece referencing
  // the same underlying memory as the StringPiece passed to the constructor.
  // Returns an empty StringPiece if no token has been parsed or the end of
  // the input string has been reached.
  const StringPiece& token() { return token_; }

 private:
  void SkipToken() {
    switch (comma_mode_) {
      case PARSE_HOSTS_COMMA_IS_TOKEN:
        pos_ = text_.find_first_of(" \t\n\r#", pos_);
        break;
      case PARSE_HOSTS_COMMA_IS_WHITESPACE:
        pos_ = text_.find_first_of(" ,\t\n\r#", pos_);
        break;
    }
  }

  void SkipWhitespace() {
    switch (comma_mode_) {
      case PARSE_HOSTS_COMMA_IS_TOKEN:
        pos_ = text_.find_first_not_of(" \t", pos_);
        break;
      case PARSE_HOSTS_COMMA_IS_WHITESPACE:
        pos_ = text_.find_first_not_of(" ,\t", pos_);
        break;
    }
  }

  const StringPiece text_;
  const char* data_;
  const size_t end_;

  size_t pos_;
  StringPiece token_;
  bool token_is_ip_;

  const ParseHostsCommaMode comma_mode_;

  DISALLOW_COPY_AND_ASSIGN(HostsParser);
};

void ParseHostsWithCommaMode(const std::string& contents,
                             DnsHosts* dns_hosts,
                             ParseHostsCommaMode comma_mode) {
  CHECK(dns_hosts);

  StringPiece ip_text;
  IPAddressNumber ip;
  AddressFamily family = ADDRESS_FAMILY_IPV4;
  HostsParser parser(contents, comma_mode);
  while (parser.Advance()) {
    if (parser.token_is_ip()) {
      StringPiece new_ip_text = parser.token();
      // Some ad-blocking hosts files contain thousands of entries pointing to
      // the same IP address (usually 127.0.0.1).  Don't bother parsing the IP
      // again if it's the same as the one above it.
      if (new_ip_text != ip_text) {
        IPAddressNumber new_ip;
        if (ParseIPLiteralToNumber(parser.token().as_string(), &new_ip)) {
          ip_text = new_ip_text;
          ip.swap(new_ip);
          family = (ip.size() == 4) ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6;
        } else {
          parser.SkipRestOfLine();
        }
      }
    } else {
      DnsHostsKey key(parser.token().as_string(), family);
      key.first = base::ToLowerASCII(key.first);
      IPAddressNumber* mapped_ip = &(*dns_hosts)[key];
      if (mapped_ip->empty())
        *mapped_ip = ip;
      // else ignore this entry (first hit counts)
    }
  }
}

}  // namespace

void ParseHostsWithCommaModeForTesting(const std::string& contents,
                                       DnsHosts* dns_hosts,
                                       ParseHostsCommaMode comma_mode) {
  ParseHostsWithCommaMode(contents, dns_hosts, comma_mode);
}

void ParseHosts(const std::string& contents, DnsHosts* dns_hosts) {
  ParseHostsCommaMode comma_mode;
#if defined(OS_MACOSX)
  // Mac OS X allows commas to separate hostnames.
  comma_mode = PARSE_HOSTS_COMMA_IS_WHITESPACE;
#else
  // Linux allows commas in hostnames.
  comma_mode = PARSE_HOSTS_COMMA_IS_TOKEN;
#endif

  ParseHostsWithCommaMode(contents, dns_hosts, comma_mode);
}

bool ParseHostsFile(const base::FilePath& path, DnsHosts* dns_hosts) {
  dns_hosts->clear();
  // Missing file indicates empty HOSTS.
  if (!base::PathExists(path))
    return true;

  int64 size;
  if (!base::GetFileSize(path, &size))
    return false;

  UMA_HISTOGRAM_COUNTS("AsyncDNS.HostsSize",
                       static_cast<base::HistogramBase::Sample>(size));

  // Reject HOSTS files larger than |kMaxHostsSize| bytes.
  const int64 kMaxHostsSize = 1 << 25;  // 32MB
  if (size > kMaxHostsSize)
    return false;

  std::string contents;
  if (!base::ReadFileToString(path, &contents))
    return false;

  ParseHosts(contents, dns_hosts);
  return true;
}

}  // namespace net

