]> WPIA git - gigi.git/blob - src/org/cacert/gigi/util/PublicSuffixes.java
ADD: prefix check for domains against database
[gigi.git] / src / org / cacert / gigi / util / PublicSuffixes.java
1 package org.cacert.gigi.util;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStreamReader;
6 import java.net.IDN;
7 import java.util.HashSet;
8
9 public class PublicSuffixes {
10
11     HashSet<String> suffixes = new HashSet<>();
12
13     HashSet<String> wildcards = new HashSet<>();
14
15     HashSet<String> exceptions = new HashSet<>();
16
17     private static final String url = "https://publicsuffix.org/list/effective_tld_names.dat";
18
19     private static PublicSuffixes instance;
20
21     private static void generateDefault() throws IOException {
22         try (BufferedReader br = new BufferedReader(new InputStreamReader(PublicSuffixes.class.getResourceAsStream("effective_tld_names.dat"), "UTF-8"))) {
23             instance = new PublicSuffixes(br);
24         }
25     }
26
27     public static PublicSuffixes getInstance() {
28         if (instance == null) {
29             try {
30                 generateDefault();
31             } catch (IOException e) {
32                 throw new Error(e);
33             }
34         }
35         return instance;
36     }
37
38     private PublicSuffixes(BufferedReader br) throws IOException {
39         String line;
40         while ((line = br.readLine()) != null) {
41             if (line.startsWith("//")) {
42                 continue;
43             }
44             if (line.isEmpty()) {
45                 continue;
46             }
47             line = line.split("\\s", 2)[0];
48             if (line.startsWith("*.")) {
49                 String data = line.substring(2);
50                 if (data.contains("*") || data.contains("!")) {
51                     System.out.println("Error! unparsable public suffix line: " + line);
52                     continue;
53                 }
54                 addWildcard(IDN.toASCII(data));
55             } else if (line.startsWith("!")) {
56                 String data = line.substring(1);
57                 if (data.contains("*") || data.contains("!")) {
58                     System.out.println("Error! unparsable public suffix line: " + line);
59                     continue;
60                 }
61                 addException(IDN.toASCII(data));
62             } else {
63                 if (line.contains("*") || line.contains("!")) {
64                     System.out.println("Error! unparsable public suffix line: " + line);
65                     continue;
66                 }
67                 addSuffix(IDN.toASCII(line));
68             }
69         }
70     }
71
72     private void addWildcard(String data) {
73         wildcards.add(data);
74     }
75
76     private void addException(String data) {
77         exceptions.add(data);
78     }
79
80     private void addSuffix(String line) {
81         suffixes.add(line);
82     }
83
84     public String getRegistrablePart(String domain) {
85         if (domain == null) {
86             return null;
87         }
88         if (domain.startsWith(".")) {
89             return null;
90         }
91         if (isSuffix(domain) && !exceptions.contains(domain)) {
92             return null;
93         }
94         return getPublicSuffix0(domain);
95     }
96
97     private String getPublicSuffix0(String domain) {
98
99         int d = domain.indexOf('.');
100         if (d == -1) {
101             return null;
102         }
103         if (exceptions.contains(domain)) {
104             return domain;
105         }
106         String nextDomain = domain.substring(d + 1);
107         if (isSuffix(nextDomain)) {
108             return domain;
109         }
110
111         return getPublicSuffix0(nextDomain);
112     }
113
114     private boolean isSuffix(String domain) {
115         if (suffixes.contains(domain)) {
116             return true;
117         }
118         if (exceptions.contains(domain)) {
119             return false;
120         }
121         int idx = domain.indexOf('.');
122         if (idx != -1 && wildcards.contains(domain.substring(idx + 1))) {
123             return true;
124         }
125         return false;
126     }
127 }