diff options
Diffstat (limited to 'vanilla/node_modules/tldts-core/src/domain.ts')
| -rw-r--r-- | vanilla/node_modules/tldts-core/src/domain.ts | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/vanilla/node_modules/tldts-core/src/domain.ts b/vanilla/node_modules/tldts-core/src/domain.ts new file mode 100644 index 0000000..640d33e --- /dev/null +++ b/vanilla/node_modules/tldts-core/src/domain.ts @@ -0,0 +1,100 @@ +import { IOptions } from './options'; + +/** + * 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 + */ +function shareSameDomainSuffix(hostname: string, vhost: string): boolean { + if (hostname.endsWith(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. + */ +function extractDomainWithSuffix( + hostname: string, + publicSuffix: string, +): string { + // 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 + const publicSuffixIndex = hostname.length - publicSuffix.length - 2; + const 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.slice(lastDotBeforeSuffixIndex + 1); +} + +/** + * Detects the domain based on rules and upon and a host string + */ +export default function getDomain( + suffix: string, + hostname: string, + options: IOptions, +): string | null { + // Check if `hostname` ends with a member of `validHosts`. + if (options.validHosts !== null) { + const validHosts = options.validHosts; + for (const vhost of validHosts) { + if (/*@__INLINE__*/ shareSameDomainSuffix(hostname, vhost)) { + return vhost; + } + } + } + + let numberOfLeadingDots = 0; + if (hostname.startsWith('.')) { + while ( + numberOfLeadingDots < hostname.length && + hostname[numberOfLeadingDots] === '.' + ) { + numberOfLeadingDots += 1; + } + } + + // 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 - numberOfLeadingDots) { + 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 /*@__INLINE__*/ extractDomainWithSuffix(hostname, suffix); +} |
