X-Git-Url: https://gitweb.stoutner.com/?a=blobdiff_plain;ds=sidebyside;f=src%2Fhelpers%2FFilterListHelper.cpp;fp=src%2Fhelpers%2FFilterListHelper.cpp;h=f84112b58531ad17f1262eb68dd5e7dff5161403;hb=f8f8d907d0caa128abf73696f812f8e92db812b7;hp=e49af5b20e5f2d7a09a4fa0e517f2b888d31c65a;hpb=a44e607fb5398c80c5de2629017865ae749e8fbf;p=PrivacyBrowserPC.git diff --git a/src/helpers/FilterListHelper.cpp b/src/helpers/FilterListHelper.cpp index e49af5b..f84112b 100644 --- a/src/helpers/FilterListHelper.cpp +++ b/src/helpers/FilterListHelper.cpp @@ -19,6 +19,7 @@ // Application headers. #include "FilterListHelper.h" +#include "structs/OverrideStruct.h" // Qt toolkit headers. #include @@ -36,6 +37,11 @@ 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"); @@ -69,7 +75,9 @@ FilterListHelper::FilterListHelper() 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"); // Populate the filter lists. ultraListStructPointer = populateFilterList(QLatin1String(":/filterlists/ultralist.txt")); @@ -81,47 +89,154 @@ FilterListHelper::FilterListHelper() 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 process 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(); + QString requestHost = requestUrl.host(); + + // Determine if this is a third-party request. + urlStruct.isThirdPartyRequest = (firstPartyHost != requestHost); + + // 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. + 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, ultraListStructPointer); - // check UltraPrivacy if the status is still true. - if (status) { - status = checkIndividualList(urlRequestInfo, requestStructPointer, ultraPrivacyStructPointer); - } + // Check UltraPrivacy. + if (continueChecking) + continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, ultraPrivacyStructPointer); - // Return the status. - return status; + // Check EasyList. + if (continueChecking) + continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, easyListStructPointer); + + // Check EasyPrivacy. + if (continueChecking) + continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, easyPrivacyStructPointer); + + 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::blockRequest(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt, + EntryStruct *entryStructPointer) const { - // Get the request URL. - QUrl url = urlRequestInfo.requestUrl(); + // Block the request. + urlRequestInfo.block(true); - // Get the request URL string. - QString urlString = url.toString(); + // 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 +{ + // Check the main allow list. + for (auto filterListEntry = filterListStructPointer->mainAllowList.begin(); filterListEntry != filterListStructPointer->mainAllowList.end(); ++filterListEntry) + { + // Get the entry struct. + EntryStruct *entryStructPointer = *filterListEntry; + + // TODO. Temporarily ignore empty applied entries. + if (!entryStructPointer->appliedEntry.isEmpty()) + { + // Check if the URL string contains the applied entry. + if (urlStruct.urlString.contains(entryStructPointer->appliedEntry) || urlStruct.urlStringWithSeparators.contains(entryStructPointer->appliedEntry)) + { + // 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; + } + } + } // Check the main block list. - for (auto filterListEntry = filterListStruct->mainBlockList.begin(); filterListEntry != filterListStruct->mainBlockList.end(); ++filterListEntry) { + for (auto filterListEntry = filterListStructPointer->mainBlockList.begin(); filterListEntry != filterListStructPointer->mainBlockList.end(); ++filterListEntry) + { // Get the entry struct. EntryStruct *entryStructPointer = *filterListEntry; - // Check if the URL string contains the applied entry - if (urlString.contains(entryStructPointer->appliedEntry)) { - // Block the request. - urlRequestInfo.block(true); + // TODO. Temporarily ignore empty applied entries. + if (!entryStructPointer->appliedEntry.isEmpty()) + { + // Check if the URL string contains the applied entry. + if (urlStruct.urlString.contains(entryStructPointer->appliedEntry) || urlStruct.urlStringWithSeparators.contains(entryStructPointer->appliedEntry)) + { + // Check the third-party status. + bool continueChecking = checkThirdParty(urlRequestInfo, requestStructPointer, urlStruct.isThirdPartyRequest, filterListStructPointer->title, MAIN_BLOCKLIST, entryStructPointer); - // Populate the request struct. - populateRequestStruct(requestStructPointer, BLOCKED, filterListStruct->title, MAIN_BLOCKLIST, entryStructPointer->appliedEntry, entryStructPointer->originalEntry); + // 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 initial domain block list. + for (auto filterListEntry = filterListStructPointer->initialDomainBlockList.begin(); filterListEntry != filterListStructPointer->initialDomainBlockList.end(); ++filterListEntry) + { + // Get the entry struct. + EntryStruct *entryStructPointer = *filterListEntry; - // Log the block. - //qDebug().noquote().nospace() << "Blocked request: " << urlString << ", Filter list entry: " << entryStructPointer->appliedEntry; + // Check if the truncated URL string begins with the applied entry. + if (urlStruct.truncatedUrlString.startsWith(entryStructPointer->appliedEntry) || urlStruct.truncatedUrlStringWithSeparators.startsWith(entryStructPointer->appliedEntry)) + { + // Check the third-party status. + bool continueChecking = checkThirdParty(urlRequestInfo, requestStructPointer, urlStruct.isThirdPartyRequest, filterListStructPointer->title, INITIAL_DOMAIN_BLOCKLIST, entryStructPointer); - // Returning `false` stops all processing of the request. - return false; + // Stop processing the filter lists if continue checking is `false`. Returning false halts all processing at upper levels. + if (continueChecking == false) + return false; } } @@ -129,6 +244,57 @@ bool FilterListHelper::checkIndividualList(QWebEngineUrlRequestInfo &urlRequestI 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 filter options are applied. + if (entryStructPointer->hasFilterOptions) // Filter options are applied. + { + // Process the filter options. + return processFilterOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer); + } + else // Filter 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. + { + // Process the filter options. + return processFilterOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer); + } + else // Filter 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. + { + // Process the filter options. + return processFilterOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer); + } + else // Filter 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. + return true; +} + QString FilterListHelper::getDispositionString(int dispositionInt) const { // Return the translated disposition string. @@ -140,6 +306,17 @@ QString FilterListHelper::getDispositionString(int dispositionInt) const } } +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. @@ -189,7 +366,9 @@ QString FilterListHelper::getSublistName(int sublistInt) const // 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; default: return QString(); // The default return should never be reached. } } @@ -223,12 +402,32 @@ FilterListStruct* FilterListHelper::populateFilterList(const QString &filterList 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; - } else if (filterListString.startsWith(QLatin1Char('!'))) { // The line starts with `!`, which are comments. + //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 << " (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. @@ -250,15 +449,349 @@ FilterListStruct* FilterListHelper::populateFilterList(const QString &filterList // 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. + { + // 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; + + // Process the filter options if they exist. + if (splitEntryStringList.size() > 1) + { + // Store the filter options. + entryStructPointer->filterOptions = splitEntryStringList[1]; + + // Split the filter options. + QStringList filterOptionsList = splitEntryStringList[1].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. + { + // Set the popup only filter option flag. + popupOnlyFilterOption = true; + } + 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; + + // Set the filter options flag. + entryStructPointer->hasFilterOptions = true; + } + + if (filterOption == QLatin1String("media")) + { + // Populate the media option. + entryStructPointer->media = FilterOptionEnum::Disposition::Apply; + + // Set the filter options flag. + entryStructPointer->hasFilterOptions = true; + } + + if (filterOption == QLatin1String("object")) + { + // Populate the object option. + entryStructPointer->object = FilterOptionEnum::Disposition::Apply; + + // Set the filter options flag. + entryStructPointer->hasFilterOptions = true; + } + + if (filterOption == QLatin1String("other")) + { + // Populate the other option. + entryStructPointer->other = FilterOptionEnum::Disposition::Apply; + + // Set the filter options flag. + entryStructPointer->hasFilterOptions = true; + } + + if (filterOption == QLatin1String("ping")) + { + // Populate the ping option. + entryStructPointer->ping = FilterOptionEnum::Disposition::Apply; + + // Set the filter options flag. + entryStructPointer->hasFilterOptions = true; + } + + if (filterOption == QLatin1String("script")) + { + // Populate the script option. + entryStructPointer->script = FilterOptionEnum::Disposition::Apply; + + // Set the filter options flag. + entryStructPointer->hasFilterOptions = true; + } + + if (filterOption == QLatin1String("stylesheet")) + { + // Populate the script option. + entryStructPointer->styleSheet = FilterOptionEnum::Disposition::Apply; + + // Set the filter options flag. + entryStructPointer->hasFilterOptions = true; + } + + if (filterOption == QLatin1String("subdocument")) + { + // Populate the sub resource option. + entryStructPointer->subFrame = FilterOptionEnum::Disposition::Apply; + + // Set the filter options flag. + entryStructPointer->hasFilterOptions = true; + } + + if (filterOption == QLatin1String("xmlhttprequest")) + { + //Populate the XML HTTP request option. + entryStructPointer->xmlHttpRequest = FilterOptionEnum::Disposition::Apply; + + // Set the filter options flag. + entryStructPointer->hasFilterOptions = true; + } + + // 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; + } + } + + // Apply the overrides. + if (overrideStruct.hasOverride) + { + // 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; + } + } + } + + // 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. + { + // Do nothing. + + // Log the dropping of the line. + //qDebug().noquote().nospace() << entryStructPointer->originalEntry << " NOT added from " << filterListFileName << " (single popup filter option)."; + } + else if (filterListString.startsWith(QLatin1String("@@"))) // Process an allow list entry. + { + // Remove the initial `@@`. + filterListString.remove(0, 2); - // Add the filter list entry struct to the main block list. - filterListStructPointer->mainBlockList.push_front(entryStructPointer); + // Remove any initial and trailing asterisks. + removeInitialAndTrailingAsterisks(filterListString); - // Log the addition to the filter list. - //qDebug().noquote().nospace() << originalFilterListString << " added from " << filterListFileName; + // 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); + + // 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. + { + // Remove the initial `||`. + filterListString.remove(0, 2); + + // Add the applied entry to the struct. + entryStructPointer->appliedEntry = filterListString; + + // Add the filter list entry struct to the initial domain block list. + filterListStructPointer->initialDomainBlockList.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. + { + // Remove any initial and trailing asterisks. + removeInitialAndTrailingAsterisks(filterListString); + + // Add the applied entry to the struct. + entryStructPointer->appliedEntry = filterListString; + + // Add the filter list entry struct to the main block list. + filterListStructPointer->mainBlockList.push_front(entryStructPointer); + + // Log the addition to the filter list. + //qDebug().noquote().nospace() << entryStructPointer->originalEntry << " added to Main Block List from " << filterListFileName << "."; + } } } @@ -269,13 +802,117 @@ FilterListStruct* FilterListHelper::populateFilterList(const QString &filterList 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.appliedEntry = entryStructPointer->appliedEntry; + requestStructPointer->entryStruct.originalEntry = entryStructPointer->originalEntry; +} + +bool FilterListHelper::processFilterOptions(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); + } + + // Returning true continues processing the filter list. + return true; +} + +void FilterListHelper::removeInitialAndTrailingAsterisks(QString &filterListEntry) const +{ + // Remove the initial asterisk if it exists. + if (filterListEntry.startsWith(QLatin1Char('*'))) + filterListEntry.remove(0, 1); + + // Remove the final asterisk if it exists. + if (filterListEntry.endsWith(QLatin1Char('*'))) + filterListEntry.chop(1); }