This source file includes following definitions.
- GetRegistryLengthImpl
- GetDomainAndRegistryImpl
- GetDomainAndRegistry
- GetDomainAndRegistry
- SameDomainOrHost
- GetRegistryLength
- GetRegistryLength
- SetFindDomainFunctionAndStringPoolForTesting
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "net/base/net_module.h"
#include "net/base/net_util.h"
#include "url/gurl.h"
#include "url/url_parse.h"
#include "effective_tld_names.cc"
namespace net {
namespace registry_controlled_domains {
namespace {
const int kExceptionRule = 1;
const int kWildcardRule = 2;
const int kPrivateRule = 4;
const FindDomainPtr kDefaultFindDomainFunction = Perfect_Hash::FindDomain;
const char* const kDefaultStringPool = stringpool;
#undef stringpool
FindDomainPtr g_find_domain_function = kDefaultFindDomainFunction;
const char* g_stringpool = kDefaultStringPool;
size_t GetRegistryLengthImpl(
const std::string& host,
UnknownRegistryFilter unknown_filter,
PrivateRegistryFilter private_filter) {
DCHECK(!host.empty());
const size_t host_check_begin = host.find_first_not_of('.');
if (host_check_begin == std::string::npos)
return 0;
size_t host_check_len = host.length();
if (host[host_check_len - 1] == '.') {
--host_check_len;
DCHECK(host_check_len > 0);
if (host[host_check_len - 1] == '.')
return 0;
}
size_t prev_start = std::string::npos;
size_t curr_start = host_check_begin;
size_t next_dot = host.find('.', curr_start);
if (next_dot >= host_check_len)
return 0;
while (1) {
const char* domain_str = host.data() + curr_start;
int domain_length = host_check_len - curr_start;
const DomainRule* rule = g_find_domain_function(domain_str, domain_length);
if (rule) {
bool do_check = !(rule->type & kPrivateRule) ||
private_filter == INCLUDE_PRIVATE_REGISTRIES;
if (do_check && base::strncasecmp(domain_str,
g_stringpool + rule->name_offset,
domain_length) == 0) {
if (rule->type & kWildcardRule && (prev_start != std::string::npos)) {
return (prev_start == host_check_begin) ?
0 : (host.length() - prev_start);
}
if (rule->type & kExceptionRule) {
if (next_dot == std::string::npos) {
NOTREACHED() << "Invalid exception rule";
return 0;
}
return host.length() - next_dot - 1;
}
return (curr_start == host_check_begin) ?
0 : (host.length() - curr_start);
}
}
if (next_dot >= host_check_len)
break;
prev_start = curr_start;
curr_start = next_dot + 1;
next_dot = host.find('.', curr_start);
}
return unknown_filter == INCLUDE_UNKNOWN_REGISTRIES ?
(host.length() - curr_start) : 0;
}
std::string GetDomainAndRegistryImpl(
const std::string& host, PrivateRegistryFilter private_filter) {
DCHECK(!host.empty());
const size_t registry_length =
GetRegistryLengthImpl(host, INCLUDE_UNKNOWN_REGISTRIES, private_filter);
if ((registry_length == std::string::npos) || (registry_length == 0))
return std::string();
DCHECK(host.length() >= 2);
if (registry_length > (host.length() - 2)) {
NOTREACHED() <<
"Host does not have at least one subcomponent before registry!";
return std::string();
}
const size_t dot = host.rfind('.', host.length() - registry_length - 2);
if (dot == std::string::npos)
return host;
return host.substr(dot + 1);
}
}
std::string GetDomainAndRegistry(
const GURL& gurl,
PrivateRegistryFilter filter) {
const url_parse::Component host =
gurl.parsed_for_possibly_invalid_spec().host;
if ((host.len <= 0) || gurl.HostIsIPAddress())
return std::string();
return GetDomainAndRegistryImpl(std::string(
gurl.possibly_invalid_spec().data() + host.begin, host.len), filter);
}
std::string GetDomainAndRegistry(
const std::string& host,
PrivateRegistryFilter filter) {
url_canon::CanonHostInfo host_info;
const std::string canon_host(CanonicalizeHost(host, &host_info));
if (canon_host.empty() || host_info.IsIPAddress())
return std::string();
return GetDomainAndRegistryImpl(canon_host, filter);
}
bool SameDomainOrHost(
const GURL& gurl1,
const GURL& gurl2,
PrivateRegistryFilter filter) {
const std::string domain1(GetDomainAndRegistry(gurl1, filter));
const std::string domain2(GetDomainAndRegistry(gurl2, filter));
if (!domain1.empty() || !domain2.empty())
return domain1 == domain2;
const url_parse::Component host1 =
gurl1.parsed_for_possibly_invalid_spec().host;
const url_parse::Component host2 =
gurl2.parsed_for_possibly_invalid_spec().host;
if ((host1.len <= 0) || (host1.len != host2.len))
return false;
return !strncmp(gurl1.possibly_invalid_spec().data() + host1.begin,
gurl2.possibly_invalid_spec().data() + host2.begin,
host1.len);
}
size_t GetRegistryLength(
const GURL& gurl,
UnknownRegistryFilter unknown_filter,
PrivateRegistryFilter private_filter) {
const url_parse::Component host =
gurl.parsed_for_possibly_invalid_spec().host;
if (host.len <= 0)
return std::string::npos;
if (gurl.HostIsIPAddress())
return 0;
return GetRegistryLengthImpl(
std::string(gurl.possibly_invalid_spec().data() + host.begin, host.len),
unknown_filter,
private_filter);
}
size_t GetRegistryLength(
const std::string& host,
UnknownRegistryFilter unknown_filter,
PrivateRegistryFilter private_filter) {
url_canon::CanonHostInfo host_info;
const std::string canon_host(CanonicalizeHost(host, &host_info));
if (canon_host.empty())
return std::string::npos;
if (host_info.IsIPAddress())
return 0;
return GetRegistryLengthImpl(canon_host, unknown_filter, private_filter);
}
void SetFindDomainFunctionAndStringPoolForTesting(FindDomainPtr function,
const char* stringpool) {
g_find_domain_function = function ? function : kDefaultFindDomainFunction;
g_stringpool = stringpool ? stringpool : kDefaultStringPool;
}
}
}