]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/blobdiff - src/helpers/FilterListHelper.cpp
Filter options implementation.
[PrivacyBrowserPC.git] / src / helpers / FilterListHelper.cpp
index e49af5b20e5f2d7a09a4fa0e517f2b888d31c65a..f84112b58531ad17f1262eb68dd5e7dff5161403 100644 (file)
@@ -19,6 +19,7 @@
 
 // Application headers.
 #include "FilterListHelper.h"
+#include "structs/OverrideStruct.h"
 
 // Qt toolkit headers.
 #include <QDebug>
@@ -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);
 }