2011-12-25 19:17:40 +01:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2011 Felix Geyer <debfx@fobos.de>
|
2017-06-09 23:40:36 +02:00
|
|
|
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
|
2011-12-25 19:17:40 +01:00
|
|
|
*
|
|
|
|
* This program 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 2 or (at your option)
|
|
|
|
* version 3 of the License.
|
|
|
|
*
|
|
|
|
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "Config.h"
|
|
|
|
|
2013-10-08 17:37:12 +02:00
|
|
|
#include <QCoreApplication>
|
2013-10-03 15:18:16 +02:00
|
|
|
#include <QDir>
|
|
|
|
#include <QSettings>
|
2018-02-04 22:55:07 +01:00
|
|
|
#include <QStandardPaths>
|
2018-03-31 16:01:30 -04:00
|
|
|
#include <QTemporaryFile>
|
2011-12-25 19:17:40 +01:00
|
|
|
|
2018-10-08 18:11:44 -07:00
|
|
|
/*
|
|
|
|
* Map of configuration file settings that are either deprecated, or have
|
|
|
|
* had their name changed. Entries in the map are of the form
|
|
|
|
* {oldName, newName}
|
|
|
|
* Set newName to empty string to remove the setting from the file.
|
|
|
|
*/
|
|
|
|
static const QMap<QString, QString> deprecationMap = {
|
|
|
|
// >2.3.4
|
2019-01-17 07:31:23 +01:00
|
|
|
{QStringLiteral("security/hidepassworddetails"), QStringLiteral("security/HidePasswordPreviewPanel")},
|
2018-10-08 18:11:44 -07:00
|
|
|
// >2.3.4
|
2019-01-17 07:31:23 +01:00
|
|
|
{QStringLiteral("GUI/HideDetailsView"), QStringLiteral("GUI/HidePreviewPanel")},
|
2018-10-08 18:11:44 -07:00
|
|
|
// >2.3.4
|
2019-01-17 07:31:23 +01:00
|
|
|
{QStringLiteral("GUI/DetailSplitterState"), QStringLiteral("GUI/PreviewSplitterState")},
|
2018-10-08 18:11:44 -07:00
|
|
|
// >2.3.4
|
2019-01-17 07:31:23 +01:00
|
|
|
{QStringLiteral("security/IconDownloadFallbackToGoogle"), QStringLiteral("security/IconDownloadFallback")},
|
2018-10-08 18:11:44 -07:00
|
|
|
};
|
|
|
|
|
2015-07-24 18:28:12 +02:00
|
|
|
Config* Config::m_instance(nullptr);
|
2012-05-31 14:51:44 +02:00
|
|
|
|
2012-05-27 20:05:57 +02:00
|
|
|
QVariant Config::get(const QString& key)
|
|
|
|
{
|
|
|
|
return m_settings->value(key, m_defaults.value(key));
|
|
|
|
}
|
|
|
|
|
2011-12-25 19:17:40 +01:00
|
|
|
QVariant Config::get(const QString& key, const QVariant& defaultValue)
|
|
|
|
{
|
|
|
|
return m_settings->value(key, defaultValue);
|
|
|
|
}
|
|
|
|
|
2017-03-06 17:12:07 -05:00
|
|
|
bool Config::hasAccessError()
|
|
|
|
{
|
|
|
|
return m_settings->status() & QSettings::AccessError;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Config::getFileName()
|
|
|
|
{
|
|
|
|
return m_settings->fileName();
|
|
|
|
}
|
|
|
|
|
2011-12-25 19:17:40 +01:00
|
|
|
void Config::set(const QString& key, const QVariant& value)
|
|
|
|
{
|
2018-10-01 10:26:24 -04:00
|
|
|
if (m_settings->contains(key) && m_settings->value(key) == value) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const bool surpressSignal = !m_settings->contains(key) && m_defaults.value(key) == value;
|
|
|
|
|
2011-12-25 19:17:40 +01:00
|
|
|
m_settings->setValue(key, value);
|
2018-10-01 10:26:24 -04:00
|
|
|
|
|
|
|
if (!surpressSignal) {
|
|
|
|
emit changed(key);
|
|
|
|
}
|
2011-12-25 19:17:40 +01:00
|
|
|
}
|
|
|
|
|
2018-02-04 13:18:59 +01:00
|
|
|
/**
|
|
|
|
* Sync configuration with persistent storage.
|
|
|
|
*
|
|
|
|
* Usually, you don't need to call this method manually, but if you are writing
|
|
|
|
* configurations after an emitted \link QCoreApplication::aboutToQuit() signal,
|
|
|
|
* use it to guarantee your config values are persisted.
|
|
|
|
*/
|
|
|
|
void Config::sync()
|
|
|
|
{
|
|
|
|
m_settings->sync();
|
|
|
|
}
|
|
|
|
|
2019-08-30 20:18:41 -04:00
|
|
|
void Config::resetToDefaults()
|
|
|
|
{
|
|
|
|
for (const auto& setting : m_defaults.keys()) {
|
|
|
|
m_settings->setValue(setting, m_defaults.value(setting));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-08 18:11:44 -07:00
|
|
|
void Config::upgrade()
|
|
|
|
{
|
2019-01-17 07:23:22 +01:00
|
|
|
const auto keys = deprecationMap.keys();
|
|
|
|
for (const auto& setting : keys) {
|
2018-10-08 18:11:44 -07:00
|
|
|
if (m_settings->contains(setting)) {
|
2018-11-01 04:27:38 +01:00
|
|
|
if (!deprecationMap.value(setting).isEmpty()) {
|
2018-10-08 18:11:44 -07:00
|
|
|
// Add entry with new name and old entry's value
|
|
|
|
m_settings->setValue(deprecationMap.value(setting), m_settings->value(setting));
|
|
|
|
}
|
|
|
|
m_settings->remove(setting);
|
|
|
|
}
|
|
|
|
}
|
2019-01-25 07:20:39 -05:00
|
|
|
|
|
|
|
// > 2.3.4
|
|
|
|
if (m_settings->value("AutoSaveAfterEveryChange").toBool()) {
|
|
|
|
m_settings->setValue("AutoSaveOnExit", true);
|
|
|
|
}
|
2019-06-09 19:15:02 +01:00
|
|
|
|
|
|
|
// Setting defaults for 'hide window on copy' behavior, keeping the user's original setting
|
|
|
|
if (m_settings->value("HideWindowOnCopy").isNull()) {
|
|
|
|
m_settings->setValue("HideWindowOnCopy", m_settings->value("MinimizeOnCopy").toBool());
|
|
|
|
m_settings->setValue("MinimizeOnCopy", true);
|
|
|
|
}
|
2018-10-08 18:11:44 -07:00
|
|
|
}
|
|
|
|
|
2012-06-14 22:55:25 +02:00
|
|
|
Config::Config(const QString& fileName, QObject* parent)
|
|
|
|
: QObject(parent)
|
|
|
|
{
|
|
|
|
init(fileName);
|
|
|
|
}
|
|
|
|
|
|
|
|
Config::Config(QObject* parent)
|
|
|
|
: QObject(parent)
|
2011-12-25 19:17:40 +01:00
|
|
|
{
|
2017-06-19 10:49:03 -04:00
|
|
|
// Check if portable config is present. If not, find it in user's directory
|
|
|
|
QString portablePath = QCoreApplication::applicationDirPath() + "/keepassxc.ini";
|
|
|
|
if (QFile::exists(portablePath)) {
|
|
|
|
init(portablePath);
|
|
|
|
} else {
|
|
|
|
QString userPath;
|
|
|
|
QString homePath = QDir::homePath();
|
|
|
|
|
2018-10-26 15:19:04 +02:00
|
|
|
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
2017-06-19 10:49:03 -04:00
|
|
|
// we can't use QStandardPaths on X11 as it uses XDG_DATA_HOME instead of XDG_CONFIG_HOME
|
|
|
|
QByteArray env = qgetenv("XDG_CONFIG_HOME");
|
|
|
|
if (env.isEmpty()) {
|
|
|
|
userPath = homePath;
|
|
|
|
userPath += "/.config";
|
|
|
|
} else if (env[0] == '/') {
|
|
|
|
userPath = QFile::decodeName(env);
|
|
|
|
} else {
|
|
|
|
userPath = homePath;
|
|
|
|
userPath += '/';
|
|
|
|
userPath += QFile::decodeName(env);
|
|
|
|
}
|
|
|
|
|
|
|
|
userPath += "/keepassxc/";
|
2018-03-31 16:01:30 -04:00
|
|
|
#else
|
2017-06-19 10:49:03 -04:00
|
|
|
userPath = QDir::fromNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
|
|
|
|
// storageLocation() appends the application name ("/keepassxc") to the end
|
|
|
|
userPath += "/";
|
2018-03-31 16:01:30 -04:00
|
|
|
#endif
|
2017-06-19 10:49:03 -04:00
|
|
|
|
2018-03-31 16:01:30 -04:00
|
|
|
#ifdef QT_DEBUG
|
2017-06-19 10:49:03 -04:00
|
|
|
userPath += "keepassxc_debug.ini";
|
2018-03-31 16:01:30 -04:00
|
|
|
#else
|
2017-06-19 10:49:03 -04:00
|
|
|
userPath += "keepassxc.ini";
|
2018-03-31 16:01:30 -04:00
|
|
|
#endif
|
2017-06-19 10:49:03 -04:00
|
|
|
|
|
|
|
init(userPath);
|
2011-12-25 19:17:40 +01:00
|
|
|
}
|
2012-06-14 22:55:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Config::~Config()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void Config::init(const QString& fileName)
|
|
|
|
{
|
|
|
|
m_settings.reset(new QSettings(fileName, QSettings::IniFormat));
|
2018-10-08 18:11:44 -07:00
|
|
|
upgrade();
|
2018-02-04 13:18:59 +01:00
|
|
|
connect(qApp, &QCoreApplication::aboutToQuit, this, &Config::sync);
|
2012-05-27 20:05:57 +02:00
|
|
|
|
2017-07-18 19:17:14 +02:00
|
|
|
m_defaults.insert("SingleInstance", true);
|
2012-05-27 23:01:14 +02:00
|
|
|
m_defaults.insert("RememberLastDatabases", true);
|
2018-11-22 11:47:31 +01:00
|
|
|
m_defaults.insert("NumberOfRememberedLastDatabases", 5);
|
2015-03-14 22:06:53 -05:00
|
|
|
m_defaults.insert("RememberLastKeyFiles", true);
|
2013-03-24 23:21:59 +01:00
|
|
|
m_defaults.insert("OpenPreviousDatabasesOnStartup", true);
|
2018-01-28 10:14:36 -05:00
|
|
|
m_defaults.insert("AutoSaveAfterEveryChange", true);
|
2014-06-09 10:51:24 +02:00
|
|
|
m_defaults.insert("AutoReloadOnChange", true);
|
2019-01-25 07:20:39 -05:00
|
|
|
m_defaults.insert("AutoSaveOnExit", true);
|
2018-01-14 18:04:33 -05:00
|
|
|
m_defaults.insert("BackupBeforeSave", false);
|
2018-01-17 20:13:13 -05:00
|
|
|
m_defaults.insert("UseAtomicSaves", true);
|
2017-06-20 16:54:13 -03:00
|
|
|
m_defaults.insert("SearchLimitGroup", false);
|
2019-06-21 19:42:27 -05:00
|
|
|
m_defaults.insert("MinimizeOnOpenUrl", false);
|
2019-06-09 19:15:02 +01:00
|
|
|
m_defaults.insert("HideWindowOnCopy", false);
|
|
|
|
m_defaults.insert("MinimizeOnCopy", true);
|
2019-08-12 19:31:37 +02:00
|
|
|
m_defaults.insert("MinimizeAfterUnlock", false);
|
2019-06-09 19:15:02 +01:00
|
|
|
m_defaults.insert("DropToBackgroundOnCopy", false);
|
|
|
|
m_defaults.insert("UseGroupIconOnEntryCreation", false);
|
2014-05-15 18:27:53 +02:00
|
|
|
m_defaults.insert("AutoTypeEntryTitleMatch", true);
|
2017-06-28 19:22:59 +03:00
|
|
|
m_defaults.insert("AutoTypeEntryURLMatch", true);
|
2017-06-28 18:37:16 +03:00
|
|
|
m_defaults.insert("AutoTypeDelay", 25);
|
2018-05-05 23:29:25 -04:00
|
|
|
m_defaults.insert("AutoTypeStartDelay", 500);
|
2017-02-22 16:08:06 +01:00
|
|
|
m_defaults.insert("UseGroupIconOnEntryCreation", true);
|
2017-09-27 18:28:14 -04:00
|
|
|
m_defaults.insert("IgnoreGroupExpansion", true);
|
2019-07-07 22:29:11 +03:00
|
|
|
m_defaults.insert("FaviconDownloadTimeout", 10);
|
2012-05-27 20:05:57 +02:00
|
|
|
m_defaults.insert("security/clearclipboard", true);
|
|
|
|
m_defaults.insert("security/clearclipboardtimeout", 10);
|
2019-07-30 23:44:34 -04:00
|
|
|
m_defaults.insert("security/clearsearch", true);
|
|
|
|
m_defaults.insert("security/clearsearchtimeout", 5);
|
2014-01-07 21:56:58 +01:00
|
|
|
m_defaults.insert("security/lockdatabaseidle", false);
|
2017-02-22 16:08:06 +01:00
|
|
|
m_defaults.insert("security/lockdatabaseidlesec", 240);
|
2016-10-25 15:17:50 +02:00
|
|
|
m_defaults.insert("security/lockdatabaseminimize", false);
|
2017-05-04 22:52:10 +02:00
|
|
|
m_defaults.insert("security/lockdatabasescreenlock", true);
|
2016-11-24 03:59:24 +01:00
|
|
|
m_defaults.insert("security/passwordsrepeat", false);
|
2014-01-12 17:23:47 +01:00
|
|
|
m_defaults.insert("security/passwordscleartext", false);
|
2018-09-29 13:44:23 +02:00
|
|
|
m_defaults.insert("security/passwordemptynodots", true);
|
2018-10-08 18:11:44 -07:00
|
|
|
m_defaults.insert("security/HidePasswordPreviewPanel", true);
|
2014-05-15 18:27:53 +02:00
|
|
|
m_defaults.insert("security/autotypeask", true);
|
2018-09-20 18:52:51 -07:00
|
|
|
m_defaults.insert("security/IconDownloadFallback", false);
|
2018-04-04 17:39:26 +02:00
|
|
|
m_defaults.insert("security/resettouchid", false);
|
|
|
|
m_defaults.insert("security/resettouchidtimeout", 30);
|
|
|
|
m_defaults.insert("security/resettouchidscreenlock", true);
|
2014-05-18 01:33:22 +02:00
|
|
|
m_defaults.insert("GUI/Language", "system");
|
2018-04-10 08:27:23 +03:00
|
|
|
m_defaults.insert("GUI/HideToolbar", false);
|
2019-01-16 18:04:32 +02:00
|
|
|
m_defaults.insert("GUI/MovableToolbar", false);
|
|
|
|
m_defaults.insert("GUI/ToolButtonStyle", Qt::ToolButtonIconOnly);
|
2014-11-02 10:15:44 +01:00
|
|
|
m_defaults.insert("GUI/ShowTrayIcon", false);
|
2017-12-27 16:46:56 +01:00
|
|
|
m_defaults.insert("GUI/DarkTrayIcon", false);
|
2014-11-02 10:15:44 +01:00
|
|
|
m_defaults.insert("GUI/MinimizeToTray", false);
|
2015-06-18 15:23:41 +02:00
|
|
|
m_defaults.insert("GUI/MinimizeOnClose", false);
|
2018-01-16 13:20:45 +01:00
|
|
|
m_defaults.insert("GUI/HideUsernames", false);
|
|
|
|
m_defaults.insert("GUI/HidePasswords", true);
|
2018-05-13 23:21:43 +02:00
|
|
|
m_defaults.insert("GUI/AdvancedSettings", false);
|
2019-06-28 22:10:47 -04:00
|
|
|
m_defaults.insert("GUI/MonospaceNotes", false);
|
2011-12-25 19:17:40 +01:00
|
|
|
}
|
|
|
|
|
2012-05-31 14:51:44 +02:00
|
|
|
Config* Config::instance()
|
2011-12-25 19:17:40 +01:00
|
|
|
{
|
2012-05-31 14:51:44 +02:00
|
|
|
if (!m_instance) {
|
2012-06-14 22:55:25 +02:00
|
|
|
m_instance = new Config(qApp);
|
2011-12-25 19:17:40 +01:00
|
|
|
}
|
|
|
|
|
2012-05-31 14:51:44 +02:00
|
|
|
return m_instance;
|
2011-12-25 19:17:40 +01:00
|
|
|
}
|
2012-06-14 22:55:25 +02:00
|
|
|
|
2014-05-15 18:26:01 +02:00
|
|
|
void Config::createConfigFromFile(const QString& file)
|
2013-03-29 20:35:54 +01:00
|
|
|
{
|
|
|
|
Q_ASSERT(!m_instance);
|
|
|
|
m_instance = new Config(file, qApp);
|
|
|
|
}
|
|
|
|
|
2012-06-14 22:55:25 +02:00
|
|
|
void Config::createTempFileInstance()
|
|
|
|
{
|
|
|
|
Q_ASSERT(!m_instance);
|
2018-02-04 13:18:59 +01:00
|
|
|
auto* tmpFile = new QTemporaryFile();
|
2012-07-03 12:39:03 +02:00
|
|
|
bool openResult = tmpFile->open();
|
|
|
|
Q_ASSERT(openResult);
|
|
|
|
Q_UNUSED(openResult);
|
2012-10-28 18:07:23 +01:00
|
|
|
m_instance = new Config(tmpFile->fileName(), qApp);
|
|
|
|
tmpFile->setParent(m_instance);
|
2012-06-14 22:55:25 +02:00
|
|
|
}
|