From f8f8d907d0caa128abf73696f812f8e92db812b7 Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Sat, 8 Jun 2024 20:47:22 -0700 Subject: [PATCH] Filter options implementation. --- src/delegates/CMakeLists.txt | 5 +- src/delegates/ViewAndCopyDelegate.cpp | 44 ++ src/delegates/ViewAndCopyDelegate.h | 38 ++ src/delegates/ViewOnlyDelegate.cpp | 6 +- src/delegates/ViewOnlyDelegate.h | 6 +- src/dialogs/FilterListsDialog.cpp | 83 ++- src/dialogs/RequestDetailDialog.cpp | 186 +++++-- src/dialogs/RequestDetailDialog.h | 36 +- src/dialogs/RequestsDialog.cpp | 13 +- src/enums/FilterOptionEnum.h | 32 ++ src/helpers/FilterListHelper.cpp | 715 ++++++++++++++++++++++++-- src/helpers/FilterListHelper.h | 24 +- src/helpers/UserAgentHelper.cpp | 10 +- src/structs/EntryStruct.h | 24 +- src/structs/FilterListStruct.h | 4 +- src/structs/OverrideStruct.h | 38 ++ src/structs/UrlStruct.h | 34 ++ src/uis/AddTabWidget.ui | 2 +- src/uis/FilterListsDialog.ui | 28 +- src/uis/RequestDetailDialog.ui | 87 +++- src/uis/RequestsDialog.ui | 4 - src/uis/TabWidget.ui | 4 +- src/widgets/TabWidget.cpp | 2 +- 23 files changed, 1272 insertions(+), 153 deletions(-) create mode 100644 src/delegates/ViewAndCopyDelegate.cpp create mode 100644 src/delegates/ViewAndCopyDelegate.h create mode 100644 src/enums/FilterOptionEnum.h create mode 100644 src/structs/OverrideStruct.h create mode 100644 src/structs/UrlStruct.h diff --git a/src/delegates/CMakeLists.txt b/src/delegates/CMakeLists.txt index d26efe7..440ec44 100644 --- a/src/delegates/CMakeLists.txt +++ b/src/delegates/CMakeLists.txt @@ -1,6 +1,6 @@ -# Copyright 2022-2023 Soren Stoutner . +# Copyright 2022-2024 Soren Stoutner . # -# This file is part of Privacy Browser PC . +# This file is part of Privacy Browser PC . # # Privacy Browser PC is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,5 +18,6 @@ # List the sources to include in the executable. target_sources(privacybrowser PRIVATE + ViewAndCopyDelegate.cpp ViewOnlyDelegate.cpp ) diff --git a/src/delegates/ViewAndCopyDelegate.cpp b/src/delegates/ViewAndCopyDelegate.cpp new file mode 100644 index 0000000..d3eb1f3 --- /dev/null +++ b/src/delegates/ViewAndCopyDelegate.cpp @@ -0,0 +1,44 @@ + /* + * Copyright 2024 Soren Stoutner . + * + * This file is part of Privacy Browser PC . + * + * Privacy Browser PC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Privacy Browser PC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Privacy Browser PC. If not, see . + */ + +// Application headers. +#include "ViewAndCopyDelegate.h" + +// Qt toolkit headers. +#include + +ViewAndCopyDelegate::ViewAndCopyDelegate(QObject *parentObjectPointer) : QStyledItemDelegate(parentObjectPointer) {} + +QWidget* ViewAndCopyDelegate::createEditor(QWidget *parentWidgetPointer, const QStyleOptionViewItem &styleOptionViewItem, const QModelIndex &modelIndex) const +{ + // Instruct the compiler to ignore the unused variables. + (void) styleOptionViewItem; + + // Get the data string from the model index. + QString dataString = modelIndex.data().toString(); + + // Create a line edit. + QLineEdit *lineEditPointer = new QLineEdit(dataString, parentWidgetPointer); + + // Set the line edit to be read only. + lineEditPointer->setReadOnly(true); + + // Return the line edit. + return lineEditPointer; +} diff --git a/src/delegates/ViewAndCopyDelegate.h b/src/delegates/ViewAndCopyDelegate.h new file mode 100644 index 0000000..722add4 --- /dev/null +++ b/src/delegates/ViewAndCopyDelegate.h @@ -0,0 +1,38 @@ +/* + * Copyright 2024 Soren Stoutner . + * + * This file is part of Privacy Browser PC . + * + * Privacy Browser PC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Privacy Browser PC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Privacy Browser PC. If not, see . + */ + +#ifndef VIEWANDCOPYDELEGATE_H +#define VIEWANDCOPYDELEGATE_H + +// Qt toolkit headers. +#include + +class ViewAndCopyDelegate : public QStyledItemDelegate +{ + // Include the Q_OBJECT macro. + Q_OBJECT + +public: + // The default constructor. + explicit ViewAndCopyDelegate(QObject *parenObjectPointer = nullptr); + + // The public functions. + QWidget* createEditor(QWidget *parentWidgetPointer, const QStyleOptionViewItem &styleOptionViewItem, const QModelIndex &modelIndex) const override; +}; +#endif diff --git a/src/delegates/ViewOnlyDelegate.cpp b/src/delegates/ViewOnlyDelegate.cpp index ab7f873..3bfc991 100644 --- a/src/delegates/ViewOnlyDelegate.cpp +++ b/src/delegates/ViewOnlyDelegate.cpp @@ -1,7 +1,7 @@ /* - * Copyright © 2022 Soren Stoutner . + * Copyright 2022, 2024 Soren Stoutner . * - * This file is part of Privacy Browser PC . + * This file is part of Privacy Browser PC . * * Privacy Browser PC is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ // Application headers. #include "ViewOnlyDelegate.h" -ViewOnlyDelegate::ViewOnlyDelegate(QObject *parentPointer) : QStyledItemDelegate(parentPointer) {} +ViewOnlyDelegate::ViewOnlyDelegate(QObject *parentObjectPointer) : QStyledItemDelegate(parentObjectPointer) {} QWidget* ViewOnlyDelegate::createEditor(QWidget *parentWidgetPointer, const QStyleOptionViewItem &styleOptionsViewItem, const QModelIndex &modelIndex) const { diff --git a/src/delegates/ViewOnlyDelegate.h b/src/delegates/ViewOnlyDelegate.h index 774335c..db73dbf 100644 --- a/src/delegates/ViewOnlyDelegate.h +++ b/src/delegates/ViewOnlyDelegate.h @@ -1,7 +1,7 @@ /* - * Copyright © 2022 Soren Stoutner . + * Copyright 2022, 2024 Soren Stoutner . * - * This file is part of Privacy Browser PC . + * This file is part of Privacy Browser PC . * * Privacy Browser PC is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,7 +30,7 @@ class ViewOnlyDelegate : public QStyledItemDelegate public: // The default constructor. - explicit ViewOnlyDelegate(QObject *parentPointer = nullptr); + explicit ViewOnlyDelegate(QObject *parentObjectPointer = nullptr); // The public functions. QWidget* createEditor(QWidget *parentWidgetPointer, const QStyleOptionViewItem &styleOptionsViewItem, const QModelIndex &modelIndex) const override; diff --git a/src/dialogs/FilterListsDialog.cpp b/src/dialogs/FilterListsDialog.cpp index dbba88e..0ab6753 100644 --- a/src/dialogs/FilterListsDialog.cpp +++ b/src/dialogs/FilterListsDialog.cpp @@ -21,6 +21,7 @@ #include "FilterListsDialog.h" #include "GlobalVariables.h" #include "ui_FilterListsDialog.h" +#include "delegates/ViewAndCopyDelegate.h" // Qt toolkit headers. #include @@ -48,6 +49,12 @@ FilterListsDialog::FilterListsDialog(QWidget *parentWidgetPointer) : QDialog(par sublistTableWidgetPointer = filterListsDialogUi.sublistTableWidget; QDialogButtonBox *dialogButtonBoxPointer = filterListsDialogUi.dialogButtonBox; + // Create a view and copy delegate. + ViewAndCopyDelegate *viewAndCopyDelegate = new ViewAndCopyDelegate(this); + + // Set the sublist table widget allow copying but not editing. + sublistTableWidgetPointer->setItemDelegate(viewAndCopyDelegate); + // Connect the combo boxes. connect(filterListComboBoxPointer, SIGNAL(currentIndexChanged(int)), this, SLOT(populateFilterListTextEdit(int))); connect(sublistComboBoxPointer, SIGNAL(currentIndexChanged(int)), this, SLOT(populateTableWidget(int))); @@ -113,14 +120,20 @@ void FilterListsDialog::populateFilterListTextEdit(int filterListComboBoxInt) co // Clear the sublist combo box. sublistComboBoxPointer->clear(); - // Calculate the size of the main filter list. + // Calculate the size of the filter lists. + int mainAllowListSize = distance(filterListStructPointer->mainAllowList.begin(), filterListStructPointer->mainAllowList.end()); int mainBlockListSize = distance(filterListStructPointer->mainBlockList.begin(), filterListStructPointer->mainBlockList.end()); + int initialDomainBlockListSize = distance(filterListStructPointer->initialDomainBlockList.begin(), filterListStructPointer->initialDomainBlockList.end()); // Get the translated filter list names. + QString mainAllowListName = globalFilterListHelperPointer->getSublistName(FilterListHelper::MAIN_ALLOWLIST); QString mainBlockListName = globalFilterListHelperPointer->getSublistName(FilterListHelper::MAIN_BLOCKLIST); + QString initialDomainBlockListName = globalFilterListHelperPointer->getSublistName(FilterListHelper::INITIAL_DOMAIN_BLOCKLIST); // Populate the sublist combo box. + sublistComboBoxPointer->addItem(i18nc("The main allow list", "%1 - %2", mainAllowListName, mainAllowListSize)); sublistComboBoxPointer->addItem(i18nc("The main block list", "%1 - %2", mainBlockListName, mainBlockListSize)); + sublistComboBoxPointer->addItem(i18nc("The initial domain block list", "%1 - %2", initialDomainBlockListName, initialDomainBlockListSize)); } void FilterListsDialog::populateTableWidget(int sublistComboBoxIndex) const @@ -163,21 +176,55 @@ void FilterListsDialog::populateTableWidget(int sublistComboBoxIndex) const // Populate the filter list forward list. switch (sublistComboBoxIndex) { - case 0: // Main block list. + case FilterListHelper::MAIN_ALLOWLIST: // The main allow list. + filterListForwardList = filterListStructPointer->mainAllowList; + break; + + case FilterListHelper::MAIN_BLOCKLIST: // The main block list. filterListForwardList = filterListStructPointer->mainBlockList; break; + + case FilterListHelper::INITIAL_DOMAIN_BLOCKLIST: // The initial domain block list. + filterListForwardList = filterListStructPointer->initialDomainBlockList; + break; } // Create the columns. - sublistTableWidgetPointer->setColumnCount(2); + sublistTableWidgetPointer->setColumnCount(15); // Create the table headers. QTableWidgetItem *appliedEntryHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist applied entry header", "Applied Entry")); + QTableWidgetItem *thirdPartyHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist third-party header", "Third-Party")); + QTableWidgetItem *fontHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist font header", "Font")); + QTableWidgetItem *imageHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist image header", "Image")); + QTableWidgetItem *mainFrameHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist main frame header", "Main Frame")); + QTableWidgetItem *mediaHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist media header", "Media")); + QTableWidgetItem *objectHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist object header", "Object")); + QTableWidgetItem *otherHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist object header", "Other")); + QTableWidgetItem *pingHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist ping header", "Ping")); + QTableWidgetItem *scriptHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist script header", "Script")); + QTableWidgetItem *styleSheetHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist style sheet header", "Style Sheet")); + QTableWidgetItem *subFrameHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist sub frame header", "Sub Frame")); + QTableWidgetItem *xmlHttpRequestHeaderItemPointer = new QTableWidgetItem(i18nc("XML HTTP request header", "XML HTTP Request")); + QTableWidgetItem *filterOptionsHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist filter options header", "Filter Options")); QTableWidgetItem *originalEntryHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist original entry header", "Original Entry")); // Set the horizontal headers. sublistTableWidgetPointer->setHorizontalHeaderItem(0, appliedEntryHeaderItemPointer); - sublistTableWidgetPointer->setHorizontalHeaderItem(1, originalEntryHeaderItemPointer); + sublistTableWidgetPointer->setHorizontalHeaderItem(1, thirdPartyHeaderItemPointer); + sublistTableWidgetPointer->setHorizontalHeaderItem(2, fontHeaderItemPointer); + sublistTableWidgetPointer->setHorizontalHeaderItem(3, imageHeaderItemPointer); + sublistTableWidgetPointer->setHorizontalHeaderItem(4, mainFrameHeaderItemPointer); + sublistTableWidgetPointer->setHorizontalHeaderItem(5, mediaHeaderItemPointer); + sublistTableWidgetPointer->setHorizontalHeaderItem(6, objectHeaderItemPointer); + sublistTableWidgetPointer->setHorizontalHeaderItem(7, otherHeaderItemPointer); + sublistTableWidgetPointer->setHorizontalHeaderItem(8, pingHeaderItemPointer); + sublistTableWidgetPointer->setHorizontalHeaderItem(9, scriptHeaderItemPointer); + sublistTableWidgetPointer->setHorizontalHeaderItem(10, styleSheetHeaderItemPointer); + sublistTableWidgetPointer->setHorizontalHeaderItem(11, subFrameHeaderItemPointer); + sublistTableWidgetPointer->setHorizontalHeaderItem(12, xmlHttpRequestHeaderItemPointer); + sublistTableWidgetPointer->setHorizontalHeaderItem(13, filterOptionsHeaderItemPointer); + sublistTableWidgetPointer->setHorizontalHeaderItem(14, originalEntryHeaderItemPointer); // Initialize the row counter. int rowCounter = 0; @@ -192,11 +239,37 @@ void FilterListsDialog::populateTableWidget(int sublistComboBoxIndex) const // Create the entry items. QTableWidgetItem *appliedEntryItemPointer = new QTableWidgetItem(entryStructPointer->appliedEntry); + QTableWidgetItem *thirdPartyItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->thirdParty)); + QTableWidgetItem *fontItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->font)); + QTableWidgetItem *imageItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->image)); + QTableWidgetItem *mainFrameItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->mainFrame)); + QTableWidgetItem *mediaItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->media)); + QTableWidgetItem *objectItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->object)); + QTableWidgetItem *otherItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->other)); + QTableWidgetItem *pingItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->ping)); + QTableWidgetItem *scriptItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->script)); + QTableWidgetItem *styleSheetItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->styleSheet)); + QTableWidgetItem *subFrameItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->subFrame)); + QTableWidgetItem *xmlHttpRequestItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->xmlHttpRequest)); + QTableWidgetItem *filterOptionsItemPointer = new QTableWidgetItem(entryStructPointer->filterOptions); QTableWidgetItem *originalEntryItemPointer = new QTableWidgetItem(entryStructPointer->originalEntry); // Add the entries to the table. sublistTableWidgetPointer->setItem(rowCounter, 0, appliedEntryItemPointer); - sublistTableWidgetPointer->setItem(rowCounter, 1, originalEntryItemPointer); + sublistTableWidgetPointer->setItem(rowCounter, 1, thirdPartyItemPointer); + sublistTableWidgetPointer->setItem(rowCounter, 2, fontItemPointer); + sublistTableWidgetPointer->setItem(rowCounter, 3, imageItemPointer); + sublistTableWidgetPointer->setItem(rowCounter, 4, mainFrameItemPointer); + sublistTableWidgetPointer->setItem(rowCounter, 5, mediaItemPointer); + sublistTableWidgetPointer->setItem(rowCounter, 6, objectItemPointer); + sublistTableWidgetPointer->setItem(rowCounter, 7, otherItemPointer); + sublistTableWidgetPointer->setItem(rowCounter, 8, pingItemPointer); + sublistTableWidgetPointer->setItem(rowCounter, 9, scriptItemPointer); + sublistTableWidgetPointer->setItem(rowCounter, 10, styleSheetItemPointer); + sublistTableWidgetPointer->setItem(rowCounter, 11, subFrameItemPointer); + sublistTableWidgetPointer->setItem(rowCounter, 12, xmlHttpRequestItemPointer); + sublistTableWidgetPointer->setItem(rowCounter, 13, filterOptionsItemPointer); + sublistTableWidgetPointer->setItem(rowCounter, 14, originalEntryItemPointer); // Increment the row counter. ++rowCounter; diff --git a/src/dialogs/RequestDetailDialog.cpp b/src/dialogs/RequestDetailDialog.cpp index bdc4b6a..14947fd 100644 --- a/src/dialogs/RequestDetailDialog.cpp +++ b/src/dialogs/RequestDetailDialog.cpp @@ -23,16 +23,98 @@ #include "ui_RequestDetailDialog.h" #include "structs/RequestStruct.h" -// Qt toolkit headers. -#include - // KDE Frameworks headers. #include #include +// Qt toolkit headers. +#include + // Construct the class. -RequestDetailDialog::RequestDetailDialog(QWidget *parentWidgetPointer, QByteArray &requestStructByteArray) : QDialog(parentWidgetPointer) +RequestDetailDialog::RequestDetailDialog(QWidget *parentWidgetPointer, QTableWidget *tableWidgetPointer, const int initialRow) : + QDialog(parentWidgetPointer), currentRow(initialRow), tableWidgetPointer(tableWidgetPointer) +{ + // Set the window modality. + setWindowModality(Qt::WindowModality::ApplicationModal); + + // Instantiate the request detail dialog UI. + Ui::RequestDetailDialog requestDetailDialogUi; + + // Setup the UI. + requestDetailDialogUi.setupUi(this); + + // Get handles for the views. + dispositionLineEditPointer = requestDetailDialogUi.dispositionLineEdit; + urlLineEditPointer = requestDetailDialogUi.urlLineEdit; + requestMethodLineEditPointer = requestDetailDialogUi.requestMethodLineEdit; + navigationTypeLineEditPointer = requestDetailDialogUi.navigationTypeLineEdit; + resourceTypeLineEditPointer = requestDetailDialogUi.resourceTypeLineEdit; + horizontalLinePointer = requestDetailDialogUi.horizontalLine; + filterListLabelPointer = requestDetailDialogUi.filterListLabel; + filterListLineEditPointer = requestDetailDialogUi.filterListLineEdit; + sublistLabelPointer = requestDetailDialogUi.sublistLabel; + sublistLineEditPointer = requestDetailDialogUi.sublistListLineEdit; + appliedEntryLabelPointer = requestDetailDialogUi.appliedEntryLabel; + appliedEntryLineEditPointer = requestDetailDialogUi.appliedEntryLineEdit; + originalEntryLabelPointer = requestDetailDialogUi.originalEntryLabel; + originalEntryLineEditPointer = requestDetailDialogUi.originalEntryLineEdit; + previousButtonPointer = requestDetailDialogUi.previousButton; + nextButtonPointer = requestDetailDialogUi.nextButton; + QDialogButtonBox *dialogButtonBoxPointer = requestDetailDialogUi.dialogButtonBox; + QPushButton *closeButtonPointer = dialogButtonBoxPointer->button(QDialogButtonBox::StandardButton::Close); + + // Make the close button the default. + closeButtonPointer->setDefault(true); + + // Get the disposition line edit palettes. + normalBackgroundPalette = dispositionLineEditPointer->palette(); + negativeBackgroundPalette = normalBackgroundPalette; + positiveBackgroundPalette = normalBackgroundPalette; + + // Modify the palettes. + KColorScheme::adjustBackground(negativeBackgroundPalette, KColorScheme::NegativeBackground); + KColorScheme::adjustBackground(positiveBackgroundPalette, KColorScheme::PositiveBackground); + + // Connect the buttons. + connect(previousButtonPointer, SIGNAL(clicked()), this, SLOT(previous())); + connect(nextButtonPointer, SIGNAL(clicked()), this, SLOT(next())); + connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(close())); + + // Create the keyboard shortcuts. + QShortcut *previousShortcutPointer = new QShortcut(Qt::Key_Left, this); + QShortcut *nextShortcutPointer = new QShortcut(Qt::Key_Right, this); + + // Connect the keyboard shortcuts to the buttons. + connect(previousShortcutPointer, SIGNAL(activated()), previousButtonPointer, SLOT(click())); + connect(nextShortcutPointer, SIGNAL(activated()), nextButtonPointer, SLOT(click())); + + // Populate the dialog. + populateDialog(currentRow); +} + +void RequestDetailDialog::populateDialog(const int row) { + // Set the window title. + setWindowTitle(i18nc("The request detail dialog window title", "Request %1 Detail", row + 1)); + + // Select the row in the table widget (this displays the correct row highlighted in the background of the dialog). + tableWidgetPointer->selectRow(row); + + // Get the first table widget item in the row. + QTableWidgetItem *rowFirstTableWidgetItemPointer = tableWidgetPointer->item(row, 0); + + // Get the data variant. + QVariant dataVariant = rowFirstTableWidgetItemPointer->data(Qt::UserRole); + + // Get the request struct byte array from the data variant. + QByteArray requestStructByteArray = dataVariant.toByteArray(); + + // Determine if previous should be enabled. + bool previousEnabled = (row > 0); + + // Determine if next should be enabled. + bool nextEnabled = (row < (tableWidgetPointer->rowCount() - 1)); + // Create a request struct data stream reader. QDataStream requestStructDataStreamReader(requestStructByteArray); @@ -50,45 +132,6 @@ RequestDetailDialog::RequestDetailDialog(QWidget *parentWidgetPointer, QByteArra requestStructDataStreamReader >> requestStructPointer->sublistInt; requestStructDataStreamReader >> requestStructPointer->urlString; - qDebug().noquote().nospace() << "Disposition: " << requestStructPointer->dispositionInt; - qDebug().noquote().nospace() << "Applied Entry: " << requestStructPointer->entryStruct.appliedEntry; - qDebug().noquote().nospace() << "Original Entry: " << requestStructPointer->entryStruct.originalEntry; - qDebug().noquote().nospace() << "Filter List: " << requestStructPointer->filterListTitle; - qDebug().noquote().nospace() << "Request Method: " << requestStructPointer->requestMethodString; - qDebug().noquote().nospace() << "Navigation Type: " << requestStructPointer->navigationTypeInt; - qDebug().noquote().nospace() << "Resource Type: " << requestStructPointer->resourceTypeInt; - qDebug().noquote().nospace() << "Sublist: " << requestStructPointer->sublistInt; - qDebug().noquote().nospace() << "URL: " << requestStructPointer->urlString; - - // Set the window title. - setWindowTitle(i18nc("The request detail dialog window title", "Request Detail")); - - // Set the window modality. - setWindowModality(Qt::WindowModality::ApplicationModal); - - // Instantiate the request detail dialog UI. - Ui::RequestDetailDialog requestDetailDialogUi; - - // Setup the UI. - requestDetailDialogUi.setupUi(this); - - // Get handles for the views. - QLineEdit *dispositionLineEditPointer = requestDetailDialogUi.dispositionLineEdit; - QLineEdit *urlLineEditPointer = requestDetailDialogUi.urlLineEdit; - QLineEdit *requestMethodLineEditPointer = requestDetailDialogUi.requestMethodLineEdit; - QLineEdit *navigationTypeLineEditPointer = requestDetailDialogUi.navigationTypeLineEdit; - QLineEdit *resourceTypeLineEditPointer = requestDetailDialogUi.resourceTypeLineEdit; - QFrame *horizontalLinePointer = requestDetailDialogUi.horizontalLine; - QLabel *filterListLabelPointer = requestDetailDialogUi.filterListLabel; - QLineEdit *filterListLineEditPointer = requestDetailDialogUi.filterListLineEdit; - QLabel *sublistLabelPointer = requestDetailDialogUi.sublistLabel; - QLineEdit *sublistLineEditPointer = requestDetailDialogUi.sublistListLineEdit; - QLabel *appliedEntryLabelPointer = requestDetailDialogUi.appliedEntryLabel; - QLineEdit *appliedEntryLineEditPointer = requestDetailDialogUi.appliedEntryLineEdit; - QLabel *originalEntryLabelPointer = requestDetailDialogUi.originalEntryLabel; - QLineEdit *originalEntryLineEditPointer = requestDetailDialogUi.originalEntryLineEdit; - QDialogButtonBox *dialogButtonBoxPointer = requestDetailDialogUi.dialogButtonBox; - // Populate the views. dispositionLineEditPointer->setText(globalFilterListHelperPointer->getDispositionString(requestStructPointer->dispositionInt)); urlLineEditPointer->setText(requestStructPointer->urlString); @@ -100,21 +143,19 @@ RequestDetailDialog::RequestDetailDialog(QWidget *parentWidgetPointer, QByteArra appliedEntryLineEditPointer->setText(requestStructPointer->entryStruct.appliedEntry); originalEntryLineEditPointer->setText(requestStructPointer->entryStruct.originalEntry); - // Get the disposition line edit palettes. - QPalette normalBackgroundPalette = dispositionLineEditPointer->palette(); - QPalette negativeBackgroundPalette = normalBackgroundPalette; - QPalette positiveBackgroundPalette = normalBackgroundPalette; - - // Modify the palettes. - KColorScheme::adjustBackground(negativeBackgroundPalette, KColorScheme::NegativeBackground); - KColorScheme::adjustBackground(positiveBackgroundPalette, KColorScheme::PositiveBackground); + // Set the button status. + previousButtonPointer->setEnabled(previousEnabled); + nextButtonPointer->setEnabled(nextEnabled); // Modify the interface based on the disposition. switch (requestStructPointer->dispositionInt) { case FilterListHelper::DEFAULT: { - // Hide the filter list views. + // Reset the disposition line edit background. + dispositionLineEditPointer->setPalette(normalBackgroundPalette); + + // Hide the views. horizontalLinePointer->hide(); filterListLabelPointer->hide(); filterListLineEditPointer->hide(); @@ -133,6 +174,17 @@ RequestDetailDialog::RequestDetailDialog(QWidget *parentWidgetPointer, QByteArra // Colorize the disposition line edit background. dispositionLineEditPointer->setPalette(positiveBackgroundPalette); + // Show the views. + horizontalLinePointer->show(); + filterListLabelPointer->show(); + filterListLineEditPointer->show(); + sublistLabelPointer->show(); + sublistLineEditPointer->show(); + appliedEntryLabelPointer->show(); + appliedEntryLineEditPointer->show(); + originalEntryLabelPointer->show(); + originalEntryLineEditPointer->show(); + break; } @@ -141,10 +193,36 @@ RequestDetailDialog::RequestDetailDialog(QWidget *parentWidgetPointer, QByteArra // Colorize the disposition line edit background. dispositionLineEditPointer->setPalette(negativeBackgroundPalette); + // Show the views. + horizontalLinePointer->show(); + filterListLabelPointer->show(); + filterListLineEditPointer->show(); + sublistLabelPointer->show(); + sublistLineEditPointer->show(); + appliedEntryLabelPointer->show(); + appliedEntryLineEditPointer->show(); + originalEntryLabelPointer->show(); + originalEntryLineEditPointer->show(); + break; } } +} - // Connect the buttons. - connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(close())); +void RequestDetailDialog::previous() +{ + // Update the current row. + --currentRow; + + // Populate the dialog. + populateDialog(currentRow); +} + +void RequestDetailDialog::next() +{ + // Update the current row. + ++currentRow; + + // Populate the dialog. + populateDialog(currentRow); } diff --git a/src/dialogs/RequestDetailDialog.h b/src/dialogs/RequestDetailDialog.h index d33f65e..c15fcad 100644 --- a/src/dialogs/RequestDetailDialog.h +++ b/src/dialogs/RequestDetailDialog.h @@ -22,6 +22,8 @@ // Qt toolkit headers. #include +#include +#include class RequestDetailDialog : public QDialog { @@ -30,6 +32,38 @@ class RequestDetailDialog : public QDialog public: // The primary constructor. - explicit RequestDetailDialog(QWidget *parentWidgetPointer, QByteArray &requestStructByteArray); + explicit RequestDetailDialog(QWidget *parentWidgetPointer, QTableWidget *tableWidgetPointer, const int initialRow); + +private Q_SLOTS: + // The private slots. + void next(); + void previous(); + +private: + // The private variables. + QLabel *appliedEntryLabelPointer; + QLineEdit *appliedEntryLineEditPointer; + int currentRow; + QLineEdit *dispositionLineEditPointer; + QLabel *filterListLabelPointer; + QLineEdit *filterListLineEditPointer; + QFrame *horizontalLinePointer; + QLineEdit *navigationTypeLineEditPointer; + QPalette negativeBackgroundPalette; + QPushButton *nextButtonPointer; + QPalette normalBackgroundPalette; + QLabel *originalEntryLabelPointer; + QLineEdit *originalEntryLineEditPointer; + QPushButton *previousButtonPointer; + QPalette positiveBackgroundPalette; + QLineEdit *requestMethodLineEditPointer; + QLineEdit *resourceTypeLineEditPointer; + QLabel *sublistLabelPointer; + QLineEdit *sublistLineEditPointer; + QTableWidget *tableWidgetPointer; + QLineEdit *urlLineEditPointer; + + // The private functions. + void populateDialog(const int row); }; #endif diff --git a/src/dialogs/RequestsDialog.cpp b/src/dialogs/RequestsDialog.cpp index 0d240e7..82535e8 100644 --- a/src/dialogs/RequestsDialog.cpp +++ b/src/dialogs/RequestsDialog.cpp @@ -158,23 +158,14 @@ RequestsDialog::RequestsDialog(QWidget *parentWidgetPointer, QListitem(row, 0); - - // Get the data variant. - QVariant dataVariant = rowFirstTableWidgetItemPointer->data(Qt::UserRole); - - // Get the request struct byte array from the data variant. - QByteArray requestStructByteArray = dataVariant.toByteArray(); - // Instantiate the request details dialog. - RequestDetailDialog *requestDetailDialogPointer = new RequestDetailDialog(this, requestStructByteArray); + RequestDetailDialog *requestDetailDialogPointer = new RequestDetailDialog(this, tableWidgetPointer, row); // Show the dialog. requestDetailDialogPointer->show(); diff --git a/src/enums/FilterOptionEnum.h b/src/enums/FilterOptionEnum.h new file mode 100644 index 0000000..8c01510 --- /dev/null +++ b/src/enums/FilterOptionEnum.h @@ -0,0 +1,32 @@ +/* + * Copyright 2024 Soren Stoutner . + * + * This file is part of Privacy Browser PC . + * + * Privacy Browser PC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Privacy Browser PC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Privacy Browser PC. If not, see . + */ + +#ifndef FILTEROPTIONENUM_H +#define FILTEROPTIONENUM_H + +struct FilterOptionEnum +{ + enum Disposition + { + Null = 0, + Apply = 1, + Override = 2, + }; +}; +#endif 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); } diff --git a/src/helpers/FilterListHelper.h b/src/helpers/FilterListHelper.h index 5bd9ad2..f8bfdf1 100644 --- a/src/helpers/FilterListHelper.h +++ b/src/helpers/FilterListHelper.h @@ -23,6 +23,7 @@ // Application headers. #include "structs/FilterListStruct.h" #include "structs/RequestStruct.h" +#include "structs/UrlStruct.h" // Qt framework headers. #include @@ -40,7 +41,9 @@ public: static const int BLOCKED = 2; // The public static sublist constant integers. - static const int MAIN_BLOCKLIST = 0; + static const int MAIN_ALLOWLIST = 0; + static const int MAIN_BLOCKLIST = 1; + static const int INITIAL_DOMAIN_BLOCKLIST = 2; // The public variables. FilterListStruct *easyListStructPointer; @@ -52,6 +55,7 @@ public: // The public functions. bool checkFilterLists(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer) const; QString getDispositionString(int dispositionInt) const; + QString getFilterOptionDispositionString(const FilterOptionEnum::Disposition filterOptionDisposition) const; QString getNavigationTypeString(int navigationTypeInt) const; QString getResourceTypeString(int resourceTypeInt) const; QString getSublistName(int sublistInt) const; @@ -62,6 +66,11 @@ private: QString ALLOWED_STRING; QString BLOCKED_STRING; + // The private translated filter option dispositions. + QString FILTER_OPTION_NULL; + QString FILTER_OPTION_APPLY; + QString FILTER_OPTION_OVERRIDE; + // The private translated navigation type strings. QString NAVIGATION_TYPE_LINK; QString NAVIGATION_TYPE_TYPED; @@ -95,12 +104,19 @@ private: QString RESOURCE_TYPE_UNKNOWN; // The private translated sublist strings. + QString MAIN_ALLOWLIST_STRING; QString MAIN_BLOCKLIST_STRING; + QString INITIAL_DOMAIN_BLOCKLIST_STRING; // The private functions. - bool checkIndividualList(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, FilterListStruct *filterListStruct) const; + bool blockRequest(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt, EntryStruct *entryStructPointer) const; + bool checkIndividualList(QWebEngineUrlRequestInfo &urlRequestInfo, UrlStruct &urlStruct, RequestStruct *requestStructPointer, FilterListStruct *filterListStructPointer) const; + bool checkThirdParty(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, const bool isThirdPartyRequest, const QString &filterListTitle, const int sublistInt, + EntryStruct *entryStructPointer) const; FilterListStruct* populateFilterList(const QString &filterListFileName) const; - void populateRequestStruct(RequestStruct *requestStructPointer, const int disposition, const QString &filterListTitle, const int sublistInt, const QString &appliedEntry, - const QString &originalEntry) const; + void populateRequestStruct(RequestStruct *requestStructPointer, const int disposition, const QString &filterListTitle, const int sublistInt, EntryStruct *entryStructPointer) const; + bool processFilterOptions(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt, + EntryStruct *entryStructPointer) const; + void removeInitialAndTrailingAsterisks(QString &filterListEntry) const; }; #endif diff --git a/src/helpers/UserAgentHelper.cpp b/src/helpers/UserAgentHelper.cpp index 1cd885d..03e7b8b 100644 --- a/src/helpers/UserAgentHelper.cpp +++ b/src/helpers/UserAgentHelper.cpp @@ -39,11 +39,11 @@ const QString UserAgentHelper::SAFARI_MACOS_DATABASE = QLatin1String("Safari mac // Define the public user agent constants. const QString UserAgentHelper::PRIVACY_BROWSER_USER_AGENT = QLatin1String("PrivacyBrowser/1.0"); const QString UserAgentHelper::FIREFOX_LINUX_USER_AGENT = QLatin1String("Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0"); -const QString UserAgentHelper::CHROMIUM_LINUX_USER_AGENT = QLatin1String("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"); -const QString UserAgentHelper::FIREFOX_WINDOWS_USER_AGENT = QLatin1String("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0"); -const QString UserAgentHelper::CHROME_WINDOWS_USER_AGENT = QLatin1String("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"); -const QString UserAgentHelper::EDGE_WINDOWS_USER_AGENT = QLatin1String("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0"); -const QString UserAgentHelper::SAFARI_MACOS_USER_AGENT = QLatin1String("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15"); +const QString UserAgentHelper::CHROMIUM_LINUX_USER_AGENT = QLatin1String("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"); +const QString UserAgentHelper::FIREFOX_WINDOWS_USER_AGENT = QLatin1String("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0"); +const QString UserAgentHelper::CHROME_WINDOWS_USER_AGENT = QLatin1String("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"); +const QString UserAgentHelper::EDGE_WINDOWS_USER_AGENT = QLatin1String("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0"); +const QString UserAgentHelper::SAFARI_MACOS_USER_AGENT = QLatin1String("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_Z) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Safari/605.1.15"); // Construct the class. UserAgentHelper::UserAgentHelper() { diff --git a/src/structs/EntryStruct.h b/src/structs/EntryStruct.h index 068d9c9..67a43eb 100644 --- a/src/structs/EntryStruct.h +++ b/src/structs/EntryStruct.h @@ -1,4 +1,4 @@ - /* +/* * Copyright 2024 Soren Stoutner . * * This file is part of Privacy Browser PC . @@ -20,12 +20,34 @@ #ifndef ENTRYSTRUCT_H #define ENTRYSTRUCT_H +// Application headers. +#include "enums/FilterOptionEnum.h" + // Qt toolkit headers. #include struct EntryStruct { + // The strings. QString appliedEntry; + QString filterOptions; QString originalEntry; + + // The filter options flag. + bool hasFilterOptions = false; + + // The filter options. + FilterOptionEnum::Disposition font = FilterOptionEnum::Disposition::Null; + FilterOptionEnum::Disposition image = FilterOptionEnum::Disposition::Null; + FilterOptionEnum::Disposition mainFrame = FilterOptionEnum::Disposition::Null; + FilterOptionEnum::Disposition media = FilterOptionEnum::Disposition::Null; + FilterOptionEnum::Disposition object = FilterOptionEnum::Disposition::Null; + FilterOptionEnum::Disposition other = FilterOptionEnum::Disposition::Null; + FilterOptionEnum::Disposition ping = FilterOptionEnum::Disposition::Null; + FilterOptionEnum::Disposition script = FilterOptionEnum::Disposition::Null; + FilterOptionEnum::Disposition styleSheet = FilterOptionEnum::Disposition::Null; + FilterOptionEnum::Disposition subFrame = FilterOptionEnum::Disposition::Null; + FilterOptionEnum::Disposition thirdParty = FilterOptionEnum::Disposition::Null; + FilterOptionEnum::Disposition xmlHttpRequest = FilterOptionEnum::Disposition::Null; }; #endif diff --git a/src/structs/FilterListStruct.h b/src/structs/FilterListStruct.h index aacc6c0..ef560d1 100644 --- a/src/structs/FilterListStruct.h +++ b/src/structs/FilterListStruct.h @@ -34,6 +34,8 @@ struct FilterListStruct QString title; QString version; QString filePath; - std::forward_list mainBlockList; + std::forward_list mainAllowList; + std::forward_list mainBlockList; + std::forward_list initialDomainBlockList; }; #endif diff --git a/src/structs/OverrideStruct.h b/src/structs/OverrideStruct.h new file mode 100644 index 0000000..0568a79 --- /dev/null +++ b/src/structs/OverrideStruct.h @@ -0,0 +1,38 @@ +/* + * Copyright 2024 Soren Stoutner . + * + * This file is part of Privacy Browser PC . + * + * Privacy Browser PC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Privacy Browser PC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Privacy Browser PC. If not, see . + */ + +#ifndef OVERRIDESTRUCT_H +#define OVERRIDESTRUCT_H + +struct OverrideStruct +{ + bool hasOverride = false; + bool font = false; + bool image = false; + bool mainFrame = false; + bool media = false; + bool object = false; + bool other = false; + bool ping = false; + bool script = false; + bool styleSheet = false; + bool subFrame = false; + bool xmlHttpRequest = false; +}; +#endif diff --git a/src/structs/UrlStruct.h b/src/structs/UrlStruct.h new file mode 100644 index 0000000..ea135d0 --- /dev/null +++ b/src/structs/UrlStruct.h @@ -0,0 +1,34 @@ +/* + * Copyright 2024 Soren Stoutner . + * + * This file is part of Privacy Browser PC . + * + * Privacy Browser PC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Privacy Browser PC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Privacy Browser PC. If not, see . + */ + +#ifndef URLSTRUCT_H +#define URLSTRUCT_H + +// Qt toolkit headers. +#include + +struct UrlStruct +{ + QString urlString; + QString urlStringWithSeparators; + QString truncatedUrlString; + QString truncatedUrlStringWithSeparators; + bool isThirdPartyRequest; +}; +#endif diff --git a/src/uis/AddTabWidget.ui b/src/uis/AddTabWidget.ui index 74d3c57..d4eda1e 100644 --- a/src/uis/AddTabWidget.ui +++ b/src/uis/AddTabWidget.ui @@ -3,7 +3,7 @@ - + + + Qt::Horizontal + + + + 5 + + - + @@ -55,13 +63,17 @@ true + + + QTextEdit::NoWrap + - + - + @@ -80,10 +92,6 @@ - - QAbstractItemView::NoEditTriggers - - QAbstractItemView::ScrollPerPixel @@ -98,8 +106,8 @@ - - + + diff --git a/src/uis/RequestDetailDialog.ui b/src/uis/RequestDetailDialog.ui index a0a322b..899fe31 100644 --- a/src/uis/RequestDetailDialog.ui +++ b/src/uis/RequestDetailDialog.ui @@ -39,6 +39,11 @@ true + + + + Qt::NoFocus + @@ -60,6 +65,11 @@ true + + + + Qt::NoFocus + @@ -81,6 +91,11 @@ true + + + + Qt::NoFocus + @@ -98,6 +113,11 @@ true + + + + Qt::NoFocus + @@ -115,6 +135,11 @@ true + + + + Qt::NoFocus + @@ -145,6 +170,11 @@ true + + + + Qt::NoFocus + @@ -166,6 +196,11 @@ true + + + + Qt::NoFocus + @@ -187,6 +222,11 @@ true + + + + Qt::NoFocus + @@ -208,6 +248,11 @@ true + + + + Qt::NoFocus + @@ -222,13 +267,43 @@ - - - - QDialogButtonBox::Close - - + + + + + + Previous + + + + + + + + + + + + + Next + + + + + + + + + + + + + QDialogButtonBox::Close + + + + diff --git a/src/uis/RequestsDialog.ui b/src/uis/RequestsDialog.ui index 3499948..3bbb9d0 100644 --- a/src/uis/RequestsDialog.ui +++ b/src/uis/RequestsDialog.ui @@ -36,10 +36,6 @@ - - QAbstractItemView::NoEditTriggers - - QAbstractItemView::ScrollPerPixel diff --git a/src/uis/TabWidget.ui b/src/uis/TabWidget.ui index 521526d..7a546f5 100644 --- a/src/uis/TabWidget.ui +++ b/src/uis/TabWidget.ui @@ -1,9 +1,9 @@