// 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/file_util.h" #include "base/logging.h" #include "base/string_tokenizer.h" #include "base/string_util.h" namespace net { void ParseHosts(const std::string& contents, DnsHosts* dns_hosts) { CHECK(dns_hosts); DnsHosts& hosts = *dns_hosts; // Split into lines. Accept CR for Windows. StringTokenizer contents_lines(contents, "\n\r"); while (contents_lines.GetNext()) { // Ignore comments after '#'. std::string line = contents_lines.token(); StringTokenizer line_parts(line, "#"); line_parts.set_options(StringTokenizer::RETURN_DELIMS); if (line_parts.GetNext() && !line_parts.token_is_delim()) { // Split and trim whitespace. std::string part = line_parts.token(); StringTokenizer tokens(part, " \t"); if (tokens.GetNext()) { IPAddressNumber ip; // TODO(szym): handle %iface notation on mac if (!ParseIPLiteralToNumber(tokens.token(), &ip)) continue; // Ignore malformed lines. AddressFamily fam = (ip.size() == 4) ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6; while (tokens.GetNext()) { DnsHostsKey key(tokens.token(), fam); StringToLowerASCII(&(key.first)); IPAddressNumber& mapped_ip = hosts[key]; if (mapped_ip.empty()) mapped_ip = ip; // else ignore this entry (first hit counts) } } } } } DnsHostsReader::DnsHostsReader(const FilePath& path, const CallbackType& callback) : path_(path), callback_(callback), success_(false) { DCHECK(!callback.is_null()); } DnsHostsReader::DnsHostsReader(const FilePath& path) : path_(path), success_(false) { } // Reads the contents of the file at |path| into |str| if the total length is // less than |max_size|. static bool ReadFile(const FilePath& path, int64 max_size, std::string* str) { int64 size; if (!file_util::GetFileSize(path, &size) || size > max_size) return false; return file_util::ReadFileToString(path, str); } void DnsHostsReader::DoWork() { success_ = false; dns_hosts_.clear(); // Missing file indicates empty HOSTS. if (!file_util::PathExists(path_)) { success_ = true; return; } std::string contents; const int64 kMaxHostsSize = 1 << 16; if (ReadFile(path_, kMaxHostsSize, &contents)) { success_ = true; ParseHosts(contents, &dns_hosts_); } } void DnsHostsReader::OnWorkFinished() { DCHECK(!IsCancelled()); if (success_) callback_.Run(dns_hosts_); } DnsHostsReader::~DnsHostsReader() {} } // namespace net