Merge pull request #2443 from brainplot/code-cleanup

Code cleanup and performance improvements - Part 2
This commit is contained in:
Jonathan White 2018-11-28 20:03:33 -05:00 committed by GitHub
commit c66f293f1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
193 changed files with 2450 additions and 2138 deletions

View File

@ -672,7 +672,7 @@ bool AutoType::checkSyntax(const QString& string)
QString shortcutKeys = "[\\^\\%~\\+@]"; QString shortcutKeys = "[\\^\\%~\\+@]";
// a normal string not in parentheses // a normal string not in parentheses
QString fixedStrings = "[^\\^\\%~\\+@\\{\\}]*"; QString fixedStrings = "[^\\^\\%~\\+@\\{\\}]*";
// clang-format off
QRegularExpression autoTypeSyntax( QRegularExpression autoTypeSyntax(
"^(?:" + shortcutKeys + "|" + fixedStrings + "|\\{(?:" + normalCommands + "|" + specialLiterals + "|" "^(?:" + shortcutKeys + "|" + fixedStrings + "|\\{(?:" + normalCommands + "|" + specialLiterals + "|"
+ functionKeys + functionKeys
@ -688,6 +688,7 @@ bool AutoType::checkSyntax(const QString& string)
+ customAttributes + customAttributes
+ "\\})*$", + "\\})*$",
QRegularExpression::CaseInsensitiveOption); QRegularExpression::CaseInsensitiveOption);
// clang-format on
QRegularExpressionMatch match = autoTypeSyntax.match(string); QRegularExpressionMatch match = autoTypeSyntax.match(string);
return match.hasMatch(); return match.hasMatch();
} }
@ -755,9 +756,10 @@ bool AutoType::verifyAutoTypeSyntax(const QString& sequence)
} }
} else if (AutoType::checkHighRepetition(sequence)) { } else if (AutoType::checkHighRepetition(sequence)) {
QMessageBox::StandardButton reply; QMessageBox::StandardButton reply;
reply = reply = QMessageBox::question(nullptr,
QMessageBox::question(nullptr, tr("Auto-Type"), tr("This Auto-Type command contains arguments which are " tr("Auto-Type"),
"repeated very often. Do you really want to proceed?")); tr("This Auto-Type command contains arguments which are "
"repeated very often. Do you really want to proceed?"));
if (reply == QMessageBox::No) { if (reply == QMessageBox::No) {
return false; return false;

View File

@ -67,10 +67,13 @@ AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent)
QLabel* descriptionLabel = new QLabel(tr("Select entry to Auto-Type:"), this); QLabel* descriptionLabel = new QLabel(tr("Select entry to Auto-Type:"), this);
layout->addWidget(descriptionLabel); layout->addWidget(descriptionLabel);
// clang-format off
connect(m_view, SIGNAL(activated(QModelIndex)), SLOT(emitMatchActivated(QModelIndex))); connect(m_view, SIGNAL(activated(QModelIndex)), SLOT(emitMatchActivated(QModelIndex)));
connect(m_view, SIGNAL(clicked(QModelIndex)), SLOT(emitMatchActivated(QModelIndex))); connect(m_view, SIGNAL(clicked(QModelIndex)), SLOT(emitMatchActivated(QModelIndex)));
connect(m_view->model(), SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(matchRemoved())); connect(m_view->model(), SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(matchRemoved()));
connect(m_view, SIGNAL(rejected()), SLOT(reject())); connect(m_view, SIGNAL(rejected()), SLOT(reject()));
// clang-format on
layout->addWidget(m_view); layout->addWidget(m_view);
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel, Qt::Horizontal, this); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel, Qt::Horizontal, this);

View File

@ -23,7 +23,7 @@
const QChar WildcardMatcher::Wildcard = '*'; const QChar WildcardMatcher::Wildcard = '*';
const Qt::CaseSensitivity WildcardMatcher::Sensitivity = Qt::CaseInsensitive; const Qt::CaseSensitivity WildcardMatcher::Sensitivity = Qt::CaseInsensitive;
WildcardMatcher::WildcardMatcher(QString text) WildcardMatcher::WildcardMatcher(QString text)
: m_text(std::move(text)) : m_text(std::move(text))
{ {
} }

View File

@ -23,7 +23,7 @@
class WildcardMatcher class WildcardMatcher
{ {
public: public:
explicit WildcardMatcher(QString text); explicit WildcardMatcher(QString text);
bool match(const QString& pattern); bool match(const QString& pattern);
static const QChar Wildcard; static const QChar Wildcard;

View File

@ -211,8 +211,7 @@ int AutoTypePlatformX11::platformEventFilter(void* event)
xcb_key_press_event_t* keyPressEvent = static_cast<xcb_key_press_event_t*>(event); xcb_key_press_event_t* keyPressEvent = static_cast<xcb_key_press_event_t*>(event);
if (keyPressEvent->detail == m_currentGlobalKeycode if (keyPressEvent->detail == m_currentGlobalKeycode
&& (keyPressEvent->state & m_modifierMask) == m_currentGlobalNativeModifiers && (keyPressEvent->state & m_modifierMask) == m_currentGlobalNativeModifiers
&& (!QApplication::activeWindow() || QApplication::activeWindow()->isMinimized()) && (!QApplication::activeWindow() || QApplication::activeWindow()->isMinimized()) && m_loaded) {
&& m_loaded) {
if (type == XCB_KEY_PRESS) { if (type == XCB_KEY_PRESS) {
emit globalShortcutTriggered(); emit globalShortcutTriggered();
} }

View File

@ -1,25 +1,26 @@
/* /*
* Copyright (C) 2013 Francois Ferrand * Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "BrowserAccessControlDialog.h" #include "BrowserAccessControlDialog.h"
#include "core/Entry.h"
#include "ui_BrowserAccessControlDialog.h" #include "ui_BrowserAccessControlDialog.h"
#include "core/Entry.h"
BrowserAccessControlDialog::BrowserAccessControlDialog(QWidget* parent) BrowserAccessControlDialog::BrowserAccessControlDialog(QWidget* parent)
: QDialog(parent) : QDialog(parent)
, m_ui(new Ui::BrowserAccessControlDialog()) , m_ui(new Ui::BrowserAccessControlDialog())
@ -38,8 +39,8 @@ BrowserAccessControlDialog::~BrowserAccessControlDialog()
void BrowserAccessControlDialog::setUrl(const QString& url) void BrowserAccessControlDialog::setUrl(const QString& url)
{ {
m_ui->label->setText(QString(tr("%1 has requested access to passwords for the following item(s).\n" m_ui->label->setText(QString(tr("%1 has requested access to passwords for the following item(s).\n"
"Please select whether you want to allow access.")) "Please select whether you want to allow access."))
.arg(QUrl(url).host())); .arg(QUrl(url).host()));
} }
void BrowserAccessControlDialog::setItems(const QList<Entry*>& items) void BrowserAccessControlDialog::setItems(const QList<Entry*>& items)

View File

@ -1,20 +1,20 @@
/* /*
* Copyright (C) 2013 Francois Ferrand * Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef BROWSERACCESSCONTROLDIALOG_H #ifndef BROWSERACCESSCONTROLDIALOG_H
#define BROWSERACCESSCONTROLDIALOG_H #define BROWSERACCESSCONTROLDIALOG_H

View File

@ -1,20 +1,20 @@
/* /*
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com> * Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "BrowserAction.h" #include "BrowserAction.h"
#include "BrowserSettings.h" #include "BrowserSettings.h"
@ -167,9 +167,10 @@ QJsonObject BrowserAction::handleAssociate(const QJsonObject& json, const QStrin
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
if (key.compare(m_clientPublicKey, Qt::CaseSensitive) == 0) { if (key.compare(m_clientPublicKey, Qt::CaseSensitive) == 0) {
// Check for identification key. If it's not found, ensure backwards compatibility and use the current public key // Check for identification key. If it's not found, ensure backwards compatibility and use the current public
// key
const QString idKey = decrypted.value("idKey").toString(); const QString idKey = decrypted.value("idKey").toString();
const QString id = m_browserService.storeKey((idKey.isEmpty() ? key: idKey)); const QString id = m_browserService.storeKey((idKey.isEmpty() ? key : idKey));
if (id.isEmpty()) { if (id.isEmpty()) {
return getErrorReply(action, ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED); return getErrorReply(action, ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED);
} }

View File

@ -1,20 +1,20 @@
/* /*
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com> * Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef BROWSERACTION_H #ifndef BROWSERACTION_H
#define BROWSERACTION_H #define BROWSERACTION_H

View File

@ -1,20 +1,20 @@
/* /*
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com> * Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "BrowserClients.h" #include "BrowserClients.h"
#include <QJsonParseError> #include <QJsonParseError>

View File

@ -1,20 +1,20 @@
/* /*
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com> * Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef BROWSERCLIENTS_H #ifndef BROWSERCLIENTS_H
#define BROWSERCLIENTS_H #define BROWSERCLIENTS_H

View File

@ -1,20 +1,20 @@
/* /*
* Copyright (C) 2013 Francois Ferrand * Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "BrowserEntryConfig.h" #include "BrowserEntryConfig.h"
#include "core/Entry.h" #include "core/Entry.h"

View File

@ -1,20 +1,20 @@
/* /*
* Copyright (C) 2013 Francois Ferrand * Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef BROWSERENTRYCONFIG_H #ifndef BROWSERENTRYCONFIG_H
#define BROWSERENTRYCONFIG_H #define BROWSERENTRYCONFIG_H

View File

@ -1,20 +1,20 @@
/* /*
* Copyright (C) 2013 Francois Ferrand * Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "BrowserEntrySaveDialog.h" #include "BrowserEntrySaveDialog.h"
#include "ui_BrowserEntrySaveDialog.h" #include "ui_BrowserEntrySaveDialog.h"
@ -34,7 +34,7 @@ BrowserEntrySaveDialog::BrowserEntrySaveDialog(QWidget* parent)
m_ui->itemsList->setSelectionMode(QAbstractItemView::SingleSelection); m_ui->itemsList->setSelectionMode(QAbstractItemView::SingleSelection);
m_ui->label->setText(QString(tr("You have multiple databases open.\n" m_ui->label->setText(QString(tr("You have multiple databases open.\n"
"Please select the correct database for saving credentials."))); "Please select the correct database for saving credentials.")));
} }
BrowserEntrySaveDialog::~BrowserEntrySaveDialog() BrowserEntrySaveDialog::~BrowserEntrySaveDialog()
@ -58,7 +58,7 @@ int BrowserEntrySaveDialog::setItems(QList<DatabaseWidget*>& databaseWidgets, Da
} else { } else {
item->setText(QString("%1 (%2)").arg(databaseName, databaseFileName)); item->setText(QString("%1 (%2)").arg(databaseName, databaseFileName));
} }
if (currentWidget == dbWidget) { if (currentWidget == dbWidget) {
activeIndex = counter; activeIndex = counter;
} }
@ -76,7 +76,7 @@ int BrowserEntrySaveDialog::setItems(QList<DatabaseWidget*>& databaseWidgets, Da
return databaseWidgets.length(); return databaseWidgets.length();
} }
QList<QListWidgetItem*> BrowserEntrySaveDialog::getSelected() const QList<QListWidgetItem*> BrowserEntrySaveDialog::getSelected() const
{ {
return m_ui->itemsList->selectedItems(); return m_ui->itemsList->selectedItems();
} }

View File

@ -1,29 +1,30 @@
/* /*
* Copyright (C) 2013 Francois Ferrand * Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef BROWSERENTRYSAVEDIALOG_H #ifndef BROWSERENTRYSAVEDIALOG_H
#define BROWSERENTRYSAVEDIALOG_H #define BROWSERENTRYSAVEDIALOG_H
#include <QDialog>
#include <QScopedPointer>
#include <QListWidgetItem>
#include "gui/DatabaseTabWidget.h" #include "gui/DatabaseTabWidget.h"
#include <QDialog>
#include <QListWidgetItem>
#include <QScopedPointer>
class Entry; class Entry;
namespace Ui namespace Ui
@ -40,7 +41,7 @@ public:
~BrowserEntrySaveDialog() override; ~BrowserEntrySaveDialog() override;
int setItems(QList<DatabaseWidget*>& databaseWidgets, DatabaseWidget* currentWidget) const; int setItems(QList<DatabaseWidget*>& databaseWidgets, DatabaseWidget* currentWidget) const;
QList<QListWidgetItem *> getSelected() const; QList<QListWidgetItem*> getSelected() const;
private: private:
QScopedPointer<Ui::BrowserEntrySaveDialog> m_ui; QScopedPointer<Ui::BrowserEntrySaveDialog> m_ui;

View File

@ -1,27 +1,28 @@
/* /*
* Copyright (C) 2013 Francois Ferrand * Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com> * Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "BrowserOptionDialog.h" #include "BrowserOptionDialog.h"
#include "ui_BrowserOptionDialog.h"
#include "BrowserSettings.h" #include "BrowserSettings.h"
#include "config-keepassx.h" #include "config-keepassx.h"
#include "core/FilePath.h" #include "core/FilePath.h"
#include "ui_BrowserOptionDialog.h"
#include <QFileDialog> #include <QFileDialog>
@ -32,18 +33,24 @@ BrowserOptionDialog::BrowserOptionDialog(QWidget* parent)
m_ui->setupUi(this); m_ui->setupUi(this);
m_ui->extensionLabel->setOpenExternalLinks(true); m_ui->extensionLabel->setOpenExternalLinks(true);
m_ui->extensionLabel->setText(tr("KeePassXC-Browser is needed for the browser integration to work. <br />Download it for %1 and %2.").arg( m_ui->extensionLabel->setText(
"<a href=\"https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/\">Firefox</a>", tr("KeePassXC-Browser is needed for the browser integration to work. <br />Download it for %1 and %2.")
"<a href=\"https://chrome.google.com/webstore/detail/keepassxc-browser/oboonakemofpalcgghocfoadofidjkkk\">Google Chrome / Chromium / Vivaldi</a>")); .arg("<a href=\"https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/\">Firefox</a>",
"<a "
"href=\"https://chrome.google.com/webstore/detail/keepassxc-browser/"
"oboonakemofpalcgghocfoadofidjkkk\">Google Chrome / Chromium / Vivaldi</a>"));
m_ui->scriptWarningWidget->setVisible(false); m_ui->scriptWarningWidget->setVisible(false);
m_ui->scriptWarningWidget->setAutoHideTimeout(-1); m_ui->scriptWarningWidget->setAutoHideTimeout(-1);
m_ui->scriptWarningWidget->showMessage(tr("<b>Warning</b>, the keepassxc-proxy application was not found!" m_ui->scriptWarningWidget->showMessage(
"<br />Please check the KeePassXC installation directory or confirm the custom path in advanced options." tr("<b>Warning</b>, the keepassxc-proxy application was not found!"
"<br />Browser integration WILL NOT WORK without the proxy application." "<br />Please check the KeePassXC installation directory or confirm the custom path in advanced options."
"<br />Expected Path: "), MessageWidget::Warning); "<br />Browser integration WILL NOT WORK without the proxy application."
"<br />Expected Path: "),
MessageWidget::Warning);
m_ui->warningWidget->showMessage(tr("<b>Warning:</b> The following options can be dangerous!"), MessageWidget::Warning); m_ui->warningWidget->showMessage(tr("<b>Warning:</b> The following options can be dangerous!"),
MessageWidget::Warning);
m_ui->warningWidget->setCloseButtonVisible(false); m_ui->warningWidget->setCloseButtonVisible(false);
m_ui->warningWidget->setAutoHideTimeout(-1); m_ui->warningWidget->setAutoHideTimeout(-1);

View File

@ -1,27 +1,27 @@
/* /*
* Copyright (C) 2013 Francois Ferrand * Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com> * Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef BROWSEROPTIONDIALOG_H #ifndef BROWSEROPTIONDIALOG_H
#define BROWSEROPTIONDIALOG_H #define BROWSEROPTIONDIALOG_H
#include <QScopedPointer>
#include <QPointer> #include <QPointer>
#include <QScopedPointer>
#include <QWidget> #include <QWidget>
namespace Ui namespace Ui

View File

@ -1,32 +1,32 @@
/* /*
* Copyright (C) 2013 Francois Ferrand * Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com> * Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <QJsonArray>
#include <QInputDialog> #include <QInputDialog>
#include <QProgressDialog> #include <QJsonArray>
#include <QMessageBox> #include <QMessageBox>
#include <QProgressDialog>
#include <QUuid> #include <QUuid>
#include "BrowserService.h"
#include "BrowserAccessControlDialog.h" #include "BrowserAccessControlDialog.h"
#include "BrowserEntryConfig.h" #include "BrowserEntryConfig.h"
#include "BrowserEntrySaveDialog.h" #include "BrowserEntrySaveDialog.h"
#include "BrowserService.h"
#include "BrowserSettings.h" #include "BrowserSettings.h"
#include "core/Database.h" #include "core/Database.h"
#include "core/EntrySearcher.h" #include "core/EntrySearcher.h"
@ -54,7 +54,8 @@ BrowserService::BrowserService(DatabaseTabWidget* parent)
// Don't connect the signals when used from DatabaseSettingsWidgetBrowser (parent is nullptr) // Don't connect the signals when used from DatabaseSettingsWidgetBrowser (parent is nullptr)
if (m_dbTabWidget) { if (m_dbTabWidget) {
connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), this, SLOT(databaseLocked(DatabaseWidget*))); connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), this, SLOT(databaseLocked(DatabaseWidget*)));
connect(m_dbTabWidget, SIGNAL(databaseUnlocked(DatabaseWidget*)), this, SLOT(databaseUnlocked(DatabaseWidget*))); connect(
m_dbTabWidget, SIGNAL(databaseUnlocked(DatabaseWidget*)), this, SLOT(databaseUnlocked(DatabaseWidget*)));
connect(m_dbTabWidget, connect(m_dbTabWidget,
SIGNAL(activateDatabaseChanged(DatabaseWidget*)), SIGNAL(activateDatabaseChanged(DatabaseWidget*)),
this, this,
@ -355,7 +356,8 @@ void BrowserService::updateEntry(const QString& id,
return; return;
} }
if (username.compare(login, Qt::CaseSensitive) != 0 || entry->password().compare(password, Qt::CaseSensitive) != 0) { if (username.compare(login, Qt::CaseSensitive) != 0
|| entry->password().compare(password, Qt::CaseSensitive) != 0) {
int dialogResult = QMessageBox::No; int dialogResult = QMessageBox::No;
if (!browserSettings()->alwaysAllowUpdate()) { if (!browserSettings()->alwaysAllowUpdate()) {
QMessageBox msgBox; QMessageBox msgBox;
@ -393,16 +395,17 @@ QList<Entry*> BrowserService::searchEntries(QSharedPointer<Database> db, const Q
QString entryScheme = entryQUrl.scheme(); QString entryScheme = entryQUrl.scheme();
QUrl qUrl(url); QUrl qUrl(url);
// Ignore entry if port or scheme defined in the URL doesn't match // Ignore entry if port or scheme defined in the URL doesn't match
if ((entryQUrl.port() > 0 && entryQUrl.port() != qUrl.port()) || if ((entryQUrl.port() > 0 && entryQUrl.port() != qUrl.port())
(browserSettings()->matchUrlScheme() && !entryScheme.isEmpty() && entryScheme.compare(qUrl.scheme()) != 0)) { || (browserSettings()->matchUrlScheme() && !entryScheme.isEmpty()
&& entryScheme.compare(qUrl.scheme()) != 0)) {
continue; continue;
} }
// Filter to match hostname in URL field // Filter to match hostname in URL field
if ((!entryUrl.isEmpty() && hostname.contains(entryUrl)) if ((!entryUrl.isEmpty() && hostname.contains(entryUrl))
|| (matchUrlScheme(entryUrl) && hostname.endsWith(entryQUrl.host()))) { || (matchUrlScheme(entryUrl) && hostname.endsWith(entryQUrl.host()))) {
entries.append(entry); entries.append(entry);
} }
} }
@ -420,7 +423,8 @@ QList<Entry*> BrowserService::searchEntries(const QString& url, const StringPair
if (const auto& db = dbWidget->database()) { if (const auto& db = dbWidget->database()) {
// Check if database is connected with KeePassXC-Browser // Check if database is connected with KeePassXC-Browser
for (const StringPair& keyPair : keyList) { for (const StringPair& keyPair : keyList) {
QString key = db->metadata()->customData()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + keyPair.first); QString key =
db->metadata()->customData()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + keyPair.first);
if (!key.isEmpty() && keyPair.second == key) { if (!key.isEmpty() && keyPair.second == key) {
databases << db; databases << db;
} }
@ -484,16 +488,22 @@ void BrowserService::convertAttributesToCustomData(QSharedPointer<Database> curr
progress.reset(); progress.reset();
if (counter > 0) { if (counter > 0) {
QMessageBox::information(nullptr, tr("KeePassXC: Converted KeePassHTTP attributes"), QMessageBox::information(nullptr,
tr("KeePassXC: Converted KeePassHTTP attributes"),
tr("Successfully converted attributes from %1 entry(s).\n" tr("Successfully converted attributes from %1 entry(s).\n"
"Moved %2 keys to custom data.", "").arg(counter).arg(keyCounter), "Moved %2 keys to custom data.",
"")
.arg(counter)
.arg(keyCounter),
QMessageBox::Ok); QMessageBox::Ok);
} else if (counter == 0 && keyCounter > 0) { } else if (counter == 0 && keyCounter > 0) {
QMessageBox::information(nullptr, tr("KeePassXC: Converted KeePassHTTP attributes"), QMessageBox::information(nullptr,
tr("KeePassXC: Converted KeePassHTTP attributes"),
tr("Successfully moved %n keys to custom data.", "", keyCounter), tr("Successfully moved %n keys to custom data.", "", keyCounter),
QMessageBox::Ok); QMessageBox::Ok);
} else { } else {
QMessageBox::information(nullptr, tr("KeePassXC: No entry with KeePassHTTP attributes found!"), QMessageBox::information(nullptr,
tr("KeePassXC: No entry with KeePassHTTP attributes found!"),
tr("The active database does not contain an entry with KeePassHTTP attributes."), tr("The active database does not contain an entry with KeePassHTTP attributes."),
QMessageBox::Ok); QMessageBox::Ok);
} }
@ -539,9 +549,14 @@ QList<Entry*> BrowserService::sortEntries(QList<Entry*>& pwEntries, const QStrin
// Sort same priority entries by Title or UserName // Sort same priority entries by Title or UserName
auto entries = priorities.values(i); auto entries = priorities.values(i);
std::sort(entries.begin(), entries.end(), [&field](Entry* left, Entry* right) { std::sort(entries.begin(), entries.end(), [&field](Entry* left, Entry* right) {
return (QString::localeAwareCompare(left->attributes()->value(field), right->attributes()->value(field)) < 0) || return (QString::localeAwareCompare(left->attributes()->value(field), right->attributes()->value(field))
((QString::localeAwareCompare(left->attributes()->value(field), right->attributes()->value(field)) == 0) && < 0)
(QString::localeAwareCompare(left->attributes()->value("UserName"), right->attributes()->value("UserName")) < 0)); || ((QString::localeAwareCompare(left->attributes()->value(field),
right->attributes()->value(field))
== 0)
&& (QString::localeAwareCompare(left->attributes()->value("UserName"),
right->attributes()->value("UserName"))
< 0));
}); });
results << entries; results << entries;
if (browserSettings()->bestMatchOnly() && !pwEntries.isEmpty()) { if (browserSettings()->bestMatchOnly() && !pwEntries.isEmpty()) {
@ -843,7 +858,8 @@ int BrowserService::moveKeysToCustomData(Entry* entry, QSharedPointer<Database>
// Add key to database custom data // Add key to database custom data
if (db && !db->metadata()->customData()->contains(QLatin1String(ASSOCIATE_KEY_PREFIX) + publicKey)) { if (db && !db->metadata()->customData()->contains(QLatin1String(ASSOCIATE_KEY_PREFIX) + publicKey)) {
db->metadata()->customData()->set(QLatin1String(ASSOCIATE_KEY_PREFIX) + publicKey, entry->attributes()->value(key)); db->metadata()->customData()->set(QLatin1String(ASSOCIATE_KEY_PREFIX) + publicKey,
entry->attributes()->value(key));
++keyCounter; ++keyCounter;
} }
} }
@ -879,7 +895,6 @@ bool BrowserService::checkLegacySettings()
"Do you want to upgrade the settings to the latest standard?\n" "Do you want to upgrade the settings to the latest standard?\n"
"This is necessary to maintain compatibility with the browser plugin."), "This is necessary to maintain compatibility with the browser plugin."),
QMessageBox::Yes | QMessageBox::No); QMessageBox::Yes | QMessageBox::No);
return dialogResult == QMessageBox::Yes; return dialogResult == QMessageBox::Yes;
} }

View File

@ -1,21 +1,21 @@
/* /*
* Copyright (C) 2013 Francois Ferrand * Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com> * Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option) * the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License. * version 3 of the License.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef BROWSERSERVICE_H #ifndef BROWSERSERVICE_H
#define BROWSERSERVICE_H #define BROWSERSERVICE_H

View File

@ -1,21 +1,21 @@
/* /*
* Copyright (C) 2013 Francois Ferrand * Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com> * Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "BrowserSettings.h" #include "BrowserSettings.h"
#include "core/Config.h" #include "core/Config.h"
@ -192,7 +192,7 @@ bool BrowserSettings::chromeSupport()
void BrowserSettings::setChromeSupport(bool enabled) void BrowserSettings::setChromeSupport(bool enabled)
{ {
m_hostInstaller.installBrowser( m_hostInstaller.installBrowser(
HostInstaller::SupportedBrowsers::CHROME, enabled, supportBrowserProxy(), customProxyLocation()); HostInstaller::SupportedBrowsers::CHROME, enabled, supportBrowserProxy(), customProxyLocation());
} }
bool BrowserSettings::chromiumSupport() bool BrowserSettings::chromiumSupport()
@ -203,7 +203,7 @@ bool BrowserSettings::chromiumSupport()
void BrowserSettings::setChromiumSupport(bool enabled) void BrowserSettings::setChromiumSupport(bool enabled)
{ {
m_hostInstaller.installBrowser( m_hostInstaller.installBrowser(
HostInstaller::SupportedBrowsers::CHROMIUM, enabled, supportBrowserProxy(), customProxyLocation()); HostInstaller::SupportedBrowsers::CHROMIUM, enabled, supportBrowserProxy(), customProxyLocation());
} }
bool BrowserSettings::firefoxSupport() bool BrowserSettings::firefoxSupport()
@ -214,7 +214,7 @@ bool BrowserSettings::firefoxSupport()
void BrowserSettings::setFirefoxSupport(bool enabled) void BrowserSettings::setFirefoxSupport(bool enabled)
{ {
m_hostInstaller.installBrowser( m_hostInstaller.installBrowser(
HostInstaller::SupportedBrowsers::FIREFOX, enabled, supportBrowserProxy(), customProxyLocation()); HostInstaller::SupportedBrowsers::FIREFOX, enabled, supportBrowserProxy(), customProxyLocation());
} }
bool BrowserSettings::vivaldiSupport() bool BrowserSettings::vivaldiSupport()
@ -225,7 +225,7 @@ bool BrowserSettings::vivaldiSupport()
void BrowserSettings::setVivaldiSupport(bool enabled) void BrowserSettings::setVivaldiSupport(bool enabled)
{ {
m_hostInstaller.installBrowser( m_hostInstaller.installBrowser(
HostInstaller::SupportedBrowsers::VIVALDI, enabled, supportBrowserProxy(), customProxyLocation()); HostInstaller::SupportedBrowsers::VIVALDI, enabled, supportBrowserProxy(), customProxyLocation());
} }
bool BrowserSettings::torBrowserSupport() bool BrowserSettings::torBrowserSupport()

View File

@ -1,21 +1,21 @@
/* /*
* Copyright (C) 2013 Francois Ferrand * Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com> * Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef BROWSERSETTINGS_H #ifndef BROWSERSETTINGS_H
#define BROWSERSETTINGS_H #define BROWSERSETTINGS_H
@ -72,7 +72,7 @@ public:
void setVivaldiSupport(bool enabled); void setVivaldiSupport(bool enabled);
bool torBrowserSupport(); bool torBrowserSupport();
void setTorBrowserSupport(bool enabled); void setTorBrowserSupport(bool enabled);
bool passwordUseNumbers(); bool passwordUseNumbers();
void setPasswordUseNumbers(bool useNumbers); void setPasswordUseNumbers(bool useNumbers);
bool passwordUseLowercase(); bool passwordUseLowercase();

View File

@ -1,20 +1,20 @@
/* /*
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com> * Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "HostInstaller.h" #include "HostInstaller.h"
#include "config-keepassx.h" #include "config-keepassx.h"
@ -46,8 +46,10 @@ HostInstaller::HostInstaller()
, TARGET_DIR_VIVALDI("/.config/vivaldi/NativeMessagingHosts") , TARGET_DIR_VIVALDI("/.config/vivaldi/NativeMessagingHosts")
, TARGET_DIR_TOR_BROWSER("/.tor-browser/app/Browser/TorBrowser/Data/Browser/.mozilla/native-messaging-hosts") , TARGET_DIR_TOR_BROWSER("/.tor-browser/app/Browser/TorBrowser/Data/Browser/.mozilla/native-messaging-hosts")
#elif defined(Q_OS_WIN) #elif defined(Q_OS_WIN)
// clang-format off
, TARGET_DIR_CHROME("HKEY_CURRENT_USER\\Software\\Google\\Chrome\\NativeMessagingHosts\\org.keepassxc.keepassxc_browser") , TARGET_DIR_CHROME("HKEY_CURRENT_USER\\Software\\Google\\Chrome\\NativeMessagingHosts\\org.keepassxc.keepassxc_browser")
, TARGET_DIR_CHROMIUM("HKEY_CURRENT_USER\\Software\\Chromium\\NativeMessagingHosts\\org.keepassxc.keepassxc_browser") , TARGET_DIR_CHROMIUM("HKEY_CURRENT_USER\\Software\\Chromium\\NativeMessagingHosts\\org.keepassxc.keepassxc_browser")
// clang-format on
, TARGET_DIR_FIREFOX("HKEY_CURRENT_USER\\Software\\Mozilla\\NativeMessagingHosts\\org.keepassxc.keepassxc_browser") , TARGET_DIR_FIREFOX("HKEY_CURRENT_USER\\Software\\Mozilla\\NativeMessagingHosts\\org.keepassxc.keepassxc_browser")
, TARGET_DIR_VIVALDI(TARGET_DIR_CHROME) , TARGET_DIR_VIVALDI(TARGET_DIR_CHROME)
, TARGET_DIR_TOR_BROWSER(TARGET_DIR_FIREFOX) , TARGET_DIR_TOR_BROWSER(TARGET_DIR_FIREFOX)
@ -163,14 +165,14 @@ QString HostInstaller::getTargetPath(SupportedBrowsers browser) const
case SupportedBrowsers::VIVALDI: case SupportedBrowsers::VIVALDI:
return TARGET_DIR_VIVALDI; return TARGET_DIR_VIVALDI;
case SupportedBrowsers::TOR_BROWSER: case SupportedBrowsers::TOR_BROWSER:
return TARGET_DIR_TOR_BROWSER; return TARGET_DIR_TOR_BROWSER;
default: default:
return QString(); return QString();
} }
} }
/** /**
* Returns the browser name * Returns the browser name
* Needed for Windows to separate Chromium- or Firefox-based scripts * Needed for Windows to separate Chromium- or Firefox-based scripts
* *
* @param browser Selected browser * @param browser Selected browser
@ -188,7 +190,7 @@ QString HostInstaller::getBrowserName(SupportedBrowsers browser) const
case SupportedBrowsers::VIVALDI: case SupportedBrowsers::VIVALDI:
return "vivaldi"; return "vivaldi";
case SupportedBrowsers::TOR_BROWSER: case SupportedBrowsers::TOR_BROWSER:
return "tor-browser"; return "tor-browser";
default: default:
return QString(); return QString();
} }

View File

@ -1,20 +1,20 @@
/* /*
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com> * Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef HOSTINSTALLER_H #ifndef HOSTINSTALLER_H
#define HOSTINSTALLER_H #define HOSTINSTALLER_H

View File

@ -1,20 +1,20 @@
/* /*
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com> * Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "NativeMessagingBase.h" #include "NativeMessagingBase.h"
#include <QStandardPaths> #include <QStandardPaths>
@ -138,7 +138,8 @@ QString NativeMessagingBase::getLocalServerPath() const
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) #if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
// Use XDG_RUNTIME_DIR instead of /tmp if it's available // Use XDG_RUNTIME_DIR instead of /tmp if it's available
QString path = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation); QString path = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
return path.isEmpty() ? QStandardPaths::writableLocation(QStandardPaths::TempLocation) + serverPath : path + serverPath; return path.isEmpty() ? QStandardPaths::writableLocation(QStandardPaths::TempLocation) + serverPath
: path + serverPath;
#else // Q_OS_MACOS, Q_OS_WIN and others #else // Q_OS_MACOS, Q_OS_WIN and others
return QStandardPaths::writableLocation(QStandardPaths::TempLocation) + serverPath; return QStandardPaths::writableLocation(QStandardPaths::TempLocation) + serverPath;
#endif #endif

View File

@ -1,20 +1,20 @@
/* /*
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com> * Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef NATIVEMESSAGINGBASE_H #ifndef NATIVEMESSAGINGBASE_H
#define NATIVEMESSAGINGBASE_H #define NATIVEMESSAGINGBASE_H
@ -33,11 +33,11 @@
#include <unistd.h> #include <unistd.h>
#ifndef Q_OS_WIN #ifndef Q_OS_WIN
#include <sys/socket.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h>
#endif #endif
static const int NATIVE_MSG_MAX_LENGTH = 1024*1024; static const int NATIVE_MSG_MAX_LENGTH = 1024 * 1024;
class NativeMessagingBase : public QObject class NativeMessagingBase : public QObject
{ {

View File

@ -1,20 +1,20 @@
/* /*
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com> * Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "NativeMessagingHost.h" #include "NativeMessagingHost.h"
#include "BrowserSettings.h" #include "BrowserSettings.h"
@ -65,8 +65,8 @@ void NativeMessagingHost::run()
// Update KeePassXC/keepassxc-proxy binary paths to Native Messaging scripts // Update KeePassXC/keepassxc-proxy binary paths to Native Messaging scripts
if (browserSettings()->updateBinaryPath()) { if (browserSettings()->updateBinaryPath()) {
browserSettings()->updateBinaryPaths(browserSettings()->useCustomProxy() ? browserSettings()->customProxyLocation() browserSettings()->updateBinaryPaths(
: ""); browserSettings()->useCustomProxy() ? browserSettings()->customProxyLocation() : "");
} }
m_running.store(true); m_running.store(true);

View File

@ -1,20 +1,20 @@
/* /*
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com> * Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef NATIVEMESSAGINGHOST_H #ifndef NATIVEMESSAGINGHOST_H
#define NATIVEMESSAGINGHOST_H #define NATIVEMESSAGINGHOST_H

View File

@ -1,19 +1,19 @@
/* /*
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "Variant.h" #include "Variant.h"

View File

@ -1,19 +1,19 @@
/* /*
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef VARIANT_H #ifndef VARIANT_H
#define VARIANT_H #define VARIANT_H

View File

@ -51,7 +51,8 @@ int Add::execute(const QStringList& arguments)
parser.addOption(Command::QuietOption); parser.addOption(Command::QuietOption);
parser.addOption(Command::KeyFileOption); parser.addOption(Command::KeyFileOption);
QCommandLineOption username(QStringList() << "u" << "username", QCommandLineOption username(QStringList() << "u"
<< "username",
QObject::tr("Username for the entry."), QObject::tr("Username for the entry."),
QObject::tr("username")); QObject::tr("username"));
parser.addOption(username); parser.addOption(username);
@ -59,15 +60,18 @@ int Add::execute(const QStringList& arguments)
QCommandLineOption url(QStringList() << "url", QObject::tr("URL for the entry."), QObject::tr("URL")); QCommandLineOption url(QStringList() << "url", QObject::tr("URL for the entry."), QObject::tr("URL"));
parser.addOption(url); parser.addOption(url);
QCommandLineOption prompt(QStringList() << "p" << "password-prompt", QCommandLineOption prompt(QStringList() << "p"
<< "password-prompt",
QObject::tr("Prompt for the entry's password.")); QObject::tr("Prompt for the entry's password."));
parser.addOption(prompt); parser.addOption(prompt);
QCommandLineOption generate(QStringList() << "g" << "generate", QCommandLineOption generate(QStringList() << "g"
<< "generate",
QObject::tr("Generate a password for the entry.")); QObject::tr("Generate a password for the entry."));
parser.addOption(generate); parser.addOption(generate);
QCommandLineOption length(QStringList() << "l" << "password-length", QCommandLineOption length(QStringList() << "l"
<< "password-length",
QObject::tr("Length for the generated password."), QObject::tr("Length for the generated password."),
QObject::tr("length")); QObject::tr("length"));
parser.addOption(length); parser.addOption(length);

View File

@ -50,12 +50,13 @@ int Clip::execute(const QStringList& arguments)
parser.addOption(Command::QuietOption); parser.addOption(Command::QuietOption);
parser.addOption(Command::KeyFileOption); parser.addOption(Command::KeyFileOption);
QCommandLineOption totp(QStringList() << "t" << "totp", QCommandLineOption totp(QStringList() << "t"
<< "totp",
QObject::tr("Copy the current TOTP to the clipboard.")); QObject::tr("Copy the current TOTP to the clipboard."));
parser.addOption(totp); parser.addOption(totp);
parser.addPositionalArgument("entry", QObject::tr("Path of the entry to clip.", "clip = copy to clipboard")); parser.addPositionalArgument("entry", QObject::tr("Path of the entry to clip.", "clip = copy to clipboard"));
parser.addPositionalArgument("timeout", parser.addPositionalArgument(
QObject::tr("Timeout in seconds before clearing the clipboard."), "[timeout]"); "timeout", QObject::tr("Timeout in seconds before clearing the clipboard."), "[timeout]");
parser.addHelpOption(); parser.addHelpOption();
parser.process(arguments); parser.process(arguments);

View File

@ -43,11 +43,13 @@ int Diceware::execute(const QStringList& arguments)
QCommandLineParser parser; QCommandLineParser parser;
parser.setApplicationDescription(description); parser.setApplicationDescription(description);
QCommandLineOption words(QStringList() << "W" << "words", QCommandLineOption words(QStringList() << "W"
<< "words",
QObject::tr("Word count for the diceware passphrase."), QObject::tr("Word count for the diceware passphrase."),
QObject::tr("count", "CLI parameter")); QObject::tr("count", "CLI parameter"));
parser.addOption(words); parser.addOption(words);
QCommandLineOption wordlistFile(QStringList() << "w" << "word-list", QCommandLineOption wordlistFile(QStringList() << "w"
<< "word-list",
QObject::tr("Wordlist for the diceware generator.\n[Default: EFF English]"), QObject::tr("Wordlist for the diceware generator.\n[Default: EFF English]"),
QObject::tr("path")); QObject::tr("path"));
parser.addOption(wordlistFile); parser.addOption(wordlistFile);

View File

@ -51,7 +51,8 @@ int Edit::execute(const QStringList& arguments)
parser.addOption(Command::QuietOption); parser.addOption(Command::QuietOption);
parser.addOption(Command::KeyFileOption); parser.addOption(Command::KeyFileOption);
QCommandLineOption username(QStringList() << "u" << "username", QCommandLineOption username(QStringList() << "u"
<< "username",
QObject::tr("Username for the entry."), QObject::tr("Username for the entry."),
QObject::tr("username")); QObject::tr("username"));
parser.addOption(username); parser.addOption(username);
@ -59,20 +60,24 @@ int Edit::execute(const QStringList& arguments)
QCommandLineOption url(QStringList() << "url", QObject::tr("URL for the entry."), QObject::tr("URL")); QCommandLineOption url(QStringList() << "url", QObject::tr("URL for the entry."), QObject::tr("URL"));
parser.addOption(url); parser.addOption(url);
QCommandLineOption title(QStringList() << "t" << "title", QCommandLineOption title(QStringList() << "t"
<< "title",
QObject::tr("Title for the entry."), QObject::tr("Title for the entry."),
QObject::tr("title")); QObject::tr("title"));
parser.addOption(title); parser.addOption(title);
QCommandLineOption prompt(QStringList() << "p" << "password-prompt", QCommandLineOption prompt(QStringList() << "p"
<< "password-prompt",
QObject::tr("Prompt for the entry's password.")); QObject::tr("Prompt for the entry's password."));
parser.addOption(prompt); parser.addOption(prompt);
QCommandLineOption generate(QStringList() << "g" << "generate", QCommandLineOption generate(QStringList() << "g"
<< "generate",
QObject::tr("Generate a password for the entry.")); QObject::tr("Generate a password for the entry."));
parser.addOption(generate); parser.addOption(generate);
QCommandLineOption length(QStringList() << "l" << "password-length", QCommandLineOption length(QStringList() << "l"
<< "password-length",
QObject::tr("Length for the generated password."), QObject::tr("Length for the generated password."),
QObject::tr("length")); QObject::tr("length"));
parser.addOption(length); parser.addOption(length);
@ -111,8 +116,7 @@ int Edit::execute(const QStringList& arguments)
} }
if (parser.value("username").isEmpty() && parser.value("url").isEmpty() && parser.value("title").isEmpty() if (parser.value("username").isEmpty() && parser.value("url").isEmpty() && parser.value("title").isEmpty()
&& !parser.isSet(prompt) && !parser.isSet(prompt) && !parser.isSet(generate)) {
&& !parser.isSet(generate)) {
err << QObject::tr("Not changing any field for entry %1.").arg(entryPath) << endl; err << QObject::tr("Not changing any field for entry %1.").arg(entryPath) << endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} }

View File

@ -51,9 +51,11 @@ static void estimate(const char* pwd, bool advanced)
int len = static_cast<int>(strlen(pwd)); int len = static_cast<int>(strlen(pwd));
if (!advanced) { if (!advanced) {
e = ZxcvbnMatch(pwd, nullptr, nullptr); e = ZxcvbnMatch(pwd, nullptr, nullptr);
// clang-format off
out << QObject::tr("Length %1").arg(len, 0) << '\t' out << QObject::tr("Length %1").arg(len, 0) << '\t'
<< QObject::tr("Entropy %1").arg(e, 0, 'f', 3) << '\t' << QObject::tr("Entropy %1").arg(e, 0, 'f', 3) << '\t'
<< QObject::tr("Log10 %1").arg(e * 0.301029996, 0, 'f', 3) << endl; << QObject::tr("Log10 %1").arg(e * 0.301029996, 0, 'f', 3) << endl;
// clang-format on
} else { } else {
int ChkLen = 0; int ChkLen = 0;
ZxcMatch_t *info, *p; ZxcMatch_t *info, *p;
@ -63,10 +65,12 @@ static void estimate(const char* pwd, bool advanced)
m += p->Entrpy; m += p->Entrpy;
} }
m = e - m; m = e - m;
// clang-format off
out << QObject::tr("Length %1").arg(len) << '\t' out << QObject::tr("Length %1").arg(len) << '\t'
<< QObject::tr("Entropy %1").arg(e, 0, 'f', 3) << '\t' << QObject::tr("Entropy %1").arg(e, 0, 'f', 3) << '\t'
<< QObject::tr("Log10 %1").arg(e * 0.301029996, 0, 'f', 3) << "\n " << QObject::tr("Log10 %1").arg(e * 0.301029996, 0, 'f', 3) << "\n "
<< QObject::tr("Multi-word extra bits %1").arg(m, 0, 'f', 1) << endl; << QObject::tr("Multi-word extra bits %1").arg(m, 0, 'f', 1) << endl;
// clang-format on
p = info; p = info;
ChkLen = 0; ChkLen = 0;
while (p) { while (p) {
@ -132,9 +136,10 @@ static void estimate(const char* pwd, bool advanced)
break; break;
} }
ChkLen += p->Length; ChkLen += p->Length;
// clang-format off
out << QObject::tr("Length %1").arg(p->Length) << '\t' out << QObject::tr("Length %1").arg(p->Length) << '\t'
<< QObject::tr("Entropy %1 (%2)").arg(p->Entrpy, 6, 'f', 3).arg(p->Entrpy * 0.301029996, 0, 'f', 2) << '\t'; << QObject::tr("Entropy %1 (%2)").arg(p->Entrpy, 6, 'f', 3).arg(p->Entrpy * 0.301029996, 0, 'f', 2) << '\t';
// clang-format on
for (n = 0; n < p->Length; ++n, ++pwd) { for (n = 0; n < p->Length; ++n, ++pwd) {
out << *pwd; out << *pwd;
} }
@ -143,7 +148,8 @@ static void estimate(const char* pwd, bool advanced)
} }
ZxcvbnFreeInfo(info); ZxcvbnFreeInfo(info);
if (ChkLen != len) { if (ChkLen != len) {
out << QObject::tr("*** Password length (%1) != sum of length of parts (%2) ***").arg(len).arg(ChkLen) << endl; out << QObject::tr("*** Password length (%1) != sum of length of parts (%2) ***").arg(len).arg(ChkLen)
<< endl;
} }
} }
} }
@ -156,7 +162,8 @@ int Estimate::execute(const QStringList& arguments)
QCommandLineParser parser; QCommandLineParser parser;
parser.setApplicationDescription(description); parser.setApplicationDescription(description);
parser.addPositionalArgument("password", QObject::tr("Password for which to estimate the entropy."), "[password]"); parser.addPositionalArgument("password", QObject::tr("Password for which to estimate the entropy."), "[password]");
QCommandLineOption advancedOption(QStringList() << "a" << "advanced", QCommandLineOption advancedOption(QStringList() << "a"
<< "advanced",
QObject::tr("Perform advanced analysis on the password.")); QObject::tr("Perform advanced analysis on the password."));
parser.addOption(advancedOption); parser.addOption(advancedOption);
parser.addHelpOption(); parser.addHelpOption();

View File

@ -84,7 +84,8 @@ int Extract::execute(const QStringList& arguments)
if (fileKey->type() != FileKey::Hashed) { if (fileKey->type() != FileKey::Hashed) {
err << QObject::tr("WARNING: You are using a legacy key file format which may become\n" err << QObject::tr("WARNING: You are using a legacy key file format which may become\n"
"unsupported in the future.\n\n" "unsupported in the future.\n\n"
"Please consider generating a new key file.") << endl; "Please consider generating a new key file.")
<< endl;
} }
// LCOV_EXCL_STOP // LCOV_EXCL_STOP

View File

@ -43,26 +43,33 @@ int Generate::execute(const QStringList& arguments)
QCommandLineParser parser; QCommandLineParser parser;
parser.setApplicationDescription(description); parser.setApplicationDescription(description);
QCommandLineOption len(QStringList() << "L" << "length", QCommandLineOption len(QStringList() << "L"
<< "length",
QObject::tr("Length of the generated password"), QObject::tr("Length of the generated password"),
QObject::tr("length")); QObject::tr("length"));
parser.addOption(len); parser.addOption(len);
QCommandLineOption lower(QStringList() << "l" << "lower", QCommandLineOption lower(QStringList() << "l"
<< "lower",
QObject::tr("Use lowercase characters")); QObject::tr("Use lowercase characters"));
parser.addOption(lower); parser.addOption(lower);
QCommandLineOption upper(QStringList() << "u" << "upper", QCommandLineOption upper(QStringList() << "u"
<< "upper",
QObject::tr("Use uppercase characters")); QObject::tr("Use uppercase characters"));
parser.addOption(upper); parser.addOption(upper);
QCommandLineOption numeric(QStringList() << "n" << "numeric", QCommandLineOption numeric(QStringList() << "n"
<< "numeric",
QObject::tr("Use numbers.")); QObject::tr("Use numbers."));
parser.addOption(numeric); parser.addOption(numeric);
QCommandLineOption special(QStringList() << "s" << "special", QCommandLineOption special(QStringList() << "s"
<< "special",
QObject::tr("Use special characters")); QObject::tr("Use special characters"));
parser.addOption(special); parser.addOption(special);
QCommandLineOption extended(QStringList() << "e" << "extended", QCommandLineOption extended(QStringList() << "e"
<< "extended",
QObject::tr("Use extended ASCII")); QObject::tr("Use extended ASCII"));
parser.addOption(extended); parser.addOption(extended);
QCommandLineOption exclude(QStringList() << "x" << "exclude", QCommandLineOption exclude(QStringList() << "x"
<< "exclude",
QObject::tr("Exclude character set"), QObject::tr("Exclude character set"),
QObject::tr("chars")); QObject::tr("chars"));
parser.addOption(exclude); parser.addOption(exclude);

View File

@ -49,7 +49,8 @@ int List::execute(const QStringList& arguments)
parser.addOption(Command::QuietOption); parser.addOption(Command::QuietOption);
parser.addOption(Command::KeyFileOption); parser.addOption(Command::KeyFileOption);
QCommandLineOption recursiveOption(QStringList() << "R" << "recursive", QCommandLineOption recursiveOption(QStringList() << "R"
<< "recursive",
QObject::tr("Recursively list the elements of the group.")); QObject::tr("Recursively list the elements of the group."));
parser.addOption(recursiveOption); parser.addOption(recursiveOption);
parser.addHelpOption(); parser.addHelpOption();

View File

@ -47,12 +47,14 @@ int Merge::execute(const QStringList& arguments)
parser.addPositionalArgument("database2", QObject::tr("Path of the database to merge from.")); parser.addPositionalArgument("database2", QObject::tr("Path of the database to merge from."));
parser.addOption(Command::QuietOption); parser.addOption(Command::QuietOption);
QCommandLineOption samePasswordOption(QStringList() << "s" << "same-credentials", QCommandLineOption samePasswordOption(QStringList() << "s"
<< "same-credentials",
QObject::tr("Use the same credentials for both database files.")); QObject::tr("Use the same credentials for both database files."));
parser.addOption(samePasswordOption); parser.addOption(samePasswordOption);
parser.addOption(Command::KeyFileOption); parser.addOption(Command::KeyFileOption);
QCommandLineOption keyFileFromOption(QStringList() << "f" << "key-file-from", QCommandLineOption keyFileFromOption(QStringList() << "f"
<< "key-file-from",
QObject::tr("Key file of the database to merge from."), QObject::tr("Key file of the database to merge from."),
QObject::tr("path")); QObject::tr("path"));
parser.addOption(keyFileFromOption); parser.addOption(keyFileFromOption);

View File

@ -48,11 +48,13 @@ int Show::execute(const QStringList& arguments)
parser.addPositionalArgument("database", QObject::tr("Path of the database.")); parser.addPositionalArgument("database", QObject::tr("Path of the database."));
parser.addOption(Command::QuietOption); parser.addOption(Command::QuietOption);
parser.addOption(Command::KeyFileOption); parser.addOption(Command::KeyFileOption);
QCommandLineOption totp(QStringList() << "t" << "totp", QCommandLineOption totp(QStringList() << "t"
<< "totp",
QObject::tr("Show the entry's current TOTP.")); QObject::tr("Show the entry's current TOTP."));
parser.addOption(totp); parser.addOption(totp);
QCommandLineOption attributes( QCommandLineOption attributes(
QStringList() << "a" << "attributes", QStringList() << "a"
<< "attributes",
QObject::tr( QObject::tr(
"Names of the attributes to show. " "Names of the attributes to show. "
"This option can be specified more than once, with each attribute shown one-per-line in the given order. " "This option can be specified more than once, with each attribute shown one-per-line in the given order. "

View File

@ -28,20 +28,20 @@
namespace Utils namespace Utils
{ {
/** /**
* STDOUT file handle for the CLI. * STDOUT file handle for the CLI.
*/ */
FILE* STDOUT = stdout; FILE* STDOUT = stdout;
/** /**
* STDERR file handle for the CLI. * STDERR file handle for the CLI.
*/ */
FILE* STDERR = stderr; FILE* STDERR = stderr;
/** /**
* STDIN file handle for the CLI. * STDIN file handle for the CLI.
*/ */
FILE* STDIN = stdin; FILE* STDIN = stdin;
/** /**
* DEVNULL file handle for the CLI. * DEVNULL file handle for the CLI.
@ -56,48 +56,47 @@ FILE* DEVNULL = fopen("/dev/null", "w");
void setStdinEcho(bool enable = true) void setStdinEcho(bool enable = true)
{ {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE); HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode; DWORD mode;
GetConsoleMode(hIn, &mode); GetConsoleMode(hIn, &mode);
if (enable) { if (enable) {
mode |= ENABLE_ECHO_INPUT; mode |= ENABLE_ECHO_INPUT;
} else { } else {
mode &= ~ENABLE_ECHO_INPUT; mode &= ~ENABLE_ECHO_INPUT;
} }
SetConsoleMode(hIn, mode);
SetConsoleMode(hIn, mode);
#else #else
struct termios t; struct termios t;
tcgetattr(STDIN_FILENO, &t); tcgetattr(STDIN_FILENO, &t);
if (enable) { if (enable) {
t.c_lflag |= ECHO; t.c_lflag |= ECHO;
} else { } else {
t.c_lflag &= ~ECHO; t.c_lflag &= ~ECHO;
}
tcsetattr(STDIN_FILENO, TCSANOW, &t);
#endif
} }
tcsetattr(STDIN_FILENO, TCSANOW, &t); namespace Test
#endif {
} QStringList nextPasswords = {};
namespace Test /**
{ * Set the next password returned by \link getPassword() instead of reading it from STDIN.
QStringList nextPasswords = {}; * Multiple calls to this method will fill a queue of passwords.
* This function is intended for testing purposes.
/** *
* Set the next password returned by \link getPassword() instead of reading it from STDIN. * @param password password to return next
* Multiple calls to this method will fill a queue of passwords. */
* This function is intended for testing purposes. void setNextPassword(const QString& password)
* {
* @param password password to return next nextPasswords.append(password);
*/ }
void setNextPassword(const QString& password) } // namespace Test
{
nextPasswords.append(password);
}
} // namespace Test
/** /**
* Read a user password from STDIN or return a password previously * Read a user password from STDIN or return a password previously
@ -109,74 +108,74 @@ QString getPassword(FILE* outputDescriptor)
{ {
TextStream out(outputDescriptor, QIODevice::WriteOnly); TextStream out(outputDescriptor, QIODevice::WriteOnly);
// return preset password if one is set // return preset password if one is set
if (!Test::nextPasswords.isEmpty()) { if (!Test::nextPasswords.isEmpty()) {
auto password = Test::nextPasswords.takeFirst(); auto password = Test::nextPasswords.takeFirst();
// simulate user entering newline // simulate user entering newline
out << endl;
return password;
}
TextStream in(STDIN, QIODevice::ReadOnly);
setStdinEcho(false);
QString line = in.readLine();
setStdinEcho(true);
out << endl; out << endl;
return password;
return line;
} }
TextStream in(STDIN, QIODevice::ReadOnly); /**
* A valid and running event loop is needed to use the global QClipboard,
* so we need to use this from the CLI.
*/
int clipText(const QString& text)
{
TextStream err(Utils::STDERR);
setStdinEcho(false); QString programName = "";
QString line = in.readLine(); QStringList arguments;
setStdinEcho(true);
out << endl;
return line;
}
/**
* A valid and running event loop is needed to use the global QClipboard,
* so we need to use this from the CLI.
*/
int clipText(const QString& text)
{
TextStream err(Utils::STDERR);
QString programName = "";
QStringList arguments;
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
programName = "xclip"; programName = "xclip";
arguments << "-i" arguments << "-i"
<< "-selection" << "-selection"
<< "clipboard"; << "clipboard";
#endif #endif
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
programName = "pbcopy"; programName = "pbcopy";
#endif #endif
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
programName = "clip"; programName = "clip";
#endif #endif
if (programName.isEmpty()) { if (programName.isEmpty()) {
err << QObject::tr("No program defined for clipboard manipulation"); err << QObject::tr("No program defined for clipboard manipulation");
err.flush(); err.flush();
return EXIT_FAILURE; return EXIT_FAILURE;
}
auto* clipProcess = new QProcess(nullptr);
clipProcess->start(programName, arguments);
clipProcess->waitForStarted();
if (clipProcess->state() != QProcess::Running) {
err << QObject::tr("Unable to start program %1").arg(programName);
err.flush();
return EXIT_FAILURE;
}
if (clipProcess->write(text.toLatin1()) == -1) {
qDebug("Unable to write to process : %s", qPrintable(clipProcess->errorString()));
}
clipProcess->waitForBytesWritten();
clipProcess->closeWriteChannel();
clipProcess->waitForFinished();
return clipProcess->exitCode();
} }
auto* clipProcess = new QProcess(nullptr); } // namespace Utils
clipProcess->start(programName, arguments);
clipProcess->waitForStarted();
if (clipProcess->state() != QProcess::Running) {
err << QObject::tr("Unable to start program %1").arg(programName);
err.flush();
return EXIT_FAILURE;
}
if (clipProcess->write(text.toLatin1()) == -1) {
qDebug("Unable to write to process : %s", qPrintable(clipProcess->errorString()));
}
clipProcess->waitForBytesWritten();
clipProcess->closeWriteChannel();
clipProcess->waitForFinished();
return clipProcess->exitCode();
}
} // namespace Utils

View File

@ -18,24 +18,24 @@
#ifndef KEEPASSXC_UTILS_H #ifndef KEEPASSXC_UTILS_H
#define KEEPASSXC_UTILS_H #define KEEPASSXC_UTILS_H
#include <QtCore/qglobal.h>
#include "cli/TextStream.h" #include "cli/TextStream.h"
#include <QtCore/qglobal.h>
namespace Utils namespace Utils
{ {
extern FILE* STDOUT; extern FILE* STDOUT;
extern FILE* STDERR; extern FILE* STDERR;
extern FILE* STDIN; extern FILE* STDIN;
extern FILE* DEVNULL; extern FILE* DEVNULL;
void setStdinEcho(bool enable); void setStdinEcho(bool enable);
QString getPassword(FILE* outputDescriptor = STDOUT); QString getPassword(FILE* outputDescriptor = STDOUT);
int clipText(const QString& text); int clipText(const QString& text);
namespace Test namespace Test
{ {
void setNextPassword(const QString& password); void setNextPassword(const QString& password);
} }
}; }; // namespace Utils
#endif // KEEPASSXC_UTILS_H #endif // KEEPASSXC_UTILS_H

View File

@ -13,7 +13,7 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef KEEPASSXC_ASYNCTASK_HPP #ifndef KEEPASSXC_ASYNCTASK_HPP
#define KEEPASSXC_ASYNCTASK_HPP #define KEEPASSXC_ASYNCTASK_HPP

View File

@ -26,201 +26,201 @@
namespace Bootstrap namespace Bootstrap
{ {
/** /**
* When QNetworkAccessManager is instantiated it regularly starts polling * When QNetworkAccessManager is instantiated it regularly starts polling
* all network interfaces to see if anything changes and if so, what. This * all network interfaces to see if anything changes and if so, what. This
* creates a latency spike every 10 seconds on Mac OS 10.12+ and Windows 7 >= * creates a latency spike every 10 seconds on Mac OS 10.12+ and Windows 7 >=
* when on a wifi connection. * when on a wifi connection.
* So here we disable it for lack of better measure. * So here we disable it for lack of better measure.
* This will also cause this message: QObject::startTimer: Timers cannot * This will also cause this message: QObject::startTimer: Timers cannot
* have negative intervals * have negative intervals
* For more info see: * For more info see:
* - https://bugreports.qt.io/browse/QTBUG-40332 * - https://bugreports.qt.io/browse/QTBUG-40332
* - https://bugreports.qt.io/browse/QTBUG-46015 * - https://bugreports.qt.io/browse/QTBUG-46015
*/ */
static inline void applyEarlyQNetworkAccessManagerWorkaround() static inline void applyEarlyQNetworkAccessManagerWorkaround()
{ {
qputenv("QT_BEARER_POLL_TIMEOUT", QByteArray::number(-1)); qputenv("QT_BEARER_POLL_TIMEOUT", QByteArray::number(-1));
}
/**
* Perform early application bootstrapping such as setting up search paths,
* configuration OS security properties, and loading translators.
* A QApplication object has to be instantiated before calling this function.
*/
void bootstrapApplication()
{
#ifdef QT_NO_DEBUG
disableCoreDumps();
#endif
setupSearchPaths();
applyEarlyQNetworkAccessManagerWorkaround();
Translator::installTranslators();
#ifdef Q_OS_MACOS
// Don't show menu icons on OSX
QApplication::setAttribute(Qt::AA_DontShowIconsInMenus);
#endif
}
/**
* Restore the main window's state after launch
*
* @param mainWindow the main window whose state to restore
*/
void restoreMainWindowState(MainWindow& mainWindow)
{
// start minimized if configured
if (config()->get("GUI/MinimizeOnStartup").toBool()) {
mainWindow.showMinimized();
} else {
mainWindow.bringToFront();
} }
if (config()->get("OpenPreviousDatabasesOnStartup").toBool()) { /**
const QStringList fileNames = config()->get("LastOpenedDatabases").toStringList(); * Perform early application bootstrapping such as setting up search paths,
for (const QString& filename : fileNames) { * configuration OS security properties, and loading translators.
if (!filename.isEmpty() && QFile::exists(filename)) { * A QApplication object has to be instantiated before calling this function.
mainWindow.openDatabase(filename); */
void bootstrapApplication()
{
#ifdef QT_NO_DEBUG
disableCoreDumps();
#endif
setupSearchPaths();
applyEarlyQNetworkAccessManagerWorkaround();
Translator::installTranslators();
#ifdef Q_OS_MACOS
// Don't show menu icons on OSX
QApplication::setAttribute(Qt::AA_DontShowIconsInMenus);
#endif
}
/**
* Restore the main window's state after launch
*
* @param mainWindow the main window whose state to restore
*/
void restoreMainWindowState(MainWindow& mainWindow)
{
// start minimized if configured
if (config()->get("GUI/MinimizeOnStartup").toBool()) {
mainWindow.showMinimized();
} else {
mainWindow.bringToFront();
}
if (config()->get("OpenPreviousDatabasesOnStartup").toBool()) {
const QStringList fileNames = config()->get("LastOpenedDatabases").toStringList();
for (const QString& filename : fileNames) {
if (!filename.isEmpty() && QFile::exists(filename)) {
mainWindow.openDatabase(filename);
}
} }
} }
} }
}
// LCOV_EXCL_START // LCOV_EXCL_START
void disableCoreDumps() void disableCoreDumps()
{ {
// default to true // default to true
// there is no point in printing a warning if this is not implemented on the platform // there is no point in printing a warning if this is not implemented on the platform
bool success = true; bool success = true;
#if defined(HAVE_RLIMIT_CORE) #if defined(HAVE_RLIMIT_CORE)
struct rlimit limit; struct rlimit limit;
limit.rlim_cur = 0; limit.rlim_cur = 0;
limit.rlim_max = 0; limit.rlim_max = 0;
success = success && (setrlimit(RLIMIT_CORE, &limit) == 0); success = success && (setrlimit(RLIMIT_CORE, &limit) == 0);
#endif #endif
#if defined(HAVE_PR_SET_DUMPABLE) #if defined(HAVE_PR_SET_DUMPABLE)
success = success && (prctl(PR_SET_DUMPABLE, 0) == 0); success = success && (prctl(PR_SET_DUMPABLE, 0) == 0);
#endif #endif
// Mac OS X // Mac OS X
#ifdef HAVE_PT_DENY_ATTACH #ifdef HAVE_PT_DENY_ATTACH
success = success && (ptrace(PT_DENY_ATTACH, 0, 0, 0) == 0); success = success && (ptrace(PT_DENY_ATTACH, 0, 0, 0) == 0);
#endif #endif
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
success = success && createWindowsDACL(); success = success && createWindowsDACL();
#endif #endif
if (!success) { if (!success) {
qWarning("Unable to disable core dumps."); qWarning("Unable to disable core dumps.");
}
} }
}
// //
// This function grants the user associated with the process token minimal access rights and // This function grants the user associated with the process token minimal access rights and
// denies everything else on Windows. This includes PROCESS_QUERY_INFORMATION and // denies everything else on Windows. This includes PROCESS_QUERY_INFORMATION and
// PROCESS_VM_READ access rights that are required for MiniDumpWriteDump() or ReadProcessMemory(). // PROCESS_VM_READ access rights that are required for MiniDumpWriteDump() or ReadProcessMemory().
// We do this using a discretionary access control list (DACL). Effectively this prevents // We do this using a discretionary access control list (DACL). Effectively this prevents
// crash dumps and disallows other processes from accessing our memory. This works as long // crash dumps and disallows other processes from accessing our memory. This works as long
// as you do not have admin privileges, since then you are able to grant yourself the // as you do not have admin privileges, since then you are able to grant yourself the
// SeDebugPrivilege or SeTakeOwnershipPrivilege and circumvent the DACL. // SeDebugPrivilege or SeTakeOwnershipPrivilege and circumvent the DACL.
// //
bool createWindowsDACL() bool createWindowsDACL()
{ {
bool bSuccess = false; bool bSuccess = false;
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
// Process token and user // Process token and user
HANDLE hToken = nullptr; HANDLE hToken = nullptr;
PTOKEN_USER pTokenUser = nullptr; PTOKEN_USER pTokenUser = nullptr;
DWORD cbBufferSize = 0; DWORD cbBufferSize = 0;
// Access control list // Access control list
PACL pACL = nullptr; PACL pACL = nullptr;
DWORD cbACL = 0; DWORD cbACL = 0;
// Open the access token associated with the calling process // Open the access token associated with the calling process
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
goto Cleanup; goto Cleanup;
} }
// Retrieve the token information in a TOKEN_USER structure // Retrieve the token information in a TOKEN_USER structure
GetTokenInformation(hToken, TokenUser, nullptr, 0, &cbBufferSize); GetTokenInformation(hToken, TokenUser, nullptr, 0, &cbBufferSize);
pTokenUser = static_cast<PTOKEN_USER>(HeapAlloc(GetProcessHeap(), 0, cbBufferSize)); pTokenUser = static_cast<PTOKEN_USER>(HeapAlloc(GetProcessHeap(), 0, cbBufferSize));
if (pTokenUser == nullptr) { if (pTokenUser == nullptr) {
goto Cleanup; goto Cleanup;
} }
if (!GetTokenInformation(hToken, TokenUser, pTokenUser, cbBufferSize, &cbBufferSize)) { if (!GetTokenInformation(hToken, TokenUser, pTokenUser, cbBufferSize, &cbBufferSize)) {
goto Cleanup; goto Cleanup;
} }
if (!IsValidSid(pTokenUser->User.Sid)) { if (!IsValidSid(pTokenUser->User.Sid)) {
goto Cleanup; goto Cleanup;
} }
// Calculate the amount of memory that must be allocated for the DACL // Calculate the amount of memory that must be allocated for the DACL
cbACL = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid); cbACL = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid);
// Create and initialize an ACL // Create and initialize an ACL
pACL = static_cast<PACL>(HeapAlloc(GetProcessHeap(), 0, cbACL)); pACL = static_cast<PACL>(HeapAlloc(GetProcessHeap(), 0, cbACL));
if (pACL == nullptr) { if (pACL == nullptr) {
goto Cleanup; goto Cleanup;
} }
if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) { if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) {
goto Cleanup; goto Cleanup;
} }
// Add allowed access control entries, everything else is denied // Add allowed access control entries, everything else is denied
if (!AddAccessAllowedAce( if (!AddAccessAllowedAce(
pACL, pACL,
ACL_REVISION, ACL_REVISION,
SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE, // same as protected process SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE, // same as protected process
pTokenUser->User.Sid // pointer to the trustee's SID pTokenUser->User.Sid // pointer to the trustee's SID
)) { )) {
goto Cleanup; goto Cleanup;
} }
// Set discretionary access control list // Set discretionary access control list
bSuccess = ERROR_SUCCESS bSuccess = ERROR_SUCCESS
== SetSecurityInfo(GetCurrentProcess(), // object handle == SetSecurityInfo(GetCurrentProcess(), // object handle
SE_KERNEL_OBJECT, // type of object SE_KERNEL_OBJECT, // type of object
DACL_SECURITY_INFORMATION, // change only the objects DACL DACL_SECURITY_INFORMATION, // change only the objects DACL
nullptr, nullptr,
nullptr, // do not change owner or group nullptr, // do not change owner or group
pACL, // DACL specified pACL, // DACL specified
nullptr // do not change SACL nullptr // do not change SACL
); );
Cleanup: Cleanup:
if (pACL != nullptr) { if (pACL != nullptr) {
HeapFree(GetProcessHeap(), 0, pACL); HeapFree(GetProcessHeap(), 0, pACL);
} }
if (pTokenUser != nullptr) { if (pTokenUser != nullptr) {
HeapFree(GetProcessHeap(), 0, pTokenUser); HeapFree(GetProcessHeap(), 0, pTokenUser);
} }
if (hToken != nullptr) { if (hToken != nullptr) {
CloseHandle(hToken); CloseHandle(hToken);
} }
#endif #endif
return bSuccess; return bSuccess;
} }
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
void setupSearchPaths() void setupSearchPaths()
{ {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
// Make sure Windows doesn't load DLLs from the current working directory // Make sure Windows doesn't load DLLs from the current working directory
SetDllDirectoryA(""); SetDllDirectoryA("");
SetSearchPathMode(BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE); SetSearchPathMode(BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE);
#endif #endif
} }
} // namespace Bootstrap } // namespace Bootstrap

View File

@ -15,7 +15,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef KEEPASSXC_BOOTSTRAP_H #ifndef KEEPASSXC_BOOTSTRAP_H
#define KEEPASSXC_BOOTSTRAP_H #define KEEPASSXC_BOOTSTRAP_H
@ -23,12 +22,11 @@
namespace Bootstrap namespace Bootstrap
{ {
void bootstrapApplication(); void bootstrapApplication();
void restoreMainWindowState(MainWindow& mainWindow); void restoreMainWindowState(MainWindow& mainWindow);
void disableCoreDumps(); void disableCoreDumps();
bool createWindowsDACL(); bool createWindowsDACL();
void setupSearchPaths(); void setupSearchPaths();
}; }; // namespace Bootstrap
#endif // KEEPASSXC_BOOTSTRAP_H
#endif //KEEPASSXC_BOOTSTRAP_H

View File

@ -84,7 +84,7 @@ void Config::upgrade()
{ {
for (const auto& setting : deprecationMap.keys()) { for (const auto& setting : deprecationMap.keys()) {
if (m_settings->contains(setting)) { if (m_settings->contains(setting)) {
if(!deprecationMap.value(setting).isEmpty()) { if (!deprecationMap.value(setting).isEmpty()) {
// Add entry with new name and old entry's value // Add entry with new name and old entry's value
m_settings->setValue(deprecationMap.value(setting), m_settings->value(setting)); m_settings->setValue(deprecationMap.value(setting), m_settings->value(setting));
} }

View File

@ -403,10 +403,11 @@ QString CsvParser::getStatus() const
int CsvParser::getCsvCols() const int CsvParser::getCsvCols() const
{ {
if ((m_table.size() > 0) && (m_table.at(0).size() > 0)) if (!m_table.isEmpty() && !m_table.at(0).isEmpty()) {
return m_table.at(0).size(); return m_table.at(0).size();
else } else {
return 0; return 0;
}
} }
int CsvParser::getCsvRows() const int CsvParser::getCsvRows() const

View File

@ -720,14 +720,15 @@ QSharedPointer<Database> Database::unlockFromStdin(const QString& databaseFilena
QString errorMessage; QString errorMessage;
// LCOV_EXCL_START // LCOV_EXCL_START
if (!fileKey->load(keyFilename, &errorMessage)) { if (!fileKey->load(keyFilename, &errorMessage)) {
err << QObject::tr("Failed to load key file %1: %2").arg(keyFilename, errorMessage)<< endl; err << QObject::tr("Failed to load key file %1: %2").arg(keyFilename, errorMessage) << endl;
return {}; return {};
} }
if (fileKey->type() != FileKey::Hashed) { if (fileKey->type() != FileKey::Hashed) {
err << QObject::tr("WARNING: You are using a legacy key file format which may become\n" err << QObject::tr("WARNING: You are using a legacy key file format which may become\n"
"unsupported in the future.\n\n" "unsupported in the future.\n\n"
"Please consider generating a new key file.") << endl; "Please consider generating a new key file.")
<< endl;
} }
// LCOV_EXCL_STOP // LCOV_EXCL_STOP

View File

@ -657,12 +657,14 @@ Entry* Entry::clone(CloneFlags flags) const
if (flags & CloneUserAsRef) { if (flags & CloneUserAsRef) {
// Build the username reference // Build the username reference
QString username = "{REF:U@I:" + uuidToHex() + "}"; QString username = "{REF:U@I:" + uuidToHex() + "}";
entry->m_attributes->set(EntryAttributes::UserNameKey, username.toUpper(), m_attributes->isProtected(EntryAttributes::UserNameKey)); entry->m_attributes->set(
EntryAttributes::UserNameKey, username.toUpper(), m_attributes->isProtected(EntryAttributes::UserNameKey));
} }
if (flags & ClonePassAsRef) { if (flags & ClonePassAsRef) {
QString password = "{REF:P@I:" + uuidToHex() + "}"; QString password = "{REF:P@I:" + uuidToHex() + "}";
entry->m_attributes->set(EntryAttributes::PasswordKey, password.toUpper(), m_attributes->isProtected(EntryAttributes::PasswordKey)); entry->m_attributes->set(
EntryAttributes::PasswordKey, password.toUpper(), m_attributes->isProtected(EntryAttributes::PasswordKey));
} }
entry->m_autoTypeAssociations->copyDataFrom(m_autoTypeAssociations); entry->m_autoTypeAssociations->copyDataFrom(m_autoTypeAssociations);
@ -1065,7 +1067,8 @@ QString Entry::resolveUrl(const QString& url) const
// Validate the URL // Validate the URL
QUrl tempUrl = QUrl(newUrl); QUrl tempUrl = QUrl(newUrl);
if (tempUrl.isValid() && (tempUrl.scheme() == "http" || tempUrl.scheme() == "https" || tempUrl.scheme() == "file")) { if (tempUrl.isValid()
&& (tempUrl.scheme() == "http" || tempUrl.scheme() == "https" || tempUrl.scheme() == "file")) {
return tempUrl.url(); return tempUrl.url();
} }

View File

@ -36,7 +36,8 @@
class Database; class Database;
class Group; class Group;
namespace Totp { namespace Totp
{
struct Settings; struct Settings;
} }

View File

@ -23,8 +23,8 @@ const QString EntryAttributes::UserNameKey = "UserName";
const QString EntryAttributes::PasswordKey = "Password"; const QString EntryAttributes::PasswordKey = "Password";
const QString EntryAttributes::URLKey = "URL"; const QString EntryAttributes::URLKey = "URL";
const QString EntryAttributes::NotesKey = "Notes"; const QString EntryAttributes::NotesKey = "Notes";
const QStringList EntryAttributes::DefaultAttributes(QStringList() << TitleKey << UserNameKey << PasswordKey << URLKey const QStringList EntryAttributes::DefaultAttributes(QStringList()
<< NotesKey); << TitleKey << UserNameKey << PasswordKey << URLKey << NotesKey);
const QString EntryAttributes::WantedFieldGroupName = "WantedField"; const QString EntryAttributes::WantedFieldGroupName = "WantedField";
const QString EntryAttributes::SearchInGroupName = "SearchIn"; const QString EntryAttributes::SearchInGroupName = "SearchIn";

View File

@ -630,10 +630,12 @@ Entry* Group::findEntryByPathRecursive(const QString& entryPath, const QString&
// Return the first entry that matches the full path OR if there is no leading // Return the first entry that matches the full path OR if there is no leading
// slash, return the first entry title that matches // slash, return the first entry title that matches
for (Entry* entry : entries()) { for (Entry* entry : entries()) {
// clang-format off
if (entryPath == (basePath + entry->title()) if (entryPath == (basePath + entry->title())
|| (!entryPath.startsWith("/") && entry->title() == entryPath)) { || (!entryPath.startsWith("/") && entry->title() == entryPath)) {
return entry; return entry;
} }
// clang-format on
} }
for (Group* group : children()) { for (Group* group : children()) {
@ -654,9 +656,11 @@ Group* Group::findGroupByPath(const QString& groupPath)
if (groupPath.isEmpty()) { if (groupPath.isEmpty()) {
normalizedGroupPath = QString("/"); // root group normalizedGroupPath = QString("/"); // root group
} else { } else {
// clang-format off
normalizedGroupPath = (groupPath.startsWith("/") ? "" : "/") normalizedGroupPath = (groupPath.startsWith("/") ? "" : "/")
+ groupPath + groupPath
+ (groupPath.endsWith("/") ? "" : "/"); + (groupPath.endsWith("/") ? "" : "/");
// clang-format on
} }
return findGroupByPathRecursive(normalizedGroupPath, "/"); return findGroupByPathRecursive(normalizedGroupPath, "/");
} }
@ -894,6 +898,7 @@ void Group::connectDatabaseSignalsRecursive(Database* db)
} }
if (db) { if (db) {
// clang-format off
connect(this, SIGNAL(groupDataChanged(Group*)), db, SIGNAL(groupDataChanged(Group*))); connect(this, SIGNAL(groupDataChanged(Group*)), db, SIGNAL(groupDataChanged(Group*)));
connect(this, SIGNAL(groupAboutToRemove(Group*)), db, SIGNAL(groupAboutToRemove(Group*))); connect(this, SIGNAL(groupAboutToRemove(Group*)), db, SIGNAL(groupAboutToRemove(Group*)));
connect(this, SIGNAL(groupRemoved()), db, SIGNAL(groupRemoved())); connect(this, SIGNAL(groupRemoved()), db, SIGNAL(groupRemoved()));
@ -902,6 +907,7 @@ void Group::connectDatabaseSignalsRecursive(Database* db)
connect(this, SIGNAL(aboutToMove(Group*,Group*,int)), db, SIGNAL(groupAboutToMove(Group*,Group*,int))); connect(this, SIGNAL(aboutToMove(Group*,Group*,int)), db, SIGNAL(groupAboutToMove(Group*,Group*,int)));
connect(this, SIGNAL(groupMoved()), db, SIGNAL(groupMoved())); connect(this, SIGNAL(groupMoved()), db, SIGNAL(groupMoved()));
connect(this, SIGNAL(groupModified()), db, SLOT(markAsModified())); connect(this, SIGNAL(groupModified()), db, SLOT(markAsModified()));
// clang-format on
} }
m_db = db; m_db = db;
@ -983,7 +989,7 @@ QStringList Group::locate(const QString& locateTerm, const QString& currentPath)
for (const Entry* entry : asConst(m_entries)) { for (const Entry* entry : asConst(m_entries)) {
QString entryPath = currentPath + entry->title(); QString entryPath = currentPath + entry->title();
if (entryPath.toLower().contains(locateTerm.toLower())) { if (entryPath.contains(locateTerm, Qt::CaseInsensitive)) {
response << entryPath; response << entryPath;
} }
} }

View File

@ -55,12 +55,13 @@ void InactivityTimer::deactivate()
bool InactivityTimer::eventFilter(QObject* watched, QEvent* event) bool InactivityTimer::eventFilter(QObject* watched, QEvent* event)
{ {
const QEvent::Type type = event->type(); const QEvent::Type type = event->type();
// clang-format off
if ((type >= QEvent::MouseButtonPress && type <= QEvent::KeyRelease) if ((type >= QEvent::MouseButtonPress && type <= QEvent::KeyRelease)
|| (type >= QEvent::HoverEnter && type <= QEvent::HoverMove) || (type >= QEvent::HoverEnter && type <= QEvent::HoverMove)
|| (type == QEvent::Wheel)) { || (type == QEvent::Wheel)) {
m_timer->start(); m_timer->start();
} }
// clang-format on
return QObject::eventFilter(watched, event); return QObject::eventFilter(watched, event);
} }

View File

@ -93,7 +93,8 @@ Merger::ChangeList Merger::mergeGroup(const MergeContext& context)
moveEntry(targetEntry, context.m_targetGroup); moveEntry(targetEntry, context.m_targetGroup);
} else { } else {
// Entry is already present in the database. Update it. // Entry is already present in the database. Update it.
const bool locationChanged = targetEntry->timeInfo().locationChanged() < sourceEntry->timeInfo().locationChanged(); const bool locationChanged =
targetEntry->timeInfo().locationChanged() < sourceEntry->timeInfo().locationChanged();
if (locationChanged && targetEntry->group() != context.m_targetGroup) { if (locationChanged && targetEntry->group() != context.m_targetGroup) {
changes << tr("Relocating %1 [%2]").arg(sourceEntry->title(), sourceEntry->uuidToHex()); changes << tr("Relocating %1 [%2]").arg(sourceEntry->title(), sourceEntry->uuidToHex());
moveEntry(targetEntry, context.m_targetGroup); moveEntry(targetEntry, context.m_targetGroup);
@ -136,7 +137,8 @@ Merger::ChangeList Merger::mergeGroup(const MergeContext& context)
return changes; return changes;
} }
Merger::ChangeList Merger::resolveGroupConflict(const MergeContext& context, const Group* sourceChildGroup, Group* targetChildGroup) Merger::ChangeList
Merger::resolveGroupConflict(const MergeContext& context, const Group* sourceChildGroup, Group* targetChildGroup)
{ {
Q_UNUSED(context); Q_UNUSED(context);
ChangeList changes; ChangeList changes;
@ -261,10 +263,13 @@ void Merger::eraseGroup(Group* group)
database->setDeletedObjects(deletions); database->setDeletedObjects(deletions);
} }
Merger::ChangeList Merger::resolveEntryConflict_Duplicate(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry) Merger::ChangeList
Merger::resolveEntryConflict_Duplicate(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry)
{ {
ChangeList changes; ChangeList changes;
const int comparison = compare(targetEntry->timeInfo().lastModificationTime(), sourceEntry->timeInfo().lastModificationTime(), CompareItemIgnoreMilliseconds); const int comparison = compare(targetEntry->timeInfo().lastModificationTime(),
sourceEntry->timeInfo().lastModificationTime(),
CompareItemIgnoreMilliseconds);
// if one entry is newer, create a clone and add it to the group // if one entry is newer, create a clone and add it to the group
if (comparison < 0) { if (comparison < 0) {
Entry* clonedEntry = sourceEntry->clone(Entry::CloneNewUuid | Entry::CloneIncludeHistory); Entry* clonedEntry = sourceEntry->clone(Entry::CloneNewUuid | Entry::CloneIncludeHistory);
@ -280,11 +285,14 @@ Merger::ChangeList Merger::resolveEntryConflict_Duplicate(const MergeContext& co
return changes; return changes;
} }
Merger::ChangeList Merger::resolveEntryConflict_KeepLocal(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry) Merger::ChangeList
Merger::resolveEntryConflict_KeepLocal(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry)
{ {
Q_UNUSED(context); Q_UNUSED(context);
ChangeList changes; ChangeList changes;
const int comparison = compare(targetEntry->timeInfo().lastModificationTime(), sourceEntry->timeInfo().lastModificationTime(), CompareItemIgnoreMilliseconds); const int comparison = compare(targetEntry->timeInfo().lastModificationTime(),
sourceEntry->timeInfo().lastModificationTime(),
CompareItemIgnoreMilliseconds);
if (comparison < 0) { if (comparison < 0) {
// we need to make our older entry "newer" than the new entry - therefore // we need to make our older entry "newer" than the new entry - therefore
// we just create a new history entry without any changes - this preserves // we just create a new history entry without any changes - this preserves
@ -293,18 +301,21 @@ Merger::ChangeList Merger::resolveEntryConflict_KeepLocal(const MergeContext& co
// this type of merge changes the database timestamp since reapplying the // this type of merge changes the database timestamp since reapplying the
// old entry is an active change of the database! // old entry is an active change of the database!
changes << tr("Reapplying older target entry on top of newer source %1 [%2]") changes << tr("Reapplying older target entry on top of newer source %1 [%2]")
.arg(targetEntry->title(), targetEntry->uuidToHex()); .arg(targetEntry->title(), targetEntry->uuidToHex());
Entry* agedTargetEntry = targetEntry->clone(Entry::CloneNoFlags); Entry* agedTargetEntry = targetEntry->clone(Entry::CloneNoFlags);
targetEntry->addHistoryItem(agedTargetEntry); targetEntry->addHistoryItem(agedTargetEntry);
} }
return changes; return changes;
} }
Merger::ChangeList Merger::resolveEntryConflict_KeepRemote(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry) Merger::ChangeList
Merger::resolveEntryConflict_KeepRemote(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry)
{ {
Q_UNUSED(context); Q_UNUSED(context);
ChangeList changes; ChangeList changes;
const int comparison = compare(targetEntry->timeInfo().lastModificationTime(), sourceEntry->timeInfo().lastModificationTime(), CompareItemIgnoreMilliseconds); const int comparison = compare(targetEntry->timeInfo().lastModificationTime(),
sourceEntry->timeInfo().lastModificationTime(),
CompareItemIgnoreMilliseconds);
if (comparison > 0) { if (comparison > 0) {
// we need to make our older entry "newer" than the new entry - therefore // we need to make our older entry "newer" than the new entry - therefore
// we just create a new history entry without any changes - this preserves // we just create a new history entry without any changes - this preserves
@ -313,7 +324,7 @@ Merger::ChangeList Merger::resolveEntryConflict_KeepRemote(const MergeContext& c
// this type of merge changes the database timestamp since reapplying the // this type of merge changes the database timestamp since reapplying the
// old entry is an active change of the database! // old entry is an active change of the database!
changes << tr("Reapplying older source entry on top of newer target %1 [%2]") changes << tr("Reapplying older source entry on top of newer target %1 [%2]")
.arg(targetEntry->title(), targetEntry->uuidToHex()); .arg(targetEntry->title(), targetEntry->uuidToHex());
targetEntry->beginUpdate(); targetEntry->beginUpdate();
targetEntry->copyDataFrom(sourceEntry); targetEntry->copyDataFrom(sourceEntry);
targetEntry->endUpdate(); targetEntry->endUpdate();
@ -322,13 +333,17 @@ Merger::ChangeList Merger::resolveEntryConflict_KeepRemote(const MergeContext& c
return changes; return changes;
} }
Merger::ChangeList Merger::resolveEntryConflict_MergeHistories(const MergeContext& context,
Merger::ChangeList Merger::resolveEntryConflict_MergeHistories(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry, Group::MergeMode mergeMethod) const Entry* sourceEntry,
Entry* targetEntry,
Group::MergeMode mergeMethod)
{ {
Q_UNUSED(context); Q_UNUSED(context);
ChangeList changes; ChangeList changes;
const int comparison = compare(targetEntry->timeInfo().lastModificationTime(), sourceEntry->timeInfo().lastModificationTime(), CompareItemIgnoreMilliseconds); const int comparison = compare(targetEntry->timeInfo().lastModificationTime(),
sourceEntry->timeInfo().lastModificationTime(),
CompareItemIgnoreMilliseconds);
if (comparison < 0) { if (comparison < 0) {
Group* currentGroup = targetEntry->group(); Group* currentGroup = targetEntry->group();
Entry* clonedEntry = sourceEntry->clone(Entry::CloneIncludeHistory); Entry* clonedEntry = sourceEntry->clone(Entry::CloneIncludeHistory);
@ -347,14 +362,15 @@ Merger::ChangeList Merger::resolveEntryConflict_MergeHistories(const MergeContex
qPrintable(targetEntry->group()->name())); qPrintable(targetEntry->group()->name()));
const bool changed = mergeHistory(sourceEntry, targetEntry, mergeMethod); const bool changed = mergeHistory(sourceEntry, targetEntry, mergeMethod);
if (changed) { if (changed) {
changes << tr("Synchronizing from older source %1 [%2]").arg(targetEntry->title(), targetEntry->uuidToHex()); changes
<< tr("Synchronizing from older source %1 [%2]").arg(targetEntry->title(), targetEntry->uuidToHex());
} }
} }
return changes; return changes;
} }
Merger::ChangeList
Merger::ChangeList Merger::resolveEntryConflict(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry) Merger::resolveEntryConflict(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry)
{ {
ChangeList changes; ChangeList changes;
// We need to cut off the milliseconds since the persistent format only supports times down to seconds // We need to cut off the milliseconds since the persistent format only supports times down to seconds
@ -395,15 +411,19 @@ bool Merger::mergeHistory(const Entry* sourceEntry, Entry* targetEntry, Group::M
Q_UNUSED(mergeMethod); Q_UNUSED(mergeMethod);
const auto targetHistoryItems = targetEntry->historyItems(); const auto targetHistoryItems = targetEntry->historyItems();
const auto sourceHistoryItems = sourceEntry->historyItems(); const auto sourceHistoryItems = sourceEntry->historyItems();
const int comparison = compare(sourceEntry->timeInfo().lastModificationTime(), targetEntry->timeInfo().lastModificationTime(), CompareItemIgnoreMilliseconds); const int comparison = compare(sourceEntry->timeInfo().lastModificationTime(),
targetEntry->timeInfo().lastModificationTime(),
CompareItemIgnoreMilliseconds);
const bool preferLocal = mergeMethod == Group::KeepLocal || comparison < 0; const bool preferLocal = mergeMethod == Group::KeepLocal || comparison < 0;
const bool preferRemote = mergeMethod == Group::KeepRemote || comparison > 0; const bool preferRemote = mergeMethod == Group::KeepRemote || comparison > 0;
QMap<QDateTime, Entry*> merged; QMap<QDateTime, Entry*> merged;
for (Entry* historyItem : targetHistoryItems) { for (Entry* historyItem : targetHistoryItems) {
const QDateTime modificationTime = Clock::serialized(historyItem->timeInfo().lastModificationTime()); const QDateTime modificationTime = Clock::serialized(historyItem->timeInfo().lastModificationTime());
if (merged.contains(modificationTime) && !merged[modificationTime]->equals(historyItem, CompareItemIgnoreMilliseconds)) { if (merged.contains(modificationTime)
::qWarning("Inconsistent history entry of %s[%s] at %s contains conflicting changes - conflict resolution may lose data!", && !merged[modificationTime]->equals(historyItem, CompareItemIgnoreMilliseconds)) {
::qWarning("Inconsistent history entry of %s[%s] at %s contains conflicting changes - conflict resolution "
"may lose data!",
qPrintable(sourceEntry->title()), qPrintable(sourceEntry->title()),
qPrintable(sourceEntry->uuidToHex()), qPrintable(sourceEntry->uuidToHex()),
qPrintable(modificationTime.toString("yyyy-MM-dd HH-mm-ss-zzz"))); qPrintable(modificationTime.toString("yyyy-MM-dd HH-mm-ss-zzz")));
@ -413,8 +433,10 @@ bool Merger::mergeHistory(const Entry* sourceEntry, Entry* targetEntry, Group::M
for (Entry* historyItem : sourceHistoryItems) { for (Entry* historyItem : sourceHistoryItems) {
// Items with same modification-time changes will be regarded as same (like KeePass2) // Items with same modification-time changes will be regarded as same (like KeePass2)
const QDateTime modificationTime = Clock::serialized(historyItem->timeInfo().lastModificationTime()); const QDateTime modificationTime = Clock::serialized(historyItem->timeInfo().lastModificationTime());
if (merged.contains(modificationTime) && !merged[modificationTime]->equals(historyItem, CompareItemIgnoreMilliseconds)) { if (merged.contains(modificationTime)
::qWarning("History entry of %s[%s] at %s contains conflicting changes - conflict resolution may lose data!", && !merged[modificationTime]->equals(historyItem, CompareItemIgnoreMilliseconds)) {
::qWarning(
"History entry of %s[%s] at %s contains conflicting changes - conflict resolution may lose data!",
qPrintable(sourceEntry->title()), qPrintable(sourceEntry->title()),
qPrintable(sourceEntry->uuidToHex()), qPrintable(sourceEntry->uuidToHex()),
qPrintable(modificationTime.toString("yyyy-MM-dd HH-mm-ss-zzz"))); qPrintable(modificationTime.toString("yyyy-MM-dd HH-mm-ss-zzz")));
@ -430,7 +452,9 @@ bool Merger::mergeHistory(const Entry* sourceEntry, Entry* targetEntry, Group::M
const QDateTime targetModificationTime = Clock::serialized(targetEntry->timeInfo().lastModificationTime()); const QDateTime targetModificationTime = Clock::serialized(targetEntry->timeInfo().lastModificationTime());
const QDateTime sourceModificationTime = Clock::serialized(sourceEntry->timeInfo().lastModificationTime()); const QDateTime sourceModificationTime = Clock::serialized(sourceEntry->timeInfo().lastModificationTime());
if (targetModificationTime == sourceModificationTime && !targetEntry->equals(sourceEntry, CompareItemIgnoreMilliseconds | CompareItemIgnoreHistory | CompareItemIgnoreLocation)) { if (targetModificationTime == sourceModificationTime
&& !targetEntry->equals(sourceEntry,
CompareItemIgnoreMilliseconds | CompareItemIgnoreHistory | CompareItemIgnoreLocation)) {
::qWarning("Entry of %s[%s] contains conflicting changes - conflict resolution may lose data!", ::qWarning("Entry of %s[%s] contains conflicting changes - conflict resolution may lose data!",
qPrintable(sourceEntry->title()), qPrintable(sourceEntry->title()),
qPrintable(sourceEntry->uuidToHex())); qPrintable(sourceEntry->uuidToHex()));
@ -480,7 +504,7 @@ bool Merger::mergeHistory(const Entry* sourceEntry, Entry* targetEntry, Group::M
bool updateTimeInfo = targetEntry->canUpdateTimeinfo(); bool updateTimeInfo = targetEntry->canUpdateTimeinfo();
targetEntry->setUpdateTimeinfo(false); targetEntry->setUpdateTimeinfo(false);
targetEntry->removeHistoryItems(targetHistoryItems); targetEntry->removeHistoryItems(targetHistoryItems);
for (Entry* historyItem : merged.values()) { for (Entry* historyItem : merged) {
Q_ASSERT(!historyItem->parent()); Q_ASSERT(!historyItem->parent());
targetEntry->addHistoryItem(historyItem); targetEntry->addHistoryItem(historyItem);
} }

View File

@ -55,14 +55,22 @@ private:
bool mergeHistory(const Entry* sourceEntry, Entry* targetEntry, Group::MergeMode mergeMethod); bool mergeHistory(const Entry* sourceEntry, Entry* targetEntry, Group::MergeMode mergeMethod);
void moveEntry(Entry* entry, Group* targetGroup); void moveEntry(Entry* entry, Group* targetGroup);
void moveGroup(Group* group, Group* targetGroup); void moveGroup(Group* group, Group* targetGroup);
void eraseEntry(Entry* entry); // remove an entry without a trace in the deletedObjects - needed for elemination cloned entries // remove an entry without a trace in the deletedObjects - needed for elemination cloned entries
void eraseGroup(Group* group); // remove an entry without a trace in the deletedObjects - needed for elemination cloned entries void eraseEntry(Entry* entry);
// remove an entry without a trace in the deletedObjects - needed for elemination cloned entries
void eraseGroup(Group* group);
ChangeList resolveEntryConflict(const MergeContext& context, const Entry* existingEntry, Entry* otherEntry); ChangeList resolveEntryConflict(const MergeContext& context, const Entry* existingEntry, Entry* otherEntry);
ChangeList resolveGroupConflict(const MergeContext& context, const Group* existingGroup, Group* otherGroup); ChangeList resolveGroupConflict(const MergeContext& context, const Group* existingGroup, Group* otherGroup);
Merger::ChangeList resolveEntryConflict_Duplicate(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry); Merger::ChangeList
Merger::ChangeList resolveEntryConflict_KeepLocal(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry); resolveEntryConflict_Duplicate(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry);
Merger::ChangeList resolveEntryConflict_KeepRemote(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry); Merger::ChangeList
Merger::ChangeList resolveEntryConflict_MergeHistories(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry, Group::MergeMode mergeMethod); resolveEntryConflict_KeepLocal(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry);
Merger::ChangeList
resolveEntryConflict_KeepRemote(const MergeContext& context, const Entry* sourceEntry, Entry* targetEntry);
Merger::ChangeList resolveEntryConflict_MergeHistories(const MergeContext& context,
const Entry* sourceEntry,
Entry* targetEntry,
Group::MergeMode mergeMethod);
private: private:
MergeContext m_context; MergeContext m_context;

View File

@ -429,7 +429,7 @@ void Metadata::removeCustomIcon(const QUuid& uuid)
emit metadataModified(); emit metadataModified();
} }
QUuid Metadata::findCustomIcon(const QImage &candidate) QUuid Metadata::findCustomIcon(const QImage& candidate)
{ {
QByteArray hash = hashImage(candidate); QByteArray hash = hashImage(candidate);
return m_customIconsHashes.value(hash, QUuid()); return m_customIconsHashes.value(hash, QUuid());

View File

@ -9,6 +9,7 @@ class OSEventFilter : public QAbstractNativeEventFilter
public: public:
OSEventFilter(); OSEventFilter();
bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override; bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override;
private: private:
Q_DISABLE_COPY(OSEventFilter) Q_DISABLE_COPY(OSEventFilter)
}; };

View File

@ -124,7 +124,6 @@ bool PasswordGenerator::isValid() const
} }
return !passwordGroups().isEmpty(); return !passwordGroups().isEmpty();
} }
QVector<PasswordGroup> PasswordGenerator::passwordGroups() const QVector<PasswordGroup> PasswordGenerator::passwordGroups() const

View File

@ -22,14 +22,12 @@
#include "core/Translator.h" #include "core/Translator.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QElapsedTimer>
#include <QIODevice> #include <QIODevice>
#include <QImageReader> #include <QImageReader>
#include <QLocale> #include <QLocale>
#include <QStringList>
#include <QRegularExpression> #include <QRegularExpression>
#include <QStringList>
#include <QElapsedTimer>
#include <cctype> #include <cctype>
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@ -59,147 +57,145 @@
namespace Tools namespace Tools
{ {
QString humanReadableFileSize(qint64 bytes, quint32 precision) QString humanReadableFileSize(qint64 bytes, quint32 precision)
{ {
constexpr auto kibibyte = 1024; constexpr auto kibibyte = 1024;
double size = bytes; double size = bytes;
QStringList units = QStringList() << "B" QStringList units = QStringList() << "B"
<< "KiB" << "KiB"
<< "MiB" << "MiB"
<< "GiB"; << "GiB";
int i = 0; int i = 0;
int maxI = units.size() - 1; int maxI = units.size() - 1;
while ((size >= kibibyte) && (i < maxI)) { while ((size >= kibibyte) && (i < maxI)) {
size /= kibibyte; size /= kibibyte;
i++; i++;
}
return QString("%1 %2").arg(QLocale().toString(size, 'f', precision), units.at(i));
} }
return QString("%1 %2").arg(QLocale().toString(size, 'f', precision), units.at(i)); bool readFromDevice(QIODevice* device, QByteArray& data, int size)
} {
QByteArray buffer;
buffer.resize(size);
bool readFromDevice(QIODevice* device, QByteArray& data, int size) qint64 readResult = device->read(buffer.data(), size);
{ if (readResult == -1) {
QByteArray buffer; return false;
buffer.resize(size); } else {
buffer.resize(readResult);
qint64 readResult = device->read(buffer.data(), size); data = buffer;
if (readResult == -1) { return true;
return false;
} else {
buffer.resize(readResult);
data = buffer;
return true;
}
}
bool readAllFromDevice(QIODevice* device, QByteArray& data)
{
QByteArray result;
qint64 readBytes = 0;
qint64 readResult;
do {
result.resize(result.size() + 16384);
readResult = device->read(result.data() + readBytes, result.size() - readBytes);
if (readResult > 0) {
readBytes += readResult;
} }
} }
while (readResult > 0);
if (readResult == -1) { bool readAllFromDevice(QIODevice* device, QByteArray& data)
return false; {
} else { QByteArray result;
result.resize(static_cast<int>(readBytes)); qint64 readBytes = 0;
data = result; qint64 readResult;
return true; do {
result.resize(result.size() + 16384);
readResult = device->read(result.data() + readBytes, result.size() - readBytes);
if (readResult > 0) {
readBytes += readResult;
}
} while (readResult > 0);
if (readResult == -1) {
return false;
} else {
result.resize(static_cast<int>(readBytes));
data = result;
return true;
}
} }
}
QString imageReaderFilter() QString imageReaderFilter()
{ {
const QList<QByteArray> formats = QImageReader::supportedImageFormats(); const QList<QByteArray> formats = QImageReader::supportedImageFormats();
QStringList formatsStringList; QStringList formatsStringList;
for (const QByteArray& format : formats) { for (const QByteArray& format : formats) {
for (char codePoint : format) { for (char codePoint : format) {
if (!QChar(codePoint).isLetterOrNumber()) { if (!QChar(codePoint).isLetterOrNumber()) {
continue; continue;
}
}
formatsStringList.append("*." + QString::fromLatin1(format).toLower());
}
return formatsStringList.join(" ");
}
bool isHex(const QByteArray& ba)
{
for (const unsigned char c : ba) {
if (!std::isxdigit(c)) {
return false;
} }
} }
formatsStringList.append("*." + QString::fromLatin1(format).toLower()); return true;
} }
return formatsStringList.join(" "); bool isBase64(const QByteArray& ba)
} {
constexpr auto pattern = R"(^(?:[a-z0-9+]{4})*(?:[a-z0-9+]{3}=|[a-z0-9+]{2}==)?$)";
QRegExp regexp(pattern, Qt::CaseInsensitive, QRegExp::RegExp2);
bool isHex(const QByteArray& ba) QString base64 = QString::fromLatin1(ba.constData(), ba.size());
{
for (const unsigned char c : ba) { return regexp.exactMatch(base64);
if (!std::isxdigit(c)) { }
return false;
void sleep(int ms)
{
Q_ASSERT(ms >= 0);
if (ms == 0) {
return;
} }
}
return true;
}
bool isBase64(const QByteArray& ba)
{
constexpr auto pattern = R"(^(?:[a-z0-9+]{4})*(?:[a-z0-9+]{3}=|[a-z0-9+]{2}==)?$)";
QRegExp regexp(pattern, Qt::CaseInsensitive, QRegExp::RegExp2);
QString base64 = QString::fromLatin1(ba.constData(), ba.size());
return regexp.exactMatch(base64);
}
void sleep(int ms)
{
Q_ASSERT(ms >= 0);
if (ms == 0) {
return;
}
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
Sleep(uint(ms)); Sleep(uint(ms));
#else #else
timespec ts; timespec ts;
ts.tv_sec = ms/1000; ts.tv_sec = ms / 1000;
ts.tv_nsec = (ms%1000)*1000*1000; ts.tv_nsec = (ms % 1000) * 1000 * 1000;
nanosleep(&ts, nullptr); nanosleep(&ts, nullptr);
#endif #endif
}
void wait(int ms)
{
Q_ASSERT(ms >= 0);
if (ms == 0) {
return;
} }
QElapsedTimer timer; void wait(int ms)
timer.start(); {
Q_ASSERT(ms >= 0);
if (ms <= 50) { if (ms == 0) {
QCoreApplication::processEvents(QEventLoop::AllEvents, ms); return;
sleep(qMax(ms - static_cast<int>(timer.elapsed()), 0)); }
} else {
int timeLeft; QElapsedTimer timer;
do { timer.start();
timeLeft = ms - timer.elapsed();
if (timeLeft > 0) { if (ms <= 50) {
QCoreApplication::processEvents(QEventLoop::AllEvents, timeLeft); QCoreApplication::processEvents(QEventLoop::AllEvents, ms);
sleep(10); sleep(qMax(ms - static_cast<int>(timer.elapsed()), 0));
} } else {
int timeLeft;
do {
timeLeft = ms - timer.elapsed();
if (timeLeft > 0) {
QCoreApplication::processEvents(QEventLoop::AllEvents, timeLeft);
sleep(10);
}
} while (!timer.hasExpired(ms));
} }
while (!timer.hasExpired(ms));
} }
}
// Escape common regex symbols except for *, ?, and | // Escape common regex symbols except for *, ?, and |
auto regexEscape = QRegularExpression(R"re(([-[\]{}()+.,\\\/^$#]))re"); auto regexEscape = QRegularExpression(R"re(([-[\]{}()+.,\\\/^$#]))re");

View File

@ -31,28 +31,28 @@ class QRegularExpression;
namespace Tools namespace Tools
{ {
QString humanReadableFileSize(qint64 bytes, quint32 precision = 2); QString humanReadableFileSize(qint64 bytes, quint32 precision = 2);
bool readFromDevice(QIODevice* device, QByteArray& data, int size = 16384); bool readFromDevice(QIODevice* device, QByteArray& data, int size = 16384);
bool readAllFromDevice(QIODevice* device, QByteArray& data); bool readAllFromDevice(QIODevice* device, QByteArray& data);
QString imageReaderFilter(); QString imageReaderFilter();
bool isHex(const QByteArray& ba); bool isHex(const QByteArray& ba);
bool isBase64(const QByteArray& ba); bool isBase64(const QByteArray& ba);
void sleep(int ms); void sleep(int ms);
void wait(int ms); void wait(int ms);
QRegularExpression convertToRegex(const QString& string, bool useWildcards = false, bool exactMatch = false, QRegularExpression convertToRegex(const QString& string, bool useWildcards = false,
bool caseSensitive = false); bool exactMatch = false, bool caseSensitive = false);
template <typename RandomAccessIterator, typename T> template <typename RandomAccessIterator, typename T>
RandomAccessIterator binaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T& value) RandomAccessIterator binaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T& value)
{ {
RandomAccessIterator it = std::lower_bound(begin, end, value); RandomAccessIterator it = std::lower_bound(begin, end, value);
if ((it == end) || (value < *it)) { if ((it == end) || (value < *it)) {
return end; return end;
} else { } else {
return it; return it;
}
} }
}
} // namespace Tools } // namespace Tools

View File

@ -144,8 +144,9 @@ bool Crypto::testSha512()
QByteArray sha512Test = QByteArray sha512Test =
CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", CryptoHash::Sha512); CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", CryptoHash::Sha512);
if (sha512Test != QByteArray::fromHex("204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b" if (sha512Test
"07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445")) { != QByteArray::fromHex("204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b"
"07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445")) {
raiseError("SHA-512 mismatch."); raiseError("SHA-512 mismatch.");
return false; return false;
} }

View File

@ -1,19 +1,19 @@
/* /*
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de> * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option) * the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License. * version 3 of the License.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "SymmetricCipher.h" #include "SymmetricCipher.h"

View File

@ -1,19 +1,19 @@
/* /*
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de> * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option) * the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License. * version 3 of the License.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef KEEPASSX_SYMMETRICCIPHER_H #ifndef KEEPASSX_SYMMETRICCIPHER_H
#define KEEPASSX_SYMMETRICCIPHER_H #define KEEPASSX_SYMMETRICCIPHER_H

View File

@ -1,19 +1,19 @@
/* /*
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de> * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option) * the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License. * version 3 of the License.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef KEEPASSX_SYMMETRICCIPHERBACKEND_H #ifndef KEEPASSX_SYMMETRICCIPHERBACKEND_H
#define KEEPASSX_SYMMETRICCIPHERBACKEND_H #define KEEPASSX_SYMMETRICCIPHERBACKEND_H

View File

@ -1,19 +1,19 @@
/* /*
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de> * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option) * the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License. * version 3 of the License.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "SymmetricCipherGcrypt.h" #include "SymmetricCipherGcrypt.h"

View File

@ -1,19 +1,19 @@
/* /*
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de> * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option) * the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License. * version 3 of the License.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef KEEPASSX_SYMMETRICCIPHERGCRYPT_H #ifndef KEEPASSX_SYMMETRICCIPHERGCRYPT_H
#define KEEPASSX_SYMMETRICCIPHERGCRYPT_H #define KEEPASSX_SYMMETRICCIPHERGCRYPT_H

View File

@ -46,12 +46,12 @@ protected:
private: private:
Q_REQUIRED_RESULT static bool transformKeyRaw(const QByteArray& key, Q_REQUIRED_RESULT static bool transformKeyRaw(const QByteArray& key,
const QByteArray& seed, const QByteArray& seed,
quint32 version, quint32 version,
quint32 rounds, quint32 rounds,
quint64 memory, quint64 memory,
quint32 parallelism, quint32 parallelism,
QByteArray& result); QByteArray& result);
}; };
#endif // KEEPASSX_ARGON2KDF_H #endif // KEEPASSX_ARGON2KDF_H

View File

@ -18,8 +18,8 @@
#ifndef KEEPASSX_KDF_H #ifndef KEEPASSX_KDF_H
#define KEEPASSX_KDF_H #define KEEPASSX_KDF_H
#include <QVariant>
#include <QUuid> #include <QUuid>
#include <QVariant>
#define KDF_DEFAULT_SEED_SIZE 32 #define KDF_DEFAULT_SEED_SIZE 32
#define KDF_DEFAULT_ROUNDS 1000000ull #define KDF_DEFAULT_ROUNDS 1000000ull

View File

@ -42,8 +42,7 @@ bool Kdbx3Reader::readDatabaseImpl(QIODevice* device,
// check if all required headers were present // check if all required headers were present
if (m_masterSeed.isEmpty() || m_encryptionIV.isEmpty() || m_streamStartBytes.isEmpty() if (m_masterSeed.isEmpty() || m_encryptionIV.isEmpty() || m_streamStartBytes.isEmpty()
|| m_protectedStreamKey.isEmpty() || m_protectedStreamKey.isEmpty() || db->cipher().isNull()) {
|| db->cipher().isNull()) {
raiseError(tr("missing database headers")); raiseError(tr("missing database headers"));
return false; return false;
} }

View File

@ -66,9 +66,10 @@ bool Kdbx3Writer::writeDatabase(QIODevice* device, Database* db)
writeMagicNumbers(&header, KeePass2::SIGNATURE_1, KeePass2::SIGNATURE_2, KeePass2::FILE_VERSION_3_1); writeMagicNumbers(&header, KeePass2::SIGNATURE_1, KeePass2::SIGNATURE_2, KeePass2::FILE_VERSION_3_1);
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toRfc4122())); CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toRfc4122()));
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::CompressionFlags, CHECK_RETURN_FALSE(
Endian::sizedIntToBytes<qint32>(db->compressionAlgorithm(), writeHeaderField<quint16>(&header,
KeePass2::BYTEORDER))); KeePass2::HeaderFieldID::CompressionFlags,
Endian::sizedIntToBytes<qint32>(db->compressionAlgorithm(), KeePass2::BYTEORDER)));
auto kdf = db->kdf(); auto kdf = db->kdf();
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::MasterSeed, masterSeed)); CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::MasterSeed, masterSeed));
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::TransformSeed, kdf->seed())); CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::TransformSeed, kdf->seed()));

View File

@ -50,7 +50,6 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db)
QByteArray masterSeed = randomGen()->randomArray(32); QByteArray masterSeed = randomGen()->randomArray(32);
QByteArray encryptionIV = randomGen()->randomArray(ivSize); QByteArray encryptionIV = randomGen()->randomArray(ivSize);
QByteArray protectedStreamKey = randomGen()->randomArray(64); QByteArray protectedStreamKey = randomGen()->randomArray(64);
QByteArray startBytes;
QByteArray endOfHeader = "\r\n\r\n"; QByteArray endOfHeader = "\r\n\r\n";
if (!db->setKey(db->key(), false, true)) { if (!db->setKey(db->key(), false, true)) {
@ -73,10 +72,12 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db)
writeMagicNumbers(&header, KeePass2::SIGNATURE_1, KeePass2::SIGNATURE_2, KeePass2::FILE_VERSION_4); writeMagicNumbers(&header, KeePass2::SIGNATURE_1, KeePass2::SIGNATURE_2, KeePass2::FILE_VERSION_4);
CHECK_RETURN_FALSE(writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toRfc4122())); CHECK_RETURN_FALSE(
CHECK_RETURN_FALSE(writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::CompressionFlags, writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toRfc4122()));
Endian::sizedIntToBytes(static_cast<int>(db->compressionAlgorithm()), CHECK_RETURN_FALSE(writeHeaderField<quint32>(
KeePass2::BYTEORDER))); &header,
KeePass2::HeaderFieldID::CompressionFlags,
Endian::sizedIntToBytes(static_cast<int>(db->compressionAlgorithm()), KeePass2::BYTEORDER)));
CHECK_RETURN_FALSE(writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::MasterSeed, masterSeed)); CHECK_RETURN_FALSE(writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::MasterSeed, masterSeed));
CHECK_RETURN_FALSE(writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::EncryptionIV, encryptionIV)); CHECK_RETURN_FALSE(writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::EncryptionIV, encryptionIV));

View File

@ -44,7 +44,7 @@ KdbxXmlReader::KdbxXmlReader(quint32 version)
* @param version KDBX version * @param version KDBX version
* @param binaryPool binary pool * @param binaryPool binary pool
*/ */
KdbxXmlReader::KdbxXmlReader(quint32 version, QHash<QString, QByteArray> binaryPool) KdbxXmlReader::KdbxXmlReader(quint32 version, QHash<QString, QByteArray> binaryPool)
: m_kdbxVersion(version) : m_kdbxVersion(version)
, m_binaryPool(std::move(binaryPool)) , m_binaryPool(std::move(binaryPool))
{ {
@ -731,7 +731,7 @@ Entry* KdbxXmlReader::parseEntry(bool history)
} }
if (m_xml.name() == "Binary") { if (m_xml.name() == "Binary") {
QPair<QString, QString> ref = parseEntryBinary(entry); QPair<QString, QString> ref = parseEntryBinary(entry);
if (!ref.first.isNull() && !ref.second.isNull()) { if (!ref.first.isEmpty() && !ref.second.isEmpty()) {
binaryRefs.append(ref); binaryRefs.append(ref);
} }
continue; continue;

View File

@ -21,7 +21,6 @@
#include "core/Database.h" #include "core/Database.h"
#include "core/Metadata.h" #include "core/Metadata.h"
#include "core/TimeInfo.h" #include "core/TimeInfo.h"
#include "core/Database.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QPair> #include <QPair>
@ -42,7 +41,7 @@ class KdbxXmlReader
public: public:
explicit KdbxXmlReader(quint32 version); explicit KdbxXmlReader(quint32 version);
explicit KdbxXmlReader(quint32 version, QHash<QString, QByteArray> binaryPool); explicit KdbxXmlReader(quint32 version, QHash<QString, QByteArray> binaryPool);
virtual ~KdbxXmlReader() = default; virtual ~KdbxXmlReader() = default;
virtual QSharedPointer<Database> readDatabase(const QString& filename); virtual QSharedPointer<Database> readDatabase(const QString& filename);

View File

@ -356,12 +356,14 @@ void KdbxXmlWriter::writeEntry(const Entry* entry)
for (const QString& key : attributesKeyList) { for (const QString& key : attributesKeyList) {
m_xml.writeStartElement("String"); m_xml.writeStartElement("String");
// clang-format off
bool protect = bool protect =
(((key == "Title") && m_meta->protectTitle()) || ((key == "UserName") && m_meta->protectUsername()) (((key == "Title") && m_meta->protectTitle()) || ((key == "UserName") && m_meta->protectUsername())
|| ((key == "Password") && m_meta->protectPassword()) || ((key == "Password") && m_meta->protectPassword())
|| ((key == "URL") && m_meta->protectUrl()) || ((key == "URL") && m_meta->protectUrl())
|| ((key == "Notes") && m_meta->protectNotes()) || ((key == "Notes") && m_meta->protectNotes())
|| entry->attributes()->isProtected(key)); || entry->attributes()->isProtected(key));
// clang-format on
writeString("Key", key); writeString("Key", key);

View File

@ -1,19 +1,19 @@
/* /*
* Copyright (C) 2012 Felix Geyer <debfx@fobos.de> * Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option) * the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License. * version 3 of the License.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef KEEPASSX_KEEPASS1_H #ifndef KEEPASSX_KEEPASS1_H
#define KEEPASSX_KEEPASS1_H #define KEEPASSX_KEEPASS1_H
@ -35,6 +35,6 @@ namespace KeePass1
Rijndael = 2, Rijndael = 2,
Twofish = 8 Twofish = 8
}; };
} } // namespace KeePass1
#endif // KEEPASSX_KEEPASS1_H #endif // KEEPASSX_KEEPASS1_H

View File

@ -23,14 +23,14 @@
#define UUID_LENGTH 16 #define UUID_LENGTH 16
const QUuid KeePass2::CIPHER_AES128 = QUuid("61ab05a1-9464-41c3-8d74-3a563df8dd35"); const QUuid KeePass2::CIPHER_AES128 = QUuid("61ab05a1-9464-41c3-8d74-3a563df8dd35");
const QUuid KeePass2::CIPHER_AES256 = QUuid("31c1f2e6-bf71-4350-be58-05216afc5aff"); const QUuid KeePass2::CIPHER_AES256 = QUuid("31c1f2e6-bf71-4350-be58-05216afc5aff");
const QUuid KeePass2::CIPHER_TWOFISH = QUuid("ad68f29f-576f-4bb9-a36a-d47af965346c"); const QUuid KeePass2::CIPHER_TWOFISH = QUuid("ad68f29f-576f-4bb9-a36a-d47af965346c");
const QUuid KeePass2::CIPHER_CHACHA20 = QUuid("d6038a2b-8b6f-4cb5-a524-339a31dbb59a"); const QUuid KeePass2::CIPHER_CHACHA20 = QUuid("d6038a2b-8b6f-4cb5-a524-339a31dbb59a");
const QUuid KeePass2::KDF_AES_KDBX3 = QUuid("c9d9f39a-628a-4460-bf74-0d08c18a4fea"); const QUuid KeePass2::KDF_AES_KDBX3 = QUuid("c9d9f39a-628a-4460-bf74-0d08c18a4fea");
const QUuid KeePass2::KDF_AES_KDBX4 = QUuid("7c02bb82-79a7-4ac0-927d-114a00648238"); const QUuid KeePass2::KDF_AES_KDBX4 = QUuid("7c02bb82-79a7-4ac0-927d-114a00648238");
const QUuid KeePass2::KDF_ARGON2 = QUuid("ef636ddf-8c29-444b-91f7-a9a403e30a0c"); const QUuid KeePass2::KDF_ARGON2 = QUuid("ef636ddf-8c29-444b-91f7-a9a403e30a0c");
const QByteArray KeePass2::INNER_STREAM_SALSA20_IV("\xe8\x30\x09\x4b\x97\x20\x5d\x2a"); const QByteArray KeePass2::INNER_STREAM_SALSA20_IV("\xe8\x30\x09\x4b\x97\x20\x5d\x2a");
@ -50,14 +50,12 @@ const QString KeePass2::KDFPARAM_ARGON2_ASSOCDATA("A");
const QList<QPair<QUuid, QString>> KeePass2::CIPHERS{ const QList<QPair<QUuid, QString>> KeePass2::CIPHERS{
qMakePair(KeePass2::CIPHER_AES256, QObject::tr("AES: 256-bit")), qMakePair(KeePass2::CIPHER_AES256, QObject::tr("AES: 256-bit")),
qMakePair(KeePass2::CIPHER_TWOFISH, QObject::tr("Twofish: 256-bit")), qMakePair(KeePass2::CIPHER_TWOFISH, QObject::tr("Twofish: 256-bit")),
qMakePair(KeePass2::CIPHER_CHACHA20, QObject::tr("ChaCha20: 256-bit")) qMakePair(KeePass2::CIPHER_CHACHA20, QObject::tr("ChaCha20: 256-bit"))};
};
const QList<QPair<QUuid, QString>> KeePass2::KDFS{ const QList<QPair<QUuid, QString>> KeePass2::KDFS{
qMakePair(KeePass2::KDF_ARGON2, QObject::tr("Argon2 (KDBX 4 recommended)")), qMakePair(KeePass2::KDF_ARGON2, QObject::tr("Argon2 (KDBX 4 recommended)")),
qMakePair(KeePass2::KDF_AES_KDBX4, QObject::tr("AES-KDF (KDBX 4)")), qMakePair(KeePass2::KDF_AES_KDBX4, QObject::tr("AES-KDF (KDBX 4)")),
qMakePair(KeePass2::KDF_AES_KDBX3, QObject::tr("AES-KDF (KDBX 3.1)")) qMakePair(KeePass2::KDF_AES_KDBX3, QObject::tr("AES-KDF (KDBX 3.1)"))};
};
QByteArray KeePass2::hmacKey(const QByteArray& masterSeed, const QByteArray& transformedMasterKey) QByteArray KeePass2::hmacKey(const QByteArray& masterSeed, const QByteArray& transformedMasterKey)
{ {

View File

@ -21,9 +21,9 @@
#include <QList> #include <QList>
#include <QMap> #include <QMap>
#include <QSharedPointer> #include <QSharedPointer>
#include <QUuid>
#include <QVariantMap> #include <QVariantMap>
#include <QtGlobal> #include <QtGlobal>
#include <QUuid>
#include "crypto/SymmetricCipher.h" #include "crypto/SymmetricCipher.h"
#include "crypto/kdf/Kdf.h" #include "crypto/kdf/Kdf.h"
@ -46,14 +46,14 @@ namespace KeePass2
const QSysInfo::Endian BYTEORDER = QSysInfo::LittleEndian; const QSysInfo::Endian BYTEORDER = QSysInfo::LittleEndian;
extern const QUuid CIPHER_AES128; extern const QUuid CIPHER_AES128;
extern const QUuid CIPHER_AES256; extern const QUuid CIPHER_AES256;
extern const QUuid CIPHER_TWOFISH; extern const QUuid CIPHER_TWOFISH;
extern const QUuid CIPHER_CHACHA20; extern const QUuid CIPHER_CHACHA20;
extern const QUuid KDF_AES_KDBX3; extern const QUuid KDF_AES_KDBX3;
extern const QUuid KDF_AES_KDBX4; extern const QUuid KDF_AES_KDBX4;
extern const QUuid KDF_ARGON2; extern const QUuid KDF_ARGON2;
extern const QByteArray INNER_STREAM_SALSA20_IV; extern const QByteArray INNER_STREAM_SALSA20_IV;
@ -68,8 +68,8 @@ extern const QUuid KDF_ARGON2;
extern const QString KDFPARAM_ARGON2_SECRET; extern const QString KDFPARAM_ARGON2_SECRET;
extern const QString KDFPARAM_ARGON2_ASSOCDATA; extern const QString KDFPARAM_ARGON2_ASSOCDATA;
extern const QList<QPair<QUuid, QString>> CIPHERS; extern const QList<QPair<QUuid, QString>> CIPHERS;
extern const QList<QPair<QUuid, QString>> KDFS; extern const QList<QPair<QUuid, QString>> KDFS;
enum class HeaderFieldID enum class HeaderFieldID
{ {
@ -126,11 +126,11 @@ extern const QList<QPair<QUuid, QString>> KDFS;
ByteArray = 0x42 ByteArray = 0x42
}; };
QByteArray hmacKey(const QByteArray& masterSeed, const QByteArray& transformedMasterKey); QByteArray hmacKey(const QByteArray& masterSeed, const QByteArray& transformedMasterKey);
QSharedPointer<Kdf> kdfFromParameters(const QVariantMap& p); QSharedPointer<Kdf> kdfFromParameters(const QVariantMap& p);
QVariantMap kdfToParameters(const QSharedPointer<Kdf>& kdf); QVariantMap kdfToParameters(const QSharedPointer<Kdf>& kdf);
QSharedPointer<Kdf> uuidToKdf(const QUuid& uuid); QSharedPointer<Kdf> uuidToKdf(const QUuid& uuid);
ProtectedStreamAlgo idToProtectedStreamAlgo(quint32 id); ProtectedStreamAlgo idToProtectedStreamAlgo(quint32 id);
} // namespace KeePass2 } // namespace KeePass2

View File

@ -64,10 +64,9 @@ AboutDialog::AboutDialog(QWidget* parent)
debugInfo.append(tr("Distribution: %1").arg(KEEPASSXC_DIST_TYPE).append("\n")); debugInfo.append(tr("Distribution: %1").arg(KEEPASSXC_DIST_TYPE).append("\n"));
#endif #endif
debugInfo.append("\n").append(QString("%1\n- Qt %2\n- %3\n\n") debugInfo.append("\n").append(
.arg(tr("Libraries:"), QString("%1\n- Qt %2\n- %3\n\n")
QString::fromLocal8Bit(qVersion()), .arg(tr("Libraries:"), QString::fromLocal8Bit(qVersion()), Crypto::backendVersion()));
Crypto::backendVersion()));
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
debugInfo.append(tr("Operating system: %1\nCPU architecture: %2\nKernel: %3 %4") debugInfo.append(tr("Operating system: %1\nCPU architecture: %2\nKernel: %3 %4")

View File

@ -25,7 +25,7 @@ namespace Ui
{ {
class ApplicationSettingsWidgetGeneral; class ApplicationSettingsWidgetGeneral;
class ApplicationSettingsWidgetSecurity; class ApplicationSettingsWidgetSecurity;
} } // namespace Ui
class ISettingsPage class ISettingsPage
{ {

View File

@ -38,8 +38,9 @@ CategoryListWidget::CategoryListWidget(QWidget* parent)
connect(m_ui->scrollUp, SIGNAL(clicked()), SLOT(scrollCategoriesUp())); connect(m_ui->scrollUp, SIGNAL(clicked()), SLOT(scrollCategoriesUp()));
connect(m_ui->scrollDown, SIGNAL(clicked()), SLOT(scrollCategoriesDown())); connect(m_ui->scrollDown, SIGNAL(clicked()), SLOT(scrollCategoriesDown()));
connect(m_ui->categoryList->verticalScrollBar(), SIGNAL(valueChanged(int)), SLOT(updateCategoryScrollButtons())); connect(m_ui->categoryList->verticalScrollBar(), SIGNAL(valueChanged(int)), SLOT(updateCategoryScrollButtons()));
connect( // clang-format off
m_ui->categoryList->verticalScrollBar(), SIGNAL(rangeChanged(int,int)), SLOT(updateCategoryScrollButtons())); connect(m_ui->categoryList->verticalScrollBar(), SIGNAL(rangeChanged(int,int)), SLOT(updateCategoryScrollButtons()));
// clang-format on
} }
CategoryListWidget::~CategoryListWidget() CategoryListWidget::~CategoryListWidget()

View File

@ -105,9 +105,11 @@ void DatabaseOpenWidget::showEvent(QShowEvent* event)
#ifdef WITH_XC_YUBIKEY #ifdef WITH_XC_YUBIKEY
// showEvent() may be called twice, so make sure we are only polling once // showEvent() may be called twice, so make sure we are only polling once
if (!m_yubiKeyBeingPolled) { if (!m_yubiKeyBeingPolled) {
// clang-format off
connect(YubiKey::instance(), SIGNAL(detected(int,bool)), SLOT(yubikeyDetected(int,bool)), Qt::QueuedConnection); connect(YubiKey::instance(), SIGNAL(detected(int,bool)), SLOT(yubikeyDetected(int,bool)), Qt::QueuedConnection);
connect(YubiKey::instance(), SIGNAL(detectComplete()), SLOT(yubikeyDetectComplete()), Qt::QueuedConnection); connect(YubiKey::instance(), SIGNAL(detectComplete()), SLOT(yubikeyDetectComplete()), Qt::QueuedConnection);
connect(YubiKey::instance(), SIGNAL(notFound()), SLOT(noYubikeyFound()), Qt::QueuedConnection); connect(YubiKey::instance(), SIGNAL(notFound()), SLOT(noYubikeyFound()), Qt::QueuedConnection);
// clang-format on
pollYubikey(); pollYubikey();
m_yubiKeyBeingPolled = true; m_yubiKeyBeingPolled = true;
@ -172,7 +174,7 @@ QSharedPointer<Database> DatabaseOpenWidget::database()
void DatabaseOpenWidget::enterKey(const QString& pw, const QString& keyFile) void DatabaseOpenWidget::enterKey(const QString& pw, const QString& keyFile)
{ {
if (!pw.isNull()) { if (!pw.isEmpty()) {
m_ui->editPassword->setText(pw); m_ui->editPassword->setText(pw);
} }
if (!keyFile.isEmpty()) { if (!keyFile.isEmpty()) {
@ -190,7 +192,7 @@ void DatabaseOpenWidget::openDatabase()
} }
if (!m_ui->editPassword->isPasswordVisible()) { if (!m_ui->editPassword->isPasswordVisible()) {
m_ui->editPassword->setShowPassword(false); m_ui->editPassword->setShowPassword(false);
} }
QCoreApplication::processEvents(); QCoreApplication::processEvents();

View File

@ -94,10 +94,12 @@ QSharedPointer<Database> DatabaseTabWidget::execNewDatabaseWizard()
Q_ASSERT(db->key()); Q_ASSERT(db->key());
Q_ASSERT(db->kdf()); Q_ASSERT(db->kdf());
if (!db->key() || !db->kdf()) { if (!db->key() || !db->kdf()) {
MessageBox::critical(this, tr("Database creation error"), MessageBox::critical(this,
tr("The created database has no key or KDF, refusing to save it.\n" tr("Database creation error"),
"This is definitely a bug, please report it to the developers."), tr("The created database has no key or KDF, refusing to save it.\n"
QMessageBox::Ok, QMessageBox::Ok); "This is definitely a bug, please report it to the developers."),
QMessageBox::Ok,
QMessageBox::Ok);
return {}; return {};
} }
@ -216,7 +218,7 @@ void DatabaseTabWidget::mergeDatabase()
auto dbWidget = currentDatabaseWidget(); auto dbWidget = currentDatabaseWidget();
if (dbWidget && !dbWidget->isLocked()) { if (dbWidget && !dbWidget->isLocked()) {
QString filter = QString("%1 (*.kdbx);;%2 (*)").arg(tr("KeePass 2 Database"), tr("All files")); QString filter = QString("%1 (*.kdbx);;%2 (*)").arg(tr("KeePass 2 Database"), tr("All files"));
const QString fileName = fileDialog()->getOpenFileName(this, tr("Merge database"), "", filter); const QString fileName = fileDialog()->getOpenFileName(this, tr("Merge database"), QString(), filter);
if (!fileName.isEmpty()) { if (!fileName.isEmpty()) {
mergeDatabase(fileName); mergeDatabase(fileName);
} }

View File

@ -50,8 +50,8 @@
#include "gui/EntryPreviewWidget.h" #include "gui/EntryPreviewWidget.h"
#include "gui/KeePass1OpenWidget.h" #include "gui/KeePass1OpenWidget.h"
#include "gui/MessageBox.h" #include "gui/MessageBox.h"
#include "gui/TotpSetupDialog.h"
#include "gui/TotpDialog.h" #include "gui/TotpDialog.h"
#include "gui/TotpSetupDialog.h"
#include "gui/TotpExportSettingsDialog.h" #include "gui/TotpExportSettingsDialog.h"
#include "gui/entry/EditEntryWidget.h" #include "gui/entry/EditEntryWidget.h"
#include "gui/entry/EntryView.h" #include "gui/entry/EntryView.h"
@ -155,6 +155,7 @@ DatabaseWidget::DatabaseWidget(QSharedPointer<Database> db, QWidget* parent)
addChildWidget(m_csvImportWizard); addChildWidget(m_csvImportWizard);
addChildWidget(m_keepass1OpenWidget); addChildWidget(m_keepass1OpenWidget);
// clang-format off
connect(m_mainSplitter, SIGNAL(splitterMoved(int,int)), SIGNAL(mainSplitterSizesChanged())); connect(m_mainSplitter, SIGNAL(splitterMoved(int,int)), SIGNAL(mainSplitterSizesChanged()));
connect(m_previewSplitter, SIGNAL(splitterMoved(int,int)), SIGNAL(previewSplitterSizesChanged())); connect(m_previewSplitter, SIGNAL(splitterMoved(int,int)), SIGNAL(previewSplitterSizesChanged()));
connect(this, SIGNAL(currentModeChanged(DatabaseWidget::Mode)), m_previewView, SLOT(setDatabaseMode(DatabaseWidget::Mode))); connect(this, SIGNAL(currentModeChanged(DatabaseWidget::Mode)), m_previewView, SLOT(setDatabaseMode(DatabaseWidget::Mode)));
@ -177,7 +178,8 @@ DatabaseWidget::DatabaseWidget(QSharedPointer<Database> db, QWidget* parent)
connect(&m_fileWatchTimer, SIGNAL(timeout()), this, SLOT(reloadDatabaseFile())); connect(&m_fileWatchTimer, SIGNAL(timeout()), this, SLOT(reloadDatabaseFile()));
connect(&m_fileWatchUnblockTimer, SIGNAL(timeout()), this, SLOT(unblockAutoReload())); connect(&m_fileWatchUnblockTimer, SIGNAL(timeout()), this, SLOT(unblockAutoReload()));
connect(this, SIGNAL(currentChanged(int)), this, SLOT(emitCurrentModeChanged())); connect(this, SIGNAL(currentChanged(int)), this, SLOT(emitCurrentModeChanged()));
// clang-format on
connectDatabaseSignals(); connectDatabaseSignals();
m_fileWatchTimer.setSingleShot(true); m_fileWatchTimer.setSingleShot(true);

View File

@ -18,6 +18,7 @@
#include "EditWidget.h" #include "EditWidget.h"
#include "ui_EditWidget.h" #include "ui_EditWidget.h"
#include <QPushButton> #include <QPushButton>
#include <QScrollArea> #include <QScrollArea>

View File

@ -31,6 +31,7 @@
#ifdef WITH_XC_NETWORKING #ifdef WITH_XC_NETWORKING
#include <QtNetwork> #include <QtNetwork>
#include <QNetworkAccessManager>
#endif #endif
IconStruct::IconStruct() IconStruct::IconStruct()
@ -44,6 +45,7 @@ EditWidgetIcons::EditWidgetIcons(QWidget* parent)
, m_ui(new Ui::EditWidgetIcons()) , m_ui(new Ui::EditWidgetIcons())
, m_db(nullptr) , m_db(nullptr)
#ifdef WITH_XC_NETWORKING #ifdef WITH_XC_NETWORKING
, m_netMgr(new QNetworkAccessManager(this))
, m_reply(nullptr) , m_reply(nullptr)
#endif #endif
, m_defaultIconModel(new DefaultIconModel(this)) , m_defaultIconModel(new DefaultIconModel(this))
@ -54,6 +56,7 @@ EditWidgetIcons::EditWidgetIcons(QWidget* parent)
m_ui->defaultIconsView->setModel(m_defaultIconModel); m_ui->defaultIconsView->setModel(m_defaultIconModel);
m_ui->customIconsView->setModel(m_customIconModel); m_ui->customIconsView->setModel(m_customIconModel);
// clang-format off
connect(m_ui->defaultIconsView, SIGNAL(clicked(QModelIndex)), this, SLOT(updateRadioButtonDefaultIcons())); connect(m_ui->defaultIconsView, SIGNAL(clicked(QModelIndex)), this, SLOT(updateRadioButtonDefaultIcons()));
connect(m_ui->customIconsView, SIGNAL(clicked(QModelIndex)), this, SLOT(updateRadioButtonCustomIcons())); connect(m_ui->customIconsView, SIGNAL(clicked(QModelIndex)), this, SLOT(updateRadioButtonCustomIcons()));
connect(m_ui->defaultIconsRadio, SIGNAL(toggled(bool)), this, SLOT(updateWidgetsDefaultIcons(bool))); connect(m_ui->defaultIconsRadio, SIGNAL(toggled(bool)), this, SLOT(updateWidgetsDefaultIcons(bool)));
@ -64,14 +67,11 @@ EditWidgetIcons::EditWidgetIcons(QWidget* parent)
connect(m_ui->defaultIconsRadio, SIGNAL(toggled(bool)), this, SIGNAL(widgetUpdated())); connect(m_ui->defaultIconsRadio, SIGNAL(toggled(bool)), this, SIGNAL(widgetUpdated()));
connect(m_ui->defaultIconsRadio, SIGNAL(toggled(bool)), this, SIGNAL(widgetUpdated())); connect(m_ui->defaultIconsRadio, SIGNAL(toggled(bool)), this, SIGNAL(widgetUpdated()));
connect(m_ui->defaultIconsView->selectionModel(), connect(m_ui->defaultIconsView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SIGNAL(widgetUpdated()));
this, connect(m_ui->customIconsView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
SIGNAL(widgetUpdated())); this, SIGNAL(widgetUpdated()));
connect(m_ui->customIconsView->selectionModel(), // clang-format on
SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
this,
SIGNAL(widgetUpdated()));
m_ui->faviconButton->setVisible(false); m_ui->faviconButton->setVisible(false);
m_ui->addButton->setEnabled(true); m_ui->addButton->setEnabled(true);
@ -156,7 +156,8 @@ void EditWidgetIcons::setUrl(const QString& url)
} }
#ifdef WITH_XC_NETWORKING #ifdef WITH_XC_NETWORKING
namespace { namespace
{
// Try to get the 2nd level domain of the host part of a QUrl. For example, // Try to get the 2nd level domain of the host part of a QUrl. For example,
// "foo.bar.example.com" would become "example.com", and "foo.bar.example.co.uk" // "foo.bar.example.com" would become "example.com", and "foo.bar.example.co.uk"
// would become "example.co.uk". // would become "example.co.uk".
@ -173,17 +174,17 @@ namespace {
{ {
QUrl url; QUrl url;
if (var.canConvert<QUrl>()) if (var.canConvert<QUrl>())
url = var.value<QUrl>(); url = var.toUrl();
return url; return url;
} }
QUrl getRedirectTarget(QNetworkReply *reply) QUrl getRedirectTarget(QNetworkReply* reply)
{ {
QVariant var = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); QVariant var = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
QUrl url = convertVariantToUrl(var); QUrl url = convertVariantToUrl(var);
return url; return url;
} }
} } // namespace
#endif #endif
void EditWidgetIcons::downloadFavicon() void EditWidgetIcons::downloadFavicon()
@ -264,9 +265,10 @@ void EditWidgetIcons::fetchFinished()
return; return;
} else { } else {
if (!fallbackEnabled) { if (!fallbackEnabled) {
emit messageEditEntry(tr("Unable to fetch favicon.") + "\n" + emit messageEditEntry(
tr("Hint: You can enable DuckDuckGo as a fallback under Tools>Settings>Security"), tr("Unable to fetch favicon.") + "\n"
MessageWidget::Error); + tr("Hint: You can enable DuckDuckGo as a fallback under Tools>Settings>Security"),
MessageWidget::Error);
} else { } else {
emit messageEditEntry(tr("Unable to fetch favicon."), MessageWidget::Error); emit messageEditEntry(tr("Unable to fetch favicon."), MessageWidget::Error);
} }
@ -294,7 +296,7 @@ void EditWidgetIcons::startFetchFavicon(const QUrl& url)
QNetworkRequest request(url); QNetworkRequest request(url);
m_reply = m_netMgr.get(request); m_reply = m_netMgr->get(request);
connect(m_reply, &QNetworkReply::finished, this, &EditWidgetIcons::fetchFinished); connect(m_reply, &QNetworkReply::finished, this, &EditWidgetIcons::fetchFinished);
connect(m_reply, &QIODevice::readyRead, this, &EditWidgetIcons::fetchReadyRead); connect(m_reply, &QIODevice::readyRead, this, &EditWidgetIcons::fetchReadyRead);
#else #else
@ -339,8 +341,9 @@ void EditWidgetIcons::addCustomIconFromFile()
if (!errornames.empty()) { if (!errornames.empty()) {
// Show the first 8 icons that failed to load // Show the first 8 icons that failed to load
errornames = errornames.mid(0, 8); errornames = errornames.mid(0, 8);
emit messageEditEntry(msg + "\n" + tr("The following icon(s) failed:", "", errornames.size()) + emit messageEditEntry(msg + "\n" + tr("The following icon(s) failed:", "", errornames.size()) + "\n"
"\n" + errornames.join("\n"), MessageWidget::Error); + errornames.join("\n"),
MessageWidget::Error);
} else if (numloaded > 0) { } else if (numloaded > 0) {
emit messageEditEntry(msg, MessageWidget::Positive); emit messageEditEntry(msg, MessageWidget::Positive);
} else { } else {

View File

@ -21,9 +21,8 @@
#include <QSet> #include <QSet>
#include <QUrl> #include <QUrl>
#include <QWidget>
#include <QNetworkAccessManager>
#include <QUuid> #include <QUuid>
#include <QWidget>
#include "config-keepassx.h" #include "config-keepassx.h"
#include "core/Global.h" #include "core/Global.h"
@ -33,6 +32,7 @@ class Database;
class DefaultIconModel; class DefaultIconModel;
class CustomIconModel; class CustomIconModel;
#ifdef WITH_XC_NETWORKING #ifdef WITH_XC_NETWORKING
class QNetworkAccessManager;
class QNetworkReply; class QNetworkReply;
#endif #endif
@ -95,8 +95,8 @@ private:
QUrl m_fetchUrl; QUrl m_fetchUrl;
QList<QUrl> m_urlsToTry; QList<QUrl> m_urlsToTry;
QByteArray m_bytesReceived; QByteArray m_bytesReceived;
QNetworkAccessManager m_netMgr; QNetworkAccessManager* m_netMgr;
QNetworkReply *m_reply; QNetworkReply* m_reply;
int m_redirects; int m_redirects;
#endif #endif
DefaultIconModel* const m_defaultIconModel; DefaultIconModel* const m_defaultIconModel;

View File

@ -16,11 +16,11 @@
*/ */
#include "EditWidgetProperties.h" #include "EditWidgetProperties.h"
#include "ui_EditWidgetProperties.h"
#include <QUuid>
#include "MessageBox.h" #include "MessageBox.h"
#include "ui_EditWidgetProperties.h"
#include <QUuid>
EditWidgetProperties::EditWidgetProperties(QWidget* parent) EditWidgetProperties::EditWidgetProperties(QWidget* parent)
: QWidget(parent) : QWidget(parent)
@ -32,9 +32,11 @@ EditWidgetProperties::EditWidgetProperties(QWidget* parent)
m_ui->removeCustomDataButton->setEnabled(false); m_ui->removeCustomDataButton->setEnabled(false);
m_ui->customDataTable->setModel(m_customDataModel); m_ui->customDataTable->setModel(m_customDataModel);
// clang-format off
connect(m_ui->customDataTable->selectionModel(), connect(m_ui->customDataTable->selectionModel(),
SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
SLOT(toggleRemoveButton(QItemSelection))); SLOT(toggleRemoveButton(QItemSelection)));
// clang-format on
connect(m_ui->removeCustomDataButton, SIGNAL(clicked()), SLOT(removeSelectedPluginData())); connect(m_ui->removeCustomDataButton, SIGNAL(clicked()), SLOT(removeSelectedPluginData()));
} }
@ -66,12 +68,13 @@ const CustomData* EditWidgetProperties::customData() const
void EditWidgetProperties::removeSelectedPluginData() void EditWidgetProperties::removeSelectedPluginData()
{ {
if (QMessageBox::Yes != MessageBox::question(this, if (QMessageBox::Yes
tr("Delete plugin data?"), != MessageBox::question(this,
tr("Do you really want to delete the selected plugin data?\n" tr("Delete plugin data?"),
"This may cause the affected plugins to malfunction."), tr("Do you really want to delete the selected plugin data?\n"
QMessageBox::Yes | QMessageBox::Cancel, "This may cause the affected plugins to malfunction."),
QMessageBox::Cancel)) { QMessageBox::Yes | QMessageBox::Cancel,
QMessageBox::Cancel)) {
return; return;
} }
@ -97,8 +100,8 @@ void EditWidgetProperties::updateModel()
m_customDataModel->setHorizontalHeaderLabels({tr("Key"), tr("Value")}); m_customDataModel->setHorizontalHeaderLabels({tr("Key"), tr("Value")});
for (const QString& key : m_customData->keys()) { for (const QString& key : m_customData->keys()) {
m_customDataModel->appendRow(QList<QStandardItem*>() << new QStandardItem(key) m_customDataModel->appendRow(QList<QStandardItem*>()
<< new QStandardItem(m_customData->value(key))); << new QStandardItem(key) << new QStandardItem(m_customData->value(key)));
} }
m_ui->removeCustomDataButton->setEnabled(false); m_ui->removeCustomDataButton->setEnabled(false);

View File

@ -220,7 +220,7 @@ void EntryPreviewWidget::updateEntryAttributesTab()
m_ui->entryAttributesEdit->clear(); m_ui->entryAttributesEdit->clear();
const EntryAttributes* attributes = m_currentEntry->attributes(); const EntryAttributes* attributes = m_currentEntry->attributes();
const QStringList customAttributes = attributes->customKeys(); const QStringList customAttributes = attributes->customKeys();
const bool haveAttributes = customAttributes.size() > 0; const bool haveAttributes = !customAttributes.isEmpty();
setTabEnabled(m_ui->entryTabWidget, m_ui->entryAttributesTab, haveAttributes); setTabEnabled(m_ui->entryTabWidget, m_ui->entryAttributesTab, haveAttributes);
if (haveAttributes) { if (haveAttributes) {
QString attributesText; QString attributesText;

View File

@ -287,7 +287,6 @@ void KMessageWidget::setMessageType(KMessageWidget::MessageType type)
// Tint close icon // Tint close icon
auto closeButtonPixmap = d->closeButtonPixmap; auto closeButtonPixmap = d->closeButtonPixmap;
QPixmap mask(closeButtonPixmap);
QPainter painter; QPainter painter;
painter.begin(&closeButtonPixmap); painter.begin(&closeButtonPixmap);
painter.setRenderHints(QPainter::HighQualityAntialiasing); painter.setRenderHints(QPainter::HighQualityAntialiasing);

View File

@ -16,6 +16,7 @@
*/ */
#include "KeePass1OpenWidget.h" #include "KeePass1OpenWidget.h"
#include "ui_DatabaseOpenWidget.h"
#include <QFile> #include <QFile>
#include <QFileInfo> #include <QFileInfo>
@ -24,7 +25,6 @@
#include "core/Metadata.h" #include "core/Metadata.h"
#include "format/KeePass1Reader.h" #include "format/KeePass1Reader.h"
#include "gui/MessageBox.h" #include "gui/MessageBox.h"
#include "ui_DatabaseOpenWidget.h"
KeePass1OpenWidget::KeePass1OpenWidget(QWidget* parent) KeePass1OpenWidget::KeePass1OpenWidget(QWidget* parent)
: DatabaseOpenWidget(parent) : DatabaseOpenWidget(parent)

View File

@ -20,10 +20,10 @@
#include "ui_MainWindow.h" #include "ui_MainWindow.h"
#include <QCloseEvent> #include <QCloseEvent>
#include <QDesktopServices>
#include <QMimeData> #include <QMimeData>
#include <QShortcut> #include <QShortcut>
#include <QTimer> #include <QTimer>
#include <QDesktopServices>
#include "config-keepassx.h" #include "config-keepassx.h"
@ -56,8 +56,8 @@
#include <QtDBus/QtDBus> #include <QtDBus/QtDBus>
#endif #endif
#include "gui/PasswordGeneratorWidget.h"
#include "gui/ApplicationSettingsWidget.h" #include "gui/ApplicationSettingsWidget.h"
#include "gui/PasswordGeneratorWidget.h"
#include "touchid/TouchID.h" #include "touchid/TouchID.h"
@ -67,7 +67,8 @@ class BrowserPlugin : public ISettingsPage
public: public:
BrowserPlugin(DatabaseTabWidget* tabWidget) BrowserPlugin(DatabaseTabWidget* tabWidget)
{ {
m_nativeMessagingHost = QSharedPointer<NativeMessagingHost>(new NativeMessagingHost(tabWidget, browserSettings()->isEnabled())); m_nativeMessagingHost =
QSharedPointer<NativeMessagingHost>(new NativeMessagingHost(tabWidget, browserSettings()->isEnabled()));
} }
~BrowserPlugin() ~BrowserPlugin()
@ -105,8 +106,8 @@ public:
} }
} }
private: private:
QSharedPointer<NativeMessagingHost> m_nativeMessagingHost; QSharedPointer<NativeMessagingHost> m_nativeMessagingHost;
}; };
#endif #endif
@ -346,11 +347,13 @@ MainWindow::MainWindow()
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
setUnifiedTitleAndToolBarOnMac(true); setUnifiedTitleAndToolBarOnMac(true);
#endif #endif
// clang-format off
connect(m_ui->tabWidget, connect(m_ui->tabWidget,
SIGNAL(messageGlobal(QString,MessageWidget::MessageType)), SIGNAL(messageGlobal(QString,MessageWidget::MessageType)),
this, this,
SLOT(displayGlobalMessage(QString,MessageWidget::MessageType))); SLOT(displayGlobalMessage(QString,MessageWidget::MessageType)));
// clang-format on
connect(m_ui->tabWidget, SIGNAL(messageDismissGlobal()), this, SLOT(hideGlobalMessage())); connect(m_ui->tabWidget, SIGNAL(messageDismissGlobal()), this, SLOT(hideGlobalMessage()));
m_screenLockListener = new ScreenLockListener(this); m_screenLockListener = new ScreenLockListener(this);
@ -368,13 +371,15 @@ MainWindow::MainWindow()
tr("WARNING: You are using an unstable build of KeePassXC!\n" tr("WARNING: You are using an unstable build of KeePassXC!\n"
"There is a high risk of corruption, maintain a backup of your databases.\n" "There is a high risk of corruption, maintain a backup of your databases.\n"
"This version is not meant for production use."), "This version is not meant for production use."),
MessageWidget::Warning, -1); MessageWidget::Warning,
-1);
#elif (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0) && QT_VERSION < QT_VERSION_CHECK(5, 6, 0)) #elif (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0) && QT_VERSION < QT_VERSION_CHECK(5, 6, 0))
if (!config()->get("QtErrorMessageShown", false).toBool()) { if (!config()->get("QtErrorMessageShown", false).toBool()) {
m_ui->globalMessageWidget->showMessage( m_ui->globalMessageWidget->showMessage(
tr("WARNING: Your Qt version may cause KeePassXC to crash with an On-Screen Keyboard!\n" tr("WARNING: Your Qt version may cause KeePassXC to crash with an On-Screen Keyboard!\n"
"We recommend you use the AppImage available on our downloads page."), "We recommend you use the AppImage available on our downloads page."),
MessageWidget::Warning, -1); MessageWidget::Warning,
-1);
config()->set("QtErrorMessageShown", true); config()->set("QtErrorMessageShown", true);
} }
#endif #endif
@ -671,10 +676,10 @@ void MainWindow::switchToSettings(bool enabled)
void MainWindow::switchToPasswordGen(bool enabled) void MainWindow::switchToPasswordGen(bool enabled)
{ {
if (enabled) { if (enabled) {
m_ui->passwordGeneratorWidget->loadSettings(); m_ui->passwordGeneratorWidget->loadSettings();
m_ui->passwordGeneratorWidget->regeneratePassword(); m_ui->passwordGeneratorWidget->regeneratePassword();
m_ui->passwordGeneratorWidget->setStandaloneMode(true); m_ui->passwordGeneratorWidget->setStandaloneMode(true);
m_ui->stackedWidget->setCurrentIndex(PasswordGeneratorScreen); m_ui->stackedWidget->setCurrentIndex(PasswordGeneratorScreen);
} else { } else {
m_ui->passwordGeneratorWidget->saveSettings(); m_ui->passwordGeneratorWidget->saveSettings();
switchToDatabases(); switchToDatabases();

View File

@ -71,8 +71,9 @@ void PasswordEdit::setShowPassword(bool show)
emit showPasswordChanged(show); emit showPasswordChanged(show);
} }
bool PasswordEdit::isPasswordVisible() const { bool PasswordEdit::isPasswordVisible() const
return isEnabled(); {
return isEnabled();
} }
bool PasswordEdit::passwordsEqual() const bool PasswordEdit::passwordsEqual() const

View File

@ -338,10 +338,8 @@ void PasswordGeneratorWidget::selectSimpleMode()
m_ui->checkBoxLower->setChecked(m_ui->checkBoxLowerAdv->isChecked()); m_ui->checkBoxLower->setChecked(m_ui->checkBoxLowerAdv->isChecked());
m_ui->checkBoxNumbers->setChecked(m_ui->checkBoxNumbersAdv->isChecked()); m_ui->checkBoxNumbers->setChecked(m_ui->checkBoxNumbersAdv->isChecked());
m_ui->checkBoxSpecialChars->setChecked(m_ui->checkBoxBraces->isChecked() | m_ui->checkBoxPunctuation->isChecked() m_ui->checkBoxSpecialChars->setChecked(m_ui->checkBoxBraces->isChecked() | m_ui->checkBoxPunctuation->isChecked()
| m_ui->checkBoxQuotes->isChecked() | m_ui->checkBoxQuotes->isChecked() | m_ui->checkBoxMath->isChecked()
| m_ui->checkBoxMath->isChecked() | m_ui->checkBoxDashes->isChecked() | m_ui->checkBoxLogograms->isChecked());
| m_ui->checkBoxDashes->isChecked()
| m_ui->checkBoxLogograms->isChecked());
m_ui->checkBoxExtASCII->setChecked(m_ui->checkBoxExtASCIIAdv->isChecked()); m_ui->checkBoxExtASCII->setChecked(m_ui->checkBoxExtASCIIAdv->isChecked());
m_ui->simpleBar->show(); m_ui->simpleBar->show();
} }

View File

@ -17,9 +17,10 @@
*/ */
#include "TotpSetupDialog.h" #include "TotpSetupDialog.h"
#include "totp/totp.h"
#include "ui_TotpSetupDialog.h" #include "ui_TotpSetupDialog.h"
#include "totp/totp.h"
TotpSetupDialog::TotpSetupDialog(QWidget* parent, Entry* entry) TotpSetupDialog::TotpSetupDialog(QWidget* parent, Entry* entry)
: QDialog(parent) : QDialog(parent)
, m_ui(new Ui::TotpSetupDialog()) , m_ui(new Ui::TotpSetupDialog())

View File

@ -40,7 +40,7 @@ CsvImportWidget::CsvImportWidget(QWidget* parent)
, m_columnHeader(QStringList() << QObject::tr("Group") << QObject::tr("Title") << QObject::tr("Username") , m_columnHeader(QStringList() << QObject::tr("Group") << QObject::tr("Title") << QObject::tr("Username")
<< QObject::tr("Password") << QObject::tr("URL") << QObject::tr("Notes") << QObject::tr("Password") << QObject::tr("URL") << QObject::tr("Notes")
<< QObject::tr("Last Modified") << QObject::tr("Created") << QObject::tr("Last Modified") << QObject::tr("Created")
/* << QObject::tr("Future field1") */ ) /* << QObject::tr("Future field1") */)
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
@ -87,9 +87,11 @@ CsvImportWidget::CsvImportWidget(QWidget* parent)
m_combos.append(combo); m_combos.append(combo);
combo->setModel(m_comboModel); combo->setModel(m_comboModel);
#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) #if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), [=]{ comboChanged(combo, i); }); connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), [=] { comboChanged(combo, i); });
#else #else
connect(combo, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=]{ comboChanged(combo, i); }); connect(combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=] {
comboChanged(combo, i);
});
#endif #endif
// layout labels and combo fields in column-first order // layout labels and combo fields in column-first order

View File

@ -42,7 +42,6 @@ void CsvImportWizard::load(const QString& filename, Database* database)
m_parse->load(filename, database); m_parse->load(filename, database);
} }
void CsvImportWizard::parseFinished(bool accepted) void CsvImportWizard::parseFinished(bool accepted)
{ {
emit importFinished(accepted); emit importFinished(accepted);

View File

@ -18,16 +18,17 @@
#include "DatabaseSettingsDialog.h" #include "DatabaseSettingsDialog.h"
#include "ui_DatabaseSettingsDialog.h" #include "ui_DatabaseSettingsDialog.h"
#include "DatabaseSettingsWidgetGeneral.h"
#include "DatabaseSettingsWidgetEncryption.h" #include "DatabaseSettingsWidgetEncryption.h"
#include "DatabaseSettingsWidgetGeneral.h"
#include "DatabaseSettingsWidgetMasterKey.h" #include "DatabaseSettingsWidgetMasterKey.h"
#ifdef WITH_XC_BROWSER #ifdef WITH_XC_BROWSER
#include "DatabaseSettingsWidgetBrowser.h" #include "DatabaseSettingsWidgetBrowser.h"
#endif #endif
#include "core/Config.h" #include "core/Config.h"
#include "core/FilePath.h"
#include "core/Database.h" #include "core/Database.h"
#include "core/FilePath.h"
#include "touchid/TouchID.h" #include "touchid/TouchID.h"
DatabaseSettingsDialog::DatabaseSettingsDialog(QWidget* parent) DatabaseSettingsDialog::DatabaseSettingsDialog(QWidget* parent)
@ -57,12 +58,13 @@ DatabaseSettingsDialog::DatabaseSettingsDialog(QWidget* parent)
m_ui->stackedWidget->setCurrentIndex(0); m_ui->stackedWidget->setCurrentIndex(0);
m_securityTabWidget->setCurrentIndex(0); m_securityTabWidget->setCurrentIndex(0);
connect(m_securityTabWidget, SIGNAL(currentChanged(int)), SLOT(pageChanged())); connect(m_securityTabWidget, SIGNAL(currentChanged(int)), SLOT(pageChanged()));
connect(m_ui->categoryList, SIGNAL(categoryChanged(int)), m_ui->stackedWidget, SLOT(setCurrentIndex(int))); connect(m_ui->categoryList, SIGNAL(categoryChanged(int)), m_ui->stackedWidget, SLOT(setCurrentIndex(int)));
connect(m_ui->advancedSettingsToggle, SIGNAL(toggled(bool)), SLOT(toggleAdvancedMode(bool))); connect(m_ui->advancedSettingsToggle, SIGNAL(toggled(bool)), SLOT(toggleAdvancedMode(bool)));
#ifdef WITH_XC_BROWSER #ifdef WITH_XC_BROWSER
m_ui->categoryList->addCategory(tr("Browser Integration"), FilePath::instance()->icon("apps", "internet-web-browser")); m_ui->categoryList->addCategory(tr("Browser Integration"),
FilePath::instance()->icon("apps", "internet-web-browser"));
m_ui->stackedWidget->addWidget(m_browserWidget); m_ui->stackedWidget->addWidget(m_browserWidget);
#endif #endif

View File

@ -18,8 +18,8 @@
#ifndef KEEPASSX_DATABASESETTINGSWIDGET_H #ifndef KEEPASSX_DATABASESETTINGSWIDGET_H
#define KEEPASSX_DATABASESETTINGSWIDGET_H #define KEEPASSX_DATABASESETTINGSWIDGET_H
#include "gui/DialogyWidget.h"
#include "config-keepassx.h" #include "config-keepassx.h"
#include "gui/DialogyWidget.h"
#include <QPointer> #include <QPointer>
#include <QScopedPointer> #include <QScopedPointer>

View File

@ -18,8 +18,8 @@
#include "DatabaseSettingsWidget.h" #include "DatabaseSettingsWidget.h"
#include "core/Database.h" #include "core/Database.h"
#include <QWidget>
#include <QTimer> #include <QTimer>
#include <QWidget>
DatabaseSettingsWidget::DatabaseSettingsWidget(QWidget* parent) DatabaseSettingsWidget::DatabaseSettingsWidget(QWidget* parent)
: SettingsWidget(parent) : SettingsWidget(parent)

View File

@ -48,4 +48,4 @@ protected:
QSharedPointer<Database> m_db; QSharedPointer<Database> m_db;
}; };
#endif //KEEPASSXC_DATABASESETTINGSWIDGET_H #endif // KEEPASSXC_DATABASESETTINGSWIDGET_H

View File

@ -17,18 +17,21 @@
*/ */
#include "DatabaseSettingsWidgetBrowser.h" #include "DatabaseSettingsWidgetBrowser.h"
#include "ui_DatabaseSettingsWidgetBrowser.h"
#include <QProgressDialog> #include <QProgressDialog>
#include "browser/BrowserSettings.h"
#include "core/Clock.h" #include "core/Clock.h"
#include "core/Database.h" #include "core/Database.h"
#include "core/Entry.h" #include "core/Entry.h"
#include "core/Group.h" #include "core/Group.h"
#include "core/Metadata.h" #include "core/Metadata.h"
#include "gui/MessageBox.h" #include "gui/MessageBox.h"
#include "browser/BrowserSettings.h"
#include "ui_DatabaseSettingsWidgetBrowser.h"
DatabaseSettingsWidgetBrowser::DatabaseSettingsWidgetBrowser(QWidget* parent) DatabaseSettingsWidgetBrowser::DatabaseSettingsWidgetBrowser(QWidget* parent)
: DatabaseSettingsWidget(parent), m_ui(new Ui::DatabaseSettingsWidgetBrowser()) : DatabaseSettingsWidget(parent)
, m_ui(new Ui::DatabaseSettingsWidgetBrowser())
, m_customData(new CustomData(this)) , m_customData(new CustomData(this))
, m_customDataModel(new QStandardItemModel(this)) , m_customDataModel(new QStandardItemModel(this))
, m_browserService(nullptr) , m_browserService(nullptr)
@ -38,8 +41,13 @@ DatabaseSettingsWidgetBrowser::DatabaseSettingsWidgetBrowser(QWidget* parent)
m_ui->customDataTable->setModel(m_customDataModel); m_ui->customDataTable->setModel(m_customDataModel);
settingsWarning(); settingsWarning();
connect(m_ui->customDataTable->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
// clang-format off
connect(m_ui->customDataTable->selectionModel(),
SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
SLOT(toggleRemoveButton(QItemSelection))); SLOT(toggleRemoveButton(QItemSelection)));
// clang-format on
connect(m_ui->removeCustomDataButton, SIGNAL(clicked()), SLOT(removeSelectedKey())); connect(m_ui->removeCustomDataButton, SIGNAL(clicked()), SLOT(removeSelectedKey()));
connect(m_ui->convertToCustomData, SIGNAL(clicked()), this, SLOT(convertAttributesToCustomData())); connect(m_ui->convertToCustomData, SIGNAL(clicked()), this, SLOT(convertAttributesToCustomData()));
connect(m_ui->convertToCustomData, SIGNAL(clicked()), this, SLOT(updateSharedKeyList())); connect(m_ui->convertToCustomData, SIGNAL(clicked()), this, SLOT(updateSharedKeyList()));
@ -83,11 +91,13 @@ bool DatabaseSettingsWidgetBrowser::save()
void DatabaseSettingsWidgetBrowser::removeSelectedKey() void DatabaseSettingsWidgetBrowser::removeSelectedKey()
{ {
if (QMessageBox::Yes != MessageBox::question(this, if (QMessageBox::Yes
tr("Delete the selected key?"), != MessageBox::question(this,
tr("Do you really want to delete the selected key?\n" tr("Delete the selected key?"),
"This may prevent connection to the browser plugin."), tr("Do you really want to delete the selected key?\n"
QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel)) { "This may prevent connection to the browser plugin."),
QMessageBox::Yes | QMessageBox::Cancel,
QMessageBox::Cancel)) {
return; return;
} }
@ -116,9 +126,8 @@ void DatabaseSettingsWidgetBrowser::updateModel()
if (key.startsWith(BrowserService::ASSOCIATE_KEY_PREFIX)) { if (key.startsWith(BrowserService::ASSOCIATE_KEY_PREFIX)) {
QString strippedKey = key; QString strippedKey = key;
strippedKey.remove(BrowserService::ASSOCIATE_KEY_PREFIX); strippedKey.remove(BrowserService::ASSOCIATE_KEY_PREFIX);
m_customDataModel->appendRow(QList<QStandardItem*>() m_customDataModel->appendRow(QList<QStandardItem*>() << new QStandardItem(strippedKey)
<< new QStandardItem(strippedKey) << new QStandardItem(customData()->value(key)));
<< new QStandardItem(customData()->value(key)));
} }
} }
@ -132,7 +141,8 @@ void DatabaseSettingsWidgetBrowser::settingsWarning()
m_ui->removeSharedEncryptionKeys->setEnabled(false); m_ui->removeSharedEncryptionKeys->setEnabled(false);
m_ui->removeStoredPermissions->setEnabled(false); m_ui->removeStoredPermissions->setEnabled(false);
m_ui->customDataTable->setEnabled(false); m_ui->customDataTable->setEnabled(false);
m_ui->warningWidget->showMessage(tr("Enable Browser Integration to access these settings."), MessageWidget::Warning); m_ui->warningWidget->showMessage(tr("Enable Browser Integration to access these settings."),
MessageWidget::Warning);
m_ui->warningWidget->setCloseButtonVisible(false); m_ui->warningWidget->setCloseButtonVisible(false);
m_ui->warningWidget->setAutoHideTimeout(-1); m_ui->warningWidget->setAutoHideTimeout(-1);
} else { } else {
@ -146,11 +156,13 @@ void DatabaseSettingsWidgetBrowser::settingsWarning()
void DatabaseSettingsWidgetBrowser::removeSharedEncryptionKeys() void DatabaseSettingsWidgetBrowser::removeSharedEncryptionKeys()
{ {
if (QMessageBox::Yes != MessageBox::question(this, if (QMessageBox::Yes
tr("Disconnect all browsers"), != MessageBox::question(this,
tr("Do you really want to disconnect all browsers?\n" tr("Disconnect all browsers"),
"This may prevent connection to the browser plugin."), tr("Do you really want to disconnect all browsers?\n"
QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel)) { "This may prevent connection to the browser plugin."),
QMessageBox::Yes | QMessageBox::Cancel,
QMessageBox::Cancel)) {
return; return;
} }
@ -182,11 +194,13 @@ void DatabaseSettingsWidgetBrowser::removeSharedEncryptionKeys()
void DatabaseSettingsWidgetBrowser::removeStoredPermissions() void DatabaseSettingsWidgetBrowser::removeStoredPermissions()
{ {
if (QMessageBox::Yes != MessageBox::question(this, if (QMessageBox::Yes
tr("Forget all site-specific settings on entries"), != MessageBox::question(this,
tr("Do you really want forget all site-specific settings on every entry?\n" tr("Forget all site-specific settings on entries"),
"Permissions to access entries will be revoked."), tr("Do you really want forget all site-specific settings on every entry?\n"
QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel)) { "Permissions to access entries will be revoked."),
QMessageBox::Yes | QMessageBox::Cancel,
QMessageBox::Cancel)) {
return; return;
} }
@ -226,11 +240,14 @@ void DatabaseSettingsWidgetBrowser::removeStoredPermissions()
void DatabaseSettingsWidgetBrowser::convertAttributesToCustomData() void DatabaseSettingsWidgetBrowser::convertAttributesToCustomData()
{ {
if (QMessageBox::Yes != MessageBox::question(this, if (QMessageBox::Yes
tr("Move KeePassHTTP attributes to custom data"), != MessageBox::question(
tr("Do you really want to move all legacy browser integration data to the latest standard?\n" this,
"This is necessary to maintain compatibility with the browser plugin."), tr("Move KeePassHTTP attributes to custom data"),
QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel)) { tr("Do you really want to move all legacy browser integration data to the latest standard?\n"
"This is necessary to maintain compatibility with the browser plugin."),
QMessageBox::Yes | QMessageBox::Cancel,
QMessageBox::Cancel)) {
return; return;
} }
@ -242,4 +259,3 @@ void DatabaseSettingsWidgetBrowser::updateSharedKeyList()
{ {
updateModel(); updateModel();
} }

Some files were not shown because too many files have changed in this diff Show More