mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
Merge pull request #2443 from brainplot/code-cleanup
Code cleanup and performance improvements - Part 2
This commit is contained in:
commit
c66f293f1e
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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();
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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. "
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,8 @@
|
|||||||
|
|
||||||
class Database;
|
class Database;
|
||||||
class Group;
|
class Group;
|
||||||
namespace Totp {
|
namespace Totp
|
||||||
|
{
|
||||||
struct Settings;
|
struct Settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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";
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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());
|
||||||
|
@ -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)
|
||||||
};
|
};
|
||||||
|
@ -124,7 +124,6 @@ bool PasswordGenerator::isValid() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
return !passwordGroups().isEmpty();
|
return !passwordGroups().isEmpty();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<PasswordGroup> PasswordGenerator::passwordGroups() const
|
QVector<PasswordGroup> PasswordGenerator::passwordGroups() const
|
||||||
|
@ -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");
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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()));
|
||||||
|
@ -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));
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
@ -25,7 +25,7 @@ namespace Ui
|
|||||||
{
|
{
|
||||||
class ApplicationSettingsWidgetGeneral;
|
class ApplicationSettingsWidgetGeneral;
|
||||||
class ApplicationSettingsWidgetSecurity;
|
class ApplicationSettingsWidgetSecurity;
|
||||||
}
|
} // namespace Ui
|
||||||
|
|
||||||
class ISettingsPage
|
class ISettingsPage
|
||||||
{
|
{
|
||||||
|
@ -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()
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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())
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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)
|
||||||
|
@ -48,4 +48,4 @@ protected:
|
|||||||
QSharedPointer<Database> m_db;
|
QSharedPointer<Database> m_db;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //KEEPASSXC_DATABASESETTINGSWIDGET_H
|
#endif // KEEPASSXC_DATABASESETTINGSWIDGET_H
|
||||||
|
@ -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
Loading…
Reference in New Issue
Block a user