#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()
{
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 continue checking tracker. If the tracker changes to false, all process of the request will be stopped.
+ // 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.
// Get the hosts.
QString firstPartyHost = firstPartyUrl.host();
- QString requestHost = requestUrl.host();
+ urlStruct.fqdn = requestUrl.host();
// Determine if this is a third-party request.
- urlStruct.isThirdPartyRequest = (firstPartyHost != requestHost);
+ urlStruct.isThirdPartyRequest = (firstPartyHost != urlStruct.fqdn);
// Get the request URL string.
urlStruct.urlString = requestUrl.toString();
urlStruct.urlStringWithSeparators.replace(QLatin1Char('='), QLatin1Char('^'));
urlStruct.urlStringWithSeparators.replace(QLatin1Char('&'), QLatin1Char('^'));
- // Add a `^` to the end of the string.
- urlStruct.urlStringWithSeparators.append(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.remove(0, fqdnIndex);
// Check UltraList.
- continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, ultraListStructPointer);
+ continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, ultraPrivacyStructPointer);
// Check UltraPrivacy.
if (continueChecking)
- continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, ultraPrivacyStructPointer);
-
- // Check EasyList.
- if (continueChecking)
- continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, easyListStructPointer);
+ continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, ultraListStructPointer);
// 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 continueChecking;
}
-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;
-}
-
bool FilterListHelper::checkIndividualList(QWebEngineUrlRequestInfo &urlRequestInfo, UrlStruct &urlStruct, RequestStruct *requestStructPointer, FilterListStruct *filterListStructPointer) const
{
+ // Initiate a continue checking tracker. If the tracker changes to false, all process of the request will be stopped.
+ bool continueChecking = true;
+
// Check the main allow list.
- for (auto filterListEntry = filterListStructPointer->mainAllowList.begin(); filterListEntry != filterListStructPointer->mainAllowList.end(); ++filterListEntry)
+ 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->appliedEntry.isEmpty())
+ if (!entryStructPointer->appliedEntryList[0].isEmpty())
{
- // Check if the URL string contains the applied entry.
- if (urlStruct.urlString.contains(entryStructPointer->appliedEntry) || urlStruct.urlStringWithSeparators.contains(entryStructPointer->appliedEntry))
+ // 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);
}
}
+ // Get the main block list end.
+ auto mainBlockListEnd = filterListStructPointer->mainBlockListPointer->end();
+
// Check the main block list.
- for (auto filterListEntry = filterListStructPointer->mainBlockList.begin(); filterListEntry != filterListStructPointer->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;
- // TODO. Temporarily ignore empty applied entries.
- if (!entryStructPointer->appliedEntry.isEmpty())
+ // Check the applied entries.
+ continueChecking = checkAppliedEntry(urlRequestInfo, urlStruct, requestStructPointer, filterListStructPointer->title, MAIN_BLOCKLIST, entryStructPointer, urlStruct.urlString,
+ urlStruct.urlStringWithSeparators);
+ }
+
+ // Get the initial domain block list end.
+ auto initialDomainBlockListEnd = filterListStructPointer->initialDomainBlockListPointer->end();
+
+ // 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);
+ }
+
+ // 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 (urlStruct.urlString.contains(entryStructPointer->appliedEntry) || urlStruct.urlStringWithSeparators.contains(entryStructPointer->appliedEntry))
+ if (urlString.contains(entryStructPointer->appliedEntryList[0]) || urlStringWithSeparators.contains(entryStructPointer->appliedEntryList[0]))
{
- // Check the third-party status.
- bool continueChecking = checkThirdParty(urlRequestInfo, requestStructPointer, urlStruct.isThirdPartyRequest, filterListStructPointer->title, MAIN_BLOCKLIST, entryStructPointer);
+ // 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();
+
+ // 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;
+ }
+ }
- // Stop processing the filter lists if continue checking is `false`. Returning false halts all processing at upper levels.
- if (continueChecking == false)
- return 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);
}
- // Check the initial domain block list.
- for (auto filterListEntry = filterListStructPointer->initialDomainBlockList.begin(); filterListEntry != filterListStructPointer->initialDomainBlockList.end(); ++filterListEntry)
+ // 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))
{
- // Get the entry struct.
- EntryStruct *entryStructPointer = *filterListEntry;
+ // Check the domain status.
+ return checkDomain(urlRequestInfo, urlStruct, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ }
- // Check if the truncated URL string begins with the applied entry.
- if (urlStruct.truncatedUrlString.startsWith(entryStructPointer->appliedEntry) || urlStruct.truncatedUrlStringWithSeparators.startsWith(entryStructPointer->appliedEntry))
+ // 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 the third-party status.
- bool continueChecking = checkThirdParty(urlRequestInfo, requestStructPointer, urlStruct.isThirdPartyRequest, filterListStructPointer->title, INITIAL_DOMAIN_BLOCKLIST, entryStructPointer);
+ // 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;
- // Stop processing the filter lists if continue checking is `false`. Returning false halts all processing at upper levels.
- if (continueChecking == false)
- return false;
+ // 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);
}
}
- // Return `true` to continue processing the URL request.
+ // There is a domain specified that doesn't match this request. Return `true` to continue processing the URL request.
return true;
}
// Check third-party status.
if (entryStructPointer->thirdParty == FilterOptionEnum::Disposition::Null) // Ignore third-party status.
{
- // Check if filter options are applied.
- if (entryStructPointer->hasFilterOptions) // Filter options are applied.
+ // Check if request options are applied.
+ if (entryStructPointer->hasRequestOptions) // Request options are applied.
{
- // Process the filter options.
- return processFilterOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ // Check the request options.
+ return checkRequestOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
}
- else // Filter options are not applied.
+ 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 filter options are applied.
- if (entryStructPointer->hasFilterOptions) // Filter options are applied.
+ // Check if request options are applied.
+ if (entryStructPointer->hasRequestOptions) // Request options are applied.
{
- // Process the filter options.
- return processFilterOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ // Check the request options.
+ return checkRequestOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
}
- else // Filter options are not applied.
+ 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 filter options are applied.
- if (entryStructPointer->hasFilterOptions) // Filter options are applied.
+ // Check if request options are applied.
+ if (entryStructPointer->hasRequestOptions) // Request options are applied.
{
- // Process the filter options.
- return processFilterOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ // Check the request options.
+ return checkRequestOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
}
- else // Filter options are not applied.
+ else // Request options are not applied.
{
// Block the request.
return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
}
}
- // Returning `true` continues to process the filter lists. Returning `false` halts all processing of the filter lists.
+ // 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::getFilterOptionDispositionString(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::getNavigationTypeString(int navigationTypeInt) const
{
// Return the translated navigation type 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.
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.
}
}
}
else // Process the filter options.
{
- // Split any filter options from the end of the string.
- QStringList splitEntryStringList = filterListString.split(QLatin1Char('$'));
-
- // Store the entry without the filter options as the filter list string.
- filterListString = splitEntryStringList[0];
-
- // Create a popup only filter option tracker.
- bool popupOnlyFilterOption = false;
+ // Get the index of the last dollar sign.
+ int indexOfLastDollarSign = filterListString.lastIndexOf(QLatin1Char('$'));
// Process the filter options if they exist.
- if (splitEntryStringList.size() > 1)
+ if (indexOfLastDollarSign > -1)
{
- // Store the filter options.
- entryStructPointer->filterOptions = splitEntryStringList[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 filterOptionsList = splitEntryStringList[1].split(QLatin1Char(','));
+ QStringList originalFilterOptionsList = entryStructPointer->originalFilterOptions.split(QLatin1Char(','));
- // Check if the entry has a single popup filter option as Qt WebEngine doesn't know how to process them.
- if ((filterOptionsList.size() == 1) && (filterOptionsList[0] == QLatin1String("popup"))) // This entry has a single popup filter option.
+ // Create an applied filter options list.
+ QStringList appliedFilterOptionsList;
+
+ // Populate the applied filter options list.
+ foreach (QString filterOption, originalFilterOptionsList)
{
- // Set the popup only filter option flag.
- popupOnlyFilterOption = true;
+ // 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);
}
- else // This entry has filter options besides popup.
- {
- // Initialize an override struct.
- OverrideStruct overrideStruct;
- // Populate the filter options entries.
- foreach (QString filterOption, filterOptionsList)
- {
- // Populate the third-party options.
- if (filterOption == QLatin1String("third-party")) entryStructPointer->thirdParty = FilterOptionEnum::Disposition::Apply;
- if (filterOption == QLatin1String("~third-party")) entryStructPointer->thirdParty = FilterOptionEnum::Disposition::Override;
-
- // Populate the filter options.
- if (filterOption == QLatin1String("document"))
- {
- // Populate the main frame option.
- entryStructPointer->mainFrame = FilterOptionEnum::Disposition::Apply;
-
- // Set the filter options flag.
- entryStructPointer->hasFilterOptions = true;
- }
-
- if (filterOption == QLatin1String("font"))
- {
- // Populate the font option.
- entryStructPointer->font = FilterOptionEnum::Disposition::Apply;
-
- // Set the filter options flag.
- entryStructPointer->hasFilterOptions = true;
- }
-
- if (filterOption == QLatin1String("image"))
- {
- // Populate the image option.
- entryStructPointer->image = FilterOptionEnum::Disposition::Apply;
+ // Store the applied filter options list.
+ entryStructPointer->appliedFilterOptionsList = appliedFilterOptionsList;
- // Set the filter options flag.
- entryStructPointer->hasFilterOptions = true;
- }
+ // Initialize an override struct.
+ OverrideStruct overrideStruct;
- if (filterOption == QLatin1String("media"))
- {
- // Populate the media option.
- entryStructPointer->media = FilterOptionEnum::Disposition::Apply;
+ // 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);
- // Set the filter options flag.
- entryStructPointer->hasFilterOptions = true;
- }
+ // Store the domain list.
+ entryStructPointer->domainList = filterOption.split(QLatin1Char('|'));
- if (filterOption == QLatin1String("object"))
+ // Set the disposition.
+ if (entryStructPointer->domainList[0].startsWith(QLatin1Char('~'))) // Override domains.
{
- // Populate the object option.
- entryStructPointer->object = FilterOptionEnum::Disposition::Apply;
+ // Populate the domain filter disposition.
+ entryStructPointer->domain = FilterOptionEnum::Disposition::Override;
- // Set the filter options flag.
- entryStructPointer->hasFilterOptions = true;
+ // Remove the initial `~` from each domain.
+ entryStructPointer->domainList.replaceInStrings(QLatin1String("~"), QLatin1String(""));
}
-
- if (filterOption == QLatin1String("other"))
+ else // Standard domains.
{
- // Populate the other option.
- entryStructPointer->other = FilterOptionEnum::Disposition::Apply;
-
- // Set the filter options flag.
- entryStructPointer->hasFilterOptions = true;
+ // 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;
- if (filterOption == QLatin1String("ping"))
- {
- // Populate the ping option.
- entryStructPointer->ping = 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 filter options flag.
- entryStructPointer->hasFilterOptions = true;
- }
+ // Set the has request options flag.
+ entryStructPointer->hasRequestOptions = true;
+ }
+ else if (filterOption == QLatin1String("image")) // Image.
+ {
+ // Populate the image disposition.
+ entryStructPointer->image = FilterOptionEnum::Disposition::Apply;
- if (filterOption == QLatin1String("script"))
- {
- // Populate the script option.
- entryStructPointer->script = 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 filter options flag.
- entryStructPointer->hasFilterOptions = true;
- }
+ // Set the has request options flag.
+ entryStructPointer->hasRequestOptions = true;
+ }
+ else if (filterOption == QLatin1String("object")) // Object.
+ {
+ // Populate the object disposition.
+ entryStructPointer->object = FilterOptionEnum::Disposition::Apply;
- if (filterOption == QLatin1String("stylesheet"))
- {
- // Populate the script option.
- entryStructPointer->styleSheet = 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 filter options flag.
- entryStructPointer->hasFilterOptions = true;
- }
+ // Set the has request options flag.
+ entryStructPointer->hasRequestOptions = true;
+ }
+ else if (filterOption == QLatin1String("ping")) // Ping.
+ {
+ // Populate the ping disposition.
+ entryStructPointer->ping = FilterOptionEnum::Disposition::Apply;
- if (filterOption == QLatin1String("subdocument"))
- {
- // Populate the sub resource option.
- entryStructPointer->subFrame = 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 filter options flag.
- entryStructPointer->hasFilterOptions = true;
- }
+ // 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;
- if (filterOption == QLatin1String("xmlhttprequest"))
- {
- //Populate the XML HTTP request option.
- entryStructPointer->xmlHttpRequest = 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 filter options flag.
- entryStructPointer->hasFilterOptions = true;
- }
+ // 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.
- if (filterOption == QLatin1String("~document"))
- {
- // Populate the override struct.
- overrideStruct.hasOverride = true;
- overrideStruct.mainFrame = true;
- }
-
- if (filterOption == QLatin1String("~font"))
- {
- // Populate the override struct.
- overrideStruct.hasOverride = true;
- overrideStruct.font = true;
- }
-
- if (filterOption == QLatin1String("~image"))
- {
- // Populate the override struct.
- overrideStruct.hasOverride = true;
- overrideStruct.image = true;
- }
-
- if (filterOption == QLatin1String("~media"))
- {
- // Populate the override struct.
- overrideStruct.hasOverride = true;
- overrideStruct.media = true;
- }
-
- if (filterOption == QLatin1String("~object"))
- {
- // Populate the override struct.
- overrideStruct.hasOverride = true;
- overrideStruct.object = true;
- }
-
- if (filterOption == QLatin1String("~other"))
- {
- // Populate the override struct.
- overrideStruct.hasOverride = true;
- overrideStruct.other = true;
- }
-
- if (filterOption == QLatin1String("~ping"))
- {
- // Populate the override struct.
- overrideStruct.hasOverride = true;
- overrideStruct.ping = true;
- }
-
- if (filterOption == QLatin1String("~script"))
- {
- // Populate the override struct.
- overrideStruct.hasOverride = true;
- overrideStruct.script = true;
- }
-
- if (filterOption == QLatin1String("~stylesheet"))
- {
- // Populate the override struct.
- overrideStruct.hasOverride = true;
- overrideStruct.styleSheet = true;
- }
-
- if (filterOption == QLatin1String("~subdocument"))
- {
- // Populate the override struct.
- overrideStruct.hasOverride = true;
- overrideStruct.subFrame = true;
- }
-
- if (filterOption == QLatin1String("~xmlhttprequest"))
- {
- // Populate the override struct.
- overrideStruct.hasOverride = true;
- overrideStruct.xmlHttpRequest = true;
- }
+ overrideStruct.hasOverride = true;
+ overrideStruct.mainFrame = true;
}
-
- // Apply the overrides.
- if (overrideStruct.hasOverride)
+ 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.
{
- // 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;
-
- // XML HTTP Request.
- if (overrideStruct.xmlHttpRequest)
- entryStructPointer->xmlHttpRequest = FilterOptionEnum::Disposition::Override;
- else
- entryStructPointer->xmlHttpRequest = FilterOptionEnum::Disposition::Apply;
+ // Populate the override struct.
+ overrideStruct.hasOverride = true;
+ overrideStruct.xmlHttpRequest = true;
}
}
- }
- // Drop entries that only have a single popup filter option as Qt WebEngine doesn't know how to process them.
- if (popupOnlyFilterOption) // This entry has a single popup filter option.
+ // 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;
+
+ // XML HTTP Request.
+ if (overrideStruct.xmlHttpRequest)
+ entryStructPointer->xmlHttpRequest = FilterOptionEnum::Disposition::Override;
+ else
+ entryStructPointer->xmlHttpRequest = FilterOptionEnum::Disposition::Apply;
+ }
+ } // Finish processing filter options.
+
+
+ if (filterListString.isEmpty() && !entryStructPointer->hasRequestOptions) // There are no applied entries and no request options.
{
- // Do nothing.
+ // 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 line.
- //qDebug().noquote().nospace() << entryStructPointer->originalEntry << " NOT added from " << filterListFileName << " (single popup filter option).";
+ // 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);
- // Remove any initial and trailing asterisks.
- removeInitialAndTrailingAsterisks(filterListString);
+ // Prepare the filter list string. TODO. Initial allow lists must be processed first.
+ prepareFilterListString(filterListString, entryStructPointer);
- // Add the applied entry to the struct.
- entryStructPointer->appliedEntry = filterListString;
-
- // Add the filter list entry struct to the main allow list.
- filterListStructPointer->mainAllowList.push_front(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 allow list entry.
+ else if (filterListString.startsWith(QLatin1String("||"))) // Process an initial domain block list entry.
{
// Remove the initial `||`.
filterListString.remove(0, 2);
- // Add the applied entry to the struct.
- entryStructPointer->appliedEntry = filterListString;
+ // Set the initial match flag.
+ entryStructPointer->initialMatch = true;
+
+ // Prepare the filter list string.
+ prepareFilterListString(filterListString, entryStructPointer);
- // Add the filter list entry struct to the initial domain block list.
- filterListStructPointer->initialDomainBlockList.push_front(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 // Process a block list entry.
+ else if (filterListString.contains(QLatin1String("\\"))) // Process a regular expression block list entry.
{
- // Remove any initial and trailing asterisks.
- removeInitialAndTrailingAsterisks(filterListString);
+ // Add the regular expression to the applied entry list.
+ entryStructPointer->appliedEntryList.append(filterListString);
- // Add the applied entry to the struct.
- entryStructPointer->appliedEntry = 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 filter list entry struct to the main block list.
- filterListStructPointer->mainBlockList.push_front(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 << ".";
requestStructPointer->dispositionInt = disposition;
requestStructPointer->filterListTitle = filterListTitle;
requestStructPointer->sublistInt = sublistInt;
- requestStructPointer->entryStruct.appliedEntry = entryStructPointer->appliedEntry;
+ requestStructPointer->entryStruct.appliedEntryList = entryStructPointer->appliedEntryList;
requestStructPointer->entryStruct.originalEntry = entryStructPointer->originalEntry;
}
-bool FilterListHelper::processFilterOptions(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt,
- EntryStruct *entryStructPointer) const
+void FilterListHelper::prepareFilterListString(QString &filterListString, 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)))
+ // Check if this is an initial match.
+ if (filterListString.startsWith(QLatin1Char('|')))
{
- // Block the request.
- return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
- }
+ // Strip the initial `|`.
+ filterListString.remove(0, 1);
- // Block ping requests
- if ((entryStructPointer->ping == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypePing))
- {
- // Block the request.
- return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ // Set the initial match flag.
+ entryStructPointer->initialMatch = true;
}
- // Block script requests.
- if ((entryStructPointer->script == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeScript))
+ // Check if this is a final match.
+ if (filterListString.endsWith(QLatin1Char('|')))
{
- // Block the request.
- return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
- }
+ // Strip the final `|`.
+ filterListString.chop(1);
- // Block style sheet requests.
- if ((entryStructPointer->styleSheet == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeStylesheet))
- {
- // Block the request.
- return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+ // Set the final match flag.
+ entryStructPointer->finalMatch = true;
}
- // 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);
- }
+ // Remove the initial asterisk if it exists.
+ if (filterListString.startsWith(QLatin1Char('*')))
+ filterListString.remove(0, 1);
- // Block XML HTTP requests.
- if ((entryStructPointer->xmlHttpRequest == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeXhr))
- {
- // Block the request.
- return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
- }
+ // Remove the final asterisk if it exists.
+ if (filterListString.endsWith(QLatin1Char('*')))
+ filterListString.chop(1);
- // Returning true continues processing the filter list.
- return true;
-}
+ // Split the filter list string and set it as the applied entry list.
+ entryStructPointer->appliedEntryList = filterListString.split(QLatin1Char('*'));
-void FilterListHelper::removeInitialAndTrailingAsterisks(QString &filterListEntry) const
-{
- // Remove the initial asterisk if it exists.
- if (filterListEntry.startsWith(QLatin1Char('*')))
- filterListEntry.remove(0, 1);
+ // Store the size of the applied entry list.
+ entryStructPointer->sizeOfAppliedEntryList = entryStructPointer->appliedEntryList.size();
- // Remove the final asterisk if it exists.
- if (filterListEntry.endsWith(QLatin1Char('*')))
- filterListEntry.chop(1);
+ // Determine if this is a single applied entry (including an empty entry).
+ entryStructPointer->singleAppliedEntry = (entryStructPointer->sizeOfAppliedEntryList == 1);
}