2 * Copyright 2024 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc/>.
6 * Privacy Browser PC is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Privacy Browser PC is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Privacy Browser PC. If not, see <http://www.gnu.org/licenses/>.
20 // Application headers.
21 #include "FilterListHelper.h"
23 // Qt toolkit headers.
26 #include <QTextStream>
28 // KDE Framework headers.
29 #include <KLocalizedString>
31 // Construct the class.
32 FilterListHelper::FilterListHelper()
34 // Populate the translated disposition strings. Translated entries cannot be public static const.
35 DEFAULT_STRING = i18nc("Default disposition", "Default - Allowed");
36 ALLOWED_STRING = i18nc("Allowed disposition", "Allowed");
37 BLOCKED_STRING = i18nc("Blocked disposition", "Blocked");
39 // Populate the translated navigation type strings. Translated entries cannot be public static const.
40 NAVIGATION_TYPE_LINK = i18nc("Navigation type link", "Link");
41 NAVIGATION_TYPE_TYPED = i18nc("Navigation type typed", "Typed");
42 NAVIGATION_TYPE_FORM_SUBMITTED = i18nc("Navigation type form submitted", "Form Submitted");
43 NAVIGATION_TYPE_BACK_FORWARD = i18nc("Navigation type back/forward", "Back/Forward");
44 NAVIGATION_TYPE_RELOAD = i18nc("Navigation type reload", "Reload");
45 NAVIGATION_TYPE_REDIRECT = i18nc("Navigation type redirect", "Redirect");
46 NAVIGATION_TYPE_OTHER = i18nc("Navigation type other", "Other");
48 // Populate the translated resource type strings. Translated entries cannot be public static const.
49 RESOURCE_TYPE_MAIN_FRAME = i18nc("Resource type main frame", "Main Frame");
50 RESOURCE_TYPE_SUB_FRAME = i18nc("Resource type sub frame", "Sub Frame");
51 RESOURCE_TYPE_STYLESHEET = i18nc("Resource type stylesheet", "Stylesheet");
52 RESOURCE_TYPE_SCRIPT = i18nc("Resource type script", "Script");
53 RESOURCE_TYPE_IMAGE = i18nc("Resource type image", "Image");
54 RESOURCE_TYPE_FONT_RESOURCE = i18nc("Resource type font", "Font");
55 RESOURCE_TYPE_SUB_RESOURCE = i18nc("Resource type sub resource", "Sub Resource");
56 RESOURCE_TYPE_OBJECT = i18nc("Resource type object", "Object");
57 RESOURCE_TYPE_MEDIA = i18nc("Resource type media", "Media");
58 RESOURCE_TYPE_WORKER = i18nc("Resource type worker", "Worker");
59 RESOURCE_TYPE_SHARED_WORKER = i18nc("Resource type shared worker", "Shared Worker");
60 RESOURCE_TYPE_PREFETCH = i18nc("Resource type prefetch", "Prefetch");
61 RESOURCE_TYPE_FAVICON = i18nc("Resource type favicon", "Favicon");
62 RESOURCE_TYPE_XHR = i18nc("Resource type XML HTTP request", "XML HTTP Request");
63 RESOURCE_TYPE_PING = i18nc("Resource type HTTP ping", "HTTP Ping");
64 RESOURCE_TYPE_SERVICE_WORKER = i18nc("Resource type service worker", "Service Worker");
65 RESOURCE_TYPE_CSP_REPORT = i18nc("Resource type content security policy report", "Content Security Policy Report");
66 RESOURCE_TYPE_PLUGIN_RESOURCE = i18nc("Resource type plugin request", "Plugin Request");
67 RESOURCE_TYPE_NAVIGATION_PRELOAD_MAIN_FRAME = i18nc("Resource type preload main frame", "Preload Main Frame");
68 RESOURCE_TYPE_NAVIGATION_PRELOAD_SUB_FRAME = i18nc("Resource type preload sub frame", "Preload Sub Frame");
69 RESOURCE_TYPE_UNKNOWN = i18nc("Resource type unknown", "Unknown");
71 // Populate the translated sublist strings. Translated entries cannot be public static const.
72 MAIN_BLOCKLIST_STRING = i18nc("Main blocklist sublist", "Main Block List");
74 // Populate the filter lists.
75 ultraListStructPointer = populateFilterList(QLatin1String(":/filterlists/ultralist.txt"));
76 ultraPrivacyStructPointer = populateFilterList(QLatin1String(":/filterlists/ultraprivacy.txt"));
77 easyListStructPointer = populateFilterList(QLatin1String(":/filterlists/easylist.txt"));
78 easyPrivacyStructPointer = populateFilterList(QLatin1String(":/filterlists/easyprivacy.txt"));
79 fanboyAnnoyanceStructPointer = populateFilterList(QLatin1String(":/filterlists/fanboy-annoyance.txt"));
82 bool FilterListHelper::checkFilterLists(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer) const
84 // Initiate a status tracker. If the tracker changes to false, all process of the request will be stopped.
88 status = checkIndividualList(urlRequestInfo, requestStructPointer, ultraListStructPointer);
90 // check UltraPrivacy if the status is still true.
92 status = checkIndividualList(urlRequestInfo, requestStructPointer, ultraPrivacyStructPointer);
99 bool FilterListHelper::checkIndividualList(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, FilterListStruct *filterListStruct) const
101 // Get the request URL.
102 QUrl url = urlRequestInfo.requestUrl();
104 // Get the request URL string.
105 QString urlString = url.toString();
107 // Check the main block list.
108 for (auto filterListEntry = filterListStruct->mainBlockList.begin(); filterListEntry != filterListStruct->mainBlockList.end(); ++filterListEntry) {
109 // Get the entry struct.
110 EntryStruct *entryStructPointer = *filterListEntry;
112 // Check if the URL string contains the applied entry
113 if (urlString.contains(entryStructPointer->appliedEntry)) {
114 // Block the request.
115 urlRequestInfo.block(true);
117 // Populate the request struct.
118 populateRequestStruct(requestStructPointer, BLOCKED, filterListStruct->title, MAIN_BLOCKLIST, entryStructPointer->appliedEntry, entryStructPointer->originalEntry);
121 //qDebug().noquote().nospace() << "Blocked request: " << urlString << ", Filter list entry: " << entryStructPointer->appliedEntry;
123 // Returning `false` stops all processing of the request.
128 // Return `true` to continue processing the URL request.
132 QString FilterListHelper::getDispositionString(int dispositionInt) const
134 // Return the translated disposition string.
135 switch (dispositionInt)
137 case ALLOWED: return ALLOWED_STRING;
138 case BLOCKED: return BLOCKED_STRING;
139 default: return DEFAULT_STRING;
143 QString FilterListHelper::getNavigationTypeString(int navigationTypeInt) const
145 // Return the translated navigation type string.
146 switch (navigationTypeInt)
148 case QWebEngineUrlRequestInfo::NavigationTypeLink: return NAVIGATION_TYPE_LINK;
149 case QWebEngineUrlRequestInfo::NavigationTypeTyped: return NAVIGATION_TYPE_TYPED;
150 case QWebEngineUrlRequestInfo::NavigationTypeFormSubmitted: return NAVIGATION_TYPE_FORM_SUBMITTED;
151 case QWebEngineUrlRequestInfo::NavigationTypeBackForward: return NAVIGATION_TYPE_BACK_FORWARD;
152 case QWebEngineUrlRequestInfo::NavigationTypeReload: return NAVIGATION_TYPE_RELOAD;
153 case QWebEngineUrlRequestInfo::NavigationTypeRedirect: return NAVIGATION_TYPE_REDIRECT;
154 default: return NAVIGATION_TYPE_OTHER;
158 QString FilterListHelper::getResourceTypeString(int resourceTypeInt) const
160 // Return the translated resource type string.
161 switch (resourceTypeInt)
163 case QWebEngineUrlRequestInfo::ResourceTypeMainFrame: return RESOURCE_TYPE_MAIN_FRAME;
164 case QWebEngineUrlRequestInfo::ResourceTypeSubFrame: return RESOURCE_TYPE_SUB_FRAME;
165 case QWebEngineUrlRequestInfo::ResourceTypeStylesheet: return RESOURCE_TYPE_STYLESHEET;
166 case QWebEngineUrlRequestInfo::ResourceTypeScript: return RESOURCE_TYPE_SCRIPT;
167 case QWebEngineUrlRequestInfo::ResourceTypeImage: return RESOURCE_TYPE_IMAGE;
168 case QWebEngineUrlRequestInfo::ResourceTypeFontResource: return RESOURCE_TYPE_FONT_RESOURCE;
169 case QWebEngineUrlRequestInfo::ResourceTypeSubResource: return RESOURCE_TYPE_SUB_RESOURCE;
170 case QWebEngineUrlRequestInfo::ResourceTypeObject: return RESOURCE_TYPE_OBJECT;
171 case QWebEngineUrlRequestInfo::ResourceTypeMedia: return RESOURCE_TYPE_MEDIA;
172 case QWebEngineUrlRequestInfo::ResourceTypeWorker: return RESOURCE_TYPE_WORKER;
173 case QWebEngineUrlRequestInfo::ResourceTypeSharedWorker: return RESOURCE_TYPE_SHARED_WORKER;
174 case QWebEngineUrlRequestInfo::ResourceTypePrefetch: return RESOURCE_TYPE_PREFETCH;
175 case QWebEngineUrlRequestInfo::ResourceTypeFavicon: return RESOURCE_TYPE_FAVICON;
176 case QWebEngineUrlRequestInfo::ResourceTypeXhr: return RESOURCE_TYPE_XHR;
177 case QWebEngineUrlRequestInfo::ResourceTypePing: return RESOURCE_TYPE_PING;
178 case QWebEngineUrlRequestInfo::ResourceTypeServiceWorker: return RESOURCE_TYPE_SERVICE_WORKER;
179 case QWebEngineUrlRequestInfo::ResourceTypeCspReport: return RESOURCE_TYPE_CSP_REPORT;
180 case QWebEngineUrlRequestInfo::ResourceTypePluginResource: return RESOURCE_TYPE_PLUGIN_RESOURCE;
181 case QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadMainFrame: return RESOURCE_TYPE_NAVIGATION_PRELOAD_MAIN_FRAME;
182 case QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadSubFrame: return RESOURCE_TYPE_NAVIGATION_PRELOAD_SUB_FRAME;
183 default: return RESOURCE_TYPE_UNKNOWN;
187 QString FilterListHelper::getSublistName(int sublistInt) const
189 // Return the name of the requested sublist.
192 case MAIN_BLOCKLIST: return MAIN_BLOCKLIST_STRING;
193 default: return QString(); // The default return should never be reached.
197 FilterListStruct* FilterListHelper::populateFilterList(const QString &filterListFileName) const
199 // Get the filter list file.
200 QFile filterListFile(filterListFileName);
202 // Open the filter list file.
203 filterListFile.open(QIODevice::ReadOnly);
205 // Create a filter list text stream.
206 QTextStream filterListTextStream(&filterListFile);
208 // Create a filter list struct.
209 FilterListStruct *filterListStructPointer = new FilterListStruct;
211 // Populate the filter list file name.
212 filterListStructPointer->filePath = filterListFileName;
214 // Create a filter list string.
215 QString filterListString;
217 // Process each line of the filter list.
218 while (filterListTextStream.readLineInto(&filterListString)) {
219 // Create an entry struct.
220 EntryStruct *entryStructPointer = new EntryStruct;
222 // Store the original entry.
223 entryStructPointer->originalEntry = filterListString;
225 // Process the entry.
226 if (filterListString.startsWith(QLatin1Char('['))) { // The line starts with `[`, which is the file format.
229 // Log the dropping of the line.
230 //qDebug().noquote().nospace() << filterListString << " NOT added from " << filterListFileName;
231 } else if (filterListString.startsWith(QLatin1Char('!'))) { // The line starts with `!`, which are comments.
232 if (filterListString.startsWith(QLatin1String("! Title: "))) // The line contains the title.
234 // Add the title to the filter list struct.
235 filterListStructPointer->title = filterListString.remove(0, 9);
237 // Log the addition of the filter list title.
238 //qDebug().noquote().nospace() << "Filter list title: " << filterListString << " added from " << filterListFileName;
240 else if (filterListString.startsWith(QLatin1String("! Version: "))) // The line contains the version.
242 // Add the version to the filter list struct.
243 filterListStructPointer->version = filterListString.remove(0, 11);
245 // Log the addition of the filter list version.
246 //qDebug().noquote().nospace() << "Filter list version: " << filterListString << " added from " << filterListFileName;
251 // Log the dropping of the line.
252 //qDebug().noquote().nospace() << originalFilterListString << " NOT added from " << filterListFileName;
253 } else { // Process the entry.
254 // Add the applied entry to the struct.
255 entryStructPointer->appliedEntry = filterListString;
257 // Add the filter list entry struct to the main block list.
258 filterListStructPointer->mainBlockList.push_front(entryStructPointer);
260 // Log the addition to the filter list.
261 //qDebug().noquote().nospace() << originalFilterListString << " added from " << filterListFileName;
265 // Close the filter list file.
266 filterListFile.close();
268 // Return the filter list pair.
269 return filterListStructPointer;
272 void FilterListHelper::populateRequestStruct(RequestStruct *requestStructPointer, const int disposition, const QString &filterListTitle, const int sublistInt, const QString &appliedEntry,
273 const QString &originalEntry) const
275 // Populate the request struct.
276 requestStructPointer->dispositionInt = disposition;
277 requestStructPointer->filterListTitle = filterListTitle;
278 requestStructPointer->sublistInt = sublistInt;
279 requestStructPointer->entryStruct.appliedEntry = appliedEntry;
280 requestStructPointer->entryStruct.originalEntry = originalEntry;