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