1 package org.cacert.gigi.util;
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStreamReader;
7 import java.util.HashSet;
9 public class PublicSuffixes {
11 HashSet<String> suffixes = new HashSet<>();
13 HashSet<String> wildcards = new HashSet<>();
15 HashSet<String> exceptions = new HashSet<>();
17 private static final String url = "https://publicsuffix.org/list/effective_tld_names.dat";
19 private static PublicSuffixes instance;
21 private static PublicSuffixes generateDefault() throws IOException {
22 try (BufferedReader br = new BufferedReader(new InputStreamReader(PublicSuffixes.class.getResourceAsStream("effective_tld_names.dat"), "UTF-8"))) {
23 return new PublicSuffixes(br);
27 public synchronized static PublicSuffixes getInstance() {
28 if (instance == null) {
30 instance = generateDefault();
31 } catch (IOException e) {
38 private PublicSuffixes(BufferedReader br) throws IOException {
40 while ((line = br.readLine()) != null) {
41 if (line.startsWith("//")) {
47 String[] lineParts = line.split("\\s", 2);
48 if (lineParts.length == 0) {
49 throw new Error("split had strange behavior");
52 if (line.startsWith("*.")) {
53 String data = line.substring(2);
54 if (data.contains("*") || data.contains("!")) {
55 System.out.println("Error! unparsable public suffix line: " + line);
58 addWildcard(IDN.toASCII(data));
59 } else if (line.startsWith("!")) {
60 String data = line.substring(1);
61 if (data.contains("*") || data.contains("!")) {
62 System.out.println("Error! unparsable public suffix line: " + line);
65 addException(IDN.toASCII(data));
67 if (line.contains("*") || line.contains("!")) {
68 System.out.println("Error! unparsable public suffix line: " + line);
71 addSuffix(IDN.toASCII(line));
76 private void addWildcard(String data) {
80 private void addException(String data) {
84 private void addSuffix(String line) {
88 public String getRegistrablePart(String domain) {
92 if (domain.startsWith(".")) {
95 if (isSuffix(domain) && !exceptions.contains(domain)) {
98 return getPublicSuffix0(domain);
101 private String getPublicSuffix0(String domain) {
103 int d = domain.indexOf('.');
107 if (exceptions.contains(domain)) {
110 String nextDomain = domain.substring(d + 1);
111 if (isSuffix(nextDomain)) {
115 return getPublicSuffix0(nextDomain);
118 private boolean isSuffix(String domain) {
119 if (suffixes.contains(domain)) {
122 if (exceptions.contains(domain)) {
125 int idx = domain.indexOf('.');
126 if (idx != -1 && wildcards.contains(domain.substring(idx + 1))) {