2 * Copyright 2018-2019,2021-2023 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
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.
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.
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/>.
20 package com.stoutner.privacybrowser.helpers
22 import android.content.res.AssetManager
24 import java.io.BufferedReader
25 import java.io.IOException
26 import java.io.InputStreamReader
27 import java.util.ArrayList
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
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"
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"
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.
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.
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.
94 // Populate the blocklists. The `try` is required by input stream reader.
96 // Load the blocklist into a buffered reader.
97 val bufferedReader = BufferedReader(InputStreamReader(assetManager.open(blocklistName)))
99 // Create strings for storing the block list entries.
100 var blocklistEntry: String
101 var originalBlocklistEntry: String
103 // Parse the block list.
104 bufferedReader.forEachLine {
105 // Store the original block list entry.
106 originalBlocklistEntry = it
108 // Remove any `^` from the block list entry. Privacy Browser does not process them in the interest of efficiency.
109 blocklistEntry = it.replace("^", "")
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.
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.
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.
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))
131 // Store the list version in the headers list.
132 headers.add(listVersion)
135 if (blocklistEntry.startsWith("! Title:")) {
136 // Get the list title.
137 val listTitle = arrayOf(blocklistEntry.substring(9))
139 // Store the list title in the headers list.
140 headers.add(listTitle)
143 //Log.i("Blocklists", "Not added: " + blocklistEntry);
144 } else if (blocklistEntry.startsWith("@@")) { // Entries that begin with `@@` are whitelists.
146 blocklistEntry = blocklistEntry.substring(2)
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)
153 if (blocklistEntry.contains("$")) { // Filter entries.
154 if (blocklistEntry.contains("~third-party")) { // Ignore entries that contain `~third-party`.
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.
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)
165 if (domains.contains("~")) { // It is uncertain what a `~` domain means inside an `@@` entry.
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)
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.
176 //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
177 } else { // Process third-party domain initial whitelist entries.
178 // Process each domain.
180 // Create a string to keep track of the current domain.
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("|"))
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.
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("*")
197 // Split the entry into components.
198 val firstEntry = entry.substring(0, wildcardIndex)
199 val secondEntry = entry.substring(wildcardIndex + 1)
201 // Create an entry string array.
202 val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
204 // Add the entry to the whitelist.
205 thirdPartyDomainInitialWhitelist.add(domainDoubleEntry)
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)
213 // Add the entry to the third party domain initial whitelist.
214 thirdPartyDomainInitialWhitelist.add(domainEntry)
216 //Log.i("Blocklists", headers.get(1)[0] + " third-party domain initial whitelist added: " + domain + " , " + entry + " - " + originalBlocklistEntry);
218 } while (domains.contains("|"))
220 } else { // Third-party domain entries.
221 // Process each domain.
223 // Create a string to keep track of the current domain.
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("|"))
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.
236 // Remove any trailing `*` from the entry.
237 if (entry.endsWith("*")) {
238 entry = entry.substring(0, entry.length - 1)
241 if (entry.contains("*")) { // Process a third-party domain double entry.
242 // Get the index of the wildcard.
243 val wildcardIndex = entry.indexOf("*")
245 // Split the entry into components.
246 val firstEntry = entry.substring(0, wildcardIndex)
247 val secondEntry = entry.substring(wildcardIndex + 1)
249 // Create an entry string array.
250 val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
252 // Add the entry to the whitelist.
253 thirdPartyDomainWhitelist.add(domainDoubleEntry)
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)
261 // Add the entry to the whitelist.
262 thirdPartyDomainWhitelist.add(domainEntry)
264 //Log.i("Blocklists", headers.get(1)[0] + " third-party domain whitelist added: " + domain + " , " + entry + " - " + originalBlocklistEntry);
266 } while (domains.contains("|"))
268 } else { // Process third-party whitelist entries.
270 val entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
272 if (entry.contains("*")) { // There are two or more entries.
273 // Get the index of the wildcard.
274 val wildcardIndex = entry.indexOf("*")
276 // Split the entry into components.
277 val firstEntry = entry.substring(0, wildcardIndex)
278 val secondEntry = entry.substring(wildcardIndex + 1)
280 if (secondEntry.contains("*")) { // There are three or more entries.
281 // Get the index of the wildcard.
282 val secondWildcardIndex = secondEntry.indexOf("*")
284 // Split the entry into components.
285 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
286 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
288 if (thirdEntry.contains("*")) { // There are four or more entries.
289 // Get the index of the wildcard.
290 val thirdWildcardIndex = thirdEntry.indexOf("*")
292 // Split the entry into components.
293 val realThirdEntry = thirdEntry.substring(0, thirdWildcardIndex)
294 val fourthEntry = thirdEntry.substring(thirdWildcardIndex + 1)
296 if (fourthEntry.contains("*")) { // Process a third-party whitelist quintuple entry.
297 // Get the index of the wildcard.
298 val fourthWildcardIndex = fourthEntry.indexOf("*")
300 // Split the entry into components.
301 val realFourthEntry = fourthEntry.substring(0, fourthWildcardIndex)
302 val fifthEntry = fourthEntry.substring(fourthWildcardIndex + 1)
304 // Create an entry string array.
305 val quintupleEntry = arrayOf(firstEntry, realSecondEntry, realThirdEntry, realFourthEntry, fifthEntry, originalBlocklistEntry)
307 // Add the entry to the whitelist.
308 thirdPartyWhitelist.add(quintupleEntry)
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)
316 // Add the entry to the whitelist.
317 thirdPartyWhitelist.add(quadrupleEntry)
319 //Log.i("Blocklists", headers.get(1)[0] + " third-party whitelist added: " + firstEntry + " , " + realSecondEntry + " , " + realThirdEntry + " , " +
320 // fourthEntry + " - " + originalBlocklistEntry);
322 } else { // Process a third-party whitelist triple entry.
323 // Create an entry string array.
324 val tripleEntry = arrayOf(firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
326 // Add the entry to the whitelist.
327 thirdPartyWhitelist.add(tripleEntry)
329 //Log.i("Blocklists", headers.get(1)[0] + " third-party whitelist added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + " - " +
330 // originalBlocklistEntry);
332 } else { // Process a third-party whitelist double entry.
333 // Create an entry string array.
334 val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
336 // Add the entry to the whitelist.
337 thirdPartyWhitelist.add(doubleEntry)
339 //Log.i("Blocklists", headers.get(1)[0] + " third-party whitelist added: " + firstEntry + " , " + secondEntry + " - " + originalBlocklistEntry);
341 } else { // Process a third-party whitelist single entry.
342 // Create an entry string array.
343 val singleEntry = arrayOf(entry, originalBlocklistEntry)
345 // Add the entry to the whitelist.
346 thirdPartyWhitelist.add(singleEntry)
348 //Log.i("Blocklists", headers.get(1)[0] + " third-party domain whitelist added: " + entry + " - " + originalBlocklistEntry);
351 } else if (blocklistEntry.contains("domain=")) { // Process domain whitelist entries.
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)
357 if (entry.startsWith("|")) { // Initial domain whitelist entries.
358 // Strip the initial `|`.
359 entry = entry.substring(1)
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.
364 //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
365 } else { // Initial domain whitelist entry.
366 // Process each domain.
368 // Create a string to keep track of the current domain.
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("|"))
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.
381 if (entry.contains("*")) { // There are two or more entries.
382 // Get the index of the wildcard.
383 val wildcardIndex = entry.indexOf("*")
385 // Split the entry into components.
386 val firstEntry = entry.substring(0, wildcardIndex)
387 val secondEntry = entry.substring(wildcardIndex + 1)
389 if (secondEntry.contains("*")) { // Process a domain initial triple entry.
390 // Get the index of the wildcard.
391 val secondWildcardIndex = secondEntry.indexOf("*")
393 // Split the entry into components.
394 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
395 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
397 // Create an entry string array.
398 val domainTripleEntry = arrayOf(domain, firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
400 // Add the entry to the whitelist.
401 domainInitialWhitelist.add(domainTripleEntry)
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)
409 // Add the entry to the whitelist.
410 domainInitialWhitelist.add(domainDoubleEntry)
412 //Log.i("Blocklists", headers.get(1)[0] + " domain initial whitelist entry added: " + domain + " , " + firstEntry + " , " + secondEntry + " - " +
413 // originalBlocklistEntry);
415 } else { // Process a domain initial single entry.
416 // Create an entry string array.
417 val domainEntry = arrayOf(domain, entry, originalBlocklistEntry)
419 // Add the entry to the whitelist.
420 domainInitialWhitelist.add(domainEntry)
422 //Log.i("Blocklists", headers.get(1)[0] + " domain initial whitelist entry added: " + domain + " , " + entry + " - " + originalBlocklistEntry);
424 } while (domains.contains("|"))
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)
430 // Process each domain.
432 // Create a string to keep track of the current domain.
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("|"))
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.
445 if (entry.contains("*")) { // Process a domain final whitelist double entry.
446 // Get the index of the wildcard.
447 val wildcardIndex = entry.indexOf("*")
449 // Split the entry into components.
450 val firstEntry = entry.substring(0, wildcardIndex)
451 val secondEntry = entry.substring(wildcardIndex + 1)
453 // Create an entry string array.
454 val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
456 // Add the entry to the whitelist.
457 domainFinalWhitelist.add(domainDoubleEntry)
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)
465 // Add the entry to the whitelist.
466 domainFinalWhitelist.add(domainEntry)
468 //Log.i("Blocklists", headers.get(1)[0] + " domain final whitelist added: " + domain + " , " + entry + " - " + originalBlocklistEntry);
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.
475 //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
477 // Process each domain.
479 // Create a string to keep track of the current domain.
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("|"))
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.
492 if (entry.contains("*")) { // There are two or more entries.
493 // Get the index of the wildcard.
494 val wildcardIndex = entry.indexOf("*")
496 // Split the entry into components.
497 val firstEntry = entry.substring(0, wildcardIndex)
498 val secondEntry = entry.substring(wildcardIndex + 1)
500 if (secondEntry.contains("*")) { // There are three or more entries.
501 // Get the index of the wildcard.
502 val secondWildcardIndex = secondEntry.indexOf("*")
504 // Split the entry into components.
505 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
506 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
508 if (thirdEntry.contains("*")) { // Process a domain whitelist quadruple entry.
509 // Get the index of the wildcard.
510 val thirdWildcardIndex = thirdEntry.indexOf("*")
512 // Split the entry into components.
513 val realThirdEntry = thirdEntry.substring(0, thirdWildcardIndex)
514 val fourthEntry = thirdEntry.substring(thirdWildcardIndex + 1)
516 // Create an entry string array.
517 val domainQuadrupleEntry = arrayOf(domain, firstEntry, realSecondEntry, realThirdEntry, fourthEntry, originalBlocklistEntry)
519 // Add the entry to the whitelist.
520 domainWhitelist.add(domainQuadrupleEntry)
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)
528 // Add the entry to the whitelist.
529 domainWhitelist.add(domainTripleEntry)
531 //Log.i("Blocklists", headers.get(1)[0] + " domain whitelist added : " + domain + " , " + firstEntry + " , " + realSecondEntry + " , " +
532 // thirdEntry + " - " + originalBlocklistEntry);
534 } else { // Process a domain whitelist double entry.
535 // Create an entry string array.
536 val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
538 // Add the entry to the whitelist.
539 domainWhitelist.add(domainDoubleEntry)
541 //Log.i("Blocklists", headers.get(1)[0] + " domain whitelist added : " + domain + " , " + firstEntry + " , " + secondEntry + " - " +
542 // originalBlocklistEntry);
544 } else { // Process a domain whitelist single entry.
545 // Create an entry string array.
546 val domainEntry = arrayOf(domain, entry, originalBlocklistEntry)
548 // Add the entry to the whitelist.
549 domainWhitelist.add(domainEntry)
551 //Log.i("Blocklists", headers.get(1)[0] + " domain whitelist added : " + domain + " , " + entry + " - " + originalBlocklistEntry);
553 } while (domains.contains("|"))
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)
561 if (entry.contains("*")) { // Process a final whitelist double entry
562 // Get the index of the wildcard.
563 val wildcardIndex = entry.indexOf("*")
565 // split the entry into components.
566 val firstEntry = entry.substring(0, wildcardIndex)
567 val secondEntry = entry.substring(wildcardIndex + 1)
569 // Create an entry string array.
570 val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
572 // Add the entry to the whitelist.
573 finalWhitelist.add(doubleEntry)
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)
580 // Add the entry to the whitelist.
581 finalWhitelist.add(singleEntry)
583 //Log.i("Blocklists", headers.get(1)[0] + " final whitelist added: " + entry + " - " + originalBlocklistEntry);
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("*")
590 // Split the entry into components.
591 val firstEntry = blocklistEntry.substring(0, wildcardIndex)
592 val secondEntry = blocklistEntry.substring(wildcardIndex + 1)
594 if (secondEntry.contains("*")) { // Process a main whitelist triple entry.
595 // Get the index of the wildcard.
596 val secondWildcardIndex = secondEntry.indexOf("*")
598 // Split the entry into components.
599 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
600 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
602 // Create an entry string array.
603 val tripleEntry = arrayOf(firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
605 // Add the entry to the whitelist.
606 mainWhitelist.add(tripleEntry)
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)
613 // Add the entry to the whitelist.
614 mainWhitelist.add(doubleEntry)
616 //Log.i("Blocklists", headers.get(1)[0] + " main whitelist added: " + firstEntry + " , " + secondEntry + " - " + originalBlocklistEntry);
618 } else { // Process a main whitelist single entry.
619 // Create an entry string array.
620 val singleEntry = arrayOf(blocklistEntry, originalBlocklistEntry)
622 // Add the entry to the whitelist.
623 mainWhitelist.add(singleEntry)
625 //Log.i("Blocklists", headers.get(1)[0] + " main whitelist added: " + blocklistEntry + " - " + originalBlocklistEntry);
628 } else if (blocklistEntry.endsWith("|")) { // Final blacklist entries.
629 // Strip out the final "|"
630 var entry = blocklistEntry.substring(0, blocklistEntry.length - 1)
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)
637 if (entry.contains("*")) { // Process a final blacklist double entry.
638 // Get the index of the wildcard.
639 val wildcardIndex = entry.indexOf("*")
641 // Split the entry into components.
642 val firstEntry = entry.substring(0, wildcardIndex)
643 val secondEntry = entry.substring(wildcardIndex + 1)
645 // Create an entry string array.
646 val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
648 // Add the entry to the blacklist.
649 finalBlacklist.add(doubleEntry)
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)
656 // Add the entry to the blacklist.
657 finalBlacklist.add(singleEntry)
659 //Log.i("Blocklists", headers.get(1)[0] + " final blacklist added: " + entry + " - " + originalBlocklistEntry);
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)
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`.
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)
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)
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.
686 //Log.i("Blocklists", headers.get(1)[0] + " not added: " + originalBlocklistEntry);
687 } else { // Third-party domain initial entries.
688 // Process each domain.
690 // Create a string to keep track of the current domain.
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("|"))
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.
703 if (entry.contains("*")) { // Three are two or more entries.
704 // Get the index of the wildcard.
705 val wildcardIndex = entry.indexOf("*")
707 // Split the entry into components.
708 val firstEntry = entry.substring(0, wildcardIndex)
709 val secondEntry = entry.substring(wildcardIndex + 1)
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("*")
715 // Split the entry into components.
716 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
717 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
719 // Create an entry string array.
720 val tripleDomainEntry = arrayOf(domain, firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
722 // Add the entry to the blacklist.
723 thirdPartyDomainInitialBlacklist.add(tripleDomainEntry)
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)
731 // Add the entry to the blacklist.
732 thirdPartyDomainInitialBlacklist.add(doubleDomainEntry)
734 //Log.i("Blocklists", headers.get(1)[0] + " third-party domain initial blacklist added: " + domain + " , " + firstEntry + " , " + secondEntry +
735 // " - " + originalBlocklistEntry);
737 } else { // Process a third-party domain initial blacklist single entry.
738 // Create an entry string array.
739 val singleEntry = arrayOf(domain, entry, originalBlocklistEntry)
741 // Add the entry to the blacklist.
742 thirdPartyDomainInitialBlacklist.add(singleEntry)
744 //Log.i("Blocklists", headers.get(1)[0] + " third-party domain initial blacklist added: " + domain + " , " + entry + " - " + originalBlocklistEntry);
746 } while (domains.contains("|"))
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)
754 // Process each domain.
756 // Create a string to keep track of the current domain.
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("|"))
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.
769 // Create an entry string array.
770 val domainEntry = arrayOf(domain, entry, originalBlocklistEntry)
772 // Add the entry to the blacklist.
773 thirdPartyDomainRegularExpressionBlacklist.add(domainEntry)
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.
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)
783 // Strip any trailing "*" from the entry.
784 if (entry.endsWith("*")) {
785 entry = entry.substring(0, entry.length - 1)
788 // Track if any third-party whitelist filters are applied.
789 var whitelistDomain = false
791 // Process each domain.
793 // Create a string to keep track of the current domain.
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("|"))
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.
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)
811 // Set the whitelist domain flag.
812 whitelistDomain = true
814 if (entry.contains("*")) { // Process a third-party domain whitelist double entry.
815 // Get the index of the wildcard.
816 val wildcardIndex = entry.indexOf("*")
818 // Split the entry into components.
819 val firstEntry = entry.substring(0, wildcardIndex)
820 val secondEntry = entry.substring(wildcardIndex + 1)
822 // Create an entry string array.
823 val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
825 // Add the entry to the whitelist.
826 thirdPartyDomainWhitelist.add(domainDoubleEntry)
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)
834 // Add the entry to the whitelist.
835 thirdPartyDomainWhitelist.add(domainEntry)
837 //Log.i("Blocklists", headers.get(1)[0] + " third-party domain whitelist added: " + domain + " , " + entry + " - " + originalBlocklistEntry);
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("*")
844 // Split the entry into components.
845 val firstEntry = entry.substring(0, wildcardIndex)
846 val secondEntry = entry.substring(wildcardIndex + 1)
848 // Create an entry string array.
849 val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
851 // Add the entry to the blacklist
852 thirdPartyDomainBlacklist.add(domainDoubleEntry)
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)
860 // Add the entry to the blacklist.
861 thirdPartyDomainBlacklist.add(domainEntry)
863 //Log.i("Blocklists", headers.get(1)[0] + " third-party domain blocklist added: " + domain + " , " + entry + " - " + originalBlocklistEntry);
866 } while (domains.contains("|"))
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("*")
874 // Split the entry into components.
875 val firstEntry = entry.substring(0, wildcardIndex)
876 val secondEntry = entry.substring(wildcardIndex + 1)
878 // Create an entry string array.
879 val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
881 // Add the entry to the blacklist.
882 thirdPartyBlacklist.add(doubleEntry)
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)
889 // Add an entry to the blacklist.
890 thirdPartyBlacklist.add(singleEntry)
892 //Log.i("Blocklists", headers.get(1)[0] + " third-party blacklist added: " + entry + " - " + originalBlocklistEntry);
896 } else if (blocklistEntry.startsWith("|")) { // Third-party initial blacklist entries.
897 // Strip the initial `|`.
898 blocklistEntry = blocklistEntry.substring(1)
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("*")
906 // Split the entry into components.
907 val firstEntry = entry.substring(0, wildcardIndex)
908 val secondEntry = entry.substring(wildcardIndex + 1)
910 // Create an entry string array.
911 val thirdPartyDoubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
913 // Add the entry to the blacklist.
914 thirdPartyInitialBlacklist.add(thirdPartyDoubleEntry)
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)
921 // Add the entry to the blacklist.
922 thirdPartyInitialBlacklist.add(singleEntry)
924 //Log.i("Blocklists", headers.get(1)[0] + " third-party initial blacklist added: " + entry + " - " + originalBlocklistEntry);
926 } else if (blocklistEntry.contains("\\")) { // Process a regular expression blacklist entry.
927 // Prepare a string to hold 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("$"))
936 // Create an entry string array.
937 val singleEntry = arrayOf(entry, originalBlocklistEntry)
939 // Add the entry to the blacklist.
940 thirdPartyRegularExpressionBlacklist.add(singleEntry)
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.
945 var entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
947 if (entry.endsWith("*")) { // Process a third-party blacklist single entry.
948 // Strip the final `*`.
949 entry = entry.substring(0, entry.length - 1)
951 // Create an entry string array.
952 val singleEntry = arrayOf(entry, originalBlocklistEntry)
954 // Add the entry to the blacklist.
955 thirdPartyBlacklist.add(singleEntry)
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("*")
962 // Split the entry into components.
963 val firstEntry = entry.substring(0, wildcardIndex)
964 val secondEntry = entry.substring(wildcardIndex + 1)
966 if (secondEntry.contains("*")) { // There are three or more entries.
967 // Get the index of the wildcard.
968 val secondWildcardIndex = secondEntry.indexOf("*")
970 // Split the entry into components.
971 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
972 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
974 if (thirdEntry.contains("*")) { // Process a third-party blacklist quadruple entry.
975 // Get the index of the wildcard.
976 val thirdWildcardIndex = thirdEntry.indexOf("*")
978 // Split the entry into components.
979 val realThirdEntry = thirdEntry.substring(0, thirdWildcardIndex)
980 val fourthEntry = thirdEntry.substring(thirdWildcardIndex + 1)
982 // Create an entry string array.
983 val quadrupleEntry = arrayOf(firstEntry, realSecondEntry, realThirdEntry, fourthEntry, originalBlocklistEntry)
985 // Add the entry to the blacklist.
986 thirdPartyBlacklist.add(quadrupleEntry)
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)
994 // Add the entry to the blacklist.
995 thirdPartyBlacklist.add(tripleEntry)
997 //Log.i("Blocklists", headers.get(1)[0] + " third-party blacklist added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + " - " +
998 // originalBlocklistEntry);
1000 } else { // Process a third-party blacklist double entry.
1001 // Create an entry string array.
1002 val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
1004 // Add the entry to the blacklist.
1005 thirdPartyBlacklist.add(doubleEntry)
1007 //Log.i("Blocklists", headers.get(1)[0] + " third-party blacklist added: " + firstEntry + " , " + secondEntry + " - " + originalBlocklistEntry);
1010 } else { // Process a third party blacklist single entry.
1012 val entry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
1014 // Create an entry string array.
1015 val singleEntry = arrayOf(entry, originalBlocklistEntry)
1017 // Add the entry to the blacklist.
1018 thirdPartyBlacklist.add(singleEntry)
1020 //Log.i("Blocklists", headers.get(1)[0] + " third party blacklist added: " + entry + " - " + originalBlocklistEntry);
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)
1029 // Strip any final `*` from the entry. They are redundant.
1030 if (entry.endsWith("*")) {
1031 entry = entry.substring(0, entry.length - 1)
1034 // Process each domain.
1036 // Create a string to keep track of the current domain.
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("|"))
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.
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("*")
1055 // Split the entry into components.
1056 val firstEntry = entry.substring(0, wildcardIndex)
1057 val secondEntry = entry.substring(wildcardIndex + 1)
1059 if (secondEntry.contains("*")) { // Process a domain whitelist triple entry.
1060 // Get the index of the wildcard.
1061 val secondWildcardIndex = secondEntry.indexOf("*")
1063 // Split the entry into components.
1064 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
1065 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
1067 // Create an entry string array.
1068 val domainTripleEntry = arrayOf(domain, firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
1070 // Add the entry to the whitelist.
1071 domainWhitelist.add(domainTripleEntry)
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)
1079 // Add the entry to the whitelist.
1080 domainWhitelist.add(domainDoubleEntry)
1082 //Log.i("Blocklists", headers.get(1)[0] + " domain whitelist added: " + domain + " , " + firstEntry + " , " + secondEntry + " - " + originalBlocklistEntry);
1084 } else { // Process a domain whitelist single entry.
1085 // Create an entry string array.
1086 val domainEntry = arrayOf(domain, entry, originalBlocklistEntry)
1088 // Add the entry to the whitelist.
1089 domainWhitelist.add(domainEntry)
1091 //Log.i("Blocklists", headers.get(1)[0] + " domain whitelist added: " + domain + " , " + entry + " - " + originalBlocklistEntry);
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)
1100 // Only process the item if the entry is not null. For example, some lines begin with `$websocket`, which create a null entry.
1102 // Process each domain.
1104 // Create a string to keep track of the current domain.
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("|"))
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.
1117 if (entry.startsWith("|")) { // Domain initial blacklist entries.
1118 // Remove the initial `|`;
1119 val entryBase = entry.substring(1)
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.
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)
1130 // Add the entry to the blacklist.
1131 domainInitialBlacklist.add(domainEntry)
1133 //Log.i("Blocklists", headers.get(1)[0] + " domain initial blacklist added: " + domain + " , " + entryBase + " - " + originalBlocklistEntry);
1135 } else if (entry.endsWith("|")) { // Domain final blacklist entries.
1136 // Remove the final `|`.
1137 val entryBase = entry.substring(0, entry.length - 1)
1139 if (entryBase.contains("*")) { // Process a domain final blacklist double entry.
1140 // Get the index of the wildcard.
1141 val wildcardIndex = entry.indexOf("*")
1143 // Split the entry into components.
1144 val firstEntry = entryBase.substring(0, wildcardIndex)
1145 val secondEntry = entryBase.substring(wildcardIndex + 1)
1147 // Create an entry string array.
1148 val domainDoubleEntry = arrayOf(domain, firstEntry, secondEntry, originalBlocklistEntry)
1150 // Add the entry to the blacklist.
1151 domainFinalBlacklist.add(domainDoubleEntry)
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)
1159 // Add the entry to the blacklist.
1160 domainFinalBlacklist.add(domainEntry)
1162 //Log.i("Blocklists", headers.get(1)[0] + " domain final blacklist added: " + domain + " , " + entryBase + " - " + originalBlocklistEntry);
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)
1168 // Add the entry to the blacklist.
1169 domainRegularExpressionBlacklist.add(domainEntry)
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("*")
1176 // Split the entry into components.
1177 val firstEntry = entry.substring(0, wildcardIndex)
1178 val secondEntry = entry.substring(wildcardIndex + 1)
1180 if (secondEntry.contains("*")) { // Process a domain blacklist triple entry.
1181 // Get the index of the wildcard.
1182 val secondWildcardIndex = secondEntry.indexOf("*")
1184 // Split the entry into components.
1185 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
1186 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
1188 // Create an entry string array.
1189 val domainTripleEntry = arrayOf(domain, firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
1191 // Add the entry to the blacklist.
1192 domainBlacklist.add(domainTripleEntry)
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)
1200 // Add the entry to the blacklist.
1201 domainBlacklist.add(domainDoubleEntry)
1203 //Log.i("Blocklists", headers.get(1)[0] + " domain blacklist added: " + domain + " , " + firstEntry + " , " + secondEntry + " - " +
1204 // originalBlocklistEntry);
1206 } else { // Process a domain blacklist single entry.
1207 // Create an entry string array.
1208 val domainEntry = arrayOf(domain, entry, originalBlocklistEntry)
1210 // Add the entry to the blacklist.
1211 domainBlacklist.add(domainEntry)
1213 //Log.i("Blocklists", headers.get(1)[0] + " domain blacklist added: " + domain + " , " + entry + " - " + originalBlocklistEntry);
1215 } while (domains.contains("|"))
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("$"))
1222 // Strip any trailing `*`.
1223 if (blocklistEntry.endsWith("*")) {
1224 blocklistEntry = blocklistEntry.substring(0, blocklistEntry.length - 1)
1227 if (blocklistEntry.contains("*")) { // Process a whitelist double entry.
1228 // Get the index of the wildcard.
1229 val wildcardIndex = blocklistEntry.indexOf("*")
1231 // Split the entry into components.
1232 val firstEntry = blocklistEntry.substring(0, wildcardIndex)
1233 val secondEntry = blocklistEntry.substring(wildcardIndex + 1)
1235 // Create an entry string array.
1236 val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
1238 // Add the entry to the whitelist.
1239 mainWhitelist.add(doubleEntry)
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)
1246 // Add the entry to the whitelist.
1247 mainWhitelist.add(singleEntry)
1249 //Log.i("Blocklists", headers.get(1)[0] + " main whitelist added: " + blocklistEntry + " - + " + originalBlocklistEntry);
1251 } else if (blocklistEntry.contains("\\")) { // Process a regular expression blacklist entry.
1252 // Remove the filter options.
1253 blocklistEntry = blocklistEntry.substring(0, blocklistEntry.indexOf("$"))
1255 // Create an entry string array.
1256 val singleEntry = arrayOf(blocklistEntry, originalBlocklistEntry)
1258 // Add the entry to the blacklist.
1259 regularExpressionBlacklist.add(singleEntry)
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("$"))
1268 // Strip any trailing `*`. These are redundant.
1269 if (blocklistEntry.endsWith("*")) {
1270 blocklistEntry = blocklistEntry.substring(0, blocklistEntry.length - 1)
1273 if (blocklistEntry.startsWith("|")) { // Initial blacklist entries.
1274 // Strip the initial `|`.
1275 val entry = blocklistEntry.substring(1)
1277 if (entry.contains("*")) { // Process an initial blacklist double entry.
1278 // Get the index of the wildcard.
1279 val wildcardIndex = entry.indexOf("*")
1281 // Split the entry into components.
1282 val firstEntry = entry.substring(0, wildcardIndex)
1283 val secondEntry = entry.substring(wildcardIndex + 1)
1285 // Create an entry string array.
1286 val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
1288 // Add the entry to the blacklist.
1289 initialBlacklist.add(doubleEntry)
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)
1296 // Add the entry to the blacklist.
1297 initialBlacklist.add(singleEntry)
1299 //Log.i("Blocklists", headers.get(1)[0] + " initial blacklist added: " + entry + " - " + originalBlocklistEntry);
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)
1307 if (entry.contains("*")) { // There are two or more entries.
1308 // Get the index of the wildcard.
1309 val wildcardIndex = entry.indexOf("*")
1311 // Split the entry into components.
1312 val firstEntry = entry.substring(0, wildcardIndex)
1313 val secondEntry = entry.substring(wildcardIndex + 1)
1315 if (secondEntry.contains("*")) { // Process a final blacklist triple entry.
1316 // Get the index of the wildcard.
1317 val secondWildcardIndex = secondEntry.indexOf("*")
1319 // Split the entry into components.
1320 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
1321 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
1323 // Create an entry string array.
1324 val tripleEntry = arrayOf(firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
1326 // Add the entry to the blacklist.
1327 finalBlacklist.add(tripleEntry)
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)
1335 // Add the entry to the blacklist.
1336 finalBlacklist.add(doubleEntry)
1338 //Log.i("Blocklists", headers.get(1)[0] + " final blacklist added: " + firstEntry + " , " + secondEntry + " - " + originalBlocklistEntry);
1340 } else { // Process a final blacklist single entry.
1341 // Create an entry sting array.
1342 val singleEntry = arrayOf(entry, originalBlocklistEntry)
1344 // Add the entry to the blacklist.
1345 finalBlacklist.add(singleEntry)
1347 //Log.i("Blocklists", headers.get(1)[0] + " final blacklist added: " + entry + " - " + originalBlocklistEntry);
1350 } else if (blocklistEntry.contains("*")) { // There are two or more entries.
1351 // Get the index of the wildcard.
1352 val wildcardIndex = blocklistEntry.indexOf("*")
1354 // Split the entry into components.
1355 val firstEntry = blocklistEntry.substring(0, wildcardIndex)
1356 val secondEntry = blocklistEntry.substring(wildcardIndex + 1)
1358 if (secondEntry.contains("*")) { // Process a main blacklist triple entry.
1359 // Get the index of the wildcard.
1360 val secondWildcardIndex = secondEntry.indexOf("*")
1362 // Split the entry into components.
1363 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
1364 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
1366 // Create an entry string array.
1367 val tripleEntry = arrayOf(firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
1369 // Add the entry to the blacklist.
1370 mainBlacklist.add(tripleEntry)
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)
1377 // Add the entry to the blacklist.
1378 mainBlacklist.add(doubleEntry)
1380 //Log.i("Blocklists", headers.get(1)[0] + " main blacklist added: " + firstEntry + " , " + secondEntry + " - " + originalBlocklistEntry);
1382 } else { // Process a main blacklist single entry.
1383 // Create an entry string array.
1384 val singleEntry = arrayOf(blocklistEntry, originalBlocklistEntry)
1386 // Add the entry to the blacklist.
1387 mainBlacklist.add(singleEntry)
1389 //Log.i("Blocklists", headers.get(1)[0] + " main blacklist added: " + blocklistEntry + " - " + originalBlocklistEntry);
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)
1398 // Strip out any initial `*`.
1399 if (blocklistEntry.startsWith("*")) {
1400 blocklistEntry = blocklistEntry.substring(1)
1403 // Strip out any trailing `*`.
1404 if (blocklistEntry.endsWith("*")) {
1405 blocklistEntry = blocklistEntry.substring(0, blocklistEntry.length - 1)
1408 if (blocklistEntry.startsWith("|")) { // Initial blacklist entries.
1409 // Strip the initial `|`.
1410 val entry = blocklistEntry.substring(1)
1412 if (entry.contains("*")) { // Process an initial blacklist double entry.
1413 // Get the index of the wildcard.
1414 val wildcardIndex = entry.indexOf("*")
1416 // Split the entry into components.
1417 val firstEntry = entry.substring(0, wildcardIndex)
1418 val secondEntry = entry.substring(wildcardIndex + 1)
1420 // Create an entry string array.
1421 val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
1423 // Add the entry to the blacklist.
1424 initialBlacklist.add(doubleEntry)
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)
1431 // Add the entry to the blacklist.
1432 initialBlacklist.add(singleEntry)
1434 //Log.i("Blocklists", headers.get(1)[0] + " initial blacklist added: " + entry + " - " + originalBlocklistEntry);
1436 } else if (blocklistEntry.endsWith("|")) { // Final blacklist entries.
1437 // Strip the final `|`.
1438 val entry = blocklistEntry.substring(0, blocklistEntry.length - 1)
1440 if (entry.contains("*")) { // There are two or more entries.
1441 // Get the index of the wildcard.
1442 val wildcardIndex = entry.indexOf("*")
1444 // Split the entry into components.
1445 val firstEntry = entry.substring(0, wildcardIndex)
1446 val secondEntry = entry.substring(wildcardIndex + 1)
1448 if (secondEntry.contains("*")) { // Process a final blacklist triple entry.
1449 // Get the index of the wildcard.
1450 val secondWildcardIndex = secondEntry.indexOf("*")
1452 // Split the entry into components.
1453 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
1454 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
1456 // Create an entry string array.
1457 val tripleEntry = arrayOf(firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
1459 // Add the entry to the blacklist.
1460 finalBlacklist.add(tripleEntry)
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)
1467 // Add the entry to the blacklist.
1468 finalBlacklist.add(doubleEntry)
1470 //Log.i("Blocklists", headers.get(1)[0] + " final blacklist added: " + firstEntry + " , " + secondEntry + " - " + originalBlocklistEntry);
1472 } else { // Process a final blacklist single entry.
1473 // Create an entry string array.
1474 val singleEntry = arrayOf(entry, originalBlocklistEntry)
1476 // Add the entry to the blacklist.
1477 finalBlacklist.add(singleEntry)
1479 //Log.i("Blocklists", headers.get(1)[0] + " final blacklist added: " + entry + " - " + originalBlocklistEntry);
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("*")
1486 // Split the entry into components.
1487 val firstEntry = blocklistEntry.substring(0, wildcardIndex)
1488 val secondEntry = blocklistEntry.substring(wildcardIndex + 1)
1490 if (secondEntry.contains("*")) { // There are three or more entries.
1491 // Get the index of the wildcard.
1492 val secondWildcardIndex = secondEntry.indexOf("*")
1494 // Split the entry into components.
1495 val realSecondEntry = secondEntry.substring(0, secondWildcardIndex)
1496 val thirdEntry = secondEntry.substring(secondWildcardIndex + 1)
1498 if (thirdEntry.contains("*")) { // There are four or more entries.
1499 // Get the index of the wildcard.
1500 val thirdWildcardIndex = thirdEntry.indexOf("*")
1502 // Split the entry into components.
1503 val realThirdEntry = thirdEntry.substring(0, thirdWildcardIndex)
1504 val fourthEntry = thirdEntry.substring(thirdWildcardIndex + 1)
1506 if (fourthEntry.contains("*")) { // Process a main blacklist quintuple entry.
1507 // Get the index of the wildcard.
1508 val fourthWildcardIndex = fourthEntry.indexOf("*")
1510 // Split the entry into components.
1511 val realFourthEntry = fourthEntry.substring(0, fourthWildcardIndex)
1512 val fifthEntry = fourthEntry.substring(fourthWildcardIndex + 1)
1514 // Create an entry string array.
1515 val quintupleEntry = arrayOf(firstEntry, realSecondEntry, realThirdEntry, realFourthEntry, fifthEntry, originalBlocklistEntry)
1517 // Add the entry to the blacklist.
1518 mainBlacklist.add(quintupleEntry)
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)
1526 // Add the entry to the blacklist.
1527 mainBlacklist.add(quadrupleEntry)
1529 //Log.i("Blocklists", headers.get(1)[0] + " main blacklist added: " + firstEntry + " , " + realSecondEntry + " , " + realThirdEntry + " , " + fourthEntry + " - " +
1530 // originalBlocklistEntry);
1532 } else { // Process a main blacklist triple entry.
1533 // Create an entry string array.
1534 val tripleEntry = arrayOf(firstEntry, realSecondEntry, thirdEntry, originalBlocklistEntry)
1536 // Add the entry to the blacklist.
1537 mainBlacklist.add(tripleEntry)
1539 //Log.i("Blocklists", headers.get(1)[0] + " main blacklist added: " + firstEntry + " , " + realSecondEntry + " , " + thirdEntry + " - " + originalBlocklistEntry);
1541 } else { // Process a main blacklist double entry.
1542 // Create an entry string array.
1543 val doubleEntry = arrayOf(firstEntry, secondEntry, originalBlocklistEntry)
1545 // Add the entry to the blacklist.
1546 mainBlacklist.add(doubleEntry)
1548 //Log.i("Blocklists", headers.get(1)[0] + " main blacklist added: " + firstEntry + " , " + secondEntry + " - " + originalBlocklistEntry);
1550 } else { // Process a main blacklist single entry.
1551 // Create an entry string array.
1552 val singleEntry = arrayOf(blocklistEntry, originalBlocklistEntry)
1554 // Add the entry to the blacklist.
1555 mainBlacklist.add(singleEntry)
1557 //Log.i("Blocklists", headers.get(1)[0] + " main blacklist added: " + blocklistEntry + " - " + originalBlocklistEntry);
1562 // Close `bufferedReader`.
1563 bufferedReader.close()
1564 } catch (e: IOException) {
1565 // The asset exists, so the `IOException` will never be thrown.
1568 // Initialize the combined list.
1569 val combinedLists = ArrayList<List<Array<String>>>()
1571 // Add the headers (0).
1572 combinedLists.add(headers) // 0.
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.
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.
1600 // Return the combined lists.
1601 return combinedLists