All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.malkusch.whoisServerList.publicSuffixList.PublicSuffixList Maven / Gradle / Ivy

package de.malkusch.whoisServerList.publicSuffixList;

import java.net.URL;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

import net.jcip.annotations.Immutable;

import org.apache.commons.lang3.StringUtils;

import de.malkusch.whoisServerList.publicSuffixList.index.Index;
import de.malkusch.whoisServerList.publicSuffixList.rule.Rule;
import de.malkusch.whoisServerList.publicSuffixList.util.DomainUtil;
import de.malkusch.whoisServerList.publicSuffixList.util.PunycodeAutoDecoder;

/**
 * API for the Public Suffix List.
 *
 * Use {@link PublicSuffixListFactory} for building this api.
 *
 * You can use the API's methods with UTF-8 domain names or Punycode
 * encoded ASCII domain names. The API will return the results in
 * the same format as the input was. I.e. if you use an UTF-8 string
 * the result will be an UTF-8 String as well. Same for Punycode.
 *
 * The API is case insensitive.
 *
 * @author [email protected]
 *
 * @see PublicSuffixListFactory
 * @see https://publicsuffix.org/
 * @see Donations
 */
@Immutable
public final class PublicSuffixList {

    /**
     * Public Suffix List url.
     */
    private final URL url;

    /**
     * Public Suffix List encoding.
     */
    private final Charset charset;

    /**
     * Rule index.
     */
    private final Index index;

    /**
     * Initializes the Public List API.
     *
     * @param index    the rule index
     * @param url      the Public Suffix List url
     * @param charset  the character encoding of the list
     *
     * @see PublicSuffixListFactory#build()
     */
    PublicSuffixList(final Index index, final URL url,
            final Charset charset) {

        this.index = index;
        this.url = url;
        this.charset = charset;
    }

    /**
     * Gets the registrable domain.
     *
     * E.g. "www.example.net" and "example.net" will return "example.net".
     * Null, an empty string or domains with a leading dot will return null.
     *
     * This method is case insensitive.
     *
     * @param domain  the domain name, null returns null
     * @return the registrable domain,
     *         null if the domain is not registrable at all
     */
    public String getRegistrableDomain(final String domain) {
        if (StringUtils.isEmpty(domain)) {
            return null;

        }
        /*
         * Mozilla's test cases implies that leading dots
         * result to no registrable domain.
         * @see ExampleTest
         */
        if (domain.charAt(0) == '.') {
            return null;

        }
        PunycodeAutoDecoder punycode = new PunycodeAutoDecoder();
        String decodedDomain = punycode.decode(domain);

        String suffix = getPublicSuffix(decodedDomain);
        if (StringUtils.equals(decodedDomain, suffix)) {
            return null;

        }
        String[] suffixLabels = DomainUtil.splitLabels(suffix);
        if (suffixLabels == null) {
            return null;

        }
        String[] labels = DomainUtil.splitLabels(decodedDomain);
        int offset = labels.length - suffixLabels.length - 1;
        String registrableDomain = DomainUtil.joinLabels(
                Arrays.copyOfRange(labels, offset, labels.length));

        return punycode.recode(registrableDomain);
    }

    /**
     * Returns whether a domain is registrable.
     *
     * E.g. example.net is registrable, "www.example.net" and "net" are not.
     *
     * This method is case insensitive.
     *
     * @param domain  the domain name, not null
     * @return {@code true} if the domain is registrable
     */
    public boolean isRegistrable(final String domain) {
        if (domain == null) {
            throw new IllegalArgumentException("The domain must not be null");

        }
        return domain.equals(getRegistrableDomain(domain));
    }

    /**
     * Returns the public suffix from a domain.
     *
     * If the domain is already a public suffix, it will be returned unchanged.
     * E.g. "www.example.net" will return "net".
     *
     * This method is case insensitive.
     *
     * @param domain  the domain name
     * @return the public suffix, {@code null} if none matched
     */
    public String getPublicSuffix(final String domain) {
        if (StringUtils.isEmpty(domain)) {
            return null;

        }
        PunycodeAutoDecoder punycode = new PunycodeAutoDecoder();
        String decodedDomain = punycode.recode(domain);

        Rule rule = index.findRule(decodedDomain);
        if (rule == null) {
            return null;

        }
        return punycode.decode(rule.match(decodedDomain));
    }

    /**
     * Returns whether a domain is a public suffix or not.
     *
     * Example: "com" is a public suffix, "example.com" isn't.
     *
     * This method is case insensitive.
     *
     * @param domain  the domain name, not null
     * @return {@code true} if the domain is a public suffix
     */
    public boolean isPublicSuffix(final String domain) {
        if (domain == null) {
            throw new IllegalArgumentException("The domain must not be null");

        }
        return domain.equals(getPublicSuffix(domain));
    }

    /**
     * Returns the character encoding of the public suffix list.
     *
     * @return the character encoding
     */
    public Charset getCharset() {
        return charset;
    }

    /**
     * Returns the URL of the public suffix list.
     *
     * @return the URL
     */
    public URL getURL() {
        return url;
    }

    /**
     * Returns a list with all rules.
     *
     * @return the rule list
     */
    public List getRules() {
        return index.getRules();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy