| Index: net/dns/dns_hosts.cc
|
| diff --git a/net/dns/dns_hosts.cc b/net/dns/dns_hosts.cc
|
| index 2fb627e81f7b04653ee1b5906a8f5a7a90ab6ee6..b43ac542331c294aa7763e8394590a6366f89991 100644
|
| --- a/net/dns/dns_hosts.cc
|
| +++ b/net/dns/dns_hosts.cc
|
| @@ -8,24 +8,25 @@
|
| #include "base/logging.h"
|
| #include "base/metrics/histogram.h"
|
| #include "base/strings/string_util.h"
|
| -#include "base/strings/string_tokenizer.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)
|
| + explicit HostsParser(const StringPiece& text, ParseHostsCommaMode comma_mode)
|
| : text_(text),
|
| data_(text.data()),
|
| end_(text.size()),
|
| pos_(0),
|
| - token_(),
|
| - token_is_ip_(false) {}
|
| + 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
|
| @@ -49,6 +50,14 @@ class HostsParser {
|
| 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();
|
| @@ -62,7 +71,6 @@ class HostsParser {
|
| }
|
| }
|
|
|
| - text_ = StringPiece();
|
| return false;
|
| }
|
|
|
| @@ -85,14 +93,28 @@ class HostsParser {
|
|
|
| private:
|
| void SkipToken() {
|
| - pos_ = text_.find_first_of(" \t\n\r#", pos_);
|
| + 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() {
|
| - pos_ = text_.find_first_not_of(" \t", pos_);
|
| + 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;
|
| + }
|
| }
|
|
|
| - StringPiece text_;
|
| + const StringPiece text_;
|
| const char* data_;
|
| const size_t end_;
|
|
|
| @@ -100,19 +122,21 @@ class HostsParser {
|
| StringPiece token_;
|
| bool token_is_ip_;
|
|
|
| + const ParseHostsCommaMode comma_mode_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(HostsParser);
|
| };
|
|
|
| -
|
| -
|
| -void ParseHosts(const std::string& contents, DnsHosts* dns_hosts) {
|
| +void ParseHostsWithCommaMode(const std::string& contents,
|
| + DnsHosts* dns_hosts,
|
| + ParseHostsCommaMode comma_mode) {
|
| CHECK(dns_hosts);
|
| DnsHosts& hosts = *dns_hosts;
|
|
|
| StringPiece ip_text;
|
| IPAddressNumber ip;
|
| AddressFamily family = ADDRESS_FAMILY_IPV4;
|
| - HostsParser parser(contents);
|
| + HostsParser parser(contents, comma_mode);
|
| while (parser.Advance()) {
|
| if (parser.token_is_ip()) {
|
| StringPiece new_ip_text = parser.token();
|
| @@ -140,6 +164,27 @@ void ParseHosts(const std::string& contents, DnsHosts* dns_hosts) {
|
| }
|
| }
|
|
|
| +} // 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.
|
|
|