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