]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blob - app/src/main/java/com/stoutner/privacybrowser/helpers/ParseBlocklistHelper.kt
Split the blocklist helper. https://redmine.stoutner.com/issues/953
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / helpers / ParseBlocklistHelper.kt
1 /*
2  * Copyright 2018-2019,2021-2023 Soren Stoutner <soren@stoutner.com>.
3  *
4  * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
5  *
6  * Privacy Browser Android 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 Android 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 Android.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 package com.stoutner.privacybrowser.helpers
21
22 import android.content.res.AssetManager
23
24 import java.io.BufferedReader
25 import java.io.IOException
26 import java.io.InputStreamReader
27 import java.util.ArrayList
28
29 // Define the schema of the string array in each entry of the resource requests array list.
30 const val REQUEST_DISPOSITION = 0
31 const val REQUEST_URL = 1
32 const val REQUEST_BLOCKLIST = 2
33 const val REQUEST_SUBLIST = 3
34 const val REQUEST_BLOCKLIST_ENTRIES = 4
35 const val REQUEST_BLOCKLIST_ORIGINAL_ENTRY = 5
36
37 // Define the whitelists.
38 const val MAIN_WHITELIST = "1"
39 const val FINAL_WHITELIST = "2"
40 const val DOMAIN_WHITELIST = "3"
41 const val DOMAIN_INITIAL_WHITELIST = "4"
42 const val DOMAIN_FINAL_WHITELIST = "5"
43 const val THIRD_PARTY_WHITELIST = "6"
44 const val THIRD_PARTY_DOMAIN_WHITELIST = "7"
45 const val THIRD_PARTY_DOMAIN_INITIAL_WHITELIST = "8"
46
47 // Define the blacklists.
48 const val MAIN_BLACKLIST = "9"
49 const val INITIAL_BLACKLIST = "10"
50 const val FINAL_BLACKLIST = "11"
51 const val DOMAIN_BLACKLIST = "12"
52 const val DOMAIN_INITIAL_BLACKLIST = "13"
53 const val DOMAIN_FINAL_BLACKLIST = "14"
54 const val DOMAIN_REGULAR_EXPRESSION_BLACKLIST = "15"
55 const val THIRD_PARTY_BLACKLIST = "16"
56 const val THIRD_PARTY_INITIAL_BLACKLIST = "17"
57 const val THIRD_PARTY_DOMAIN_BLACKLIST = "18"
58 const val THIRD_PARTY_DOMAIN_INITIAL_BLACKLIST = "19"
59 const val THIRD_PARTY_REGULAR_EXPRESSION_BLACKLIST = "20"
60 const val THIRD_PARTY_DOMAIN_REGULAR_EXPRESSION_BLACKLIST = "21"
61 const val REGULAR_EXPRESSION_BLACKLIST = "22"
62
63 class ParseBlocklistHelper {
64     fun parseBlocklist(assetManager: AssetManager, blocklistName: String): ArrayList<List<Array<String>>> {
65         // Initialize the header list.
66         val headers: MutableList<Array<String>> = ArrayList()  // 0.
67
68         // Initialize the whitelists.
69         val mainWhitelist: MutableList<Array<String>> = ArrayList()  // 1.
70         val finalWhitelist: MutableList<Array<String>> = ArrayList()  // 2.
71         val domainWhitelist: MutableList<Array<String>> = ArrayList()  // 3.
72         val domainInitialWhitelist: MutableList<Array<String>> = ArrayList()  // 4.
73         val domainFinalWhitelist: MutableList<Array<String>> = ArrayList()  // 5.
74         val thirdPartyWhitelist: MutableList<Array<String>> = ArrayList()  // 6.
75         val thirdPartyDomainWhitelist: MutableList<Array<String>> = ArrayList()  // 7.
76         val thirdPartyDomainInitialWhitelist: MutableList<Array<String>> = ArrayList()  // 8.
77
78         // Initialize the blacklists.
79         val mainBlacklist: MutableList<Array<String>> = ArrayList()  // 9.
80         val initialBlacklist: MutableList<Array<String>> = ArrayList()  // 10.
81         val finalBlacklist: MutableList<Array<String>> = ArrayList()  // 11.
82         val domainBlacklist: MutableList<Array<String>> = ArrayList()  // 12.
83         val domainInitialBlacklist: MutableList<Array<String>> = ArrayList()  // 13.
84         val domainFinalBlacklist: MutableList<Array<String>> = ArrayList()  // 14.
85         val domainRegularExpressionBlacklist: MutableList<Array<String>> = ArrayList()  // 15.
86         val thirdPartyBlacklist: MutableList<Array<String>> = ArrayList()  // 16.
87         val thirdPartyInitialBlacklist: MutableList<Array<String>> = ArrayList()  // 17.
88         val thirdPartyDomainBlacklist: MutableList<Array<String>> = ArrayList()  // 18.
89         val thirdPartyDomainInitialBlacklist: MutableList<Array<String>> = ArrayList()  // 19.
90         val regularExpressionBlacklist: MutableList<Array<String>> = ArrayList()  // 20.
91         val thirdPartyRegularExpressionBlacklist: MutableList<Array<String>> = ArrayList()  // 21.
92         val thirdPartyDomainRegularExpressionBlacklist: MutableList<Array<String>> = ArrayList()  // 22.
93
94         // Populate the blocklists.  The `try` is required by input stream reader.
95         try {
96             // Load the blocklist into a buffered reader.
97             val bufferedReader = BufferedReader(InputStreamReader(assetManager.open(blocklistName)))
98
99             // Create strings for storing the block list entries.
100             var blocklistEntry: String
101             var originalBlocklistEntry: String
102
103             // Parse the block list.
104             bufferedReader.forEachLine {
105                 // Store the original block list entry.
106                 originalBlocklistEntry = it
107
108                 // Remove any `^` from the block list entry.  Privacy Browser does not process them in the interest of efficiency.
109                 blocklistEntry = it.replace("^", "")
110
111                 // Parse the entry.
112                 if (blocklistEntry.contains("##") || blocklistEntry.contains("#?#") || blocklistEntry.contains("#@#") || blocklistEntry.startsWith("[")) {
113                     // Entries that contain `##`, `#?#`, and `#@#` are for hiding elements in the main page's HTML.  Entries that start with `[` describe the AdBlock compatibility level.
114                     // Do nothing.  Privacy Browser does not currently use these entries.
115
116                     //Log.i("Blocklists", "Not added: " + blocklistEntry);
117                 } else if (blocklistEntry.contains("\$csp=script-src")) {  // Ignore entries that contain `$csp=script-src`.
118                     // Do nothing.  It is uncertain what this directive is even supposed to mean, and it is blocking entire websites like androidcentral.com.  https://redmine.stoutner.com/issues/306.
119
120                     //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
121                 } else if (blocklistEntry.contains("\$websocket") || blocklistEntry.contains("\$third-party,websocket") || blocklistEntry.contains("\$script,websocket")) {
122                     // Ignore entries with `websocket`.
123                     // Do nothing.  Privacy Browser does not differentiate between websocket requests and other requests and these entries cause a lot of false positives.
124
125                     //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
126                 } else if (blocklistEntry.startsWith("!")) {  //  Comment entries.
127                     if (blocklistEntry.startsWith("! Version:")) {
128                         // Get the list version number.
129                         val listVersion = arrayOf(blocklistEntry.substring(11))
130
131                         // Store the list version in the headers list.
132                         headers.add(listVersion)
133                     }
134
135                     if (blocklistEntry.startsWith("! Title:")) {
136                         // Get the list title.
137                         val listTitle = arrayOf(blocklistEntry.substring(9))
138
139                         // Store the list title in the headers list.
140                         headers.add(listTitle)
141                     }
142
143                     //Log.i("Blocklists", "Not added: " + blocklistEntry);
144                 } else if (blocklistEntry.startsWith("@@")) {  // Entries that begin with `@@` are whitelists.
145                     // Remove the `@@`
146                     blocklistEntry = blocklistEntry.substring(2)
147
148                     // Strip out any initial `||`.  Privacy Browser doesn't differentiate items that only match against the end of the domain name.
149                     if (blocklistEntry.startsWith("||")) {
150                         blocklistEntry = blocklistEntry.substring(2)
151                     }
152
153                     if (blocklistEntry.contains("$")) {  // Filter entries.
154                         if (blocklistEntry.contains("~third-party")) {  // Ignore entries that contain `~third-party`.
155                             // Do nothing.
156
157                             //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
158                         } else if (blocklistEntry.contains("third-party")) {  // Third-party whitelist entries.
159                             if (blocklistEntry.contains("domain=")) {  // Third-party domain whitelist entries.
160                                 // Parse the entry.
161                                 var entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
162                                 val filters = blocklistEntry.substring(blocklistEntry.indexOf("$") + 1)
163                                 var domains = filters.substring(filters.indexOf("domain=") + 7)
164
165                                 if (domains.contains("~")) {  // It is uncertain what a `~` domain means inside an `@@` entry.
166                                     // Do Nothing
167
168                                     //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
169                                 } else if (blocklistEntry.startsWith("|")) {  // Third-party domain initial whitelist entries.
170                                     // Strip out the initial `|`.
171                                     entry = entry.substring(1)
172
173                                     if (entry == "http://" || entry == "https://") {  // Ignore generic entries.
174                                         // Do nothing.  These entries are designed for filter options that Privacy Browser does not use.
175
176                                         //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
177                                     } else {  // Process third-party domain initial whitelist entries.
178                                         // Process each domain.
179                                         do {
180                                             // Create a string to keep track of the current domain.
181                                             var domain: String
182
183                                             if (domains.contains("|")) {  // There is more than one domain in the list.
184                                                 // Get the first domain from the list.
185                                                 domain = domains.substring(0, domains.indexOf("|"))
186
187                                                 // Remove the first domain from the list.
188                                                 domains = domains.substring(domains.indexOf("|") + 1)
189                                             } else {  // There is only one domain in the list.
190                                                 domain = domains
191                                             }
192
193                                             if (entry.contains("*")) {  // Process a third-party domain initial whitelist double entry.
194                                                 // Get the index of the wildcard.
195                                                 val wildcardIndex = entry.indexOf("*")
196
197                                                 // Split the entry into components.
198                                                 val firstEntry = entry.substring(0, wildcardIndex)
199                                                 val secondEntry = entry.substring(wildcardIndex + 1)
200
201                                                 // Create an entry string array.
202                                                 val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
203
204                                                 // Add the entry to the whitelist.
205                                                 thirdPartyDomainInitialWhitelist.add(domainDoubleEntry)
206
207                                                 //Log.i("Blocklists", headers.get(1)[0] + " third-party domain initial whitelist added: " + domain + " , " + firstEntry + " , " + secondEntry +
208                                                 //        "  -  " + originalBlocklistEntry);
209                                             } else {  // Process a third-party domain initial whitelist single entry.
210                                                 // Create a domain entry string array.
211                                                 val domainEntry = arrayOf(domain, entry, originalBlocklistEntry)
212
213                                                 // Add the entry to the third party domain initial whitelist.
214                                                 thirdPartyDomainInitialWhitelist.add(domainEntry)
215
216                                                 //Log.i("Blocklists", headers.get(1)[0] + " third-party domain initial whitelist added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
217                                             }
218                                         } while (domains.contains("|"))
219                                     }
220                                 } else {  // Third-party domain entries.
221                                     // Process each domain.
222                                     do {
223                                         // Create a string to keep track of the current domain.
224                                         var domain: String
225
226                                         if (domains.contains("|")) {  // three is more than one domain in the list.
227                                             // Get the first domain from the list.
228                                             domain = domains.substring(0, domains.indexOf("|"))
229
230                                             // Remove the first domain from the list.
231                                             domains = domains.substring(domains.indexOf("|") + 1)
232                                         } else {  // There is only one domain in the list.
233                                             domain = domains
234                                         }
235
236                                         // Remove any trailing `*` from the entry.
237                                         if (entry.endsWith("*")) {
238                                             entry = entry.substring(0, entry.length - 1)
239                                         }
240
241                                         if (entry.contains("*")) {  // Process a third-party domain double entry.
242                                             // Get the index of the wildcard.
243                                             val wildcardIndex = entry.indexOf("*")
244
245                                             // Split the entry into components.
246                                             val firstEntry = entry.substring(0, wildcardIndex)
247                                             val secondEntry = entry.substring(wildcardIndex + 1)
248
249                                             // Create an entry string array.
250                                             val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
251
252                                             // Add the entry to the whitelist.
253                                             thirdPartyDomainWhitelist.add(domainDoubleEntry)
254
255                                             //Log.i("Blocklists", headers.get(1)[0] + " third-party domain whitelist added: " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " +
256                                             //        originalBlocklistEntry);
257                                         } else {  // Process a third-party domain single entry.
258                                             // Create an entry string array.
259                                             val domainEntry = arrayOf(domain, entry, originalBlocklistEntry)
260
261                                             // Add the entry to the whitelist.
262                                             thirdPartyDomainWhitelist.add(domainEntry)
263
264                                             //Log.i("Blocklists", headers.get(1)[0] + " third-party domain whitelist added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
265                                         }
266                                     } while (domains.contains("|"))
267                                 }
268                             } else {  // Process third-party whitelist entries.
269                                 // Parse the entry
270                                 val entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
271
272                                 if (entry.contains("*")) {  // There are two or more entries.
273                                     // Get the index of the wildcard.
274                                     val wildcardIndex = entry.indexOf("*")
275
276                                     // Split the entry into components.
277                                     val firstEntry = entry.substring(0, wildcardIndex)
278                                     val secondEntry = entry.substring(wildcardIndex + 1)
279
280                                     if (secondEntry.contains("*")) {  // There are three or more entries.
281                                         // Get the index of the wildcard.
282                                         val secondWildcardIndex = secondEntry.indexOf("*")
283
284                                         // Split the entry into components.
285                                         val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
286                                         val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
287
288                                         if (thirdEntry.contains("*")) {  // There are four or more entries.
289                                             // Get the index of the wildcard.
290                                             val thirdWildcardIndex = thirdEntry.indexOf("*")
291
292                                             // Split the entry into components.
293                                             val realThirdEntry = thirdEntry.substring(0, thirdWildcardIndex)
294                                             val fourthEntry = thirdEntry.substring(thirdWildcardIndex + 1)
295
296                                             if (fourthEntry.contains("*")) {  // Process a third-party whitelist quintuple entry.
297                                                 // Get the index of the wildcard.
298                                                 val fourthWildcardIndex = fourthEntry.indexOf("*")
299
300                                                 // Split the entry into components.
301                                                 val realFourthEntry = fourthEntry.substring(0, fourthWildcardIndex)
302                                                 val fifthEntry = fourthEntry.substring(fourthWildcardIndex + 1)
303
304                                                 // Create an entry string array.
305                                                 val quintupleEntry = arrayOf(firstEntry, realSecondEntry, realThirdEntry, realFourthEntry, fifthEntry, originalBlocklistEntry)
306
307                                                 // Add the entry to the whitelist.
308                                                 thirdPartyWhitelist.add(quintupleEntry)
309
310                                                 //Log.i("Blocklists", headers.get(1)[0] + " third-party whitelist added: " + firstEntry + " , " + realSecondEntry + " , " + realThirdEntry + " , " +
311                                                 //        realFourthEntry + " , " + fifthEntry + "  -  " + originalBlocklistEntry);
312                                             } else {  // Process a third-party whitelist quadruple entry.
313                                                 // Create an entry string array.
314                                                 val quadrupleEntry = arrayOf(firstEntry, realSecondEntry, realThirdEntry, fourthEntry, originalBlocklistEntry)
315
316                                                 // Add the entry to the whitelist.
317                                                 thirdPartyWhitelist.add(quadrupleEntry)
318
319                                                 //Log.i("Blocklists", headers.get(1)[0] + " third-party whitelist added: " + firstEntry + " , " + realSecondEntry + " , " + realThirdEntry + " , " +
320                                                 //        fourthEntry + "  -  " + originalBlocklistEntry);
321                                             }
322                                         } else {  // Process a third-party whitelist triple entry.
323                                             // Create an entry string array.
324                                             val tripleEntry = arrayOf(firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
325
326                                             // Add the entry to the whitelist.
327                                             thirdPartyWhitelist.add(tripleEntry)
328
329                                             //Log.i("Blocklists", headers.get(1)[0] + " third-party whitelist added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + "  -  " +
330                                             //        originalBlocklistEntry);
331                                         }
332                                     } else {  // Process a third-party whitelist double entry.
333                                         // Create an entry string array.
334                                         val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
335
336                                         // Add the entry to the whitelist.
337                                         thirdPartyWhitelist.add(doubleEntry)
338
339                                         //Log.i("Blocklists", headers.get(1)[0] + " third-party whitelist added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
340                                     }
341                                 } else {  // Process a third-party whitelist single entry.
342                                     // Create an entry string array.
343                                     val singleEntry = arrayOf(entry, originalBlocklistEntry)
344
345                                     // Add the entry to the whitelist.
346                                     thirdPartyWhitelist.add(singleEntry)
347
348                                     //Log.i("Blocklists", headers.get(1)[0] + " third-party domain whitelist added: " + entry + "  -  " + originalBlocklistEntry);
349                                 }
350                             }
351                         } else if (blocklistEntry.contains("domain=")) {  // Process domain whitelist entries.
352                             // Parse the entry
353                             var entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
354                             val filters = blocklistEntry.substring(blocklistEntry.indexOf("$") + 1)
355                             var domains = filters.substring(filters.indexOf("domain=") + 7)
356
357                             if (entry.startsWith("|")) {  // Initial domain whitelist entries.
358                                 // Strip the initial `|`.
359                                 entry = entry.substring(1)
360
361                                 if (entry == "http://" || entry == "https://") {  // Ignore generic entries.
362                                     // Do nothing.  These entries are designed for filter options that Privacy Browser does not use.
363
364                                     //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
365                                 } else {  // Initial domain whitelist entry.
366                                     // Process each domain.
367                                     do {
368                                         // Create a string to keep track of the current domain.
369                                         var domain: String
370
371                                         if (domains.contains("|")) {  // There is more than one domain in the list.
372                                             // Get the first domain from the list.
373                                             domain = domains.substring(0, domains.indexOf("|"))
374
375                                             // Remove the first domain from the list.
376                                             domains = domains.substring(domains.indexOf("|") + 1)
377                                         } else {  // There is only one domain in the list.
378                                             domain = domains
379                                         }
380
381                                         if (entry.contains("*")) {  // There are two or more entries.
382                                             // Get the index of the wildcard.
383                                             val wildcardIndex = entry.indexOf("*")
384
385                                             // Split the entry into components.
386                                             val firstEntry = entry.substring(0, wildcardIndex)
387                                             val secondEntry = entry.substring(wildcardIndex + 1)
388
389                                             if (secondEntry.contains("*")) {  // Process a domain initial triple entry.
390                                                 // Get the index of the wildcard.
391                                                 val secondWildcardIndex = secondEntry.indexOf("*")
392
393                                                 // Split the entry into components.
394                                                 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
395                                                 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
396
397                                                 // Create an entry string array.
398                                                 val domainTripleEntry = arrayOf(domain, firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
399
400                                                 // Add the entry to the whitelist.
401                                                 domainInitialWhitelist.add(domainTripleEntry)
402
403                                                 //Log.i("Blocklists", headers.get(1)[0] + " domain initial whitelist entry added: " + domain + " , " + firstEntry + " , " + realSecondEntry + " , " +
404                                                 //        thirdEntry + "  -  " + originalBlocklistEntry);
405                                             } else {  // Process a domain initial double entry.
406                                                 // Create an entry string array.
407                                                 val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
408
409                                                 // Add the entry to the whitelist.
410                                                 domainInitialWhitelist.add(domainDoubleEntry)
411
412                                                 //Log.i("Blocklists", headers.get(1)[0] + " domain initial whitelist entry added: " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " +
413                                                 //        originalBlocklistEntry);
414                                             }
415                                         } else {  // Process a domain initial single entry.
416                                             // Create an entry string array.
417                                             val domainEntry = arrayOf(domain, entry, originalBlocklistEntry)
418
419                                             // Add the entry to the whitelist.
420                                             domainInitialWhitelist.add(domainEntry)
421
422                                             //Log.i("Blocklists", headers.get(1)[0] + " domain initial whitelist entry added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
423                                         }
424                                     } while (domains.contains("|"))
425                                 }
426                             } else if (entry.endsWith("|")) {  // Final domain whitelist entries.
427                                 // Strip the `|` from the end of the entry.
428                                 entry = entry.substring(0, entry.length - 1)
429
430                                 // Process each domain.
431                                 do {
432                                     // Create a string to keep track of the current domain.
433                                     var domain: String
434
435                                     if (domains.contains("|")) {  // There is more than one domain in the list.
436                                         // Get the first domain from the list.
437                                         domain = domains.substring(0, domains.indexOf("|"))
438
439                                         // Remove the first domain from the list.
440                                         domains = domains.substring(domains.indexOf("|") + 1)
441                                     } else {  // There is only one domain in the list.
442                                         domain = domains
443                                     }
444
445                                     if (entry.contains("*")) {  // Process a domain final whitelist double entry.
446                                         // Get the index of the wildcard.
447                                         val wildcardIndex = entry.indexOf("*")
448
449                                         // Split the entry into components.
450                                         val firstEntry = entry.substring(0, wildcardIndex)
451                                         val secondEntry = entry.substring(wildcardIndex + 1)
452
453                                         // Create an entry string array.
454                                         val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
455
456                                         // Add the entry to the whitelist.
457                                         domainFinalWhitelist.add(domainDoubleEntry)
458
459                                         //Log.i("Blocklists", headers.get(1)[0] + " domain final whitelist added: " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " +
460                                         //        originalBlocklistEntry);
461                                     } else {  // Process a domain final whitelist single entry.
462                                         // create an entry string array.
463                                         val domainEntry = arrayOf(domain, entry, originalBlocklistEntry)
464
465                                         // Add the entry to the whitelist.
466                                         domainFinalWhitelist.add(domainEntry)
467
468                                         //Log.i("Blocklists", headers.get(1)[0] + " domain final whitelist added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
469                                     }
470                                 } while (domains.contains("|"))
471                             } else {  // Standard domain whitelist entries with filters.
472                                 if (domains.contains("~")) {  // It is uncertain what a `~` domain means inside an `@@` entry.
473                                     // Do Nothing
474
475                                     //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
476                                 } else {
477                                     // Process each domain.
478                                     do {
479                                         // Create a string to keep track of the current domain.
480                                         var domain: String
481
482                                         if (domains.contains("|")) {  // There is more than one domain in the list.
483                                             // Get the first domain from the list.
484                                             domain = domains.substring(0, domains.indexOf("|"))
485
486                                             // Remove the first domain from the list.
487                                             domains = domains.substring(domains.indexOf("|") + 1)
488                                         } else {  // There is only one domain in the list.
489                                             domain = domains
490                                         }
491
492                                         if (entry.contains("*")) {  // There are two or more entries.
493                                             // Get the index of the wildcard.
494                                             val wildcardIndex = entry.indexOf("*")
495
496                                             // Split the entry into components.
497                                             val firstEntry = entry.substring(0, wildcardIndex)
498                                             val secondEntry = entry.substring(wildcardIndex + 1)
499
500                                             if (secondEntry.contains("*")) {  // There are three or more entries.
501                                                 // Get the index of the wildcard.
502                                                 val secondWildcardIndex = secondEntry.indexOf("*")
503
504                                                 // Split the entry into components.
505                                                 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
506                                                 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
507
508                                                 if (thirdEntry.contains("*")) {  // Process a domain whitelist quadruple entry.
509                                                     // Get the index of the wildcard.
510                                                     val thirdWildcardIndex = thirdEntry.indexOf("*")
511
512                                                     // Split the entry into components.
513                                                     val realThirdEntry = thirdEntry.substring(0, thirdWildcardIndex)
514                                                     val fourthEntry = thirdEntry.substring(thirdWildcardIndex + 1)
515
516                                                     // Create an entry string array.
517                                                     val domainQuadrupleEntry = arrayOf(domain, firstEntry, realSecondEntry, realThirdEntry, fourthEntry, originalBlocklistEntry)
518
519                                                     // Add the entry to the whitelist.
520                                                     domainWhitelist.add(domainQuadrupleEntry)
521
522                                                     //Log.i("Blocklists", headers.get(1)[0] + " domain whitelist added : " + domain + " , " + firstEntry + " , " + realSecondEntry + " , " +
523                                                     //        realThirdEntry + " , " + fourthEntry + "  -  " + originalBlocklistEntry);
524                                                 } else {  // Process a domain whitelist triple entry.
525                                                     // Create an entry string array.
526                                                     val domainTripleEntry = arrayOf(domain, firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
527
528                                                     // Add the entry to the whitelist.
529                                                     domainWhitelist.add(domainTripleEntry)
530
531                                                     //Log.i("Blocklists", headers.get(1)[0] + " domain whitelist added : " + domain + " , " + firstEntry + " , " + realSecondEntry + " , " +
532                                                     //        thirdEntry + "  -  " + originalBlocklistEntry);
533                                                 }
534                                             } else {  // Process a domain whitelist double entry.
535                                                 // Create an entry string array.
536                                                 val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
537
538                                                 // Add the entry to the whitelist.
539                                                 domainWhitelist.add(domainDoubleEntry)
540
541                                                 //Log.i("Blocklists", headers.get(1)[0] + " domain whitelist added : " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " +
542                                                 //        originalBlocklistEntry);
543                                             }
544                                         } else {  // Process a domain whitelist single entry.
545                                             // Create an entry string array.
546                                             val domainEntry = arrayOf(domain, entry, originalBlocklistEntry)
547
548                                             // Add the entry to the whitelist.
549                                             domainWhitelist.add(domainEntry)
550
551                                             //Log.i("Blocklists", headers.get(1)[0] + " domain whitelist added : " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
552                                         }
553                                     } while (domains.contains("|"))
554                                 }
555                             }
556                         }  // Ignore all other filter entries.
557                     } else if (blocklistEntry.endsWith("|")) {  // Final whitelist entries.
558                         // Remove the final `|` from the entry.
559                         val entry = blocklistEntry.substring(0, blocklistEntry.length - 1)
560
561                         if (entry.contains("*")) {  // Process a final whitelist double entry
562                             // Get the index of the wildcard.
563                             val wildcardIndex = entry.indexOf("*")
564
565                             // split the entry into components.
566                             val firstEntry = entry.substring(0, wildcardIndex)
567                             val secondEntry = entry.substring(wildcardIndex + 1)
568
569                             // Create an entry string array.
570                             val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
571
572                             // Add the entry to the whitelist.
573                             finalWhitelist.add(doubleEntry)
574
575                             //Log.i("Blocklists", headers.get(1)[0] + " final whitelist added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
576                         } else {  // Process a final whitelist single entry.
577                             // Create an entry string array.
578                             val singleEntry = arrayOf(entry, originalBlocklistEntry)
579
580                             // Add the entry to the whitelist.
581                             finalWhitelist.add(singleEntry)
582
583                             //Log.i("Blocklists", headers.get(1)[0] + " final whitelist added: " + entry + "  -  " + originalBlocklistEntry);
584                         }
585                     } else {  // Main whitelist entries.
586                         if (blocklistEntry.contains("*")) {  // There are two or more entries.
587                             // Get the index of the wildcard.
588                             val wildcardIndex = blocklistEntry.indexOf("*")
589
590                             // Split the entry into components.
591                             val firstEntry = blocklistEntry.substring(0, wildcardIndex)
592                             val secondEntry = blocklistEntry.substring(wildcardIndex + 1)
593
594                             if (secondEntry.contains("*")) {  // Process a main whitelist triple entry.
595                                 // Get the index of the wildcard.
596                                 val secondWildcardIndex = secondEntry.indexOf("*")
597
598                                 // Split the entry into components.
599                                 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
600                                 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
601
602                                 // Create an entry string array.
603                                 val tripleEntry = arrayOf(firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
604
605                                 // Add the entry to the whitelist.
606                                 mainWhitelist.add(tripleEntry)
607
608                                 //Log.i("Blocklists", headers.get(1)[0] + " main whitelist added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + "  -  " + originalBlocklistEntry);
609                             } else {  // Process a main whitelist double entry.
610                                 // Create an entry string array.
611                                 val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
612
613                                 // Add the entry to the whitelist.
614                                 mainWhitelist.add(doubleEntry)
615
616                                 //Log.i("Blocklists", headers.get(1)[0] + " main whitelist added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
617                             }
618                         } else {  // Process a main whitelist single entry.
619                             // Create an entry string array.
620                             val singleEntry = arrayOf(blocklistEntry, originalBlocklistEntry)
621
622                             // Add the entry to the whitelist.
623                             mainWhitelist.add(singleEntry)
624
625                             //Log.i("Blocklists", headers.get(1)[0] + " main whitelist added: " + blocklistEntry + "  -  " + originalBlocklistEntry);
626                         }
627                     }
628                 } else if (blocklistEntry.endsWith("|")) {  // Final blacklist entries.
629                     // Strip out the final "|"
630                     var entry = blocklistEntry.substring(0, blocklistEntry.length - 1)
631
632                     // Strip out any initial `||`.  They are redundant in this case because the blocklist entry is being matched against the end of the URL.
633                     if (entry.startsWith("||")) {
634                         entry = entry.substring(2)
635                     }
636
637                     if (entry.contains("*")) {  // Process a final blacklist double entry.
638                         // Get the index of the wildcard.
639                         val wildcardIndex = entry.indexOf("*")
640
641                         // Split the entry into components.
642                         val firstEntry = entry.substring(0, wildcardIndex)
643                         val secondEntry = entry.substring(wildcardIndex + 1)
644
645                         // Create an entry string array.
646                         val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
647
648                         // Add the entry to the blacklist.
649                         finalBlacklist.add(doubleEntry)
650
651                         //Log.i("Blocklists", headers.get(1)[0] + " final blacklist added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
652                     } else {  // Process a final blacklist single entry.
653                         // create an entry string array.
654                         val singleEntry = arrayOf(entry, originalBlocklistEntry)
655
656                         // Add the entry to the blacklist.
657                         finalBlacklist.add(singleEntry)
658
659                         //Log.i("Blocklists", headers.get(1)[0] + " final blacklist added: " + entry + "  -  " + originalBlocklistEntry);
660                     }
661                 } else if (blocklistEntry.contains("$")) {  // Entries with filter options.
662                     // Strip out any initial `||`.  These will be treated like any other entry.
663                     if (blocklistEntry.startsWith("||")) {
664                         blocklistEntry = blocklistEntry.substring(2)
665                     }
666
667                     if (blocklistEntry.contains("third-party")) {  // Third-party entries.
668                         if (blocklistEntry.contains("~third-party")) {  // Third-party filter whitelist entries.
669                             // Do not process these whitelist entries.  They are designed to combine with block filters that Privacy Browser doesn't use, like `subdocument` and `xmlhttprequest`.
670
671                             //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
672                         } else if (blocklistEntry.contains("domain=")) {  // Third-party domain entries.
673                             if (blocklistEntry.startsWith("|")) {  // Third-party domain initial entries.
674                                 // Strip the initial `|`.
675                                 blocklistEntry = blocklistEntry.substring(1)
676
677                                 // Parse the entry
678                                 val entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
679                                 val filters = blocklistEntry.substring(blocklistEntry.indexOf("$") + 1)
680                                 var domains = filters.substring(filters.indexOf("domain=") + 7)
681
682                                 if (entry == "http:" || entry == "https:" || entry == "http://" || entry == "https://") {  // Ignore generic entries.
683                                     // Do nothing.  These entries will almost entirely disable the website.
684                                     // Often the original entry blocks filter options like `$script`, which Privacy Browser does not differentiate.
685
686                                     //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
687                                 } else {  // Third-party domain initial entries.
688                                     // Process each domain.
689                                     do {
690                                         // Create a string to keep track of the current domain.
691                                         var domain: String
692
693                                         if (domains.contains("|")) {  // There is more than one domain in the list.
694                                             // Get the first domain from the list.
695                                             domain = domains.substring(0, domains.indexOf("|"))
696
697                                             // Remove the first domain from the list.
698                                             domains = domains.substring(domains.indexOf("|") + 1)
699                                         } else {  // There is only one domain in the list.
700                                             domain = domains
701                                         }
702
703                                         if (entry.contains("*")) {  // Three are two or more entries.
704                                             // Get the index of the wildcard.
705                                             val wildcardIndex = entry.indexOf("*")
706
707                                             // Split the entry into components.
708                                             val firstEntry = entry.substring(0, wildcardIndex)
709                                             val secondEntry = entry.substring(wildcardIndex + 1)
710
711                                             if (secondEntry.contains("*")) {  // Process a third-party domain initial blacklist triple entry.
712                                                 // Get the index of the wildcard.
713                                                 val secondWildcardIndex = secondEntry.indexOf("*")
714
715                                                 // Split the entry into components.
716                                                 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
717                                                 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
718
719                                                 // Create an entry string array.
720                                                 val tripleDomainEntry = arrayOf(domain, firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
721
722                                                 // Add the entry to the blacklist.
723                                                 thirdPartyDomainInitialBlacklist.add(tripleDomainEntry)
724
725                                                 //Log.i("Blocklists", headers.get(1)[0] + " third-party domain initial blacklist added: " + domain + " , " + firstEntry + " , " + realSecondEntry +
726                                                 //        " , " + thirdEntry + "  -  " + originalBlocklistEntry);
727                                             } else {  // Process a third-party domain initial blacklist double entry.
728                                                 // Create an entry string array.
729                                                 val doubleDomainEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
730
731                                                 // Add the entry to the blacklist.
732                                                 thirdPartyDomainInitialBlacklist.add(doubleDomainEntry)
733
734                                                 //Log.i("Blocklists", headers.get(1)[0] + " third-party domain initial blacklist added: " + domain + " , " + firstEntry + " , " + secondEntry +
735                                                 //        "  -  " + originalBlocklistEntry);
736                                             }
737                                         } else {  // Process a third-party domain initial blacklist single entry.
738                                             // Create an entry string array.
739                                             val singleEntry = arrayOf(domain, entry, originalBlocklistEntry)
740
741                                             // Add the entry to the blacklist.
742                                             thirdPartyDomainInitialBlacklist.add(singleEntry)
743
744                                             //Log.i("Blocklists", headers.get(1)[0] + " third-party domain initial blacklist added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
745                                         }
746                                     } while (domains.contains("|"))
747                                 }
748                             } else if (blocklistEntry.contains("\\")) {  // Process a third-party domain blacklist regular expression.
749                                 // Parse the entry.  At least one regular expression in this entry contains `$`, so the parser uses `/$`.
750                                 val entry = blocklistEntry.substring(0, blocklistEntry.indexOf("/$") + 1)
751                                 val filters = blocklistEntry.substring(blocklistEntry.indexOf("/$") + 2)
752                                 var domains = filters.substring(filters.indexOf("domain=") + 7)
753
754                                 // Process each domain.
755                                 do {
756                                     // Create a string to keep track of the current domain.
757                                     var domain: String
758
759                                     if (domains.contains("|")) {  // There is more than one domain in the list.
760                                         // Get the first domain from the list.
761                                         domain = domains.substring(0, domains.indexOf("|"))
762
763                                         // Remove the first domain from the list.
764                                         domains = domains.substring(domains.indexOf("|") + 1)
765                                     } else {  // There is only one domain in the list.
766                                         domain = domains
767                                     }
768
769                                     // Create an entry string array.
770                                     val domainEntry = arrayOf(domain, entry, originalBlocklistEntry)
771
772                                     // Add the entry to the blacklist.
773                                     thirdPartyDomainRegularExpressionBlacklist.add(domainEntry)
774
775                                     //Log.i("Blocklists", headers.get(1)[0] + " third-party domain regular expression blacklist added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
776                                 } while (domains.contains("|"))
777                             } else {  // Third-party domain entries.
778                                 // Parse the entry
779                                 var entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
780                                 val filters = blocklistEntry.substring(blocklistEntry.indexOf("$") + 1)
781                                 var domains = filters.substring(filters.indexOf("domain=") + 7)
782
783                                 // Strip any trailing "*" from the entry.
784                                 if (entry.endsWith("*")) {
785                                     entry = entry.substring(0, entry.length - 1)
786                                 }
787
788                                 // Track if any third-party whitelist filters are applied.
789                                 var whitelistDomain = false
790
791                                 // Process each domain.
792                                 do {
793                                     // Create a string to keep track of the current domain.
794                                     var domain: String
795
796                                     if (domains.contains("|")) {  // There is more than one domain in the list.
797                                         // Get the first domain from the list.
798                                         domain = domains.substring(0, domains.indexOf("|"))
799
800                                         // Remove the first domain from the list.
801                                         domains = domains.substring(domains.indexOf("|") + 1)
802                                     } else {  // The is only one domain in the list.
803                                         domain = domains
804                                     }
805
806                                     // Differentiate between blocklist domains and whitelist domains.
807                                     if (domain.startsWith("~")) {  // Whitelist third-party domain entry.
808                                         // Strip the initial `~`.
809                                         domain = domain.substring(1)
810
811                                         // Set the whitelist domain flag.
812                                         whitelistDomain = true
813
814                                         if (entry.contains("*")) {  // Process a third-party domain whitelist double entry.
815                                             // Get the index of the wildcard.
816                                             val wildcardIndex = entry.indexOf("*")
817
818                                             // Split the entry into components.
819                                             val firstEntry = entry.substring(0, wildcardIndex)
820                                             val secondEntry = entry.substring(wildcardIndex + 1)
821
822                                             // Create an entry string array.
823                                             val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
824
825                                             // Add the entry to the whitelist.
826                                             thirdPartyDomainWhitelist.add(domainDoubleEntry)
827
828                                             //Log.i("Blocklists", headers.get(1)[0] + " third-party domain whitelist added: " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " +
829                                             //        originalBlocklistEntry);
830                                         } else {  // Process a third-party domain whitelist single entry.
831                                             // Create an entry string array.
832                                             val domainEntry = arrayOf(domain, entry, originalBlocklistEntry)
833
834                                             // Add the entry to the whitelist.
835                                             thirdPartyDomainWhitelist.add(domainEntry)
836
837                                             //Log.i("Blocklists", headers.get(1)[0] + " third-party domain whitelist added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
838                                         }
839                                     } else {  // Third-party domain blacklist entries.
840                                         if (entry.contains("*")) {  // Process a third-party domain blacklist double entry.
841                                             // Get the index of the wildcard.
842                                             val wildcardIndex = entry.indexOf("*")
843
844                                             // Split the entry into components.
845                                             val firstEntry = entry.substring(0, wildcardIndex)
846                                             val secondEntry = entry.substring(wildcardIndex + 1)
847
848                                             // Create an entry string array.
849                                             val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
850
851                                             // Add the entry to the blacklist
852                                             thirdPartyDomainBlacklist.add(domainDoubleEntry)
853
854                                             //Log.i("Blocklists", headers.get(1)[0] + " third-party domain blacklist added: " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " +
855                                             //        originalBlocklistEntry);
856                                         } else {  // Process a third-party domain blacklist single entry.
857                                             // Create an entry string array.
858                                             val domainEntry = arrayOf(domain, entry, originalBlocklistEntry)
859
860                                             // Add the entry to the blacklist.
861                                             thirdPartyDomainBlacklist.add(domainEntry)
862
863                                             //Log.i("Blocklists", headers.get(1)[0] + " third-party domain blocklist added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
864                                         }
865                                     }
866                                 } while (domains.contains("|"))
867
868                                 // Add a third-party blacklist entry if a whitelist domain was processed.
869                                 if (whitelistDomain) {
870                                     if (entry.contains("*")) {  // Process a third-party blacklist double entry.
871                                         // Get the index of the wildcard.
872                                         val wildcardIndex = entry.indexOf("*")
873
874                                         // Split the entry into components.
875                                         val firstEntry = entry.substring(0, wildcardIndex)
876                                         val secondEntry = entry.substring(wildcardIndex + 1)
877
878                                         // Create an entry string array.
879                                         val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
880
881                                         // Add the entry to the blacklist.
882                                         thirdPartyBlacklist.add(doubleEntry)
883
884                                         //Log.i("Blocklists", headers.get(1)[0] + " third-party blacklist added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
885                                     } else {  // Process a third-party blacklist single entry.
886                                         // Create an entry string array.
887                                         val singleEntry = arrayOf(entry, originalBlocklistEntry)
888
889                                         // Add an entry to the blacklist.
890                                         thirdPartyBlacklist.add(singleEntry)
891
892                                         //Log.i("Blocklists", headers.get(1)[0] + " third-party blacklist added: " + entry + "  -  " + originalBlocklistEntry);
893                                     }
894                                 }
895                             }
896                         } else if (blocklistEntry.startsWith("|")) {  // Third-party initial blacklist entries.
897                             // Strip the initial `|`.
898                             blocklistEntry = blocklistEntry.substring(1)
899
900                             // Get the entry.
901                             val entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
902                             if (entry.contains("*")) {  // Process a third-party initial blacklist double entry.
903                                 // Get the index of the wildcard.
904                                 val wildcardIndex = entry.indexOf("*")
905
906                                 // Split the entry into components.
907                                 val firstEntry = entry.substring(0, wildcardIndex)
908                                 val secondEntry = entry.substring(wildcardIndex + 1)
909
910                                 // Create an entry string array.
911                                 val thirdPartyDoubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
912
913                                 // Add the entry to the blacklist.
914                                 thirdPartyInitialBlacklist.add(thirdPartyDoubleEntry)
915
916                                 //Log.i("Blocklists", headers.get(1)[0] + " third-party initial blacklist added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
917                             } else {  // Process a third-party initial blacklist single entry.
918                                 // Create an entry string array.
919                                 val singleEntry = arrayOf(entry, originalBlocklistEntry)
920
921                                 // Add the entry to the blacklist.
922                                 thirdPartyInitialBlacklist.add(singleEntry)
923
924                                 //Log.i("Blocklists", headers.get(1)[0] + " third-party initial blacklist added: " + entry + "  -  " + originalBlocklistEntry);
925                             }
926                         } else if (blocklistEntry.contains("\\")) {  // Process a regular expression blacklist entry.
927                             // Prepare a string to hold the entry.
928
929                             // Get the entry.
930                             val entry: String = if (blocklistEntry.contains("$/$")) {  // The first `$` is part of the regular expression.
931                                 blocklistEntry.substring(0, blocklistEntry.indexOf("$/$") + 2)
932                             } else {  // The only `$` indicates the filter options.
933                                 blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
934                             }
935
936                             // Create an entry string array.
937                             val singleEntry = arrayOf(entry, originalBlocklistEntry)
938
939                             // Add the entry to the blacklist.
940                             thirdPartyRegularExpressionBlacklist.add(singleEntry)
941
942                             //Log.i("Blocklists", headers.get(1)[0] + " third-party regular expression blacklist added: " + entry + "  -  " + originalBlocklistEntry);
943                         } else if (blocklistEntry.contains("*")) {  // Third-party and regular expression blacklist entries.
944                             // Get the entry.
945                             var entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
946
947                             if (entry.endsWith("*")) {  // Process a third-party blacklist single entry.
948                                 // Strip the final `*`.
949                                 entry = entry.substring(0, entry.length - 1)
950
951                                 // Create an entry string array.
952                                 val singleEntry = arrayOf(entry, originalBlocklistEntry)
953
954                                 // Add the entry to the blacklist.
955                                 thirdPartyBlacklist.add(singleEntry)
956
957                                 //Log.i("Blocklists", headers.get(1)[0] + " third party blacklist added: " + entry + "  -  " + originalBlocklistEntry);
958                             } else {  // There are two or more entries.
959                                 // Get the index of the wildcard.
960                                 val wildcardIndex = entry.indexOf("*")
961
962                                 // Split the entry into components.
963                                 val firstEntry = entry.substring(0, wildcardIndex)
964                                 val secondEntry = entry.substring(wildcardIndex + 1)
965
966                                 if (secondEntry.contains("*")) {  // There are three or more entries.
967                                     // Get the index of the wildcard.
968                                     val secondWildcardIndex = secondEntry.indexOf("*")
969
970                                     // Split the entry into components.
971                                     val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
972                                     val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
973
974                                     if (thirdEntry.contains("*")) {  // Process a third-party blacklist quadruple entry.
975                                         // Get the index of the wildcard.
976                                         val thirdWildcardIndex = thirdEntry.indexOf("*")
977
978                                         // Split the entry into components.
979                                         val realThirdEntry = thirdEntry.substring(0, thirdWildcardIndex)
980                                         val fourthEntry = thirdEntry.substring(thirdWildcardIndex + 1)
981
982                                         // Create an entry string array.
983                                         val quadrupleEntry = arrayOf(firstEntry, realSecondEntry, realThirdEntry, fourthEntry, originalBlocklistEntry)
984
985                                         // Add the entry to the blacklist.
986                                         thirdPartyBlacklist.add(quadrupleEntry)
987
988                                         //Log.i("Blocklists", headers.get(1)[0] + " third-party blacklist added: " + firstEntry + " , " + realSecondEntry + " , " + realThirdEntry + " , " +
989                                         //        fourthEntry + "  -  " + originalBlocklistEntry);
990                                     } else {  // Process a third-party blacklist triple entry.
991                                         // Create an entry string array.
992                                         val tripleEntry = arrayOf(firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
993
994                                         // Add the entry to the blacklist.
995                                         thirdPartyBlacklist.add(tripleEntry)
996
997                                         //Log.i("Blocklists", headers.get(1)[0] + " third-party blacklist added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + "  -  " +
998                                         //        originalBlocklistEntry);
999                                     }
1000                                 } else {  // Process a third-party blacklist double entry.
1001                                     // Create an entry string array.
1002                                     val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
1003
1004                                     // Add the entry to the blacklist.
1005                                     thirdPartyBlacklist.add(doubleEntry)
1006
1007                                     //Log.i("Blocklists", headers.get(1)[0] + " third-party blacklist added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1008                                 }
1009                             }
1010                         } else {  // Process a third party blacklist single entry.
1011                             // Get the entry.
1012                             val entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
1013
1014                             // Create an entry string array.
1015                             val singleEntry = arrayOf(entry, originalBlocklistEntry)
1016
1017                             // Add the entry to the blacklist.
1018                             thirdPartyBlacklist.add(singleEntry)
1019
1020                             //Log.i("Blocklists", headers.get(1)[0] + " third party blacklist added: " + entry + "  -  " + originalBlocklistEntry);
1021                         }
1022                     } else if (blocklistEntry.substring(blocklistEntry.indexOf("$")).contains("domain=")) {  // Domain entries.
1023                         if (blocklistEntry.contains("~")) {  // Domain whitelist entries.
1024                             // Separate the filters.
1025                             var entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
1026                             val filters = blocklistEntry.substring(blocklistEntry.indexOf("$") + 1)
1027                             var domains = filters.substring(filters.indexOf("domain=") + 7)
1028
1029                             // Strip any final `*` from the entry.  They are redundant.
1030                             if (entry.endsWith("*")) {
1031                                 entry = entry.substring(0, entry.length - 1)
1032                             }
1033
1034                             // Process each domain.
1035                             do {
1036                                 // Create a string to keep track of the current domain.
1037                                 var domain: String
1038
1039                                 if (domains.contains("|")) {  // There is more than one domain in the list.
1040                                     // Get the first domain from the list.
1041                                     domain = domains.substring(0, domains.indexOf("|"))
1042
1043                                     // Remove the first domain from the list.
1044                                     domains = domains.substring(domains.indexOf("|") + 1)
1045                                 } else {  // There is only one domain in the list.
1046                                     domain = domains
1047                                 }
1048
1049                                 // Strip the initial `~`.
1050                                 domain = domain.substring(1)
1051                                 if (entry.contains("*")) {  // There are two or more entries.
1052                                     // Get the index of the wildcard.
1053                                     val wildcardIndex = entry.indexOf("*")
1054
1055                                     // Split the entry into components.
1056                                     val firstEntry = entry.substring(0, wildcardIndex)
1057                                     val secondEntry = entry.substring(wildcardIndex + 1)
1058
1059                                     if (secondEntry.contains("*")) {  // Process a domain whitelist triple entry.
1060                                         // Get the index of the wildcard.
1061                                         val secondWildcardIndex = secondEntry.indexOf("*")
1062
1063                                         // Split the entry into components.
1064                                         val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
1065                                         val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
1066
1067                                         // Create an entry string array.
1068                                         val domainTripleEntry = arrayOf(domain, firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
1069
1070                                         // Add the entry to the whitelist.
1071                                         domainWhitelist.add(domainTripleEntry)
1072
1073                                         //Log.i("Blocklists", headers.get(1)[0] + " domain whitelist added: " + domain + " , " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry +
1074                                         //        "  -  " + originalBlocklistEntry);
1075                                     } else {  // Process a domain whitelist double entry.
1076                                         // Create an entry string array.
1077                                         val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
1078
1079                                         // Add the entry to the whitelist.
1080                                         domainWhitelist.add(domainDoubleEntry)
1081
1082                                         //Log.i("Blocklists", headers.get(1)[0] + " domain whitelist added: " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1083                                     }
1084                                 } else {  // Process a domain whitelist single entry.
1085                                     // Create an entry string array.
1086                                     val domainEntry = arrayOf(domain, entry, originalBlocklistEntry)
1087
1088                                     // Add the entry to the whitelist.
1089                                     domainWhitelist.add(domainEntry)
1090
1091                                     //Log.i("Blocklists", headers.get(1)[0] + " domain whitelist added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
1092                                 }
1093                             } while (domains.contains("|"))
1094                         } else {  // Domain blacklist entries.
1095                             // Separate the filters.
1096                             val entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
1097                             val filters = blocklistEntry.substring(blocklistEntry.indexOf("$") + 1)
1098                             var domains = filters.substring(filters.indexOf("domain=") + 7)
1099
1100                             // Only process the item if the entry is not null.  For example, some lines begin with `$websocket`, which create a null entry.
1101                             if (entry != "") {
1102                                 // Process each domain.
1103                                 do {
1104                                     // Create a string to keep track of the current domain.
1105                                     var domain: String
1106
1107                                     if (domains.contains("|")) {  // There is more than one domain in the list.
1108                                         // Get the first domain from the list.
1109                                         domain = domains.substring(0, domains.indexOf("|"))
1110
1111                                         // Remove the first domain from the list.
1112                                         domains = domains.substring(domains.indexOf("|") + 1)
1113                                     } else {  // There is only one domain in the list.
1114                                         domain = domains
1115                                     }
1116
1117                                     if (entry.startsWith("|")) {  // Domain initial blacklist entries.
1118                                         // Remove the initial `|`;
1119                                         val entryBase = entry.substring(1)
1120
1121                                         if (entryBase == "http://" || entryBase == "https://") {
1122                                             // Do nothing.  These entries will entirely block the website.
1123                                             // Often the original entry blocks `$script` but Privacy Browser does not currently differentiate between scripts and other entries.
1124
1125                                             //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
1126                                         } else {  // Process a domain initial blacklist entry
1127                                             // Create an entry string array.
1128                                             val domainEntry = arrayOf(domain, entryBase, originalBlocklistEntry)
1129
1130                                             // Add the entry to the blacklist.
1131                                             domainInitialBlacklist.add(domainEntry)
1132
1133                                             //Log.i("Blocklists", headers.get(1)[0] + " domain initial blacklist added: " + domain + " , " + entryBase + "  -  " + originalBlocklistEntry);
1134                                         }
1135                                     } else if (entry.endsWith("|")) {  // Domain final blacklist entries.
1136                                         // Remove the final `|`.
1137                                         val entryBase = entry.substring(0, entry.length - 1)
1138
1139                                         if (entryBase.contains("*")) {  // Process a domain final blacklist double entry.
1140                                             // Get the index of the wildcard.
1141                                             val wildcardIndex = entry.indexOf("*")
1142
1143                                             // Split the entry into components.
1144                                             val firstEntry = entryBase.substring(0, wildcardIndex)
1145                                             val secondEntry = entryBase.substring(wildcardIndex + 1)
1146
1147                                             // Create an entry string array.
1148                                             val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
1149
1150                                             // Add the entry to the blacklist.
1151                                             domainFinalBlacklist.add(domainDoubleEntry)
1152
1153                                             //Log.i("Blocklists", headers.get(1)[0] + " domain final blacklist added: " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " +
1154                                             //        originalBlocklistEntry);
1155                                         } else {  // Process a domain final blacklist single entry.
1156                                             // Create an entry string array.
1157                                             val domainEntry = arrayOf(domain, entryBase, originalBlocklistEntry)
1158
1159                                             // Add the entry to the blacklist.
1160                                             domainFinalBlacklist.add(domainEntry)
1161
1162                                             //Log.i("Blocklists", headers.get(1)[0] + " domain final blacklist added: " + domain + " , " + entryBase + "  -  " + originalBlocklistEntry);
1163                                         }
1164                                     } else if (entry.contains("\\")) {  // Process a domain regular expression blacklist entry.
1165                                         // Create an entry string array.
1166                                         val domainEntry = arrayOf(domain, entry, originalBlocklistEntry)
1167
1168                                         // Add the entry to the blacklist.
1169                                         domainRegularExpressionBlacklist.add(domainEntry)
1170
1171                                         //Log.i("Blocklists", headers.get(1)[0] + " domain regular expression blacklist added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
1172                                     } else if (entry.contains("*")) {  // There are two or more entries.
1173                                         // Get the index of the wildcard.
1174                                         val wildcardIndex = entry.indexOf("*")
1175
1176                                         // Split the entry into components.
1177                                         val firstEntry = entry.substring(0, wildcardIndex)
1178                                         val secondEntry = entry.substring(wildcardIndex + 1)
1179
1180                                         if (secondEntry.contains("*")) {  // Process a domain blacklist triple entry.
1181                                             // Get the index of the wildcard.
1182                                             val secondWildcardIndex = secondEntry.indexOf("*")
1183
1184                                             // Split the entry into components.
1185                                             val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
1186                                             val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
1187
1188                                             // Create an entry string array.
1189                                             val domainTripleEntry = arrayOf(domain, firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
1190
1191                                             // Add the entry to the blacklist.
1192                                             domainBlacklist.add(domainTripleEntry)
1193
1194                                             //Log.i("Blocklists", headers.get(1)[0] + " domain blacklist added: " + domain + " , " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry +
1195                                             //        "  -  " + originalBlocklistEntry);
1196                                         } else {  // Process a domain blacklist double entry.
1197                                             // Create an entry string array.
1198                                             val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
1199
1200                                             // Add the entry to the blacklist.
1201                                             domainBlacklist.add(domainDoubleEntry)
1202
1203                                             //Log.i("Blocklists", headers.get(1)[0] + " domain blacklist added: " + domain + " , " + firstEntry + " , " + secondEntry + "  -  " +
1204                                             //        originalBlocklistEntry);
1205                                         }
1206                                     } else {  // Process a domain blacklist single entry.
1207                                         // Create an entry string array.
1208                                         val domainEntry = arrayOf(domain, entry, originalBlocklistEntry)
1209
1210                                         // Add the entry to the blacklist.
1211                                         domainBlacklist.add(domainEntry)
1212
1213                                         //Log.i("Blocklists", headers.get(1)[0] + " domain blacklist added: " + domain + " , " + entry + "  -  " + originalBlocklistEntry);
1214                                     }
1215                                 } while (domains.contains("|"))
1216                             }
1217                         }
1218                     } else if (blocklistEntry.contains("~")) {  // Whitelist entries.  Privacy Browser does not differentiate against these filter options, so they are just generally whitelisted.
1219                         // Remove the filter options.
1220                         blocklistEntry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
1221
1222                         // Strip any trailing `*`.
1223                         if (blocklistEntry.endsWith("*")) {
1224                             blocklistEntry = blocklistEntry.substring(0, blocklistEntry.length - 1)
1225                         }
1226
1227                         if (blocklistEntry.contains("*")) {  // Process a whitelist double entry.
1228                             // Get the index of the wildcard.
1229                             val wildcardIndex = blocklistEntry.indexOf("*")
1230
1231                             // Split the entry into components.
1232                             val firstEntry = blocklistEntry.substring(0, wildcardIndex)
1233                             val secondEntry = blocklistEntry.substring(wildcardIndex + 1)
1234
1235                             // Create an entry string array.
1236                             val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
1237
1238                             // Add the entry to the whitelist.
1239                             mainWhitelist.add(doubleEntry)
1240
1241                             //Log.i("Blocklists", headers.get(1)[0] + " main whitelist added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1242                         } else {  // Process a whitelist single entry.
1243                             // Create an entry string array.
1244                             val singleEntry = arrayOf(blocklistEntry, originalBlocklistEntry)
1245
1246                             // Add the entry to the whitelist.
1247                             mainWhitelist.add(singleEntry)
1248
1249                             //Log.i("Blocklists", headers.get(1)[0] + " main whitelist added: " + blocklistEntry + "  -  + " + originalBlocklistEntry);
1250                         }
1251                     } else if (blocklistEntry.contains("\\")) {  // Process a regular expression blacklist entry.
1252                         // Remove the filter options.
1253                         blocklistEntry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
1254
1255                         // Create an entry string array.
1256                         val singleEntry = arrayOf(blocklistEntry, originalBlocklistEntry)
1257
1258                         // Add the entry to the blacklist.
1259                         regularExpressionBlacklist.add(singleEntry)
1260
1261                         //Log.i("Blocklists", headers.get(1)[0] + " regular expression blacklist added: " + blocklistEntry + "  -  " + originalBlocklistEntry);
1262                     } else {  // Blacklist entries.
1263                         // Remove the filter options.
1264                         if (!blocklistEntry.contains("\$file")) {  // EasyPrivacy contains an entry with `$file` that does not have filter options.
1265                             blocklistEntry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
1266                         }
1267
1268                         // Strip any trailing `*`.  These are redundant.
1269                         if (blocklistEntry.endsWith("*")) {
1270                             blocklistEntry = blocklistEntry.substring(0, blocklistEntry.length - 1)
1271                         }
1272
1273                         if (blocklistEntry.startsWith("|")) {  // Initial blacklist entries.
1274                             // Strip the initial `|`.
1275                             val entry = blocklistEntry.substring(1)
1276
1277                             if (entry.contains("*")) {  // Process an initial blacklist double entry.
1278                                 // Get the index of the wildcard.
1279                                 val wildcardIndex = entry.indexOf("*")
1280
1281                                 // Split the entry into components.
1282                                 val firstEntry = entry.substring(0, wildcardIndex)
1283                                 val secondEntry = entry.substring(wildcardIndex + 1)
1284
1285                                 // Create an entry string array.
1286                                 val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
1287
1288                                 // Add the entry to the blacklist.
1289                                 initialBlacklist.add(doubleEntry)
1290
1291                                 //Log.i("Blocklists", headers.get(1)[0] + " initial blacklist added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1292                             } else {  // Process an initial blacklist single entry.
1293                                 // Create an entry string array.
1294                                 val singleEntry = arrayOf(entry, originalBlocklistEntry)
1295
1296                                 // Add the entry to the blacklist.
1297                                 initialBlacklist.add(singleEntry)
1298
1299                                 //Log.i("Blocklists", headers.get(1)[0] + " initial blacklist added: " + entry + "  -  " + originalBlocklistEntry);
1300                             }
1301                         } else if (blocklistEntry.endsWith("|")) {  // Final blacklist entries.
1302                             // Ignore entries with `object` filters.  They can block entire websites and don't have any meaning in the context of Privacy Browser.
1303                             if (!originalBlocklistEntry.contains("\$object")) {
1304                                 // Strip the final `|`.
1305                                 val entry = blocklistEntry.substring(0, blocklistEntry.length - 1)
1306
1307                                 if (entry.contains("*")) {  // There are two or more entries.
1308                                     // Get the index of the wildcard.
1309                                     val wildcardIndex = entry.indexOf("*")
1310
1311                                     // Split the entry into components.
1312                                     val firstEntry = entry.substring(0, wildcardIndex)
1313                                     val secondEntry = entry.substring(wildcardIndex + 1)
1314
1315                                     if (secondEntry.contains("*")) {  // Process a final blacklist triple entry.
1316                                         // Get the index of the wildcard.
1317                                         val secondWildcardIndex = secondEntry.indexOf("*")
1318
1319                                         // Split the entry into components.
1320                                         val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
1321                                         val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
1322
1323                                         // Create an entry string array.
1324                                         val tripleEntry = arrayOf(firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
1325
1326                                         // Add the entry to the blacklist.
1327                                         finalBlacklist.add(tripleEntry)
1328
1329                                         //Log.i("Blocklists", headers.get(1)[0] + " final blacklist added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + "  -  " +
1330                                         //        originalBlocklistEntry);
1331                                     } else {  // Process a final blacklist double entry.
1332                                         // Create an entry string array.
1333                                         val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
1334
1335                                         // Add the entry to the blacklist.
1336                                         finalBlacklist.add(doubleEntry)
1337
1338                                         //Log.i("Blocklists", headers.get(1)[0] + " final blacklist added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1339                                     }
1340                                 } else {  // Process a final blacklist single entry.
1341                                     // Create an entry sting array.
1342                                     val singleEntry = arrayOf(entry, originalBlocklistEntry)
1343
1344                                     // Add the entry to the blacklist.
1345                                     finalBlacklist.add(singleEntry)
1346
1347                                     //Log.i("Blocklists", headers.get(1)[0] + " final blacklist added: " + entry + "  -  " + originalBlocklistEntry);
1348                                 }
1349                             }
1350                         } else if (blocklistEntry.contains("*")) {  // There are two or more entries.
1351                             // Get the index of the wildcard.
1352                             val wildcardIndex = blocklistEntry.indexOf("*")
1353
1354                             // Split the entry into components.
1355                             val firstEntry = blocklistEntry.substring(0, wildcardIndex)
1356                             val secondEntry = blocklistEntry.substring(wildcardIndex + 1)
1357
1358                             if (secondEntry.contains("*")) {  // Process a main blacklist triple entry.
1359                                 // Get the index of the wildcard.
1360                                 val secondWildcardIndex = secondEntry.indexOf("*")
1361
1362                                 // Split the entry into components.
1363                                 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
1364                                 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
1365
1366                                 // Create an entry string array.
1367                                 val tripleEntry = arrayOf(firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
1368
1369                                 // Add the entry to the blacklist.
1370                                 mainBlacklist.add(tripleEntry)
1371
1372                                 //Log.i("Blocklists", headers.get(1)[0] + " main blacklist added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + "  -  " + originalBlocklistEntry);
1373                             } else {  // Process a main blacklist double entry.
1374                                 // Create an entry string array.
1375                                 val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
1376
1377                                 // Add the entry to the blacklist.
1378                                 mainBlacklist.add(doubleEntry)
1379
1380                                 //Log.i("Blocklists", headers.get(1)[0] + " main blacklist added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1381                             }
1382                         } else {  // Process a main blacklist single entry.
1383                             // Create an entry string array.
1384                             val singleEntry = arrayOf(blocklistEntry, originalBlocklistEntry)
1385
1386                             // Add the entry to the blacklist.
1387                             mainBlacklist.add(singleEntry)
1388
1389                             //Log.i("Blocklists", headers.get(1)[0] + " main blacklist added: " + blocklistEntry + "  -  " + originalBlocklistEntry);
1390                         }
1391                     }
1392                 } else {  // Main blacklist entries
1393                     // Strip out any initial `||`.  These will be treated like any other entry.
1394                     if (blocklistEntry.startsWith("||")) {
1395                         blocklistEntry = blocklistEntry.substring(2)
1396                     }
1397
1398                     // Strip out any initial `*`.
1399                     if (blocklistEntry.startsWith("*")) {
1400                         blocklistEntry = blocklistEntry.substring(1)
1401                     }
1402
1403                     // Strip out any trailing `*`.
1404                     if (blocklistEntry.endsWith("*")) {
1405                         blocklistEntry = blocklistEntry.substring(0, blocklistEntry.length - 1)
1406                     }
1407
1408                     if (blocklistEntry.startsWith("|")) {  // Initial blacklist entries.
1409                         // Strip the initial `|`.
1410                         val entry = blocklistEntry.substring(1)
1411
1412                         if (entry.contains("*")) {  // Process an initial blacklist double entry.
1413                             // Get the index of the wildcard.
1414                             val wildcardIndex = entry.indexOf("*")
1415
1416                             // Split the entry into components.
1417                             val firstEntry = entry.substring(0, wildcardIndex)
1418                             val secondEntry = entry.substring(wildcardIndex + 1)
1419
1420                             // Create an entry string array.
1421                             val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
1422
1423                             // Add the entry to the blacklist.
1424                             initialBlacklist.add(doubleEntry)
1425
1426                             //Log.i("Blocklists", headers.get(1)[0] + " initial blacklist added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1427                         } else {  // Process an initial blacklist single entry.
1428                             // Create an entry string array.
1429                             val singleEntry = arrayOf(entry, originalBlocklistEntry)
1430
1431                             // Add the entry to the blacklist.
1432                             initialBlacklist.add(singleEntry)
1433
1434                             //Log.i("Blocklists", headers.get(1)[0] + " initial blacklist added: " + entry + "  -  " + originalBlocklistEntry);
1435                         }
1436                     } else if (blocklistEntry.endsWith("|")) {  // Final blacklist entries.
1437                         // Strip the final `|`.
1438                         val entry = blocklistEntry.substring(0, blocklistEntry.length - 1)
1439
1440                         if (entry.contains("*")) {  // There are two or more entries.
1441                             // Get the index of the wildcard.
1442                             val wildcardIndex = entry.indexOf("*")
1443
1444                             // Split the entry into components.
1445                             val firstEntry = entry.substring(0, wildcardIndex)
1446                             val secondEntry = entry.substring(wildcardIndex + 1)
1447
1448                             if (secondEntry.contains("*")) {  // Process a final blacklist triple entry.
1449                                 // Get the index of the wildcard.
1450                                 val secondWildcardIndex = secondEntry.indexOf("*")
1451
1452                                 // Split the entry into components.
1453                                 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
1454                                 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
1455
1456                                 // Create an entry string array.
1457                                 val tripleEntry = arrayOf(firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
1458
1459                                 // Add the entry to the blacklist.
1460                                 finalBlacklist.add(tripleEntry)
1461
1462                                 //Log.i("Blocklists", headers.get(1)[0] + " final blacklist added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + "  -  " + originalBlocklistEntry);
1463                             } else {  // Process a final blacklist double entry.
1464                                 // Create an entry string array.
1465                                 val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
1466
1467                                 // Add the entry to the blacklist.
1468                                 finalBlacklist.add(doubleEntry)
1469
1470                                 //Log.i("Blocklists", headers.get(1)[0] + " final blacklist added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1471                             }
1472                         } else {  // Process a final blacklist single entry.
1473                             // Create an entry string array.
1474                             val singleEntry = arrayOf(entry, originalBlocklistEntry)
1475
1476                             // Add the entry to the blacklist.
1477                             finalBlacklist.add(singleEntry)
1478
1479                             //Log.i("Blocklists", headers.get(1)[0] + " final blacklist added: " + entry + "  -  " + originalBlocklistEntry);
1480                         }
1481                     } else {  // Main blacklist entries.
1482                         if (blocklistEntry.contains("*")) {  // There are two or more entries.
1483                             // Get the index of the wildcard.
1484                             val wildcardIndex = blocklistEntry.indexOf("*")
1485
1486                             // Split the entry into components.
1487                             val firstEntry = blocklistEntry.substring(0, wildcardIndex)
1488                             val secondEntry = blocklistEntry.substring(wildcardIndex + 1)
1489
1490                             if (secondEntry.contains("*")) {  // There are three or more entries.
1491                                 // Get the index of the wildcard.
1492                                 val secondWildcardIndex = secondEntry.indexOf("*")
1493
1494                                 // Split the entry into components.
1495                                 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
1496                                 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
1497
1498                                 if (thirdEntry.contains("*")) {  // There are four or more entries.
1499                                     // Get the index of the wildcard.
1500                                     val thirdWildcardIndex = thirdEntry.indexOf("*")
1501
1502                                     // Split the entry into components.
1503                                     val realThirdEntry = thirdEntry.substring(0, thirdWildcardIndex)
1504                                     val fourthEntry = thirdEntry.substring(thirdWildcardIndex + 1)
1505
1506                                     if (fourthEntry.contains("*")) {  // Process a main blacklist quintuple entry.
1507                                         // Get the index of the wildcard.
1508                                         val fourthWildcardIndex = fourthEntry.indexOf("*")
1509
1510                                         // Split the entry into components.
1511                                         val realFourthEntry = fourthEntry.substring(0, fourthWildcardIndex)
1512                                         val fifthEntry = fourthEntry.substring(fourthWildcardIndex + 1)
1513
1514                                         // Create an entry string array.
1515                                         val quintupleEntry = arrayOf(firstEntry, realSecondEntry, realThirdEntry, realFourthEntry, fifthEntry, originalBlocklistEntry)
1516
1517                                         // Add the entry to the blacklist.
1518                                         mainBlacklist.add(quintupleEntry)
1519
1520                                         //Log.i("Blocklists", headers.get(1)[0] + " main blacklist added: " + firstEntry + " , " + realSecondEntry + " , " + realThirdEntry + " , " + realFourthEntry + " , " +
1521                                         //      fifthEntry + "  -  " + originalBlocklistEntry);
1522                                     } else {  // Process a main blacklist quadruple entry.
1523                                         // Create an entry string array.
1524                                         val quadrupleEntry = arrayOf(firstEntry, realSecondEntry, realThirdEntry, fourthEntry, originalBlocklistEntry)
1525
1526                                         // Add the entry to the blacklist.
1527                                         mainBlacklist.add(quadrupleEntry)
1528
1529                                         //Log.i("Blocklists", headers.get(1)[0] + " main blacklist added: " + firstEntry + " , " + realSecondEntry + " , " + realThirdEntry + " , " + fourthEntry + "  -  " +
1530                                         //      originalBlocklistEntry);
1531                                     }
1532                                 } else {  // Process a main blacklist triple entry.
1533                                     // Create an entry string array.
1534                                     val tripleEntry = arrayOf(firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
1535
1536                                     // Add the entry to the blacklist.
1537                                     mainBlacklist.add(tripleEntry)
1538
1539                                     //Log.i("Blocklists", headers.get(1)[0] + " main blacklist added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + "  -  " + originalBlocklistEntry);
1540                                 }
1541                             } else {  // Process a main blacklist double entry.
1542                                 // Create an entry string array.
1543                                 val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
1544
1545                                 // Add the entry to the blacklist.
1546                                 mainBlacklist.add(doubleEntry)
1547
1548                                 //Log.i("Blocklists", headers.get(1)[0] + " main blacklist added: " + firstEntry + " , " + secondEntry + "  -  " + originalBlocklistEntry);
1549                             }
1550                         } else {  // Process a main blacklist single entry.
1551                             // Create an entry string array.
1552                             val singleEntry = arrayOf(blocklistEntry, originalBlocklistEntry)
1553
1554                             // Add the entry to the blacklist.
1555                             mainBlacklist.add(singleEntry)
1556
1557                             //Log.i("Blocklists", headers.get(1)[0] + " main blacklist added: " + blocklistEntry + "  -  " + originalBlocklistEntry);
1558                         }
1559                     }
1560                 }
1561             }
1562             // Close `bufferedReader`.
1563             bufferedReader.close()
1564         } catch (e: IOException) {
1565             // The asset exists, so the `IOException` will never be thrown.
1566         }
1567
1568         // Initialize the combined list.
1569         val combinedLists = ArrayList<List<Array<String>>>()
1570
1571         // Add the headers (0).
1572         combinedLists.add(headers) // 0.
1573
1574         // Add the whitelists (1-8).
1575         combinedLists.add(mainWhitelist) // 1.
1576         combinedLists.add(finalWhitelist) // 2.
1577         combinedLists.add(domainWhitelist) // 3.
1578         combinedLists.add(domainInitialWhitelist) // 4.
1579         combinedLists.add(domainFinalWhitelist) // 5.
1580         combinedLists.add(thirdPartyWhitelist) // 6.
1581         combinedLists.add(thirdPartyDomainWhitelist) // 7.
1582         combinedLists.add(thirdPartyDomainInitialWhitelist) // 8.
1583
1584         // Add the blacklists (9-22).
1585         combinedLists.add(mainBlacklist) // 9.
1586         combinedLists.add(initialBlacklist) // 10.
1587         combinedLists.add(finalBlacklist) // 11.
1588         combinedLists.add(domainBlacklist) //  12.
1589         combinedLists.add(domainInitialBlacklist) // 13.
1590         combinedLists.add(domainFinalBlacklist) // 14.
1591         combinedLists.add(domainRegularExpressionBlacklist) // 15.
1592         combinedLists.add(thirdPartyBlacklist) // 16.
1593         combinedLists.add(thirdPartyInitialBlacklist) // 17.
1594         combinedLists.add(thirdPartyDomainBlacklist) // 18.
1595         combinedLists.add(thirdPartyDomainInitialBlacklist) // 19.
1596         combinedLists.add(thirdPartyRegularExpressionBlacklist) // 20.
1597         combinedLists.add(thirdPartyDomainRegularExpressionBlacklist) // 21.
1598         combinedLists.add(regularExpressionBlacklist) // 22.
1599
1600         // Return the combined lists.
1601         return combinedLists
1602     }
1603 }