)
# Add the subdirectories.
+add_subdirectory(databases)
add_subdirectory(dialogs)
add_subdirectory(filters)
add_subdirectory(helpers)
--- /dev/null
+# Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+#
+# This file is part of Privacy Browser PC <https://www.stoutner.com/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 <http://www.gnu.org/licenses/>.
+
+
+# List the sources to include in the executable.
+target_sources(privacy-browser PRIVATE
+ CookiesDatabase.cpp
+ DomainsDatabase.cpp
+)
--- /dev/null
+/*
+ * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Browser PC <https://www.stoutner.com/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 <http://www.gnu.org/licenses/>.
+ */
+
+// Application headers.
+#include "CookiesDatabase.h"
+
+// Define the private static schema constants.
+const int CookiesDatabase::SCHEMA_VERSION = 0;
+
+// Define the public static database constants.
+const QString CookiesDatabase::CONNECTION_NAME = "cookies_database";
+const QString CookiesDatabase::COOKIES_TABLE = "cookies";
+
+// Define the public static database field names.
+const QString CookiesDatabase::_ID = "_id";
+const QString CookiesDatabase::DOMAIN = "domain";
+const QString CookiesDatabase::NAME = "name";
+const QString CookiesDatabase::PATH = "path";
+const QString CookiesDatabase::EXPIRATION_DATE = "expiration_date";
+const QString CookiesDatabase::HTTP_ONLY = "http_only";
+const QString CookiesDatabase::SECURE = "secure";
+const QString CookiesDatabase::VALUE = "value";
+
+// Construct the class.
+CookiesDatabase::CookiesDatabase() {}
+
+void CookiesDatabase::addDatabase()
+{
+ // Add the cookies database.
+ QSqlDatabase cookiesDatabase = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), CONNECTION_NAME);
+
+ // Set the database name.
+ cookiesDatabase.setDatabaseName(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/cookies.db");
+
+ // Open the database.
+ if (cookiesDatabase.open()) // Opening the database succeeded.
+ {
+ // Check to see if the cookies table already exists.
+ if (cookiesDatabase.tables().contains(COOKIES_TABLE)) // The cookies table exists.
+ {
+ // Query the database schema version.
+ QSqlQuery schemaVersionQuery = cookiesDatabase.exec(QStringLiteral("PRAGMA user_version"));
+
+ // Move to the first record.
+ schemaVersionQuery.first();
+
+ // Get the current schema versin.
+ int currentSchemaVersion = schemaVersionQuery.value(0).toInt();
+
+ // Check to see if the schema has been updated.
+ if (currentSchemaVersion < SCHEMA_VERSION)
+ {
+ // Run the schema update code.
+ switch (currentSchemaVersion)
+ {
+ // Upgrade code here.
+ }
+
+ // Update the schema version.
+ cookiesDatabase.exec("PRAGMA user_version = " + QString::number(SCHEMA_VERSION));
+ }
+ }
+ else // The cookies table does not exist.
+ {
+ // Instantiate a create table query.
+ QSqlQuery createTableQuery(cookiesDatabase);
+
+ // Prepare the create table query.
+ createTableQuery.prepare("CREATE TABLE " + COOKIES_TABLE + "(" +
+ _ID + " INTEGER PRIMARY KEY, " +
+ DOMAIN + " TEXT NOT NULL, " +
+ NAME + " TEXT NOT NULL, " +
+ PATH + " TEXT NOT NULL, " +
+ EXPIRATION_DATE + " TEXT, " +
+ HTTP_ONLY + " INTEGER NOT NULL DEFAULT 0, " +
+ SECURE + " INTEGER NOT NULL DEFAULT 0, " +
+ VALUE + " TEXT NOT NULL)"
+ );
+
+ // Execute the query.
+ if (!createTableQuery.exec())
+ {
+ // Log any errors.
+ qDebug().noquote().nospace() << "Error creating table: " << cookiesDatabase.lastError();
+ }
+
+ // Set the schema version.
+ cookiesDatabase.exec("PRAGMA user_version = " + QString::number(SCHEMA_VERSION));
+ }
+ }
+ else // Opening the database failed.
+ {
+ // Write the last database error message to the debug output.
+ qDebug().noquote().nospace() << "Error opening database: " << cookiesDatabase.lastError();
+ }
+}
+
+void CookiesDatabase::addCookie(const QNetworkCookie &cookie)
+{
+ // Get a handle for the cookies database.
+ QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME);
+
+ // Check to see if the cookie already exists in the database.
+ if (isDurable(cookie)) // The cookie already exists.
+ {
+ // Update the existing cookie.
+ updateCookie(cookie);
+ }
+ else // The cookie doesn't already exist.
+ {
+ // Instantiate an add cookie query.
+ QSqlQuery addCookieQuery(cookiesDatabase);
+
+ // Prepare the add cookie query.
+ addCookieQuery.prepare("INSERT INTO " + COOKIES_TABLE + " (" + DOMAIN + ", " + NAME + ", " + PATH + ", " + EXPIRATION_DATE + ", " + HTTP_ONLY + ", " + SECURE + ", " + VALUE + ") "
+ "VALUES (:domain, :name, :path, :expiration_date, :http_only, :secure, :value)"
+ );
+
+ // Bind the values.
+ addCookieQuery.bindValue(":domain", cookie.domain());
+ addCookieQuery.bindValue(":name", QString(cookie.name()));
+ addCookieQuery.bindValue(":path", cookie.path());
+ addCookieQuery.bindValue(":expiration_date", cookie.expirationDate());
+ addCookieQuery.bindValue(":http_only", cookie.isHttpOnly());
+ addCookieQuery.bindValue(":secure", cookie.isSecure());
+ addCookieQuery.bindValue(":value", QString(cookie.value()));
+
+ // Execute the query.
+ addCookieQuery.exec();
+ }
+}
+
+void CookiesDatabase::deleteAllCookies()
+{
+ // Get a handle for the cookies database.
+ QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME);
+
+ // Instantiate a delete all cookies query.
+ QSqlQuery deleteAllCookiesQuery(cookiesDatabase);
+
+ // Prepare the delete all cookies query.
+ deleteAllCookiesQuery.prepare("DELETE FROM " + COOKIES_TABLE);
+
+ // Execute the query.
+ deleteAllCookiesQuery.exec();
+}
+
+void CookiesDatabase::deleteCookie(const QNetworkCookie &cookie)
+{
+ // Get a handle for the cookies database.
+ QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME);
+
+ // Instantiate a delete cookie query.
+ QSqlQuery deleteCookieQuery(cookiesDatabase);
+
+ // Prepare the delete cookie query.
+ deleteCookieQuery.prepare("DELETE FROM " + COOKIES_TABLE + " WHERE " + DOMAIN + " = :domain AND " + NAME + " = :name AND " + PATH + " = :path");
+
+ // Bind the values.
+ deleteCookieQuery.bindValue(":domain", cookie.domain());
+ deleteCookieQuery.bindValue(":name", QString(cookie.name()));
+ deleteCookieQuery.bindValue(":path", cookie.path());
+
+ // Execute the query.
+ deleteCookieQuery.exec();
+}
+
+QList<QNetworkCookie*>* CookiesDatabase::getCookies()
+{
+ // Get a handle for the cookies database.
+ QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME);
+
+ // Instantiate a cookies query.
+ QSqlQuery cookiesQuery(cookiesDatabase);
+
+ // Set the query to be forward only.
+ cookiesQuery.setForwardOnly(true);
+
+ // Prepare the cookies query.
+ cookiesQuery.prepare("SELECT * FROM " + COOKIES_TABLE);
+
+ // Execute the query.
+ cookiesQuery.exec();
+
+ // Create a cookie list.
+ QList<QNetworkCookie*> *cookieListPointer = new QList<QNetworkCookie*>;
+
+ // Populate the cookie list.
+ while (cookiesQuery.next())
+ {
+ // Create a cookie.
+ QNetworkCookie *cookiePointer = new QNetworkCookie();
+
+ // Populate the cookie.
+ cookiePointer->setDomain(cookiesQuery.value(DOMAIN).toString());
+ cookiePointer->setName(cookiesQuery.value(NAME).toString().toUtf8());
+ cookiePointer->setPath(cookiesQuery.value(PATH).toString());
+ cookiePointer->setExpirationDate(QDateTime::fromString(cookiesQuery.value(EXPIRATION_DATE).toString(), Qt::ISODate));
+ cookiePointer->setHttpOnly(cookiesQuery.value(HTTP_ONLY).toBool());
+ cookiePointer->setSecure(cookiesQuery.value(SECURE).toBool());
+ cookiePointer->setValue(cookiesQuery.value(VALUE).toString().toUtf8());
+
+ // Add the cookie to the list.
+ cookieListPointer->append(cookiePointer);
+ }
+
+ // Return the cookie list.
+ return cookieListPointer;
+}
+
+bool CookiesDatabase::isDurable(const QNetworkCookie &cookie)
+{
+ // Get a handle for the cookies database.
+ QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME);
+
+ // Instantiate an is durable query.
+ QSqlQuery isDurableQuery(cookiesDatabase);
+
+ // Set the query to be forward only.
+ isDurableQuery.setForwardOnly(true);
+
+ // Prepare the is durable query.
+ isDurableQuery.prepare("SELECT " + _ID + " FROM " + COOKIES_TABLE + " WHERE " + DOMAIN + " = :domain AND " + NAME + " = :name AND " + PATH + " = :path");
+
+ // Bind the values.
+ isDurableQuery.bindValue(":domain", cookie.domain());
+ isDurableQuery.bindValue(":name", QString(cookie.name()));
+ isDurableQuery.bindValue(":path", cookie.path());
+
+ // Execute the query.
+ isDurableQuery.exec();
+
+ // Move to the first entry.
+ isDurableQuery.first();
+
+ // Return the status of the cookie in the database.
+ return (isDurableQuery.isValid());
+}
+
+bool CookiesDatabase::isUpdate(const QNetworkCookie &cookie)
+{
+ // Get a handle for the cookies database.
+ QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME);
+
+ // Instantiate an is update query.
+ QSqlQuery isUpdateQuery(cookiesDatabase);
+
+ // Prepare the is update query.
+ isUpdateQuery.prepare("SELECT " + EXPIRATION_DATE + " , " + HTTP_ONLY + " , " + SECURE + " , " + VALUE + " FROM " + COOKIES_TABLE + " WHERE " + DOMAIN + " = :domain AND " +
+ NAME + " = :name AND " + PATH + " = :path");
+
+ // Bind the values.
+ isUpdateQuery.bindValue(":domain", cookie.domain());
+ isUpdateQuery.bindValue(":name", QString(cookie.name()));
+ isUpdateQuery.bindValue(":path", cookie.path());
+
+ // Execute the query.
+ isUpdateQuery.exec();
+
+ // Move to the first entry.
+ isUpdateQuery.first();
+
+ // Check to see if the cookie exists.
+ if (isUpdateQuery.isValid()) // The cookie exists in the database.
+ {
+ // Check to see if the cookie data has changed.
+ if ((QDateTime::fromString(isUpdateQuery.value(0).toString(), Qt::ISODate) != cookie.expirationDate()) ||
+ (isUpdateQuery.value(1).toBool() != cookie.isHttpOnly()) ||
+ (isUpdateQuery.value(2).toBool() != cookie.isSecure()) ||
+ (isUpdateQuery.value(3).toString().toUtf8() != cookie.value())) // The cookies data has changed.
+ {
+ qDebug() << "The durable cookie data has changed.";
+
+ // Return true.
+ return true;
+ }
+ else // The cookie data has not changed.
+ {
+ qDebug() << "The durable cookie data is unchanged.";
+
+ // Return false.
+ return false;
+ }
+ }
+ else // The cookie does not exist in the database.
+ {
+ // Return false.
+ return false;
+ }
+}
+
+void CookiesDatabase::updateCookie(const QNetworkCookie &cookie)
+{
+ // Get a handle for the cookies database.
+ QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME);
+
+ // Create the update cookie query.
+ QSqlQuery updateCookieQuery(cookiesDatabase);
+
+ // Prepare the edit cookie query.
+ updateCookieQuery.prepare("UPDATE " + COOKIES_TABLE + " SET " + EXPIRATION_DATE + " = :expiration_date , " + HTTP_ONLY + " = :http_only , " + SECURE + " = :secure , " +
+ VALUE + " = :value WHERE " + DOMAIN + " = :domain AND " + NAME + " = :name AND " + PATH + " = :path");
+
+ // Bind the values.
+ updateCookieQuery.bindValue(":domain", cookie.domain());
+ updateCookieQuery.bindValue(":name", QString(cookie.name()));
+ updateCookieQuery.bindValue(":path", cookie.path());
+ updateCookieQuery.bindValue(":expiration_date", cookie.expirationDate());
+ updateCookieQuery.bindValue(":http_only", cookie.isHttpOnly());
+ updateCookieQuery.bindValue(":secure", cookie.isSecure());
+ updateCookieQuery.bindValue(":value", QString(cookie.value()));
+
+ // Execute the query.
+ updateCookieQuery.exec();
+}
+
+void CookiesDatabase::updateCookie(const QNetworkCookie &oldCookie, const QNetworkCookie &newCookie)
+{
+ // Get a handle for the cookies database.
+ QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME);
+
+ // Create the old cookie query.
+ QSqlQuery oldCookieQuery(cookiesDatabase);
+
+ // Set the query to be forward only.
+ oldCookieQuery.setForwardOnly(true);
+
+ // Prepare the old cookie query.
+ oldCookieQuery.prepare("SELECT " + _ID + " FROM " + COOKIES_TABLE + " WHERE " + DOMAIN + " = :domain AND " + NAME + " = :name AND " + PATH + " = :path");
+
+ // Bind the values.
+ oldCookieQuery.bindValue(":domain", oldCookie.domain());
+ oldCookieQuery.bindValue(":name", QString(oldCookie.name()));
+ oldCookieQuery.bindValue(":path", oldCookie.path());
+
+ // Execute the query.
+ oldCookieQuery.exec();
+
+ // Move to the first entry.
+ oldCookieQuery.first();
+
+ // Create the update cookie query.
+ QSqlQuery updateCookieQuery(cookiesDatabase);
+
+ // Prepare the update cookie query.
+ updateCookieQuery.prepare("UPDATE " + COOKIES_TABLE + " SET " + DOMAIN + " = :domain , " + NAME + " = :name , " + PATH + " = :path , " + EXPIRATION_DATE + " = :expiration_date , " +
+ HTTP_ONLY + " = :http_only , " + SECURE + " = :secure , " + VALUE + " = :value WHERE " + _ID + " = :id");
+
+ // Bind the values.
+ updateCookieQuery.bindValue(":id", oldCookieQuery.value(0).toLongLong());
+ updateCookieQuery.bindValue(":domain", newCookie.domain());
+ updateCookieQuery.bindValue(":name", QString(newCookie.name()));
+ updateCookieQuery.bindValue(":path", newCookie.path());
+ updateCookieQuery.bindValue(":expiration_date", newCookie.expirationDate());
+ updateCookieQuery.bindValue(":http_only", newCookie.isHttpOnly());
+ updateCookieQuery.bindValue(":secure", newCookie.isSecure());
+ updateCookieQuery.bindValue(":value", QString(newCookie.value()));
+
+ // Execute the query.
+ updateCookieQuery.exec();
+}
--- /dev/null
+/*
+ * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Browser PC <https://www.stoutner.com/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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef COOKIESDATABASE_H
+#define COOKIESDATABASE_H
+
+// Qt framework headers.
+#include <QNetworkCookie>
+#include <QtSql>
+
+class CookiesDatabase
+{
+public:
+ // The default constructor.
+ CookiesDatabase();
+
+ // The public functions.
+ static void addDatabase();
+ static void addCookie(const QNetworkCookie &cookie);
+ static void deleteAllCookies();
+ static void deleteCookie(const QNetworkCookie &cookie);
+ static QList<QNetworkCookie*>* getCookies();
+ static bool isDurable(const QNetworkCookie &cookie);
+ static bool isUpdate(const QNetworkCookie &cookie);
+ static void updateCookie(const QNetworkCookie &cookie);
+ static void updateCookie(const QNetworkCookie &oldCookie, const QNetworkCookie &newCookie);
+
+ // The public constants.
+ static const QString _ID;
+ static const QString CONNECTION_NAME;
+ static const QString COOKIES_TABLE;
+ static const QString DOMAIN;
+ static const QString EXPIRATION_DATE;
+ static const QString HTTP_ONLY;
+ static const QString NAME;
+ static const QString PATH;
+ static const QString SECURE;
+ static const QString VALUE;
+
+private:
+ // The private static constants.
+ static const int SCHEMA_VERSION;
+};
+#endif
--- /dev/null
+/*
+ * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Browser PC <https://www.stoutner.com/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 <http://www.gnu.org/licenses/>.
+ */
+
+// Application headers.
+#include "DomainsDatabase.h"
+#include "helpers/UserAgentHelper.h"
+
+// Define the private static schema constants.
+const int DomainsDatabase::SCHEMA_VERSION = 5;
+
+// Define the public static database constants.
+const QString DomainsDatabase::CONNECTION_NAME = "domains_database";
+const QString DomainsDatabase::DOMAINS_TABLE = "domains";
+
+// Define the public static database field names.
+const QString DomainsDatabase::_ID = "_id";
+const QString DomainsDatabase::DOMAIN_NAME = "domain_name";
+const QString DomainsDatabase::JAVASCRIPT = "javascript";
+const QString DomainsDatabase::LOCAL_STORAGE = "local_storage";
+const QString DomainsDatabase::DOM_STORAGE = "dom_storage";
+const QString DomainsDatabase::USER_AGENT = "user_agent";
+const QString DomainsDatabase::ZOOM_FACTOR = "zoom_factor";
+const QString DomainsDatabase::CUSTOM_ZOOM_FACTOR = "custom_zoom_factor";
+
+// Construct the class.
+DomainsDatabase::DomainsDatabase() {}
+
+void DomainsDatabase::addDatabase()
+{
+ // Add the domain settings database.
+ QSqlDatabase domainsDatabase = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), CONNECTION_NAME);
+
+ // Set the database name.
+ domainsDatabase.setDatabaseName(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/domains.db");
+
+ // Open the database.
+ if (domainsDatabase.open()) // Opening the database succeeded.
+ {
+ // Check to see if the domains table already exists.
+ if (domainsDatabase.tables().contains(DOMAINS_TABLE)) // The domains table already exists.
+ {
+ // Query the database schema version.
+ QSqlQuery schemaVersionQuery = domainsDatabase.exec(QStringLiteral("PRAGMA user_version"));
+
+ // Move to the first record.
+ schemaVersionQuery.first();
+
+ // Get the current schema version.
+ int currentSchemaVersion = schemaVersionQuery.value(0).toInt();
+
+ // Check to see if the schema has been updated.
+ if (currentSchemaVersion < SCHEMA_VERSION)
+ {
+ // Run the schema update code.
+ switch (currentSchemaVersion)
+ {
+ // Upgrade from schema version 0 to schema version 1.
+ case 0:
+ {
+ // Add the JavaScript column.
+ domainsDatabase.exec("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + JAVASCRIPT + " INTEGER DEFAULT 0");
+
+ // Fallthrough to the next case.
+ [[fallthrough]];
+ }
+
+ // Upgrade from schema version 1 to schema version 2.
+ case 1:
+ {
+ // Add the User Agent column.
+ domainsDatabase.exec("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + USER_AGENT + " TEXT DEFAULT '" + UserAgentHelper::SYSTEM_DEFAULT_DATABASE + "'");
+
+ // Fallthrough to the next case.
+ [[fallthrough]];
+ }
+
+ // Upgrade from schema version 2 to schema version 3.
+ case 2:
+ {
+ // Add the Zoom Factor columns.
+ domainsDatabase.exec("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + ZOOM_FACTOR + " INTEGER DEFAULT 0");
+ domainsDatabase.exec("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + CUSTOM_ZOOM_FACTOR + " REAL DEFAULT 1.0");
+
+ // Fallthrough to the next case.
+ [[fallthrough]];
+ }
+
+ // Upgrade from schema version 3 to schema version 4.
+ case 3:
+ {
+ // Add the DOM Storage column.
+ domainsDatabase.exec("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + DOM_STORAGE + " INTEGER DEFAULT 0");
+
+ // Fallthrough to the next case.
+ [[fallthrough]];
+ }
+
+ // Upgrade from schema version 4 to schema version 5.
+ case 4:
+ {
+ // Add the Local Storage column.
+ domainsDatabase.exec("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + LOCAL_STORAGE + " INTEGER DEFAULT 0");
+
+ // Fallthrough to the next case.
+ // [[fallthrough]];
+ }
+ }
+
+ // Update the schema version.
+ domainsDatabase.exec("PRAGMA user_version = " + QString::number(SCHEMA_VERSION));
+ }
+ }
+ else // The domains table does not exist.
+ {
+ // Instantiate a create table query.
+ QSqlQuery createTableQuery(domainsDatabase);
+
+ // Prepare the create table query.
+ createTableQuery.prepare("CREATE TABLE " + DOMAINS_TABLE + "(" +
+ _ID + " INTEGER PRIMARY KEY, " +
+ DOMAIN_NAME + " TEXT, " +
+ JAVASCRIPT + " INTEGER DEFAULT 0, " +
+ LOCAL_STORAGE + " INTEGER DEFAULT 0, " +
+ DOM_STORAGE + " INTEGER DEFAULT 0, " +
+ USER_AGENT + " TEXT DEFAULT '" + UserAgentHelper::SYSTEM_DEFAULT_DATABASE + "', " +
+ ZOOM_FACTOR + " INTEGER DEFAULT 0, " +
+ CUSTOM_ZOOM_FACTOR + " REAL DEFAULT 1.0)"
+ );
+
+ // Execute the query.
+ if (!createTableQuery.exec())
+ {
+ // Log any errors.
+ qDebug().noquote().nospace() << "Error creating table: " << domainsDatabase.lastError();
+ }
+
+ // Set the schema version.
+ domainsDatabase.exec("PRAGMA user_version = " + QString::number(SCHEMA_VERSION));
+ }
+ }
+ else // Opening the database failed.
+ {
+ // Write the last database error message to the debug output.
+ qDebug().noquote().nospace() << "Error opening database: " << domainsDatabase.lastError();
+ }
+};
+
+QSqlQuery DomainsDatabase::getDomainQuery(const QString &hostname)
+{
+ // Get a handle for the domains database.
+ QSqlDatabase domainsDatabase = QSqlDatabase::database(CONNECTION_NAME);
+
+ // Instantiate the all domain names query.
+ QSqlQuery allDomainNamesQuery(domainsDatabase);
+
+ // Set the query to be forward only (increases performance while iterating over the query).
+ allDomainNamesQuery.setForwardOnly(true);
+
+ // Prepare the query.
+ allDomainNamesQuery.prepare("SELECT " + _ID + "," + DOMAIN_NAME + " FROM " + DOMAINS_TABLE);
+
+ // Execute the query.
+ allDomainNamesQuery.exec();
+
+ // Create a domains settings map.
+ QMap<QString, int> domainSettingsMap;
+
+ // Populate the domain settings map.
+ while (allDomainNamesQuery.next())
+ {
+ // Add the domain name and database ID to the map.
+ domainSettingsMap.insert(allDomainNamesQuery.record().field(DOMAIN_NAME).value().toString(), allDomainNamesQuery.record().field(_ID).value().toInt());
+ }
+
+ // Initialize the database ID tracker.
+ int databaseId = -1;
+
+ // Get the database ID if the hostname is found in the domain settings set.
+ if (domainSettingsMap.contains(hostname))
+ {
+ databaseId = domainSettingsMap.value(hostname);
+ }
+
+ // Create a subdomain string.
+ QString subdomain = hostname;
+
+ // Check all the subdomains of the hostname.
+ while ((databaseId == -1) && subdomain.contains(".")) // Stop checking when a match is found or there are no more `.` in the hostname.
+ {
+ // Check to see if the domain settings map contains the subdomain with a `*.` prepended.
+ if (domainSettingsMap.contains("*." + subdomain))
+ {
+ // Get the database ID.
+ databaseId = domainSettingsMap.value("*." + subdomain);
+ }
+
+ // Strip out the first subdomain.
+ subdomain = subdomain.section('.', 1);
+ }
+
+ // Instantiate the domain lookup query.
+ QSqlQuery domainLookupQuery(domainsDatabase);
+
+ // Prepare the domain lookup query.
+ domainLookupQuery.prepare("SELECT * FROM " + DOMAINS_TABLE + " WHERE " + _ID + " = " + QString::number(databaseId));
+
+ // Execute the query.
+ domainLookupQuery.exec();
+
+ // Move to the first entry.
+ domainLookupQuery.first();
+
+ // Return the query.
+ return domainLookupQuery;
+}
--- /dev/null
+/*
+ * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Browser PC <https://www.stoutner.com/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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DOMAINSDATABASE_H
+#define DOMAINSDATABASE_H
+
+// Qt framework headers.
+#include <QtSql>
+
+class DomainsDatabase
+{
+public:
+ // The default constructor.
+ DomainsDatabase();
+
+ // The public functions.
+ static void addDatabase();
+ static QSqlQuery getDomainQuery(const QString &hostname);
+
+ // The public int constants.
+ static const int SYSTEM_DEFAULT = 0;
+ static const int DISABLED = 1;
+ static const int ENABLED = 2;
+ static const int CUSTOM = 1;
+
+ // The public constants.
+ static const QString _ID;
+ static const QString CONNECTION_NAME;
+ static const QString CUSTOM_ZOOM_FACTOR;
+ static const QString DOM_STORAGE;
+ static const QString DOMAIN_NAME;
+ static const QString DOMAINS_TABLE;
+ static const QString JAVASCRIPT;
+ static const QString LOCAL_STORAGE;
+ static const QString USER_AGENT;
+ static const QString ZOOM_FACTOR;
+
+private:
+ // The private static constants.
+ static const int SCHEMA_VERSION;
+};
+#endif
// Application headers.
#include "AddOrEditCookieDialog.h"
#include "ui_AddOrEditCookieDialog.h"
+#include "databases/CookiesDatabase.h"
// KDE Framework headers.
#include <KLocalizedString>
const int AddOrEditCookieDialog::EditCookie = 1;
// Construct the class.
-AddOrEditCookieDialog::AddOrEditCookieDialog(const int &dialogType, const QNetworkCookie *cookiePointer) : QDialog(nullptr)
+AddOrEditCookieDialog::AddOrEditCookieDialog(const int &dialogType, const QNetworkCookie *cookiePointer, const bool &isDurable) : QDialog(nullptr)
{
// Set the dialog window title according to the dialog type.
if (dialogType == AddCookie)
else
setWindowTitle(i18nc("The edit cookie dialog window title.", "Edit Cookie"));
- // Populate the is edit dialog boolean.
+ // Populate the class variables.
isEditDialog = (dialogType == EditCookie);
+ originalIsDurable = isDurable;
// Set the window modality.
setWindowModality(Qt::WindowModality::ApplicationModal);
// Get handles for the widgets.
domainLineEditPointer = addOrEditCookieDialogUi.domainLineEdit;
nameLineEditPointer = addOrEditCookieDialogUi.nameLineEdit;
+ durableCheckBoxPointer = addOrEditCookieDialogUi.durableCheckBox;
expirationCheckBoxPointer = addOrEditCookieDialogUi.expirationCheckBox;
expirationDateTimeEditPointer = addOrEditCookieDialogUi.expirationDateTimeEdit;
pathLineEditPointer = addOrEditCookieDialogUi.pathLineEdit;
if (isEditDialog)
{
// Store the old cookie.
- oldCookie = *cookiePointer;
+ originalCookie = *cookiePointer;
// Populate the widgets.
- domainLineEditPointer->setText(oldCookie.domain());
- nameLineEditPointer->setText(oldCookie.name());
- pathLineEditPointer->setText(oldCookie.path());
- httpOnlyCheckBoxPointer->setChecked(oldCookie.isHttpOnly());
- secureCheckBoxPointer->setChecked(oldCookie.isSecure());
- valueLineEditPointer->setText(oldCookie.value());
+ domainLineEditPointer->setText(originalCookie.domain());
+ durableCheckBoxPointer->setChecked(originalIsDurable);
+ nameLineEditPointer->setText(originalCookie.name());
+ pathLineEditPointer->setText(originalCookie.path());
+ httpOnlyCheckBoxPointer->setChecked(originalCookie.isHttpOnly());
+ secureCheckBoxPointer->setChecked(originalCookie.isSecure());
+ valueLineEditPointer->setText(originalCookie.value());
// Populate the expiration date if it exists.
- if (!oldCookie.isSessionCookie())
+ if (!originalCookie.isSessionCookie())
{
// Check the expiration box.
expirationCheckBoxPointer->setChecked(true);
expirationDateTimeEditPointer->setEnabled(true);
// Set the expiration date.
- expirationDateTimeEditPointer->setDateTime(oldCookie.expirationDate());
+ expirationDateTimeEditPointer->setDateTime(originalCookie.expirationDate());
}
}
{
// Delete the old cookie if this is an edit dialog.
if (isEditDialog)
- emit deleteCookie(oldCookie);
+ emit deleteCookie(originalCookie);
// Create the variables.
QNetworkCookie cookie;
// Populate the cookie.
- cookie.setDomain(domainLineEditPointer->text());
+ cookie.setDomain(domainLineEditPointer->text().toLower());
cookie.setName(nameLineEditPointer->text().toUtf8());
cookie.setPath(pathLineEditPointer->text());
cookie.setHttpOnly(httpOnlyCheckBoxPointer->isChecked());
// Populate the expiration date if it is specified.
if (expirationCheckBoxPointer->isChecked()) cookie.setExpirationDate(expirationDateTimeEditPointer->dateTime());
- // Add the cookie.
- emit addCookie(cookie);
+ // Get the durable status.
+ const bool isDurable = durableCheckBoxPointer->isChecked();
+
+ // Update the durable cookies database.
+ if (originalIsDurable) // The cookie is currently in the durable cookies database.
+ {
+ if (isDurable) // Update the cookie in the database.
+ {
+ qDebug() << "Updating a durable cookie.";
+
+ // Update the cookie in the durable cookies database.
+ CookiesDatabase::updateCookie(originalCookie, cookie);
+ }
+ else // Delete the cookie from the database.
+ {
+ qDebug() << "Deleting a durable cookie.";
+
+ // Delete the cookie from the durable cookies database.
+ CookiesDatabase::deleteCookie(originalCookie);
+ }
+ }
+ else if (isDurable) // The cookie is being added to the durable cookies database.
+ {
+ qDebug() << "Adding a durable cookie.";
+
+ // Add the cookie to the durable cookies database.
+ CookiesDatabase::addCookie(cookie);
+ }
+
+ // Add the cookie to the store, the list, and the tree.
+ emit addCookie(cookie, isDurable);
// Close the dialog.
reject();
public:
// The primary constructor.
- explicit AddOrEditCookieDialog(const int &dialogType, const QNetworkCookie *cookiePointer = nullptr);
+ explicit AddOrEditCookieDialog(const int &dialogType, const QNetworkCookie *cookiePointer = nullptr, const bool &isDurable = false);
// The public static constants.
static const int AddCookie;
signals:
// The signals.
- void addCookie(const QNetworkCookie &cookie) const;
+ void addCookie(const QNetworkCookie &cookie, const bool &isDurable) const;
void deleteCookie(const QNetworkCookie &cookie) const;
private Q_SLOTS:
private:
// The private widgets.
QLineEdit *domainLineEditPointer;
+ QCheckBox *durableCheckBoxPointer;
QCheckBox *expirationCheckBoxPointer;
QDateTimeEdit *expirationDateTimeEditPointer;
QCheckBox *httpOnlyCheckBoxPointer;
QLineEdit *valueLineEditPointer;
// The private variables.
- QNetworkCookie oldCookie;
bool isEditDialog;
+ QNetworkCookie originalCookie;
+ bool originalIsDurable;
};
#endif
#include "AddOrEditCookieDialog.h"
#include "CookiesDialog.h"
#include "ui_CookiesDialog.h"
+#include "databases/CookiesDatabase.h"
// KDE Frameworks headers.
#include <KLocalizedString>
// Get a handle for the tree view.
treeViewPointer = cookiesDialogUi.treeView;
- // Initialize the standard item model.
- standardItemModelPointer = new QStandardItemModel();
+ // Initialize the tree model.
+ treeModelPointer = new QStandardItemModel();
// Set the column count.
- standardItemModelPointer->setColumnCount(6);
-
- // Set the header data.
- standardItemModelPointer->setHeaderData(0, Qt::Horizontal, i18nc("The cookie Name header.", "Name"));
- standardItemModelPointer->setHeaderData(1, Qt::Horizontal, i18nc("The cookie Path header.", "Path"));
- standardItemModelPointer->setHeaderData(2, Qt::Horizontal, i18nc("The cookie Expiration Date header.", "Expiration Date"));
- standardItemModelPointer->setHeaderData(3, Qt::Horizontal, i18nc("The cookie HTTP Only header.", "HTTP Only"));
- standardItemModelPointer->setHeaderData(4, Qt::Horizontal, i18nc("The cookie Secure header.", "Secure"));
- standardItemModelPointer->setHeaderData(5, Qt::Horizontal, i18nc("The cookie Value header.", "Value"));
-
- // Set the header tool tips.
- standardItemModelPointer->horizontalHeaderItem(0)->setToolTip(i18nc("The cookie Name tool tip.",
+ treeModelPointer->setColumnCount(7);
+
+ // Set the tree header data.
+ treeModelPointer->setHeaderData(0, Qt::Horizontal, i18nc("The cookie Name header.", "Name"));
+ treeModelPointer->setHeaderData(1, Qt::Horizontal, i18nc("The cookie Durable header.", "Durable"));
+ treeModelPointer->setHeaderData(2, Qt::Horizontal, i18nc("The cookie Path header.", "Path"));
+ treeModelPointer->setHeaderData(3, Qt::Horizontal, i18nc("The cookie Expiration Date header.", "Expiration Date"));
+ treeModelPointer->setHeaderData(4, Qt::Horizontal, i18nc("The cookie HTTP Only header.", "HTTP Only"));
+ treeModelPointer->setHeaderData(5, Qt::Horizontal, i18nc("The cookie Secure header.", "Secure"));
+ treeModelPointer->setHeaderData(6, Qt::Horizontal, i18nc("The cookie Value header.", "Value"));
+
+ // Set the tree header tool tips.
+ treeModelPointer->horizontalHeaderItem(0)->setToolTip(i18nc("The cookie Name tool tip.",
"The name identifies the cookie. Each cookie has a unique combination of domain, name, and path."));
- standardItemModelPointer->horizontalHeaderItem(1)->setToolTip(i18nc("The cookie Path tool tip.", "Websites can restrict cookie access to subpath of their URL."));
- standardItemModelPointer->horizontalHeaderItem(2)->setToolTip(i18nc("The cookie Expiration Date tool tip.",
+ treeModelPointer->horizontalHeaderItem(1)->setToolTip(i18nc("The cookie Durable tool tip",
+ "Durable cookies pursist across restarts, irrespective of the expiration date. All other cookies are deleted when Privacy Browser closes, irrespective of the expiration date."));
+ treeModelPointer->horizontalHeaderItem(2)->setToolTip(i18nc("The cookie Path tool tip.", "Websites can restrict cookie access to subpath of their URL."));
+ treeModelPointer->horizontalHeaderItem(3)->setToolTip(i18nc("The cookie Expiration Date tool tip.",
"Cookies without an expiration date are known as session cookies and are expected to be deleted every time the browser closes."));
- standardItemModelPointer->horizontalHeaderItem(3)->setToolTip(i18nc("The cookie HTTP Only tool tip.",
+ treeModelPointer->horizontalHeaderItem(4)->setToolTip(i18nc("The cookie HTTP Only tool tip.",
"Restrict cookie access to HTTP (and HTTPS). This prevents JavaScript from accessing the cookie, which hardens it against cross-site scripting attacks."));
- standardItemModelPointer->horizontalHeaderItem(4)->setToolTip(i18nc("The cookie Secure tool tip.", "Only allow the cookie to be transferred across HTTPS (as opposed to HTTP)."));
- standardItemModelPointer->horizontalHeaderItem(5)->setToolTip(i18nc("The cookie Value tool tip.", "The value contains the cookie data."));
+ treeModelPointer->horizontalHeaderItem(5)->setToolTip(i18nc("The cookie Secure tool tip.", "Only allow the cookie to be transferred across HTTPS (as opposed to HTTP)."));
+ treeModelPointer->horizontalHeaderItem(6)->setToolTip(i18nc("The cookie Value tool tip.", "The value contains the cookie data."));
// Sort the cookie list.
cookieListPointer->sort(cookieSortPredicate);
// Create the current domain string.
QString currentDomainString = "";
- // Create the current domain standard item pointer.
- QStandardItem *currentDomainStandardItemPointer;
+ // Create the current domain item pointer.
+ QStandardItem *currentDomainItemPointer;
- // Populate the VBoxLayout.
+ // Populate the cookie tree view.
for (QNetworkCookie cookie : *cookieListPointer)
{
// Get the cookie domain.
// Check to see if the cookie is a member of the current domain.
if (cookieDomain != currentDomainString) // Create a new domain in the tree.
{
- // Create a list for the domain standard items.
- QList<QStandardItem*> domainStandardItemList;
-
- // Create the new domain standard items.
- QStandardItem *domainStandardItemPointer = new QStandardItem(cookieDomain);
- QStandardItem *pathStandardItemPointer = new QStandardItem(QStringLiteral(""));
- QStandardItem *expirationDateStandardItemPointer = new QStandardItem(QStringLiteral(""));
- QStandardItem *isHttpOnlyStandardItemPointer = new QStandardItem(QStringLiteral(""));
- QStandardItem *isSecureStandardItemPointer = new QStandardItem(QStringLiteral(""));
- QStandardItem *valueStandardItemPointer = new QStandardItem(QStringLiteral(""));
-
- // Disable editing of the domain.
- domainStandardItemPointer->setEditable(false);
- pathStandardItemPointer->setEditable(false);
- expirationDateStandardItemPointer->setEditable(false);
- isHttpOnlyStandardItemPointer->setEditable(false);
- isSecureStandardItemPointer->setEditable(false);
- valueStandardItemPointer->setEditable(false);
-
- // Populate the domain standard item list.
- domainStandardItemList.append(domainStandardItemPointer);
- domainStandardItemList.append(pathStandardItemPointer);
- domainStandardItemList.append(expirationDateStandardItemPointer);
- domainStandardItemList.append(isHttpOnlyStandardItemPointer);
- domainStandardItemList.append(isSecureStandardItemPointer);
- domainStandardItemList.append(valueStandardItemPointer);
+ // Create the domain name item.
+ QStandardItem *domainNameItemPointer = new QStandardItem(cookieDomain);
// Add the domain to the tree.
- standardItemModelPointer->invisibleRootItem()->appendRow(domainStandardItemList);
+ treeModelPointer->invisibleRootItem()->appendRow(domainNameItemPointer);
// Update the current domain string.
currentDomainString = cookieDomain;
- // Update the current domain standard item pointer.
- currentDomainStandardItemPointer = domainStandardItemPointer;
+ // Update the current domain item pointer.
+ currentDomainItemPointer = domainNameItemPointer;
}
- // Create a list for the cookie standard items.
- QList<QStandardItem*> cookieStandardItemList;
-
- // Create the cookie standard items.
- QStandardItem *nameStandardItemPointer = new QStandardItem(QString(cookie.name()));
- QStandardItem *pathStandardItemPointer = new QStandardItem(QString(cookie.path()));
- QStandardItem *expirationDateStandardItemPointer = new QStandardItem(QString(cookie.expirationDate().toString()));
- QStandardItem *isHttpOnlyStandardItemPointer = new QStandardItem(QString(cookie.isHttpOnly() ? i18n("yes") : i18n("no")));
- QStandardItem *isSecureStandardItemPointer = new QStandardItem(QString(cookie.isSecure() ? i18n("yes") : i18n("no")));
- QStandardItem *valueStandardItemPointer = new QStandardItem(QString(cookie.value()));
-
- // Disable editing of the cookie standard items.
- nameStandardItemPointer->setEditable(false);
- pathStandardItemPointer->setEditable(false);
- expirationDateStandardItemPointer->setEditable(false);
- isHttpOnlyStandardItemPointer->setEditable(false);
- isSecureStandardItemPointer->setEditable(false);
- valueStandardItemPointer->setEditable(false);
+ // Check to see if the cookie is durable.
+ bool isDurable = CookiesDatabase::isDurable(cookie);
+
+ // Create a list for the cookie items.
+ QList<QStandardItem*> cookieItemList;
+
+ // Create the cookie items.
+ QStandardItem *nameItemPointer = new QStandardItem(QString(cookie.name()));
+ QStandardItem *durableItemPointer = new QStandardItem(QString(isDurable ? i18n("yes") : i18n("no")));
+ QStandardItem *pathItemPointer = new QStandardItem(QString(cookie.path()));
+ QStandardItem *expirationDateItemPointer = new QStandardItem(QString(cookie.expirationDate().toString()));
+ QStandardItem *isHttpOnlyItemPointer = new QStandardItem(QString(cookie.isHttpOnly() ? i18n("yes") : i18n("no")));
+ QStandardItem *isSecureItemPointer = new QStandardItem(QString(cookie.isSecure() ? i18n("yes") : i18n("no")));
+ QStandardItem *valueItemPointer = new QStandardItem(QString(cookie.value()));
// Populate the cookie standard item list.
- cookieStandardItemList.append(nameStandardItemPointer);
- cookieStandardItemList.append(pathStandardItemPointer);
- cookieStandardItemList.append(expirationDateStandardItemPointer);
- cookieStandardItemList.append(isHttpOnlyStandardItemPointer);
- cookieStandardItemList.append(isSecureStandardItemPointer);
- cookieStandardItemList.append(valueStandardItemPointer);
+ cookieItemList.append(nameItemPointer);
+ cookieItemList.append(durableItemPointer);
+ cookieItemList.append(pathItemPointer);
+ cookieItemList.append(expirationDateItemPointer);
+ cookieItemList.append(isHttpOnlyItemPointer);
+ cookieItemList.append(isSecureItemPointer);
+ cookieItemList.append(valueItemPointer);
// Add the cookie to the tree.
- currentDomainStandardItemPointer->appendRow(cookieStandardItemList);
+ currentDomainItemPointer->appendRow(cookieItemList);
}
// Auto resize the headers.
// Indicate that all the rows are the same height, wich improves performance.
treeViewPointer->setUniformRowHeights(true);
- // Set the tree view model.
- treeViewPointer->setModel(standardItemModelPointer);
+ // Disable editing.
+ treeViewPointer->setEditTriggers(QAbstractItemView::NoEditTriggers);
+
+ // Set the tree model.
+ treeViewPointer->setModel(treeModelPointer);
- // Get a handle for the tree view selection model.
- treeViewSelectionModelPointer = treeViewPointer->selectionModel();
+ // Get a handle for the tree selection model.
+ treeSelectionModelPointer = treeViewPointer->selectionModel();
// Listen for selection changes.
- connect(treeViewSelectionModelPointer, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(updateUi()));
+ connect(treeSelectionModelPointer, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(updateUi()));
// Get handles for the buttons.
addCookieButtonPointer = cookiesDialogUi.addCookieButton;
updateUi();
};
-void CookiesDialog::addCookieFromDialog(const QNetworkCookie &cookie) const
+void CookiesDialog::addCookieFromDialog(const QNetworkCookie &cookie, const bool &isDurable) const
{
// Add the cookie to the cookie list and the cookie store.
emit addCookie(cookie);
QString newDomain = cookie.domain();
// Check to see if the domain already exists in the model.
- QList<QStandardItem*> currentDomainStandardItemList = standardItemModelPointer->findItems(newDomain);
+ QList<QStandardItem*> currentDomainItemList = treeModelPointer->findItems(newDomain);
- // Create a domain standard item pointer.
- QStandardItem *domainStandardItemPointer;
+ // Create a domain item pointer.
+ QStandardItem *domainNameItemPointer;
- // Prepare the domain standard item pointer.
- if (currentDomainStandardItemList.isEmpty()) // The domain doesn't currently exist in the tree.
+ // Prepare the domain item pointer.
+ if (currentDomainItemList.isEmpty()) // The domain doesn't currently exist in the tree.
{
- // Create a list for the domain standard items.
- QList<QStandardItem*> domainStandardItemList;
-
- // Create the new domain standard items.
- domainStandardItemPointer = new QStandardItem(newDomain);
- QStandardItem *pathStandardItemPointer = new QStandardItem(QStringLiteral(""));
- QStandardItem *expirationDateStandardItemPointer = new QStandardItem(QStringLiteral(""));
- QStandardItem *isHttpOnlyStandardItemPointer = new QStandardItem(QStringLiteral(""));
- QStandardItem *isSecureStandardItemPointer = new QStandardItem(QStringLiteral(""));
- QStandardItem *valueStandardItemPointer = new QStandardItem(QStringLiteral(""));
-
- // Disable editing of the domain.
- domainStandardItemPointer->setEditable(false);
- pathStandardItemPointer->setEditable(false);
- expirationDateStandardItemPointer->setEditable(false);
- isHttpOnlyStandardItemPointer->setEditable(false);
- isSecureStandardItemPointer->setEditable(false);
- valueStandardItemPointer->setEditable(false);
-
- // Populate the domain standard item list.
- domainStandardItemList.append(domainStandardItemPointer);
- domainStandardItemList.append(pathStandardItemPointer);
- domainStandardItemList.append(expirationDateStandardItemPointer);
- domainStandardItemList.append(isHttpOnlyStandardItemPointer);
- domainStandardItemList.append(isSecureStandardItemPointer);
- domainStandardItemList.append(valueStandardItemPointer);
+ // Create the domain name item.
+ domainNameItemPointer = new QStandardItem(newDomain);
// Create the insert domain row number.
int insertDomainRowNumber = 0;
// Get the number of domains in the tree.
- int numberOfDomains = standardItemModelPointer->invisibleRootItem()->rowCount();
+ int numberOfDomains = treeModelPointer->invisibleRootItem()->rowCount();
// Get the new domain strings.
QString newDomainTopLevelDomain = newDomain.section('.', -1);
for (int i = 0; i < numberOfDomains; ++i)
{
// Get the current domain strings.
- QString currentDomain = standardItemModelPointer->invisibleRootItem()->child(i, 0)->index().data().toString();
+ QString currentDomain = treeModelPointer->invisibleRootItem()->child(i, 0)->index().data().toString();
QString currentDomainTopLevelDomain = currentDomain.section('.', -1);
QString currentDomainSecondLevelDomain = currentDomain.section('.', -2);
QString currentDomainThirdLevelDomain = currentDomain.section('.', -3);
}
// Add the domain to the tree.
- standardItemModelPointer->invisibleRootItem()->insertRow(insertDomainRowNumber, domainStandardItemList);
+ treeModelPointer->invisibleRootItem()->insertRow(insertDomainRowNumber, domainNameItemPointer);
}
else // The domain already exists in the tree.
{
// Use the current domain standard item.
- domainStandardItemPointer = currentDomainStandardItemList[0];
+ domainNameItemPointer = currentDomainItemList[0];
}
// Get strings for the new cookie name and path (used later in the placement of the row).
QString newCookieName = QString(cookie.name());
QString newCookiePath = QString(cookie.path());
- // Create a list for the cookie standard items.
- QList<QStandardItem*> cookieStandardItemList;
-
- // Create the cookie standard items.
- QStandardItem *nameStandardItemPointer = new QStandardItem(newCookieName);
- QStandardItem *pathStandardItemPointer = new QStandardItem(newCookiePath);
- QStandardItem *expirationDateStandardItemPointer = new QStandardItem(QString(cookie.expirationDate().toString()));
- QStandardItem *isHttpOnlyStandardItemPointer = new QStandardItem(QString(cookie.isHttpOnly() ? i18n("yes") : i18n("no")));
- QStandardItem *isSecureStandardItemPointer = new QStandardItem(QString(cookie.isSecure() ? i18n("yes") : i18n("no")));
- QStandardItem *valueStandardItemPointer = new QStandardItem(QString(cookie.value()));
-
- // Disable editing of the cookie standard items.
- nameStandardItemPointer->setEditable(false);
- pathStandardItemPointer->setEditable(false);
- expirationDateStandardItemPointer->setEditable(false);
- isHttpOnlyStandardItemPointer->setEditable(false);
- isSecureStandardItemPointer->setEditable(false);
- valueStandardItemPointer->setEditable(false);
-
- // Populate the cookie standard item list.
- cookieStandardItemList.append(nameStandardItemPointer);
- cookieStandardItemList.append(pathStandardItemPointer);
- cookieStandardItemList.append(expirationDateStandardItemPointer);
- cookieStandardItemList.append(isHttpOnlyStandardItemPointer);
- cookieStandardItemList.append(isSecureStandardItemPointer);
- cookieStandardItemList.append(valueStandardItemPointer);
+ // Create a cookie item list.
+ QList<QStandardItem*> cookieItemList;
+
+ // Create the cookie items.
+ QStandardItem *nameItemPointer = new QStandardItem(newCookieName);
+ QStandardItem *durableItemPointer = new QStandardItem(QString(isDurable ? i18n("yes") : i18n("no")));
+ QStandardItem *pathItemPointer = new QStandardItem(newCookiePath);
+ QStandardItem *expirationDateItemPointer = new QStandardItem(QString(cookie.expirationDate().toString()));
+ QStandardItem *isHttpOnlyItemPointer = new QStandardItem(QString(cookie.isHttpOnly() ? i18n("yes") : i18n("no")));
+ QStandardItem *isSecureItemPointer = new QStandardItem(QString(cookie.isSecure() ? i18n("yes") : i18n("no")));
+ QStandardItem *valueItemPointer = new QStandardItem(QString(cookie.value()));
+
+ // Populate the cookie item list.
+ cookieItemList.append(nameItemPointer);
+ cookieItemList.append(durableItemPointer);
+ cookieItemList.append(pathItemPointer);
+ cookieItemList.append(expirationDateItemPointer);
+ cookieItemList.append(isHttpOnlyItemPointer);
+ cookieItemList.append(isSecureItemPointer);
+ cookieItemList.append(valueItemPointer);
// Create the insert cookie row number.
int insertCookieRowNumber = 0;
+ // Create the remove existing row tracker.
+ bool removeExistingRow = false;
+
// Get the number of cookies in the domain.
- int numberOfCookies = domainStandardItemPointer->rowCount();
+ int numberOfCookies = domainNameItemPointer->rowCount();
// Iterate through the cookies for this domain.
for (int i = 0; i < numberOfCookies; ++i)
{
// Get the current cookie name and path at the indicated row.
- QString currentCookieName = domainStandardItemPointer->child(i, 0)->index().data().toString();
- QString currentCookiePath = domainStandardItemPointer->child(i, 1)->index().data().toString();
+ QString currentCookieName = domainNameItemPointer->child(i, 0)->index().data().toString();
+ QString currentCookiePath = domainNameItemPointer->child(i, 2)->index().data().toString();
// Check to see if the new cookie should be inserted after the current cookie.
- if (newCookieName > currentCookieName)
+ if (newCookieName > currentCookieName) // The new cookie name comes after the current cookie name.
{
// Insert the new cookie after the current cookie.
insertCookieRowNumber = i + 1;
}
- else if ((newCookieName == currentCookieName) && (newCookiePath > currentCookiePath))
+ else if ((newCookieName == currentCookieName) && (newCookiePath > currentCookiePath)) // The names are the same, but the new cookie path comes after the current cookie path.
{
// Insert the new cookie after the current cookie.
insertCookieRowNumber = i + 1;
}
+ else if ((newCookieName == currentCookieName) && (newCookiePath == currentCookiePath)) // The cookies are the same.
+ {
+ // Remove the existing cookie in this row.
+ removeExistingRow = true;
+
+ // Insert the cookie in it's place.
+ insertCookieRowNumber = i;
+ }
}
- // Add the cookie to the tree.
- domainStandardItemPointer->insertRow(insertCookieRowNumber, cookieStandardItemList);
+ // Remove the existing row if it is being edited.
+ if (removeExistingRow)
+ domainNameItemPointer->removeRow(insertCookieRowNumber);
+
+ // Add the cookie to the tree model.
+ domainNameItemPointer->insertRow(insertCookieRowNumber, cookieItemList);
// Get the new cookie model index.
- QModelIndex newCookieIndex = nameStandardItemPointer->index();
+ QModelIndex newCookieIndex = nameItemPointer->index();
// Set the new cookie to be the current index.
treeViewPointer->setCurrentIndex(newCookieIndex);
treeViewPointer->expand(newCookieIndex.parent());
}
-void CookiesDialog::deleteCookie(const QModelIndex &modelIndex) const
+void CookiesDialog::deleteCookie(const QModelIndex &modelIndex, const bool &deleteDurableCookies) const
{
// Create a partial cookie.
QNetworkCookie partialCookie;
// Populate the partial cookie from the current model index.
partialCookie.setDomain(modelIndex.parent().siblingAtColumn(0).data().toString());
partialCookie.setName(modelIndex.siblingAtColumn(0).data().toString().toUtf8());
- partialCookie.setPath(modelIndex.siblingAtColumn(1).data().toString());
+ partialCookie.setPath(modelIndex.siblingAtColumn(2).data().toString());
// Create a cookie to delete.
QNetworkCookie cookieToDelete;
- // Search for the partial cookie in the cookie list.
- for (QNetworkCookie cookie : *cookieListPointer)
+ // Check if the cookie is durable.
+ bool isDurable = CookiesDatabase::isDurable(partialCookie);
+
+ // Only delete durable cookies if directed.
+ if (deleteDurableCookies || !isDurable)
{
- // Store the cookie to delete if it has the same identifier as the partial cookie.
- if (cookie.hasSameIdentifier(partialCookie))
- cookieToDelete = cookie;
+ // Search for the partial cookie in the cookie list.
+ for (QNetworkCookie cookie : *cookieListPointer)
+ {
+ // Store the cookie to delete if it has the same identifier as the partial cookie.
+ if (cookie.hasSameIdentifier(partialCookie))
+ cookieToDelete = cookie;
+ }
+
+ // Remove the cookie from the tree model.
+ treeModelPointer->removeRow(modelIndex.row(), modelIndex.parent());
+
+ // Delete the cookie from the cookie list and cookie store.
+ emit deleteCookie(cookieToDelete);
+
+ // Delete the cookie from the durable cookies database.
+ if (isDurable)
+ CookiesDatabase::deleteCookie(cookieToDelete);
}
+}
- // Remove the cookie from the tree view.
- standardItemModelPointer->removeRow(modelIndex.row(), modelIndex.parent());
+void CookiesDialog::deleteDomain(const QModelIndex &modelIndex, const bool &deleteDurableCookies) const
+{
+ // Get the parent index.
+ QModelIndex parentIndex = modelIndex.parent();
- // Delete the cookie from the cookie list and cookie store.
- emit deleteCookie(cookieToDelete);
+ // Get the number of cookies in the domain.
+ int numberOfCookies = treeModelPointer->rowCount(modelIndex);
+
+ // Delete each child cookie, starting from the bottom.
+ for (int i = numberOfCookies; i > 0; --i)
+ deleteCookie(treeModelPointer->index(i-1, 0, modelIndex), deleteDurableCookies);
+
+ // Remove the domain if all the cookies have been deleted.
+ if (treeModelPointer->rowCount(modelIndex) == 0)
+ treeModelPointer->removeRow(modelIndex.row(), parentIndex);
}
+
void CookiesDialog::deleteCookieFromDialog(const QNetworkCookie &cookie) const
{
// Get the current model index.
- QModelIndex currentIndex = treeViewSelectionModelPointer->currentIndex();
+ QModelIndex currentIndex = treeSelectionModelPointer->currentIndex();
// Get the parent index.
QModelIndex parentIndex = currentIndex.parent();
- // Remove the cookie from the tree view.
- standardItemModelPointer->removeRow(currentIndex.row(), parentIndex);
+ // Remove the cookie from the tree model.
+ treeModelPointer->removeRow(currentIndex.row(), parentIndex);
- // Remove the domain from the tree view if its only cookie has been deleted.
- if (standardItemModelPointer->rowCount(parentIndex) == 0)
- standardItemModelPointer->removeRow(parentIndex.row(), parentIndex.parent());
+ // Remove the domain from the tree model if its only cookie has been deleted.
+ if (treeModelPointer->rowCount(parentIndex) == 0)
+ treeModelPointer->removeRow(parentIndex.row(), parentIndex.parent());
// Delete the cookie from the cookie list and cookie store.
emit deleteCookie(cookie);
addCookieDialogPointer->show();
// Add the cookie if directed.
- connect(addCookieDialogPointer, SIGNAL(addCookie(QNetworkCookie)), this, SLOT(addCookieFromDialog(QNetworkCookie)));
+ connect(addCookieDialogPointer, SIGNAL(addCookie(QNetworkCookie, bool)), this, SLOT(addCookieFromDialog(QNetworkCookie, bool)));
}
void CookiesDialog::showDeleteAllMessageBox() const
// Set the text.
deleteAllCookiesMessageBox.setText(i18nc("Delete all cookies dialog text", "Delete all cookies?"));
+ // Create a delete durable cookies check box.
+ QCheckBox deleteDurableCookiesCheckBox(i18nc("Delete durable cookies check box", "Delete even if durable"));
+
+ // Add the check box to the dialog.
+ deleteAllCookiesMessageBox.setCheckBox(&deleteDurableCookiesCheckBox);
+
// Set the standard buttons.
deleteAllCookiesMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
// Delete all cookies if instructed.
if (returnValue == QMessageBox::Yes)
{
- // Delete all the cookies.
- emit deleteAllCookies();
+ // Only delete durable cookies if requested.
+ if (deleteDurableCookiesCheckBox.isChecked()) // Delete everything.
+ {
+ // Delete all the cookies.
+ emit deleteAllCookies();
+
+ // Clear the tree model.
+ treeModelPointer->clear();
+
+ // Delete the durable cookies from the database.
+ CookiesDatabase::deleteAllCookies();
+
+ // Update the UI.
+ updateUi();
+ }
+ else // Only delete cookies that are not durable.
+ {
+ // Get the root model index.
+ QModelIndex rootIndex = treeModelPointer->invisibleRootItem()->index();
- // Clear the standard item model.
- standardItemModelPointer->clear();
+ // Get the number of domains.
+ int numberOfDomains = treeModelPointer->rowCount(rootIndex);
- // Update the UI.
- updateUi();
+ // Delete each domain, starting from the bottom.
+ for (int i = numberOfDomains; i > 0; --i)
+ deleteDomain(treeModelPointer->index(i - 1, 0, rootIndex), deleteDurableCookiesCheckBox.isChecked());
+ }
}
}
void CookiesDialog::showDeleteCookieMessageBox() const
{
// Get the current model index.
- QModelIndex currentIndex = treeViewSelectionModelPointer->currentIndex();
-
- // Get the parent model index.
- QModelIndex parentIndex = currentIndex.parent();
+ QModelIndex currentIndex = treeSelectionModelPointer->currentIndex();
// Determine if a domain is selected.
- bool isDomain = standardItemModelPointer->hasChildren(currentIndex);
+ bool isDomain = treeModelPointer->hasChildren(currentIndex);
// Instantiate a delete cookie message box.
QMessageBox deleteCookieMessageBox;
// Set the icon.
deleteCookieMessageBox.setIcon(QMessageBox::Warning);
- if (isDomain)
+ // Create a delete durable cookies check box.
+ QCheckBox deleteDurableCookiesCheckBox(i18nc("Delete durable cookies check box", "Delete even if durable"));
+
+ if (isDomain) // A domain is selected.
{
// Get the number of cookies.
- int numberOfCookiesToDelete = standardItemModelPointer->rowCount(currentIndex);
+ int numberOfCookiesToDelete = treeModelPointer->rowCount(currentIndex);
// Set the window title.
- deleteCookieMessageBox.setWindowTitle(i18nc("Delete cookies dialog title", "Delete %1 Cookies", numberOfCookiesToDelete));
+ deleteCookieMessageBox.setWindowTitle(i18ncp("Delete cookies dialog title", "Delete %1 Cookie", "Delete 1% Cookies", numberOfCookiesToDelete));
// Set the text.
- deleteCookieMessageBox.setText(i18nc("Delete cookies dialog text", "Delete %1 cookies?", numberOfCookiesToDelete));
+ deleteCookieMessageBox.setText(i18ncp("Delete cookies dialog text", "Delete %1 cookie?", "Delete %1 cookies?", numberOfCookiesToDelete));
}
- else
+ else // A single cookie is selected.
{
// Set the window title.
deleteCookieMessageBox.setWindowTitle(i18nc("Delete cookie dialog title", "Delete 1 Cookie"));
// Set the text.
deleteCookieMessageBox.setText(i18nc("Delete cookie dialog text", "Delete 1 cookie?"));
+
+ // Check the box.
+ deleteDurableCookiesCheckBox.setChecked(true);
}
+ // Add the check box to the dialog.
+ deleteCookieMessageBox.setCheckBox(&deleteDurableCookiesCheckBox);
+
// Set the standard buttons.
deleteCookieMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
// Delete the cookies according to the selection.
if (isDomain) // A domain is selected.
{
- // Get the number of cookies.
- int numberOfCookies = standardItemModelPointer->rowCount(currentIndex);
-
- // Delete each child cookie.
- for (int i = 0; i < numberOfCookies; ++i)
- {
- // Delete the cookie for the first child. Once this is deleted, the second child will become the first child.
- deleteCookie(standardItemModelPointer->index(0, 0, currentIndex));
- }
-
- // Delete the domain from the tree view.
- standardItemModelPointer->removeRow(currentIndex.row(), parentIndex);
+ // Delete the domain.
+ deleteDomain(currentIndex, deleteDurableCookiesCheckBox.isChecked());
}
else // A single cookie is selected.
{
+ // Get the parent model index.
+ QModelIndex parentIndex = currentIndex.parent();
+
// Delete the cookie.
- deleteCookie(currentIndex);
+ deleteCookie(currentIndex, deleteDurableCookiesCheckBox.isChecked());
// Remove the domain row if its only cookie has been deleted.
- if (standardItemModelPointer->rowCount(parentIndex) == 0)
- standardItemModelPointer->removeRow(parentIndex.row(), parentIndex.parent());
+ if (treeModelPointer->rowCount(parentIndex) == 0)
+ treeModelPointer->removeRow(parentIndex.row(), parentIndex.parent());
}
}
}
void CookiesDialog::showEditCookieDialog() const
{
// Get the current model index.
- QModelIndex currentIndex = treeViewSelectionModelPointer->currentIndex();
+ QModelIndex currentIndex = treeSelectionModelPointer->currentIndex();
// Create a partial cookie.
QNetworkCookie partialCookie;
// Populate the partial cookie from the current model index.
partialCookie.setDomain(currentIndex.parent().siblingAtColumn(0).data().toString());
partialCookie.setName(currentIndex.siblingAtColumn(0).data().toString().toUtf8());
- partialCookie.setPath(currentIndex.siblingAtColumn(1).data().toString());
+ partialCookie.setPath(currentIndex.siblingAtColumn(2).data().toString());
// Create a cookie to edit.
QNetworkCookie cookieToEdit;
}
// Instantiate an edit cookie dialog.
- QDialog *editCookieDialogPointer = new AddOrEditCookieDialog(AddOrEditCookieDialog::EditCookie, &cookieToEdit);
+ QDialog *editCookieDialogPointer = new AddOrEditCookieDialog(AddOrEditCookieDialog::EditCookie, &cookieToEdit, currentIndex.siblingAtColumn(1).data().toString() == i18n("yes"));
// Show the dialog.
editCookieDialogPointer->show();
// Process cookie events.
- connect(editCookieDialogPointer, SIGNAL(addCookie(QNetworkCookie)), this, SLOT(addCookieFromDialog(QNetworkCookie)));
+ connect(editCookieDialogPointer, SIGNAL(addCookie(QNetworkCookie, bool)), this, SLOT(addCookieFromDialog(QNetworkCookie, bool)));
connect(editCookieDialogPointer, SIGNAL(deleteCookie(QNetworkCookie)), this, SLOT(deleteCookieFromDialog(QNetworkCookie)));
}
void CookiesDialog::updateUi() const
{
// Get the current index of the first column.
- QModelIndex currentIndex = treeViewSelectionModelPointer->currentIndex().siblingAtColumn(0);
+ QModelIndex currentIndex = treeSelectionModelPointer->currentIndex().siblingAtColumn(0);
// Set the status of the buttons.
- editCookieButtonPointer->setEnabled(treeViewSelectionModelPointer->hasSelection() && !standardItemModelPointer->hasChildren(currentIndex));
- deleteCookieButtonPointer->setEnabled(treeViewSelectionModelPointer->hasSelection());;
- deleteAllButtonPointer->setEnabled(standardItemModelPointer->hasChildren(standardItemModelPointer->invisibleRootItem()->index()));
+ editCookieButtonPointer->setEnabled(treeSelectionModelPointer->hasSelection() && !treeModelPointer->hasChildren(currentIndex));
+ deleteCookieButtonPointer->setEnabled(treeSelectionModelPointer->hasSelection());;
+ deleteAllButtonPointer->setEnabled(treeModelPointer->hasChildren(treeModelPointer->invisibleRootItem()->index()));
// Update the delete cookie button text.
if (deleteCookieButtonPointer->isEnabled()) // The button is enabled.
{
- if (standardItemModelPointer->hasChildren(currentIndex)) // A domain is selected.
+ if (treeModelPointer->hasChildren(currentIndex)) // A domain is selected.
{
// Update the button text.
- deleteCookieButtonPointer->setText(i18nc("Delete cookies button.", "&Delete %1 cookies", standardItemModelPointer->rowCount(currentIndex)));
+ deleteCookieButtonPointer->setText(i18ncp("Delete cookies button.", "&Delete %1 cookie", "&Delete %1 cookies", treeModelPointer->rowCount(currentIndex)));
}
else // A single cookie is selected.
{
private Q_SLOTS:
// The private slots.
- void addCookieFromDialog(const QNetworkCookie &cookie) const;
+ void addCookieFromDialog(const QNetworkCookie &cookie, const bool &isDurable) const;
void deleteCookieFromDialog(const QNetworkCookie &cookie) const;
void showAddCookieDialog() const;
void showDeleteAllMessageBox() const;
private:
// The private variables.
- QItemSelectionModel *treeViewSelectionModelPointer;
QPushButton *addCookieButtonPointer;
std::list<QNetworkCookie> *cookieListPointer;
QPushButton *deleteAllButtonPointer;
QPushButton *deleteCookieButtonPointer;
QPushButton *editCookieButtonPointer;
- QStandardItemModel *standardItemModelPointer;
+ QStandardItemModel *treeModelPointer;
+ QItemSelectionModel *treeSelectionModelPointer;
QTreeView *treeViewPointer;
// The private functions.
- void deleteCookie(const QModelIndex &modelIndex) const;
+ void deleteCookie(const QModelIndex &modelIndex, const bool &deleteDurableCookies) const;
+ void deleteDomain(const QModelIndex &modelIndex, const bool &deleteDurableCookies) const;
};
#endif
#include "DomainSettingsDialog.h"
#include "Settings.h"
#include "ui_DomainSettingsDialog.h"
-#include "helpers/DomainsDatabaseHelper.h"
+#include "databases/DomainsDatabase.h"
#include "helpers/UserAgentHelper.h"
// Qt toolkit headers.
resetButtonPointer = dialogButtonBoxPointer->button(QDialogButtonBox::StandardButton::Reset);
// Create a table model.
- domainsTableModelPointer = new QSqlTableModel(nullptr, QSqlDatabase::database(DomainsDatabaseHelper::CONNECTION_NAME));
+ domainsTableModelPointer = new QSqlTableModel(nullptr, QSqlDatabase::database(DomainsDatabase::CONNECTION_NAME));
// Set the table for the model.
- domainsTableModelPointer->setTable(DomainsDatabaseHelper::DOMAINS_TABLE);
+ domainsTableModelPointer->setTable(DomainsDatabase::DOMAINS_TABLE);
// Set the edit strategy to be manual.
domainsTableModelPointer->setEditStrategy(QSqlTableModel::EditStrategy::OnManualSubmit);
case SHOW_ALL_DOMAINS:
{
// Select the first entry in the list view.
- domainsListViewPointer->setCurrentIndex(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::DOMAIN_NAME)));
+ domainsListViewPointer->setCurrentIndex(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME)));
// Populate the domain settings.
domainSelected(domainsSelectionModelPointer->currentIndex());
case EDIT_DOMAIN:
{
// Find the index for the new domain. `1` returns the first match.
- QModelIndexList newDomainIndex = domainsTableModelPointer->match(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::DOMAIN_NAME)),
- Qt::DisplayRole, domainName, 1, Qt::MatchWrap);
+ QModelIndexList newDomainIndex = domainsTableModelPointer->match(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME)),
+ Qt::DisplayRole, domainName, 1, Qt::MatchWrap);
// Move to the new domain.
domainsListViewPointer->setCurrentIndex(newDomainIndex[0]);
void DomainSettingsDialog::addDomain(const QString &domainName) const
{
// Create a new domain record.
- QSqlRecord newDomainRecord = QSqlDatabase::database(DomainsDatabaseHelper::CONNECTION_NAME).record(DomainsDatabaseHelper::DOMAINS_TABLE);
+ QSqlRecord newDomainRecord = QSqlDatabase::database(DomainsDatabase::CONNECTION_NAME).record(DomainsDatabase::DOMAINS_TABLE);
// Set the values for the new domain.
- newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::DOMAIN_NAME), domainName);
- newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::JAVASCRIPT), DomainsDatabaseHelper::SYSTEM_DEFAULT);
- newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::DOM_STORAGE), DomainsDatabaseHelper::SYSTEM_DEFAULT);
- newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::USER_AGENT), UserAgentHelper::SYSTEM_DEFAULT_DATABASE);
- newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::ZOOM_FACTOR), DomainsDatabaseHelper::SYSTEM_DEFAULT);
- newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::CUSTOM_ZOOM_FACTOR), 1.0);
+ newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME), domainName);
+ newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabase::JAVASCRIPT), DomainsDatabase::SYSTEM_DEFAULT);
+ newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabase::DOM_STORAGE), DomainsDatabase::SYSTEM_DEFAULT);
+ newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabase::USER_AGENT), UserAgentHelper::SYSTEM_DEFAULT_DATABASE);
+ newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabase::ZOOM_FACTOR), DomainsDatabase::SYSTEM_DEFAULT);
+ newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabase::CUSTOM_ZOOM_FACTOR), 1.0);
// Insert the new domain. `-1` appends it to the end.
domainsTableModelPointer->insertRecord(-1, newDomainRecord);
domainsTableModelPointer->submitAll();
// Find the index for the new domain. `-1` allows for multiple entries to be returned.
- QModelIndexList newDomainIndex = domainsTableModelPointer->match(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::DOMAIN_NAME)),
- Qt::DisplayRole, domainName, -1, Qt::MatchWrap);
+ QModelIndexList newDomainIndex = domainsTableModelPointer->match(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME)),
+ Qt::DisplayRole, domainName, -1, Qt::MatchWrap);
// Move to the new domain. If there are multiple domains with the same name, the new one should be the last in the list.
domainsListViewPointer->setCurrentIndex(newDomainIndex[newDomainIndex.size() - 1]);
QModelIndex currentIndex = domainsListViewPointer->currentIndex();
// Get the ID of the current index row.
- QVariant currentId = currentIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::_ID)).data();
+ QVariant currentId = currentIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::_ID)).data();
// Submit all pending changes.
domainsTableModelPointer->submitAll();
// Find the new index for the selected id. The `1` keeps searching after the first match.
- QModelIndexList newIndexList = domainsTableModelPointer->match(currentIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::_ID)), Qt::DisplayRole, currentId,
+ QModelIndexList newIndexList = domainsTableModelPointer->match(currentIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::_ID)), Qt::DisplayRole, currentId,
1, Qt::MatchWrap);
// Select the new index.
- domainsListViewPointer->setCurrentIndex(newIndexList[0].siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::DOMAIN_NAME)));
+ domainsListViewPointer->setCurrentIndex(newIndexList[0].siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME)));
// Update the UI.
updateUi();
void DomainSettingsDialog::customZoomFactorChanged(const double &newValue) const
{
// Update the domains table model.
- domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::CUSTOM_ZOOM_FACTOR)), newValue);
+ domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::CUSTOM_ZOOM_FACTOR)), newValue);
// Update the UI.
updateUi();
void DomainSettingsDialog::domStorageChanged(const int &newIndex) const
{
// Update the domains table model.
- domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::DOM_STORAGE)), newIndex);
+ domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::DOM_STORAGE)), newIndex);
// Populate the DOM storage label.
populateDomStorageLabel();
domainNameLineEditPointer->setText(modelIndex.data().toString());
// Populate the JavaScript combo box.
- javaScriptComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::JAVASCRIPT)).data().toInt());
+ javaScriptComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::JAVASCRIPT)).data().toInt());
// Populate the local storage combo box.
- localStorageComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::LOCAL_STORAGE)).data().toInt());
+ localStorageComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::LOCAL_STORAGE)).data().toInt());
// Populate the DOM storage combo box.
- domStorageComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::DOM_STORAGE)).data().toInt());
+ domStorageComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::DOM_STORAGE)).data().toInt());
// Get the user agent string.
- QString userAgent = modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::USER_AGENT)).data().toString();
+ QString userAgent = modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::USER_AGENT)).data().toString();
// Get the user agent index.
int userAgentIndex = UserAgentHelper::getDomainSettingsUserAgentIndex(userAgent);
if (userAgentIndex == -1) userAgentComboBoxPointer->setCurrentText(userAgent);
// Get the zoom factor combo box index.
- int zoomFactorComboBoxIndex = modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::ZOOM_FACTOR)).data().toInt();
+ int zoomFactorComboBoxIndex = modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::ZOOM_FACTOR)).data().toInt();
// Populate the zoom factor combo box.
zoomFactorComboBoxPointer->setCurrentIndex(zoomFactorComboBoxIndex);
else // Custom zoom factor is selected.
{
// Display the custom zoom factor from the domain settings.
- customZoomFactorSpinBoxPointer->setValue(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::CUSTOM_ZOOM_FACTOR)).data().toDouble());
+ customZoomFactorSpinBoxPointer->setValue(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::CUSTOM_ZOOM_FACTOR)).data().toDouble());
}
// Set the initial status of the custom zoom factor spin box.
void DomainSettingsDialog::javaScriptChanged(const int &newIndex) const
{
// Update the domains table model.
- domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::JAVASCRIPT)), newIndex);
+ domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::JAVASCRIPT)), newIndex);
// Populate the JavaScript label.
populateJavaScriptLabel();
void DomainSettingsDialog::localStorageChanged(const int &newIndex) const
{
// Update the domains table model.
- domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::LOCAL_STORAGE)), newIndex);
+ domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::LOCAL_STORAGE)), newIndex);
// Poplate the local storage label.
populateLocalStorageLabel();
switch (domStorageComboBoxPointer->currentIndex())
{
// Set the text according to the system default.
- case (DomainsDatabaseHelper::SYSTEM_DEFAULT):
+ case (DomainsDatabase::SYSTEM_DEFAULT):
{
if (Settings::domStorageEnabled())
domStorageLabelPointer->setText(i18nc("Domain settings DOM storage label.", "DOM storage enabled"));
}
// Set the disabled text in bold.
- case (DomainsDatabaseHelper::DISABLED):
+ case (DomainsDatabase::DISABLED):
{
domStorageLabelPointer->setText(i18nc("Domain settings DOM storage label. The <b> tags should be retained.", "<b>DOM storage disabled</b>"));
}
// Set the enabled text in bold.
- case (DomainsDatabaseHelper::ENABLED):
+ case (DomainsDatabase::ENABLED):
{
domStorageLabelPointer->setText(i18nc("Domain settings DOM storage label. The <b> tags should be retained.", "<b>DOM storage enabled</b>"));
switch (javaScriptComboBoxPointer->currentIndex())
{
// Set the text according to the system default.
- case (DomainsDatabaseHelper::SYSTEM_DEFAULT):
+ case (DomainsDatabase::SYSTEM_DEFAULT):
{
if (Settings::javaScriptEnabled())
javaScriptLabelPointer->setText(i18nc("Domain settings JavaScript label.", "JavaScript enabled"));
}
// Set the disabled text in bold.
- case (DomainsDatabaseHelper::DISABLED):
+ case (DomainsDatabase::DISABLED):
{
javaScriptLabelPointer->setText(i18nc("Domain settings JavaScript label. The <b> tags should be retained.", "<b>JavaScript disabled</b>"));
}
// Set the enabled text in bold.
- case (DomainsDatabaseHelper::ENABLED):
+ case (DomainsDatabase::ENABLED):
{
javaScriptLabelPointer->setText(i18nc("Domain settings JavaScript label. The <b> tags should be retained.", "<b>JavaScript enabled</b>"));
switch (localStorageComboBoxPointer->currentIndex())
{
// Set the text according to the system default.
- case (DomainsDatabaseHelper::SYSTEM_DEFAULT):
+ case (DomainsDatabase::SYSTEM_DEFAULT):
{
if (Settings::localStorageEnabled())
localStorageLabelPointer->setText(i18nc("Domain settings local storage label.", "Local storage enabled"));
}
// Set the disabled text in bold.
- case (DomainsDatabaseHelper::DISABLED):
+ case (DomainsDatabase::DISABLED):
{
localStorageLabelPointer->setText(i18nc("Domain settings local storage label. The <b> tags should be retained.", "<b>Local storage disabled</b>"));
}
// Set the enabled text in bold.
- case (DomainsDatabaseHelper::ENABLED):
+ case (DomainsDatabase::ENABLED):
{
localStorageLabelPointer->setText(i18nc("Domain settings local storage label. The <b> tabs should be retained.", "<b>Local storage enabled</b>"));
void DomainSettingsDialog::userAgentChanged(const QString &updatedUserAgent) const
{
// Update the domains table model.
- domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::USER_AGENT)),
+ domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::USER_AGENT)),
UserAgentHelper::getDatabaseUserAgentNameFromTranslatedName(updatedUserAgent));
// Populate the user agent label.
QModelIndex modelIndex = domainsSelectionModelPointer->currentIndex();
// Update the domains table model.
- domainsTableModelPointer->setData(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::ZOOM_FACTOR)), newIndex);
+ domainsTableModelPointer->setData(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::ZOOM_FACTOR)), newIndex);
// Populate the custom zoom factor spin box according to the zoom factor combo box.
if (newIndex == 0) // System default zoom factor is selected.
else // Custom zoom factor is selected.
{
// Display the custom zoom factor from the domain settings.
- customZoomFactorSpinBoxPointer->setValue(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::CUSTOM_ZOOM_FACTOR)).data().toDouble());
+ customZoomFactorSpinBoxPointer->setValue(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::CUSTOM_ZOOM_FACTOR)).data().toDouble());
}
// Update the status of the custom zoom factor spin box.
# List the sources to include in the executable.
target_sources(privacy-browser PRIVATE
- DomainsDatabaseHelper.cpp
SearchEngineHelper.cpp
UserAgentHelper.cpp
)
+++ /dev/null
-/*
- * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
- *
- * This file is part of Privacy Browser PC <https://www.stoutner.com/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 <http://www.gnu.org/licenses/>.
- */
-
-// Application headers.
-#include "DomainsDatabaseHelper.h"
-#include "UserAgentHelper.h"
-
-// Define the public static domain constants.
-const QString DomainsDatabaseHelper::CONNECTION_NAME = "domains_database";
-const QString DomainsDatabaseHelper::DOMAINS_TABLE = "domains";
-
-// Define the private static schema constants.
-const int DomainsDatabaseHelper::SCHEMA_VERSION = 5;
-
-// Define the public static database field names.
-const QString DomainsDatabaseHelper::_ID = "_id";
-const QString DomainsDatabaseHelper::DOMAIN_NAME = "domain_name";
-const QString DomainsDatabaseHelper::JAVASCRIPT = "javascript";
-const QString DomainsDatabaseHelper::LOCAL_STORAGE = "local_storage";
-const QString DomainsDatabaseHelper::DOM_STORAGE = "dom_storage";
-const QString DomainsDatabaseHelper::USER_AGENT = "user_agent";
-const QString DomainsDatabaseHelper::ZOOM_FACTOR = "zoom_factor";
-const QString DomainsDatabaseHelper::CUSTOM_ZOOM_FACTOR = "custom_zoom_factor";
-
-// Construct the class.
-DomainsDatabaseHelper::DomainsDatabaseHelper() {}
-
-void DomainsDatabaseHelper::addDatabase()
-{
- // Add the domain settings database.
- QSqlDatabase domainsDatabase = QSqlDatabase::addDatabase("QSQLITE", CONNECTION_NAME);
-
- // Set the database name.
- domainsDatabase.setDatabaseName(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/domains.db");
-
- // Open the database.
- if (domainsDatabase.open()) // Opening the database succeeded.
- {
- // Check to see if the domains table already exists.
- if (domainsDatabase.tables().contains(DOMAINS_TABLE))
- {
- // Query the database schema version.
- QSqlQuery getSchemaVersionQuery = domainsDatabase.exec("PRAGMA user_version");
-
- // Move to the first record.
- getSchemaVersionQuery.first();
-
- // Get the current schema version.
- int currentSchemaVersion = getSchemaVersionQuery.value(0).toInt();
-
- // Check to see if the schama has been updated.
- if (SCHEMA_VERSION > currentSchemaVersion)
- {
- // Run schema update code.
- switch (currentSchemaVersion)
- {
- // Upgrade from schema version 0 to schema version 1.
- case 0:
- {
- // Add the JavaScript column.
- domainsDatabase.exec("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + JAVASCRIPT + " INTEGER DEFAULT 0");
-
- // Fallthrough to the next case.
- [[fallthrough]];
- }
-
- // Upgrade from schema version 1 to schema version 2.
- case 1:
- {
- // Add the User Agent column.
- domainsDatabase.exec("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + USER_AGENT + " TEXT DEFAULT '" + UserAgentHelper::SYSTEM_DEFAULT_DATABASE + "'");
-
- // Fallthrough to the next case.
- [[fallthrough]];
- }
-
- // Upgrade from schema version 2 to schema version 3.
- case 2:
- {
- // Add the Zoom Factor columns.
- domainsDatabase.exec("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + ZOOM_FACTOR + " INTEGER DEFAULT 0");
- domainsDatabase.exec("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + CUSTOM_ZOOM_FACTOR + " REAL DEFAULT 1.0");
-
- // Fallthrough to the next case.
- [[fallthrough]];
- }
-
- // Upgrade from schema version 3 to schema version 4.
- case 3:
- {
- // Add the DOM Storage column.
- domainsDatabase.exec("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + DOM_STORAGE + " INTEGER DEFAULT 0");
-
- // Fallthrough to the next case.
- [[fallthrough]];
- }
-
- case 4:
- {
- // Add the Local Storage column.
- domainsDatabase.exec("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + LOCAL_STORAGE + " INTEGER DEFAULT 0");
-
- // Fallthrough to the next case.
- // [[fallthrough]];
- }
- }
-
- // Update the schema version.
- domainsDatabase.exec("PRAGMA user_version = " + QString::number(SCHEMA_VERSION));
- }
- }
- else
- {
- // Instantiate a create table query.
- QSqlQuery createTableQuery(domainsDatabase);
-
- // Prepare the create table query.
- createTableQuery.prepare("CREATE TABLE " + DOMAINS_TABLE + "(" +
- _ID + " INTEGER PRIMARY KEY, " +
- DOMAIN_NAME + " TEXT, " +
- JAVASCRIPT + " INTEGER DEFAULT 0, " +
- LOCAL_STORAGE + " INTEGER DEFAULT 0, " +
- DOM_STORAGE + " INTEGER DEFAULT 0, " +
- USER_AGENT + " TEXT DEFAULT '" + UserAgentHelper::SYSTEM_DEFAULT_DATABASE + "', " +
- ZOOM_FACTOR + " INTEGER DEFAULT 0, " +
- CUSTOM_ZOOM_FACTOR + " REAL DEFAULT 1.0)"
- );
-
- // Execute the query.
- if (!createTableQuery.exec())
- {
- // Log any errors.
- qDebug().noquote().nospace() << "Error creating table: " << domainsDatabase.lastError();
- }
-
- // Set the schema version.
- domainsDatabase.exec("PRAGMA user_version = " + QString::number(SCHEMA_VERSION));
- }
- }
- else // Opening the database failed.
- {
- // Write the last database error message to the debug output.
- qDebug().noquote().nospace() << "Error opening database: " << domainsDatabase.lastError();
- }
-};
-
-QSqlQuery DomainsDatabaseHelper::getDomainQuery(const QString &hostname)
-{
- // Get a handle for the domains database.
- QSqlDatabase domainsDatabase = QSqlDatabase::database(CONNECTION_NAME);
-
- // Instantiate the all domain names query.
- QSqlQuery allDomainNamesQuery(domainsDatabase);
-
- // Set the query to be forward only (increases performance while iterating over the query).
- allDomainNamesQuery.setForwardOnly(true);
-
- // Prepare the query.
- allDomainNamesQuery.prepare("SELECT " + _ID + "," + DOMAIN_NAME + " FROM " + DOMAINS_TABLE);
-
- // Execute the query.
- allDomainNamesQuery.exec();
-
- // Create a domains settings map.
- QMap<QString, int> domainSettingsMap;
-
- // Populate the domain settings map.
- while (allDomainNamesQuery.next())
- {
- // Add the domain name and database ID to the map.
- domainSettingsMap.insert(allDomainNamesQuery.record().field(DomainsDatabaseHelper::DOMAIN_NAME).value().toString(),
- allDomainNamesQuery.record().field(DomainsDatabaseHelper::_ID).value().toInt());
- }
-
- // Initialize the database ID tracker.
- int databaseId = -1;
-
- // Get the database ID if the hostname is found in the domain settings set.
- if (domainSettingsMap.contains(hostname))
- {
- databaseId = domainSettingsMap.value(hostname);
- }
-
- // Create a subdomain string.
- QString subdomain = hostname;
-
- // Check all the subdomains of the hostname.
- while ((databaseId == -1) && subdomain.contains(".")) // Stop checking when a match is found or there are no more `.` in the hostname.
- {
- // Check to see if the domain settings map contains the subdomain with a `*.` prepended.
- if (domainSettingsMap.contains("*." + subdomain))
- {
- // Get the database ID.
- databaseId = domainSettingsMap.value("*." + subdomain);
- }
-
- // Strip out the first subdomain.
- subdomain = subdomain.section('.', 1);
- }
-
- // Instantiate the domain lookup query.
- QSqlQuery domainLookupQuery(domainsDatabase);
-
- // Prepare the domain lookup query.
- domainLookupQuery.prepare("SELECT * FROM " + DOMAINS_TABLE + " WHERE " + _ID + " = " + QString::number(databaseId));
-
- // Execute the query.
- domainLookupQuery.exec();
-
- // Move to the first entry.
- domainLookupQuery.first();
-
- // Return the query.
- return domainLookupQuery;
-}
+++ /dev/null
-/*
- * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
- *
- * This file is part of Privacy Browser PC <https://www.stoutner.com/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 <http://www.gnu.org/licenses/>.
- */
-
-#ifndef DOMAINSDATABASEHELPER_H
-#define DOMAINSDATABASEHELPER_H
-
-// Qt framework headers.
-#include <QtSql>
-
-class DomainsDatabaseHelper
-{
-public:
- // The default constructor.
- DomainsDatabaseHelper();
-
- // The public functions.
- static void addDatabase();
- static QSqlQuery getDomainQuery(const QString &hostname);
-
- // The public int constants.
- static const int SYSTEM_DEFAULT = 0;
- static const int DISABLED = 1;
- static const int ENABLED = 2;
- static const int CUSTOM = 1;
-
- // The public constants.
- static const QString _ID;
- static const QString CONNECTION_NAME;
- static const QString CUSTOM_ZOOM_FACTOR;
- static const QString DOM_STORAGE;
- static const QString DOMAIN_NAME;
- static const QString DOMAINS_TABLE;
- static const QString JAVASCRIPT;
- static const QString LOCAL_STORAGE;
- static const QString USER_AGENT;
- static const QString ZOOM_FACTOR;
-
-private:
- // The private static constants.
- static const int SCHEMA_VERSION;
-};
-#endif
*/
// Application headers.
-#include "helpers/DomainsDatabaseHelper.h"
+#include "databases/CookiesDatabase.h"
+#include "databases/DomainsDatabase.h"
#include "windows/BrowserWindow.h"
// KDE Frameworks headers.
// Register with D-Bus, allowing multiple instances and allowing the program to run if for some reason the registration fails.
KDBusService appDBusService(KDBusService::Multiple | KDBusService::NoExitOnFailure);
- // Add the domains database.
- DomainsDatabaseHelper::addDatabase();
+ // Add the databases.
+ DomainsDatabase::addDatabase();
+ CookiesDatabase::addDatabase();
// Create the main window.
BrowserWindow *browserWindowPointer = new BrowserWindow();
<enum>Qt::AlignLeft</enum>
</property>
+ <!-- Durable. -->
+ <item>
+ <widget class="QCheckBox" name="durableCheckBox">
+ <property name="toolTip">
+ <string>Durable cookies pursist across restarts, irrespective of the expiration date. All other cookies are deleted when Privacy Browser closes, irrespective of the expiration date.</string>
+ </property>
+ </widget>
+ </item>
+
+ <item>
+ <widget class="QLabel">
+ <property name="text">
+ <string>Durable</string>
+ </property>
+
+ <property name="toolTip">
+ <string>Durable cookies pursist across restarts, irrespective of the expiration date. All other cookies are deleted when Privacy Browser closes, irrespective of the expiration date.</string>
+ </property>
+ </widget>
+ </item>
+
+ <item>
+ <widget class="QLabel">
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+
+ <!-- Spacer label. -->
+ <property name="text">
+ <string>&nbsp;&nbsp;&nbsp;</string>
+ </property>
+ </widget>
+ </item>
+
<!-- Path. -->
<item>
<widget class="QLabel">
<item>
<widget class="QLabel">
- <property name="toolTip">
- <string>Cookies without an expiration date are known as session cookies and are expected to be deleted every time the browser closes.</string>
- </property>
-
<property name="text">
<string>Expiration date</string>
</property>
+
+ <property name="toolTip">
+ <string>Cookies without an expiration date are known as session cookies and are expected to be deleted every time the browser closes.</string>
+ </property>
</widget>
</item>
<item>
<widget class="QLabel">
- <property name="toolTip">
- <string>Restrict cookie access to HTTP (and HTTPS). This prevents JavaScript from accessing the cookie, which hardens it against cross-site scripting attacks.</string>
- </property>
-
<property name="text">
<string>HTTP only</string>
</property>
+
+ <property name="toolTip">
+ <string>Restrict cookie access to HTTP (and HTTPS). This prevents JavaScript from accessing the cookie, which hardens it against cross-site scripting attacks.</string>
+ </property>
</widget>
</item>
<item>
<widget class="QLabel">
- <property name="toolTip">
- <string>Only allow the cookie to be transferred across HTTPS (as opposed to HTTP).</string>
- </property>
-
<property name="text">
<string>Secure</string>
</property>
+
+ <property name="toolTip">
+ <string>Only allow the cookie to be transferred across HTTPS (as opposed to HTTP).</string>
+ </property>
</widget>
</item>
</layout>
#include "BrowserView.h"
#include "Settings.h"
#include "ui_BrowserView.h"
+#include "databases/CookiesDatabase.h"
+#include "databases/DomainsDatabase.h"
#include "filters/MouseEventFilter.h"
-#include "helpers/DomainsDatabaseHelper.h"
#include "helpers/SearchEngineHelper.h"
#include "helpers/UserAgentHelper.h"
#include "interceptors/UrlRequestInterceptor.h"
connect(webEngineCookieStorePointer, SIGNAL(cookieAdded(QNetworkCookie)), this, SLOT(cookieAdded(QNetworkCookie)));
connect(webEngineCookieStorePointer, SIGNAL(cookieRemoved(QNetworkCookie)), this, SLOT(cookieRemoved(QNetworkCookie)));
+ // Get a list of durable cookies.
+ QList<QNetworkCookie*> *durableCookiesListPointer = CookiesDatabase::getCookies();
+
+ // Add the durable cookies to the store.
+ for (QNetworkCookie *cookiePointer : *durableCookiesListPointer)
+ addCookieToStore(*cookiePointer);
+
// Store a copy of the WebEngine default user agent.
webEngineDefaultUserAgent = webEngineProfilePointer->httpUserAgent();
webEnginePagePointer->deleteLater();
}
-void BrowserView::addCookieToStore(QNetworkCookie &cookie) const
+// The cookie is copied instead of referenced so that changes made to the cookie do not create a race condition with the display of the cookie in the dialog.
+void BrowserView::addCookieToStore(QNetworkCookie cookie) const
{
// Create a url.
QUrl url;
void BrowserView::applyDomainSettings(const QString &hostname, const bool reloadWebsite)
{
// Get the record for the hostname.
- QSqlQuery domainQuery = DomainsDatabaseHelper::getDomainQuery(hostname);
+ QSqlQuery domainQuery = DomainsDatabase::getDomainQuery(hostname);
// Check if the hostname has domain settings.
if (domainQuery.isValid()) // The hostname has domain settings.
QSqlRecord domainRecord = domainQuery.record();
// Set the JavaScript status.
- switch (domainRecord.field(DomainsDatabaseHelper::JAVASCRIPT).value().toInt())
+ switch (domainRecord.field(DomainsDatabase::JAVASCRIPT).value().toInt())
{
// Set the default JavaScript status.
- case (DomainsDatabaseHelper::SYSTEM_DEFAULT):
+ case (DomainsDatabase::SYSTEM_DEFAULT):
{
webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled());
}
// Disable JavaScript.
- case (DomainsDatabaseHelper::DISABLED):
+ case (DomainsDatabase::DISABLED):
{
webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, false);
}
// Enable JavaScript.
- case (DomainsDatabaseHelper::ENABLED):
+ case (DomainsDatabase::ENABLED):
{
webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
}
// Set the local storage status.
- switch (domainRecord.field(DomainsDatabaseHelper::LOCAL_STORAGE).value().toInt())
+ switch (domainRecord.field(DomainsDatabase::LOCAL_STORAGE).value().toInt())
{
// Set the default local storage status.
- case (DomainsDatabaseHelper::SYSTEM_DEFAULT):
+ case (DomainsDatabase::SYSTEM_DEFAULT):
{
currentPrivacyWebEnginePointer->localStorageEnabled = Settings::localStorageEnabled();
}
// Disable local storage.
- case (DomainsDatabaseHelper::DISABLED):
+ case (DomainsDatabase::DISABLED):
{
currentPrivacyWebEnginePointer->localStorageEnabled = false;
}
// Enable local storage.
- case (DomainsDatabaseHelper::ENABLED):
+ case (DomainsDatabase::ENABLED):
{
currentPrivacyWebEnginePointer->localStorageEnabled = true;
}
// Set the DOM storage status.
- switch (domainRecord.field(DomainsDatabaseHelper::DOM_STORAGE).value().toInt())
+ switch (domainRecord.field(DomainsDatabase::DOM_STORAGE).value().toInt())
{
// Set the default DOM storage status.
- case (DomainsDatabaseHelper::SYSTEM_DEFAULT):
+ case (DomainsDatabase::SYSTEM_DEFAULT):
{
webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled());
}
// Disable DOM storage.
- case (DomainsDatabaseHelper::DISABLED):
+ case (DomainsDatabase::DISABLED):
{
webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, false);
}
// Enable DOM storage.
- case (DomainsDatabaseHelper::ENABLED):
+ case (DomainsDatabase::ENABLED):
{
webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
}
// Set the user agent.
- webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getResultingDomainSettingsUserAgent(domainRecord.field(DomainsDatabaseHelper::USER_AGENT).value().toString()));
+ webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getResultingDomainSettingsUserAgent(domainRecord.field(DomainsDatabase::USER_AGENT).value().toString()));
// Check if a custom zoom factor is set.
- if (domainRecord.field(DomainsDatabaseHelper::ZOOM_FACTOR).value().toInt())
+ if (domainRecord.field(DomainsDatabase::ZOOM_FACTOR).value().toInt())
{
// Store the current zoom factor.
- currentZoomFactor = domainRecord.field(DomainsDatabaseHelper::CUSTOM_ZOOM_FACTOR).value().toDouble();
+ currentZoomFactor = domainRecord.field(DomainsDatabase::CUSTOM_ZOOM_FACTOR).value().toDouble();
}
else
{
webEngineViewPointer->setZoomFactor(currentZoomFactor);
// Apply the domain settings palette to the URL line edit.
- emit updateDomainSettingsIndicator(true, domainRecord.field(DomainsDatabaseHelper::DOMAIN_NAME).value().toString());
+ emit updateDomainSettingsIndicator(true, domainRecord.field(DomainsDatabase::DOMAIN_NAME).value().toString());
}
else // The hostname does not have domain settings.
{
public Q_SLOTS:
// The public slots.
- void addCookieToStore(QNetworkCookie &cookie) const;
+ void addCookieToStore(QNetworkCookie cookie) const;
void applyApplicationSettings();
void applyDomainSettingsAndReload();
void applyDomainSettingsWithoutReloading(const QString &hostname);
#include "Settings.h"
#include "ui_SettingsPrivacy.h"
#include "ui_SettingsGeneral.h"
+#include "databases/CookiesDatabase.h"
#include "dialogs/CookiesDialog.h"
#include "dialogs/DomainSettingsDialog.h"
#include "helpers/SearchEngineHelper.h"
// Update the action text.
cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", cookieListPointer->size()));
+
+ // Update the cookie if it is durable and has new data.
+ if (CookiesDatabase::isUpdate(newCookie))
+ CookiesDatabase::updateCookie(newCookie);
}
void BrowserWindow::addOrEditDomainSettings() const