]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blob - app/src/main/java/com/stoutner/privacybrowser/helpers/BlocklistHelper.java
913cc0b1c775e24ba69689f6b45b402694ba7b52
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / helpers / BlocklistHelper.java
1 /*
2  * Copyright © 2018-2019 Soren Stoutner <soren@stoutner.com>.
3  *
4  * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
5  *
6  * Privacy Browser is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Privacy Browser is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 package com.stoutner.privacybrowser.helpers;
21
22 import android.content.res.AssetManager;
23
24 import java.io.BufferedReader;
25 import java.io.IOException;
26 import java.io.InputStreamReader;
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.regex.Pattern;
30
31 public class BlocklistHelper {
32     // Describe the schema of the string array in each entry of the resource requests array list.
33     public final static int REQUEST_DISPOSITION = 0;
34     public final static int REQUEST_URL = 1;
35     public final static int REQUEST_BLOCKLIST = 2;
36     public final static int REQUEST_SUBLIST = 3;
37     public final static int REQUEST_BLOCKLIST_ENTRIES = 4;
38     public final static int REQUEST_BLOCKLIST_ORIGINAL_ENTRY = 5;
39
40     // The request disposition options.
41     public final static String REQUEST_DEFAULT = "0";
42     public final static String REQUEST_ALLOWED = "1";
43     public final static String REQUEST_THIRD_PARTY = "2";
44     public final static String REQUEST_BLOCKED = "3";
45
46     // The whitelists.
47     public final static String MAIN_WHITELIST = "1";
48     public final static String FINAL_WHITELIST = "2";
49     public final static String DOMAIN_WHITELIST = "3";
50     public final static String DOMAIN_INITIAL_WHITELIST = "4";
51     public final static String DOMAIN_FINAL_WHITELIST = "5";
52     public final static String THIRD_PARTY_WHITELIST = "6";
53     public final static String THIRD_PARTY_DOMAIN_WHITELIST = "7";
54     public final static String THIRD_PARTY_DOMAIN_INITIAL_WHITELIST = "8";
55
56     // The blacklists.
57     public final static String MAIN_BLACKLIST = "9";
58     public final static String INITIAL_BLACKLIST = "10";
59     public final static String FINAL_BLACKLIST = "11";
60     public final static String DOMAIN_BLACKLIST = "12";
61     public final static String DOMAIN_INITIAL_BLACKLIST = "13";
62     public final static String DOMAIN_FINAL_BLACKLIST = "14";
63     public final static String DOMAIN_REGULAR_EXPRESSION_BLACKLIST = "15";
64     public final static String THIRD_PARTY_BLACKLIST = "16";
65     public final static String THIRD_PARTY_INITIAL_BLACKLIST = "17";
66     public final static String THIRD_PARTY_DOMAIN_BLACKLIST = "18";
67     public final static String THIRD_PARTY_DOMAIN_INITIAL_BLACKLIST = "19";
68     public final static String THIRD_PARTY_REGULAR_EXPRESSION_BLACKLIST = "20";
69     public final static String THIRD_PARTY_DOMAIN_REGULAR_EXPRESSION_BLACKLIST = "21";
70     public final static String REGULAR_EXPRESSION_BLACKLIST = "22";
71
72     public ArrayList<List<String[]>> parseBlocklist(AssetManager assets, String blocklistName) {
73         // Initialize the header list.
74         List<String[]> headers = new ArrayList<>();  // 0.
75
76         // Initialize the whitelists.
77         List<String[]> mainWhitelist = new ArrayList<>();  // 1.
78         List<String[]> finalWhitelist = new ArrayList<>();  // 2.
79         List<String[]> domainWhitelist = new ArrayList<>();  // 3.
80         List<String[]> domainInitialWhitelist = new ArrayList<>();  // 4.
81         List<String[]> domainFinalWhitelist = new ArrayList<>();  // 5.
82         List<String[]> thirdPartyWhitelist = new ArrayList<>();  // 6.
83         List<String[]> thirdPartyDomainWhitelist = new ArrayList<>();  // 7.
84         List<String[]> thirdPartyDomainInitialWhitelist = new ArrayList<>();  // 8.
85
86         // Initialize the blacklists
87         List<String[]> mainBlacklist = new ArrayList<>();  // 9.
88         List<String[]> initialBlacklist = new ArrayList<>();  // 10.
89         List<String[]> finalBlacklist = new ArrayList<>();  // 11.
90         List<String[]> domainBlacklist = new ArrayList<>();  // 12.
91         List<String[]> domainInitialBlacklist = new ArrayList<>();  // 13.
92         List<String[]> domainFinalBlacklist = new ArrayList<>();  // 14.
93         List<String[]> domainRegularExpressionBlacklist = new ArrayList<>();  // 15.
94         List<String[]> thirdPartyBlacklist = new ArrayList<>();  // 16.
95         List<String[]> thirdPartyInitialBlacklist = new ArrayList<>();  // 17.
96         List<String[]> thirdPartyDomainBlacklist = new ArrayList<>();  // 18.
97         List<String[]> thirdPartyDomainInitialBlacklist = new ArrayList<>();  // 19.
98         List<String[]> regularExpressionBlacklist = new ArrayList<>();  // 20.
99         List<String[]> thirdPartyRegularExpressionBlacklist = new ArrayList<>();  // 21.
100         List<String[]> thirdPartyDomainRegularExpressionBlacklist = new ArrayList<>();  // 22.
101
102
103         // Populate the block lists.  The `try` is required by `InputStreamReader`.
104         try {
105             // Load the block list into a `BufferedReader`.
106             BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(assets.open(blocklistName)));
107
108             // Create a string for storing the block list entries.
109             String blocklistEntry;
110
111             // Parse the block list.
112             while ((blocklistEntry = bufferedReader.readLine()) != null) {
113                 // Store the original block list entry.
114                 String originalBlocklistEntry = blocklistEntry;
115
116                 // Remove any `^` from the block list entry.  Privacy Browser does not process them in the interest of efficiency.
117                 blocklistEntry = blocklistEntry.replace("^", "");
118
119                 //noinspection StatementWithEmptyBody
120                 if (blocklistEntry.contains("##") || blocklistEntry.contains("#?#") || blocklistEntry.contains("#@#") || blocklistEntry.startsWith("[")) {
121                     // Entries that contain `##`, `#?#`, and `#@#` are for hiding elements in the main page's HTML.  Entries that start with `[` describe the AdBlock compatibility level.
122                     // Do nothing.  Privacy Browser does not currently use these entries.
123
124                     //Log.i("Blocklists", "Not added: " + blocklistEntry);
125                 } else //noinspection StatementWithEmptyBody
126                     if (blocklistEntry.contains("$csp=script-src")) {  // Ignore entries that contain `$csp=script-src`.
127                         // Do nothing.  It is uncertain what this directive is even supposed to mean, and it is blocking entire websites like androidcentral.com.  https://redmine.stoutner.com/issues/306.
128
129                         //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
130                 } else //noinspection StatementWithEmptyBody
131                     if (blocklistEntry.contains("$websocket") || blocklistEntry.contains("$third-party,websocket") || blocklistEntry.contains("$script,websocket")) {  // Ignore entries with `websocket`.
132                         // Do nothing.  Privacy Browser does not differentiate between websocket requests and other requests and these entries cause a lot of false positives.
133
134                         //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
135                 } else if (blocklistEntry.startsWith("!")) {  //  Comment entries.
136                     if (blocklistEntry.startsWith("! Version:")) {
137                         // Get the list version number.
138                         String[] listVersion = {blocklistEntry.substring(11)};
139
140                         // Store the list version in the headers list.
141                         headers.add(listVersion);
142                     }
143
144                     if (blocklistEntry.startsWith("! Title:")) {
145                         // Get the list title.
146                         String[] listTitle = {blocklistEntry.substring(9)};
147
148                         // Store the list title in the headers list.
149                         headers.add(listTitle);
150                     }
151
152                     //Log.i("Blocklists", "Not added: " + blocklistEntry);
153                 } else if (blocklistEntry.startsWith("@@")) {  // Entries that begin with `@@` are whitelists.
154                     // Remove the `@@`
155                     blocklistEntry = blocklistEntry.substring(2);
156
157                     // Strip out any initial `||`.  Privacy Browser doesn't differentiate items that only match against the end of the domain name.
158                     if (blocklistEntry.startsWith("||")) {
159                         blocklistEntry = blocklistEntry.substring(2);
160                     }
161
162                     if (blocklistEntry.contains("$")) {  // Filter entries.
163                         //noinspection StatementWithEmptyBody
164                         if (blocklistEntry.contains("~third-party")) {  // Ignore entries that contain `~third-party`.
165                             // Do nothing.
166
167                             //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
168                         } else if (blocklistEntry.contains("third-party")) {  // Third-party white list entries.
169                             if (blocklistEntry.contains("domain=")) {  // Third-party domain white list entries.
170                                 // Parse the entry.
171                                 String entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"));
172                                 String filters = blocklistEntry.substring(blocklistEntry.indexOf("$") + 1);
173                                 String domains = filters.substring(filters.indexOf("domain=") + 7);
174
175                                 //noinspection StatementWithEmptyBody
176                                 if (domains.contains("~")) {  // It is uncertain what a `~` domain means inside an `@@` entry.
177                                     // Do Nothing
178
179                                     //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
180                                 } else if (blocklistEntry.startsWith("|")) {  // Third-party domain initial white list entries.
181                                     // Strip out the initial `|`.
182                                     entry = entry.substring(1);
183
184                                     //noinspection StatementWithEmptyBody
185                                     if (entry.equals("http://") || entry.equals("https://")) {  // Ignore generic entries.
186                                         // Do nothing.  These entries are designed for filter options that Privacy Browser does not use.
187
188                                         //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
189                                     } else {  // Process third-party domain initial white list entries.
190                                         // Process each domain.
191                                         do {
192                                             // Create a string to keep track of the current domain.
193                                             String domain;
194
195                                             if (domains.contains("|")) {  // There is more than one domain in the list.
196                                                 // Get the first domain from the list.
197                                                 domain = domains.substring(0, domains.indexOf("|"));
198
199                                                 // Remove the first domain from the list.
200                                                 domains = domains.substring(domains.indexOf("|") + 1);
201                                             } else {  // There is only one domain in the list.
202                                                 domain = domains;
203                                             }
204
205                                             if (entry.contains("*")) {  // Process a third-party domain initial white list double entry.
206                                                 // Get the index of the wildcard.
207                                                 int wildcardIndex = entry.indexOf("*");
208
209                                                 // Split the entry into components.
210                                                 String firstEntry = entry.substring(0, wildcardIndex);
211                                                 String secondEntry = entry.substring(wildcardIndex + 1);
212
213                                                 // Create an entry string array.
214                                                 String[] domainDoubleEntry = {domain, firstEntry, secondEntry, originalBlocklistEntry};
215
216                                                 // Add the entry to the white list.
217                                                 thirdPartyDomainInitialWhitelist.add(domainDoubleEntry);
218
219                                                 //Log.i("Blocklists", headers.get(1)[0] + " third-party domain initial white list added: " + domain + " , " + firstEntry + " , " + secondEntry +
220                                                 //        "  -  " + originalBlocklistEntry);
221                                             } else {  // Process a third-party domain initial white list single entry.
222                                                 // Create a domain entry string array.
223                                                 String[] domainEntry = {domain, entry, originalBlocklistEntry};
224
225                                                 // Add the entry to the third party domain initial white list.
226                                                 thirdPartyDomainInitialWhitelist.add(domainEntry);
227
228                                                 //Log.i("Blocklists", headers.get(1)[0] + " third-party domain initial white list added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
229                                             }
230                                         } while (domains.contains("|"));
231                                     }
232                                 } else {  // Third-party domain entries.
233                                     // Process each domain.
234                                     do {
235                                         // Create a string to keep track of the current domain.
236                                         String domain;
237
238                                         if (domains.contains("|")) {  // three is more than one domain in the list.
239                                             // Get the first domain from the list.
240                                             domain = domains.substring(0, domains.indexOf("|"));
241
242                                             // Remove the first domain from the list.
243                                             domains = domains.substring(domains.indexOf("|") + 1);
244                                         } else {  // There is only one domain in the list.
245                                             domain = domains;
246                                         }
247
248                                         // Remove any trailing `*` from the entry.
249                                         if (entry.endsWith("*")) {
250                                             entry = entry.substring(0, entry.length() - 1);
251                                         }
252
253                                         if (entry.contains("*")) {  // Process a third-party domain double entry.
254                                             // Get the index of the wildcard.
255                                             int wildcardIndex = entry.indexOf("*");
256
257                                             // Split the entry into components.
258                                             String firstEntry = entry.substring(0, wildcardIndex);
259                                             String secondEntry = entry.substring(wildcardIndex + 1);
260
261                                             // Create an entry string array.
262                                             String[] domainDoubleEntry = {domain, firstEntry, secondEntry, originalBlocklistEntry};
263
264                                             // Add the entry to the white list.
265                                             thirdPartyDomainWhitelist.add(domainDoubleEntry);
266
267                                             //Log.i("Blocklists", headers.get(1)[0] + " third-party domain white list added: " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " +
268                                             //        originalBlocklistEntry);
269                                         } else {  // Process a third-party domain single entry.
270                                             // Create an entry string array.
271                                             String[] domainEntry = {domain, entry, originalBlocklistEntry};
272
273                                             // Add the entry to the white list.
274                                             thirdPartyDomainWhitelist.add(domainEntry);
275
276                                             //Log.i("Blocklists", headers.get(1)[0] + " third-party domain white list added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
277                                         }
278                                     } while (domains.contains("|"));
279                                 }
280                             } else {  // Process third-party white list entries.
281                                 // Parse the entry
282                                 String entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"));
283
284                                 if (entry.contains("*")) {  // There are two or more entries.
285                                     // Get the index of the wildcard.
286                                     int wildcardIndex = entry.indexOf("*");
287
288                                     // Split the entry into components.
289                                     String firstEntry = entry.substring(0, wildcardIndex);
290                                     String secondEntry = entry.substring(wildcardIndex + 1);
291
292                                     if (secondEntry.contains("*")) {  // There are three or more entries.
293                                         // Get the index of the wildcard.
294                                         int secondWildcardIndex = secondEntry.indexOf("*");
295
296                                         // Split the entry into components.
297                                         String realSecondEntry = secondEntry.substring(0, secondWildcardIndex);
298                                         String thirdEntry = secondEntry.substring(secondWildcardIndex + 1);
299
300                                         if (thirdEntry.contains("*")) {  // There are four or more entries.
301                                             // Get the index of the wildcard.
302                                             int thirdWildcardIndex = thirdEntry.indexOf("*");
303
304                                             // Split the entry into components.
305                                             String realThirdEntry = thirdEntry.substring(0, thirdWildcardIndex);
306                                             String fourthEntry = thirdEntry.substring(thirdWildcardIndex + 1);
307
308                                             if (fourthEntry.contains("*")) {  // Process a third-party white list quintuple entry.
309                                                 // Get the index of the wildcard.
310                                                 int fourthWildcardIndex = fourthEntry.indexOf("*");
311
312                                                 // Split the entry into components.
313                                                 String realFourthEntry = fourthEntry.substring(0, fourthWildcardIndex);
314                                                 String fifthEntry = fourthEntry.substring(fourthWildcardIndex + 1);
315
316                                                 // Create an entry string array.
317                                                 String[] quintupleEntry = {firstEntry, realSecondEntry, realThirdEntry, realFourthEntry, fifthEntry, originalBlocklistEntry};
318
319                                                 // Add the entry to the white list.
320                                                 thirdPartyWhitelist.add(quintupleEntry);
321
322                                                 //Log.i("Blocklists", headers.get(1)[0] + " third-party white list added: " + firstEntry + " , " + realSecondEntry + " , " + realThirdEntry + " , " +
323                                                 //        realFourthEntry + " , " + fifthEntry + "  -  " + originalBlocklistEntry);
324                                             } else {  // Process a third-party white list quadruple entry.
325                                                 // Create an entry string array.
326                                                 String[] quadrupleEntry = {firstEntry, realSecondEntry, realThirdEntry, fourthEntry, originalBlocklistEntry};
327
328                                                 // Add the entry to the white list.
329                                                 thirdPartyWhitelist.add(quadrupleEntry);
330
331                                                 //Log.i("Blocklists", headers.get(1)[0] + " third-party white list added: " + firstEntry + " , " + realSecondEntry + " , " + realThirdEntry + " , " +
332                                                 //        fourthEntry + "  -  " + originalBlocklistEntry);
333                                             }
334                                         } else {  // Process a third-party white list triple entry.
335                                             // Create an entry string array.
336                                             String[] tripleEntry = {firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry};
337
338                                             // Add the entry to the white list.
339                                             thirdPartyWhitelist.add(tripleEntry);
340
341                                             //Log.i("Blocklists", headers.get(1)[0] + " third-party white list added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + "  -  " +
342                                             //        originalBlocklistEntry);
343                                         }
344                                     } else {  // Process a third-party white list double entry.
345                                         // Create an entry string array.
346                                         String[] doubleEntry = {firstEntry, secondEntry, originalBlocklistEntry};
347
348                                         // Add the entry to the white list.
349                                         thirdPartyWhitelist.add(doubleEntry);
350
351                                         //Log.i("Blocklists", headers.get(1)[0] + " third-party white list added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
352                                     }
353                                 } else {  // Process a third-party white list single entry.
354                                     // Create an entry string array.
355                                     String[] singleEntry = {entry, originalBlocklistEntry};
356
357                                     // Add the entry to the white list.
358                                     thirdPartyWhitelist.add(singleEntry);
359
360                                     //Log.i("Blocklists", headers.get(1)[0] + " third-party domain white list added: " + entry + "  -  " + originalBlocklistEntry);
361                                 }
362                             }
363                         } else if (blocklistEntry.contains("domain=")) {  // Process domain white list entries.
364                             // Parse the entry
365                             String entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"));
366                             String filters = blocklistEntry.substring(blocklistEntry.indexOf("$") + 1);
367                             String domains = filters.substring(filters.indexOf("domain=") + 7);
368
369                             if (entry.startsWith("|")) {  // Initial domain white list entries.
370                                 // Strip the initial `|`.
371                                 entry = entry.substring(1);
372
373                                 //noinspection StatementWithEmptyBody
374                                 if (entry.equals("http://") || entry.equals("https://")) {  // Ignore generic entries.
375                                     // Do nothing.  These entries are designed for filter options that Privacy Browser does not use.
376
377                                     //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
378                                 } else {  // Initial domain white list entry.
379                                     // Process each domain.
380                                     do {
381                                         // Create a string to keep track of the current domain.
382                                         String domain;
383
384                                         if (domains.contains("|")) {  // There is more than one domain in the list.
385                                             // Get the first domain from the list.
386                                             domain = domains.substring(0, domains.indexOf("|"));
387
388                                             // Remove the first domain from the list.
389                                             domains = domains.substring(domains.indexOf("|") + 1);
390                                         } else {  // There is only one domain in the list.
391                                             domain = domains;
392                                         }
393
394                                         if (entry.contains("*")) {  // There are two or more entries.
395                                             // Get the index of the wildcard.
396                                             int wildcardIndex = entry.indexOf("*");
397
398                                             // Split the entry into components.
399                                             String firstEntry = entry.substring(0, wildcardIndex);
400                                             String secondEntry = entry.substring(wildcardIndex + 1);
401
402                                             if (secondEntry.contains("*")) {  // Process a domain initial triple entry.
403                                                 // Get the index of the wildcard.
404                                                 int secondWildcardIndex = secondEntry.indexOf("*");
405
406                                                 // Split the entry into components.
407                                                 String realSecondEntry = secondEntry.substring(0, secondWildcardIndex);
408                                                 String thirdEntry = secondEntry.substring(secondWildcardIndex + 1);
409
410                                                 // Create an entry string array.
411                                                 String[] domainTripleEntry = {domain, firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry};
412
413                                                 // Add the entry to the white list.
414                                                 domainInitialWhitelist.add(domainTripleEntry);
415
416                                                 //Log.i("Blocklists", headers.get(1)[0] + " domain initial white list entry added: " + domain + " , " + firstEntry + " , " + realSecondEntry + " , " +
417                                                 //        thirdEntry + "  -  " + originalBlocklistEntry);
418                                             } else {  // Process a domain initial double entry.
419                                                 // Create an entry string array.
420                                                 String[] domainDoubleEntry = {domain, firstEntry, secondEntry, originalBlocklistEntry};
421
422                                                 // Add the entry to the white list.
423                                                 domainInitialWhitelist.add(domainDoubleEntry);
424
425                                                 //Log.i("Blocklists", headers.get(1)[0] + " domain initial white list entry added: " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " +
426                                                 //        originalBlocklistEntry);
427                                             }
428                                         } else {  // Process a domain initial single entry.
429                                             // Create an entry string array.
430                                             String[] domainEntry = {domain, entry, originalBlocklistEntry};
431
432                                             // Add the entry to the white list.
433                                             domainInitialWhitelist.add(domainEntry);
434
435                                             //Log.i("Blocklists", headers.get(1)[0] + " domain initial white list entry added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
436                                         }
437                                     } while (domains.contains("|"));
438                                 }
439                             } else if (entry.endsWith("|")) {  // Final domain white list entries.
440                                 // Strip the `|` from the end of the entry.
441                                 entry = entry.substring(0, entry.length() - 1);
442
443                                 // Process each domain.
444                                 do {
445                                     // Create a string to keep track of the current domain.
446                                     String domain;
447
448                                     if (domains.contains("|")) {  // There is more than one domain in the list.
449                                         // Get the first domain from the list.
450                                         domain = domains.substring(0, domains.indexOf("|"));
451
452                                         // Remove the first domain from the list.
453                                         domains = domains.substring(domains.indexOf("|") + 1);
454                                     } else {  // There is only one domain in the list.
455                                         domain = domains;
456                                     }
457
458                                     if (entry.contains("*")) {  // Process a domain final white list double entry.
459                                         // Get the index of the wildcard.
460                                         int wildcardIndex = entry.indexOf("*");
461
462                                         // Split the entry into components.
463                                         String firstEntry = entry.substring(0, wildcardIndex);
464                                         String secondEntry = entry.substring(wildcardIndex + 1);
465
466                                         // Create an entry string array.
467                                         String[] domainDoubleEntry = {domain, firstEntry, secondEntry, originalBlocklistEntry};
468
469                                         // Add the entry to the white list.
470                                         domainFinalWhitelist.add(domainDoubleEntry);
471
472                                         //Log.i("Blocklists", headers.get(1)[0] + " domain final white list added: " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " +
473                                         //        originalBlocklistEntry);
474                                     } else {  // Process a domain final white list single entry.
475                                         // create an entry string array.
476                                         String[] domainEntry = {domain, entry, originalBlocklistEntry};
477
478                                         // Add the entry to the white list.
479                                         domainFinalWhitelist.add(domainEntry);
480
481                                         //Log.i("Blocklists", headers.get(1)[0] + " domain final white list added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
482                                     }
483                                 } while (domains.contains("|"));
484
485                             } else {  // Standard domain white list entries with filters.
486                                 //noinspection StatementWithEmptyBody
487                                 if (domains.contains("~")) {  // It is uncertain what a `~` domain means inside an `@@` entry.
488                                     // Do Nothing
489
490                                     //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
491                                 } else {
492                                     // Process each domain.
493                                     do {
494                                         // Create a string to keep track of the current domain.
495                                         String domain;
496
497                                         if (domains.contains("|")) {  // There is more than one domain in the list.
498                                             // Get the first domain from the list.
499                                             domain = domains.substring(0, domains.indexOf("|"));
500
501                                             // Remove the first domain from the list.
502                                             domains = domains.substring(domains.indexOf("|") + 1);
503                                         } else {  // There is only one domain in the list.
504                                             domain = domains;
505                                         }
506
507                                         if (entry.contains("*")) {  // There are two or more entries.
508                                             // Get the index of the wildcard.
509                                             int wildcardIndex = entry.indexOf("*");
510
511                                             // Split the entry into components.
512                                             String firstEntry = entry.substring(0, wildcardIndex);
513                                             String secondEntry = entry.substring(wildcardIndex + 1);
514
515                                             if (secondEntry.contains("*")) {  // There are three or more entries.
516                                                 // Get the index of the wildcard.
517                                                 int secondWildcardIndex = secondEntry.indexOf("*");
518
519                                                 // Split the entry into components.
520                                                 String realSecondEntry = secondEntry.substring(0, secondWildcardIndex);
521                                                 String thirdEntry = secondEntry.substring(secondWildcardIndex + 1);
522
523                                                 if (thirdEntry.contains("*")) {  // Process a domain white list quadruple entry.
524                                                     // Get the index of the wildcard.
525                                                     int thirdWildcardIndex = thirdEntry.indexOf("*");
526
527                                                     // Split the entry into components.
528                                                     String realThirdEntry = thirdEntry.substring(0, thirdWildcardIndex);
529                                                     String fourthEntry = thirdEntry.substring(thirdWildcardIndex + 1);
530
531                                                     // Create an entry string array.
532                                                     String[] domainQuadrupleEntry = {domain, firstEntry, realSecondEntry, realThirdEntry, fourthEntry, originalBlocklistEntry};
533
534                                                     // Add the entry to the white list.
535                                                     domainWhitelist.add(domainQuadrupleEntry);
536
537                                                     //Log.i("Blocklists", headers.get(1)[0] + " domain white list added : " + domain + " , " + firstEntry + " , " + realSecondEntry + " , " +
538                                                     //        realThirdEntry + " , " + fourthEntry + "  -  " + originalBlocklistEntry);
539                                                 } else {  // Process a domain white list triple entry.
540                                                     // Create an entry string array.
541                                                     String[] domainTripleEntry = {domain, firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry};
542
543                                                     // Add the entry to the white list.
544                                                     domainWhitelist.add(domainTripleEntry);
545
546                                                     //Log.i("Blocklists", headers.get(1)[0] + " domain white list added : " + domain + " , " + firstEntry + " , " + realSecondEntry + " , " +
547                                                     //        thirdEntry + "  -  " + originalBlocklistEntry);
548                                                 }
549                                             } else {  // Process a domain white list double entry.
550                                                 // Create an entry string array.
551                                                 String[] domainDoubleEntry = {domain, firstEntry, secondEntry, originalBlocklistEntry};
552
553                                                 // Add the entry to the white list.
554                                                 domainWhitelist.add(domainDoubleEntry);
555
556                                                 //Log.i("Blocklists", headers.get(1)[0] + " domain white list added : " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " +
557                                                 //        originalBlocklistEntry);
558                                             }
559                                         } else {  // Process a domain white list single entry.
560                                             // Create an entry string array.
561                                             String[] domainEntry = {domain, entry, originalBlocklistEntry};
562
563                                             // Add the entry to the white list.
564                                             domainWhitelist.add(domainEntry);
565
566                                             //Log.i("Blocklists", headers.get(1)[0] + " domain white list added : " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
567                                         }
568                                     } while (domains.contains("|"));
569                                 }
570                             }
571                         }  // Ignore all other filter entries.
572                     } else if (blocklistEntry.endsWith("|")) {  // Final white list entries.
573                         // Remove the final `|` from the entry.
574                         String entry = blocklistEntry.substring(0, blocklistEntry.length() - 1);
575
576                         if (entry.contains("*")) {  // Process a final white list double entry
577                             // Get the index of the wildcard.
578                             int wildcardIndex = entry.indexOf("*");
579
580                             // split the entry into components.
581                             String firstEntry = entry.substring(0, wildcardIndex);
582                             String secondEntry = entry.substring(wildcardIndex + 1);
583
584                             // Create an entry string array.
585                             String[] doubleEntry = {firstEntry, secondEntry, originalBlocklistEntry};
586
587                             // Add the entry to the white list.
588                             finalWhitelist.add(doubleEntry);
589
590                             //Log.i("Blocklists", headers.get(1)[0] + " final white list added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
591                         } else {  // Process a final white list single entry.
592                             // Create an entry string array.
593                             String[] singleEntry = {entry, originalBlocklistEntry};
594
595                             // Add the entry to the white list.
596                             finalWhitelist.add(singleEntry);
597
598                             //Log.i("Blocklists", headers.get(1)[0] + " final white list added: " + entry + "  -  " + originalBlocklistEntry);
599                         }
600                     } else {  // Main white list entries.
601                         if (blocklistEntry.contains("*")) {  // There are two or more entries.
602                             // Get the index of the wildcard.
603                             int wildcardIndex = blocklistEntry.indexOf("*");
604
605                             // Split the entry into components.
606                             String firstEntry = blocklistEntry.substring(0, wildcardIndex);
607                             String secondEntry = blocklistEntry.substring(wildcardIndex + 1);
608
609                             if (secondEntry.contains("*")) {  // Process a main white list triple entry.
610                                 // Get the index of the wildcard.
611                                 int secondWildcardIndex = secondEntry.indexOf("*");
612
613                                 // Split the entry into components.
614                                 String realSecondEntry = secondEntry.substring(0, secondWildcardIndex);
615                                 String thirdEntry = secondEntry.substring(secondWildcardIndex + 1);
616
617                                 // Create an entry string array.
618                                 String[] tripleEntry = {firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry};
619
620                                 // Add the entry to the white list.
621                                 mainWhitelist.add(tripleEntry);
622
623                                 //Log.i("Blocklists", headers.get(1)[0] + " main white list added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + "  -  " + originalBlocklistEntry);
624                             } else {  // Process a main white list double entry.
625                                 // Create an entry string array.
626                                 String[] doubleEntry = {firstEntry, secondEntry, originalBlocklistEntry};
627
628                                 // Add the entry to the white list.
629                                 mainWhitelist.add(doubleEntry);
630
631                                 //Log.i("Blocklists", headers.get(1)[0] + " main white list added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
632                             }
633                         } else {  // Process a main white list single entry.
634                             // Create an entry string array.
635                             String[] singleEntry = {blocklistEntry, originalBlocklistEntry};
636
637                             // Add the entry to the white list.
638                             mainWhitelist.add(singleEntry);
639
640                             //Log.i("Blocklists", headers.get(1)[0] + " main white list added: " + blocklistEntry + "  -  " + originalBlocklistEntry);
641                         }
642                     }
643                 } else if (blocklistEntry.endsWith("|")) {  // Final black list entries.
644                     // Strip out the final "|"
645                     String entry = blocklistEntry.substring(0, blocklistEntry.length() - 1);
646
647                     // Strip out any initial `||`.  They are redundant in this case because the block list entry is being matched against the end of the URL.
648                     if (entry.startsWith("||")) {
649                         entry = entry.substring(2);
650                     }
651
652                     if (entry.contains("*")) {  // Process a final black list double entry.
653                         // Get the index of the wildcard.
654                         int wildcardIndex = entry.indexOf("*");
655
656                         // Split the entry into components.
657                         String firstEntry = entry.substring(0, wildcardIndex);
658                         String secondEntry = entry.substring(wildcardIndex + 1);
659
660                         // Create an entry string array.
661                         String[] doubleEntry = {firstEntry, secondEntry, originalBlocklistEntry};
662
663                         // Add the entry to the black list.
664                         finalBlacklist.add(doubleEntry);
665
666                         //Log.i("Blocklists", headers.get(1)[0] + " final black list added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
667                     } else {  // Process a final black list single entry.
668                         // create an entry string array.
669                         String[] singleEntry = {entry, originalBlocklistEntry};
670
671                         // Add the entry to the black list.
672                         finalBlacklist.add(singleEntry);
673
674                         //Log.i("Blocklists", headers.get(1)[0] + " final black list added: " + entry + "  -  " + originalBlocklistEntry);
675                     }
676                 } else if (blocklistEntry.contains("$")) {  // Entries with filter options.
677                     // Strip out any initial `||`.  These will be treated like any other entry.
678                     if (blocklistEntry.startsWith("||")) {
679                         blocklistEntry = blocklistEntry.substring(2);
680                     }
681
682                     if (blocklistEntry.contains("third-party")) {  // Third-party entries.
683                         //noinspection StatementWithEmptyBody
684                         if (blocklistEntry.contains("~third-party")) {  // Third-party filter white list entries.
685                             // Do not process these white list entries.  They are designed to combine with block filters that Privacy Browser doesn't use, like `subdocument` and `xmlhttprequest`.
686
687                             //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
688                         } else if (blocklistEntry.contains("domain=")) {  // Third-party domain entries.
689                             if (blocklistEntry.startsWith("|")) {  // Third-party domain initial entries.
690                                 // Strip the initial `|`.
691                                 blocklistEntry = blocklistEntry.substring(1);
692
693                                 // Parse the entry
694                                 String entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"));
695                                 String filters = blocklistEntry.substring(blocklistEntry.indexOf("$") + 1);
696                                 String domains = filters.substring(filters.indexOf("domain=") + 7);
697
698                                 //noinspection StatementWithEmptyBody
699                                 if (entry.equals("http:") || entry.equals("https:") || entry.equals("http://") || entry.equals("https://")) {  // Ignore generic entries.
700                                     // Do nothing.  These entries will almost entirely disable the website.
701                                     // Often the original entry blocks filter options like `$script`, which Privacy Browser does not differentiate.
702
703                                     //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
704                                 } else {  // Third-party domain initial entries.
705                                     // Process each domain.
706                                     do {
707                                         // Create a string to keep track of the current domain.
708                                         String domain;
709
710                                         if (domains.contains("|")) {  // There is more than one domain in the list.
711                                             // Get the first domain from the list.
712                                             domain = domains.substring(0, domains.indexOf("|"));
713
714                                             // Remove the first domain from the list.
715                                             domains = domains.substring(domains.indexOf("|") + 1);
716                                         } else {  // There is only one domain in the list.
717                                             domain = domains;
718                                         }
719
720                                         if (entry.contains("*")) {  // Three are two or more entries.
721                                             // Get the index of the wildcard.
722                                             int wildcardIndex = entry.indexOf("*");
723
724                                             // Split the entry into components.
725                                             String firstEntry = entry.substring(0, wildcardIndex);
726                                             String secondEntry = entry.substring(wildcardIndex + 1);
727
728                                             if (secondEntry.contains("*")) {  // Process a third-party domain initial black list triple entry.
729                                                 // Get the index of the wildcard.
730                                                 int secondWildcardIndex = secondEntry.indexOf("*");
731
732                                                 // Split the entry into components.
733                                                 String realSecondEntry = secondEntry.substring(0, secondWildcardIndex);
734                                                 String thirdEntry = secondEntry.substring(secondWildcardIndex + 1);
735
736                                                 // Create an entry string array.
737                                                 String[] tripleDomainEntry = {domain, firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry};
738
739                                                 // Add the entry to the black list.
740                                                 thirdPartyDomainInitialBlacklist.add(tripleDomainEntry);
741
742                                                 //Log.i("Blocklists", headers.get(1)[0] + " third-party domain initial black list added: " + domain + " , " + firstEntry + " , " + realSecondEntry +
743                                                 //        " , " + thirdEntry + "  -  " + originalBlocklistEntry);
744                                             } else {  // Process a third-party domain initial black list double entry.
745                                                 // Create an entry string array.
746                                                 String[] doubleDomainEntry = {domain, firstEntry, secondEntry, originalBlocklistEntry};
747
748                                                 // Add the entry to the black list.
749                                                 thirdPartyDomainInitialBlacklist.add(doubleDomainEntry);
750
751                                                 //Log.i("Blocklists", headers.get(1)[0] + " third-party domain initial black list added: " + domain + " , " + firstEntry + " , " + secondEntry +
752                                                 //        "  -  " + originalBlocklistEntry);
753                                             }
754                                         } else {  // Process a third-party domain initial black list single entry.
755                                             // Create an entry string array.
756                                             String[] singleEntry = {domain, entry, originalBlocklistEntry};
757
758                                             // Add the entry to the black list.
759                                             thirdPartyDomainInitialBlacklist.add(singleEntry);
760
761                                             //Log.i("Blocklists", headers.get(1)[0] + " third-party domain initial black list added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
762                                         }
763                                     } while (domains.contains("|"));
764                                 }
765                             } else if (blocklistEntry.contains("\\")) {  // Process a third-party domain black list regular expression.
766                                 // Parse the entry.  At least one regular expression in this entry contains `$`, so the parser uses `/$`.
767                                 String entry = blocklistEntry.substring(0, blocklistEntry.indexOf("/$") + 1);
768                                 String filters = blocklistEntry.substring(blocklistEntry.indexOf("/$") + 2);
769                                 String domains = filters.substring(filters.indexOf("domain=") + 7);
770
771                                 // Process each domain.
772                                 do {
773                                     // Create a string to keep track of the current domain.
774                                     String domain;
775
776                                     if (domains.contains("|")) {  // There is more than one domain in the list.
777                                         // Get the first domain from the list.
778                                         domain = domains.substring(0, domains.indexOf("|"));
779
780                                         // Remove the first domain from the list.
781                                         domains = domains.substring(domains.indexOf("|") + 1);
782                                     } else {  // There is only one domain in the list.
783                                         domain = domains;
784                                     }
785
786                                     // Create an entry string array.
787                                     String[] domainEntry = {domain, entry, originalBlocklistEntry};
788
789                                     // Add the entry to the black list.
790                                     thirdPartyDomainRegularExpressionBlacklist.add(domainEntry);
791
792                                     //Log.i("Blocklists", headers.get(1)[0] + " third-party domain regular expression black list added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
793                                 } while (domains.contains("|"));
794                             } else {  // Third-party domain entries.
795                                 // Parse the entry
796                                 String entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"));
797                                 String filters = blocklistEntry.substring(blocklistEntry.indexOf("$") + 1);
798                                 String domains = filters.substring(filters.indexOf("domain=") + 7);
799
800                                 // Strip any trailing "*" from the entry.
801                                 if (entry.endsWith("*")) {
802                                     entry = entry.substring(0, entry.length() - 1);
803                                 }
804
805                                 // Track if any third-party white list filters are applied.
806                                 boolean whitelistDomain = false;
807
808                                 // Process each domain.
809                                 do {
810                                     // Create a string to keep track of the current domain.
811                                     String domain;
812
813                                     if (domains.contains("|")) {  // There is more than one domain in the list.
814                                         // Get the first domain from the list.
815                                         domain = domains.substring(0, domains.indexOf("|"));
816
817                                         // Remove the first domain from the list.
818                                         domains = domains.substring(domains.indexOf("|") + 1);
819                                     } else {  // The is only one domain in the list.
820                                         domain = domains;
821                                     }
822
823                                     // Differentiate between block list domains and white list domains.
824                                     if (domain.startsWith("~")) {  // White list third-party domain entry.
825                                         // Strip the initial `~`.
826                                         domain = domain.substring(1);
827
828                                         // Set the white list domain flag.
829                                         whitelistDomain = true;
830
831                                         if (entry.contains("*")) {  // Process a third-party domain white list double entry.
832                                             // Get the index of the wildcard.
833                                             int wildcardIndex = entry.indexOf("*");
834
835                                             // Split the entry into components.
836                                             String firstEntry = entry.substring(0, wildcardIndex);
837                                             String secondEntry = entry.substring(wildcardIndex + 1);
838
839                                             // Create an entry string array.
840                                             String[] domainDoubleEntry = {domain, firstEntry, secondEntry, originalBlocklistEntry};
841
842                                             // Add the entry to the white list.
843                                             thirdPartyDomainWhitelist.add(domainDoubleEntry);
844
845                                             //Log.i("Blocklists", headers.get(1)[0] + " third-party domain white list added: " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " +
846                                             //        originalBlocklistEntry);
847                                         } else {  // Process a third-party domain white list single entry.
848                                             // Create an entry string array.
849                                             String[] domainEntry = {domain, entry, originalBlocklistEntry};
850
851                                             // Add the entry to the white list.
852                                             thirdPartyDomainWhitelist.add(domainEntry);
853
854                                             //Log.i("Blocklists", headers.get(1)[0] + " third-party domain white list added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
855                                         }
856                                     } else {  // Third-party domain black list entries.
857                                         if (entry.contains("*")) {  // Process a third-party domain black list double entry.
858                                             // Get the index of the wildcard.
859                                             int wildcardIndex = entry.indexOf("*");
860
861                                             // Split the entry into components.
862                                             String firstEntry = entry.substring(0, wildcardIndex);
863                                             String secondEntry = entry.substring(wildcardIndex + 1);
864
865                                             // Create an entry string array.
866                                             String[] domainDoubleEntry = {domain, firstEntry, secondEntry, originalBlocklistEntry};
867
868                                             // Add the entry to the black list
869                                             thirdPartyDomainBlacklist.add(domainDoubleEntry);
870
871                                             //Log.i("Blocklists", headers.get(1)[0] + " third-party domain black list added: " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " +
872                                             //        originalBlocklistEntry);
873                                         } else {  // Process a third-party domain black list single entry.
874                                             // Create an entry string array.
875                                             String[] domainEntry = {domain, entry, originalBlocklistEntry};
876
877                                             // Add the entry to the black list.
878                                             thirdPartyDomainBlacklist.add(domainEntry);
879
880                                             //Log.i("Blocklists", headers.get(1)[0] + " third-party domain block list added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
881                                         }
882                                     }
883                                 } while (domains.contains("|"));
884
885                                 // Add a third-party black list entry if a white list domain was processed.
886                                 if (whitelistDomain) {
887                                     if (entry.contains("*")) {  // Process a third-party black list double entry.
888                                         // Get the index of the wildcard.
889                                         int wildcardIndex = entry.indexOf("*");
890
891                                         // Split the entry into components.
892                                         String firstEntry = entry.substring(0, wildcardIndex);
893                                         String secondEntry = entry.substring(wildcardIndex + 1);
894
895                                         // Create an entry string array.
896                                         String[] doubleEntry = {firstEntry, secondEntry, originalBlocklistEntry};
897
898                                         // Add the entry to the black list.
899                                         thirdPartyBlacklist.add(doubleEntry);
900
901                                         //Log.i("Blocklists", headers.get(1)[0] + " third-party black list added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
902                                     } else {  // Process a third-party black list single entry.
903                                         // Create an entry string array.
904                                         String[] singleEntry = {entry, originalBlocklistEntry};
905
906                                         // Add an entry to the black list.
907                                         thirdPartyBlacklist.add(singleEntry);
908
909                                         //Log.i("Blocklists", headers.get(1)[0] + " third-party black list added: " + entry + "  -  " + originalBlocklistEntry);
910                                     }
911                                 }
912                             }
913                         } else if (blocklistEntry.startsWith("|")) {  // Third-party initial black list entries.
914                             // Strip the initial `|`.
915                             blocklistEntry = blocklistEntry.substring(1);
916
917                             // Get the entry.
918                             String entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"));
919
920                             if (entry.contains("*")) {  // Process a third-party initial black list double entry.
921                                 // Get the index of the wildcard.
922                                 int wildcardIndex = entry.indexOf("*");
923
924                                 // Split the entry into components.
925                                 String firstEntry = entry.substring(0, wildcardIndex);
926                                 String secondEntry = entry.substring(wildcardIndex + 1);
927
928                                 // Create an entry string array.
929                                 String[] thirdPartyDoubleEntry = {firstEntry, secondEntry, originalBlocklistEntry};
930
931                                 // Add the entry to the black list.
932                                 thirdPartyInitialBlacklist.add(thirdPartyDoubleEntry);
933
934                                 //Log.i("Blocklists", headers.get(1)[0] + " third-party initial black list added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
935                             } else {  // Process a third-party initial black list single entry.
936                                 // Create an entry string array.
937                                 String[] singleEntry = {entry, originalBlocklistEntry};
938
939                                 // Add the entry to the black list.
940                                 thirdPartyInitialBlacklist.add(singleEntry);
941
942                                 //Log.i("Blocklists", headers.get(1)[0] + " third-party initial black list added: " + entry + "  -  " + originalBlocklistEntry);
943                             }
944                         } else if (blocklistEntry.contains("\\")) {  // Process a regular expression black list entry.
945                             // Prepare a string to hold the entry.
946                             String entry;
947
948                             // Get the entry.
949                             if (blocklistEntry.contains("$/$")) {  // The first `$` is part of the regular expression.
950                                 entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$/$") + 2);
951                             } else {  // The only `$` indicates the filter options.
952                                 entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"));
953                             }
954
955                             // Create an entry string array.
956                             String[] singleEntry = {entry, originalBlocklistEntry};
957
958                             // Add the entry to the black list.
959                             thirdPartyRegularExpressionBlacklist.add(singleEntry);
960
961                             //Log.i("Blocklists", headers.get(1)[0] + " third-party regular expression black list added: " + entry + "  -  " + originalBlocklistEntry);
962                         } else if (blocklistEntry.contains("*")) {  // Third-party and regular expression black list entries.
963                             // Get the entry.
964                             String entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"));
965
966                             if (entry.endsWith("*")) {  // Process a third-party black list single entry.
967                                 // Strip the final `*`.
968                                 entry = entry.substring(0, entry.length() - 1);
969
970                                 // Create an entry string array.
971                                 String[] singleEntry = {entry, originalBlocklistEntry};
972
973                                 // Add the entry to the black list.
974                                 thirdPartyBlacklist.add(singleEntry);
975
976                                 //Log.i("Blocklists", headers.get(1)[0] + " third party black list added: " + entry + "  -  " + originalBlocklistEntry);
977                             } else {  // There are two or more entries.
978                                 // Get the index of the wildcard.
979                                 int wildcardIndex = entry.indexOf("*");
980
981                                 // Split the entry into components.
982                                 String firstEntry = entry.substring(0, wildcardIndex);
983                                 String secondEntry = entry.substring(wildcardIndex + 1);
984
985                                 if (secondEntry.contains("*")) {  // There are three or more entries.
986                                     // Get the index of the wildcard.
987                                     int secondWildcardIndex = secondEntry.indexOf("*");
988
989                                     // Split the entry into components.
990                                     String realSecondEntry = secondEntry.substring(0, secondWildcardIndex);
991                                     String thirdEntry = secondEntry.substring(secondWildcardIndex + 1);
992
993                                     if (thirdEntry.contains("*")) {  // Process a third-party black list quadruple entry.
994                                         // Get the index of the wildcard.
995                                         int thirdWildcardIndex = thirdEntry.indexOf("*");
996
997                                         // Split the entry into components.
998                                         String realThirdEntry = thirdEntry.substring(0, thirdWildcardIndex);
999                                         String fourthEntry = thirdEntry.substring(thirdWildcardIndex + 1);
1000
1001                                         // Create an entry string array.
1002                                         String[] quadrupleEntry = {firstEntry, realSecondEntry, realThirdEntry, fourthEntry, originalBlocklistEntry};
1003
1004                                         // Add the entry to the black list.
1005                                         thirdPartyBlacklist.add(quadrupleEntry);
1006
1007                                         //Log.i("Blocklists", headers.get(1)[0] + " third-party black list added: " + firstEntry + " , " + realSecondEntry + " , " + realThirdEntry + " , " +
1008                                         //        fourthEntry + "  -  " + originalBlocklistEntry);
1009                                     } else {  // Process a third-party black list triple entry.
1010                                         // Create an entry string array.
1011                                         String[] tripleEntry = {firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry};
1012
1013                                         // Add the entry to the black list.
1014                                         thirdPartyBlacklist.add(tripleEntry);
1015
1016                                         //Log.i("Blocklists", headers.get(1)[0] + " third-party black list added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + "  -  " +
1017                                         //        originalBlocklistEntry);
1018                                     }
1019                                 } else {  // Process a third-party black list double entry.
1020                                     // Create an entry string array.
1021                                     String[] doubleEntry = {firstEntry, secondEntry, originalBlocklistEntry};
1022
1023                                     // Add the entry to the black list.
1024                                     thirdPartyBlacklist.add(doubleEntry);
1025
1026                                     //Log.i("Blocklists", headers.get(1)[0] + " third-party black list added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1027                                 }
1028                             }
1029                         } else {  // Process a third party black list single entry.
1030                             // Get the entry.
1031                             String entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"));
1032
1033                             // Create an entry string array.
1034                             String[] singleEntry = {entry, originalBlocklistEntry};
1035
1036                             // Add the entry to the black list.
1037                             thirdPartyBlacklist.add(singleEntry);
1038
1039                             //Log.i("Blocklists", headers.get(1)[0] + " third party black list added: " + entry + "  -  " + originalBlocklistEntry);
1040                         }
1041                     } else if (blocklistEntry.substring(blocklistEntry.indexOf("$")).contains("domain=")) {  // Domain entries.
1042                         if (blocklistEntry.contains("~")) {  // Domain white list entries.
1043                             // Separate the filters.
1044                             String entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"));
1045                             String filters = blocklistEntry.substring(blocklistEntry.indexOf("$") + 1);
1046                             String domains = filters.substring(filters.indexOf("domain=") + 7);
1047
1048                             // Strip any final `*` from the entry.  They are redundant.
1049                             if (entry.endsWith("*")) {
1050                                 entry = entry.substring(0, entry.length() - 1);
1051                             }
1052
1053                             // Process each domain.
1054                             do {
1055                                 // Create a string to keep track of the current domain.
1056                                 String domain;
1057
1058                                 if (domains.contains("|")) {  // There is more than one domain in the list.
1059                                     // Get the first domain from the list.
1060                                     domain = domains.substring(0, domains.indexOf("|"));
1061
1062                                     // Remove the first domain from the list.
1063                                     domains = domains.substring(domains.indexOf("|") + 1);
1064                                 } else {  // There is only one domain in the list.
1065                                     domain = domains;
1066                                 }
1067
1068                                 // Strip the initial `~`.
1069                                 domain = domain.substring(1);
1070
1071                                 if (entry.contains("*")) {  // There are two or more entries.
1072                                     // Get the index of the wildcard.
1073                                     int wildcardIndex = entry.indexOf("*");
1074
1075                                     // Split the entry into components.
1076                                     String firstEntry = entry.substring(0, wildcardIndex);
1077                                     String secondEntry = entry.substring(wildcardIndex + 1);
1078
1079                                     if (secondEntry.contains("*")) {  // Process a domain white list triple entry.
1080                                         // Get the index of the wildcard.
1081                                         int secondWildcardIndex = secondEntry.indexOf("*");
1082
1083                                         // Split the entry into components.
1084                                         String realSecondEntry = secondEntry.substring(0, secondWildcardIndex);
1085                                         String thirdEntry = secondEntry.substring((secondWildcardIndex + 1));
1086
1087                                         // Create an entry string array.
1088                                         String[] domainTripleEntry = {domain, firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry};
1089
1090                                         // Add the entry to the white list.
1091                                         domainWhitelist.add(domainTripleEntry);
1092
1093                                         //Log.i("Blocklists", headers.get(1)[0] + " domain white list added: " + domain + " , " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry +
1094                                         //        "  -  " + originalBlocklistEntry);
1095                                     } else {  // Process a domain white list double entry.
1096                                         // Create an entry string array.
1097                                         String[] domainDoubleEntry = {domain, firstEntry, secondEntry, originalBlocklistEntry};
1098
1099                                         // Add the entry to the white list.
1100                                         domainWhitelist.add(domainDoubleEntry);
1101
1102                                         //Log.i("Blocklists", headers.get(1)[0] + " domain white list added: " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1103                                     }
1104                                 } else {  // Process a domain white list single entry.
1105                                     // Create an entry string array.
1106                                     String[] domainEntry = {domain, entry, originalBlocklistEntry};
1107
1108                                     // Add the entry to the white list.
1109                                     domainWhitelist.add(domainEntry);
1110
1111                                     //Log.i("Blocklists", headers.get(1)[0] + " domain white list added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
1112                                 }
1113                             } while (domains.contains("|"));
1114                         } else {  // Domain black list entries.
1115                             // Separate the filters.
1116                             String entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"));
1117                             String filters = blocklistEntry.substring(blocklistEntry.indexOf("$") + 1);
1118                             String domains = filters.substring(filters.indexOf("domain=") + 7);
1119
1120                             // Only process the item if the entry is not null.  For example, some lines begin with `$websocket`, which create a null entry.
1121                             if (!entry.equals("")) {
1122                                 // Process each domain.
1123                                 do {
1124                                     // Create a string to keep track of the current domain.
1125                                     String domain;
1126
1127                                     if (domains.contains("|")) {  // There is more than one domain in the list.
1128                                         // Get the first domain from the list.
1129                                         domain = domains.substring(0, domains.indexOf("|"));
1130
1131                                         // Remove the first domain from the list.
1132                                         domains = domains.substring(domains.indexOf("|") + 1);
1133                                     } else {  // There is only one domain in the list.
1134                                         domain = domains;
1135                                     }
1136
1137                                     if (entry.startsWith("|")) {  // Domain initial black list entries.
1138                                         // Remove the initial `|`;
1139                                         String entryBase = entry.substring(1);
1140
1141                                         //noinspection StatementWithEmptyBody
1142                                         if (entryBase.equals("http://") || entryBase.equals("https://")) {
1143                                             // Do nothing.  These entries will entirely block the website.
1144                                             // Often the original entry blocks `$script` but Privacy Browser does not currently differentiate between scripts and other entries.
1145
1146                                             //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
1147                                         } else {  // Process a domain initial black list entry
1148                                             // Create an entry string array.
1149                                             String[] domainEntry = {domain, entryBase, originalBlocklistEntry};
1150
1151                                             // Add the entry to the black list.
1152                                             domainInitialBlacklist.add(domainEntry);
1153
1154                                             //Log.i("Blocklists", headers.get(1)[0] + " domain initial black list added: " + domain + " , " + entryBase + "  -  " + originalBlocklistEntry);
1155                                         }
1156                                     } else if (entry.endsWith("|")) {  // Domain final black list entries.
1157                                         // Remove the final `|`.
1158                                         String entryBase = entry.substring(0, entry.length() - 1);
1159
1160                                         if (entryBase.contains("*")) {  // Process a domain final black list double entry.
1161                                             // Get the index of the wildcard.
1162                                             int wildcardIndex = entry.indexOf("*");
1163
1164                                             // Split the entry into components.
1165                                             String firstEntry = entryBase.substring(0, wildcardIndex);
1166                                             String secondEntry = entryBase.substring(wildcardIndex + 1);
1167
1168                                             // Create an entry string array.
1169                                             String[] domainDoubleEntry = {domain, firstEntry, secondEntry, originalBlocklistEntry};
1170
1171                                             // Add the entry to the black list.
1172                                             domainFinalBlacklist.add(domainDoubleEntry);
1173
1174                                             //Log.i("Blocklists", headers.get(1)[0] + " domain final black list added: " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " +
1175                                             //        originalBlocklistEntry);
1176                                         } else {  // Process a domain final black list single entry.
1177                                             // Create an entry string array.
1178                                             String[] domainEntry = {domain, entryBase, originalBlocklistEntry};
1179
1180                                             // Add the entry to the black list.
1181                                             domainFinalBlacklist.add(domainEntry);
1182
1183                                             //Log.i("Blocklists", headers.get(1)[0] + " domain final black list added: " + domain + " , " + entryBase + "  -  " + originalBlocklistEntry);
1184                                         }
1185                                     } else if (entry.contains("\\")) {  // Process a domain regular expression black list entry.
1186                                         // Create an entry string array.
1187                                         String[] domainEntry = {domain, entry, originalBlocklistEntry};
1188
1189                                         // Add the entry to the black list.
1190                                         domainRegularExpressionBlacklist.add(domainEntry);
1191
1192                                         //Log.i("Blocklists", headers.get(1)[0] + " domain regular expression black list added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
1193                                     } else if (entry.contains("*")) {  // There are two or more entries.
1194                                         // Get the index of the wildcard.
1195                                         int wildcardIndex = entry.indexOf("*");
1196
1197                                         // Split the entry into components.
1198                                         String firstEntry = entry.substring(0, wildcardIndex);
1199                                         String secondEntry = entry.substring(wildcardIndex + 1);
1200
1201                                         if (secondEntry.contains("*")) {  // Process a domain black list triple entry.
1202                                             // Get the index of the wildcard.
1203                                             int secondWildcardIndex = secondEntry.indexOf("*");
1204
1205                                             // Split the entry into components.
1206                                             String realSecondEntry = secondEntry.substring(0, secondWildcardIndex);
1207                                             String thirdEntry = secondEntry.substring(secondWildcardIndex + 1);
1208
1209                                             // Create an entry string array.
1210                                             String[] domainTripleEntry = {domain, firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry};
1211
1212                                             // Add the entry to the black list.
1213                                             domainBlacklist.add(domainTripleEntry);
1214
1215                                             //Log.i("Blocklists", headers.get(1)[0] + " domain black list added: " + domain + " , " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry +
1216                                             //        "  -  " + originalBlocklistEntry);
1217                                         } else {  // Process a domain black list double entry.
1218                                             // Create an entry string array.
1219                                             String[] domainDoubleEntry = {domain, firstEntry, secondEntry, originalBlocklistEntry};
1220
1221                                             // Add the entry to the black list.
1222                                             domainBlacklist.add(domainDoubleEntry);
1223
1224                                             //Log.i("Blocklists", headers.get(1)[0] + " domain black list added: " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " +
1225                                             //        originalBlocklistEntry);
1226                                         }
1227                                     } else {  // Process a domain black list single entry.
1228                                         // Create an entry string array.
1229                                         String[] domainEntry = {domain, entry, originalBlocklistEntry};
1230
1231                                         // Add the entry to the black list.
1232                                         domainBlacklist.add(domainEntry);
1233
1234                                         //Log.i("Blocklists", headers.get(1)[0] + " domain black list added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
1235                                     }
1236                                 } while (domains.contains("|"));
1237                             }
1238                         }
1239                     } else if (blocklistEntry.contains("~")) {  // White list entries.  Privacy Browser does not differentiate against these filter options, so they are just generally white listed.
1240                         // Remove the filter options.
1241                         blocklistEntry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"));
1242
1243                         // Strip any trailing `*`.
1244                         if (blocklistEntry.endsWith("*")) {
1245                             blocklistEntry = blocklistEntry.substring(0, blocklistEntry.length() - 1);
1246                         }
1247
1248                         if (blocklistEntry.contains("*")) {  // Process a white list double entry.
1249                             // Get the index of the wildcard.
1250                             int wildcardIndex = blocklistEntry.indexOf("*");
1251
1252                             // Split the entry into components.
1253                             String firstEntry = blocklistEntry.substring(0, wildcardIndex);
1254                             String secondEntry = blocklistEntry.substring(wildcardIndex + 1);
1255
1256                             // Create an entry string array.
1257                             String[] doubleEntry = {firstEntry, secondEntry, originalBlocklistEntry};
1258
1259                             // Add the entry to the white list.
1260                             mainWhitelist.add(doubleEntry);
1261
1262                             //Log.i("Blocklists", headers.get(1)[0] + " main white list added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1263                         } else {  // Process a white list single entry.
1264                             // Create an entry string array.
1265                             String[] singleEntry = {blocklistEntry, originalBlocklistEntry};
1266
1267                             // Add the entry to the white list.
1268                             mainWhitelist.add(singleEntry);
1269
1270                             //Log.i("Blocklists", headers.get(1)[0] + " main white list added: " + blocklistEntry + "  -  + " + originalBlocklistEntry);
1271                         }
1272                     } else if (blocklistEntry.contains("\\")) {  // Process a regular expression black list entry.
1273                         // Remove the filter options.
1274                         blocklistEntry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"));
1275
1276                         // Create an entry string array.
1277                         String[] singleEntry = {blocklistEntry, originalBlocklistEntry};
1278
1279                         // Add the entry to the black list.
1280                         regularExpressionBlacklist.add(singleEntry);
1281
1282                         //Log.i("Blocklists", headers.get(1)[0] + " regular expression black list added: " + blocklistEntry + "  -  " + originalBlocklistEntry);
1283                     } else {  // Black list entries.
1284                         // Remove the filter options.
1285                         if (!blocklistEntry.contains("$file")) {  // EasyPrivacy contains an entry with `$file` that does not have filter options.
1286                             blocklistEntry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"));
1287                         }
1288
1289                         // Strip any trailing `*`.  These are redundant.
1290                         if (blocklistEntry.endsWith("*")) {
1291                             blocklistEntry = blocklistEntry.substring(0, blocklistEntry.length() - 1);
1292                         }
1293
1294                         if (blocklistEntry.startsWith("|")) {  // Initial black list entries.
1295                             // Strip the initial `|`.
1296                             String entry = blocklistEntry.substring(1);
1297
1298                             if (entry.contains("*")) {  // Process an initial black list double entry.
1299                                 // Get the index of the wildcard.
1300                                 int wildcardIndex = entry.indexOf("*");
1301
1302                                 // Split the entry into components.
1303                                 String firstEntry = entry.substring(0, wildcardIndex);
1304                                 String secondEntry = entry.substring(wildcardIndex + 1);
1305
1306                                 // Create an entry string array.
1307                                 String[] doubleEntry = {firstEntry, secondEntry, originalBlocklistEntry};
1308
1309                                 // Add the entry to the black list.
1310                                 initialBlacklist.add(doubleEntry);
1311
1312                                 //Log.i("Blocklists", headers.get(1)[0] + " initial black list added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1313                             } else {  // Process an initial black list single entry.
1314                                 // Create an entry string array.
1315                                 String[] singleEntry = {entry, originalBlocklistEntry};
1316
1317                                 // Add the entry to the black list.
1318                                 initialBlacklist.add(singleEntry);
1319
1320                                 //Log.i("Blocklists", headers.get(1)[0] + " initial black list added: " + entry + "  -  " + originalBlocklistEntry);
1321                             }
1322                         } else if (blocklistEntry.endsWith("|")) {  // Final black list entries.
1323                             // Ignore entries with `object` filters.  They can block entire websites and don't have any meaning in the context of Privacy Browser.
1324                             if (!originalBlocklistEntry.contains("$object")) {
1325                                 // Strip the final `|`.
1326                                 String entry = blocklistEntry.substring(0, blocklistEntry.length() - 1);
1327
1328                                 if (entry.contains("*")) {  // There are two or more entries.
1329                                     // Get the index of the wildcard.
1330                                     int wildcardIndex = entry.indexOf("*");
1331
1332                                     // Split the entry into components.
1333                                     String firstEntry = entry.substring(0, wildcardIndex);
1334                                     String secondEntry = entry.substring(wildcardIndex + 1);
1335
1336                                     if (secondEntry.contains("*")) {  // Process a final black list triple entry.
1337                                         // Get the index of the wildcard.
1338                                         int secondWildcardIndex = secondEntry.indexOf("*");
1339
1340                                         // Split the entry into components.
1341                                         String realSecondEntry = secondEntry.substring(0, secondWildcardIndex);
1342                                         String thirdEntry = secondEntry.substring(secondWildcardIndex + 1);
1343
1344                                         // Create an entry string array.
1345                                         String[] tripleEntry = {firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry};
1346
1347                                         // Add the entry to the black list.
1348                                         finalBlacklist.add(tripleEntry);
1349
1350                                         //Log.i("Blocklists", headers.get(1)[0] + " final black list added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + "  -  " +
1351                                         //        originalBlocklistEntry);
1352                                     } else {  // Process a final black list double entry.
1353                                         // Create an entry string array.
1354                                         String[] doubleEntry = {firstEntry, secondEntry, originalBlocklistEntry};
1355
1356                                         // Add the entry to the black list.
1357                                         finalBlacklist.add(doubleEntry);
1358
1359                                         //Log.i("Blocklists", headers.get(1)[0] + " final black list added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1360                                     }
1361                                 } else {  // Process a final black list single entry.
1362                                     // Create an entry sting array.
1363                                     String[] singleEntry = {entry, originalBlocklistEntry};
1364
1365                                     // Add the entry to the black list.
1366                                     finalBlacklist.add(singleEntry);
1367
1368                                     //Log.i("Blocklists", headers.get(1)[0] + " final black list added: " + entry + "  -  " + originalBlocklistEntry);
1369                                 }
1370                             }
1371                         } else if (blocklistEntry.contains("*")) {  // There are two or more entries.
1372                             // Get the index of the wildcard.
1373                             int wildcardIndex = blocklistEntry.indexOf("*");
1374
1375                             // Split the entry into components.
1376                             String firstEntry = blocklistEntry.substring(0, wildcardIndex);
1377                             String secondEntry = blocklistEntry.substring(wildcardIndex + 1);
1378
1379                             if (secondEntry.contains("*")) {  // Process a main black list triple entry.
1380                                 // Get the index of the wildcard.
1381                                 int secondWildcardIndex = secondEntry.indexOf("*");
1382
1383                                 // Split the entry into components.
1384                                 String realSecondEntry = secondEntry.substring(0, secondWildcardIndex);
1385                                 String thirdEntry = secondEntry.substring(secondWildcardIndex + 1);
1386
1387                                 // Create an entry string array.
1388                                 String[] tripleEntry = {firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry};
1389
1390                                 // Add the entry to the black list.
1391                                 mainBlacklist.add(tripleEntry);
1392
1393                                 //Log.i("Blocklists", headers.get(1)[0] + " main black list added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + "  -  " + originalBlocklistEntry);
1394                             } else {  // Process a main black list double entry.
1395                                 // Create an entry string array.
1396                                 String[] doubleEntry = {firstEntry, secondEntry, originalBlocklistEntry};
1397
1398                                 // Add the entry to the black list.
1399                                 mainBlacklist.add(doubleEntry);
1400
1401                                 //Log.i("Blocklists", headers.get(1)[0] + " main black list added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1402                             }
1403                         } else {  // Process a main black list single entry.
1404                             // Create an entry string array.
1405                             String[] singleEntry = {blocklistEntry, originalBlocklistEntry};
1406
1407                             // Add the entry to the black list.
1408                             mainBlacklist.add(singleEntry);
1409
1410                             //Log.i("Blocklists", headers.get(1)[0] + " main black list added: " + blocklistEntry + "  -  " + originalBlocklistEntry);
1411                         }
1412                     }
1413                 } else {  // Main black list entries
1414                     // Strip out any initial `||`.  These will be treated like any other entry.
1415                     if (blocklistEntry.startsWith("||")) {
1416                         blocklistEntry = blocklistEntry.substring(2);
1417                     }
1418
1419                     // Strip out any initial `*`.
1420                     if (blocklistEntry.startsWith("*")) {
1421                         blocklistEntry = blocklistEntry.substring(1);
1422                     }
1423
1424                     // Strip out any trailing `*`.
1425                     if (blocklistEntry.endsWith("*")) {
1426                         blocklistEntry = blocklistEntry.substring(0, blocklistEntry.length() - 1);
1427                     }
1428
1429                     if (blocklistEntry.startsWith("|")) {  // Initial black list entries.
1430                         // Strip the initial `|`.
1431                         String entry = blocklistEntry.substring(1);
1432
1433                         if (entry.contains("*")) {  // Process an initial black list double entry.
1434                             // Get the index of the wildcard.
1435                             int wildcardIndex = entry.indexOf("*");
1436
1437                             // Split the entry into components.
1438                             String firstEntry = entry.substring(0, wildcardIndex);
1439                             String secondEntry = entry.substring(wildcardIndex + 1);
1440
1441                             // Create an entry string array.
1442                             String[] doubleEntry = {firstEntry, secondEntry, originalBlocklistEntry};
1443
1444                             // Add the entry to the black list.
1445                             initialBlacklist.add(doubleEntry);
1446
1447                             //Log.i("Blocklists", headers.get(1)[0] + " initial black list added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1448                         } else {  // Process an initial black list single entry.
1449                             // Create an entry string array.
1450                             String[] singleEntry = {entry, originalBlocklistEntry};
1451
1452                             // Add the entry to the black list.
1453                             initialBlacklist.add(singleEntry);
1454
1455                             //Log.i("Blocklists", headers.get(1)[0] + " initial black list added: " + entry + "  -  " + originalBlocklistEntry);
1456                         }
1457                     } else if (blocklistEntry.endsWith("|")) {  // Final black list entries.
1458                         // Strip the final `|`.
1459                         String entry = blocklistEntry.substring(0, blocklistEntry.length() - 1);
1460
1461                         if (entry.contains("*")) {  // There are two or more entries.
1462                             // Get the index of the wildcard.
1463                             int wildcardIndex = entry.indexOf("*");
1464
1465                             // Split the entry into components.
1466                             String firstEntry = entry.substring(0, wildcardIndex);
1467                             String secondEntry = entry.substring(wildcardIndex + 1);
1468
1469                             if (secondEntry.contains("*")) {  // Process a final black list triple entry.
1470                                 // Get the index of the wildcard.
1471                                 int secondWildcardIndex = secondEntry.indexOf("*");
1472
1473                                 // Split the entry into components.
1474                                 String realSecondEntry = secondEntry.substring(0, secondWildcardIndex);
1475                                 String thirdEntry = secondEntry.substring(secondWildcardIndex + 1);
1476
1477                                 // Create an entry string array.
1478                                 String[] tripleEntry = {firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry};
1479
1480                                 // Add the entry to the black list.
1481                                 finalBlacklist.add(tripleEntry);
1482
1483                                 //Log.i("Blocklists", headers.get(1)[0] + " final black list added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + "  -  " +
1484                                 //        originalBlocklistEntry);
1485                             } else {  // Process a final black list double entry.
1486                                 // Create an entry string array.
1487                                 String[] doubleEntry = {firstEntry, secondEntry, originalBlocklistEntry};
1488
1489                                 // Add the entry to the black list.
1490                                 finalBlacklist.add(doubleEntry);
1491
1492                                 //Log.i("Blocklists", headers.get(1)[0] + " final black list added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1493                             }
1494                         } else {  // Process a final black list single entry.
1495                             // Create an entry string array.
1496                             String[] singleEntry = {entry, originalBlocklistEntry};
1497
1498                             // Add the entry to the black list.
1499                             finalBlacklist.add(singleEntry);
1500
1501                             //Log.i("Blocklists", headers.get(1)[0] + " final black list added: " + entry + "  -  " + originalBlocklistEntry);
1502                         }
1503                     } else {  // Main black list entries.
1504                         if (blocklistEntry.contains("*")) {  // There are two or more entries.
1505                             // Get the index of the wildcard.
1506                             int wildcardIndex = blocklistEntry.indexOf("*");
1507
1508                             // Split the entry into components.
1509                             String firstEntry = blocklistEntry.substring(0, wildcardIndex);
1510                             String secondEntry = blocklistEntry.substring(wildcardIndex + 1);
1511
1512                             if (secondEntry.contains("*")) {  // There are three or more entries.
1513                                 // Get the index of the wildcard.
1514                                 int secondWildcardIndex = secondEntry.indexOf("*");
1515
1516                                 // Split the entry into components.
1517                                 String realSecondEntry = secondEntry.substring(0, secondWildcardIndex);
1518                                 String thirdEntry = secondEntry.substring(secondWildcardIndex + 1);
1519
1520                                 if (thirdEntry.contains("*")) {  // There are four or more entries.
1521                                     // Get the index of the wildcard.
1522                                     int thirdWildcardIndex = thirdEntry.indexOf("*");
1523
1524                                     // Split the entry into components.
1525                                     String realThirdEntry = thirdEntry.substring(0, thirdWildcardIndex);
1526                                     String fourthEntry = thirdEntry.substring(thirdWildcardIndex + 1);
1527
1528                                     if (fourthEntry.contains("*")) {  // Process a main black list quintuple entry.
1529                                         // Get the index of the wildcard.
1530                                         int fourthWildcardIndex = fourthEntry.indexOf("*");
1531
1532                                         // Split the entry into components.
1533                                         String realFourthEntry = fourthEntry.substring(0, fourthWildcardIndex);
1534                                         String fifthEntry = fourthEntry.substring(fourthWildcardIndex + 1);
1535
1536                                         // Create an entry string array.
1537                                         String[] quintupleEntry = {firstEntry, realSecondEntry, realThirdEntry, realFourthEntry, fifthEntry, originalBlocklistEntry};
1538
1539                                         // Add the entry to the black list.
1540                                         mainBlacklist.add(quintupleEntry);
1541
1542                                         //Log.i("Blocklists", headers.get(1)[0] + " main black list added: " + firstEntry + " , " + realSecondEntry + " , " + realThirdEntry + " , " +
1543                                         //        realFourthEntry + " , " + fifthEntry + "  -  " + originalBlocklistEntry);
1544                                     } else {  // Process a main black list quadruple entry.
1545                                         // Create an entry string array.
1546                                         String[] quadrupleEntry = {firstEntry, realSecondEntry, realThirdEntry, fourthEntry, originalBlocklistEntry};
1547
1548                                         // Add the entry to the black list.
1549                                         mainBlacklist.add(quadrupleEntry);
1550
1551                                         //Log.i("Blocklists", headers.get(1)[0] + " main black list added: " + firstEntry + " , " + realSecondEntry + " , " + realThirdEntry + " , " +
1552                                         //        fourthEntry + "  -  " + originalBlocklistEntry);
1553                                     }
1554                                 } else {  // Process a main black list triple entry.
1555                                     // Create an entry string array.
1556                                     String[] tripleEntry = {firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry};
1557
1558                                     // Add the entry to the black list.
1559                                     mainBlacklist.add(tripleEntry);
1560
1561                                     //Log.i("Blocklists", headers.get(1)[0] + " main black list added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + "  -  " + originalBlocklistEntry);
1562                                 }
1563                             } else {  // Process a main black list double entry.
1564                                 // Create an entry string array.
1565                                 String[] doubleEntry = {firstEntry, secondEntry, originalBlocklistEntry};
1566
1567                                 // Add the entry to the black list.
1568                                 mainBlacklist.add(doubleEntry);
1569
1570                                 //Log.i("Blocklists", headers.get(1)[0] + " main black list added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1571                             }
1572                         } else {  // Process a main black list single entry.
1573                             // Create an entry string array.
1574                             String[] singleEntry = {blocklistEntry, originalBlocklistEntry};
1575
1576                             // Add the entry to the black list.
1577                             mainBlacklist.add(singleEntry);
1578
1579                             //Log.i("Blocklists", headers.get(1)[0] + " main black list added: " + blocklistEntry + "  -  " + originalBlocklistEntry);
1580                         }
1581                     }
1582                 }
1583             }
1584             // Close `bufferedReader`.
1585             bufferedReader.close();
1586         } catch (IOException e) {
1587             // The asset exists, so the `IOException` will never be thrown.
1588         }
1589
1590         // Initialize the combined list.
1591         ArrayList<List<String[]>> combinedLists = new ArrayList<>();
1592
1593         // Add the headers (0).
1594         combinedLists.add(headers);  // 0.
1595
1596         // Add the white lists (1-8).
1597         combinedLists.add(mainWhitelist);  // 1.
1598         combinedLists.add(finalWhitelist);  // 2.
1599         combinedLists.add(domainWhitelist);  // 3.
1600         combinedLists.add(domainInitialWhitelist);  // 4.
1601         combinedLists.add(domainFinalWhitelist); // 5.
1602         combinedLists.add(thirdPartyWhitelist);  // 6.
1603         combinedLists.add(thirdPartyDomainWhitelist);  // 7.
1604         combinedLists.add(thirdPartyDomainInitialWhitelist);  // 8.
1605
1606         // Add the black lists (9-22).
1607         combinedLists.add(mainBlacklist);  // 9.
1608         combinedLists.add(initialBlacklist);  // 10.
1609         combinedLists.add(finalBlacklist);  // 11.
1610         combinedLists.add(domainBlacklist);  //  12.
1611         combinedLists.add(domainInitialBlacklist);  // 13.
1612         combinedLists.add(domainFinalBlacklist);  // 14.
1613         combinedLists.add(domainRegularExpressionBlacklist);  // 15.
1614         combinedLists.add(thirdPartyBlacklist);  // 16.
1615         combinedLists.add(thirdPartyInitialBlacklist);  // 17.
1616         combinedLists.add(thirdPartyDomainBlacklist);  // 18.
1617         combinedLists.add(thirdPartyDomainInitialBlacklist);  // 19.
1618         combinedLists.add(thirdPartyRegularExpressionBlacklist);  // 20.
1619         combinedLists.add(thirdPartyDomainRegularExpressionBlacklist);  // 21.
1620         combinedLists.add(regularExpressionBlacklist);  // 22.
1621
1622         return combinedLists;
1623     }
1624
1625     public String[] checkBlocklist(String currentDomain, String resourceUrl, boolean isThirdPartyRequest, ArrayList<List<String[]>> blocklist) {
1626         // Get the blocklist name.
1627         String BLOCK_LIST_NAME_STRING = blocklist.get(0).get(1)[0];
1628
1629         // Assert that currentDomain != null only if this is a third party request.  Apparently, lint can't tell that this isn't redundant.
1630         //noinspection RedundantIfStatement
1631         if (isThirdPartyRequest) {
1632             assert currentDomain != null;
1633         }
1634
1635         // Process the white lists.
1636         // Main white list.
1637         for (String[] whitelistEntry : blocklist.get(Integer.valueOf(MAIN_WHITELIST))) {
1638             switch (whitelistEntry.length) {
1639                 case 2:  // There is one entry.
1640                     if (resourceUrl.contains(whitelistEntry[0])) {
1641                         // Return a whitelist match request allowed.
1642                         return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, MAIN_WHITELIST, whitelistEntry[0], whitelistEntry[1]};
1643                     }
1644                     break;
1645
1646                 case 3:  // There are two entries.
1647                     if (resourceUrl.contains(whitelistEntry[0]) && resourceUrl.contains(whitelistEntry[1])) {
1648                         // Return a whitelist match request allowed.
1649                         return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, MAIN_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1], whitelistEntry[2]};
1650                     }
1651                     break;
1652
1653                 case 4:  // There are three entries.
1654                     if (resourceUrl.contains(whitelistEntry[0]) && resourceUrl.contains(whitelistEntry[1]) && resourceUrl.contains(whitelistEntry[2])) {
1655                         // Return a whitelist match request allowed.
1656                         return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, MAIN_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1] + "\n" + whitelistEntry[2], whitelistEntry[3]};
1657                     }
1658                     break;
1659             }
1660         }
1661
1662         // Final white list.
1663         for (String[] whitelistEntry : blocklist.get(Integer.valueOf(FINAL_WHITELIST))) {
1664             if (whitelistEntry.length == 2) {  // There is one entry.
1665                 if (resourceUrl.contains(whitelistEntry[0])) {
1666                     // Return a whitelist match request allowed.
1667                     return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, FINAL_WHITELIST, whitelistEntry[0], whitelistEntry[1]};
1668                 }
1669             } else {  // There are two entries.
1670                 if (resourceUrl.contains(whitelistEntry[0]) && resourceUrl.contains(whitelistEntry[1])) {
1671                     // Return a whitelist match request allowed.
1672                     return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, FINAL_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1], whitelistEntry[2]};
1673                 }
1674             }
1675         }
1676
1677         // Only check the domain lists if the current domain is not null (like `about:blank`).
1678         if (currentDomain != null) {
1679             // Domain white list.
1680             for (String[] whitelistEntry : blocklist.get(Integer.valueOf(DOMAIN_WHITELIST))) {
1681                 switch (whitelistEntry.length) {
1682                     case 3:  // There is one entry.
1683                         if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.contains(whitelistEntry[1])) {
1684                             // Return a whitelist match request allowed.
1685                             return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1], whitelistEntry[2]};
1686                         }
1687                         break;
1688
1689                     case 4:  // There are two entries.
1690                         if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.contains(whitelistEntry[1]) && resourceUrl.contains(whitelistEntry[2])) {
1691                             // Return a whitelist match request allowed.
1692                             return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1] + "\n" + whitelistEntry[2],
1693                                     whitelistEntry[3]};
1694                         }
1695                         break;
1696
1697                     case 5:  // There are three entries.
1698                         if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.contains(whitelistEntry[1]) && resourceUrl.contains(whitelistEntry[2]) && resourceUrl.contains(whitelistEntry[3])) {
1699                             // Return a whitelist match request allowed.
1700                             return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1] + "\n" + whitelistEntry[2] + "\n" +
1701                                     whitelistEntry[3], whitelistEntry[4]};
1702                         }
1703                         break;
1704
1705                     case 6:  // There are four entries.
1706                         if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.contains(whitelistEntry[1]) && resourceUrl.contains(whitelistEntry[2]) && resourceUrl.contains(whitelistEntry[3]) &&
1707                                 resourceUrl.contains(whitelistEntry[4])) {
1708                             // Return a whitelist match request allowed.
1709                             return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1] + "\n" + whitelistEntry[2] + "\n" +
1710                                     whitelistEntry[3] + "\n" + whitelistEntry[4], whitelistEntry[5]};
1711                         }
1712                         break;
1713                 }
1714             }
1715
1716             // Domain initial white list.
1717             for (String[] whitelistEntry : blocklist.get(Integer.valueOf(DOMAIN_INITIAL_WHITELIST))) {
1718                 switch (whitelistEntry.length) {
1719                     case 3:  // There is one entry.
1720                         if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.startsWith(whitelistEntry[1])) {
1721                             // Return a whitelist match request allowed.
1722                             return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_INITIAL_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1], whitelistEntry[2]};
1723                         }
1724                         break;
1725
1726                     case 4:  // There are two entries.
1727                         if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.startsWith(whitelistEntry[1]) && resourceUrl.contains(whitelistEntry[2])) {
1728                             // Return a whitelist match request allowed.
1729                             return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_INITIAL_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1] + "\n" + whitelistEntry[2],
1730                                     whitelistEntry[3]};
1731                         }
1732                         break;
1733
1734                     case 5:  // There are three entries.
1735                         if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.startsWith(whitelistEntry[1]) && resourceUrl.contains(whitelistEntry[2]) && resourceUrl.startsWith(whitelistEntry[3])) {
1736                             // Return a whitelist match request allowed.
1737                             return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_INITIAL_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1] + "\n" + whitelistEntry[2] + "\n" +
1738                                     whitelistEntry[3], whitelistEntry[4]};
1739                         }
1740                         break;
1741                 }
1742             }
1743
1744             // Domain final white list.
1745             for (String[] whitelistEntry : blocklist.get(Integer.valueOf(DOMAIN_FINAL_WHITELIST))) {
1746                 switch (whitelistEntry.length) {
1747                     case 3:  // There is one entry;
1748                         if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.endsWith(whitelistEntry[1])) {
1749                             // Return a whitelist match request allowed.
1750                             return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_FINAL_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1], whitelistEntry[2]};
1751                         }
1752                         break;
1753
1754                     case 4:  // There are two entries;
1755                         if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.contains(whitelistEntry[1]) && resourceUrl.endsWith(whitelistEntry[2])) {
1756                             // Return a whitelist match request allowed.
1757                             return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_FINAL_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1] + "\n" + whitelistEntry[2],
1758                                     whitelistEntry[3]};
1759                         }
1760                         break;
1761                 }
1762             }
1763         }
1764
1765         // Only check the third-party white lists if this is a third-party request.
1766         if (isThirdPartyRequest) {
1767             // Third-party white list.
1768             for (String[] whitelistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_WHITELIST))) {
1769                 switch (whitelistEntry.length) {
1770                     case 2:  // There is one entry
1771                         if (resourceUrl.contains(whitelistEntry[0])) {
1772                             // Return a whitelist match request allowed.
1773                             return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_WHITELIST, whitelistEntry[0], whitelistEntry[1]};
1774                         }
1775                         break;
1776
1777                     case 3:  // There are two entries.
1778                         if (resourceUrl.contains(whitelistEntry[0]) && resourceUrl.contains(whitelistEntry[1])) {
1779                             // Return a whitelist match request allowed.
1780                             return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1], whitelistEntry[2]};
1781                         }
1782                         break;
1783
1784                     case 4:  // There are three entries.
1785                         if (resourceUrl.contains(whitelistEntry[0]) && resourceUrl.contains(whitelistEntry[1]) && resourceUrl.contains(whitelistEntry[2])) {
1786                             // Return a whitelist match request allowed.
1787                             return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1] + "\n" + whitelistEntry[2],
1788                                     whitelistEntry[3]};
1789                         }
1790                         break;
1791
1792                     case 5:  // There are four entries.
1793                         if (resourceUrl.contains(whitelistEntry[0]) && resourceUrl.contains(whitelistEntry[1]) && resourceUrl.contains(whitelistEntry[2]) && resourceUrl.contains(whitelistEntry[3])) {
1794                             // Return a whitelist match request allowed.
1795                             return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1] + "\n" + whitelistEntry[2] + "\n" +
1796                                     whitelistEntry[3], whitelistEntry[4]};
1797                         }
1798                         break;
1799
1800                     case 6:  // There are five entries.
1801                         if (resourceUrl.contains(whitelistEntry[0]) && resourceUrl.contains(whitelistEntry[1]) && resourceUrl.contains(whitelistEntry[2]) && resourceUrl.contains(whitelistEntry[3]) &&
1802                                 resourceUrl.contains(whitelistEntry[4])) {
1803                             // Return a whitelist match request allowed.
1804                             return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1] + "\n" + whitelistEntry[2] + "\n" +
1805                                     whitelistEntry[3] + "\n" + whitelistEntry[4], whitelistEntry[5]};
1806                         }
1807                         break;
1808                 }
1809             }
1810
1811             // Third-party domain white list.
1812             for (String[] whitelistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_DOMAIN_WHITELIST))) {
1813                 if (whitelistEntry.length == 3) {  // There is one entry.
1814                     if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.contains(whitelistEntry[1])) {
1815                         // Return a whitelist match request allowed.
1816                         return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_DOMAIN_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1], whitelistEntry[2]};
1817                     }
1818                 } else {  // There are two entries.
1819                     if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.contains(whitelistEntry[1]) && resourceUrl.contains(whitelistEntry[2])) {
1820                         // Return a whitelist match request allowed.
1821                         return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_DOMAIN_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1] + "\n" + whitelistEntry[2],
1822                                 whitelistEntry[3]};
1823                     }
1824                 }
1825             }
1826
1827             // Third-party domain initial white list.
1828             for (String[] whitelistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_DOMAIN_INITIAL_WHITELIST))) {
1829                 if (whitelistEntry.length == 3) {  // There is one entry.
1830                     if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.startsWith(whitelistEntry[1])) {
1831                         // Return a whitelist match request allowed.
1832                         return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_DOMAIN_INITIAL_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1], whitelistEntry[2]};
1833                     }
1834                 } else {  // There are two entries.
1835                     if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.startsWith(whitelistEntry[1]) && resourceUrl.contains(whitelistEntry[2])) {
1836                         // Return a whitelist match request allowed.
1837                         return new String[] {REQUEST_ALLOWED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_DOMAIN_WHITELIST, whitelistEntry[0] + "\n" + whitelistEntry[1] + "\n" + whitelistEntry[2],
1838                                 whitelistEntry[3]};
1839                     }
1840                 }
1841             }
1842         }
1843
1844         // Process the black lists.
1845         // Main black list.
1846         for (String[] blacklistEntry : blocklist.get(Integer.valueOf(MAIN_BLACKLIST))) {
1847             switch (blacklistEntry.length) {
1848                 case 2:  // There is one entry.
1849                     if (resourceUrl.contains(blacklistEntry[0])) {
1850                         // Return a blacklist match request blocked.
1851                         return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, MAIN_BLACKLIST, blacklistEntry[0], blacklistEntry[1]};
1852                     }
1853                     break;
1854
1855                 case 3:  // There are two entries.
1856                     if (resourceUrl.contains(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1])) {
1857                         // Return a blacklist match request blocked.
1858                         return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, MAIN_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1], blacklistEntry[2]};
1859                     }
1860                     break;
1861
1862                 case 4:  // There are three entries.
1863                     if (resourceUrl.contains(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1]) && resourceUrl.contains(blacklistEntry[2])) {
1864                         // Return a blacklist match request blocked.
1865                         return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, MAIN_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1] + "\n" + blacklistEntry[2], blacklistEntry[3]};
1866                     }
1867                     break;
1868
1869                 case 5:  // There are four entries.
1870                     if (resourceUrl.contains(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1]) && resourceUrl.contains(blacklistEntry[2]) && resourceUrl.contains(blacklistEntry[3])) {
1871                         // Return a blacklist match request blocked.
1872                         return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, MAIN_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1] + "\n" + blacklistEntry[2] + "\n" +
1873                                 blacklistEntry[3], blacklistEntry[4]};
1874                     }
1875                     break;
1876
1877                 case 6:  // There are five entries.
1878                     if (resourceUrl.contains(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1]) && resourceUrl.contains(blacklistEntry[2]) && resourceUrl.contains(blacklistEntry[3]) &&
1879                             resourceUrl.contains(blacklistEntry[4])) {
1880                         // Return a blacklist match request blocked.
1881                         return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, MAIN_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1] + "\n" + blacklistEntry[2] + "\n" +
1882                                 blacklistEntry[3] + "\n" + blacklistEntry[4], blacklistEntry[5]};
1883                     }
1884                     break;
1885             }
1886         }
1887
1888         // Initial black list.
1889         for (String[] blacklistEntry : blocklist.get(Integer.valueOf(INITIAL_BLACKLIST))) {
1890             if (blacklistEntry.length == 2) {  // There is one entry.
1891                 if (resourceUrl.startsWith(blacklistEntry[0])) {
1892                     // Return a blacklist match request blocked.
1893                     return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, INITIAL_BLACKLIST, blacklistEntry[0], blacklistEntry[1]};
1894                 }
1895             } else {  // There are two entries
1896                 if (resourceUrl.startsWith(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1])) {
1897                     // Return a blacklist match request blocked.
1898                     return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, INITIAL_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1], blacklistEntry[2]};
1899                 }
1900             }
1901         }
1902
1903         // Final black list.
1904         for (String[] blacklistEntry : blocklist.get(Integer.valueOf(FINAL_BLACKLIST))) {
1905             switch (blacklistEntry.length) {
1906                 case 2:  // There is one entry.
1907                     if (resourceUrl.endsWith(blacklistEntry[0])) {
1908                         // Return a blacklist match request blocked.
1909                         return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, FINAL_BLACKLIST, blacklistEntry[0], blacklistEntry[1]};
1910                     }
1911                     break;
1912
1913                 case 3:  // There are two entries.
1914                     if (resourceUrl.contains(blacklistEntry[0]) && resourceUrl.endsWith(blacklistEntry[1])) {
1915                         // Return a blacklist match request blocked.
1916                         return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, FINAL_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1], blacklistEntry[2]};
1917                     }
1918                     break;
1919
1920                 case 4:  // There are three entries.
1921                     if (resourceUrl.contains(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1]) && resourceUrl.endsWith(blacklistEntry[2])) {
1922                         // Return a blacklist match request blocked.
1923                         return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, FINAL_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1] + "\n" + blacklistEntry[2], blacklistEntry[3]};
1924                     }
1925                     break;
1926             }
1927         }
1928
1929         // Only check the domain lists if the current domain is not null (like `about:blank`).
1930         if (currentDomain != null) {
1931             // Domain black list.
1932             for (String[] blacklistEntry : blocklist.get(Integer.valueOf(DOMAIN_BLACKLIST))) {
1933                 switch (blacklistEntry.length) {
1934                     case 3:  // There is one entry.
1935                         if (currentDomain.endsWith(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1])) {
1936                             // Return a blacklist match request blocked.
1937                             return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1], blacklistEntry[2]};
1938                         }
1939                         break;
1940
1941                     case 4:  // There are two entries.
1942                         if (currentDomain.endsWith(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1]) && resourceUrl.contains(blacklistEntry[2])) {
1943                             // Return a blacklist match request blocked.
1944                             return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1] + "\n" + blacklistEntry[2],
1945                                     blacklistEntry[3]};
1946                         }
1947                         break;
1948
1949                     case 5:  // There are three entries.
1950                         if (currentDomain.endsWith(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1]) && resourceUrl.contains(blacklistEntry[2]) && resourceUrl.contains(blacklistEntry[3])) {
1951                             // Return a blacklist match request blocked.
1952                             return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1] + "\n" + blacklistEntry[2] + "\n" +
1953                                     blacklistEntry[3], blacklistEntry[4]};
1954                         }
1955                         break;
1956                 }
1957             }
1958
1959             // Domain initial black list.
1960             for (String[] blacklistEntry : blocklist.get(Integer.valueOf(DOMAIN_INITIAL_BLACKLIST))) {
1961                 // Store the entry in the resource request log.
1962                 if (currentDomain.endsWith(blacklistEntry[0]) && resourceUrl.startsWith(blacklistEntry[1])) {
1963                     // Return a blacklist match request blocked.
1964                     return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_INITIAL_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1], blacklistEntry[2]};
1965                 }
1966             }
1967
1968             // Domain final black list.
1969             for (String[] blacklistEntry : blocklist.get(Integer.valueOf(DOMAIN_FINAL_BLACKLIST))) {
1970                 switch (blacklistEntry.length) {
1971                     case 3:  // There is one entry.
1972                         if (currentDomain.endsWith(blacklistEntry[0]) && resourceUrl.endsWith(blacklistEntry[1])) {
1973                             // Return a blacklist match request blocked.
1974                             return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_FINAL_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1], blacklistEntry[2]};
1975                         }
1976                         break;
1977
1978                     case 4:  // There are two entries.
1979                         if (currentDomain.endsWith(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1]) && resourceUrl.endsWith(blacklistEntry[2])) {
1980                             // Return a blacklist match request blocked.
1981                             return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_FINAL_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1] + "\n" + blacklistEntry[2],
1982                                     blacklistEntry[3]};
1983                         }
1984                         break;
1985                 }
1986             }
1987
1988             // Domain regular expression black list.
1989             for (String[] blacklistEntry : blocklist.get(Integer.valueOf(DOMAIN_REGULAR_EXPRESSION_BLACKLIST))) {
1990                 if (currentDomain.endsWith(blacklistEntry[0]) && Pattern.matches(blacklistEntry[1], resourceUrl)) {
1991                     // Return a blacklist match request blocked.
1992                     return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_REGULAR_EXPRESSION_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1], blacklistEntry[2]};
1993                 }
1994             }
1995         }
1996
1997         // Only check the third-party black lists if this is a third-party request.
1998         if (isThirdPartyRequest) {
1999             // Third-party black list.
2000             for (String[] blacklistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_BLACKLIST))) {
2001                 switch (blacklistEntry.length) {
2002                     case 2:  // There is one entry.
2003                         if (resourceUrl.contains(blacklistEntry[0])) {
2004                             // Return a blacklist match request blocked.
2005                             return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_BLACKLIST, blacklistEntry[0], blacklistEntry[1]};
2006                         }
2007                         break;
2008
2009                     case 3:  // There are two entries.
2010                         if (resourceUrl.contains(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1])) {
2011                             // Return a blacklist match request blocked.
2012                             return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1], blacklistEntry[2]};
2013                         }
2014                         break;
2015
2016                     case 4:  // There are three entries.
2017                         if (resourceUrl.contains(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1]) && resourceUrl.contains(blacklistEntry[2])) {
2018                             // Return a blacklist match request blocked.
2019                             return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1] + "\n" + blacklistEntry[2],
2020                                     blacklistEntry[3]};
2021                         }
2022                         break;
2023
2024                     case 5:  // There are four entries.
2025                         if (resourceUrl.contains(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1]) && resourceUrl.contains(blacklistEntry[2]) && resourceUrl.contains(blacklistEntry[3])) {
2026                             // Return a blacklist match request blocked.
2027                             return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1] + "\n" + blacklistEntry[2] + "\n" +
2028                                     blacklistEntry[3], blacklistEntry[4]};
2029                         }
2030                         break;
2031                 }
2032             }
2033
2034             // Third-party initial black list.
2035             for (String[] blacklistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_INITIAL_BLACKLIST))) {
2036                 if (blacklistEntry.length == 2) {  // There is one entry.
2037                     if (resourceUrl.startsWith(blacklistEntry[0])) {
2038                         // Return a blacklist match request blocked.
2039                         return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_INITIAL_BLACKLIST, blacklistEntry[0], blacklistEntry[1]};
2040                     }
2041                 } else {  // There are two entries.
2042                     if (resourceUrl.startsWith(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1])) {
2043                         // Return a blacklist match request blocked.
2044                         return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_INITIAL_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1], blacklistEntry[2]};
2045                     }
2046                 }
2047             }
2048
2049             // Third-party domain black list.
2050             for (String[] blacklistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_DOMAIN_BLACKLIST))) {
2051                 if (blacklistEntry.length == 3) {  // There is one entry.
2052                     if (currentDomain.endsWith(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1])) {
2053                         // Return a blacklist match request blocked.
2054                         return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_DOMAIN_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1], blacklistEntry[2]};
2055                     }
2056                 } else { // There are two entries.
2057                     if (currentDomain.endsWith(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1]) && resourceUrl.contains(blacklistEntry[2])) {
2058                         // Return a blacklist match request blocked.
2059                         return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_DOMAIN_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1] + "\n" + blacklistEntry[2],
2060                                 blacklistEntry[3]};
2061                     }
2062                 }
2063             }
2064
2065             // Third-party domain initial black list.
2066             for (String[] blacklistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_DOMAIN_INITIAL_BLACKLIST))) {
2067                 switch (blacklistEntry.length) {
2068                     case 3:  // There is one entry.
2069                         if (currentDomain.endsWith(blacklistEntry[0]) && resourceUrl.startsWith(blacklistEntry[1])) {
2070                             // Return a blacklist match request blocked.
2071                             return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_DOMAIN_INITIAL_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1], blacklistEntry[2]};
2072                         }
2073                         break;
2074
2075                     case 4:  // There are two entries.
2076                         if (currentDomain.endsWith(blacklistEntry[0]) && resourceUrl.startsWith(blacklistEntry[1]) && resourceUrl.contains(blacklistEntry[2])) {
2077                             // Return a blacklist match request blocked.
2078                             return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_DOMAIN_INITIAL_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1] + "\n" +
2079                                     blacklistEntry[2], blacklistEntry[3]};
2080                         }
2081                         break;
2082
2083                     case 5:  // There are three entries.
2084                         if (currentDomain.endsWith(blacklistEntry[0]) && resourceUrl.startsWith(blacklistEntry[1]) && resourceUrl.contains(blacklistEntry[2]) && resourceUrl.contains(blacklistEntry[3])) {
2085                             // Return a blacklist match request blocked.
2086                             return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_DOMAIN_INITIAL_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1] + "\n" +
2087                                     blacklistEntry[2] + "\n" + blacklistEntry[3], blacklistEntry[4]};
2088                         }
2089                         break;
2090                 }
2091             }
2092
2093             // Third-party regular expression black list.
2094             for (String[] blacklistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_REGULAR_EXPRESSION_BLACKLIST))) {
2095                 if (Pattern.matches(blacklistEntry[0], resourceUrl)) {
2096                     // Return a blacklist match request blocked.
2097                     return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_REGULAR_EXPRESSION_BLACKLIST, blacklistEntry[0], blacklistEntry[1]};
2098                 }
2099             }
2100
2101             // Third-party domain regular expression black list.
2102             for (String[] blacklistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_DOMAIN_REGULAR_EXPRESSION_BLACKLIST))) {
2103                 if (currentDomain.endsWith(blacklistEntry[0]) && Pattern.matches(blacklistEntry[1], resourceUrl)) {
2104                     // Return a blacklist match request blocked.
2105                     return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_DOMAIN_REGULAR_EXPRESSION_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1], blacklistEntry[2]};
2106                 }
2107             }
2108         }
2109
2110         // Regular expression black list.
2111         for (String[] blacklistEntry : blocklist.get(Integer.valueOf(REGULAR_EXPRESSION_BLACKLIST))) {
2112             if (Pattern.matches(blacklistEntry[0], resourceUrl)) {
2113                 // Return a blacklist match request blocked.
2114                 return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, REGULAR_EXPRESSION_BLACKLIST, blacklistEntry[0], blacklistEntry[1]};
2115             }
2116         }
2117
2118         // Return a no match request default.
2119         return new String[] {REQUEST_DEFAULT};
2120     }
2121 }