amis-rpc-design/node_modules/tldjs/lib/domain.js
2023-10-07 19:42:30 +08:00

116 lines
3.2 KiB
JavaScript

'use strict';
/**
* Polyfill for `endsWith`
*
* @param {string} str
* @param {string} pattern
* @return {boolean}
*/
function endsWith(str, pattern) {
return (
str.lastIndexOf(pattern) === (str.length - pattern.length)
);
}
/**
* Check if `vhost` is a valid suffix of `hostname` (top-domain)
*
* It means that `vhost` needs to be a suffix of `hostname` and we then need to
* make sure that: either they are equal, or the character preceding `vhost` in
* `hostname` is a '.' (it should not be a partial label).
*
* * hostname = 'not.evil.com' and vhost = 'vil.com' => not ok
* * hostname = 'not.evil.com' and vhost = 'evil.com' => ok
* * hostname = 'not.evil.com' and vhost = 'not.evil.com' => ok
*
* @param {string} hostname
* @param {string} vhost
* @return {boolean}
*/
function shareSameDomainSuffix(hostname, vhost) {
if (endsWith(hostname, vhost)) {
return (
hostname.length === vhost.length ||
hostname[hostname.length - vhost.length - 1] === '.'
);
}
return false;
}
/**
* Given a hostname and its public suffix, extract the general domain.
*
* @param {string} hostname
* @param {string} publicSuffix
* @return {string}
*/
function extractDomainWithSuffix(hostname, publicSuffix) {
// Locate the index of the last '.' in the part of the `hostname` preceding
// the public suffix.
//
// examples:
// 1. not.evil.co.uk => evil.co.uk
// ^ ^
// | | start of public suffix
// | index of the last dot
//
// 2. example.co.uk => example.co.uk
// ^ ^
// | | start of public suffix
// |
// | (-1) no dot found before the public suffix
var publicSuffixIndex = hostname.length - publicSuffix.length - 2;
var lastDotBeforeSuffixIndex = hostname.lastIndexOf('.', publicSuffixIndex);
// No '.' found, then `hostname` is the general domain (no sub-domain)
if (lastDotBeforeSuffixIndex === -1) {
return hostname;
}
// Extract the part between the last '.'
return hostname.substr(lastDotBeforeSuffixIndex + 1);
}
/**
* Detects the domain based on rules and upon and a host string
*
* @api
* @param {string} host
* @return {String}
*/
module.exports = function getDomain(validHosts, suffix, hostname) {
// Check if `hostname` ends with a member of `validHosts`.
for (var i = 0; i < validHosts.length; i += 1) {
var vhost = validHosts[i];
if (shareSameDomainSuffix(hostname, vhost)) {
return vhost;
}
}
// If there is no suffix, there is no hostname
if (suffix === null) {
return null;
}
// If `hostname` is a valid public suffix, then there is no domain to return.
// Since we already know that `getPublicSuffix` returns a suffix of `hostname`
// there is no need to perform a string comparison and we only compare the
// size.
if (suffix.length === hostname.length) {
return null;
}
// To extract the general domain, we start by identifying the public suffix
// (if any), then consider the domain to be the public suffix with one added
// level of depth. (e.g.: if hostname is `not.evil.co.uk` and public suffix:
// `co.uk`, then we take one more level: `evil`, giving the final result:
// `evil.co.uk`).
return extractDomainWithSuffix(hostname, suffix);
};