// Application headers.
#include "FilterListHelper.h"
+#include "structs/OverrideStruct.h"
+
+// KDE Framework headers.
+#include <KLocalizedString>
// Qt toolkit headers.
#include <QDebug>
#include <QFile>
+#include <QRegularExpression>
#include <QTextStream>
-// KDE Framework headers.
-#include <KLocalizedString>
-
// Construct the class.
FilterListHelper::FilterListHelper()
{
ALLOWED_STRING = i18nc("Allowed disposition", "Allowed");
BLOCKED_STRING = i18nc("Blocked disposition", "Blocked");
+ // Populate the translated filter option disposition strings. Translated entries cannot be public static const.
+ FILTER_OPTION_NULL = QString();
+ FILTER_OPTION_APPLY = i18nc("Apply filter option", "Apply");
+ FILTER_OPTION_OVERRIDE = i18nc("Override filter option", "Override");
+
// Populate the translated navigation type strings. Translated entries cannot be public static const.
NAVIGATION_TYPE_LINK = i18nc("Navigation type link", "Link");
NAVIGATION_TYPE_TYPED = i18nc("Navigation type typed", "Typed");
RESOURCE_TYPE_UNKNOWN = i18nc("Resource type unknown", "Unknown");
// Populate the translated sublist strings. Translated entries cannot be public static const.
+ MAIN_ALLOWLIST_STRING = i18nc("Main allowlist sublist", "Main Allow List");
MAIN_BLOCKLIST_STRING = i18nc("Main blocklist sublist", "Main Block List");
+ INITIAL_DOMAIN_BLOCKLIST_STRING = i18nc("Initial domain blocklist string", "Initial Domain Block List");
+ REGULAR_EXPRESSION_BLOCKLIST_STRING = i18nc("Regular expression blocklist string", "Regular Expression Block List");
// Populate the filter lists.
- ultraListStructPointer = populateFilterList(QLatin1String(":/filterlists/ultralist.txt"));
ultraPrivacyStructPointer = populateFilterList(QLatin1String(":/filterlists/ultraprivacy.txt"));
- easyListStructPointer = populateFilterList(QLatin1String(":/filterlists/easylist.txt"));
+ ultraListStructPointer = populateFilterList(QLatin1String(":/filterlists/ultralist.txt"));
easyPrivacyStructPointer = populateFilterList(QLatin1String(":/filterlists/easyprivacy.txt"));
+ easyListStructPointer = populateFilterList(QLatin1String(":/filterlists/easylist.txt"));
fanboyAnnoyanceStructPointer = populateFilterList(QLatin1String(":/filterlists/fanboy-annoyance.txt"));
}
bool FilterListHelper::checkFilterLists(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer) const
{
- // Initiate a status tracker. If the tracker changes to false, all process of the request will be stopped.
- bool status = true;
+ // Initiate a continue checking tracker. If the tracker changes to false, all processing of the request will be stopped.
+ bool continueChecking = true;
+
+ // Create a URL struct.
+ UrlStruct urlStruct;
+
+ // Get the URLs.
+ QUrl firstPartyUrl = urlRequestInfo.firstPartyUrl();
+ QUrl requestUrl = urlRequestInfo.requestUrl();
+
+ // Get the hosts.
+ QString firstPartyHost = firstPartyUrl.host();
+ urlStruct.fqdn = requestUrl.host();
+
+ // Determine if this is a third-party request.
+ urlStruct.isThirdPartyRequest = (firstPartyHost != urlStruct.fqdn);
+
+ // Get the request URL string.
+ urlStruct.urlString = requestUrl.toString();
+
+ // Create a URL string with separators.
+ urlStruct.urlStringWithSeparators = urlStruct.urlString;
+
+ // Replace the separators characters with `^`.
+ urlStruct.urlStringWithSeparators.replace(QLatin1Char(':'), QLatin1Char('^'));
+ urlStruct.urlStringWithSeparators.replace(QLatin1Char('/'), QLatin1Char('^'));
+ urlStruct.urlStringWithSeparators.replace(QLatin1Char('?'), QLatin1Char('^'));
+ urlStruct.urlStringWithSeparators.replace(QLatin1Char('='), QLatin1Char('^'));
+ urlStruct.urlStringWithSeparators.replace(QLatin1Char('&'), QLatin1Char('^'));
+
+ // Add a `^` to the end of the string it it doesn't already contain one.
+ if (!urlStruct.urlStringWithSeparators.endsWith(QLatin1Char('^')))
+ urlStruct.urlStringWithSeparators.append(QLatin1Char('^'));
+
+ // Create truncated URL strings and initially populate it with the original URL strings.
+ urlStruct.truncatedUrlString = urlStruct.urlString;
+ urlStruct.truncatedUrlStringWithSeparators = urlStruct.urlStringWithSeparators;
+
+ // Get the index of the beginning of the fully qualified domain name.
+ int fqdnIndex = urlStruct.truncatedUrlString.indexOf(QLatin1String("://")) + 3;
+
+ // Truncate the URL to the beginning of the fully qualified domain name.
+ urlStruct.truncatedUrlString.remove(0, fqdnIndex);
+ urlStruct.truncatedUrlStringWithSeparators.remove(0, fqdnIndex);
// Check UltraList.
- status = checkIndividualList(urlRequestInfo, requestStructPointer, ultraListStructPointer);
+ continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, ultraPrivacyStructPointer);
- // check UltraPrivacy if the status is still true.
- if (status) {
- status = checkIndividualList(urlRequestInfo, requestStructPointer, ultraPrivacyStructPointer);
- }
+ // Check UltraPrivacy.
+ if (continueChecking)
+ continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, ultraListStructPointer);
- // Return the status.
- return status;
+ // Check EasyPrivacy.
+ if (continueChecking)
+ continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, easyPrivacyStructPointer);
+
+ // Check EasyList.
+ if (continueChecking)
+ continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, easyListStructPointer);
+
+ // Check Fanboy's Annoyance list.
+ if (continueChecking)
+ continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, fanboyAnnoyanceStructPointer);
+
+ // Return the continue checking status.
+ return continueChecking;
}
-bool FilterListHelper::checkIndividualList(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, FilterListStruct *filterListStruct) const
+bool FilterListHelper::checkIndividualList(QWebEngineUrlRequestInfo &urlRequestInfo, UrlStruct &urlStruct, RequestStruct *requestStructPointer, FilterListStruct *filterListStructPointer) const
{
- // Get the request URL.
- QUrl url = urlRequestInfo.requestUrl();
+ // Initiate a continue checking tracker. If the tracker changes to false, all process of the request will be stopped.
+ bool continueChecking = true;
- // Get the request URL string.
- QString urlString = url.toString();
+ // Check the main allow list.
+ for (auto filterListEntry = filterListStructPointer->mainAllowListPointer->begin(); filterListEntry != filterListStructPointer->mainAllowListPointer->end(); ++filterListEntry)
+ {
+ // Get the entry struct.
+ EntryStruct *entryStructPointer = *filterListEntry;
+
+ // TODO. Temporarily ignore empty applied entries.
+ if (!entryStructPointer->appliedEntryList[0].isEmpty())
+ {
+ // Check if the URL string contains the applied entry. TODO.
+ if (urlStruct.urlString.contains(entryStructPointer->appliedEntryList[0]) || urlStruct.urlStringWithSeparators.contains(entryStructPointer->appliedEntryList[0]))
+ {
+ // Allow the request.
+ urlRequestInfo.block(false);
+
+ // Populate the request struct.
+ populateRequestStruct(requestStructPointer, ALLOWED, filterListStructPointer->title, MAIN_ALLOWLIST, entryStructPointer);
+
+ // Log the allow.
+ //qDebug().noquote().nospace() << "Allowed request: " << urlStruct.urlString << ", Filter list entry: " << entryStructPointer->appliedEntry;
+
+ // Returning `false` stops all processing of the request.
+ return false;
+ }
+ }
+ }
+
+ // Get the main block list end.
+ auto mainBlockListEnd = filterListStructPointer->mainBlockListPointer->end();
// Check the main block list.
- for (auto filterListEntry = filterListStruct->mainBlockList.begin(); filterListEntry != filterListStruct->mainBlockList.end(); ++filterListEntry) {
+ for (auto mainBlockListEntry = filterListStructPointer->mainBlockListPointer->begin(); mainBlockListEntry != mainBlockListEnd; ++mainBlockListEntry)
+ {
+ // Exit the loop if continue checking is false.
+ if (!continueChecking)
+ break;
+
// Get the entry struct.
- EntryStruct *entryStructPointer = *filterListEntry;
+ EntryStruct *entryStructPointer = *mainBlockListEntry;
- // Check if the URL string contains the applied entry
- if (urlString.contains(entryStructPointer->appliedEntry)) {
- // Block the request.
- urlRequestInfo.block(true);
+ // Check the applied entries.
+ continueChecking = checkAppliedEntry(urlRequestInfo, urlStruct, requestStructPointer, filterListStructPointer->title, MAIN_BLOCKLIST, entryStructPointer, urlStruct.urlString,
+ urlStruct.urlStringWithSeparators);
+ }
- // Populate the request struct.
- populateRequestStruct(requestStructPointer, BLOCKED, filterListStruct->title, MAIN_BLOCKLIST, entryStructPointer->appliedEntry, entryStructPointer->originalEntry);
+ // Get the initial domain block list end.
+ auto initialDomainBlockListEnd = filterListStructPointer->initialDomainBlockListPointer->end();
- // Log the block.
- //qDebug().noquote().nospace() << "Blocked request: " << urlString << ", Filter list entry: " << entryStructPointer->appliedEntry;
+ // Check the initial domain block list.
+ for (auto initialDomainBlockListEntry = filterListStructPointer->initialDomainBlockListPointer->begin(); initialDomainBlockListEntry != initialDomainBlockListEnd;
+ ++initialDomainBlockListEntry)
+ {
+ // Exit the loop if continue checking is false.
+ if (!continueChecking)
+ break;
+
+ // Get the entry struct.
+ EntryStruct *entryStructPointer = *initialDomainBlockListEntry;
+
+ // Check the applied entries.
+ continueChecking = checkAppliedEntry(urlRequestInfo, urlStruct, requestStructPointer, filterListStructPointer->title, INITIAL_DOMAIN_BLOCKLIST, entryStructPointer,
+ urlStruct.truncatedUrlString, urlStruct.truncatedUrlStringWithSeparators);
+ }
+
+ // Get the regular expression block list end.
+ auto regularExpressionBlockListEnd = filterListStructPointer->regularExpressionBlockListPointer->end();
+
+ // Check the regular expression block list.
+ for (auto regularExpressionBlockListEntry = filterListStructPointer->regularExpressionBlockListPointer->begin(); regularExpressionBlockListEntry != regularExpressionBlockListEnd;
+ ++regularExpressionBlockListEntry)
+ {
+ // Exit the loop if continue checking is false.
+ if (!continueChecking)
+ break;
+
+ // Get the entry struct.
+ EntryStruct *entryStructPointer = *regularExpressionBlockListEntry;
+
+ // Check the applied entries.
+ continueChecking = checkRegularExpression(urlRequestInfo, urlStruct, requestStructPointer, filterListStructPointer->title, REGULAR_EXPRESSION_BLOCKLIST, entryStructPointer);
+ }
- // Returning `false` stops all processing of the request.
- return false;
+ // Return the continue checking status.
+ return continueChecking;
+}
+
+bool FilterListHelper::checkAppliedEntry(QWebEngineUrlRequestInfo &urlRequestInfo, UrlStruct &urlStruct, RequestStruct *requestStructPointer, const QString &filterListTitle,
+ const int sublistInt, EntryStruct *entryStructPointer, QString &urlString, QString &urlStringWithSeparators) const
+{
+ // Check the entries according to the number.
+ if (entryStructPointer->singleAppliedEntry)
+ {
+ // Process initial and final matches.
+ if (entryStructPointer->initialMatch && entryStructPointer->finalMatch) // This is both an initial and final match.
+ {
+ // Check the URL against the applied entry.
+ if ((urlString == entryStructPointer->appliedEntryList[0]) || (urlStringWithSeparators == entryStructPointer->appliedEntryList[0]))
+ {
+ // Check the domain status.
+ return checkDomain(urlRequestInfo, urlStruct, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+ }
+ else if (entryStructPointer->initialMatch) // This is an initial match.
+ {
+ // Check the URL against the applied entry.
+ if (urlString.startsWith(entryStructPointer->appliedEntryList[0]) || urlStringWithSeparators.startsWith(entryStructPointer->appliedEntryList[0]))
+ {
+ // Check the domain status.
+ return checkDomain(urlRequestInfo, urlStruct, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+ }
+ else if (entryStructPointer->finalMatch) // This is a final match.
+ {
+ // Check the URL against the applied entry.
+ if (urlString.endsWith(entryStructPointer->appliedEntryList[0]) || urlStringWithSeparators.endsWith(entryStructPointer->appliedEntryList[0]))
+ {
+ // Check the domain status.
+ return checkDomain(urlRequestInfo, urlStruct, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+ }
+ else // There is no initial or final matching.
+ {
+ // Check if the URL string contains the applied entry.
+ if (urlString.contains(entryStructPointer->appliedEntryList[0]) || urlStringWithSeparators.contains(entryStructPointer->appliedEntryList[0]))
+ {
+ // Check the domain status.
+ return checkDomain(urlRequestInfo, urlStruct, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
}
}
+ else // There are multiple entries.
+ {
+ // Create a URL matches flag.
+ bool urlMatches = true;
+
+ // Process initial and final matches.
+ if (entryStructPointer->initialMatch && entryStructPointer->finalMatch) // This is both an initial and final match.
+ {
+ // Check the first entry.
+ if (urlString.startsWith(entryStructPointer->appliedEntryList[0]) ||
+ urlStringWithSeparators.startsWith(entryStructPointer->appliedEntryList[0])) // The URL string starts with the first applied entry.
+ {
+ // Get the number of characters to remove from the front of the URL strings.
+ int charactersToRemove = entryStructPointer->appliedEntryList[0].size();
- // Return `true` to continue processing the URL request.
+ // Remove the entry from the front of the URL string copies.
+ urlString.remove(0, charactersToRemove);
+ urlStringWithSeparators.remove(0, charactersToRemove);
+ }
+ else // The URL string does not end with the last applied entry.
+ {
+ // Mark the URL matches flag as false.
+ urlMatches = false;
+ }
+
+ // Check the other entries if the URL still matches.
+ if (urlMatches)
+ {
+ // Calculate the penultimate entry.
+ int penultimateEntryNumber = (entryStructPointer->sizeOfAppliedEntryList - 1);
+ int ultimateEntryIndex = penultimateEntryNumber;
+
+ // Check all the middle entries.
+ for (int i = 1; i < penultimateEntryNumber; ++i)
+ {
+ // Get the index of the applied entry, which will be `-1` if it doesn't exist.
+ int stringIndex = urlString.indexOf(entryStructPointer->appliedEntryList[i]);
+ int stringWithSeparatorsIndex = urlStringWithSeparators.indexOf(entryStructPointer->appliedEntryList[i]);
+
+ // Get the larger of the two indexes.
+ int index = std::max(stringIndex, stringWithSeparatorsIndex);
+
+ // Check if the entry was found.
+ if (index >= 0) // The entry is contained in the URL string.
+ {
+ // Get the number of characters to remove from the front of the URL strings.
+ int charactersToRemove = index + entryStructPointer->appliedEntryList[i].size();
+
+ // Remove the entry from the front of the URL string copies.
+ urlString.remove(0, charactersToRemove);
+ urlStringWithSeparators.remove(0, charactersToRemove);
+ }
+ else // The entry is not contained in the URL string.
+ {
+ // Mark the URL matches flag as false.
+ urlMatches = false;
+ }
+ }
+
+ // Check the final entry if the URL still matches.
+ if (urlMatches)
+ {
+ if (urlString.endsWith(entryStructPointer->appliedEntryList[ultimateEntryIndex]) ||
+ urlStringWithSeparators.endsWith(entryStructPointer->appliedEntryList[ultimateEntryIndex])) // The URL string ends with the last applied entry.
+ {
+ // There is no need to modify the URL string copies as no further checks will be performed.
+ }
+ else // The URL string does not end with the last applied entry.
+ {
+ // Mark the URL matches flag as false.
+ urlMatches = false;
+ }
+ }
+ }
+ }
+ else if (entryStructPointer->initialMatch) // This is an initial match.
+ {
+ // Check the first entry.
+ if (urlString.startsWith(entryStructPointer->appliedEntryList[0]) ||
+ urlStringWithSeparators.startsWith(entryStructPointer->appliedEntryList[0])) // The URL string starts with the first applied entry.
+ {
+ // Get the number of characters to remove from the front of the URL strings.
+ int charactersToRemove = entryStructPointer->appliedEntryList[0].size();
+
+ // Remove the entry from the front of the URL string copies.
+ urlString.remove(0, charactersToRemove);
+ urlStringWithSeparators.remove(0, charactersToRemove);
+ }
+ else // The URL string does not end with the last applied entry.
+ {
+ // Mark the URL matches flag as false.
+ urlMatches = false;
+ }
+
+ // Check the other entries if the URL still matches.
+ if (urlMatches)
+ {
+ for (int i = 1; i < entryStructPointer->sizeOfAppliedEntryList; ++i)
+ {
+ // Get the index of the applied entry, which will be `-1` if it doesn't exist.
+ int stringIndex = urlString.indexOf(entryStructPointer->appliedEntryList[i]);
+ int stringWithSeparatorsIndex = urlStringWithSeparators.indexOf(entryStructPointer->appliedEntryList[i]);
+
+ // Get the larger of the two indexes.
+ int index = std::max(stringIndex, stringWithSeparatorsIndex);
+
+ // Check if the entry was found.
+ if (index >= 0) // The entry is contained in the URL string.
+ {
+ // Get the number of characters to remove from the front of the URL strings.
+ int charactersToRemove = index + entryStructPointer->appliedEntryList[i].size();
+
+ // Remove the entry from the front of the URL string copies.
+ urlString.remove(0, charactersToRemove);
+ urlStringWithSeparators.remove(0, charactersToRemove);
+ }
+ else // The entry is not contained in the URL string.
+ {
+ // Mark the URL matches flag as false.
+ urlMatches = false;
+ }
+ }
+ }
+ }
+ else if (entryStructPointer->finalMatch) // This is a final match.
+ {
+ // Calculate the penultimate entry.
+ int penultimateEntryNumber = (entryStructPointer->sizeOfAppliedEntryList - 1);
+ int ultimateEntryIndex = penultimateEntryNumber;
+
+ // Check all the entries except the last one.
+ for (int i = 0; i < penultimateEntryNumber; ++i)
+ {
+ // Get the index of the applied entry, which will be `-1` if it doesn't exist.
+ int stringIndex = urlString.indexOf(entryStructPointer->appliedEntryList[i]);
+ int stringWithSeparatorsIndex = urlStringWithSeparators.indexOf(entryStructPointer->appliedEntryList[i]);
+
+ // Get the larger of the two indexes.
+ int index = std::max(stringIndex, stringWithSeparatorsIndex);
+
+ // Check if the entry was found.
+ if (index >= 0) // The entry is contained in the URL string.
+ {
+ // Get the number of characters to remove from the front of the URL strings.
+ int charactersToRemove = index + entryStructPointer->appliedEntryList[i].size();
+
+ // Remove the entry from the front of the URL string copies.
+ urlString.remove(0, charactersToRemove);
+ urlStringWithSeparators.remove(0, charactersToRemove);
+ }
+ else // The entry is not contained in the URL string.
+ {
+ // Mark the URL matches flag as false.
+ urlMatches = false;
+ }
+ }
+
+ // Check the final entry if the URL still matches.
+ if (urlMatches)
+ {
+ if (urlString.endsWith(entryStructPointer->appliedEntryList[ultimateEntryIndex]) ||
+ urlStringWithSeparators.endsWith(entryStructPointer->appliedEntryList[ultimateEntryIndex])) // The URL string ends with the last applied entry.
+ {
+ // There is no need to modify the URL string copies as no further checks will be performed.
+ }
+ else // The URL string does not end with the last applied entry.
+ {
+ // Mark the URL matches flag as false.
+ urlMatches = false;
+ }
+ }
+ }
+ else // There is no initial or final matching.
+ {
+ for (int i = 0; i < entryStructPointer->sizeOfAppliedEntryList; ++i)
+ {
+ // Get the index of the applied entry, which will be `-1` if it doesn't exist.
+ int stringIndex = urlString.indexOf(entryStructPointer->appliedEntryList[i]);
+ int stringWithSeparatorsIndex = urlStringWithSeparators.indexOf(entryStructPointer->appliedEntryList[i]);
+
+ // Get the larger of the two indexes.
+ int index = std::max(stringIndex, stringWithSeparatorsIndex);
+
+ // Check if the entry was found.
+ if (index >= 0) // The entry is contained in the URL string.
+ {
+
+ // Get the number of characters to remove from the front of the URL strings.
+ int charactersToRemove = index + entryStructPointer->appliedEntryList[i].size();
+
+ // Remove the entry from the front of the URL string copies.
+ urlString.remove(0, charactersToRemove);
+ urlStringWithSeparators.remove(0, charactersToRemove);
+ }
+ else // The entry is not contained in the URL string.
+ {
+ // Mark the URL matches flag as false.
+ urlMatches = false;
+ }
+ }
+ }
+
+ // Check the domain status if the URL matches.
+ if (urlMatches)
+ return checkDomain(urlRequestInfo, urlStruct, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+
+ // If the applied entry doesn't match, return `true` to continue processing the URL request.
return true;
}
+bool FilterListHelper::checkRegularExpression(QWebEngineUrlRequestInfo &urlRequestInfo, UrlStruct &urlStruct, RequestStruct *requestStructPointer, const QString &filterListTitle,
+ const int sublistInt, EntryStruct *entryStructPointer) const
+{
+ // Create an applied entry regular expression.
+ QRegularExpression appliedEntryRegularExpression(entryStructPointer->appliedEntryList[0]);
+
+ // Check if the regular expression matches the applied entry.
+ if (urlStruct.urlString.contains(appliedEntryRegularExpression))
+ {
+ // Check the domain status.
+ return checkDomain(urlRequestInfo, urlStruct, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+
+ // If the regular expression doesn't match, return `true` to continue processing the URL request.
+ return true;
+}
+
+bool FilterListHelper::checkDomain(QWebEngineUrlRequestInfo &urlRequestInfo, UrlStruct &urlStruct, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt,
+ EntryStruct *entryStructPointer) const
+{
+ // Check domain status.
+ if (entryStructPointer->domain == FilterOptionEnum::Disposition::Null) // Ignore domain status.
+ {
+ // Check the third-party status.
+ return checkThirdParty(urlRequestInfo, requestStructPointer, urlStruct.isThirdPartyRequest, filterListTitle, sublistInt, entryStructPointer);
+ }
+ else if (entryStructPointer->domain == FilterOptionEnum::Disposition::Apply) // Block requests from listed domains.
+ {
+ // Check each domain.
+ foreach (QString blockedDomain, entryStructPointer->domainList)
+ {
+ // Check if the request came from a blocked domain.
+ if (urlStruct.fqdn.endsWith(blockedDomain))
+ {
+ // Check the third-party status.
+ return checkThirdParty(urlRequestInfo, requestStructPointer, urlStruct.isThirdPartyRequest, filterListTitle, sublistInt, entryStructPointer);
+ }
+ }
+ }
+ else if (entryStructPointer->domain == FilterOptionEnum::Disposition::Override) // Block domains that are not overridden.
+ {
+ // Create a block domain flag.
+ bool blockDomain = true;
+
+ // Check each overridden domain.
+ foreach (QString overriddenDomain, entryStructPointer->domainList)
+ {
+ // Check if the request came from an overridden domain.
+ if (urlStruct.fqdn.endsWith(overriddenDomain))
+ {
+ // Don't block the domain.
+ blockDomain = false;
+ }
+ }
+
+ // Continue checking if the domain is blocked.
+ if (blockDomain)
+ {
+ // Check the third-party status.
+ return checkThirdParty(urlRequestInfo, requestStructPointer, urlStruct.isThirdPartyRequest, filterListTitle, sublistInt, entryStructPointer);
+ }
+ }
+
+ // There is a domain specified that doesn't match this request. Return `true` to continue processing the URL request.
+ return true;
+}
+
+bool FilterListHelper::checkThirdParty(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, const bool isThirdPartyRequest, const QString &filterListTitle,
+ const int sublistInt, EntryStruct *entryStructPointer) const
+{
+ // Check third-party status.
+ if (entryStructPointer->thirdParty == FilterOptionEnum::Disposition::Null) // Ignore third-party status.
+ {
+ // Check if request options are applied.
+ if (entryStructPointer->hasRequestOptions) // Request options are applied.
+ {
+ // Check the request options.
+ return checkRequestOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+ else // Request options are not applied.
+ {
+ // Block the request.
+ return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+ }
+ else if ((entryStructPointer->thirdParty == FilterOptionEnum::Disposition::Apply) && isThirdPartyRequest) // Block third-party request.
+ {
+ // Check if request options are applied.
+ if (entryStructPointer->hasRequestOptions) // Request options are applied.
+ {
+ // Check the request options.
+ return checkRequestOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+ else // Request options are not applied.
+ {
+ // Block the request.
+ return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+ }
+ else if ((entryStructPointer->thirdParty == FilterOptionEnum::Disposition::Override) && !isThirdPartyRequest) // Block first-party requests.
+ {
+ // Check if request options are applied.
+ if (entryStructPointer->hasRequestOptions) // Request options are applied.
+ {
+ // Check the request options.
+ return checkRequestOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+ else // Request options are not applied.
+ {
+ // Block the request.
+ return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+ }
+
+ // The third-party option specified doesn't match this request. Return `true` to continue processing the URL request.
+ return true;
+}
+
+bool FilterListHelper::checkRequestOptions(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt,
+ EntryStruct *entryStructPointer) const
+{
+ // Block font requests.
+ if ((entryStructPointer->font == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeFontResource))
+ {
+ // Block the request.
+ return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+
+ // Block image requests.
+ if ((entryStructPointer->image == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeImage))
+ {
+ // Block the request.
+ return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+
+ // Block main frame requests.
+ if ((entryStructPointer->mainFrame == FilterOptionEnum::Disposition::Apply) && ((requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeMainFrame) ||
+ (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadMainFrame)))
+ {
+ // Block the request.
+ return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+
+ // Block media requests.
+ if ((entryStructPointer->media == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeMedia))
+ {
+ // Block the request.
+ return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+
+ // Block object requests.
+ if ((entryStructPointer->object == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeObject))
+ {
+ // Block the request.
+ return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+
+ // Block other requests.
+ if ((entryStructPointer->other == FilterOptionEnum::Disposition::Apply) && ((requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeSubResource) ||
+ (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeWorker) ||
+ (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeSharedWorker) ||
+ (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypePrefetch) ||
+ (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeFavicon) ||
+ (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeServiceWorker) ||
+ (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeCspReport) ||
+ (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypePluginResource) ||
+ (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeUnknown)))
+ {
+ // Block the request.
+ return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+
+ // Block ping requests
+ if ((entryStructPointer->ping == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypePing))
+ {
+ // Block the request.
+ return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+
+ // Block script requests.
+ if ((entryStructPointer->script == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeScript))
+ {
+ // Block the request.
+ return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+
+ // Block style sheet requests.
+ if ((entryStructPointer->styleSheet == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeStylesheet))
+ {
+ // Block the request.
+ return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+
+ // Block sub resource requests.
+ if ((entryStructPointer->subFrame == FilterOptionEnum::Disposition::Apply) && ((requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeSubFrame) ||
+ (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadSubFrame)))
+ {
+ // Block the request.
+ return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+
+ // Block XML HTTP requests.
+ if ((entryStructPointer->xmlHttpRequest == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeXhr))
+ {
+ // Block the request.
+ return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
+
+ // The request options specified don't match this request. Return `true` to continue processing the URL request.
+ return true;
+}
+
+bool FilterListHelper::blockRequest(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt,
+ EntryStruct *entryStructPointer) const
+{
+ // Block the request.
+ urlRequestInfo.block(true);
+
+ // Populate the request struct.
+ populateRequestStruct(requestStructPointer, BLOCKED, filterListTitle, sublistInt, entryStructPointer);
+
+ // Log the block.
+ //qDebug().noquote().nospace() << "Blocked request: " << urlRequestInfo.firstPartyUrl() << ", Filter list entry: " << entryStructPointer->appliedEntry;
+
+ // Returning `false` stops all processing of the request.
+ return false;
+}
+
QString FilterListHelper::getDispositionString(int dispositionInt) const
{
// Return the translated disposition string.
}
}
+QString FilterListHelper::getRequestOptionDispositionString(const FilterOptionEnum::Disposition filterOptionDisposition) const
+{
+ // Return the translated filter option disposition string.
+ switch (filterOptionDisposition)
+ {
+ case FilterOptionEnum::Disposition::Apply: return FILTER_OPTION_APPLY;
+ case FilterOptionEnum::Disposition::Override: return FILTER_OPTION_OVERRIDE;
+ default: return FILTER_OPTION_NULL;
+ }
+}
+
QString FilterListHelper::getResourceTypeString(int resourceTypeInt) const
{
// Return the translated resource type string.
// Return the name of the requested sublist.
switch (sublistInt)
{
+ case MAIN_ALLOWLIST: return MAIN_ALLOWLIST_STRING;
case MAIN_BLOCKLIST: return MAIN_BLOCKLIST_STRING;
+ case INITIAL_DOMAIN_BLOCKLIST: return INITIAL_DOMAIN_BLOCKLIST_STRING;
+ case REGULAR_EXPRESSION_BLOCKLIST: return REGULAR_EXPRESSION_BLOCKLIST_STRING;
default: return QString(); // The default return should never be reached.
}
}
entryStructPointer->originalEntry = filterListString;
// Process the entry.
- if (filterListString.startsWith(QLatin1Char('['))) { // The line starts with `[`, which is the file format.
+ if (filterListString.isEmpty()) // Ignore empty lines.
+ {
+ // Do nothing.
+
+ // Log the dropping of the line.
+ //qDebug().noquote().nospace() << filterListString << " NOT added from " << filterListFileName << " (empty line).";
+ }
+ else if (filterListString.startsWith(QLatin1Char('['))) // The line starts with `[`, which is the file format.
+ {
+ // Do nothing.
+
+ // Log the dropping of the line.
+ //qDebug().noquote().nospace() << filterListString << " NOT added from " << filterListFileName << " (file format).";
+ }
+ else if (filterListString.contains(QLatin1String("##")) ||
+ filterListString.contains(QLatin1String("#?#")) ||
+ filterListString.contains(QLatin1String("#@#")) ||
+ filterListString.contains(QLatin1String("#$#"))) // The line contains unimplemented content filtering.
+ {
// Do nothing.
// Log the dropping of the line.
- //qDebug().noquote().nospace() << filterListString << " NOT added from " << filterListFileName;
- } else if (filterListString.startsWith(QLatin1Char('!'))) { // The line starts with `!`, which are comments.
+ //qDebug().noquote().nospace() << filterListString << " NOT added from " << filterListFileName << " (content filtering).";
+ }
+ else if (filterListString.startsWith(QLatin1Char('!'))) // The line starts with `!`, which are comments.
+ {
if (filterListString.startsWith(QLatin1String("! Title: "))) // The line contains the title.
{
// Add the title to the filter list struct.
// Log the dropping of the line.
//qDebug().noquote().nospace() << originalFilterListString << " NOT added from " << filterListFileName;
- } else { // Process the entry.
- // Add the applied entry to the struct.
- entryStructPointer->appliedEntry = filterListString;
+ }
+ else // Process the filter options.
+ {
+ // Get the index of the last dollar sign.
+ int indexOfLastDollarSign = filterListString.lastIndexOf(QLatin1Char('$'));
+
+ // Process the filter options if they exist.
+ if (indexOfLastDollarSign > -1)
+ {
+ // Get the filter options.
+ entryStructPointer->originalFilterOptions = filterListString.section(QLatin1Char('$'), -1);
+
+ // Store the entry without the filter options as the filter list string.
+ filterListString.truncate(indexOfLastDollarSign);
+
+ // Split the filter options.
+ QStringList originalFilterOptionsList = entryStructPointer->originalFilterOptions.split(QLatin1Char(','));
+
+ // Create an applied filter options list.
+ QStringList appliedFilterOptionsList;
+
+ // Populate the applied filter options list.
+ foreach (QString filterOption, originalFilterOptionsList)
+ {
+ // Only add filter options that are handled by Privacy Browser.
+ if (!(filterOption.startsWith(QLatin1String("csp=")) ||
+ filterOption.startsWith(QLatin1String("method=")) ||
+ filterOption.startsWith(QLatin1String("redirect=")) ||
+ filterOption.startsWith(QLatin1String("rewrite="))))
+ appliedFilterOptionsList.append(filterOption);
+ }
+
+ // Store the applied filter options list.
+ entryStructPointer->appliedFilterOptionsList = appliedFilterOptionsList;
+
+ // Initialize an override struct.
+ OverrideStruct overrideStruct;
+
+ // Populate the filter options entries.
+ foreach (QString filterOption, appliedFilterOptionsList)
+ {
+ // Parse the filter options.
+ if (filterOption.startsWith(QLatin1String("domain="))) // Domain.
+ {
+ // Remove `domain=` from the filter option.
+ filterOption.remove(0, 7);
+
+ // Store the domain list.
+ entryStructPointer->domainList = filterOption.split(QLatin1Char('|'));
+
+ // Set the disposition.
+ if (entryStructPointer->domainList[0].startsWith(QLatin1Char('~'))) // Override domains.
+ {
+ // Populate the domain filter disposition.
+ entryStructPointer->domain = FilterOptionEnum::Disposition::Override;
+
+ // Remove the initial `~` from each domain.
+ entryStructPointer->domainList.replaceInStrings(QLatin1String("~"), QLatin1String(""));
+ }
+ else // Standard domains.
+ {
+ // Populate the domain filter disposition.
+ entryStructPointer->domain = FilterOptionEnum::Disposition::Apply;
+ }
+ }
+ else if (filterOption == QLatin1String("third-party")) // Third-party.
+ {
+ // Populate the third-party filter disposition.
+ entryStructPointer->thirdParty = FilterOptionEnum::Disposition::Apply;
+ }
+ else if (filterOption == QLatin1String("~third-party")) // Third-party override.
+ {
+ // Populate the third-party filter disposition.
+ entryStructPointer->thirdParty = FilterOptionEnum::Disposition::Override;
+ }
+ else if ((filterOption == QLatin1String("document")) || (filterOption == QLatin1String("popup"))) // Document (and popup).
+ {
+ // Populate the main frame disposition.
+ entryStructPointer->mainFrame = FilterOptionEnum::Disposition::Apply;
+
+ // Set the has request options flag.
+ entryStructPointer->hasRequestOptions = true;
+ }
+ else if (filterOption == QLatin1String("font")) // Font.
+ {
+ // Populate the font disposition.
+ entryStructPointer->font = FilterOptionEnum::Disposition::Apply;
+
+ // Set the has request options flag.
+ entryStructPointer->hasRequestOptions = true;
+ }
+ else if (filterOption == QLatin1String("image")) // Image.
+ {
+ // Populate the image disposition.
+ entryStructPointer->image = FilterOptionEnum::Disposition::Apply;
+
+ // Set the has request options flag.
+ entryStructPointer->hasRequestOptions = true;
+ }
+ else if (filterOption == QLatin1String("media")) // Media.
+ {
+ // Populate the media disposition.
+ entryStructPointer->media = FilterOptionEnum::Disposition::Apply;
+
+ // Set the has request options flag.
+ entryStructPointer->hasRequestOptions = true;
+ }
+ else if (filterOption == QLatin1String("object")) // Object.
+ {
+ // Populate the object disposition.
+ entryStructPointer->object = FilterOptionEnum::Disposition::Apply;
+
+ // Set the has request options flag.
+ entryStructPointer->hasRequestOptions = true;
+ }
+ else if ((filterOption == QLatin1String("other")) || (filterOption == QLatin1String("webrtc")) || (filterOption == QLatin1String("websocket"))) // Other.
+ { // `websocket` will get its own section in Qt6.
+ // Populate the other disposition.
+ entryStructPointer->other = FilterOptionEnum::Disposition::Apply;
+
+ // Set the has request options flag.
+ entryStructPointer->hasRequestOptions = true;
+ }
+ else if (filterOption == QLatin1String("ping")) // Ping.
+ {
+ // Populate the ping disposition.
+ entryStructPointer->ping = FilterOptionEnum::Disposition::Apply;
+
+ // Set the has request options flag.
+ entryStructPointer->hasRequestOptions = true;
+ }
+ else if (filterOption == QLatin1String("script")) // Script.
+ {
+ // Populate the script disposition.
+ entryStructPointer->script = FilterOptionEnum::Disposition::Apply;
+
+ // Set the has request options flag.
+ entryStructPointer->hasRequestOptions = true;
+ }
+ else if (filterOption == QLatin1String("stylesheet")) // Style sheet.
+ {
+ // Populate the script disposition.
+ entryStructPointer->styleSheet = FilterOptionEnum::Disposition::Apply;
+
+ // Set the has request options flag.
+ entryStructPointer->hasRequestOptions = true;
+ }
+ else if (filterOption == QLatin1String("subdocument")) // Sub document.
+ {
+ // Populate the sub resource disposition.
+ entryStructPointer->subFrame = FilterOptionEnum::Disposition::Apply;
+
+ // Set the has request options flag.
+ entryStructPointer->hasRequestOptions = true;
+ }
+ else if (filterOption == QLatin1String("xmlhttprequest")) // XML HTTP request.
+ {
+ //Populate the XML HTTP request disposition.
+ entryStructPointer->xmlHttpRequest = FilterOptionEnum::Disposition::Apply;
+
+ // Set the has request options flag.
+ entryStructPointer->hasRequestOptions = true;
+ }
+ else if (filterOption == QLatin1String("~document")) // Document override.
+ {
+ // Populate the override struct.
+ overrideStruct.hasOverride = true;
+ overrideStruct.mainFrame = true;
+ }
+ else if (filterOption == QLatin1String("~font")) // Font override.
+ {
+ // Populate the override struct.
+ overrideStruct.hasOverride = true;
+ overrideStruct.font = true;
+ }
+ else if (filterOption == QLatin1String("~image")) // Image override.
+ {
+ // Populate the override struct.
+ overrideStruct.hasOverride = true;
+ overrideStruct.image = true;
+ }
+ else if (filterOption == QLatin1String("~media")) // Media override.
+ {
+ // Populate the override struct.
+ overrideStruct.hasOverride = true;
+ overrideStruct.media = true;
+ }
+ else if (filterOption == QLatin1String("~object")) // Object override.
+ {
+ // Populate the override struct.
+ overrideStruct.hasOverride = true;
+ overrideStruct.object = true;
+ }
+ else if ((filterOption == QLatin1String("~other")) || (filterOption == QLatin1String("~webrtc")) || (filterOption == QLatin1String("~websocket"))) // Other override.
+ { // `websocket` will get its own section in Qt6.
+ // Populate the override struct.
+ overrideStruct.hasOverride = true;
+ overrideStruct.other = true;
+ }
+ else if (filterOption == QLatin1String("~ping")) // Ping override.
+ {
+ // Populate the override struct.
+ overrideStruct.hasOverride = true;
+ overrideStruct.ping = true;
+ }
+ else if (filterOption == QLatin1String("~script")) // Script override.
+ {
+ // Populate the override struct.
+ overrideStruct.hasOverride = true;
+ overrideStruct.script = true;
+ }
+ else if (filterOption == QLatin1String("~stylesheet")) // Style sheet override.
+ {
+ // Populate the override struct.
+ overrideStruct.hasOverride = true;
+ overrideStruct.styleSheet = true;
+ }
+ else if (filterOption == QLatin1String("~subdocument")) // Sub document override.
+ {
+ // Populate the override struct.
+ overrideStruct.hasOverride = true;
+ overrideStruct.subFrame = true;
+ }
+ else if (filterOption == QLatin1String("~xmlhttprequest")) // XML HTTP request override.
+ {
+ // Populate the override struct.
+ overrideStruct.hasOverride = true;
+ overrideStruct.xmlHttpRequest = true;
+ }
+ }
+
+ // Apply the overrides.
+ if (overrideStruct.hasOverride)
+ {
+ // Set the has request options flag.
+ entryStructPointer->hasRequestOptions = true;
+
+ // Font.
+ if (overrideStruct.font)
+ entryStructPointer->font = FilterOptionEnum::Disposition::Override;
+ else
+ entryStructPointer->font = FilterOptionEnum::Disposition::Apply;
+
+ // Image.
+ if (overrideStruct.image)
+ entryStructPointer->image = FilterOptionEnum::Disposition::Override;
+ else
+ entryStructPointer->image = FilterOptionEnum::Disposition::Apply;
+
+ // Main Frame (document).
+ if (overrideStruct.mainFrame)
+ entryStructPointer->mainFrame = FilterOptionEnum::Disposition::Override;
+ else
+ entryStructPointer->mainFrame = FilterOptionEnum::Disposition::Apply;
+
+ // Media.
+ if (overrideStruct.media)
+ entryStructPointer->media = FilterOptionEnum::Disposition::Override;
+ else
+ entryStructPointer->media = FilterOptionEnum::Disposition::Apply;
+
+ // Object.
+ if (overrideStruct.object)
+ entryStructPointer->object = FilterOptionEnum::Disposition::Override;
+ else
+ entryStructPointer->object = FilterOptionEnum::Disposition::Apply;
+
+ // Other.
+ if (overrideStruct.other)
+ entryStructPointer->other = FilterOptionEnum::Disposition::Override;
+ else
+ entryStructPointer->other = FilterOptionEnum::Disposition::Apply;
+
+ // Ping.
+ if (overrideStruct.ping)
+ entryStructPointer->ping = FilterOptionEnum::Disposition::Override;
+ else
+ entryStructPointer->ping = FilterOptionEnum::Disposition::Apply;
+
+ // Script.
+ if (overrideStruct.script)
+ entryStructPointer->script = FilterOptionEnum::Disposition::Override;
+ else
+ entryStructPointer->script = FilterOptionEnum::Disposition::Apply;
+
+ // Style Sheet.
+ if (overrideStruct.styleSheet)
+ entryStructPointer->styleSheet = FilterOptionEnum::Disposition::Override;
+ else
+ entryStructPointer->styleSheet = FilterOptionEnum::Disposition::Apply;
+
+ // Sub Resource.
+ if (overrideStruct.subFrame)
+ entryStructPointer->subFrame = FilterOptionEnum::Disposition::Override;
+ else
+ entryStructPointer->subFrame = FilterOptionEnum::Disposition::Apply;
- // Add the filter list entry struct to the main block list.
- filterListStructPointer->mainBlockList.push_front(entryStructPointer);
+ // XML HTTP Request.
+ if (overrideStruct.xmlHttpRequest)
+ entryStructPointer->xmlHttpRequest = FilterOptionEnum::Disposition::Override;
+ else
+ entryStructPointer->xmlHttpRequest = FilterOptionEnum::Disposition::Apply;
+ }
+ } // Finish processing filter options.
- // Log the addition to the filter list.
- //qDebug().noquote().nospace() << originalFilterListString << " added from " << filterListFileName;
+
+ if (filterListString.isEmpty() && !entryStructPointer->hasRequestOptions) // There are no applied entries and no request options.
+ {
+ // Ignore these entries as they will block all requests generally or for a specified domain. Typically these are left over after removing `csp=` filter options.
+
+ // Log the dropping of the entry.
+ //qDebug().noquote().nospace() << entryStructPointer->originalEntry << " NOT added from " << filterListFileName << ".";
+ }
+ else if (filterListString.startsWith(QLatin1String("@@"))) // Process an allow list entry.
+ {
+ // Remove the initial `@@`.
+ filterListString.remove(0, 2);
+
+ // Prepare the filter list string. TODO. Initial allow lists must be processed first.
+ prepareFilterListString(filterListString, entryStructPointer);
+
+ // Add the entry struct to the main allow list.
+ filterListStructPointer->mainAllowListPointer->push_front(entryStructPointer);
+
+ // Log the addition to the filter list.
+ //qDebug().noquote().nospace() << entryStructPointer->originalEntry << " added to Main Allow List from " << filterListFileName << ".";
+ }
+ else if (filterListString.startsWith(QLatin1String("||"))) // Process an initial domain block list entry.
+ {
+ // Remove the initial `||`.
+ filterListString.remove(0, 2);
+
+ // Set the initial match flag.
+ entryStructPointer->initialMatch = true;
+
+ // Prepare the filter list string.
+ prepareFilterListString(filterListString, entryStructPointer);
+
+ // Add the entry struct to the initial domain block list.
+ filterListStructPointer->initialDomainBlockListPointer->push_front(entryStructPointer);
+
+ // Log the addition to the filter list.
+ //qDebug().noquote().nospace() << entryStructPointer->originalEntry << " added to Initial Domain Block List from " << filterListFileName << ".";
+ }
+ else if (filterListString.contains(QLatin1String("\\"))) // Process a regular expression block list entry.
+ {
+ // Add the regular expression to the applied entry list.
+ entryStructPointer->appliedEntryList.append(filterListString);
+
+ // Add the entry struct to the regular expression block list.
+ filterListStructPointer->regularExpressionBlockListPointer->push_front(entryStructPointer);
+ }
+ else // Process a main block list entry.
+ {
+ // Prepare the filter list string.
+ prepareFilterListString(filterListString, entryStructPointer);
+
+ // Add the entry struct to the main block list.
+ filterListStructPointer->mainBlockListPointer->push_front(entryStructPointer);
+
+ // Log the addition to the filter list.
+ //qDebug().noquote().nospace() << entryStructPointer->originalEntry << " added to Main Block List from " << filterListFileName << ".";
+ }
}
}
return filterListStructPointer;
}
-void FilterListHelper::populateRequestStruct(RequestStruct *requestStructPointer, const int disposition, const QString &filterListTitle, const int sublistInt, const QString &appliedEntry,
- const QString &originalEntry) const
+void FilterListHelper::populateRequestStruct(RequestStruct *requestStructPointer, const int disposition, const QString &filterListTitle, const int sublistInt, EntryStruct *entryStructPointer) const
{
// Populate the request struct.
requestStructPointer->dispositionInt = disposition;
requestStructPointer->filterListTitle = filterListTitle;
requestStructPointer->sublistInt = sublistInt;
- requestStructPointer->entryStruct.appliedEntry = appliedEntry;
- requestStructPointer->entryStruct.originalEntry = originalEntry;
+ requestStructPointer->entryStruct.appliedEntryList = entryStructPointer->appliedEntryList;
+ requestStructPointer->entryStruct.originalEntry = entryStructPointer->originalEntry;
+}
+
+void FilterListHelper::prepareFilterListString(QString &filterListString, EntryStruct *entryStructPointer) const
+{
+ // Check if this is an initial match.
+ if (filterListString.startsWith(QLatin1Char('|')))
+ {
+ // Strip the initial `|`.
+ filterListString.remove(0, 1);
+
+ // Set the initial match flag.
+ entryStructPointer->initialMatch = true;
+ }
+
+ // Check if this is a final match.
+ if (filterListString.endsWith(QLatin1Char('|')))
+ {
+ // Strip the final `|`.
+ filterListString.chop(1);
+
+ // Set the final match flag.
+ entryStructPointer->finalMatch = true;
+ }
+
+ // Remove the initial asterisk if it exists.
+ if (filterListString.startsWith(QLatin1Char('*')))
+ filterListString.remove(0, 1);
+
+ // Remove the final asterisk if it exists.
+ if (filterListString.endsWith(QLatin1Char('*')))
+ filterListString.chop(1);
+
+ // Split the filter list string and set it as the applied entry list.
+ entryStructPointer->appliedEntryList = filterListString.split(QLatin1Char('*'));
+
+ // Store the size of the applied entry list.
+ entryStructPointer->sizeOfAppliedEntryList = entryStructPointer->appliedEntryList.size();
+
+ // Determine if this is a single applied entry (including an empty entry).
+ entryStructPointer->singleAppliedEntry = (entryStructPointer->sizeOfAppliedEntryList == 1);
}