mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-12-28 16:59:44 -05:00
commit
dd246f1ff0
@ -30,7 +30,7 @@ BraceWrapping:
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: true
|
||||
|
7
.github/CONTRIBUTING.md
vendored
7
.github/CONTRIBUTING.md
vendored
@ -108,9 +108,12 @@ The Branch Strategy is based on [git-flow-lite](http://nvie.com/posts/a-successf
|
||||
|
||||
### Coding styleguide
|
||||
|
||||
This project follows the [Qt Coding Style](https://wiki.qt.io/Qt_Coding_Style). All submissions are expected to follow this style.
|
||||
The coding style of the project is enforced using llvm's `clang-format` formatting tool. A thorough description
|
||||
of the coding style can be found in the `.clang-format` file, but the main conventions are presented here.
|
||||
|
||||
In particular, code must stick to the following rules:
|
||||
Formatting can be performed automatically by calling `make format` from the `build/` directory.
|
||||
|
||||
Note that [formatting can be disabled on a piece of code](https://clang.llvm.org/docs/ClangFormatStyleOptions.html#disabling-formatting-on-a-piece-of-code) if manual formatting is deemed more readable.
|
||||
|
||||
#### Naming convention
|
||||
`lowerCamelCase`
|
||||
|
@ -279,6 +279,8 @@ if(WITH_TESTS)
|
||||
enable_testing()
|
||||
endif(WITH_TESTS)
|
||||
|
||||
include(CLangFormat)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(Qt5 COMPONENTS Core Network Concurrent Widgets Test LinguistTools DBus REQUIRED)
|
||||
elseif(APPLE)
|
||||
|
60
cmake/CLangFormat.cmake
Normal file
60
cmake/CLangFormat.cmake
Normal file
@ -0,0 +1,60 @@
|
||||
# Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 2 or (at your option)
|
||||
# version 3 of the License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
set(EXCLUDED_DIRS
|
||||
# third-party directories
|
||||
zxcvbn/
|
||||
streams/QtIOCompressor
|
||||
# objective-c directories
|
||||
autotype/mac
|
||||
)
|
||||
|
||||
set(EXCLUDED_FILES
|
||||
# third-party files
|
||||
streams/qtiocompressor.cpp
|
||||
streams/qtiocompressor.h
|
||||
gui/KMessageWidget.h
|
||||
gui/KMessageWidget.cpp
|
||||
gui/MainWindowAdaptor.h
|
||||
gui/MainWindowAdaptor.cpp
|
||||
sshagent/bcrypt_pbkdf.cpp
|
||||
sshagent/blf.h
|
||||
sshagent/blowfish.c
|
||||
tests/modeltest.cpp
|
||||
tests/modeltest.h
|
||||
# objective-c files
|
||||
core/ScreenLockListenerMac.h
|
||||
core/ScreenLockListenerMac.cpp
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h)
|
||||
foreach (SOURCE_FILE ${ALL_SOURCE_FILES})
|
||||
foreach (EXCLUDED_DIR ${EXCLUDED_DIRS})
|
||||
string(FIND ${SOURCE_FILE} ${EXCLUDED_DIR} SOURCE_FILE_EXCLUDED)
|
||||
if (NOT ${SOURCE_FILE_EXCLUDED} EQUAL -1)
|
||||
list(REMOVE_ITEM ALL_SOURCE_FILES ${SOURCE_FILE})
|
||||
endif ()
|
||||
endforeach ()
|
||||
foreach (EXCLUDED_FILE ${EXCLUDED_FILES})
|
||||
if (${SOURCE_FILE} MATCHES ".*${EXCLUDED_FILE}$")
|
||||
list(REMOVE_ITEM ALL_SOURCE_FILES ${SOURCE_FILE})
|
||||
endif ()
|
||||
endforeach ()
|
||||
endforeach ()
|
||||
|
||||
add_custom_target(
|
||||
format
|
||||
COMMAND echo ${ALL_SOURCE_FILES} | xargs clang-format -style=file -i
|
||||
)
|
@ -20,7 +20,7 @@
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPluginLoader>
|
||||
#include <QRegularExpression>
|
||||
#include <QRegularExpression>
|
||||
|
||||
#include "config-keepassx.h"
|
||||
|
||||
@ -304,8 +304,8 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
|
||||
auto* msgBox = new QMessageBox();
|
||||
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||
msgBox->setWindowTitle(tr("Auto-Type - KeePassXC"));
|
||||
msgBox->setText(tr("Couldn't find an entry that matches the window title:").append("\n\n")
|
||||
.append(windowTitle));
|
||||
msgBox->setText(
|
||||
tr("Couldn't find an entry that matches the window title:").append("\n\n").append(windowTitle));
|
||||
msgBox->setIcon(QMessageBox::Information);
|
||||
msgBox->setStandardButtons(QMessageBox::Ok);
|
||||
msgBox->show();
|
||||
@ -323,8 +323,7 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
|
||||
auto* selectDialog = new AutoTypeSelectDialog();
|
||||
|
||||
// connect slots, both of which must unlock the m_inGlobalAutoTypeDialog mutex
|
||||
connect(selectDialog, SIGNAL(matchActivated(AutoTypeMatch)),
|
||||
SLOT(performAutoTypeFromGlobal(AutoTypeMatch)));
|
||||
connect(selectDialog, SIGNAL(matchActivated(AutoTypeMatch)), SLOT(performAutoTypeFromGlobal(AutoTypeMatch)));
|
||||
connect(selectDialog, SIGNAL(rejected()), SLOT(autoTypeRejectedFromGlobal()));
|
||||
|
||||
selectDialog->setMatchList(matchList);
|
||||
@ -449,11 +448,11 @@ QList<AutoTypeAction*> AutoType::createActionFromTemplate(const QString& tmpl, c
|
||||
list.append(new AutoTypeKey(Qt::Key_Left));
|
||||
} else if (tmplName.compare("right", Qt::CaseInsensitive) == 0) {
|
||||
list.append(new AutoTypeKey(Qt::Key_Right));
|
||||
} else if (tmplName.compare("insert", Qt::CaseInsensitive) == 0 ||
|
||||
tmplName.compare("ins", Qt::CaseInsensitive) == 0) {
|
||||
} else if (tmplName.compare("insert", Qt::CaseInsensitive) == 0
|
||||
|| tmplName.compare("ins", Qt::CaseInsensitive) == 0) {
|
||||
list.append(new AutoTypeKey(Qt::Key_Insert));
|
||||
} else if (tmplName.compare("delete", Qt::CaseInsensitive) == 0 ||
|
||||
tmplName.compare("del", Qt::CaseInsensitive) == 0) {
|
||||
} else if (tmplName.compare("delete", Qt::CaseInsensitive) == 0
|
||||
|| tmplName.compare("del", Qt::CaseInsensitive) == 0) {
|
||||
list.append(new AutoTypeKey(Qt::Key_Delete));
|
||||
} else if (tmplName.compare("home", Qt::CaseInsensitive) == 0) {
|
||||
list.append(new AutoTypeKey(Qt::Key_Home));
|
||||
@ -463,8 +462,9 @@ QList<AutoTypeAction*> AutoType::createActionFromTemplate(const QString& tmpl, c
|
||||
list.append(new AutoTypeKey(Qt::Key_PageUp));
|
||||
} else if (tmplName.compare("pgdown", Qt::CaseInsensitive) == 0) {
|
||||
list.append(new AutoTypeKey(Qt::Key_PageDown));
|
||||
} else if (tmplName.compare("backspace", Qt::CaseInsensitive) == 0 ||
|
||||
tmplName.compare("bs", Qt::CaseInsensitive) == 0 || tmplName.compare("bksp", Qt::CaseInsensitive) == 0) {
|
||||
} else if (tmplName.compare("backspace", Qt::CaseInsensitive) == 0
|
||||
|| tmplName.compare("bs", Qt::CaseInsensitive) == 0
|
||||
|| tmplName.compare("bksp", Qt::CaseInsensitive) == 0) {
|
||||
list.append(new AutoTypeKey(Qt::Key_Backspace));
|
||||
} else if (tmplName.compare("break", Qt::CaseInsensitive) == 0) {
|
||||
list.append(new AutoTypeKey(Qt::Key_Pause));
|
||||
@ -591,13 +591,13 @@ QList<QString> AutoType::autoTypeSequences(const Entry* entry, const QString& wi
|
||||
}
|
||||
}
|
||||
|
||||
if (config()->get("AutoTypeEntryTitleMatch").toBool() &&
|
||||
windowMatchesTitle(windowTitle, entry->resolvePlaceholder(entry->title()))) {
|
||||
if (config()->get("AutoTypeEntryTitleMatch").toBool()
|
||||
&& windowMatchesTitle(windowTitle, entry->resolvePlaceholder(entry->title()))) {
|
||||
sequenceList.append(entry->effectiveAutoTypeSequence());
|
||||
}
|
||||
|
||||
if (config()->get("AutoTypeEntryURLMatch").toBool() &&
|
||||
windowMatchesUrl(windowTitle, entry->resolvePlaceholder(entry->url()))) {
|
||||
if (config()->get("AutoTypeEntryURLMatch").toBool()
|
||||
&& windowMatchesUrl(windowTitle, entry->resolvePlaceholder(entry->url()))) {
|
||||
sequenceList.append(entry->effectiveAutoTypeSequence());
|
||||
}
|
||||
|
||||
@ -605,7 +605,7 @@ QList<QString> AutoType::autoTypeSequences(const Entry* entry, const QString& wi
|
||||
return sequenceList;
|
||||
}
|
||||
} else {
|
||||
sequenceList.append(entry->effectiveAutoTypeSequence());
|
||||
sequenceList.append(entry->effectiveAutoTypeSequence());
|
||||
}
|
||||
|
||||
return sequenceList;
|
||||
@ -659,7 +659,7 @@ bool AutoType::checkSyntax(const QString& string)
|
||||
QString allowRepetition = "(?:\\s\\d+)?";
|
||||
// the ":" allows custom commands with syntax S:Field
|
||||
// exclude BEEP otherwise will be checked as valid
|
||||
QString normalCommands = "(?!BEEP\\s)[A-Z:]*" + allowRepetition;
|
||||
QString normalCommands = "(?!BEEP\\s)[A-Z:]*" + allowRepetition;
|
||||
QString specialLiterals = "[\\^\\%\\(\\)~\\{\\}\\[\\]\\+]" + allowRepetition;
|
||||
QString functionKeys = "(?:F[1-9]" + allowRepetition + "|F1[0-2])" + allowRepetition;
|
||||
QString numpad = "NUMPAD\\d" + allowRepetition;
|
||||
@ -673,9 +673,21 @@ bool AutoType::checkSyntax(const QString& string)
|
||||
// a normal string not in parentheses
|
||||
QString fixedStrings = "[^\\^\\%~\\+@\\{\\}]*";
|
||||
|
||||
QRegularExpression autoTypeSyntax("^(?:" + shortcutKeys + "|" + fixedStrings + "|\\{(?:" + normalCommands + "|" + specialLiterals +
|
||||
"|" + functionKeys + "|" + numpad + "|" + delay + "|" + beep + "|" + vkey + ")\\}|\\{" + customAttributes + "\\})*$",
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpression autoTypeSyntax(
|
||||
"^(?:" + shortcutKeys + "|" + fixedStrings + "|\\{(?:" + normalCommands + "|" + specialLiterals + "|"
|
||||
+ functionKeys
|
||||
+ "|"
|
||||
+ numpad
|
||||
+ "|"
|
||||
+ delay
|
||||
+ "|"
|
||||
+ beep
|
||||
+ "|"
|
||||
+ vkey
|
||||
+ ")\\}|\\{"
|
||||
+ customAttributes
|
||||
+ "\\})*$",
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpressionMatch match = autoTypeSyntax.match(string);
|
||||
return match.hasMatch();
|
||||
}
|
||||
@ -686,7 +698,7 @@ bool AutoType::checkSyntax(const QString& string)
|
||||
bool AutoType::checkHighDelay(const QString& string)
|
||||
{
|
||||
// 5 digit numbers(10 seconds) are too much
|
||||
QRegularExpression highDelay("\\{DELAY\\s\\d{5,}\\}", QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpression highDelay("\\{DELAY\\s\\d{5,}\\}", QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpressionMatch match = highDelay.match(string);
|
||||
return match.hasMatch();
|
||||
}
|
||||
@ -697,7 +709,7 @@ bool AutoType::checkHighDelay(const QString& string)
|
||||
bool AutoType::checkSlowKeypress(const QString& string)
|
||||
{
|
||||
// 3 digit numbers(100 milliseconds) are too much
|
||||
QRegularExpression slowKeypress("\\{DELAY=\\d{3,}\\}", QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpression slowKeypress("\\{DELAY=\\d{3,}\\}", QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpressionMatch match = slowKeypress.match(string);
|
||||
return match.hasMatch();
|
||||
}
|
||||
@ -724,7 +736,9 @@ bool AutoType::verifyAutoTypeSyntax(const QString& sequence)
|
||||
return false;
|
||||
} else if (AutoType::checkHighDelay(sequence)) {
|
||||
QMessageBox::StandardButton reply;
|
||||
reply = QMessageBox::question(nullptr, tr("Auto-Type"),
|
||||
reply = QMessageBox::question(
|
||||
nullptr,
|
||||
tr("Auto-Type"),
|
||||
tr("This Auto-Type command contains a very long delay. Do you really want to proceed?"));
|
||||
|
||||
if (reply == QMessageBox::No) {
|
||||
@ -732,7 +746,9 @@ bool AutoType::verifyAutoTypeSyntax(const QString& sequence)
|
||||
}
|
||||
} else if (AutoType::checkSlowKeypress(sequence)) {
|
||||
QMessageBox::StandardButton reply;
|
||||
reply = QMessageBox::question(nullptr, tr("Auto-Type"),
|
||||
reply = QMessageBox::question(
|
||||
nullptr,
|
||||
tr("Auto-Type"),
|
||||
tr("This Auto-Type command contains very slow key presses. Do you really want to proceed?"));
|
||||
|
||||
if (reply == QMessageBox::No) {
|
||||
@ -740,8 +756,9 @@ bool AutoType::verifyAutoTypeSyntax(const QString& sequence)
|
||||
}
|
||||
} else if (AutoType::checkHighRepetition(sequence)) {
|
||||
QMessageBox::StandardButton reply;
|
||||
reply = QMessageBox::question(nullptr, tr("Auto-Type"),
|
||||
tr("This Auto-Type command contains arguments which are repeated very often. Do you really want to proceed?"));
|
||||
reply =
|
||||
QMessageBox::question(nullptr, tr("Auto-Type"), tr("This Auto-Type command contains arguments which are "
|
||||
"repeated very often. Do you really want to proceed?"));
|
||||
|
||||
if (reply == QMessageBox::No) {
|
||||
return false;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
|
||||
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
@ -19,10 +19,10 @@
|
||||
#ifndef KEEPASSX_AUTOTYPE_H
|
||||
#define KEEPASSX_AUTOTYPE_H
|
||||
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QWidget>
|
||||
#include <QMutex>
|
||||
|
||||
#include "core/AutoTypeMatch.h"
|
||||
|
||||
@ -47,8 +47,7 @@ public:
|
||||
static bool checkSlowKeypress(const QString& string);
|
||||
static bool checkHighDelay(const QString& string);
|
||||
static bool verifyAutoTypeSyntax(const QString& sequence);
|
||||
void performAutoType(const Entry* entry,
|
||||
QWidget* hideWindow = nullptr);
|
||||
void performAutoType(const Entry* entry, QWidget* hideWindow = nullptr);
|
||||
|
||||
inline bool isAvailable()
|
||||
{
|
||||
|
@ -34,7 +34,6 @@ void AutoTypeChar::accept(AutoTypeExecutor* executor)
|
||||
executor->execChar(this);
|
||||
}
|
||||
|
||||
|
||||
AutoTypeKey::AutoTypeKey(Qt::Key key)
|
||||
: key(key)
|
||||
{
|
||||
@ -50,7 +49,6 @@ void AutoTypeKey::accept(AutoTypeExecutor* executor)
|
||||
executor->execKey(this);
|
||||
}
|
||||
|
||||
|
||||
AutoTypeDelay::AutoTypeDelay(int delayMs)
|
||||
: delayMs(delayMs)
|
||||
{
|
||||
@ -66,7 +64,6 @@ void AutoTypeDelay::accept(AutoTypeExecutor* executor)
|
||||
executor->execDelay(this);
|
||||
}
|
||||
|
||||
|
||||
AutoTypeClearField::AutoTypeClearField()
|
||||
{
|
||||
}
|
||||
@ -81,7 +78,6 @@ void AutoTypeClearField::accept(AutoTypeExecutor* executor)
|
||||
executor->execClearField(this);
|
||||
}
|
||||
|
||||
|
||||
void AutoTypeExecutor::execDelay(AutoTypeDelay* action)
|
||||
{
|
||||
Tools::wait(action->delayMs);
|
||||
|
@ -19,8 +19,8 @@
|
||||
#define KEEPASSX_AUTOTYPEACTION_H
|
||||
|
||||
#include <QChar>
|
||||
#include <Qt>
|
||||
#include <QObject>
|
||||
#include <Qt>
|
||||
|
||||
#include "core/Global.h"
|
||||
|
||||
@ -29,7 +29,9 @@ class AutoTypeExecutor;
|
||||
class KEEPASSX_EXPORT AutoTypeAction
|
||||
{
|
||||
public:
|
||||
virtual ~AutoTypeAction() {}
|
||||
virtual ~AutoTypeAction()
|
||||
{
|
||||
}
|
||||
virtual AutoTypeAction* clone() = 0;
|
||||
virtual void accept(AutoTypeExecutor* executor) = 0;
|
||||
};
|
||||
@ -75,7 +77,9 @@ public:
|
||||
class KEEPASSX_EXPORT AutoTypeExecutor
|
||||
{
|
||||
public:
|
||||
virtual ~AutoTypeExecutor() {}
|
||||
virtual ~AutoTypeExecutor()
|
||||
{
|
||||
}
|
||||
virtual void execChar(AutoTypeChar* action) = 0;
|
||||
virtual void execKey(AutoTypeKey* action) = 0;
|
||||
virtual void execDelay(AutoTypeDelay* action);
|
||||
|
@ -25,7 +25,9 @@
|
||||
class AutoTypePlatformInterface
|
||||
{
|
||||
public:
|
||||
virtual ~AutoTypePlatformInterface() {}
|
||||
virtual ~AutoTypePlatformInterface()
|
||||
{
|
||||
}
|
||||
virtual bool isAvailable() = 0;
|
||||
virtual QStringList windowTitles() = 0;
|
||||
virtual WId activeWindow() = 0;
|
||||
@ -35,7 +37,9 @@ public:
|
||||
virtual int platformEventFilter(void* event) = 0;
|
||||
virtual int initialTimeout() = 0;
|
||||
virtual bool raiseWindow(WId window) = 0;
|
||||
virtual void unload() {}
|
||||
virtual void unload()
|
||||
{
|
||||
}
|
||||
|
||||
virtual AutoTypeExecutor* createExecutor() = 0;
|
||||
|
||||
|
@ -61,7 +61,7 @@ AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent)
|
||||
|
||||
connect(m_view, SIGNAL(activated(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()));
|
||||
layout->addWidget(m_view);
|
||||
|
||||
@ -109,7 +109,7 @@ void AutoTypeSelectDialog::matchRemoved()
|
||||
if (m_rejected) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (m_view->model()->rowCount() == 0) {
|
||||
reject();
|
||||
}
|
||||
|
@ -36,8 +36,7 @@ void AutoTypeSelectView::mouseMoveEvent(QMouseEvent* event)
|
||||
if (index.isValid()) {
|
||||
setCurrentIndex(index);
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
unsetCursor();
|
||||
}
|
||||
|
||||
|
@ -50,8 +50,7 @@ void ShortcutWidget::setShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
|
||||
|
||||
if (autoType()->registerGlobalShortcut(m_key, m_modifiers)) {
|
||||
setStyleSheet("");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
setStyleSheet("background-color: #FF9696;");
|
||||
}
|
||||
}
|
||||
@ -112,14 +111,12 @@ void ShortcutWidget::keyEvent(QKeyEvent* event)
|
||||
if (!release && !keyIsModifier) {
|
||||
if (modifiers != 0) {
|
||||
setShortcut(key, modifiers);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
resetShortcut();
|
||||
setStyleSheet("");
|
||||
displayShortcut(key, modifiers);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (m_locked) {
|
||||
resetShortcut();
|
||||
setStyleSheet("");
|
||||
|
@ -33,8 +33,7 @@ bool WildcardMatcher::match(const QString& pattern)
|
||||
|
||||
if (patternContainsWildcard()) {
|
||||
return matchWithWildcards();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return patternEqualsText();
|
||||
}
|
||||
}
|
||||
@ -63,8 +62,7 @@ bool WildcardMatcher::matchWithWildcards()
|
||||
|
||||
bool WildcardMatcher::startOrEndDoesNotMatch(const QStringList& parts)
|
||||
{
|
||||
return !m_text.startsWith(parts.first(), Sensitivity) ||
|
||||
!m_text.endsWith(parts.last(), Sensitivity);
|
||||
return !m_text.startsWith(parts.first(), Sensitivity) || !m_text.endsWith(parts.last(), Sensitivity);
|
||||
}
|
||||
|
||||
bool WildcardMatcher::partsMatch(const QStringList& parts)
|
||||
|
@ -20,13 +20,11 @@
|
||||
|
||||
#include <QtPlugin>
|
||||
|
||||
#include "autotype/AutoTypePlatformPlugin.h"
|
||||
#include "autotype/AutoTypeAction.h"
|
||||
#include "autotype/AutoTypePlatformPlugin.h"
|
||||
#include "autotype/test/AutoTypeTestInterface.h"
|
||||
|
||||
class AutoTypePlatformTest : public QObject,
|
||||
public AutoTypePlatformInterface,
|
||||
public AutoTypeTestInterface
|
||||
class AutoTypePlatformTest : public QObject, public AutoTypePlatformInterface, public AutoTypeTestInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.keepassx.AutoTypePlatformInterface")
|
||||
|
@ -23,7 +23,9 @@
|
||||
class AutoTypeTestInterface
|
||||
{
|
||||
public:
|
||||
virtual ~AutoTypeTestInterface() {}
|
||||
virtual ~AutoTypeTestInterface()
|
||||
{
|
||||
}
|
||||
virtual void setActiveWindowTitle(const QString& title) = 0;
|
||||
|
||||
virtual QString actionChars() = 0;
|
||||
|
@ -94,7 +94,7 @@ void AutoTypePlatformWin::unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModi
|
||||
//
|
||||
int AutoTypePlatformWin::platformEventFilter(void* event)
|
||||
{
|
||||
MSG *msg = static_cast<MSG *>(event);
|
||||
MSG* msg = static_cast<MSG*>(event);
|
||||
|
||||
if (msg->message == WM_HOTKEY && msg->wParam == HOTKEY_ID) {
|
||||
emit globalShortcutTriggered();
|
||||
@ -173,6 +173,7 @@ void AutoTypePlatformWin::sendKey(Qt::Key key, bool isKeyDown)
|
||||
::SendInput(1, &in, sizeof(INPUT));
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
//
|
||||
// Translate qt key code to windows virtual key code
|
||||
// see: https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
|
||||
@ -426,6 +427,7 @@ BOOL AutoTypePlatformWin::isExtendedKey(DWORD nativeKeyCode)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
//
|
||||
// Translate qt key modifiers to windows modifiers
|
||||
@ -478,17 +480,14 @@ BOOL AutoTypePlatformWin::isAltTabWindow(HWND hwnd)
|
||||
//
|
||||
// Window title enum proc
|
||||
//
|
||||
BOOL CALLBACK AutoTypePlatformWin::windowTitleEnumProc(
|
||||
_In_ HWND hwnd,
|
||||
_In_ LPARAM lParam
|
||||
)
|
||||
BOOL CALLBACK AutoTypePlatformWin::windowTitleEnumProc(_In_ HWND hwnd, _In_ LPARAM lParam)
|
||||
{
|
||||
if (!isAltTabWindow(hwnd)) {
|
||||
// Skip window
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
QStringList *list = reinterpret_cast<QStringList *>(lParam);
|
||||
QStringList* list = reinterpret_cast<QStringList*>(lParam);
|
||||
QString title = windowTitle(hwnd);
|
||||
|
||||
if (!title.isEmpty()) {
|
||||
@ -506,7 +505,7 @@ QString AutoTypePlatformWin::windowTitle(HWND hwnd)
|
||||
wchar_t title[MAX_WINDOW_TITLE_LENGTH];
|
||||
int count = ::GetWindowTextW(hwnd, title, MAX_WINDOW_TITLE_LENGTH);
|
||||
|
||||
return QString::fromUtf16(reinterpret_cast<const ushort *>(title), count);
|
||||
return QString::fromUtf16(reinterpret_cast<const ushort*>(title), count);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -22,8 +22,8 @@
|
||||
#include <QtPlugin>
|
||||
#include <Windows.h>
|
||||
|
||||
#include "autotype/AutoTypePlatformPlugin.h"
|
||||
#include "autotype/AutoTypeAction.h"
|
||||
#include "autotype/AutoTypePlatformPlugin.h"
|
||||
|
||||
class AutoTypePlatformWin : public QObject, public AutoTypePlatformInterface
|
||||
{
|
||||
@ -72,4 +72,3 @@ private:
|
||||
};
|
||||
|
||||
#endif // KEEPASSX_AUTOTYPEWINDOWS_H
|
||||
|
||||
|
@ -40,11 +40,14 @@ AutoTypePlatformX11::AutoTypePlatformX11()
|
||||
m_atomUtf8String = XInternAtom(m_dpy, "UTF8_STRING", True);
|
||||
m_atomNetActiveWindow = XInternAtom(m_dpy, "_NET_ACTIVE_WINDOW", True);
|
||||
|
||||
m_classBlacklist << "desktop_window" << "gnome-panel"; // Gnome
|
||||
m_classBlacklist << "kdesktop" << "kicker"; // KDE 3
|
||||
m_classBlacklist << "desktop_window"
|
||||
<< "gnome-panel"; // Gnome
|
||||
m_classBlacklist << "kdesktop"
|
||||
<< "kicker"; // KDE 3
|
||||
m_classBlacklist << "Plasma"; // KDE 4
|
||||
m_classBlacklist << "plasmashell"; // KDE 5
|
||||
m_classBlacklist << "xfdesktop" << "xfce4-panel"; // Xfce 4
|
||||
m_classBlacklist << "xfdesktop"
|
||||
<< "xfce4-panel"; // Xfce 4
|
||||
|
||||
m_currentGlobalKey = static_cast<Qt::Key>(0);
|
||||
m_currentGlobalModifiers = 0;
|
||||
@ -146,12 +149,9 @@ bool AutoTypePlatformX11::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifi
|
||||
|
||||
startCatchXErrors();
|
||||
XGrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow, True, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow, True, GrabModeAsync,
|
||||
GrabModeAsync);
|
||||
XGrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow, True, GrabModeAsync,
|
||||
GrabModeAsync);
|
||||
XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow, True,
|
||||
GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow, True, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow, True, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow, True, GrabModeAsync, GrabModeAsync);
|
||||
stopCatchXErrors();
|
||||
|
||||
if (!m_xErrorOccurred) {
|
||||
@ -160,8 +160,7 @@ bool AutoTypePlatformX11::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifi
|
||||
m_currentGlobalKeycode = keycode;
|
||||
m_currentGlobalNativeModifiers = nativeModifiers;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
unregisterGlobalShortcut(key, modifiers);
|
||||
return false;
|
||||
}
|
||||
@ -211,29 +210,26 @@ int AutoTypePlatformX11::platformEventFilter(void* event)
|
||||
if (type == XCB_KEY_PRESS || type == XCB_KEY_RELEASE) {
|
||||
xcb_key_press_event_t* keyPressEvent = static_cast<xcb_key_press_event_t*>(event);
|
||||
if (keyPressEvent->detail == m_currentGlobalKeycode
|
||||
&& (keyPressEvent->state & m_modifierMask) == m_currentGlobalNativeModifiers
|
||||
&& (!QApplication::activeWindow() || QApplication::activeWindow()->isMinimized())
|
||||
&& m_loaded) {
|
||||
&& (keyPressEvent->state & m_modifierMask) == m_currentGlobalNativeModifiers
|
||||
&& (!QApplication::activeWindow() || QApplication::activeWindow()->isMinimized())
|
||||
&& m_loaded) {
|
||||
if (type == XCB_KEY_PRESS) {
|
||||
emit globalShortcutTriggered();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (type == XCB_MAPPING_NOTIFY) {
|
||||
} else if (type == XCB_MAPPING_NOTIFY) {
|
||||
xcb_mapping_notify_event_t* mappingNotifyEvent = static_cast<xcb_mapping_notify_event_t*>(event);
|
||||
if (mappingNotifyEvent->request == XCB_MAPPING_KEYBOARD
|
||||
|| mappingNotifyEvent->request == XCB_MAPPING_MODIFIER)
|
||||
{
|
||||
|| mappingNotifyEvent->request == XCB_MAPPING_MODIFIER) {
|
||||
XMappingEvent xMappingEvent;
|
||||
memset(&xMappingEvent, 0, sizeof(xMappingEvent));
|
||||
xMappingEvent.type = MappingNotify;
|
||||
xMappingEvent.display = m_dpy;
|
||||
if (mappingNotifyEvent->request == XCB_MAPPING_KEYBOARD) {
|
||||
xMappingEvent.request = MappingKeyboard;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
xMappingEvent.request = MappingModifier;
|
||||
}
|
||||
xMappingEvent.first_keycode = mappingNotifyEvent->first_keycode;
|
||||
@ -263,13 +259,12 @@ QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist)
|
||||
|
||||
// the window manager spec says we should read _NET_WM_NAME first, then fall back to WM_NAME
|
||||
|
||||
int retVal = XGetWindowProperty(m_dpy, window, m_atomNetWmName, 0, 1000, False, m_atomUtf8String,
|
||||
&type, &format, &nitems, &after, &data);
|
||||
int retVal = XGetWindowProperty(
|
||||
m_dpy, window, m_atomNetWmName, 0, 1000, False, m_atomUtf8String, &type, &format, &nitems, &after, &data);
|
||||
|
||||
if ((retVal == 0) && data) {
|
||||
title = QString::fromUtf8(reinterpret_cast<char*>(data));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
XTextProperty textProp;
|
||||
retVal = XGetTextProperty(m_dpy, window, &textProp, m_atomWmName);
|
||||
if ((retVal != 0) && textProp.value) {
|
||||
@ -278,12 +273,10 @@ QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist)
|
||||
|
||||
if (textProp.encoding == m_atomUtf8String) {
|
||||
title = QString::fromUtf8(reinterpret_cast<char*>(textProp.value));
|
||||
}
|
||||
else if ((XmbTextPropertyToTextList(m_dpy, &textProp, &textList, &count) == 0)
|
||||
&& textList && (count > 0)) {
|
||||
} else if ((XmbTextPropertyToTextList(m_dpy, &textProp, &textList, &count) == 0) && textList
|
||||
&& (count > 0)) {
|
||||
title = QString::fromLocal8Bit(textList[0]);
|
||||
}
|
||||
else if (textProp.encoding == m_atomString) {
|
||||
} else if (textProp.encoding == m_atomString) {
|
||||
title = QString::fromLocal8Bit(reinterpret_cast<char*>(textProp.value));
|
||||
}
|
||||
|
||||
@ -386,8 +379,8 @@ bool AutoTypePlatformX11::isTopLevelWindow(Window window)
|
||||
unsigned long nitems;
|
||||
unsigned long after;
|
||||
unsigned char* data = Q_NULLPTR;
|
||||
int retVal = XGetWindowProperty(m_dpy, window, m_atomWmState, 0, 2, False, m_atomWmState, &type, &format,
|
||||
&nitems, &after, &data);
|
||||
int retVal = XGetWindowProperty(
|
||||
m_dpy, window, m_atomWmState, 0, 2, False, m_atomWmState, &type, &format, &nitems, &after, &data);
|
||||
|
||||
bool result = false;
|
||||
|
||||
@ -408,15 +401,12 @@ KeySym AutoTypePlatformX11::charToKeySym(const QChar& ch)
|
||||
ushort unicode = ch.unicode();
|
||||
|
||||
/* first check for Latin-1 characters (1:1 mapping) */
|
||||
if ((unicode >= 0x0020 && unicode <= 0x007e)
|
||||
|| (unicode >= 0x00a0 && unicode <= 0x00ff)) {
|
||||
if ((unicode >= 0x0020 && unicode <= 0x007e) || (unicode >= 0x00a0 && unicode <= 0x00ff)) {
|
||||
return unicode;
|
||||
}
|
||||
|
||||
/* mapping table generated from keysymdef.h */
|
||||
const uint* match = Tools::binaryFind(m_unicodeToKeysymKeys,
|
||||
m_unicodeToKeysymKeys + m_unicodeToKeysymLen,
|
||||
unicode);
|
||||
const uint* match = Tools::binaryFind(m_unicodeToKeysymKeys, m_unicodeToKeysymKeys + m_unicodeToKeysymLen, unicode);
|
||||
int index = match - m_unicodeToKeysymKeys;
|
||||
if (index != m_unicodeToKeysymLen) {
|
||||
return m_unicodeToKeysymValues[index];
|
||||
@ -483,8 +473,7 @@ KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key)
|
||||
default:
|
||||
if (key >= Qt::Key_F1 && key <= Qt::Key_F16) {
|
||||
return XK_F1 + (key - Qt::Key_F1);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return NoSymbol;
|
||||
}
|
||||
}
|
||||
@ -493,13 +482,13 @@ KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key)
|
||||
/*
|
||||
* Update the keyboard and modifier mapping.
|
||||
* We need the KeyboardMapping for AddKeysym.
|
||||
* Modifier mapping is required for clearing the modifiers.
|
||||
* Modifier mapping is required for clearing the modifiers.
|
||||
*/
|
||||
void AutoTypePlatformX11::updateKeymap()
|
||||
{
|
||||
int keycode, inx;
|
||||
int mod_index, mod_key;
|
||||
XModifierKeymap *modifiers;
|
||||
XModifierKeymap* modifiers;
|
||||
|
||||
if (m_xkb) {
|
||||
XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True);
|
||||
@ -507,10 +496,9 @@ void AutoTypePlatformX11::updateKeymap()
|
||||
m_xkb = getKeyboard();
|
||||
|
||||
XDisplayKeycodes(m_dpy, &m_minKeycode, &m_maxKeycode);
|
||||
if (m_keysymTable != NULL) XFree(m_keysymTable);
|
||||
m_keysymTable = XGetKeyboardMapping(m_dpy,
|
||||
m_minKeycode, m_maxKeycode - m_minKeycode + 1,
|
||||
&m_keysymPerKeycode);
|
||||
if (m_keysymTable != NULL)
|
||||
XFree(m_keysymTable);
|
||||
m_keysymTable = XGetKeyboardMapping(m_dpy, m_minKeycode, m_maxKeycode - m_minKeycode + 1, &m_keysymPerKeycode);
|
||||
|
||||
/* determine the keycode to use for remapped keys */
|
||||
inx = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode;
|
||||
@ -518,16 +506,16 @@ void AutoTypePlatformX11::updateKeymap()
|
||||
for (keycode = m_minKeycode; keycode <= m_maxKeycode; keycode++) {
|
||||
inx = (keycode - m_minKeycode) * m_keysymPerKeycode;
|
||||
if (m_keysymTable[inx] == NoSymbol) {
|
||||
m_remapKeycode = keycode;
|
||||
m_currentRemapKeysym = NoSymbol;
|
||||
break;
|
||||
m_remapKeycode = keycode;
|
||||
m_currentRemapKeysym = NoSymbol;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* determine the keycode to use for modifiers */
|
||||
modifiers = XGetModifierMapping(m_dpy);
|
||||
for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
|
||||
for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index++) {
|
||||
m_modifier_keycode[mod_index] = 0;
|
||||
for (mod_key = 0; mod_key < modifiers->max_keypermod; mod_key++) {
|
||||
keycode = modifiers->modifiermap[mod_index * modifiers->max_keypermod + mod_key];
|
||||
@ -625,7 +613,7 @@ int AutoTypePlatformX11::AddKeysym(KeySym keysym)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int inx = (m_remapKeycode- m_minKeycode) * m_keysymPerKeycode;
|
||||
int inx = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode;
|
||||
m_keysymTable[inx] = keysym;
|
||||
m_currentRemapKeysym = keysym;
|
||||
|
||||
@ -644,7 +632,7 @@ int AutoTypePlatformX11::AddKeysym(KeySym keysym)
|
||||
void AutoTypePlatformX11::SendKeyEvent(unsigned keycode, bool press)
|
||||
{
|
||||
XSync(m_dpy, False);
|
||||
int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler);
|
||||
int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler);
|
||||
|
||||
XTestFakeKeyEvent(m_dpy, keycode, press, 0);
|
||||
XFlush(m_dpy);
|
||||
@ -659,7 +647,7 @@ void AutoTypePlatformX11::SendKeyEvent(unsigned keycode, bool press)
|
||||
void AutoTypePlatformX11::SendModifiers(unsigned int mask, bool press)
|
||||
{
|
||||
int mod_index;
|
||||
for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
|
||||
for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index++) {
|
||||
if (mask & (1 << mod_index)) {
|
||||
SendKeyEvent(m_modifier_keycode[mod_index], press);
|
||||
}
|
||||
@ -670,7 +658,7 @@ void AutoTypePlatformX11::SendModifiers(unsigned int mask, bool press)
|
||||
* Determines the keycode and modifier mask for the given
|
||||
* keysym.
|
||||
*/
|
||||
int AutoTypePlatformX11::GetKeycode(KeySym keysym, unsigned int *mask)
|
||||
int AutoTypePlatformX11::GetKeycode(KeySym keysym, unsigned int* mask)
|
||||
{
|
||||
int keycode = XKeysymToKeycode(m_dpy, keysym);
|
||||
|
||||
@ -688,15 +676,15 @@ int AutoTypePlatformX11::GetKeycode(KeySym keysym, unsigned int *mask)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool AutoTypePlatformX11::keysymModifiers(KeySym keysym, int keycode, unsigned int *mask)
|
||||
bool AutoTypePlatformX11::keysymModifiers(KeySym keysym, int keycode, unsigned int* mask)
|
||||
{
|
||||
int shift, mod;
|
||||
unsigned int mods_rtrn;
|
||||
|
||||
/* determine whether there is a combination of the modifiers
|
||||
(Mod1-Mod5) with or without shift which returns keysym */
|
||||
for (shift = 0; shift < 2; shift ++) {
|
||||
for (mod = ControlMapIndex; mod <= Mod5MapIndex; mod ++) {
|
||||
for (shift = 0; shift < 2; shift++) {
|
||||
for (mod = ControlMapIndex; mod <= Mod5MapIndex; mod++) {
|
||||
KeySym keysym_rtrn;
|
||||
*mask = (mod == ControlMapIndex) ? shift : shift | (1 << mod);
|
||||
XkbTranslateKeyCode(m_xkb, keycode, *mask, &mods_rtrn, &keysym_rtrn);
|
||||
@ -709,8 +697,6 @@ bool AutoTypePlatformX11::keysymModifiers(KeySym keysym, int keycode, unsigned i
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Send sequence of KeyPressed/KeyReleased events to the focused
|
||||
* window to simulate keyboard. If modifiers (shift, control, etc)
|
||||
@ -753,7 +739,7 @@ void AutoTypePlatformX11::SendKey(KeySym keysym, unsigned int modifiers)
|
||||
if (!modifiers) {
|
||||
// check every release_check_mask individually if it affects the keysym we would generate
|
||||
// if it doesn't we probably don't need to release it
|
||||
for (int mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
|
||||
for (int mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index++) {
|
||||
if (release_check_mask & (1 << mod_index)) {
|
||||
unsigned int mods_rtrn;
|
||||
KeySym keysym_rtrn;
|
||||
@ -768,7 +754,8 @@ void AutoTypePlatformX11::SendKey(KeySym keysym, unsigned int modifiers)
|
||||
// finally check if the combination of pressed modifiers that we chose to ignore affects the keysym
|
||||
unsigned int mods_rtrn;
|
||||
KeySym keysym_rtrn;
|
||||
XkbTranslateKeyCode(m_xkb, keycode, wanted_mask | (release_check_mask & ~release_mask), &mods_rtrn, &keysym_rtrn);
|
||||
XkbTranslateKeyCode(
|
||||
m_xkb, keycode, wanted_mask | (release_check_mask & ~release_mask), &mods_rtrn, &keysym_rtrn);
|
||||
if (keysym_rtrn != keysym) {
|
||||
// oh well, release all the modifiers we don't want
|
||||
release_mask = release_check_mask;
|
||||
@ -810,7 +797,6 @@ int AutoTypePlatformX11::MyErrorHandler(Display* my_dpy, XErrorEvent* event)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
AutoTypeExecutorX11::AutoTypeExecutorX11(AutoTypePlatformX11* platform)
|
||||
: m_platform(platform)
|
||||
{
|
||||
@ -844,7 +830,6 @@ void AutoTypeExecutorX11::execClearField(AutoTypeClearField* action = nullptr)
|
||||
nanosleep(&ts, nullptr);
|
||||
}
|
||||
|
||||
|
||||
int AutoTypePlatformX11::initialTimeout()
|
||||
{
|
||||
return 500;
|
||||
@ -870,15 +855,12 @@ bool AutoTypePlatformX11::raiseWindow(WId window)
|
||||
QWidget* activeWindow = QApplication::activeWindow();
|
||||
if (activeWindow) {
|
||||
event.xclient.data.l[2] = activeWindow->internalWinId();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
event.xclient.data.l[2] = 0;
|
||||
}
|
||||
event.xclient.data.l[3] = 0;
|
||||
event.xclient.data.l[4] = 0;
|
||||
XSendEvent(m_dpy, m_rootWindow, False,
|
||||
SubstructureRedirectMask | SubstructureNotifyMask,
|
||||
&event);
|
||||
XSendEvent(m_dpy, m_rootWindow, False, SubstructureRedirectMask | SubstructureNotifyMask, &event);
|
||||
XFlush(m_dpy);
|
||||
|
||||
return true;
|
||||
|
@ -22,16 +22,16 @@
|
||||
|
||||
#include <QApplication>
|
||||
#include <QSet>
|
||||
#include <QtPlugin>
|
||||
#include <QWidget>
|
||||
#include <QX11Info>
|
||||
#include <QtPlugin>
|
||||
|
||||
#include <X11/XKBlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
#include <X11/XKBlib.h>
|
||||
|
||||
#include "autotype/AutoTypePlatformPlugin.h"
|
||||
#include "autotype/AutoTypeAction.h"
|
||||
#include "autotype/AutoTypePlatformPlugin.h"
|
||||
|
||||
#define N_MOD_INDICES (Mod5MapIndex + 1)
|
||||
|
||||
@ -81,8 +81,8 @@ private:
|
||||
void AddModifier(KeySym keysym);
|
||||
void SendKeyEvent(unsigned keycode, bool press);
|
||||
void SendModifiers(unsigned int mask, bool press);
|
||||
int GetKeycode(KeySym keysym, unsigned int *mask);
|
||||
bool keysymModifiers(KeySym keysym, int keycode, unsigned int *mask);
|
||||
int GetKeycode(KeySym keysym, unsigned int* mask);
|
||||
bool keysymModifiers(KeySym keysym, int keycode, unsigned int* mask);
|
||||
|
||||
static int MyErrorHandler(Display* my_dpy, XErrorEvent* event);
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
const int AutoTypePlatformX11::m_unicodeToKeysymLen = 632;
|
||||
|
||||
// clang-format off
|
||||
const uint AutoTypePlatformX11::m_unicodeToKeysymKeys[] = {
|
||||
0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107,
|
||||
0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e, 0x010f,
|
||||
@ -167,3 +168,4 @@ const uint AutoTypePlatformX11::m_unicodeToKeysymValues[] = {
|
||||
0x04ac, 0x04d4, 0x04ad, 0x04d5, 0x04ae, 0x04d6, 0x04d7, 0x04d8,
|
||||
0x04d9, 0x04da, 0x04db, 0x04dc, 0x04a6, 0x04dd, 0x04a5, 0x04b0
|
||||
};
|
||||
// clang-format on
|
||||
|
11
src/browser/BrowserAccessControlDialog.cpp
Executable file → Normal file
11
src/browser/BrowserAccessControlDialog.cpp
Executable file → Normal file
@ -17,12 +17,12 @@
|
||||
*/
|
||||
|
||||
#include "BrowserAccessControlDialog.h"
|
||||
#include "ui_BrowserAccessControlDialog.h"
|
||||
#include "core/Entry.h"
|
||||
#include "ui_BrowserAccessControlDialog.h"
|
||||
|
||||
BrowserAccessControlDialog::BrowserAccessControlDialog(QWidget* parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::BrowserAccessControlDialog())
|
||||
BrowserAccessControlDialog::BrowserAccessControlDialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::BrowserAccessControlDialog())
|
||||
{
|
||||
this->setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
|
||||
|
||||
@ -38,7 +38,8 @@ BrowserAccessControlDialog::~BrowserAccessControlDialog()
|
||||
void BrowserAccessControlDialog::setUrl(const QString& url)
|
||||
{
|
||||
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.")).arg(QUrl(url).host()));
|
||||
"Please select whether you want to allow access."))
|
||||
.arg(QUrl(url).host()));
|
||||
}
|
||||
|
||||
void BrowserAccessControlDialog::setItems(const QList<Entry*>& items)
|
||||
|
5
src/browser/BrowserAccessControlDialog.h
Executable file → Normal file
5
src/browser/BrowserAccessControlDialog.h
Executable file → Normal file
@ -24,8 +24,9 @@
|
||||
|
||||
class Entry;
|
||||
|
||||
namespace Ui {
|
||||
class BrowserAccessControlDialog;
|
||||
namespace Ui
|
||||
{
|
||||
class BrowserAccessControlDialog;
|
||||
}
|
||||
|
||||
class BrowserAccessControlDialog : public QDialog
|
||||
|
82
src/browser/BrowserAction.cpp
Executable file → Normal file
82
src/browser/BrowserAction.cpp
Executable file → Normal file
@ -16,21 +16,20 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonParseError>
|
||||
#include "BrowserAction.h"
|
||||
#include "BrowserSettings.h"
|
||||
#include "config-keepassx.h"
|
||||
#include "sodium.h"
|
||||
#include "sodium/crypto_box.h"
|
||||
#include "sodium/randombytes.h"
|
||||
#include "config-keepassx.h"
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonParseError>
|
||||
|
||||
BrowserAction::BrowserAction(BrowserService& browserService) :
|
||||
m_mutex(QMutex::Recursive),
|
||||
m_browserService(browserService),
|
||||
m_associated(false)
|
||||
BrowserAction::BrowserAction(BrowserService& browserService)
|
||||
: m_mutex(QMutex::Recursive)
|
||||
, m_browserService(browserService)
|
||||
, m_associated(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QJsonObject BrowserAction::readResponse(const QJsonObject& json)
|
||||
@ -62,7 +61,6 @@ QJsonObject BrowserAction::readResponse(const QJsonObject& json)
|
||||
return handleAction(json);
|
||||
}
|
||||
|
||||
|
||||
// Private functions
|
||||
///////////////////////
|
||||
|
||||
@ -80,7 +78,7 @@ QJsonObject BrowserAction::handleAction(const QJsonObject& json)
|
||||
} else if (action.compare("associate", Qt::CaseSensitive) == 0) {
|
||||
return handleAssociate(json, action);
|
||||
} else if (action.compare("test-associate", Qt::CaseSensitive) == 0) {
|
||||
return handleTestAssociate(json, action);
|
||||
return handleTestAssociate(json, action);
|
||||
} else if (action.compare("get-logins", Qt::CaseSensitive) == 0) {
|
||||
return handleGetLogins(json, action);
|
||||
} else if (action.compare("generate-password", Qt::CaseSensitive) == 0) {
|
||||
@ -270,7 +268,7 @@ QJsonObject BrowserAction::handleGeneratePassword(const QJsonObject& json, const
|
||||
|
||||
QJsonArray arr;
|
||||
QJsonObject passwd;
|
||||
passwd["login"] = QString::number(password.length() * 8); //bits;
|
||||
passwd["login"] = QString::number(password.length() * 8); // bits;
|
||||
passwd["password"] = password;
|
||||
arr.append(passwd);
|
||||
|
||||
@ -386,31 +384,49 @@ QJsonObject BrowserAction::buildResponse(const QString& action, const QJsonObjec
|
||||
QString BrowserAction::getErrorMessage(const int errorCode) const
|
||||
{
|
||||
switch (errorCode) {
|
||||
case ERROR_KEEPASS_DATABASE_NOT_OPENED: return QObject::tr("Database not opened");
|
||||
case ERROR_KEEPASS_DATABASE_HASH_NOT_RECEIVED: return QObject::tr("Database hash not available");
|
||||
case ERROR_KEEPASS_CLIENT_PUBLIC_KEY_NOT_RECEIVED: return QObject::tr("Client public key not received");
|
||||
case ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE: return QObject::tr("Cannot decrypt message");
|
||||
case ERROR_KEEPASS_TIMEOUT_OR_NOT_CONNECTED: return QObject::tr("Timeout or cannot connect to KeePassXC");
|
||||
case ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED: return QObject::tr("Action cancelled or denied");
|
||||
case ERROR_KEEPASS_CANNOT_ENCRYPT_MESSAGE: return QObject::tr("Cannot encrypt message or public key not found. Is Native Messaging enabled in KeePassXC?");
|
||||
case ERROR_KEEPASS_ASSOCIATION_FAILED: return QObject::tr("KeePassXC association failed, try again");
|
||||
case ERROR_KEEPASS_KEY_CHANGE_FAILED: return QObject::tr("Key change was not successful");
|
||||
case ERROR_KEEPASS_ENCRYPTION_KEY_UNRECOGNIZED: return QObject::tr("Encryption key is not recognized");
|
||||
case ERROR_KEEPASS_NO_SAVED_DATABASES_FOUND: return QObject::tr("No saved databases found");
|
||||
case ERROR_KEEPASS_INCORRECT_ACTION: return QObject::tr("Incorrect action");
|
||||
case ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED: return QObject::tr("Empty message received");
|
||||
case ERROR_KEEPASS_NO_URL_PROVIDED: return QObject::tr("No URL provided");
|
||||
case ERROR_KEEPASS_NO_LOGINS_FOUND: return QObject::tr("No logins found");
|
||||
default: return QObject::tr("Unknown error");
|
||||
case ERROR_KEEPASS_DATABASE_NOT_OPENED:
|
||||
return QObject::tr("Database not opened");
|
||||
case ERROR_KEEPASS_DATABASE_HASH_NOT_RECEIVED:
|
||||
return QObject::tr("Database hash not available");
|
||||
case ERROR_KEEPASS_CLIENT_PUBLIC_KEY_NOT_RECEIVED:
|
||||
return QObject::tr("Client public key not received");
|
||||
case ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE:
|
||||
return QObject::tr("Cannot decrypt message");
|
||||
case ERROR_KEEPASS_TIMEOUT_OR_NOT_CONNECTED:
|
||||
return QObject::tr("Timeout or cannot connect to KeePassXC");
|
||||
case ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED:
|
||||
return QObject::tr("Action cancelled or denied");
|
||||
case ERROR_KEEPASS_CANNOT_ENCRYPT_MESSAGE:
|
||||
return QObject::tr("Cannot encrypt message or public key not found. Is Native Messaging enabled in KeePassXC?");
|
||||
case ERROR_KEEPASS_ASSOCIATION_FAILED:
|
||||
return QObject::tr("KeePassXC association failed, try again");
|
||||
case ERROR_KEEPASS_KEY_CHANGE_FAILED:
|
||||
return QObject::tr("Key change was not successful");
|
||||
case ERROR_KEEPASS_ENCRYPTION_KEY_UNRECOGNIZED:
|
||||
return QObject::tr("Encryption key is not recognized");
|
||||
case ERROR_KEEPASS_NO_SAVED_DATABASES_FOUND:
|
||||
return QObject::tr("No saved databases found");
|
||||
case ERROR_KEEPASS_INCORRECT_ACTION:
|
||||
return QObject::tr("Incorrect action");
|
||||
case ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED:
|
||||
return QObject::tr("Empty message received");
|
||||
case ERROR_KEEPASS_NO_URL_PROVIDED:
|
||||
return QObject::tr("No URL provided");
|
||||
case ERROR_KEEPASS_NO_LOGINS_FOUND:
|
||||
return QObject::tr("No logins found");
|
||||
default:
|
||||
return QObject::tr("Unknown error");
|
||||
}
|
||||
}
|
||||
|
||||
QString BrowserAction::getDatabaseHash()
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
QByteArray hash = QCryptographicHash::hash(
|
||||
(m_browserService.getDatabaseRootUuid() + m_browserService.getDatabaseRecycleBinUuid()).toUtf8(),
|
||||
QCryptographicHash::Sha256).toHex();
|
||||
QByteArray hash =
|
||||
QCryptographicHash::hash(
|
||||
(m_browserService.getDatabaseRootUuid() + m_browserService.getDatabaseRecycleBinUuid()).toUtf8(),
|
||||
QCryptographicHash::Sha256)
|
||||
.toHex();
|
||||
return QString(hash);
|
||||
}
|
||||
|
||||
@ -463,8 +479,8 @@ QString BrowserAction::encrypt(const QString plaintext, const QString nonce)
|
||||
}
|
||||
|
||||
if (crypto_box_easy(e.data(), m.data(), m.size(), n.data(), ck.data(), sk.data()) == 0) {
|
||||
QByteArray res = getQByteArray(e.data(), (crypto_box_MACBYTES + ma.length()));
|
||||
return res.toBase64();
|
||||
QByteArray res = getQByteArray(e.data(), (crypto_box_MACBYTES + ma.length()));
|
||||
return res.toBase64();
|
||||
}
|
||||
|
||||
return QString();
|
||||
@ -491,7 +507,7 @@ QByteArray BrowserAction::decrypt(const QString encrypted, const QString nonce)
|
||||
}
|
||||
|
||||
if (crypto_box_open_easy(d.data(), m.data(), ma.length(), n.data(), ck.data(), sk.data()) == 0) {
|
||||
return getQByteArray(d.data(), std::char_traits<char>::length(reinterpret_cast<const char *>(d.data())));
|
||||
return getQByteArray(d.data(), std::char_traits<char>::length(reinterpret_cast<const char*>(d.data())));
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
|
73
src/browser/BrowserAction.h
Executable file → Normal file
73
src/browser/BrowserAction.h
Executable file → Normal file
@ -19,32 +19,33 @@
|
||||
#ifndef BROWSERACTION_H
|
||||
#define BROWSERACTION_H
|
||||
|
||||
#include <QtCore>
|
||||
#include <QObject>
|
||||
#include "BrowserService.h"
|
||||
#include <QJsonObject>
|
||||
#include <QMutex>
|
||||
#include "BrowserService.h"
|
||||
#include <QObject>
|
||||
#include <QtCore>
|
||||
|
||||
class BrowserAction : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
enum {
|
||||
ERROR_KEEPASS_DATABASE_NOT_OPENED = 1,
|
||||
ERROR_KEEPASS_DATABASE_HASH_NOT_RECEIVED = 2,
|
||||
ERROR_KEEPASS_CLIENT_PUBLIC_KEY_NOT_RECEIVED = 3,
|
||||
ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE = 4,
|
||||
ERROR_KEEPASS_TIMEOUT_OR_NOT_CONNECTED = 5,
|
||||
ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED = 6,
|
||||
ERROR_KEEPASS_CANNOT_ENCRYPT_MESSAGE = 7,
|
||||
ERROR_KEEPASS_ASSOCIATION_FAILED = 8,
|
||||
ERROR_KEEPASS_KEY_CHANGE_FAILED = 9,
|
||||
ERROR_KEEPASS_ENCRYPTION_KEY_UNRECOGNIZED = 10,
|
||||
ERROR_KEEPASS_NO_SAVED_DATABASES_FOUND = 11,
|
||||
ERROR_KEEPASS_INCORRECT_ACTION = 12,
|
||||
ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED = 13,
|
||||
ERROR_KEEPASS_NO_URL_PROVIDED = 14,
|
||||
ERROR_KEEPASS_NO_LOGINS_FOUND = 15
|
||||
enum
|
||||
{
|
||||
ERROR_KEEPASS_DATABASE_NOT_OPENED = 1,
|
||||
ERROR_KEEPASS_DATABASE_HASH_NOT_RECEIVED = 2,
|
||||
ERROR_KEEPASS_CLIENT_PUBLIC_KEY_NOT_RECEIVED = 3,
|
||||
ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE = 4,
|
||||
ERROR_KEEPASS_TIMEOUT_OR_NOT_CONNECTED = 5,
|
||||
ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED = 6,
|
||||
ERROR_KEEPASS_CANNOT_ENCRYPT_MESSAGE = 7,
|
||||
ERROR_KEEPASS_ASSOCIATION_FAILED = 8,
|
||||
ERROR_KEEPASS_KEY_CHANGE_FAILED = 9,
|
||||
ERROR_KEEPASS_ENCRYPTION_KEY_UNRECOGNIZED = 10,
|
||||
ERROR_KEEPASS_NO_SAVED_DATABASES_FOUND = 11,
|
||||
ERROR_KEEPASS_INCORRECT_ACTION = 12,
|
||||
ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED = 13,
|
||||
ERROR_KEEPASS_NO_URL_PROVIDED = 14,
|
||||
ERROR_KEEPASS_NO_LOGINS_FOUND = 15
|
||||
};
|
||||
|
||||
public:
|
||||
@ -54,8 +55,8 @@ public:
|
||||
QJsonObject readResponse(const QJsonObject& json);
|
||||
|
||||
public slots:
|
||||
void removeSharedEncryptionKeys();
|
||||
void removeStoredPermissions();
|
||||
void removeSharedEncryptionKeys();
|
||||
void removeStoredPermissions();
|
||||
|
||||
private:
|
||||
QJsonObject handleAction(const QJsonObject& json);
|
||||
@ -71,28 +72,28 @@ private:
|
||||
QJsonObject buildMessage(const QString& nonce) const;
|
||||
QJsonObject buildResponse(const QString& action, const QJsonObject& message, const QString& nonce);
|
||||
QJsonObject getErrorReply(const QString& action, const int errorCode) const;
|
||||
QString getErrorMessage(const int errorCode) const;
|
||||
QString getDatabaseHash();
|
||||
QString getErrorMessage(const int errorCode) const;
|
||||
QString getDatabaseHash();
|
||||
|
||||
QString encryptMessage(const QJsonObject& message, const QString& nonce);
|
||||
QString encryptMessage(const QJsonObject& message, const QString& nonce);
|
||||
QJsonObject decryptMessage(const QString& message, const QString& nonce, const QString& action = QString());
|
||||
QString encrypt(const QString plaintext, const QString nonce);
|
||||
QByteArray decrypt(const QString encrypted, const QString nonce);
|
||||
QString encrypt(const QString plaintext, const QString nonce);
|
||||
QByteArray decrypt(const QString encrypted, const QString nonce);
|
||||
|
||||
QString getBase64FromKey(const uchar* array, const uint len);
|
||||
QByteArray getQByteArray(const uchar* array, const uint len) const;
|
||||
QString getBase64FromKey(const uchar* array, const uint len);
|
||||
QByteArray getQByteArray(const uchar* array, const uint len) const;
|
||||
QJsonObject getJsonObject(const uchar* pArray, const uint len) const;
|
||||
QJsonObject getJsonObject(const QByteArray ba) const;
|
||||
QByteArray base64Decode(const QString str);
|
||||
QString incrementNonce(const QString& nonce);
|
||||
QByteArray base64Decode(const QString str);
|
||||
QString incrementNonce(const QString& nonce);
|
||||
|
||||
private:
|
||||
QMutex m_mutex;
|
||||
BrowserService& m_browserService;
|
||||
QString m_clientPublicKey;
|
||||
QString m_publicKey;
|
||||
QString m_secretKey;
|
||||
bool m_associated;
|
||||
QMutex m_mutex;
|
||||
BrowserService& m_browserService;
|
||||
QString m_clientPublicKey;
|
||||
QString m_publicKey;
|
||||
QString m_secretKey;
|
||||
bool m_associated;
|
||||
};
|
||||
|
||||
#endif // BROWSERACTION_H
|
||||
|
12
src/browser/BrowserClients.cpp
Executable file → Normal file
12
src/browser/BrowserClients.cpp
Executable file → Normal file
@ -16,13 +16,13 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QJsonValue>
|
||||
#include <QJsonParseError>
|
||||
#include "BrowserClients.h"
|
||||
#include <QJsonParseError>
|
||||
#include <QJsonValue>
|
||||
|
||||
BrowserClients::BrowserClients(BrowserService& browserService) :
|
||||
m_mutex(QMutex::Recursive),
|
||||
m_browserService(browserService)
|
||||
BrowserClients::BrowserClients(BrowserService& browserService)
|
||||
: m_mutex(QMutex::Recursive)
|
||||
, m_browserService(browserService)
|
||||
{
|
||||
m_clients.reserve(1000);
|
||||
}
|
||||
@ -63,7 +63,7 @@ QString BrowserClients::getClientID(const QJsonObject& json) const
|
||||
BrowserClients::ClientPtr BrowserClients::getClient(const QString& clientID)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
for (const auto &i : m_clients) {
|
||||
for (const auto& i : m_clients) {
|
||||
if (i->clientID.compare(clientID, Qt::CaseSensitive) == 0) {
|
||||
return i;
|
||||
}
|
||||
|
35
src/browser/BrowserClients.h
Executable file → Normal file
35
src/browser/BrowserClients.h
Executable file → Normal file
@ -19,22 +19,27 @@
|
||||
#ifndef BROWSERCLIENTS_H
|
||||
#define BROWSERCLIENTS_H
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QMutex>
|
||||
#include <QVector>
|
||||
#include <QSharedPointer>
|
||||
#include <QLocalSocket>
|
||||
#include "BrowserAction.h"
|
||||
#include <QJsonObject>
|
||||
#include <QLocalSocket>
|
||||
#include <QMutex>
|
||||
#include <QSharedPointer>
|
||||
#include <QVector>
|
||||
|
||||
class BrowserClients
|
||||
{
|
||||
struct Client {
|
||||
Client(const QString& id, QSharedPointer<BrowserAction> ba) : clientID(id), browserAction(ba) {}
|
||||
QString clientID;
|
||||
QSharedPointer<BrowserAction> browserAction;
|
||||
struct Client
|
||||
{
|
||||
Client(const QString& id, QSharedPointer<BrowserAction> ba)
|
||||
: clientID(id)
|
||||
, browserAction(ba)
|
||||
{
|
||||
}
|
||||
QString clientID;
|
||||
QSharedPointer<BrowserAction> browserAction;
|
||||
};
|
||||
|
||||
typedef QSharedPointer<Client> ClientPtr;
|
||||
typedef QSharedPointer<Client> ClientPtr;
|
||||
|
||||
public:
|
||||
BrowserClients(BrowserService& browserService);
|
||||
@ -44,13 +49,13 @@ public:
|
||||
|
||||
private:
|
||||
QJsonObject byteArrayToJson(const QByteArray& arr) const;
|
||||
QString getClientID(const QJsonObject& json) const;
|
||||
ClientPtr getClient(const QString& clientID);
|
||||
QString getClientID(const QJsonObject& json) const;
|
||||
ClientPtr getClient(const QString& clientID);
|
||||
|
||||
private:
|
||||
QMutex m_mutex;
|
||||
QVector<ClientPtr> m_clients;
|
||||
BrowserService& m_browserService;
|
||||
QMutex m_mutex;
|
||||
QVector<ClientPtr> m_clients;
|
||||
BrowserService& m_browserService;
|
||||
};
|
||||
|
||||
#endif // BROWSERCLIENTS_H
|
||||
|
@ -17,15 +17,14 @@
|
||||
*/
|
||||
|
||||
#include "BrowserEntryConfig.h"
|
||||
#include <QtCore>
|
||||
#include "core/Entry.h"
|
||||
#include "core/EntryAttributes.h"
|
||||
#include <QtCore>
|
||||
|
||||
static const char KEEPASSBROWSER_NAME[] = "KeePassXC-Browser Settings";
|
||||
|
||||
|
||||
BrowserEntryConfig::BrowserEntryConfig(QObject* parent) :
|
||||
QObject(parent)
|
||||
BrowserEntryConfig::BrowserEntryConfig(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -19,11 +19,11 @@
|
||||
#ifndef BROWSERENTRYCONFIG_H
|
||||
#define BROWSERENTRYCONFIG_H
|
||||
|
||||
#include "Variant.h"
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QSet>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QSet>
|
||||
#include "Variant.h"
|
||||
|
||||
class Entry;
|
||||
|
||||
@ -31,8 +31,8 @@ class BrowserEntryConfig : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QStringList Allow READ allowedHosts WRITE setAllowedHosts)
|
||||
Q_PROPERTY(QStringList Deny READ deniedHosts WRITE setDeniedHosts )
|
||||
Q_PROPERTY(QString Realm READ realm WRITE setRealm )
|
||||
Q_PROPERTY(QStringList Deny READ deniedHosts WRITE setDeniedHosts)
|
||||
Q_PROPERTY(QString Realm READ realm WRITE setRealm)
|
||||
|
||||
public:
|
||||
BrowserEntryConfig(QObject* object = 0);
|
||||
@ -54,7 +54,7 @@ private:
|
||||
|
||||
QSet<QString> m_allowedHosts;
|
||||
QSet<QString> m_deniedHosts;
|
||||
QString m_realm;
|
||||
QString m_realm;
|
||||
};
|
||||
|
||||
#endif // BROWSERENTRYCONFIG_H
|
||||
|
21
src/browser/BrowserOptionDialog.cpp
Executable file → Normal file
21
src/browser/BrowserOptionDialog.cpp
Executable file → Normal file
@ -18,23 +18,24 @@
|
||||
*/
|
||||
|
||||
#include "BrowserOptionDialog.h"
|
||||
#include "ui_BrowserOptionDialog.h"
|
||||
#include "config-keepassx.h"
|
||||
#include "BrowserSettings.h"
|
||||
#include "config-keepassx.h"
|
||||
#include "core/FilePath.h"
|
||||
#include "ui_BrowserOptionDialog.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
BrowserOptionDialog::BrowserOptionDialog(QWidget* parent) :
|
||||
QWidget(parent),
|
||||
m_ui(new Ui::BrowserOptionDialog())
|
||||
BrowserOptionDialog::BrowserOptionDialog(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_ui(new Ui::BrowserOptionDialog())
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
connect(m_ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SIGNAL(removeSharedEncryptionKeys()));
|
||||
connect(m_ui->removeStoredPermissions, SIGNAL(clicked()), this, SIGNAL(removeStoredPermissions()));
|
||||
|
||||
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->setAutoHideTimeout(-1);
|
||||
|
||||
@ -95,7 +96,8 @@ void BrowserOptionDialog::loadSettings()
|
||||
m_ui->enableBrowserSupport->setChecked(false);
|
||||
m_ui->enableBrowserSupport->setEnabled(false);
|
||||
m_ui->browserGlobalWarningWidget->showMessage(
|
||||
tr("We're sorry, but KeePassXC-Browser is not supported for Snap releases at the moment."), MessageWidget::Warning);
|
||||
tr("We're sorry, but KeePassXC-Browser is not supported for Snap releases at the moment."),
|
||||
MessageWidget::Warning);
|
||||
m_ui->browserGlobalWarningWidget->setCloseButtonVisible(false);
|
||||
m_ui->browserGlobalWarningWidget->setAutoHideTimeout(-1);
|
||||
#endif
|
||||
@ -134,7 +136,8 @@ void BrowserOptionDialog::showProxyLocationFileDialog()
|
||||
#else
|
||||
QString fileTypeFilter(QString("%1 (*)").arg(tr("Executable Files")));
|
||||
#endif
|
||||
auto proxyLocation = QFileDialog::getOpenFileName(this, tr("Select custom proxy location"),
|
||||
auto proxyLocation = QFileDialog::getOpenFileName(this,
|
||||
tr("Select custom proxy location"),
|
||||
QFileInfo(QCoreApplication::applicationDirPath()).filePath(),
|
||||
fileTypeFilter);
|
||||
m_ui->customProxyLocation->setText(proxyLocation);
|
||||
|
7
src/browser/BrowserOptionDialog.h
Executable file → Normal file
7
src/browser/BrowserOptionDialog.h
Executable file → Normal file
@ -20,11 +20,12 @@
|
||||
#ifndef BROWSEROPTIONDIALOG_H
|
||||
#define BROWSEROPTIONDIALOG_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QScopedPointer>
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class BrowserOptionDialog;
|
||||
namespace Ui
|
||||
{
|
||||
class BrowserOptionDialog;
|
||||
}
|
||||
|
||||
class BrowserOptionDialog : public QWidget
|
||||
|
@ -17,41 +17,43 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QInputDialog>
|
||||
#include <QProgressDialog>
|
||||
#include <QMessageBox>
|
||||
#include "BrowserService.h"
|
||||
#include "BrowserSettings.h"
|
||||
#include "BrowserEntryConfig.h"
|
||||
#include "BrowserAccessControlDialog.h"
|
||||
#include "BrowserEntryConfig.h"
|
||||
#include "BrowserSettings.h"
|
||||
#include "core/Database.h"
|
||||
#include "core/Group.h"
|
||||
#include "core/EntrySearcher.h"
|
||||
#include "core/Group.h"
|
||||
#include "core/Metadata.h"
|
||||
#include "core/Uuid.h"
|
||||
#include "core/PasswordGenerator.h"
|
||||
#include "core/Uuid.h"
|
||||
#include "gui/MainWindow.h"
|
||||
|
||||
#include <QInputDialog>
|
||||
#include <QJsonArray>
|
||||
#include <QMessageBox>
|
||||
#include <QProgressDialog>
|
||||
|
||||
// de887cc3-0363-43b8-974b-5911b8816224
|
||||
static const unsigned char KEEPASSXCBROWSER_UUID_DATA[] = {
|
||||
0xde, 0x88, 0x7c, 0xc3, 0x03, 0x63, 0x43, 0xb8,
|
||||
0x97, 0x4b, 0x59, 0x11, 0xb8, 0x81, 0x62, 0x24
|
||||
};
|
||||
static const Uuid KEEPASSXCBROWSER_UUID = Uuid(QByteArray::fromRawData(reinterpret_cast<const char *>(KEEPASSXCBROWSER_UUID_DATA), sizeof(KEEPASSXCBROWSER_UUID_DATA)));
|
||||
static const unsigned char KEEPASSXCBROWSER_UUID_DATA[] =
|
||||
{0xde, 0x88, 0x7c, 0xc3, 0x03, 0x63, 0x43, 0xb8, 0x97, 0x4b, 0x59, 0x11, 0xb8, 0x81, 0x62, 0x24};
|
||||
static const Uuid KEEPASSXCBROWSER_UUID =
|
||||
Uuid(QByteArray::fromRawData(reinterpret_cast<const char*>(KEEPASSXCBROWSER_UUID_DATA),
|
||||
sizeof(KEEPASSXCBROWSER_UUID_DATA)));
|
||||
static const char KEEPASSXCBROWSER_NAME[] = "KeePassXC-Browser Settings";
|
||||
static const char ASSOCIATE_KEY_PREFIX[] = "Public Key: ";
|
||||
static const char KEEPASSXCBROWSER_GROUP_NAME[] = "KeePassXC-Browser Passwords";
|
||||
static int KEEPASSXCBROWSER_DEFAULT_ICON = 1;
|
||||
static int KEEPASSXCBROWSER_DEFAULT_ICON = 1;
|
||||
|
||||
BrowserService::BrowserService(DatabaseTabWidget* parent) :
|
||||
m_dbTabWidget(parent),
|
||||
m_dialogActive(false)
|
||||
BrowserService::BrowserService(DatabaseTabWidget* parent)
|
||||
: m_dbTabWidget(parent)
|
||||
, m_dialogActive(false)
|
||||
{
|
||||
connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), this, SLOT(databaseLocked(DatabaseWidget*)));
|
||||
connect(m_dbTabWidget, SIGNAL(databaseUnlocked(DatabaseWidget*)), this, SLOT(databaseUnlocked(DatabaseWidget*)));
|
||||
connect(m_dbTabWidget, SIGNAL(activateDatabaseChanged(DatabaseWidget*)), this, SLOT(activateDatabaseChanged(DatabaseWidget*)));
|
||||
connect(m_dbTabWidget,
|
||||
SIGNAL(activateDatabaseChanged(DatabaseWidget*)),
|
||||
this,
|
||||
SLOT(activateDatabaseChanged(DatabaseWidget*)));
|
||||
}
|
||||
|
||||
bool BrowserService::isDatabaseOpened() const
|
||||
@ -62,7 +64,6 @@ bool BrowserService::isDatabaseOpened() const
|
||||
}
|
||||
|
||||
return dbWidget->currentMode() == DatabaseWidget::ViewMode || dbWidget->currentMode() == DatabaseWidget::EditMode;
|
||||
|
||||
}
|
||||
|
||||
bool BrowserService::openDatabase(bool triggerUnlock)
|
||||
@ -167,9 +168,8 @@ QString BrowserService::storeKey(const QString& key)
|
||||
QString id;
|
||||
|
||||
if (thread() != QThread::currentThread()) {
|
||||
QMetaObject::invokeMethod(this, "storeKey", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(QString, id),
|
||||
Q_ARG(const QString&, key));
|
||||
QMetaObject::invokeMethod(
|
||||
this, "storeKey", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, id), Q_ARG(const QString&, key));
|
||||
return id;
|
||||
}
|
||||
|
||||
@ -185,8 +185,8 @@ QString BrowserService::storeKey(const QString& key)
|
||||
QInputDialog keyDialog;
|
||||
keyDialog.setWindowTitle(tr("KeePassXC: New key association request"));
|
||||
keyDialog.setLabelText(tr("You have received an association request for the above key.\n\n"
|
||||
"If you would like to allow it access to your KeePassXC database,\n"
|
||||
"give it a unique name to identify and accept it."));
|
||||
"If you would like to allow it access to your KeePassXC database,\n"
|
||||
"give it a unique name to identify and accept it."));
|
||||
keyDialog.setOkButtonText(tr("Save and allow access"));
|
||||
keyDialog.setWindowFlags(keyDialog.windowFlags() | Qt::WindowStaysOnTopHint);
|
||||
keyDialog.show();
|
||||
@ -202,7 +202,8 @@ QString BrowserService::storeKey(const QString& key)
|
||||
|
||||
contains = config->attributes()->contains(QLatin1String(ASSOCIATE_KEY_PREFIX) + id);
|
||||
if (contains) {
|
||||
dialogResult = QMessageBox::warning(nullptr, tr("KeePassXC: Overwrite existing key?"),
|
||||
dialogResult = QMessageBox::warning(nullptr,
|
||||
tr("KeePassXC: Overwrite existing key?"),
|
||||
tr("A shared encryption key with the name \"%1\" "
|
||||
"already exists.\nDo you want to overwrite it?")
|
||||
.arg(id),
|
||||
@ -224,11 +225,16 @@ QString BrowserService::getKey(const QString& id)
|
||||
return config->attributes()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + id);
|
||||
}
|
||||
|
||||
QJsonArray BrowserService::findMatchingEntries(const QString& id, const QString& url, const QString& submitUrl, const QString& realm)
|
||||
QJsonArray BrowserService::findMatchingEntries(const QString& id,
|
||||
const QString& url,
|
||||
const QString& submitUrl,
|
||||
const QString& realm)
|
||||
{
|
||||
QJsonArray result;
|
||||
if (thread() != QThread::currentThread()) {
|
||||
QMetaObject::invokeMethod(this, "findMatchingEntries", Qt::BlockingQueuedConnection,
|
||||
QMetaObject::invokeMethod(this,
|
||||
"findMatchingEntries",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(QJsonArray, result),
|
||||
Q_ARG(const QString&, id),
|
||||
Q_ARG(const QString&, url),
|
||||
@ -283,7 +289,12 @@ QJsonArray BrowserService::findMatchingEntries(const QString& id, const QString&
|
||||
return result;
|
||||
}
|
||||
|
||||
void BrowserService::addEntry(const QString&, const QString& login, const QString& password, const QString& url, const QString& submitUrl, const QString& realm)
|
||||
void BrowserService::addEntry(const QString&,
|
||||
const QString& login,
|
||||
const QString& password,
|
||||
const QString& url,
|
||||
const QString& submitUrl,
|
||||
const QString& realm)
|
||||
{
|
||||
Group* group = findCreateAddEntryGroup();
|
||||
if (!group) {
|
||||
@ -313,10 +324,16 @@ void BrowserService::addEntry(const QString&, const QString& login, const QStrin
|
||||
config.save(entry);
|
||||
}
|
||||
|
||||
void BrowserService::updateEntry(const QString& id, const QString& uuid, const QString& login, const QString& password, const QString& url)
|
||||
void BrowserService::updateEntry(const QString& id,
|
||||
const QString& uuid,
|
||||
const QString& login,
|
||||
const QString& password,
|
||||
const QString& url)
|
||||
{
|
||||
if (thread() != QThread::currentThread()) {
|
||||
QMetaObject::invokeMethod(this, "updateEntry", Qt::BlockingQueuedConnection,
|
||||
QMetaObject::invokeMethod(this,
|
||||
"updateEntry",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_ARG(const QString&, id),
|
||||
Q_ARG(const QString&, uuid),
|
||||
Q_ARG(const QString&, login),
|
||||
@ -339,13 +356,15 @@ void BrowserService::updateEntry(const QString& id, const QString& uuid, const Q
|
||||
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) {
|
||||
QMessageBox::StandardButton dialogResult = QMessageBox::No;
|
||||
if (!BrowserSettings::alwaysAllowUpdate()) {
|
||||
dialogResult = QMessageBox::warning(0, tr("KeePassXC: Update Entry"),
|
||||
tr("Do you want to update the information in %1 - %2?")
|
||||
.arg(QUrl(url).host()).arg(username),
|
||||
QMessageBox::Yes|QMessageBox::No);
|
||||
dialogResult = QMessageBox::warning(
|
||||
0,
|
||||
tr("KeePassXC: Update Entry"),
|
||||
tr("Do you want to update the information in %1 - %2?").arg(QUrl(url).host()).arg(username),
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
}
|
||||
|
||||
if (BrowserSettings::alwaysAllowUpdate() || dialogResult == QMessageBox::Yes) {
|
||||
@ -370,11 +389,10 @@ QList<Entry*> BrowserService::searchEntries(Database* db, const QString& hostnam
|
||||
QString url = entry->url();
|
||||
|
||||
// Filter to match hostname in Title and Url fields
|
||||
if ((!title.isEmpty() && hostname.contains(title))
|
||||
|| (!url.isEmpty() && hostname.contains(url))
|
||||
if ((!title.isEmpty() && hostname.contains(title)) || (!url.isEmpty() && hostname.contains(url))
|
||||
|| (matchUrlScheme(title) && hostname.endsWith(QUrl(title).host()))
|
||||
|| (matchUrlScheme(url) && hostname.endsWith(QUrl(url).host())) ) {
|
||||
entries.append(entry);
|
||||
|| (matchUrlScheme(url) && hostname.endsWith(QUrl(url).host()))) {
|
||||
entries.append(entry);
|
||||
}
|
||||
}
|
||||
|
||||
@ -413,7 +431,8 @@ QList<Entry*> BrowserService::searchEntries(const QString& text)
|
||||
void BrowserService::removeSharedEncryptionKeys()
|
||||
{
|
||||
if (!isDatabaseOpened()) {
|
||||
QMessageBox::critical(0, tr("KeePassXC: Database locked!"),
|
||||
QMessageBox::critical(0,
|
||||
tr("KeePassXC: Database locked!"),
|
||||
tr("The active database is locked!\n"
|
||||
"Please unlock the selected database or choose another one which is unlocked."),
|
||||
QMessageBox::Ok);
|
||||
@ -422,7 +441,8 @@ void BrowserService::removeSharedEncryptionKeys()
|
||||
|
||||
Entry* entry = getConfigEntry();
|
||||
if (!entry) {
|
||||
QMessageBox::information(0, tr("KeePassXC: Settings not available!"),
|
||||
QMessageBox::information(0,
|
||||
tr("KeePassXC: Settings not available!"),
|
||||
tr("The active database does not contain a settings entry."),
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
@ -436,7 +456,8 @@ void BrowserService::removeSharedEncryptionKeys()
|
||||
}
|
||||
|
||||
if (keysToRemove.isEmpty()) {
|
||||
QMessageBox::information(0, tr("KeePassXC: No keys found"),
|
||||
QMessageBox::information(0,
|
||||
tr("KeePassXC: No keys found"),
|
||||
tr("No shared encryption keys found in KeePassXC settings."),
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
@ -449,16 +470,17 @@ void BrowserService::removeSharedEncryptionKeys()
|
||||
entry->endUpdate();
|
||||
|
||||
const int count = keysToRemove.count();
|
||||
QMessageBox::information(0, tr("KeePassXC: Removed keys from database"),
|
||||
QMessageBox::information(0,
|
||||
tr("KeePassXC: Removed keys from database"),
|
||||
tr("Successfully removed %n encryption key(s) from KeePassXC settings.", "", count),
|
||||
QMessageBox::Ok);
|
||||
|
||||
}
|
||||
|
||||
void BrowserService::removeStoredPermissions()
|
||||
{
|
||||
if (!isDatabaseOpened()) {
|
||||
QMessageBox::critical(0, tr("KeePassXC: Database locked!"),
|
||||
QMessageBox::critical(0,
|
||||
tr("KeePassXC: Database locked!"),
|
||||
tr("The active database is locked!\n"
|
||||
"Please unlock the selected database or choose another one which is unlocked."),
|
||||
QMessageBox::Ok);
|
||||
@ -492,11 +514,13 @@ void BrowserService::removeStoredPermissions()
|
||||
progress.reset();
|
||||
|
||||
if (counter > 0) {
|
||||
QMessageBox::information(0, tr("KeePassXC: Removed permissions"),
|
||||
QMessageBox::information(0,
|
||||
tr("KeePassXC: Removed permissions"),
|
||||
tr("Successfully removed permissions from %n entry(s).", "", counter),
|
||||
QMessageBox::Ok);
|
||||
} else {
|
||||
QMessageBox::information(0, tr("KeePassXC: No entry with permissions found!"),
|
||||
QMessageBox::information(0,
|
||||
tr("KeePassXC: No entry with permissions found!"),
|
||||
tr("The active database does not contain an entry with permissions."),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
@ -510,7 +534,8 @@ QList<Entry*> BrowserService::sortEntries(QList<Entry*>& pwEntries, const QStrin
|
||||
}
|
||||
|
||||
const QString submitUrl = url.toString(QUrl::StripTrailingSlash);
|
||||
const QString baseSubmitUrl = url.toString(QUrl::StripTrailingSlash | QUrl::RemovePath | QUrl::RemoveQuery | QUrl::RemoveFragment);
|
||||
const QString baseSubmitUrl =
|
||||
url.toString(QUrl::StripTrailingSlash | QUrl::RemovePath | QUrl::RemoveQuery | QUrl::RemoveFragment);
|
||||
|
||||
QMultiMap<int, const Entry*> priorities;
|
||||
for (const Entry* entry : pwEntries) {
|
||||
@ -529,7 +554,11 @@ QList<Entry*> BrowserService::sortEntries(QList<Entry*>& pwEntries, const QStrin
|
||||
return pwEntries;
|
||||
}
|
||||
|
||||
bool BrowserService::confirmEntries(QList<Entry*>& pwEntriesToConfirm, const QString& url, const QString& host, const QString& submitHost, const QString& realm)
|
||||
bool BrowserService::confirmEntries(QList<Entry*>& pwEntriesToConfirm,
|
||||
const QString& url,
|
||||
const QString& host,
|
||||
const QString& submitHost,
|
||||
const QString& realm)
|
||||
{
|
||||
if (pwEntriesToConfirm.isEmpty() || m_dialogActive) {
|
||||
return false;
|
||||
@ -593,7 +622,8 @@ QJsonObject BrowserService::prepareEntry(const Entry* entry)
|
||||
return res;
|
||||
}
|
||||
|
||||
BrowserService::Access BrowserService::checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm)
|
||||
BrowserService::Access
|
||||
BrowserService::checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm)
|
||||
{
|
||||
BrowserEntryConfig config;
|
||||
if (!config.load(entry)) {
|
||||
@ -623,7 +653,8 @@ Group* BrowserService::findCreateAddEntryGroup()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const QString groupName = QLatin1String(KEEPASSXCBROWSER_GROUP_NAME); //TODO: setting to decide where new keys are created
|
||||
const QString groupName =
|
||||
QLatin1String(KEEPASSXCBROWSER_GROUP_NAME); // TODO: setting to decide where new keys are created
|
||||
|
||||
for (const Group* g : rootGroup->groupsRecursive(true)) {
|
||||
if (g->name() == groupName) {
|
||||
@ -639,14 +670,18 @@ Group* BrowserService::findCreateAddEntryGroup()
|
||||
return group;
|
||||
}
|
||||
|
||||
int BrowserService::sortPriority(const Entry* entry, const QString& host, const QString& submitUrl, const QString& baseSubmitUrl) const
|
||||
int BrowserService::sortPriority(const Entry* entry,
|
||||
const QString& host,
|
||||
const QString& submitUrl,
|
||||
const QString& baseSubmitUrl) const
|
||||
{
|
||||
QUrl url(entry->url());
|
||||
if (url.scheme().isEmpty()) {
|
||||
url.setScheme("http");
|
||||
}
|
||||
const QString entryURL = url.toString(QUrl::StripTrailingSlash);
|
||||
const QString baseEntryURL = url.toString(QUrl::StripTrailingSlash | QUrl::RemovePath | QUrl::RemoveQuery | QUrl::RemoveFragment);
|
||||
const QString baseEntryURL =
|
||||
url.toString(QUrl::StripTrailingSlash | QUrl::RemovePath | QUrl::RemoveQuery | QUrl::RemoveFragment);
|
||||
|
||||
if (submitUrl == entryURL) {
|
||||
return 100;
|
||||
|
@ -20,63 +20,86 @@
|
||||
#ifndef BROWSERSERVICE_H
|
||||
#define BROWSERSERVICE_H
|
||||
|
||||
#include <QtCore>
|
||||
#include <QObject>
|
||||
#include "gui/DatabaseTabWidget.h"
|
||||
#include "core/Entry.h"
|
||||
#include "gui/DatabaseTabWidget.h"
|
||||
#include <QObject>
|
||||
#include <QtCore>
|
||||
|
||||
enum { max_length = 16*1024 };
|
||||
enum
|
||||
{
|
||||
max_length = 16 * 1024
|
||||
};
|
||||
|
||||
class BrowserService : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BrowserService(DatabaseTabWidget* parent);
|
||||
explicit BrowserService(DatabaseTabWidget* parent);
|
||||
|
||||
bool isDatabaseOpened() const;
|
||||
bool openDatabase(bool triggerUnlock);
|
||||
QString getDatabaseRootUuid();
|
||||
QString getDatabaseRecycleBinUuid();
|
||||
Entry* getConfigEntry(bool create = false);
|
||||
QString getKey(const QString& id);
|
||||
void addEntry(const QString& id, const QString& login, const QString& password, const QString& url, const QString& submitUrl, const QString& realm);
|
||||
QList<Entry*> searchEntries(Database* db, const QString& hostname);
|
||||
QList<Entry*> searchEntries(const QString& text);
|
||||
void removeSharedEncryptionKeys();
|
||||
void removeStoredPermissions();
|
||||
bool isDatabaseOpened() const;
|
||||
bool openDatabase(bool triggerUnlock);
|
||||
QString getDatabaseRootUuid();
|
||||
QString getDatabaseRecycleBinUuid();
|
||||
Entry* getConfigEntry(bool create = false);
|
||||
QString getKey(const QString& id);
|
||||
void addEntry(const QString& id,
|
||||
const QString& login,
|
||||
const QString& password,
|
||||
const QString& url,
|
||||
const QString& submitUrl,
|
||||
const QString& realm);
|
||||
QList<Entry*> searchEntries(Database* db, const QString& hostname);
|
||||
QList<Entry*> searchEntries(const QString& text);
|
||||
void removeSharedEncryptionKeys();
|
||||
void removeStoredPermissions();
|
||||
|
||||
public slots:
|
||||
QJsonArray findMatchingEntries(const QString& id, const QString& url, const QString& submitUrl, const QString& realm);
|
||||
QString storeKey(const QString& key);
|
||||
void updateEntry(const QString& id, const QString& uuid, const QString& login, const QString& password, const QString& url);
|
||||
void databaseLocked(DatabaseWidget* dbWidget);
|
||||
void databaseUnlocked(DatabaseWidget* dbWidget);
|
||||
void activateDatabaseChanged(DatabaseWidget* dbWidget);
|
||||
void lockDatabase();
|
||||
QJsonArray
|
||||
findMatchingEntries(const QString& id, const QString& url, const QString& submitUrl, const QString& realm);
|
||||
QString storeKey(const QString& key);
|
||||
void updateEntry(const QString& id,
|
||||
const QString& uuid,
|
||||
const QString& login,
|
||||
const QString& password,
|
||||
const QString& url);
|
||||
void databaseLocked(DatabaseWidget* dbWidget);
|
||||
void databaseUnlocked(DatabaseWidget* dbWidget);
|
||||
void activateDatabaseChanged(DatabaseWidget* dbWidget);
|
||||
void lockDatabase();
|
||||
|
||||
signals:
|
||||
void databaseLocked();
|
||||
void databaseUnlocked();
|
||||
void databaseChanged();
|
||||
void databaseLocked();
|
||||
void databaseUnlocked();
|
||||
void databaseChanged();
|
||||
|
||||
private:
|
||||
enum Access { Denied, Unknown, Allowed};
|
||||
enum Access
|
||||
{
|
||||
Denied,
|
||||
Unknown,
|
||||
Allowed
|
||||
};
|
||||
|
||||
private:
|
||||
QList<Entry*> sortEntries(QList<Entry*>& pwEntries, const QString& host, const QString& submitUrl);
|
||||
bool confirmEntries(QList<Entry*>& pwEntriesToConfirm, const QString& url, const QString& host, const QString& submitHost, const QString& realm);
|
||||
QJsonObject prepareEntry(const Entry* entry);
|
||||
Access checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm);
|
||||
Group* findCreateAddEntryGroup();
|
||||
int sortPriority(const Entry* entry, const QString &host, const QString& submitUrl, const QString& baseSubmitUrl) const;
|
||||
bool matchUrlScheme(const QString& url);
|
||||
bool removeFirstDomain(QString& hostname);
|
||||
Database* getDatabase();
|
||||
QList<Entry*> sortEntries(QList<Entry*>& pwEntries, const QString& host, const QString& submitUrl);
|
||||
bool confirmEntries(QList<Entry*>& pwEntriesToConfirm,
|
||||
const QString& url,
|
||||
const QString& host,
|
||||
const QString& submitHost,
|
||||
const QString& realm);
|
||||
QJsonObject prepareEntry(const Entry* entry);
|
||||
Access checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm);
|
||||
Group* findCreateAddEntryGroup();
|
||||
int
|
||||
sortPriority(const Entry* entry, const QString& host, const QString& submitUrl, const QString& baseSubmitUrl) const;
|
||||
bool matchUrlScheme(const QString& url);
|
||||
bool removeFirstDomain(QString& hostname);
|
||||
Database* getDatabase();
|
||||
|
||||
private:
|
||||
DatabaseTabWidget* const m_dbTabWidget;
|
||||
bool m_dialogActive;
|
||||
DatabaseTabWidget* const m_dbTabWidget;
|
||||
bool m_dialogActive;
|
||||
};
|
||||
|
||||
#endif // BROWSERSERVICE_H
|
||||
|
36
src/browser/BrowserSettings.cpp
Executable file → Normal file
36
src/browser/BrowserSettings.cpp
Executable file → Normal file
@ -177,36 +177,48 @@ void BrowserSettings::setUpdateBinaryPath(bool enabled)
|
||||
config()->set("Browser/UpdateBinaryPath", enabled);
|
||||
}
|
||||
|
||||
bool BrowserSettings::chromeSupport() {
|
||||
bool BrowserSettings::chromeSupport()
|
||||
{
|
||||
return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::CHROME);
|
||||
}
|
||||
|
||||
void BrowserSettings::setChromeSupport(bool enabled) {
|
||||
m_hostInstaller.installBrowser(HostInstaller::SupportedBrowsers::CHROME, enabled, supportBrowserProxy(), customProxyLocation());
|
||||
void BrowserSettings::setChromeSupport(bool enabled)
|
||||
{
|
||||
m_hostInstaller.installBrowser(
|
||||
HostInstaller::SupportedBrowsers::CHROME, enabled, supportBrowserProxy(), customProxyLocation());
|
||||
}
|
||||
|
||||
bool BrowserSettings::chromiumSupport() {
|
||||
bool BrowserSettings::chromiumSupport()
|
||||
{
|
||||
return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::CHROMIUM);
|
||||
}
|
||||
|
||||
void BrowserSettings::setChromiumSupport(bool enabled) {
|
||||
m_hostInstaller.installBrowser(HostInstaller::SupportedBrowsers::CHROMIUM, enabled, supportBrowserProxy(), customProxyLocation());
|
||||
void BrowserSettings::setChromiumSupport(bool enabled)
|
||||
{
|
||||
m_hostInstaller.installBrowser(
|
||||
HostInstaller::SupportedBrowsers::CHROMIUM, enabled, supportBrowserProxy(), customProxyLocation());
|
||||
}
|
||||
|
||||
bool BrowserSettings::firefoxSupport() {
|
||||
bool BrowserSettings::firefoxSupport()
|
||||
{
|
||||
return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::FIREFOX);
|
||||
}
|
||||
|
||||
void BrowserSettings::setFirefoxSupport(bool enabled) {
|
||||
m_hostInstaller.installBrowser(HostInstaller::SupportedBrowsers::FIREFOX, enabled, supportBrowserProxy(), customProxyLocation());
|
||||
void BrowserSettings::setFirefoxSupport(bool enabled)
|
||||
{
|
||||
m_hostInstaller.installBrowser(
|
||||
HostInstaller::SupportedBrowsers::FIREFOX, enabled, supportBrowserProxy(), customProxyLocation());
|
||||
}
|
||||
|
||||
bool BrowserSettings::vivaldiSupport() {
|
||||
bool BrowserSettings::vivaldiSupport()
|
||||
{
|
||||
return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::VIVALDI);
|
||||
}
|
||||
|
||||
void BrowserSettings::setVivaldiSupport(bool enabled) {
|
||||
m_hostInstaller.installBrowser(HostInstaller::SupportedBrowsers::VIVALDI, enabled, supportBrowserProxy(), customProxyLocation());
|
||||
void BrowserSettings::setVivaldiSupport(bool enabled)
|
||||
{
|
||||
m_hostInstaller.installBrowser(
|
||||
HostInstaller::SupportedBrowsers::VIVALDI, enabled, supportBrowserProxy(), customProxyLocation());
|
||||
}
|
||||
|
||||
bool BrowserSettings::passwordUseNumbers()
|
||||
|
12
src/browser/BrowserSettings.h
Executable file → Normal file
12
src/browser/BrowserSettings.h
Executable file → Normal file
@ -20,9 +20,9 @@
|
||||
#ifndef BROWSERSETTINGS_H
|
||||
#define BROWSERSETTINGS_H
|
||||
|
||||
#include "core/PasswordGenerator.h"
|
||||
#include "core/PassphraseGenerator.h"
|
||||
#include "HostInstaller.h"
|
||||
#include "core/PassphraseGenerator.h"
|
||||
#include "core/PasswordGenerator.h"
|
||||
|
||||
class BrowserSettings
|
||||
{
|
||||
@ -30,9 +30,9 @@ public:
|
||||
static bool isEnabled();
|
||||
static void setEnabled(bool enabled);
|
||||
|
||||
static bool showNotification(); //TODO!!
|
||||
static bool showNotification(); // TODO!!
|
||||
static void setShowNotification(bool showNotification);
|
||||
static bool bestMatchOnly(); //TODO!!
|
||||
static bool bestMatchOnly(); // TODO!!
|
||||
static void setBestMatchOnly(bool bestMatchOnly);
|
||||
static bool unlockDatabase();
|
||||
static void setUnlockDatabase(bool unlockDatabase);
|
||||
@ -46,7 +46,7 @@ public:
|
||||
static void setAlwaysAllowAccess(bool alwaysAllowAccess);
|
||||
static bool alwaysAllowUpdate();
|
||||
static void setAlwaysAllowUpdate(bool alwaysAllowUpdate);
|
||||
static bool searchInAllDatabases();//TODO!!
|
||||
static bool searchInAllDatabases(); // TODO!!
|
||||
static void setSearchInAllDatabases(bool searchInAllDatabases);
|
||||
static bool supportKphFields();
|
||||
static void setSupportKphFields(bool supportKphFields);
|
||||
@ -88,7 +88,7 @@ public:
|
||||
static void setPasswordEveryGroup(bool everyGroup);
|
||||
static bool passwordExcludeAlike();
|
||||
static void setPasswordExcludeAlike(bool excludeAlike);
|
||||
static int passwordLength();
|
||||
static int passwordLength();
|
||||
static void setPasswordLength(int length);
|
||||
static PasswordGenerator::CharClasses passwordCharClasses();
|
||||
static PasswordGenerator::GeneratorFlags passwordGeneratorFlags();
|
||||
|
@ -18,43 +18,45 @@
|
||||
|
||||
#include "HostInstaller.h"
|
||||
#include "config-keepassx.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QStandardPaths>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QCoreApplication>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QMessageBox>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QStandardPaths>
|
||||
|
||||
const QString HostInstaller::HOST_NAME = "org.keepassxc.keepassxc_browser";
|
||||
const QStringList HostInstaller::ALLOWED_ORIGINS = QStringList()
|
||||
<< "chrome-extension://iopaggbpplllidnfmcghoonnokmjoicf/"
|
||||
<< "chrome-extension://oboonakemofpalcgghocfoadofidjkkk/";
|
||||
<< "chrome-extension://iopaggbpplllidnfmcghoonnokmjoicf/"
|
||||
<< "chrome-extension://oboonakemofpalcgghocfoadofidjkkk/";
|
||||
|
||||
const QStringList HostInstaller::ALLOWED_EXTENSIONS = QStringList()
|
||||
<< "keepassxc-browser@keepassxc.org";
|
||||
const QStringList HostInstaller::ALLOWED_EXTENSIONS = QStringList() << "keepassxc-browser@keepassxc.org";
|
||||
|
||||
#if defined(Q_OS_OSX)
|
||||
const QString HostInstaller::TARGET_DIR_CHROME = "/Library/Application Support/Google/Chrome/NativeMessagingHosts";
|
||||
const QString HostInstaller::TARGET_DIR_CHROMIUM = "/Library/Application Support/Chromium/NativeMessagingHosts";
|
||||
const QString HostInstaller::TARGET_DIR_FIREFOX = "/Library/Application Support/Mozilla/NativeMessagingHosts";
|
||||
const QString HostInstaller::TARGET_DIR_VIVALDI = "/Library/Application Support/Vivaldi/NativeMessagingHosts";
|
||||
const QString HostInstaller::TARGET_DIR_CHROME = "/Library/Application Support/Google/Chrome/NativeMessagingHosts";
|
||||
const QString HostInstaller::TARGET_DIR_CHROMIUM = "/Library/Application Support/Chromium/NativeMessagingHosts";
|
||||
const QString HostInstaller::TARGET_DIR_FIREFOX = "/Library/Application Support/Mozilla/NativeMessagingHosts";
|
||||
const QString HostInstaller::TARGET_DIR_VIVALDI = "/Library/Application Support/Vivaldi/NativeMessagingHosts";
|
||||
#elif defined(Q_OS_LINUX)
|
||||
const QString HostInstaller::TARGET_DIR_CHROME = "/.config/google-chrome/NativeMessagingHosts";
|
||||
const QString HostInstaller::TARGET_DIR_CHROMIUM = "/.config/chromium/NativeMessagingHosts";
|
||||
const QString HostInstaller::TARGET_DIR_FIREFOX = "/.mozilla/native-messaging-hosts";
|
||||
const QString HostInstaller::TARGET_DIR_VIVALDI = "/.config/vivaldi/NativeMessagingHosts";
|
||||
const QString HostInstaller::TARGET_DIR_CHROME = "/.config/google-chrome/NativeMessagingHosts";
|
||||
const QString HostInstaller::TARGET_DIR_CHROMIUM = "/.config/chromium/NativeMessagingHosts";
|
||||
const QString HostInstaller::TARGET_DIR_FIREFOX = "/.mozilla/native-messaging-hosts";
|
||||
const QString HostInstaller::TARGET_DIR_VIVALDI = "/.config/vivaldi/NativeMessagingHosts";
|
||||
#elif defined(Q_OS_WIN)
|
||||
const QString HostInstaller::TARGET_DIR_CHROME = "HKEY_CURRENT_USER\\Software\\Google\\Chrome\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME;
|
||||
const QString HostInstaller::TARGET_DIR_CHROMIUM = "HKEY_CURRENT_USER\\Software\\Chromium\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME;
|
||||
const QString HostInstaller::TARGET_DIR_FIREFOX = "HKEY_CURRENT_USER\\Software\\Mozilla\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME;
|
||||
const QString HostInstaller::TARGET_DIR_VIVALDI = "HKEY_CURRENT_USER\\Software\\Vivaldi\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME;
|
||||
const QString HostInstaller::TARGET_DIR_CHROME =
|
||||
"HKEY_CURRENT_USER\\Software\\Google\\Chrome\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME;
|
||||
const QString HostInstaller::TARGET_DIR_CHROMIUM =
|
||||
"HKEY_CURRENT_USER\\Software\\Chromium\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME;
|
||||
const QString HostInstaller::TARGET_DIR_FIREFOX =
|
||||
"HKEY_CURRENT_USER\\Software\\Mozilla\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME;
|
||||
const QString HostInstaller::TARGET_DIR_VIVALDI =
|
||||
"HKEY_CURRENT_USER\\Software\\Vivaldi\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME;
|
||||
#endif
|
||||
|
||||
HostInstaller::HostInstaller()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool HostInstaller::checkIfInstalled(SupportedBrowsers browser)
|
||||
@ -68,34 +70,39 @@ bool HostInstaller::checkIfInstalled(SupportedBrowsers browser)
|
||||
#endif
|
||||
}
|
||||
|
||||
void HostInstaller::installBrowser(SupportedBrowsers browser, const bool& enabled, const bool& proxy, const QString& location)
|
||||
void HostInstaller::installBrowser(SupportedBrowsers browser,
|
||||
const bool& enabled,
|
||||
const bool& proxy,
|
||||
const QString& location)
|
||||
{
|
||||
if (enabled) {
|
||||
#ifdef Q_OS_WIN
|
||||
// Create a registry key
|
||||
QSettings settings(getTargetPath(browser), QSettings::NativeFormat);
|
||||
if (!registryEntryFound(settings)) {
|
||||
settings.setValue("Default", getPath(browser));
|
||||
}
|
||||
#endif
|
||||
// Always create the script file
|
||||
QJsonObject script = constructFile(browser, proxy, location);
|
||||
if (!saveFile(browser, script)) {
|
||||
QMessageBox::critical(0, tr("KeePassXC: Cannot save file!"),
|
||||
tr("Cannot save the native messaging script file."), QMessageBox::Ok);
|
||||
}
|
||||
} else {
|
||||
// Remove the script file
|
||||
QString fileName = getPath(browser);
|
||||
QFile::remove(fileName);
|
||||
#ifdef Q_OS_WIN
|
||||
// Remove the registry entry
|
||||
QSettings settings(getTargetPath(browser), QSettings::NativeFormat);
|
||||
if (registryEntryFound(settings)) {
|
||||
settings.remove("Default");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef Q_OS_WIN
|
||||
// Create a registry key
|
||||
QSettings settings(getTargetPath(browser), QSettings::NativeFormat);
|
||||
if (!registryEntryFound(settings)) {
|
||||
settings.setValue("Default", getPath(browser));
|
||||
}
|
||||
#endif
|
||||
// Always create the script file
|
||||
QJsonObject script = constructFile(browser, proxy, location);
|
||||
if (!saveFile(browser, script)) {
|
||||
QMessageBox::critical(0,
|
||||
tr("KeePassXC: Cannot save file!"),
|
||||
tr("Cannot save the native messaging script file."),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
} else {
|
||||
// Remove the script file
|
||||
QString fileName = getPath(browser);
|
||||
QFile::remove(fileName);
|
||||
#ifdef Q_OS_WIN
|
||||
// Remove the registry entry
|
||||
QSettings settings(getTargetPath(browser), QSettings::NativeFormat);
|
||||
if (registryEntryFound(settings)) {
|
||||
settings.remove("Default");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void HostInstaller::updateBinaryPaths(const bool& proxy, const QString& location)
|
||||
@ -110,22 +117,32 @@ void HostInstaller::updateBinaryPaths(const bool& proxy, const QString& location
|
||||
QString HostInstaller::getTargetPath(SupportedBrowsers browser) const
|
||||
{
|
||||
switch (browser) {
|
||||
case SupportedBrowsers::CHROME: return HostInstaller::TARGET_DIR_CHROME;
|
||||
case SupportedBrowsers::CHROMIUM: return HostInstaller::TARGET_DIR_CHROMIUM;
|
||||
case SupportedBrowsers::FIREFOX: return HostInstaller::TARGET_DIR_FIREFOX;
|
||||
case SupportedBrowsers::VIVALDI: return HostInstaller::TARGET_DIR_VIVALDI;
|
||||
default: return QString();
|
||||
case SupportedBrowsers::CHROME:
|
||||
return HostInstaller::TARGET_DIR_CHROME;
|
||||
case SupportedBrowsers::CHROMIUM:
|
||||
return HostInstaller::TARGET_DIR_CHROMIUM;
|
||||
case SupportedBrowsers::FIREFOX:
|
||||
return HostInstaller::TARGET_DIR_FIREFOX;
|
||||
case SupportedBrowsers::VIVALDI:
|
||||
return HostInstaller::TARGET_DIR_VIVALDI;
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
QString HostInstaller::getBrowserName(SupportedBrowsers browser) const
|
||||
{
|
||||
switch (browser) {
|
||||
case SupportedBrowsers::CHROME: return "chrome";
|
||||
case SupportedBrowsers::CHROMIUM: return "chromium";
|
||||
case SupportedBrowsers::FIREFOX: return "firefox";
|
||||
case SupportedBrowsers::VIVALDI: return "vivaldi";
|
||||
default: return QString();
|
||||
case SupportedBrowsers::CHROME:
|
||||
return "chrome";
|
||||
case SupportedBrowsers::CHROMIUM:
|
||||
return "chromium";
|
||||
case SupportedBrowsers::FIREFOX:
|
||||
return "firefox";
|
||||
case SupportedBrowsers::VIVALDI:
|
||||
return "vivaldi";
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,7 +159,7 @@ QString HostInstaller::getPath(SupportedBrowsers browser) const
|
||||
}
|
||||
|
||||
QString winPath = QString("%1/%2_%3.json").arg(userPath, HostInstaller::HOST_NAME, getBrowserName(browser));
|
||||
winPath.replace("/","\\");
|
||||
winPath.replace("/", "\\");
|
||||
return winPath;
|
||||
#else
|
||||
QString path = getTargetPath(browser);
|
||||
@ -184,16 +201,16 @@ QJsonObject HostInstaller::constructFile(SupportedBrowsers browser, const bool&
|
||||
path = QFileInfo(QCoreApplication::applicationFilePath()).absoluteFilePath();
|
||||
}
|
||||
#ifdef Q_OS_WIN
|
||||
path.replace("/","\\");
|
||||
path.replace("/", "\\");
|
||||
#endif
|
||||
|
||||
#endif // #ifdef KEEPASSXC_DIST_APPIMAGE
|
||||
#endif // #ifdef KEEPASSXC_DIST_APPIMAGE
|
||||
|
||||
QJsonObject script;
|
||||
script["name"] = HostInstaller::HOST_NAME;
|
||||
script["description"] = "KeePassXC integration with native messaging support";
|
||||
script["path"] = path;
|
||||
script["type"] = "stdio";
|
||||
script["name"] = HostInstaller::HOST_NAME;
|
||||
script["description"] = "KeePassXC integration with native messaging support";
|
||||
script["path"] = path;
|
||||
script["type"] = "stdio";
|
||||
|
||||
QJsonArray arr;
|
||||
if (browser == SupportedBrowsers::FIREFOX) {
|
||||
|
@ -19,8 +19,8 @@
|
||||
#ifndef HOSTINSTALLER_H
|
||||
#define HOSTINSTALLER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QJsonObject>
|
||||
#include <QObject>
|
||||
#include <QSettings>
|
||||
|
||||
class HostInstaller : public QObject
|
||||
@ -28,27 +28,31 @@ class HostInstaller : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum SupportedBrowsers : int {
|
||||
CHROME = 0,
|
||||
CHROMIUM = 1,
|
||||
FIREFOX = 2,
|
||||
VIVALDI = 3
|
||||
enum SupportedBrowsers : int
|
||||
{
|
||||
CHROME = 0,
|
||||
CHROMIUM = 1,
|
||||
FIREFOX = 2,
|
||||
VIVALDI = 3
|
||||
};
|
||||
|
||||
public:
|
||||
HostInstaller();
|
||||
bool checkIfInstalled(SupportedBrowsers browser);
|
||||
void installBrowser(SupportedBrowsers browser, const bool& enabled, const bool& proxy = false, const QString& location = "");
|
||||
void installBrowser(SupportedBrowsers browser,
|
||||
const bool& enabled,
|
||||
const bool& proxy = false,
|
||||
const QString& location = "");
|
||||
void updateBinaryPaths(const bool& proxy, const QString& location = "");
|
||||
|
||||
private:
|
||||
QString getTargetPath(SupportedBrowsers browser) const;
|
||||
QString getBrowserName(SupportedBrowsers browser) const;
|
||||
QString getPath(SupportedBrowsers browser) const;
|
||||
QString getInstallDir(SupportedBrowsers browser) const;
|
||||
QString getTargetPath(SupportedBrowsers browser) const;
|
||||
QString getBrowserName(SupportedBrowsers browser) const;
|
||||
QString getPath(SupportedBrowsers browser) const;
|
||||
QString getInstallDir(SupportedBrowsers browser) const;
|
||||
QJsonObject constructFile(SupportedBrowsers browser, const bool& proxy, const QString& location);
|
||||
bool registryEntryFound(const QSettings& settings);
|
||||
bool saveFile(SupportedBrowsers browser, const QJsonObject& script);
|
||||
bool registryEntryFound(const QSettings& settings);
|
||||
bool saveFile(SupportedBrowsers browser, const QJsonObject& script);
|
||||
|
||||
private:
|
||||
static const QString HOST_NAME;
|
||||
|
@ -20,9 +20,9 @@
|
||||
#include <QStandardPaths>
|
||||
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_LINUX)
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
@ -51,7 +51,7 @@ void NativeMessagingBase::newNativeMessage()
|
||||
{
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_LINUX)
|
||||
struct kevent ev[1];
|
||||
struct timespec ts = { 5, 0 };
|
||||
struct timespec ts = {5, 0};
|
||||
|
||||
int fd = kqueue();
|
||||
if (fd == -1) {
|
||||
@ -123,7 +123,8 @@ void NativeMessagingBase::sendReply(const QString& reply)
|
||||
if (!reply.isEmpty()) {
|
||||
QByteArray bytes = reply.toUtf8();
|
||||
uint len = bytes.size();
|
||||
std::cout << char(((len>>0) & 0xFF)) << char(((len>>8) & 0xFF)) << char(((len>>16) & 0xFF)) << char(((len>>24) & 0xFF));
|
||||
std::cout << char(((len >> 0) & 0xFF)) << char(((len >> 8) & 0xFF)) << char(((len >> 16) & 0xFF))
|
||||
<< char(((len >> 24) & 0xFF));
|
||||
std::cout << reply.toStdString() << std::flush;
|
||||
}
|
||||
}
|
||||
@ -136,7 +137,7 @@ QString NativeMessagingBase::getLocalServerPath() const
|
||||
// Use XDG_RUNTIME_DIR instead of /tmp/ if it's available
|
||||
QString path = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation) + "/kpxc_server";
|
||||
return path.isEmpty() ? "/tmp/kpxc_server" : path;
|
||||
#else // Q_OS_MAC and others
|
||||
#else // Q_OS_MAC and others
|
||||
return "/tmp/kpxc_server";
|
||||
#endif
|
||||
}
|
||||
|
@ -19,16 +19,16 @@
|
||||
#ifndef NATIVEMESSAGINGBASE_H
|
||||
#define NATIVEMESSAGINGBASE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
#include <QAtomicInteger>
|
||||
#include <QFuture>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <QMutex>
|
||||
#include <QSocketNotifier>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include <QAtomicInteger>
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
#include <QSocketNotifier>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
|
||||
@ -41,21 +41,21 @@ public:
|
||||
~NativeMessagingBase() = default;
|
||||
|
||||
protected slots:
|
||||
void newNativeMessage();
|
||||
void newNativeMessage();
|
||||
|
||||
protected:
|
||||
virtual void readLength() = 0;
|
||||
virtual void readStdIn(const quint32 length) = 0;
|
||||
void readNativeMessages();
|
||||
QString jsonToString(const QJsonObject& json) const;
|
||||
void sendReply(const QJsonObject& json);
|
||||
void sendReply(const QString& reply);
|
||||
QString getLocalServerPath() const;
|
||||
virtual void readLength() = 0;
|
||||
virtual void readStdIn(const quint32 length) = 0;
|
||||
void readNativeMessages();
|
||||
QString jsonToString(const QJsonObject& json) const;
|
||||
void sendReply(const QJsonObject& json);
|
||||
void sendReply(const QString& reply);
|
||||
QString getLocalServerPath() const;
|
||||
|
||||
protected:
|
||||
QAtomicInteger<quint8> m_running;
|
||||
QAtomicInteger<quint8> m_running;
|
||||
QSharedPointer<QSocketNotifier> m_notifier;
|
||||
QFuture<void> m_future;
|
||||
QFuture<void> m_future;
|
||||
};
|
||||
|
||||
#endif // NATIVEMESSAGINGBASE_H
|
||||
#endif // NATIVEMESSAGINGBASE_H
|
||||
|
24
src/browser/NativeMessagingHost.cpp
Executable file → Normal file
24
src/browser/NativeMessagingHost.cpp
Executable file → Normal file
@ -16,18 +16,18 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "NativeMessagingHost.h"
|
||||
#include "BrowserSettings.h"
|
||||
#include "sodium.h"
|
||||
#include <QMutexLocker>
|
||||
#include <QtNetwork>
|
||||
#include <iostream>
|
||||
#include "sodium.h"
|
||||
#include "NativeMessagingHost.h"
|
||||
#include "BrowserSettings.h"
|
||||
|
||||
NativeMessagingHost::NativeMessagingHost(DatabaseTabWidget* parent) :
|
||||
NativeMessagingBase(),
|
||||
m_mutex(QMutex::Recursive),
|
||||
m_browserClients(m_browserService),
|
||||
m_browserService(parent)
|
||||
NativeMessagingHost::NativeMessagingHost(DatabaseTabWidget* parent)
|
||||
: NativeMessagingBase()
|
||||
, m_mutex(QMutex::Recursive)
|
||||
, m_browserClients(m_browserService)
|
||||
, m_browserService(parent)
|
||||
{
|
||||
m_localServer.reset(new QLocalServer(this));
|
||||
m_localServer->setSocketOptions(QLocalServer::UserAccessOption);
|
||||
@ -61,12 +61,14 @@ void NativeMessagingHost::run()
|
||||
|
||||
// Update KeePassXC/keepassxc-proxy binary paths to Native Messaging scripts
|
||||
if (BrowserSettings::updateBinaryPath()) {
|
||||
BrowserSettings::updateBinaryPaths(BrowserSettings::useCustomProxy() ? BrowserSettings::customProxyLocation() : "");
|
||||
BrowserSettings::updateBinaryPaths(BrowserSettings::useCustomProxy() ? BrowserSettings::customProxyLocation()
|
||||
: "");
|
||||
}
|
||||
|
||||
m_running.store(true);
|
||||
#ifdef Q_OS_WIN
|
||||
m_future = QtConcurrent::run(this, static_cast<void(NativeMessagingHost::*)()>(&NativeMessagingHost::readNativeMessages));
|
||||
m_future =
|
||||
QtConcurrent::run(this, static_cast<void (NativeMessagingHost::*)()>(&NativeMessagingHost::readNativeMessages));
|
||||
#endif
|
||||
|
||||
if (BrowserSettings::supportBrowserProxy()) {
|
||||
@ -101,7 +103,7 @@ void NativeMessagingHost::readLength()
|
||||
if (!std::cin.eof() && length > 0) {
|
||||
readStdIn(length);
|
||||
} else {
|
||||
m_notifier->setEnabled(false);
|
||||
m_notifier->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
42
src/browser/NativeMessagingHost.h
Executable file → Normal file
42
src/browser/NativeMessagingHost.h
Executable file → Normal file
@ -19,9 +19,9 @@
|
||||
#ifndef NATIVEMESSAGINGHOST_H
|
||||
#define NATIVEMESSAGINGHOST_H
|
||||
|
||||
#include "NativeMessagingBase.h"
|
||||
#include "BrowserClients.h"
|
||||
#include "BrowserService.h"
|
||||
#include "NativeMessagingBase.h"
|
||||
#include "gui/DatabaseTabWidget.h"
|
||||
|
||||
class NativeMessagingHost : public NativeMessagingBase
|
||||
@ -31,37 +31,37 @@ class NativeMessagingHost : public NativeMessagingBase
|
||||
typedef QList<QLocalSocket*> SocketList;
|
||||
|
||||
public:
|
||||
explicit NativeMessagingHost(DatabaseTabWidget* parent = 0);
|
||||
explicit NativeMessagingHost(DatabaseTabWidget* parent = 0);
|
||||
~NativeMessagingHost();
|
||||
int init();
|
||||
void run();
|
||||
void stop();
|
||||
int init();
|
||||
void run();
|
||||
void stop();
|
||||
|
||||
public slots:
|
||||
void removeSharedEncryptionKeys();
|
||||
void removeStoredPermissions();
|
||||
void removeSharedEncryptionKeys();
|
||||
void removeStoredPermissions();
|
||||
|
||||
signals:
|
||||
void quit();
|
||||
void quit();
|
||||
|
||||
private:
|
||||
void readLength();
|
||||
void readStdIn(const quint32 length);
|
||||
void sendReplyToAllClients(const QJsonObject& json);
|
||||
void readLength();
|
||||
void readStdIn(const quint32 length);
|
||||
void sendReplyToAllClients(const QJsonObject& json);
|
||||
|
||||
private slots:
|
||||
void databaseLocked();
|
||||
void databaseUnlocked();
|
||||
void newLocalConnection();
|
||||
void newLocalMessage();
|
||||
void disconnectSocket();
|
||||
void databaseLocked();
|
||||
void databaseUnlocked();
|
||||
void newLocalConnection();
|
||||
void newLocalMessage();
|
||||
void disconnectSocket();
|
||||
|
||||
private:
|
||||
QMutex m_mutex;
|
||||
BrowserClients m_browserClients;
|
||||
BrowserService m_browserService;
|
||||
QSharedPointer<QLocalServer> m_localServer;
|
||||
SocketList m_socketList;
|
||||
QMutex m_mutex;
|
||||
BrowserClients m_browserClients;
|
||||
BrowserService m_browserService;
|
||||
QSharedPointer<QLocalServer> m_localServer;
|
||||
SocketList m_socketList;
|
||||
};
|
||||
|
||||
#endif // NATIVEMESSAGINGHOST_H
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
QVariantMap qo2qv(const QObject* object, const QStringList& ignoredProperties = QStringList(QString(QLatin1String("objectName"))));
|
||||
QVariantMap qo2qv(const QObject* object,
|
||||
const QStringList& ignoredProperties = QStringList(QString(QLatin1String("objectName"))));
|
||||
|
||||
#endif // VARIANT_H
|
||||
|
@ -42,14 +42,15 @@ int Diceware::execute(const QStringList& arguments)
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(this->description);
|
||||
QCommandLineOption words(QStringList() << "W" << "words",
|
||||
QObject::tr("Word count for the diceware passphrase."),
|
||||
QObject::tr("count"));
|
||||
QCommandLineOption words(QStringList() << "W"
|
||||
<< "words",
|
||||
QObject::tr("Word count for the diceware passphrase."),
|
||||
QObject::tr("count"));
|
||||
parser.addOption(words);
|
||||
QCommandLineOption wordlistFile(QStringList() << "w"
|
||||
<< "word-list",
|
||||
QObject::tr("Wordlist for the diceware generator.\n[Default: EFF English]"),
|
||||
QObject::tr("path"));
|
||||
<< "word-list",
|
||||
QObject::tr("Wordlist for the diceware generator.\n[Default: EFF English]"),
|
||||
QObject::tr("path"));
|
||||
parser.addOption(wordlistFile);
|
||||
parser.process(arguments);
|
||||
|
||||
@ -78,7 +79,7 @@ int Diceware::execute(const QStringList& arguments)
|
||||
outputTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli diceware");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
QString password = dicewareGenerator.generatePassphrase();
|
||||
outputTextStream << password << endl;
|
||||
|
||||
|
@ -115,8 +115,9 @@ int Edit::execute(const QStringList& arguments)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (parser.value("username").isEmpty() && parser.value("url").isEmpty() && parser.value("title").isEmpty() &&
|
||||
!parser.isSet(prompt) && !parser.isSet(generate)) {
|
||||
if (parser.value("username").isEmpty() && parser.value("url").isEmpty() && parser.value("title").isEmpty()
|
||||
&& !parser.isSet(prompt)
|
||||
&& !parser.isSet(generate)) {
|
||||
qCritical("Not changing any field for entry %s.", qPrintable(entryPath));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -84,8 +84,8 @@ int Extract::execute(const QStringList& arguments)
|
||||
|
||||
if (fileKey.type() != FileKey::Hashed) {
|
||||
errorTextStream << QObject::tr("WARNING: You are using a legacy key file format which may become\n"
|
||||
"unsupported in the future.\n\n"
|
||||
"Please consider generating a new key file.");
|
||||
"unsupported in the future.\n\n"
|
||||
"Please consider generating a new key file.");
|
||||
errorTextStream << endl;
|
||||
}
|
||||
|
||||
|
@ -42,24 +42,20 @@ int Generate::execute(const QStringList& arguments)
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(this->description);
|
||||
QCommandLineOption len(QStringList() << "L" << "length",
|
||||
QObject::tr("Length of the generated password."),
|
||||
QObject::tr("length"));
|
||||
QCommandLineOption len(QStringList() << "L"
|
||||
<< "length",
|
||||
QObject::tr("Length of the generated password."),
|
||||
QObject::tr("length"));
|
||||
parser.addOption(len);
|
||||
QCommandLineOption lower(QStringList() << "l",
|
||||
QObject::tr("Use lowercase characters in the generated password."));
|
||||
QCommandLineOption lower(QStringList() << "l", QObject::tr("Use lowercase characters in the generated password."));
|
||||
parser.addOption(lower);
|
||||
QCommandLineOption upper(QStringList() << "u",
|
||||
QObject::tr("Use uppercase characters in the generated password."));
|
||||
QCommandLineOption upper(QStringList() << "u", QObject::tr("Use uppercase characters in the generated password."));
|
||||
parser.addOption(upper);
|
||||
QCommandLineOption numeric(QStringList() << "n",
|
||||
QObject::tr("Use numbers in the generated password."));
|
||||
QCommandLineOption numeric(QStringList() << "n", QObject::tr("Use numbers in the generated password."));
|
||||
parser.addOption(numeric);
|
||||
QCommandLineOption special(QStringList() << "s",
|
||||
QObject::tr("Use special characters in the generated password."));
|
||||
QCommandLineOption special(QStringList() << "s", QObject::tr("Use special characters in the generated password."));
|
||||
parser.addOption(special);
|
||||
QCommandLineOption extended(QStringList() << "e",
|
||||
QObject::tr("Use extended ASCII in the generated password."));
|
||||
QCommandLineOption extended(QStringList() << "e", QObject::tr("Use extended ASCII in the generated password."));
|
||||
parser.addOption(extended);
|
||||
parser.process(arguments);
|
||||
|
||||
@ -81,19 +77,19 @@ int Generate::execute(const QStringList& arguments)
|
||||
PasswordGenerator::CharClasses classes = 0x0;
|
||||
|
||||
if (parser.isSet(lower)) {
|
||||
classes |= PasswordGenerator::LowerLetters;
|
||||
classes |= PasswordGenerator::LowerLetters;
|
||||
}
|
||||
if (parser.isSet(upper)) {
|
||||
classes |= PasswordGenerator::UpperLetters;
|
||||
classes |= PasswordGenerator::UpperLetters;
|
||||
}
|
||||
if (parser.isSet(numeric)) {
|
||||
classes |= PasswordGenerator::Numbers;
|
||||
classes |= PasswordGenerator::Numbers;
|
||||
}
|
||||
if (parser.isSet(special)) {
|
||||
classes |= PasswordGenerator::SpecialCharacters;
|
||||
classes |= PasswordGenerator::SpecialCharacters;
|
||||
}
|
||||
if (parser.isSet(extended)) {
|
||||
classes |= PasswordGenerator::EASCII;
|
||||
classes |= PasswordGenerator::EASCII;
|
||||
}
|
||||
|
||||
passwordGenerator.setCharClasses(classes);
|
||||
|
@ -49,12 +49,14 @@ int Show::execute(const QStringList& arguments)
|
||||
QObject::tr("Key file of the database."),
|
||||
QObject::tr("path"));
|
||||
parser.addOption(keyFile);
|
||||
QCommandLineOption attributes(QStringList() << "a"
|
||||
<< "attributes",
|
||||
QObject::tr("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. "
|
||||
"If no attributes are specified, a summary of the default attributes is given."),
|
||||
QObject::tr("attribute"));
|
||||
QCommandLineOption attributes(
|
||||
QStringList() << "a"
|
||||
<< "attributes",
|
||||
QObject::tr(
|
||||
"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. "
|
||||
"If no attributes are specified, a summary of the default attributes is given."),
|
||||
QObject::tr("attribute"));
|
||||
parser.addOption(attributes);
|
||||
parser.addPositionalArgument("entry", QObject::tr("Name of the entry to show."));
|
||||
parser.process(arguments);
|
||||
|
@ -22,42 +22,42 @@
|
||||
#include <QFutureWatcher>
|
||||
#include <QtConcurrent>
|
||||
|
||||
|
||||
/**
|
||||
* Asynchronously run computations outside the GUI thread.
|
||||
*/
|
||||
namespace AsyncTask
|
||||
{
|
||||
|
||||
/**
|
||||
* Wait for the given future without blocking the event loop.
|
||||
*
|
||||
* @param future future to wait for
|
||||
* @return async task result
|
||||
*/
|
||||
template<typename FunctionObject>
|
||||
typename std::result_of<FunctionObject()>::type waitForFuture(QFuture<typename std::result_of<FunctionObject()>::type> future)
|
||||
{
|
||||
QEventLoop loop;
|
||||
QFutureWatcher<typename std::result_of<FunctionObject()>::type> watcher;
|
||||
QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
watcher.setFuture(future);
|
||||
loop.exec();
|
||||
return future.result();
|
||||
}
|
||||
/**
|
||||
* Wait for the given future without blocking the event loop.
|
||||
*
|
||||
* @param future future to wait for
|
||||
* @return async task result
|
||||
*/
|
||||
template <typename FunctionObject>
|
||||
typename std::result_of<FunctionObject()>::type
|
||||
waitForFuture(QFuture<typename std::result_of<FunctionObject()>::type> future)
|
||||
{
|
||||
QEventLoop loop;
|
||||
QFutureWatcher<typename std::result_of<FunctionObject()>::type> watcher;
|
||||
QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
watcher.setFuture(future);
|
||||
loop.exec();
|
||||
return future.result();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a given task and wait for it to finish without blocking the event loop.
|
||||
*
|
||||
* @param task std::function object to run
|
||||
* @return async task result
|
||||
*/
|
||||
template<typename FunctionObject>
|
||||
typename std::result_of<FunctionObject()>::type runAndWaitForFuture(FunctionObject task)
|
||||
{
|
||||
return waitForFuture<FunctionObject>(QtConcurrent::run(task));
|
||||
}
|
||||
/**
|
||||
* Run a given task and wait for it to finish without blocking the event loop.
|
||||
*
|
||||
* @param task std::function object to run
|
||||
* @return async task result
|
||||
*/
|
||||
template <typename FunctionObject>
|
||||
typename std::result_of<FunctionObject()>::type runAndWaitForFuture(FunctionObject task)
|
||||
{
|
||||
return waitForFuture<FunctionObject>(QtConcurrent::run(task));
|
||||
}
|
||||
|
||||
}; // namespace AsyncTask
|
||||
}; // namespace AsyncTask
|
||||
|
||||
#endif //KEEPASSXC_ASYNCTASK_HPP
|
||||
#endif // KEEPASSXC_ASYNCTASK_HPP
|
||||
|
@ -27,7 +27,6 @@ bool AutoTypeAssociations::Association::operator!=(const AutoTypeAssociations::A
|
||||
return window != other.window || sequence != other.sequence;
|
||||
}
|
||||
|
||||
|
||||
AutoTypeAssociations::AutoTypeAssociations(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
@ -106,7 +105,7 @@ int AutoTypeAssociations::size() const
|
||||
int AutoTypeAssociations::associationsSize() const
|
||||
{
|
||||
int size = 0;
|
||||
for (const Association &association : m_associations) {
|
||||
for (const Association& association : m_associations) {
|
||||
size += association.sequence.toUtf8().size() + association.window.toUtf8().size();
|
||||
}
|
||||
return size;
|
||||
|
@ -19,14 +19,16 @@
|
||||
#include "AutoTypeMatch.h"
|
||||
|
||||
AutoTypeMatch::AutoTypeMatch()
|
||||
: entry(nullptr),
|
||||
sequence()
|
||||
{}
|
||||
: entry(nullptr)
|
||||
, sequence()
|
||||
{
|
||||
}
|
||||
|
||||
AutoTypeMatch::AutoTypeMatch(Entry* entry, QString sequence)
|
||||
: entry(entry),
|
||||
sequence(sequence)
|
||||
{}
|
||||
: entry(entry)
|
||||
, sequence(sequence)
|
||||
{
|
||||
}
|
||||
|
||||
bool AutoTypeMatch::operator==(const AutoTypeMatch& other) const
|
||||
{
|
||||
|
@ -21,8 +21,8 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QSettings>
|
||||
#include <QTemporaryFile>
|
||||
#include <QStandardPaths>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
Config* Config::m_instance(nullptr);
|
||||
|
||||
@ -80,7 +80,7 @@ Config::Config(QObject* parent)
|
||||
QString userPath;
|
||||
QString homePath = QDir::homePath();
|
||||
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
|
||||
// we can't use QStandardPaths on X11 as it uses XDG_DATA_HOME instead of XDG_CONFIG_HOME
|
||||
QByteArray env = qgetenv("XDG_CONFIG_HOME");
|
||||
if (env.isEmpty()) {
|
||||
@ -95,17 +95,17 @@ Config::Config(QObject* parent)
|
||||
}
|
||||
|
||||
userPath += "/keepassxc/";
|
||||
#else
|
||||
#else
|
||||
userPath = QDir::fromNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
|
||||
// storageLocation() appends the application name ("/keepassxc") to the end
|
||||
userPath += "/";
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
#ifdef QT_DEBUG
|
||||
userPath += "keepassxc_debug.ini";
|
||||
#else
|
||||
#else
|
||||
userPath += "keepassxc.ini";
|
||||
#endif
|
||||
#endif
|
||||
|
||||
init(userPath);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ class QSettings;
|
||||
|
||||
class Config : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Q_DISABLE_COPY(Config)
|
||||
@ -54,7 +54,8 @@ private:
|
||||
QHash<QString, QVariant> m_defaults;
|
||||
};
|
||||
|
||||
inline Config* config() {
|
||||
inline Config* config()
|
||||
{
|
||||
return Config::instance();
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,8 @@
|
||||
|
||||
#include "CsvParser.h"
|
||||
|
||||
#include <QTextCodec>
|
||||
#include <QObject>
|
||||
#include <QTextCodec>
|
||||
|
||||
#include "core/Tools.h"
|
||||
|
||||
@ -44,21 +44,24 @@ CsvParser::CsvParser()
|
||||
m_ts.setCodec("UTF-8");
|
||||
}
|
||||
|
||||
CsvParser::~CsvParser() {
|
||||
CsvParser::~CsvParser()
|
||||
{
|
||||
m_csv.close();
|
||||
}
|
||||
|
||||
bool CsvParser::isFileLoaded() {
|
||||
bool CsvParser::isFileLoaded()
|
||||
{
|
||||
return m_isFileLoaded;
|
||||
}
|
||||
|
||||
bool CsvParser::reparse() {
|
||||
bool CsvParser::reparse()
|
||||
{
|
||||
reset();
|
||||
return parseFile();
|
||||
}
|
||||
|
||||
|
||||
bool CsvParser::parse(QFile *device) {
|
||||
bool CsvParser::parse(QFile* device)
|
||||
{
|
||||
clear();
|
||||
if (nullptr == device) {
|
||||
appendStatusMsg(QObject::tr("NULL device"), true);
|
||||
@ -69,7 +72,8 @@ bool CsvParser::parse(QFile *device) {
|
||||
return parseFile();
|
||||
}
|
||||
|
||||
bool CsvParser::readFile(QFile *device) {
|
||||
bool CsvParser::readFile(QFile* device)
|
||||
{
|
||||
if (device->isOpen())
|
||||
device->close();
|
||||
|
||||
@ -77,20 +81,20 @@ bool CsvParser::readFile(QFile *device) {
|
||||
if (!Tools::readAllFromDevice(device, m_array)) {
|
||||
appendStatusMsg(QObject::tr("error reading from device"), true);
|
||||
m_isFileLoaded = false;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
device->close();
|
||||
|
||||
m_array.replace("\r\n", "\n");
|
||||
m_array.replace("\r", "\n");
|
||||
if (0 == m_array.size())
|
||||
appendStatusMsg(QObject::tr("file empty").append("\n"));
|
||||
appendStatusMsg(QObject::tr("file empty").append("\n"));
|
||||
m_isFileLoaded = true;
|
||||
}
|
||||
return m_isFileLoaded;
|
||||
}
|
||||
|
||||
void CsvParser::reset() {
|
||||
void CsvParser::reset()
|
||||
{
|
||||
m_ch = 0;
|
||||
m_currCol = 1;
|
||||
m_currRow = 1;
|
||||
@ -101,21 +105,23 @@ void CsvParser::reset() {
|
||||
m_statusMsg = "";
|
||||
m_ts.seek(0);
|
||||
m_table.clear();
|
||||
//the following are users' concern :)
|
||||
//m_comment = '#';
|
||||
//m_backslashSyntax = false;
|
||||
//m_comment = '#';
|
||||
//m_qualifier = '"';
|
||||
//m_separator = ',';
|
||||
// the following are users' concern :)
|
||||
// m_comment = '#';
|
||||
// m_backslashSyntax = false;
|
||||
// m_comment = '#';
|
||||
// m_qualifier = '"';
|
||||
// m_separator = ',';
|
||||
}
|
||||
|
||||
void CsvParser::clear() {
|
||||
void CsvParser::clear()
|
||||
{
|
||||
reset();
|
||||
m_isFileLoaded = false;
|
||||
m_array.clear();
|
||||
}
|
||||
|
||||
bool CsvParser::parseFile() {
|
||||
bool CsvParser::parseFile()
|
||||
{
|
||||
parseRecord();
|
||||
while (!m_isEof) {
|
||||
if (!skipEndline())
|
||||
@ -128,7 +134,8 @@ bool CsvParser::parseFile() {
|
||||
return m_isGood;
|
||||
}
|
||||
|
||||
void CsvParser::parseRecord() {
|
||||
void CsvParser::parseRecord()
|
||||
{
|
||||
CsvRow row;
|
||||
if (isComment()) {
|
||||
skipLine();
|
||||
@ -151,19 +158,21 @@ void CsvParser::parseRecord() {
|
||||
m_currCol++;
|
||||
}
|
||||
|
||||
void CsvParser::parseField(CsvRow& row) {
|
||||
void CsvParser::parseField(CsvRow& row)
|
||||
{
|
||||
QString field;
|
||||
peek(m_ch);
|
||||
if (!isTerminator(m_ch)) {
|
||||
if (isQualifier(m_ch))
|
||||
parseQuoted(field);
|
||||
parseQuoted(field);
|
||||
else
|
||||
parseSimple(field);
|
||||
}
|
||||
row.push_back(field);
|
||||
}
|
||||
|
||||
void CsvParser::parseSimple(QString &s) {
|
||||
void CsvParser::parseSimple(QString& s)
|
||||
{
|
||||
QChar c;
|
||||
getChar(c);
|
||||
while ((isText(c)) && (!m_isEof)) {
|
||||
@ -174,16 +183,18 @@ void CsvParser::parseSimple(QString &s) {
|
||||
ungetChar();
|
||||
}
|
||||
|
||||
void CsvParser::parseQuoted(QString &s) {
|
||||
//read and discard initial qualifier (e.g. quote)
|
||||
void CsvParser::parseQuoted(QString& s)
|
||||
{
|
||||
// read and discard initial qualifier (e.g. quote)
|
||||
getChar(m_ch);
|
||||
parseEscaped(s);
|
||||
//getChar(m_ch);
|
||||
// getChar(m_ch);
|
||||
if (!isQualifier(m_ch))
|
||||
appendStatusMsg(QObject::tr("missing closing quote"), true);
|
||||
}
|
||||
|
||||
void CsvParser::parseEscaped(QString &s) {
|
||||
void CsvParser::parseEscaped(QString& s)
|
||||
{
|
||||
parseEscapedText(s);
|
||||
while (processEscapeMark(s, m_ch))
|
||||
parseEscapedText(s);
|
||||
@ -191,7 +202,8 @@ void CsvParser::parseEscaped(QString &s) {
|
||||
ungetChar();
|
||||
}
|
||||
|
||||
void CsvParser::parseEscapedText(QString &s) {
|
||||
void CsvParser::parseEscapedText(QString& s)
|
||||
{
|
||||
getChar(m_ch);
|
||||
while ((!isQualifier(m_ch)) && !m_isEof) {
|
||||
s.append(m_ch);
|
||||
@ -199,19 +211,20 @@ void CsvParser::parseEscapedText(QString &s) {
|
||||
}
|
||||
}
|
||||
|
||||
bool CsvParser::processEscapeMark(QString &s, QChar c) {
|
||||
bool CsvParser::processEscapeMark(QString& s, QChar c)
|
||||
{
|
||||
QChar buf;
|
||||
peek(buf);
|
||||
QChar c2;
|
||||
if (true == m_isBackslashSyntax) {
|
||||
//escape-character syntax, e.g. \"
|
||||
// escape-character syntax, e.g. \"
|
||||
if (c != '\\') {
|
||||
return false;
|
||||
}
|
||||
//consume (and append) second qualifier
|
||||
// consume (and append) second qualifier
|
||||
getChar(c2);
|
||||
if (m_isEof) {
|
||||
c2='\\';
|
||||
c2 = '\\';
|
||||
s.append('\\');
|
||||
return false;
|
||||
} else {
|
||||
@ -219,11 +232,11 @@ bool CsvParser::processEscapeMark(QString &s, QChar c) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
//double quote syntax, e.g. ""
|
||||
// double quote syntax, e.g. ""
|
||||
if (!isQualifier(c))
|
||||
return false;
|
||||
peek(c2);
|
||||
if (!m_isEof) { //not EOF, can read one char
|
||||
if (!m_isEof) { // not EOF, can read one char
|
||||
if (isQualifier(c2)) {
|
||||
s.append(c2);
|
||||
getChar(c2);
|
||||
@ -234,10 +247,11 @@ bool CsvParser::processEscapeMark(QString &s, QChar c) {
|
||||
}
|
||||
}
|
||||
|
||||
void CsvParser::fillColumns() {
|
||||
//fill shorter rows with empty placeholder columns
|
||||
void CsvParser::fillColumns()
|
||||
{
|
||||
// fill shorter rows with empty placeholder columns
|
||||
for (int i = 0; i < m_table.size(); ++i) {
|
||||
int gap = m_maxCols-m_table.at(i).size();
|
||||
int gap = m_maxCols - m_table.at(i).size();
|
||||
if (gap > 0) {
|
||||
CsvRow r = m_table.at(i);
|
||||
for (int j = 0; j < gap; ++j) {
|
||||
@ -248,18 +262,20 @@ void CsvParser::fillColumns() {
|
||||
}
|
||||
}
|
||||
|
||||
void CsvParser::skipLine() {
|
||||
void CsvParser::skipLine()
|
||||
{
|
||||
m_ts.readLine();
|
||||
m_ts.seek(m_ts.pos() - 1);
|
||||
}
|
||||
|
||||
bool CsvParser::skipEndline() {
|
||||
bool CsvParser::skipEndline()
|
||||
{
|
||||
getChar(m_ch);
|
||||
return (m_ch == '\n');
|
||||
}
|
||||
|
||||
|
||||
void CsvParser::getChar(QChar& c) {
|
||||
void CsvParser::getChar(QChar& c)
|
||||
{
|
||||
m_isEof = m_ts.atEnd();
|
||||
if (!m_isEof) {
|
||||
m_lastPos = m_ts.pos();
|
||||
@ -267,32 +283,37 @@ void CsvParser::getChar(QChar& c) {
|
||||
}
|
||||
}
|
||||
|
||||
void CsvParser::ungetChar() {
|
||||
void CsvParser::ungetChar()
|
||||
{
|
||||
if (!m_ts.seek(m_lastPos)) {
|
||||
qWarning("CSV Parser: unget lower bound exceeded");
|
||||
m_isGood = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CsvParser::peek(QChar& c) {
|
||||
void CsvParser::peek(QChar& c)
|
||||
{
|
||||
getChar(c);
|
||||
if (!m_isEof)
|
||||
ungetChar();
|
||||
}
|
||||
|
||||
bool CsvParser::isQualifier(const QChar &c) const {
|
||||
bool CsvParser::isQualifier(const QChar& c) const
|
||||
{
|
||||
if (true == m_isBackslashSyntax && (c != m_qualifier))
|
||||
return (c == '\\');
|
||||
else
|
||||
return (c == m_qualifier);
|
||||
}
|
||||
|
||||
bool CsvParser::isComment() {
|
||||
bool CsvParser::isComment()
|
||||
{
|
||||
bool result = false;
|
||||
QChar c2;
|
||||
qint64 pos = m_ts.pos();
|
||||
|
||||
do getChar(c2);
|
||||
do
|
||||
getChar(c2);
|
||||
while ((isSpace(c2) || isTab(c2)) && (!m_isEof));
|
||||
|
||||
if (c2 == m_comment)
|
||||
@ -301,84 +322,100 @@ bool CsvParser::isComment() {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CsvParser::isText(QChar c) const {
|
||||
return !( (isCRLF(c)) || (isSeparator(c)) );
|
||||
bool CsvParser::isText(QChar c) const
|
||||
{
|
||||
return !((isCRLF(c)) || (isSeparator(c)));
|
||||
}
|
||||
|
||||
bool CsvParser::isEmptyRow(CsvRow row) const {
|
||||
bool CsvParser::isEmptyRow(CsvRow row) const
|
||||
{
|
||||
CsvRow::const_iterator it = row.constBegin();
|
||||
for (; it != row.constEnd(); ++it)
|
||||
if ( ((*it) != "\n") && ((*it) != "") )
|
||||
if (((*it) != "\n") && ((*it) != ""))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CsvParser::isCRLF(const QChar &c) const {
|
||||
bool CsvParser::isCRLF(const QChar& c) const
|
||||
{
|
||||
return (c == '\n');
|
||||
}
|
||||
|
||||
bool CsvParser::isSpace(const QChar &c) const {
|
||||
bool CsvParser::isSpace(const QChar& c) const
|
||||
{
|
||||
return (c == ' ');
|
||||
}
|
||||
|
||||
bool CsvParser::isTab(const QChar &c) const {
|
||||
bool CsvParser::isTab(const QChar& c) const
|
||||
{
|
||||
return (c == '\t');
|
||||
}
|
||||
|
||||
bool CsvParser::isSeparator(const QChar &c) const {
|
||||
bool CsvParser::isSeparator(const QChar& c) const
|
||||
{
|
||||
return (c == m_separator);
|
||||
}
|
||||
|
||||
bool CsvParser::isTerminator(const QChar &c) const {
|
||||
bool CsvParser::isTerminator(const QChar& c) const
|
||||
{
|
||||
return (isSeparator(c) || (c == '\n') || (c == '\r'));
|
||||
}
|
||||
|
||||
void CsvParser::setBackslashSyntax(bool set) {
|
||||
void CsvParser::setBackslashSyntax(bool set)
|
||||
{
|
||||
m_isBackslashSyntax = set;
|
||||
}
|
||||
|
||||
void CsvParser::setComment(const QChar &c) {
|
||||
void CsvParser::setComment(const QChar& c)
|
||||
{
|
||||
m_comment = c.unicode();
|
||||
}
|
||||
|
||||
void CsvParser::setCodec(const QString &s) {
|
||||
void CsvParser::setCodec(const QString& s)
|
||||
{
|
||||
m_ts.setCodec(QTextCodec::codecForName(s.toLocal8Bit()));
|
||||
}
|
||||
|
||||
void CsvParser::setFieldSeparator(const QChar &c) {
|
||||
void CsvParser::setFieldSeparator(const QChar& c)
|
||||
{
|
||||
m_separator = c.unicode();
|
||||
}
|
||||
|
||||
void CsvParser::setTextQualifier(const QChar &c) {
|
||||
void CsvParser::setTextQualifier(const QChar& c)
|
||||
{
|
||||
m_qualifier = c.unicode();
|
||||
}
|
||||
|
||||
int CsvParser::getFileSize() const {
|
||||
int CsvParser::getFileSize() const
|
||||
{
|
||||
return m_csv.size();
|
||||
}
|
||||
|
||||
const CsvTable CsvParser::getCsvTable() const {
|
||||
const CsvTable CsvParser::getCsvTable() const
|
||||
{
|
||||
return m_table;
|
||||
}
|
||||
|
||||
QString CsvParser::getStatus() const {
|
||||
QString CsvParser::getStatus() const
|
||||
{
|
||||
return m_statusMsg;
|
||||
}
|
||||
|
||||
int CsvParser::getCsvCols() const {
|
||||
int CsvParser::getCsvCols() const
|
||||
{
|
||||
if ((m_table.size() > 0) && (m_table.at(0).size() > 0))
|
||||
return m_table.at(0).size();
|
||||
else return 0;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CsvParser::getCsvRows() const {
|
||||
int CsvParser::getCsvRows() const
|
||||
{
|
||||
return m_table.size();
|
||||
}
|
||||
|
||||
|
||||
void CsvParser::appendStatusMsg(QString s, bool isCritical) {
|
||||
m_statusMsg += QObject::tr("%1: (row, col) %2,%3")
|
||||
.arg(s, m_currRow, m_currCol)
|
||||
.append("\n");
|
||||
void CsvParser::appendStatusMsg(QString s, bool isCritical)
|
||||
{
|
||||
m_statusMsg += QObject::tr("%1: (row, col) %2,%3").arg(s, m_currRow, m_currCol).append("\n");
|
||||
m_isGood = !isCritical;
|
||||
}
|
||||
|
@ -19,28 +19,29 @@
|
||||
#ifndef KEEPASSX_CSVPARSER_H
|
||||
#define KEEPASSX_CSVPARSER_H
|
||||
|
||||
#include <QFile>
|
||||
#include <QBuffer>
|
||||
#include <QFile>
|
||||
#include <QQueue>
|
||||
#include <QTextStream>
|
||||
|
||||
typedef QStringList CsvRow;
|
||||
typedef QList<CsvRow> CsvTable;
|
||||
|
||||
class CsvParser {
|
||||
class CsvParser
|
||||
{
|
||||
|
||||
public:
|
||||
CsvParser();
|
||||
~CsvParser();
|
||||
//read data from device and parse it
|
||||
bool parse(QFile *device);
|
||||
// read data from device and parse it
|
||||
bool parse(QFile* device);
|
||||
bool isFileLoaded();
|
||||
//reparse the same buffer (device is not opened again)
|
||||
// reparse the same buffer (device is not opened again)
|
||||
bool reparse();
|
||||
void setCodec(const QString &s);
|
||||
void setComment(const QChar &c);
|
||||
void setFieldSeparator(const QChar &c);
|
||||
void setTextQualifier(const QChar &c);
|
||||
void setCodec(const QString& s);
|
||||
void setComment(const QChar& c);
|
||||
void setFieldSeparator(const QChar& c);
|
||||
void setTextQualifier(const QChar& c);
|
||||
void setBackslashSyntax(bool set);
|
||||
int getFileSize() const;
|
||||
int getCsvRows() const;
|
||||
@ -52,45 +53,45 @@ protected:
|
||||
CsvTable m_table;
|
||||
|
||||
private:
|
||||
QByteArray m_array;
|
||||
QBuffer m_csv;
|
||||
QChar m_ch;
|
||||
QChar m_comment;
|
||||
QByteArray m_array;
|
||||
QBuffer m_csv;
|
||||
QChar m_ch;
|
||||
QChar m_comment;
|
||||
unsigned int m_currCol;
|
||||
unsigned int m_currRow;
|
||||
bool m_isBackslashSyntax;
|
||||
bool m_isEof;
|
||||
bool m_isFileLoaded;
|
||||
bool m_isGood;
|
||||
qint64 m_lastPos;
|
||||
int m_maxCols;
|
||||
QChar m_qualifier;
|
||||
QChar m_separator;
|
||||
QString m_statusMsg;
|
||||
QTextStream m_ts;
|
||||
bool m_isBackslashSyntax;
|
||||
bool m_isEof;
|
||||
bool m_isFileLoaded;
|
||||
bool m_isGood;
|
||||
qint64 m_lastPos;
|
||||
int m_maxCols;
|
||||
QChar m_qualifier;
|
||||
QChar m_separator;
|
||||
QString m_statusMsg;
|
||||
QTextStream m_ts;
|
||||
|
||||
void getChar(QChar &c);
|
||||
void getChar(QChar& c);
|
||||
void ungetChar();
|
||||
void peek(QChar &c);
|
||||
void peek(QChar& c);
|
||||
void fillColumns();
|
||||
bool isTerminator(const QChar &c) const;
|
||||
bool isSeparator(const QChar &c) const;
|
||||
bool isQualifier(const QChar &c) const;
|
||||
bool processEscapeMark(QString &s, QChar c);
|
||||
bool isTerminator(const QChar& c) const;
|
||||
bool isSeparator(const QChar& c) const;
|
||||
bool isQualifier(const QChar& c) const;
|
||||
bool processEscapeMark(QString& s, QChar c);
|
||||
bool isText(QChar c) const;
|
||||
bool isComment();
|
||||
bool isCRLF(const QChar &c) const;
|
||||
bool isSpace(const QChar &c) const;
|
||||
bool isTab(const QChar &c) const;
|
||||
bool isCRLF(const QChar& c) const;
|
||||
bool isSpace(const QChar& c) const;
|
||||
bool isTab(const QChar& c) const;
|
||||
bool isEmptyRow(CsvRow row) const;
|
||||
bool parseFile();
|
||||
void parseRecord();
|
||||
void parseField(CsvRow &row);
|
||||
void parseSimple(QString &s);
|
||||
void parseQuoted(QString &s);
|
||||
void parseEscaped(QString &s);
|
||||
void parseEscapedText(QString &s);
|
||||
bool readFile(QFile *device);
|
||||
void parseField(CsvRow& row);
|
||||
void parseSimple(QString& s);
|
||||
void parseQuoted(QString& s);
|
||||
void parseEscaped(QString& s);
|
||||
void parseEscapedText(QString& s);
|
||||
bool readFile(QFile* device);
|
||||
void reset();
|
||||
void clear();
|
||||
bool skipEndline();
|
||||
@ -98,5 +99,4 @@ private:
|
||||
void appendStatusMsg(QString s, bool isCritical = false);
|
||||
};
|
||||
|
||||
#endif //CSVPARSER_H
|
||||
|
||||
#endif // CSVPARSER_H
|
||||
|
@ -54,7 +54,7 @@ void CustomData::set(const QString& key, const QString& value)
|
||||
|
||||
if (addAttribute) {
|
||||
emit aboutToBeAdded(key);
|
||||
}
|
||||
}
|
||||
|
||||
if (addAttribute || changeValue) {
|
||||
m_data.insert(key, value);
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
class CustomData : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CustomData(QObject* parent = nullptr);
|
||||
@ -45,7 +45,6 @@ public:
|
||||
bool operator==(const CustomData& other) const;
|
||||
bool operator!=(const CustomData& other) const;
|
||||
|
||||
|
||||
signals:
|
||||
void modified();
|
||||
void aboutToBeAdded(const QString& key);
|
||||
|
@ -32,8 +32,8 @@
|
||||
#include "format/KeePass2.h"
|
||||
#include "format/KeePass2Reader.h"
|
||||
#include "format/KeePass2Writer.h"
|
||||
#include "keys/PasswordKey.h"
|
||||
#include "keys/FileKey.h"
|
||||
#include "keys/PasswordKey.h"
|
||||
|
||||
QHash<Uuid, Database*> Database::m_uuidMap;
|
||||
|
||||
@ -129,7 +129,8 @@ Entry* Database::findEntryRecursive(const Uuid& uuid, Group* group)
|
||||
|
||||
Entry* Database::findEntryRecursive(const QString& text, EntryReferenceType referenceType, Group* group)
|
||||
{
|
||||
Q_ASSERT_X(referenceType != EntryReferenceType::Unknown, "Database::findEntryRecursive",
|
||||
Q_ASSERT_X(referenceType != EntryReferenceType::Unknown,
|
||||
"Database::findEntryRecursive",
|
||||
"Can't search entry with \"referenceType\" parameter equal to \"Unknown\"");
|
||||
|
||||
bool found = false;
|
||||
@ -335,7 +336,6 @@ void Database::setPublicCustomData(const QVariantMap& customData)
|
||||
m_data.publicCustomData = customData;
|
||||
}
|
||||
|
||||
|
||||
void Database::createRecycleBin()
|
||||
{
|
||||
Group* recycleBin = Group::createRecycleBin();
|
||||
@ -407,7 +407,6 @@ void Database::setEmitModified(bool value)
|
||||
m_emitModified = value;
|
||||
}
|
||||
|
||||
|
||||
Uuid Database::uuid()
|
||||
{
|
||||
return m_uuid;
|
||||
|
@ -23,8 +23,8 @@
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
|
||||
#include "crypto/kdf/Kdf.h"
|
||||
#include "core/Uuid.h"
|
||||
#include "crypto/kdf/Kdf.h"
|
||||
#include "keys/CompositeKey.h"
|
||||
|
||||
class Entry;
|
||||
@ -101,8 +101,7 @@ public:
|
||||
void setCipher(const Uuid& cipher);
|
||||
void setCompressionAlgo(Database::CompressionAlgorithm algo);
|
||||
void setKdf(QSharedPointer<Kdf> kdf);
|
||||
bool setKey(const CompositeKey& key, bool updateChangedTime = true,
|
||||
bool updateTransformSalt = false);
|
||||
bool setKey(const CompositeKey& key, bool updateChangedTime = true, bool updateTransformSalt = false);
|
||||
bool hasKey() const;
|
||||
bool verifyKey(const CompositeKey& key) const;
|
||||
QVariantMap& publicCustomData();
|
||||
|
@ -22,6 +22,8 @@
|
||||
DatabaseIcons* DatabaseIcons::m_instance(nullptr);
|
||||
const int DatabaseIcons::IconCount(69);
|
||||
const int DatabaseIcons::ExpiredIconIndex(45);
|
||||
|
||||
// clang-format off
|
||||
const char* const DatabaseIcons::m_indexToName[] = {
|
||||
"C00_Password.png",
|
||||
"C01_Package_Network.png",
|
||||
@ -93,6 +95,7 @@ const char* const DatabaseIcons::m_indexToName[] = {
|
||||
"C67_Certificate.png",
|
||||
"C68_BlackBerry.png"
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
QImage DatabaseIcons::icon(int index)
|
||||
{
|
||||
@ -103,8 +106,7 @@ QImage DatabaseIcons::icon(int index)
|
||||
|
||||
if (!m_iconCache[index].isNull()) {
|
||||
return m_iconCache[index];
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
QString iconPath = QString("icons/database/").append(m_indexToName[index]);
|
||||
QImage icon(filePath()->dataPath(iconPath));
|
||||
|
||||
|
@ -46,7 +46,8 @@ private:
|
||||
Q_DISABLE_COPY(DatabaseIcons)
|
||||
};
|
||||
|
||||
inline DatabaseIcons* databaseIcons() {
|
||||
inline DatabaseIcons* databaseIcons()
|
||||
{
|
||||
return DatabaseIcons::instance();
|
||||
}
|
||||
|
||||
|
@ -20,59 +20,55 @@
|
||||
#define KEEPASSX_ENDIAN_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QIODevice>
|
||||
#include <QSysInfo>
|
||||
#include <QtEndian>
|
||||
#include <QIODevice>
|
||||
|
||||
namespace Endian
|
||||
{
|
||||
|
||||
template<typename SizedQInt>
|
||||
SizedQInt bytesToSizedInt(const QByteArray& ba, QSysInfo::Endian byteOrder)
|
||||
{
|
||||
Q_ASSERT(ba.size() == sizeof(SizedQInt));
|
||||
template <typename SizedQInt> SizedQInt bytesToSizedInt(const QByteArray& ba, QSysInfo::Endian byteOrder)
|
||||
{
|
||||
Q_ASSERT(ba.size() == sizeof(SizedQInt));
|
||||
|
||||
if (byteOrder == QSysInfo::LittleEndian) {
|
||||
return qFromLittleEndian<SizedQInt>(reinterpret_cast<const uchar*>(ba.constData()));
|
||||
}
|
||||
return qFromBigEndian<SizedQInt>(reinterpret_cast<const uchar*>(ba.constData()));
|
||||
}
|
||||
|
||||
template<typename SizedQInt>
|
||||
SizedQInt readSizedInt(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok)
|
||||
{
|
||||
QByteArray ba = device->read(sizeof(SizedQInt));
|
||||
|
||||
if (ba.size() != sizeof(SizedQInt)) {
|
||||
*ok = false;
|
||||
return 0;
|
||||
}
|
||||
*ok = true;
|
||||
return bytesToSizedInt<SizedQInt>(ba, byteOrder);
|
||||
}
|
||||
|
||||
template<typename SizedQInt>
|
||||
QByteArray sizedIntToBytes(SizedQInt num, QSysInfo::Endian byteOrder)
|
||||
{
|
||||
QByteArray ba;
|
||||
ba.resize(sizeof(SizedQInt));
|
||||
|
||||
if (byteOrder == QSysInfo::LittleEndian) {
|
||||
qToLittleEndian<SizedQInt>(num, reinterpret_cast<uchar*>(ba.data()));
|
||||
} else {
|
||||
qToBigEndian<SizedQInt>(num, reinterpret_cast<uchar*>(ba.data()));
|
||||
if (byteOrder == QSysInfo::LittleEndian) {
|
||||
return qFromLittleEndian<SizedQInt>(reinterpret_cast<const uchar*>(ba.constData()));
|
||||
}
|
||||
return qFromBigEndian<SizedQInt>(reinterpret_cast<const uchar*>(ba.constData()));
|
||||
}
|
||||
|
||||
return ba;
|
||||
}
|
||||
template <typename SizedQInt> SizedQInt readSizedInt(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok)
|
||||
{
|
||||
QByteArray ba = device->read(sizeof(SizedQInt));
|
||||
|
||||
template<typename SizedQInt>
|
||||
bool writeSizedInt(SizedQInt num, QIODevice* device, QSysInfo::Endian byteOrder)
|
||||
{
|
||||
QByteArray ba = sizedIntToBytes<SizedQInt>(num, byteOrder);
|
||||
qint64 bytesWritten = device->write(ba);
|
||||
return (bytesWritten == ba.size());
|
||||
}
|
||||
if (ba.size() != sizeof(SizedQInt)) {
|
||||
*ok = false;
|
||||
return 0;
|
||||
}
|
||||
*ok = true;
|
||||
return bytesToSizedInt<SizedQInt>(ba, byteOrder);
|
||||
}
|
||||
|
||||
template <typename SizedQInt> QByteArray sizedIntToBytes(SizedQInt num, QSysInfo::Endian byteOrder)
|
||||
{
|
||||
QByteArray ba;
|
||||
ba.resize(sizeof(SizedQInt));
|
||||
|
||||
if (byteOrder == QSysInfo::LittleEndian) {
|
||||
qToLittleEndian<SizedQInt>(num, reinterpret_cast<uchar*>(ba.data()));
|
||||
} else {
|
||||
qToBigEndian<SizedQInt>(num, reinterpret_cast<uchar*>(ba.data()));
|
||||
}
|
||||
|
||||
return ba;
|
||||
}
|
||||
|
||||
template <typename SizedQInt> bool writeSizedInt(SizedQInt num, QIODevice* device, QSysInfo::Endian byteOrder)
|
||||
{
|
||||
QByteArray ba = sizedIntToBytes<SizedQInt>(num, byteOrder);
|
||||
qint64 bytesWritten = device->write(ba);
|
||||
return (bytesWritten == ba.size());
|
||||
}
|
||||
|
||||
} // namespace Endian
|
||||
|
||||
|
@ -32,7 +32,6 @@ const int Entry::ResolveMaximumDepth = 10;
|
||||
const QString Entry::AutoTypeSequenceUsername = "{USERNAME}{ENTER}";
|
||||
const QString Entry::AutoTypeSequencePassword = "{PASSWORD}{ENTER}";
|
||||
|
||||
|
||||
Entry::Entry()
|
||||
: m_attributes(new EntryAttributes(this))
|
||||
, m_attachments(new EntryAttachments(this))
|
||||
@ -78,8 +77,7 @@ template <class T> inline bool Entry::set(T& property, const T& value)
|
||||
property = value;
|
||||
emit modified();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -129,14 +127,12 @@ QImage Entry::icon() const
|
||||
{
|
||||
if (m_data.customIcon.isNull()) {
|
||||
return databaseIcons()->icon(m_data.iconNumber);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Q_ASSERT(database());
|
||||
|
||||
if (database()) {
|
||||
return database()->metadata()->customIcon(m_data.customIcon);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return QImage();
|
||||
}
|
||||
}
|
||||
@ -146,14 +142,12 @@ QPixmap Entry::iconPixmap() const
|
||||
{
|
||||
if (m_data.customIcon.isNull()) {
|
||||
return databaseIcons()->iconPixmap(m_data.iconNumber);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Q_ASSERT(database());
|
||||
|
||||
if (database()) {
|
||||
return database()->metadata()->customIconPixmap(m_data.customIcon);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return QPixmap();
|
||||
}
|
||||
}
|
||||
@ -164,8 +158,7 @@ QPixmap Entry::iconScaledPixmap() const
|
||||
if (m_data.customIcon.isNull()) {
|
||||
// built-in icons are 16x16 so don't need to be scaled
|
||||
return databaseIcons()->iconPixmap(m_data.iconNumber);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Q_ASSERT(database());
|
||||
|
||||
return database()->metadata()->customIconScaledPixmap(m_data.customIcon);
|
||||
@ -381,7 +374,7 @@ void Entry::setTotp(const QString& seed, quint8& step, quint8& digits)
|
||||
}
|
||||
QString data;
|
||||
|
||||
const Totp::Encoder & enc = Totp::encoders.value(digits, Totp::defaultEncoder);
|
||||
const Totp::Encoder& enc = Totp::encoders.value(digits, Totp::defaultEncoder);
|
||||
|
||||
if (m_attributes->hasKey("otp")) {
|
||||
data = QString("key=%1&step=%2&size=%3").arg(seed).arg(step).arg(enc.digits == 0 ? digits : enc.digits);
|
||||
@ -503,9 +496,9 @@ void Entry::setTitle(const QString& title)
|
||||
|
||||
void Entry::setUrl(const QString& url)
|
||||
{
|
||||
bool remove = url != m_attributes->value(EntryAttributes::URLKey) &&
|
||||
(m_attributes->value(EntryAttributes::RememberCmdExecAttr) == "1" ||
|
||||
m_attributes->value(EntryAttributes::RememberCmdExecAttr) == "0");
|
||||
bool remove = url != m_attributes->value(EntryAttributes::URLKey)
|
||||
&& (m_attributes->value(EntryAttributes::RememberCmdExecAttr) == "1"
|
||||
|| m_attributes->value(EntryAttributes::RememberCmdExecAttr) == "0");
|
||||
if (remove) {
|
||||
m_attributes->remove(EntryAttributes::RememberCmdExecAttr);
|
||||
}
|
||||
@ -640,8 +633,7 @@ Entry* Entry::clone(CloneFlags flags) const
|
||||
entry->setUpdateTimeinfo(false);
|
||||
if (flags & CloneNewUuid) {
|
||||
entry->m_uuid = Uuid::random();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
entry->m_uuid = m_uuid;
|
||||
}
|
||||
entry->m_data = m_data;
|
||||
@ -652,12 +644,14 @@ Entry* Entry::clone(CloneFlags flags) const
|
||||
if (flags & CloneUserAsRef) {
|
||||
// Build the username reference
|
||||
QString username = "{REF:U@I:" + m_uuid.toHex() + "}";
|
||||
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) {
|
||||
QString password = "{REF:P@I:" + m_uuid.toHex() + "}";
|
||||
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);
|
||||
@ -719,8 +713,7 @@ bool Entry::endUpdate()
|
||||
m_tmpHistoryItem->setUpdateTimeinfo(true);
|
||||
addHistoryItem(m_tmpHistoryItem);
|
||||
truncateHistory();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
delete m_tmpHistoryItem;
|
||||
}
|
||||
|
||||
@ -933,8 +926,8 @@ void Entry::setGroup(Group* group)
|
||||
|
||||
// copy custom icon to the new database
|
||||
if (!iconUuid().isNull() && group->database()
|
||||
&& m_group->database()->metadata()->containsCustomIcon(iconUuid())
|
||||
&& !group->database()->metadata()->containsCustomIcon(iconUuid())) {
|
||||
&& m_group->database()->metadata()->containsCustomIcon(iconUuid())
|
||||
&& !group->database()->metadata()->containsCustomIcon(iconUuid())) {
|
||||
group->database()->metadata()->addCustomIcon(iconUuid(), icon());
|
||||
}
|
||||
}
|
||||
@ -959,8 +952,7 @@ const Database* Entry::database() const
|
||||
{
|
||||
if (m_group) {
|
||||
return m_group->database();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@ -1028,26 +1020,25 @@ Entry::PlaceholderType Entry::placeholderType(const QString& placeholder) const
|
||||
return PlaceholderType::Reference;
|
||||
}
|
||||
|
||||
static const QMap<QString, PlaceholderType> placeholders {
|
||||
{ QStringLiteral("{TITLE}"), PlaceholderType::Title },
|
||||
{ QStringLiteral("{USERNAME}"), PlaceholderType::UserName },
|
||||
{ QStringLiteral("{PASSWORD}"), PlaceholderType::Password },
|
||||
{ QStringLiteral("{NOTES}"), PlaceholderType::Notes },
|
||||
{ QStringLiteral("{TOTP}"), PlaceholderType::Totp },
|
||||
{ QStringLiteral("{URL}"), PlaceholderType::Url },
|
||||
{ QStringLiteral("{URL:RMVSCM}"), PlaceholderType::UrlWithoutScheme },
|
||||
{ QStringLiteral("{URL:WITHOUTSCHEME}"), PlaceholderType::UrlWithoutScheme },
|
||||
{ QStringLiteral("{URL:SCM}"), PlaceholderType::UrlScheme },
|
||||
{ QStringLiteral("{URL:SCHEME}"), PlaceholderType::UrlScheme },
|
||||
{ QStringLiteral("{URL:HOST}"), PlaceholderType::UrlHost },
|
||||
{ QStringLiteral("{URL:PORT}"), PlaceholderType::UrlPort },
|
||||
{ QStringLiteral("{URL:PATH}"), PlaceholderType::UrlPath },
|
||||
{ QStringLiteral("{URL:QUERY}"), PlaceholderType::UrlQuery },
|
||||
{ QStringLiteral("{URL:FRAGMENT}"), PlaceholderType::UrlFragment },
|
||||
{ QStringLiteral("{URL:USERINFO}"), PlaceholderType::UrlUserInfo },
|
||||
{ QStringLiteral("{URL:USERNAME}"), PlaceholderType::UrlUserName },
|
||||
{ QStringLiteral("{URL:PASSWORD}"), PlaceholderType::UrlPassword }
|
||||
};
|
||||
static const QMap<QString, PlaceholderType> placeholders{
|
||||
{QStringLiteral("{TITLE}"), PlaceholderType::Title},
|
||||
{QStringLiteral("{USERNAME}"), PlaceholderType::UserName},
|
||||
{QStringLiteral("{PASSWORD}"), PlaceholderType::Password},
|
||||
{QStringLiteral("{NOTES}"), PlaceholderType::Notes},
|
||||
{QStringLiteral("{TOTP}"), PlaceholderType::Totp},
|
||||
{QStringLiteral("{URL}"), PlaceholderType::Url},
|
||||
{QStringLiteral("{URL:RMVSCM}"), PlaceholderType::UrlWithoutScheme},
|
||||
{QStringLiteral("{URL:WITHOUTSCHEME}"), PlaceholderType::UrlWithoutScheme},
|
||||
{QStringLiteral("{URL:SCM}"), PlaceholderType::UrlScheme},
|
||||
{QStringLiteral("{URL:SCHEME}"), PlaceholderType::UrlScheme},
|
||||
{QStringLiteral("{URL:HOST}"), PlaceholderType::UrlHost},
|
||||
{QStringLiteral("{URL:PORT}"), PlaceholderType::UrlPort},
|
||||
{QStringLiteral("{URL:PATH}"), PlaceholderType::UrlPath},
|
||||
{QStringLiteral("{URL:QUERY}"), PlaceholderType::UrlQuery},
|
||||
{QStringLiteral("{URL:FRAGMENT}"), PlaceholderType::UrlFragment},
|
||||
{QStringLiteral("{URL:USERINFO}"), PlaceholderType::UrlUserInfo},
|
||||
{QStringLiteral("{URL:USERNAME}"), PlaceholderType::UrlUserName},
|
||||
{QStringLiteral("{URL:PASSWORD}"), PlaceholderType::UrlPassword}};
|
||||
|
||||
return placeholders.value(placeholder.toUpper(), PlaceholderType::Unknown);
|
||||
}
|
||||
@ -1062,7 +1053,7 @@ QString Entry::resolveUrl(const QString& url) const
|
||||
|
||||
if (newUrl.startsWith("cmd://")) {
|
||||
QStringList cmdList = newUrl.split(" ");
|
||||
for (int i=1; i < cmdList.size(); ++i) {
|
||||
for (int i = 1; i < cmdList.size(); ++i) {
|
||||
// Don't pass arguments to the resolveUrl function (they look like URL's)
|
||||
if (!cmdList[i].startsWith("-") && !cmdList[i].startsWith("/")) {
|
||||
return resolveUrl(cmdList[i].remove(QRegExp("'|\"")));
|
||||
|
@ -37,7 +37,8 @@
|
||||
class Database;
|
||||
class Group;
|
||||
|
||||
enum class EntryReferenceType {
|
||||
enum class EntryReferenceType
|
||||
{
|
||||
Unknown,
|
||||
Title,
|
||||
UserName,
|
||||
@ -142,18 +143,20 @@ public:
|
||||
void removeHistoryItems(const QList<Entry*>& historyEntries);
|
||||
void truncateHistory();
|
||||
|
||||
enum CloneFlag {
|
||||
CloneNoFlags = 0,
|
||||
CloneNewUuid = 1, // generate a random uuid for the clone
|
||||
CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time
|
||||
CloneIncludeHistory = 4, // clone the history items
|
||||
CloneRenameTitle = 8, // add "-Clone" after the original title
|
||||
CloneUserAsRef = 16, // Add the user as a reference to the original entry
|
||||
ClonePassAsRef = 32, // Add the password as a reference to the original entry
|
||||
enum CloneFlag
|
||||
{
|
||||
CloneNoFlags = 0,
|
||||
CloneNewUuid = 1, // generate a random uuid for the clone
|
||||
CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time
|
||||
CloneIncludeHistory = 4, // clone the history items
|
||||
CloneRenameTitle = 8, // add "-Clone" after the original title
|
||||
CloneUserAsRef = 16, // Add the user as a reference to the original entry
|
||||
ClonePassAsRef = 32, // Add the password as a reference to the original entry
|
||||
};
|
||||
Q_DECLARE_FLAGS(CloneFlags, CloneFlag)
|
||||
|
||||
enum class PlaceholderType {
|
||||
enum class PlaceholderType
|
||||
{
|
||||
NotPlaceholder,
|
||||
Unknown,
|
||||
Title,
|
||||
|
@ -17,8 +17,8 @@
|
||||
|
||||
#include "EntryAttachments.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QSet>
|
||||
#include <QStringList>
|
||||
|
||||
EntryAttachments::EntryAttachments(QObject* parent)
|
||||
: QObject(parent)
|
||||
@ -61,8 +61,7 @@ void EntryAttachments::set(const QString& key, const QByteArray& value)
|
||||
|
||||
if (addAttachment) {
|
||||
emit added(key);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
emit keyModified(key);
|
||||
}
|
||||
|
||||
@ -74,8 +73,7 @@ void EntryAttachments::set(const QString& key, const QByteArray& value)
|
||||
void EntryAttachments::remove(const QString& key)
|
||||
{
|
||||
if (!m_attachments.contains(key)) {
|
||||
Q_ASSERT_X(false, "EntryAttachments::remove",
|
||||
qPrintable(QString("Can't find attachment for key %1").arg(key)));
|
||||
Q_ASSERT_X(false, "EntryAttachments::remove", qPrintable(QString("Can't find attachment for key %1").arg(key)));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -94,10 +92,10 @@ void EntryAttachments::remove(const QStringList& keys)
|
||||
}
|
||||
|
||||
bool isModified = false;
|
||||
for (const QString &key: keys) {
|
||||
for (const QString& key : keys) {
|
||||
if (!m_attachments.contains(key)) {
|
||||
Q_ASSERT_X(false, "EntryAttachments::remove",
|
||||
qPrintable(QString("Can't find attachment for key %1").arg(key)));
|
||||
Q_ASSERT_X(
|
||||
false, "EntryAttachments::remove", qPrintable(QString("Can't find attachment for key %1").arg(key)));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -23,8 +23,8 @@ const QString EntryAttributes::UserNameKey = "UserName";
|
||||
const QString EntryAttributes::PasswordKey = "Password";
|
||||
const QString EntryAttributes::URLKey = "URL";
|
||||
const QString EntryAttributes::NotesKey = "Notes";
|
||||
const QStringList EntryAttributes::DefaultAttributes(QStringList() << TitleKey << UserNameKey
|
||||
<< PasswordKey << URLKey << NotesKey);
|
||||
const QStringList EntryAttributes::DefaultAttributes(QStringList() << TitleKey << UserNameKey << PasswordKey << URLKey
|
||||
<< NotesKey);
|
||||
|
||||
const QString EntryAttributes::WantedFieldGroupName = "WantedField";
|
||||
const QString EntryAttributes::SearchInGroupName = "SearchIn";
|
||||
@ -113,8 +113,7 @@ void EntryAttributes::set(const QString& key, const QString& value, bool protect
|
||||
emitModified = true;
|
||||
}
|
||||
m_protectedAttributes.insert(key);
|
||||
}
|
||||
else if (m_protectedAttributes.remove(key)) {
|
||||
} else if (m_protectedAttributes.remove(key)) {
|
||||
emitModified = true;
|
||||
}
|
||||
|
||||
@ -124,11 +123,9 @@ void EntryAttributes::set(const QString& key, const QString& value, bool protect
|
||||
|
||||
if (defaultAttribute && changeValue) {
|
||||
emit defaultKeyModified();
|
||||
}
|
||||
else if (addAttribute) {
|
||||
} else if (addAttribute) {
|
||||
emit added(key);
|
||||
}
|
||||
else if (emitModified) {
|
||||
} else if (emitModified) {
|
||||
emit customKeyModified(key);
|
||||
}
|
||||
}
|
||||
@ -249,21 +246,19 @@ void EntryAttributes::copyDataFrom(const EntryAttributes* other)
|
||||
|
||||
bool EntryAttributes::operator==(const EntryAttributes& other) const
|
||||
{
|
||||
return (m_attributes == other.m_attributes
|
||||
&& m_protectedAttributes == other.m_protectedAttributes);
|
||||
return (m_attributes == other.m_attributes && m_protectedAttributes == other.m_protectedAttributes);
|
||||
}
|
||||
|
||||
bool EntryAttributes::operator!=(const EntryAttributes& other) const
|
||||
{
|
||||
return (m_attributes != other.m_attributes
|
||||
|| m_protectedAttributes != other.m_protectedAttributes);
|
||||
return (m_attributes != other.m_attributes || m_protectedAttributes != other.m_protectedAttributes);
|
||||
}
|
||||
|
||||
QRegularExpressionMatch EntryAttributes::matchReference(const QString& text)
|
||||
{
|
||||
static QRegularExpression referenceRegExp(
|
||||
"\\{REF:(?<WantedField>[TUPANI])@(?<SearchIn>[TUPANIO]):(?<SearchText>[^}]+)\\}",
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
"\\{REF:(?<WantedField>[TUPANI])@(?<SearchIn>[TUPANIO]):(?<SearchText>[^}]+)\\}",
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
|
||||
return referenceRegExp.match(text);
|
||||
}
|
||||
|
@ -20,8 +20,7 @@
|
||||
|
||||
#include "core/Group.h"
|
||||
|
||||
QList<Entry*> EntrySearcher::search(const QString& searchTerm, const Group* group,
|
||||
Qt::CaseSensitivity caseSensitivity)
|
||||
QList<Entry*> EntrySearcher::search(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity)
|
||||
{
|
||||
if (!group->resolveSearchingEnabled()) {
|
||||
return QList<Entry*>();
|
||||
@ -30,14 +29,14 @@ QList<Entry*> EntrySearcher::search(const QString& searchTerm, const Group* grou
|
||||
return searchEntries(searchTerm, group, caseSensitivity);
|
||||
}
|
||||
|
||||
QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Group* group,
|
||||
Qt::CaseSensitivity caseSensitivity)
|
||||
QList<Entry*>
|
||||
EntrySearcher::searchEntries(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity)
|
||||
{
|
||||
QList<Entry*> searchResult;
|
||||
|
||||
const QList<Entry*> entryList = group->entries();
|
||||
for (Entry* entry : entryList) {
|
||||
searchResult.append(matchEntry(searchTerm, entry, caseSensitivity));
|
||||
searchResult.append(matchEntry(searchTerm, entry, caseSensitivity));
|
||||
}
|
||||
|
||||
const QList<Group*> children = group->children();
|
||||
@ -54,8 +53,7 @@ QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Grou
|
||||
return searchResult;
|
||||
}
|
||||
|
||||
QList<Entry*> EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry,
|
||||
Qt::CaseSensitivity caseSensitivity)
|
||||
QList<Entry*> EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry, Qt::CaseSensitivity caseSensitivity)
|
||||
{
|
||||
const QStringList wordList = searchTerm.split(QRegExp("\\s"), QString::SkipEmptyParts);
|
||||
for (const QString& word : wordList) {
|
||||
@ -69,10 +67,10 @@ QList<Entry*> EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry,
|
||||
|
||||
bool EntrySearcher::wordMatch(const QString& word, Entry* entry, Qt::CaseSensitivity caseSensitivity)
|
||||
{
|
||||
return entry->resolvePlaceholder(entry->title()).contains(word, caseSensitivity) ||
|
||||
entry->resolvePlaceholder(entry->username()).contains(word, caseSensitivity) ||
|
||||
entry->resolvePlaceholder(entry->url()).contains(word, caseSensitivity) ||
|
||||
entry->resolvePlaceholder(entry->notes()).contains(word, caseSensitivity);
|
||||
return entry->resolvePlaceholder(entry->title()).contains(word, caseSensitivity)
|
||||
|| entry->resolvePlaceholder(entry->username()).contains(word, caseSensitivity)
|
||||
|| entry->resolvePlaceholder(entry->url()).contains(word, caseSensitivity)
|
||||
|| entry->resolvePlaceholder(entry->notes()).contains(word, caseSensitivity);
|
||||
}
|
||||
|
||||
bool EntrySearcher::matchGroup(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity)
|
||||
@ -89,6 +87,5 @@ bool EntrySearcher::matchGroup(const QString& searchTerm, const Group* group, Qt
|
||||
|
||||
bool EntrySearcher::wordMatch(const QString& word, const Group* group, Qt::CaseSensitivity caseSensitivity)
|
||||
{
|
||||
return group->name().contains(word, caseSensitivity) ||
|
||||
group->notes().contains(word, caseSensitivity);
|
||||
return group->name().contains(word, caseSensitivity) || group->notes().contains(word, caseSensitivity);
|
||||
}
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
#include <QString>
|
||||
|
||||
|
||||
class Group;
|
||||
class Entry;
|
||||
|
||||
|
@ -8,7 +8,9 @@ class Exporter
|
||||
{
|
||||
public:
|
||||
virtual Database* exportGroup(Group* group) = 0;
|
||||
virtual ~Exporter() {}
|
||||
virtual ~Exporter()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif // KEEPASSX_EXPORTER_H
|
||||
|
@ -23,8 +23,8 @@
|
||||
#include <QLibrary>
|
||||
|
||||
#include "config-keepassx.h"
|
||||
#include "core/Global.h"
|
||||
#include "core/Config.h"
|
||||
#include "core/Global.h"
|
||||
|
||||
FilePath* FilePath::m_instance(nullptr);
|
||||
|
||||
@ -32,8 +32,7 @@ QString FilePath::dataPath(const QString& name)
|
||||
{
|
||||
if (name.isEmpty() || name.startsWith('/')) {
|
||||
return m_dataPath + name;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return m_dataPath + "/" + name;
|
||||
}
|
||||
}
|
||||
@ -61,14 +60,12 @@ QString FilePath::pluginPath(const QString& name)
|
||||
if (configuredPluginDir != ".") {
|
||||
if (QDir(configuredPluginDir).isAbsolute()) {
|
||||
pluginPaths << configuredPluginDir;
|
||||
}
|
||||
else {
|
||||
QString relativePluginDir = QString("%1/../%2")
|
||||
.arg(QCoreApplication::applicationDirPath(), configuredPluginDir);
|
||||
} else {
|
||||
QString relativePluginDir =
|
||||
QString("%1/../%2").arg(QCoreApplication::applicationDirPath(), configuredPluginDir);
|
||||
pluginPaths << QDir(relativePluginDir).canonicalPath();
|
||||
|
||||
QString absolutePluginDir = QString("%1/%2")
|
||||
.arg(KEEPASSX_PREFIX_DIR, configuredPluginDir);
|
||||
QString absolutePluginDir = QString("%1/%2").arg(KEEPASSX_PREFIX_DIR, configuredPluginDir);
|
||||
pluginPaths << QDir(absolutePluginDir).canonicalPath();
|
||||
}
|
||||
}
|
||||
@ -151,11 +148,11 @@ QIcon FilePath::icon(const QString& category, const QString& name, bool fromThem
|
||||
}
|
||||
|
||||
if (icon.isNull()) {
|
||||
const QList<int> pngSizes = { 16, 22, 24, 32, 48, 64, 128 };
|
||||
const QList<int> pngSizes = {16, 22, 24, 32, 48, 64, 128};
|
||||
QString filename;
|
||||
for (int size : pngSizes) {
|
||||
filename = QString("%1/icons/application/%2x%2/%3.png").arg(m_dataPath, QString::number(size),
|
||||
combinedName);
|
||||
filename =
|
||||
QString("%1/icons/application/%2x%2/%3.png").arg(m_dataPath, QString::number(size), combinedName);
|
||||
if (QFile::exists(filename)) {
|
||||
icon.addFile(filename, QSize(size, size));
|
||||
}
|
||||
@ -189,17 +186,16 @@ QIcon FilePath::onOffIcon(const QString& category, const QString& name)
|
||||
if (i == 0) {
|
||||
state = QIcon::Off;
|
||||
stateName = "off";
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
state = QIcon::On;
|
||||
stateName = "on";
|
||||
}
|
||||
|
||||
const QList<int> pngSizes = { 16, 22, 24, 32, 48, 64, 128 };
|
||||
const QList<int> pngSizes = {16, 22, 24, 32, 48, 64, 128};
|
||||
QString filename;
|
||||
for (int size : pngSizes) {
|
||||
filename = QString("%1/icons/application/%2x%2/%3-%4.png").arg(m_dataPath, QString::number(size),
|
||||
combinedName, stateName);
|
||||
filename = QString("%1/icons/application/%2x%2/%3-%4.png")
|
||||
.arg(m_dataPath, QString::number(size), combinedName, stateName);
|
||||
if (QFile::exists(filename)) {
|
||||
icon.addFile(filename, QSize(size, size), QIcon::Normal, state);
|
||||
}
|
||||
@ -229,10 +225,8 @@ FilePath::FilePath()
|
||||
#endif
|
||||
#if defined(Q_OS_UNIX) && !(defined(Q_OS_MAC) && defined(WITH_APP_BUNDLE))
|
||||
else if (isDataDirAbsolute && testSetDir(KEEPASSX_DATA_DIR)) {
|
||||
}
|
||||
else if (!isDataDirAbsolute && testSetDir(QString("%1/../%2").arg(appDirPath, KEEPASSX_DATA_DIR))) {
|
||||
}
|
||||
else if (!isDataDirAbsolute && testSetDir(QString("%1/%2").arg(KEEPASSX_PREFIX_DIR, KEEPASSX_DATA_DIR))) {
|
||||
} else if (!isDataDirAbsolute && testSetDir(QString("%1/../%2").arg(appDirPath, KEEPASSX_DATA_DIR))) {
|
||||
} else if (!isDataDirAbsolute && testSetDir(QString("%1/%2").arg(KEEPASSX_PREFIX_DIR, KEEPASSX_DATA_DIR))) {
|
||||
}
|
||||
#endif
|
||||
#if defined(Q_OS_MAC) && defined(WITH_APP_BUNDLE)
|
||||
@ -249,8 +243,7 @@ FilePath::FilePath()
|
||||
|
||||
if (m_dataPath.isEmpty()) {
|
||||
qWarning("FilePath::DataPath: can't find data dir");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
m_dataPath = QDir::cleanPath(m_dataPath);
|
||||
}
|
||||
}
|
||||
@ -260,8 +253,7 @@ bool FilePath::testSetDir(const QString& dir)
|
||||
if (QFile::exists(dir + "/icons/database/C00_Password.png")) {
|
||||
m_dataPath = dir;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,8 @@ private:
|
||||
Q_DISABLE_COPY(FilePath)
|
||||
};
|
||||
|
||||
inline FilePath* filePath() {
|
||||
inline FilePath* filePath()
|
||||
{
|
||||
return FilePath::instance();
|
||||
}
|
||||
|
||||
|
@ -23,26 +23,30 @@
|
||||
#include <QtGlobal>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
# if defined(KEEPASSX_BUILDING_CORE)
|
||||
# define KEEPASSX_EXPORT Q_DECL_IMPORT
|
||||
# else
|
||||
# define KEEPASSX_EXPORT Q_DECL_EXPORT
|
||||
# endif
|
||||
#if defined(KEEPASSX_BUILDING_CORE)
|
||||
#define KEEPASSX_EXPORT Q_DECL_IMPORT
|
||||
#else
|
||||
# define KEEPASSX_EXPORT Q_DECL_EXPORT
|
||||
#define KEEPASSX_EXPORT Q_DECL_EXPORT
|
||||
#endif
|
||||
#else
|
||||
#define KEEPASSX_EXPORT Q_DECL_EXPORT
|
||||
#endif
|
||||
|
||||
#ifndef QUINT32_MAX
|
||||
#define QUINT32_MAX 4294967295U
|
||||
#endif
|
||||
|
||||
template <typename T> struct AddConst { typedef const T Type; };
|
||||
template <typename T> struct AddConst
|
||||
{
|
||||
typedef const T Type;
|
||||
};
|
||||
|
||||
// this adds const to non-const objects (like std::as_const)
|
||||
template <typename T>
|
||||
constexpr typename AddConst<T>::Type& asConst(T &t) noexcept { return t; }
|
||||
template <typename T> constexpr typename AddConst<T>::Type& asConst(T& t) noexcept
|
||||
{
|
||||
return t;
|
||||
}
|
||||
// prevent rvalue arguments:
|
||||
template <typename T>
|
||||
void asConst(const T&&) = delete;
|
||||
template <typename T> void asConst(const T&&) = delete;
|
||||
|
||||
#endif // KEEPASSX_GLOBAL_H
|
||||
|
@ -27,10 +27,10 @@ const int Group::DefaultIconNumber = 48;
|
||||
const int Group::RecycleBinIconNumber = 43;
|
||||
const QString Group::RootAutoTypeSequence = "{USERNAME}{TAB}{PASSWORD}{ENTER}";
|
||||
|
||||
Group::CloneFlags Group::DefaultCloneFlags = static_cast<Group::CloneFlags>(
|
||||
Group::CloneNewUuid | Group::CloneResetTimeInfo | Group::CloneIncludeEntries);
|
||||
Entry::CloneFlags Group::DefaultEntryCloneFlags = static_cast<Entry::CloneFlags>(
|
||||
Entry::CloneNewUuid | Entry::CloneResetTimeInfo);
|
||||
Group::CloneFlags Group::DefaultCloneFlags =
|
||||
static_cast<Group::CloneFlags>(Group::CloneNewUuid | Group::CloneResetTimeInfo | Group::CloneIncludeEntries);
|
||||
Entry::CloneFlags Group::DefaultEntryCloneFlags =
|
||||
static_cast<Entry::CloneFlags>(Entry::CloneNewUuid | Entry::CloneResetTimeInfo);
|
||||
|
||||
Group::Group()
|
||||
: m_customData(new CustomData(this))
|
||||
@ -81,7 +81,8 @@ Group* Group::createRecycleBin()
|
||||
return recycleBin;
|
||||
}
|
||||
|
||||
template <class P, class V> inline bool Group::set(P& property, const V& value) {
|
||||
template <class P, class V> inline bool Group::set(P& property, const V& value)
|
||||
{
|
||||
if (property != value) {
|
||||
property = value;
|
||||
emit modified();
|
||||
@ -123,14 +124,12 @@ QImage Group::icon() const
|
||||
{
|
||||
if (m_data.customIcon.isNull()) {
|
||||
return databaseIcons()->icon(m_data.iconNumber);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Q_ASSERT(m_db);
|
||||
|
||||
if (m_db) {
|
||||
return m_db->metadata()->customIcon(m_data.customIcon);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return QImage();
|
||||
}
|
||||
}
|
||||
@ -140,14 +139,12 @@ QPixmap Group::iconPixmap() const
|
||||
{
|
||||
if (m_data.customIcon.isNull()) {
|
||||
return databaseIcons()->iconPixmap(m_data.iconNumber);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Q_ASSERT(m_db);
|
||||
|
||||
if (m_db) {
|
||||
return m_db->metadata()->customIconPixmap(m_data.customIcon);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return QPixmap();
|
||||
}
|
||||
}
|
||||
@ -158,14 +155,12 @@ QPixmap Group::iconScaledPixmap() const
|
||||
if (m_data.customIcon.isNull()) {
|
||||
// built-in icons are 16x16 so don't need to be scaled
|
||||
return databaseIcons()->iconPixmap(m_data.iconNumber);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Q_ASSERT(m_db);
|
||||
|
||||
if (m_db) {
|
||||
return m_db->metadata()->customIconScaledPixmap(m_data.customIcon);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return QPixmap();
|
||||
}
|
||||
}
|
||||
@ -401,9 +396,8 @@ void Group::setParent(Group* parent, int index)
|
||||
recCreateDelObjects();
|
||||
|
||||
// copy custom icon to the new database
|
||||
if (!iconUuid().isNull() && parent->m_db
|
||||
&& m_db->metadata()->containsCustomIcon(iconUuid())
|
||||
&& !parent->m_db->metadata()->containsCustomIcon(iconUuid())) {
|
||||
if (!iconUuid().isNull() && parent->m_db && m_db->metadata()->containsCustomIcon(iconUuid())
|
||||
&& !parent->m_db->metadata()->containsCustomIcon(iconUuid())) {
|
||||
parent->m_db->metadata()->addCustomIcon(iconUuid(), icon());
|
||||
}
|
||||
}
|
||||
@ -414,8 +408,7 @@ void Group::setParent(Group* parent, int index)
|
||||
emit aboutToAdd(this, index);
|
||||
Q_ASSERT(index <= parent->m_children.size());
|
||||
parent->m_children.insert(index, this);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
emit aboutToMove(this, parent, index);
|
||||
m_parent->m_children.removeAll(this);
|
||||
m_parent = parent;
|
||||
@ -432,8 +425,7 @@ void Group::setParent(Group* parent, int index)
|
||||
|
||||
if (!moveWithinDatabase) {
|
||||
emit added();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
emit moved();
|
||||
}
|
||||
}
|
||||
@ -457,7 +449,7 @@ QStringList Group::hierarchy() const
|
||||
const Group* group = this;
|
||||
const Group* parent = m_parent;
|
||||
hierarchy.prepend(group->name());
|
||||
|
||||
|
||||
while (parent) {
|
||||
group = group->parentGroup();
|
||||
parent = group->parentGroup();
|
||||
@ -733,7 +725,6 @@ void Group::merge(const Group* other)
|
||||
resolveGroupConflict(existingGroup, group);
|
||||
existingGroup->merge(group);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
emit modified();
|
||||
@ -849,9 +840,9 @@ void Group::recSetDatabase(Database* db)
|
||||
disconnect(SIGNAL(dataChanged(Group*)), m_db);
|
||||
disconnect(SIGNAL(aboutToRemove(Group*)), m_db);
|
||||
disconnect(SIGNAL(removed()), m_db);
|
||||
disconnect(SIGNAL(aboutToAdd(Group*,int)), m_db);
|
||||
disconnect(SIGNAL(aboutToAdd(Group*, int)), m_db);
|
||||
disconnect(SIGNAL(added()), m_db);
|
||||
disconnect(SIGNAL(aboutToMove(Group*,Group*,int)), m_db);
|
||||
disconnect(SIGNAL(aboutToMove(Group*, Group*, int)), m_db);
|
||||
disconnect(SIGNAL(moved()), m_db);
|
||||
disconnect(SIGNAL(modified()), m_db);
|
||||
}
|
||||
@ -869,9 +860,9 @@ void Group::recSetDatabase(Database* db)
|
||||
connect(this, SIGNAL(dataChanged(Group*)), db, SIGNAL(groupDataChanged(Group*)));
|
||||
connect(this, SIGNAL(aboutToRemove(Group*)), db, SIGNAL(groupAboutToRemove(Group*)));
|
||||
connect(this, SIGNAL(removed()), db, SIGNAL(groupRemoved()));
|
||||
connect(this, SIGNAL(aboutToAdd(Group*,int)), db, SIGNAL(groupAboutToAdd(Group*,int)));
|
||||
connect(this, SIGNAL(aboutToAdd(Group*, int)), db, SIGNAL(groupAboutToAdd(Group*, int)));
|
||||
connect(this, SIGNAL(added()), db, SIGNAL(groupAdded()));
|
||||
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(moved()), db, SIGNAL(groupMoved()));
|
||||
connect(this, SIGNAL(modified()), db, SIGNAL(modifiedImmediate()));
|
||||
}
|
||||
@ -910,8 +901,7 @@ void Group::recCreateDelObjects()
|
||||
void Group::markOlderEntry(Entry* entry)
|
||||
{
|
||||
entry->attributes()->set(
|
||||
"merged",
|
||||
tr("older entry merged from database \"%1\"").arg(entry->group()->database()->metadata()->name()));
|
||||
"merged", tr("older entry merged from database \"%1\"").arg(entry->group()->database()->metadata()->name()));
|
||||
}
|
||||
|
||||
bool Group::resolveSearchingEnabled() const
|
||||
@ -920,8 +910,7 @@ bool Group::resolveSearchingEnabled() const
|
||||
case Inherit:
|
||||
if (!m_parent) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return m_parent->resolveSearchingEnabled();
|
||||
}
|
||||
case Enable:
|
||||
@ -940,8 +929,7 @@ bool Group::resolveAutoTypeEnabled() const
|
||||
case Inherit:
|
||||
if (!m_parent) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return m_parent->resolveAutoTypeEnabled();
|
||||
}
|
||||
case Enable:
|
||||
@ -1003,13 +991,12 @@ void Group::resolveGroupConflict(Group* existingGroup, Group* otherGroup)
|
||||
existingGroup->setName(otherGroup->name());
|
||||
existingGroup->setNotes(otherGroup->notes());
|
||||
if (otherGroup->iconNumber() == 0) {
|
||||
existingGroup->setIcon(otherGroup->iconUuid());
|
||||
existingGroup->setIcon(otherGroup->iconUuid());
|
||||
} else {
|
||||
existingGroup->setIcon(otherGroup->iconNumber());
|
||||
existingGroup->setIcon(otherGroup->iconNumber());
|
||||
}
|
||||
existingGroup->setExpiryTime(otherGroup->timeInfo().expiryTime());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QStringList Group::locate(QString locateTerm, QString currentPath)
|
||||
@ -1059,5 +1046,4 @@ Entry* Group::addEntryWithPath(QString entryPath)
|
||||
entry->setGroup(group);
|
||||
|
||||
return entry;
|
||||
|
||||
}
|
||||
|
@ -24,9 +24,9 @@
|
||||
#include <QPixmapCache>
|
||||
#include <QPointer>
|
||||
|
||||
#include "core/CustomData.h"
|
||||
#include "core/Database.h"
|
||||
#include "core/Entry.h"
|
||||
#include "core/CustomData.h"
|
||||
#include "core/TimeInfo.h"
|
||||
#include "core/Uuid.h"
|
||||
|
||||
@ -35,14 +35,26 @@ class Group : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum TriState { Inherit, Enable, Disable };
|
||||
enum MergeMode { ModeInherit, KeepBoth, KeepNewer, KeepExisting };
|
||||
enum TriState
|
||||
{
|
||||
Inherit,
|
||||
Enable,
|
||||
Disable
|
||||
};
|
||||
enum MergeMode
|
||||
{
|
||||
ModeInherit,
|
||||
KeepBoth,
|
||||
KeepNewer,
|
||||
KeepExisting
|
||||
};
|
||||
|
||||
enum CloneFlag {
|
||||
CloneNoFlags = 0,
|
||||
CloneNewUuid = 1, // generate a random uuid for the clone
|
||||
CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time
|
||||
CloneIncludeEntries = 4, // clone the group entries
|
||||
enum CloneFlag
|
||||
{
|
||||
CloneNoFlags = 0,
|
||||
CloneNewUuid = 1, // generate a random uuid for the clone
|
||||
CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time
|
||||
CloneIncludeEntries = 4, // clone the group entries
|
||||
};
|
||||
Q_DECLARE_FLAGS(CloneFlags, CloneFlag)
|
||||
|
||||
|
@ -56,9 +56,9 @@ bool InactivityTimer::eventFilter(QObject* watched, QEvent* event)
|
||||
{
|
||||
const QEvent::Type type = event->type();
|
||||
|
||||
if ( (type >= QEvent::MouseButtonPress && type <= QEvent::KeyRelease)
|
||||
|| (type >= QEvent::HoverEnter && type <= QEvent::HoverMove)
|
||||
|| (type == QEvent::Wheel) ) {
|
||||
if ((type >= QEvent::MouseButtonPress && type <= QEvent::KeyRelease)
|
||||
|| (type >= QEvent::HoverEnter && type <= QEvent::HoverMove)
|
||||
|| (type == QEvent::Wheel)) {
|
||||
m_timer->start();
|
||||
}
|
||||
|
||||
|
@ -20,12 +20,15 @@
|
||||
|
||||
#include <QList>
|
||||
|
||||
template <typename T>
|
||||
class ListDeleter
|
||||
template <typename T> class ListDeleter
|
||||
{
|
||||
public:
|
||||
inline explicit ListDeleter(QList<T>* list) : m_list(list) {}
|
||||
inline ~ListDeleter() {
|
||||
inline explicit ListDeleter(QList<T>* list)
|
||||
: m_list(list)
|
||||
{
|
||||
}
|
||||
inline ~ListDeleter()
|
||||
{
|
||||
qDeleteAll(*m_list);
|
||||
}
|
||||
|
||||
|
@ -17,9 +17,13 @@
|
||||
|
||||
#include "MacPasteboard.h"
|
||||
|
||||
QString MacPasteboard::convertorName() { return QLatin1String("MacPasteboard"); }
|
||||
QString MacPasteboard::convertorName()
|
||||
{
|
||||
return QLatin1String("MacPasteboard");
|
||||
}
|
||||
|
||||
QString MacPasteboard::flavorFor(const QString& mimetype) {
|
||||
QString MacPasteboard::flavorFor(const QString& mimetype)
|
||||
{
|
||||
if (mimetype == QLatin1String("text/plain")) {
|
||||
return QLatin1String("public.utf8-plain-text");
|
||||
} else if (mimetype == QLatin1String("application/x-nspasteboard-concealed-type")) {
|
||||
@ -38,15 +42,15 @@ QString MacPasteboard::flavorFor(const QString& mimetype) {
|
||||
|
||||
if (cs == QLatin1String("system")) {
|
||||
return QLatin1String("public.utf8-plain-text");
|
||||
} else if (cs == QLatin1String("iso-10646-ucs-2") ||
|
||||
cs == QLatin1String("utf16")) {
|
||||
} else if (cs == QLatin1String("iso-10646-ucs-2") || cs == QLatin1String("utf16")) {
|
||||
return QLatin1String("public.utf16-plain-text");
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString MacPasteboard::mimeFor(QString flavor) {
|
||||
QString MacPasteboard::mimeFor(QString flavor)
|
||||
{
|
||||
if (flavor == QLatin1String("public.utf8-plain-text"))
|
||||
return QLatin1String("text/plain");
|
||||
if (flavor == QLatin1String("org.nspasteboard.ConcealedType"))
|
||||
@ -56,13 +60,15 @@ QString MacPasteboard::mimeFor(QString flavor) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool MacPasteboard::canConvert(const QString& mimetype, QString flavor) {
|
||||
bool MacPasteboard::canConvert(const QString& mimetype, QString flavor)
|
||||
{
|
||||
Q_UNUSED(mimetype);
|
||||
Q_UNUSED(flavor);
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant MacPasteboard::convertToMime(const QString& mimetype, QList<QByteArray> data, QString flavor) {
|
||||
QVariant MacPasteboard::convertToMime(const QString& mimetype, QList<QByteArray> data, QString flavor)
|
||||
{
|
||||
if (data.count() > 1)
|
||||
qWarning("QMime::convertToMime: Cannot handle multiple member data");
|
||||
const QByteArray& firstData = data.first();
|
||||
@ -74,13 +80,13 @@ QVariant MacPasteboard::convertToMime(const QString& mimetype, QList<QByteArray>
|
||||
} else if (flavor == QLatin1String("public.utf16-plain-text")) {
|
||||
ret = QTextCodec::codecForName("UTF-16")->toUnicode(firstData);
|
||||
} else {
|
||||
qWarning("QMime::convertToMime: unhandled mimetype: %s",
|
||||
qPrintable(mimetype));
|
||||
qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<QByteArray> MacPasteboard::convertFromMime(const QString&, QVariant data, QString flavor) {
|
||||
QList<QByteArray> MacPasteboard::convertFromMime(const QString&, QVariant data, QString flavor)
|
||||
{
|
||||
QList<QByteArray> ret;
|
||||
QString string = data.toString();
|
||||
if (flavor == QLatin1String("public.utf8-plain-text"))
|
||||
@ -91,4 +97,3 @@ QList<QByteArray> MacPasteboard::convertFromMime(const QString&, QVariant data,
|
||||
ret.append(QTextCodec::codecForName("UTF-16")->fromUnicode(string));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -19,20 +19,23 @@
|
||||
#define KEEPASSXC_MACPASTEBOARD_H
|
||||
|
||||
#include <QMacPasteboardMime>
|
||||
#include <QTextCodec>
|
||||
#include <QObject>
|
||||
#include <QTextCodec>
|
||||
|
||||
class MacPasteboard : public QObject, public QMacPasteboardMime
|
||||
{
|
||||
public:
|
||||
explicit MacPasteboard() : QMacPasteboardMime(MIME_ALL) {}
|
||||
explicit MacPasteboard()
|
||||
: QMacPasteboardMime(MIME_ALL)
|
||||
{
|
||||
}
|
||||
|
||||
QString convertorName() override;
|
||||
bool canConvert(const QString &mime, QString flav) override;
|
||||
bool canConvert(const QString& mime, QString flav) override;
|
||||
QString mimeFor(QString flav) override;
|
||||
QString flavorFor(const QString &mime) override;
|
||||
QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav) override;
|
||||
QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav) override;
|
||||
QString flavorFor(const QString& mime) override;
|
||||
QVariant convertToMime(const QString& mime, QList<QByteArray> data, QString flav) override;
|
||||
QList<QByteArray> convertFromMime(const QString& mime, QVariant data, QString flav) override;
|
||||
};
|
||||
|
||||
#endif // KEEPASSXC_MACPASTEBOARD_H
|
||||
|
@ -15,8 +15,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QtCore/QCryptographicHash>
|
||||
#include "Metadata.h"
|
||||
#include <QtCore/QCryptographicHash>
|
||||
|
||||
#include "core/Entry.h"
|
||||
#include "core/Group.h"
|
||||
@ -61,13 +61,13 @@ template <class P, class V> bool Metadata::set(P& property, const V& value)
|
||||
property = value;
|
||||
emit modified();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <class P, class V> bool Metadata::set(P& property, const V& value, QDateTime& dateTime) {
|
||||
template <class P, class V> bool Metadata::set(P& property, const V& value, QDateTime& dateTime)
|
||||
{
|
||||
if (property != value) {
|
||||
property = value;
|
||||
if (m_updateDatetime) {
|
||||
@ -75,8 +75,7 @@ template <class P, class V> bool Metadata::set(P& property, const V& value, QDat
|
||||
}
|
||||
emit modified();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -402,10 +401,8 @@ void Metadata::addCustomIconScaled(const Uuid& uuid, const QImage& icon)
|
||||
|
||||
// scale down to 128x128 if icon is larger
|
||||
if (icon.width() > 128 || icon.height() > 128) {
|
||||
iconScaled = icon.scaled(QSize(128, 128), Qt::KeepAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
}
|
||||
else {
|
||||
iconScaled = icon.scaled(QSize(128, 128), Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
} else {
|
||||
iconScaled = icon;
|
||||
}
|
||||
|
||||
@ -433,7 +430,7 @@ void Metadata::removeCustomIcon(const Uuid& uuid)
|
||||
emit modified();
|
||||
}
|
||||
|
||||
Uuid Metadata::findCustomIcon(const QImage &candidate)
|
||||
Uuid Metadata::findCustomIcon(const QImage& candidate)
|
||||
{
|
||||
QByteArray hash = hashImage(candidate);
|
||||
return m_customIconsHashes.value(hash, Uuid());
|
||||
|
@ -26,8 +26,8 @@
|
||||
#include <QPixmapCache>
|
||||
#include <QPointer>
|
||||
|
||||
#include "core/Uuid.h"
|
||||
#include "core/CustomData.h"
|
||||
#include "core/Uuid.h"
|
||||
|
||||
class Database;
|
||||
class Group;
|
||||
|
@ -17,12 +17,12 @@
|
||||
|
||||
#include "PassphraseGenerator.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <cmath>
|
||||
|
||||
#include "crypto/Random.h"
|
||||
#include "core/FilePath.h"
|
||||
#include "crypto/Random.h"
|
||||
|
||||
const char* PassphraseGenerator::DefaultSeparator = " ";
|
||||
const char* PassphraseGenerator::DefaultWordList = "eff_large.wordlist";
|
||||
@ -52,7 +52,6 @@ void PassphraseGenerator::setWordCount(int wordCount)
|
||||
// safe default if something goes wrong
|
||||
m_wordCount = DefaultWordCount;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PassphraseGenerator::setWordList(const QString& path)
|
||||
@ -82,7 +81,8 @@ void PassphraseGenerator::setDefaultWordList()
|
||||
setWordList(path);
|
||||
}
|
||||
|
||||
void PassphraseGenerator::setWordSeparator(const QString& separator) {
|
||||
void PassphraseGenerator::setWordSeparator(const QString& separator)
|
||||
{
|
||||
m_separator = separator;
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ QString PassphraseGenerator::generatePassphrase() const
|
||||
Q_ASSERT(isValid());
|
||||
|
||||
// In case there was an error loading the wordlist
|
||||
if(m_wordlist.length() == 0) {
|
||||
if (m_wordlist.length() == 0) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ QString PassphraseGenerator::generatePassphrase() const
|
||||
bool PassphraseGenerator::isValid() const
|
||||
{
|
||||
if (m_wordCount == 0) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_wordlist.size() >= 1000;
|
||||
|
@ -45,7 +45,7 @@ void PasswordGenerator::setLength(int length)
|
||||
void PasswordGenerator::setCharClasses(const CharClasses& classes)
|
||||
{
|
||||
if (classes == 0) {
|
||||
m_classes = DefaultCharset;
|
||||
m_classes = DefaultCharset;
|
||||
return;
|
||||
}
|
||||
m_classes = classes;
|
||||
@ -92,8 +92,7 @@ QString PasswordGenerator::generatePassword() const
|
||||
password[i] = password[j];
|
||||
password[j] = tmp;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
for (int i = 0; i < m_length; i++) {
|
||||
int pos = randomGen()->randomUInt(passwordChars.size());
|
||||
|
||||
@ -110,7 +109,7 @@ int PasswordGenerator::getbits() const
|
||||
|
||||
int bits = 0;
|
||||
QVector<QChar> passwordChars;
|
||||
for (const PasswordGroup& group: groups) {
|
||||
for (const PasswordGroup& group : groups) {
|
||||
bits += group.size();
|
||||
}
|
||||
|
||||
@ -119,13 +118,11 @@ int PasswordGenerator::getbits() const
|
||||
return bits;
|
||||
}
|
||||
|
||||
|
||||
bool PasswordGenerator::isValid() const
|
||||
{
|
||||
if (m_classes == 0) {
|
||||
return false;
|
||||
}
|
||||
else if (m_length == 0) {
|
||||
} else if (m_length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -30,20 +30,20 @@ class PasswordGenerator
|
||||
public:
|
||||
enum CharClass
|
||||
{
|
||||
LowerLetters = 0x1,
|
||||
UpperLetters = 0x2,
|
||||
Numbers = 0x4,
|
||||
LowerLetters = 0x1,
|
||||
UpperLetters = 0x2,
|
||||
Numbers = 0x4,
|
||||
SpecialCharacters = 0x8,
|
||||
EASCII = 0x10,
|
||||
DefaultCharset = LowerLetters | UpperLetters | Numbers
|
||||
EASCII = 0x10,
|
||||
DefaultCharset = LowerLetters | UpperLetters | Numbers
|
||||
};
|
||||
Q_DECLARE_FLAGS(CharClasses, CharClass)
|
||||
|
||||
enum GeneratorFlag
|
||||
{
|
||||
ExcludeLookAlike = 0x1,
|
||||
ExcludeLookAlike = 0x1,
|
||||
CharFromEveryGroup = 0x2,
|
||||
DefaultFlags = ExcludeLookAlike | CharFromEveryGroup
|
||||
DefaultFlags = ExcludeLookAlike | CharFromEveryGroup
|
||||
};
|
||||
Q_DECLARE_FLAGS(GeneratorFlags, GeneratorFlag)
|
||||
|
||||
|
@ -18,11 +18,13 @@
|
||||
#include "ScreenLockListener.h"
|
||||
#include "ScreenLockListenerPrivate.h"
|
||||
|
||||
ScreenLockListener::ScreenLockListener(QWidget* parent):
|
||||
QObject(parent){
|
||||
ScreenLockListener::ScreenLockListener(QWidget* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
m_listener = ScreenLockListenerPrivate::instance(parent);
|
||||
connect(m_listener,SIGNAL(screenLocked()), this,SIGNAL(screenLocked()));
|
||||
connect(m_listener, SIGNAL(screenLocked()), this, SIGNAL(screenLocked()));
|
||||
}
|
||||
|
||||
ScreenLockListener::~ScreenLockListener(){
|
||||
ScreenLockListener::~ScreenLockListener()
|
||||
{
|
||||
}
|
||||
|
@ -21,7 +21,8 @@
|
||||
|
||||
class ScreenLockListenerPrivate;
|
||||
|
||||
class ScreenLockListener : public QObject {
|
||||
class ScreenLockListener : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -22,60 +22,54 @@
|
||||
#include <QDBusReply>
|
||||
#include <QProcessEnvironment>
|
||||
|
||||
ScreenLockListenerDBus::ScreenLockListenerDBus(QWidget *parent):
|
||||
ScreenLockListenerPrivate(parent)
|
||||
ScreenLockListenerDBus::ScreenLockListenerDBus(QWidget* parent)
|
||||
: ScreenLockListenerPrivate(parent)
|
||||
{
|
||||
QDBusConnection sessionBus = QDBusConnection::sessionBus();
|
||||
QDBusConnection systemBus = QDBusConnection::systemBus();
|
||||
|
||||
sessionBus.connect(
|
||||
"org.freedesktop.ScreenSaver", // service
|
||||
"/org/freedesktop/ScreenSaver", // path
|
||||
"org.freedesktop.ScreenSaver", // interface
|
||||
"ActiveChanged", // signal name
|
||||
this, //receiver
|
||||
SLOT(freedesktopScreenSaver(bool)));
|
||||
sessionBus.connect("org.freedesktop.ScreenSaver", // service
|
||||
"/org/freedesktop/ScreenSaver", // path
|
||||
"org.freedesktop.ScreenSaver", // interface
|
||||
"ActiveChanged", // signal name
|
||||
this, // receiver
|
||||
SLOT(freedesktopScreenSaver(bool)));
|
||||
|
||||
sessionBus.connect(
|
||||
"org.gnome.ScreenSaver", // service
|
||||
"/org/gnome/ScreenSaver", // path
|
||||
"org.gnome.ScreenSaver", // interface
|
||||
"ActiveChanged", // signal name
|
||||
this, //receiver
|
||||
SLOT(freedesktopScreenSaver(bool)));
|
||||
sessionBus.connect("org.gnome.ScreenSaver", // service
|
||||
"/org/gnome/ScreenSaver", // path
|
||||
"org.gnome.ScreenSaver", // interface
|
||||
"ActiveChanged", // signal name
|
||||
this, // receiver
|
||||
SLOT(freedesktopScreenSaver(bool)));
|
||||
|
||||
sessionBus.connect(
|
||||
"org.gnome.SessionManager", // service
|
||||
"/org/gnome/SessionManager/Presence", // path
|
||||
"org.gnome.SessionManager.Presence", // interface
|
||||
"StatusChanged", // signal name
|
||||
this, //receiver
|
||||
SLOT(gnomeSessionStatusChanged(uint)));
|
||||
sessionBus.connect("org.gnome.SessionManager", // service
|
||||
"/org/gnome/SessionManager/Presence", // path
|
||||
"org.gnome.SessionManager.Presence", // interface
|
||||
"StatusChanged", // signal name
|
||||
this, // receiver
|
||||
SLOT(gnomeSessionStatusChanged(uint)));
|
||||
|
||||
systemBus.connect(
|
||||
"org.freedesktop.login1", // service
|
||||
"/org/freedesktop/login1", // path
|
||||
"org.freedesktop.login1.Manager", // interface
|
||||
"PrepareForSleep", // signal name
|
||||
this, //receiver
|
||||
SLOT(logindPrepareForSleep(bool)));
|
||||
systemBus.connect("org.freedesktop.login1", // service
|
||||
"/org/freedesktop/login1", // path
|
||||
"org.freedesktop.login1.Manager", // interface
|
||||
"PrepareForSleep", // signal name
|
||||
this, // receiver
|
||||
SLOT(logindPrepareForSleep(bool)));
|
||||
|
||||
QString sessionId = QProcessEnvironment::systemEnvironment().value("XDG_SESSION_ID");
|
||||
systemBus.connect(
|
||||
"", // service
|
||||
QString("/org/freedesktop/login1/session/") + sessionId, // path
|
||||
"org.freedesktop.login1.Session", // interface
|
||||
"Lock", // signal name
|
||||
this, //receiver
|
||||
SLOT(unityLocked()));
|
||||
systemBus.connect("", // service
|
||||
QString("/org/freedesktop/login1/session/") + sessionId, // path
|
||||
"org.freedesktop.login1.Session", // interface
|
||||
"Lock", // signal name
|
||||
this, // receiver
|
||||
SLOT(unityLocked()));
|
||||
|
||||
sessionBus.connect(
|
||||
"com.canonical.Unity", // service
|
||||
"/com/canonical/Unity/Session", // path
|
||||
"com.canonical.Unity.Session", // interface
|
||||
"Locked", // signal name
|
||||
this, //receiver
|
||||
SLOT(unityLocked()));
|
||||
sessionBus.connect("com.canonical.Unity", // service
|
||||
"/com/canonical/Unity/Session", // path
|
||||
"com.canonical.Unity.Session", // interface
|
||||
"Locked", // signal name
|
||||
this, // receiver
|
||||
SLOT(unityLocked()));
|
||||
}
|
||||
|
||||
void ScreenLockListenerDBus::gnomeSessionStatusChanged(uint status)
|
||||
|
@ -17,15 +17,15 @@
|
||||
|
||||
#ifndef SCREENLOCKLISTENERDBUS_H
|
||||
#define SCREENLOCKLISTENERDBUS_H
|
||||
#include "ScreenLockListenerPrivate.h"
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include "ScreenLockListenerPrivate.h"
|
||||
|
||||
class ScreenLockListenerDBus : public ScreenLockListenerPrivate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ScreenLockListenerDBus(QWidget *parent = 0);
|
||||
explicit ScreenLockListenerDBus(QWidget* parent = 0);
|
||||
|
||||
private slots:
|
||||
void gnomeSessionStatusChanged(uint status);
|
||||
|
@ -25,7 +25,7 @@
|
||||
#endif
|
||||
|
||||
ScreenLockListenerPrivate::ScreenLockListenerPrivate(QWidget* parent)
|
||||
: QObject(parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* See https://msdn.microsoft.com/en-us/library/aa383841(v=vs.85).aspx
|
||||
* See https://blogs.msdn.microsoft.com/oldnewthing/20060104-50/?p=32783
|
||||
*/
|
||||
ScreenLockListenerWin::ScreenLockListenerWin(QWidget* parent)
|
||||
ScreenLockListenerWin::ScreenLockListenerWin(QWidget* parent)
|
||||
: ScreenLockListenerPrivate(parent)
|
||||
, QAbstractNativeEventFilter()
|
||||
{
|
||||
@ -36,20 +36,17 @@ ScreenLockListenerWin::ScreenLockListenerWin(QWidget* parent)
|
||||
|
||||
// This call requests a notification from windows when a laptop is closed
|
||||
HPOWERNOTIFY hPnotify = RegisterPowerSettingNotification(
|
||||
reinterpret_cast<HWND>(parent->winId()),
|
||||
&GUID_LIDSWITCH_STATE_CHANGE, DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||
reinterpret_cast<HWND>(parent->winId()), &GUID_LIDSWITCH_STATE_CHANGE, DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||
m_powerNotificationHandle = reinterpret_cast<void*>(hPnotify);
|
||||
|
||||
// This call requests a notification for session changes
|
||||
if (!WTSRegisterSessionNotification(
|
||||
reinterpret_cast<HWND>(parent->winId()),
|
||||
NOTIFY_FOR_THIS_SESSION)) {
|
||||
if (!WTSRegisterSessionNotification(reinterpret_cast<HWND>(parent->winId()), NOTIFY_FOR_THIS_SESSION)) {
|
||||
}
|
||||
}
|
||||
|
||||
ScreenLockListenerWin::~ScreenLockListenerWin()
|
||||
{
|
||||
HWND h= reinterpret_cast<HWND>(static_cast<QWidget*>(parent())->winId());
|
||||
HWND h = reinterpret_cast<HWND>(static_cast<QWidget*>(parent())->winId());
|
||||
WTSUnRegisterSessionNotification(h);
|
||||
|
||||
if (m_powerNotificationHandle) {
|
||||
|
@ -17,9 +17,9 @@
|
||||
|
||||
#ifndef SCREENLOCKLISTENERWIN_H
|
||||
#define SCREENLOCKLISTENERWIN_H
|
||||
#include <QAbstractNativeEventFilter>
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QAbstractNativeEventFilter>
|
||||
|
||||
#include "ScreenLockListenerPrivate.h"
|
||||
|
||||
@ -29,10 +29,10 @@ class ScreenLockListenerWin : public ScreenLockListenerPrivate, public QAbstract
|
||||
public:
|
||||
explicit ScreenLockListenerWin(QWidget* parent = 0);
|
||||
~ScreenLockListenerWin();
|
||||
virtual bool nativeEventFilter(const QByteArray &eventType, void* message, long*) override;
|
||||
virtual bool nativeEventFilter(const QByteArray& eventType, void* message, long*) override;
|
||||
|
||||
private:
|
||||
void* m_powerNotificationHandle ;
|
||||
void* m_powerNotificationHandle;
|
||||
};
|
||||
|
||||
#endif // SCREENLOCKLISTENERWIN_H
|
||||
|
@ -131,8 +131,7 @@ void SignalMultiplexer::connect(const Connection& con)
|
||||
|
||||
if (con.sender) {
|
||||
QObject::connect(con.sender, con.signal, m_currentObject, con.slot);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
QObject::connect(m_currentObject, con.signal, con.receiver, con.slot);
|
||||
}
|
||||
}
|
||||
@ -143,8 +142,7 @@ void SignalMultiplexer::disconnect(const Connection& con)
|
||||
|
||||
if (con.sender) {
|
||||
QObject::disconnect(con.sender, con.signal, m_currentObject, con.slot);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
QObject::disconnect(m_currentObject, con.signal, con.receiver, con.slot);
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,9 @@
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
QDateTime operator+(const QDateTime& dateTime, const TimeDelta& delta) {
|
||||
return dateTime.addDays(delta.getDays())
|
||||
.addMonths(delta.getMonths())
|
||||
.addYears(delta.getYears());
|
||||
QDateTime operator+(const QDateTime& dateTime, const TimeDelta& delta)
|
||||
{
|
||||
return dateTime.addDays(delta.getDays()).addMonths(delta.getMonths()).addYears(delta.getYears());
|
||||
}
|
||||
|
||||
TimeDelta TimeDelta::fromDays(int days)
|
||||
|
@ -20,16 +20,16 @@
|
||||
#include "Tools.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QImageReader>
|
||||
#include <QIODevice>
|
||||
#include <QImageReader>
|
||||
#include <QLocale>
|
||||
#include <QStringList>
|
||||
|
||||
#include <QElapsedTimer>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <aclapi.h> // for SetSecurityInfo()
|
||||
#include <windows.h> // for Sleep(), SetDllDirectoryA(), SetSearchPathMode(), ...
|
||||
#include <aclapi.h> // for SetSecurityInfo()
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
@ -47,314 +47,298 @@
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PT_DENY_ATTACH
|
||||
#include <sys/types.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
namespace Tools {
|
||||
|
||||
QString humanReadableFileSize(qint64 bytes)
|
||||
namespace Tools
|
||||
{
|
||||
double size = bytes;
|
||||
|
||||
QStringList units = QStringList() << "B" << "KiB" << "MiB" << "GiB";
|
||||
int i = 0;
|
||||
int maxI = units.size() - 1;
|
||||
QString humanReadableFileSize(qint64 bytes)
|
||||
{
|
||||
double size = bytes;
|
||||
|
||||
while ((size >= 1024) && (i < maxI)) {
|
||||
size /= 1024;
|
||||
i++;
|
||||
QStringList units = QStringList() << "B"
|
||||
<< "KiB"
|
||||
<< "MiB"
|
||||
<< "GiB";
|
||||
int i = 0;
|
||||
int maxI = units.size() - 1;
|
||||
|
||||
while ((size >= 1024) && (i < maxI)) {
|
||||
size /= 1024;
|
||||
i++;
|
||||
}
|
||||
|
||||
return QString("%1 %2").arg(QLocale().toString(size, 'f', 2), units.at(i));
|
||||
}
|
||||
|
||||
return QString("%1 %2").arg(QLocale().toString(size, 'f', 2), units.at(i));
|
||||
}
|
||||
bool hasChild(const QObject* parent, const QObject* child)
|
||||
{
|
||||
if (!parent || !child) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasChild(const QObject* parent, const QObject* child)
|
||||
{
|
||||
if (!parent || !child) {
|
||||
const QObjectList children = parent->children();
|
||||
for (QObject* c : children) {
|
||||
if (child == c || hasChild(c, child)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const QObjectList children = parent->children();
|
||||
for (QObject* c : children) {
|
||||
if (child == c || hasChild(c, child)) {
|
||||
bool readFromDevice(QIODevice* device, QByteArray& data, int size)
|
||||
{
|
||||
QByteArray buffer;
|
||||
buffer.resize(size);
|
||||
|
||||
qint64 readResult = device->read(buffer.data(), size);
|
||||
if (readResult == -1) {
|
||||
return false;
|
||||
} else {
|
||||
buffer.resize(readResult);
|
||||
data = buffer;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool readFromDevice(QIODevice* device, QByteArray& data, int size)
|
||||
{
|
||||
QByteArray buffer;
|
||||
buffer.resize(size);
|
||||
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);
|
||||
|
||||
qint64 readResult = device->read(buffer.data(), size);
|
||||
if (readResult == -1) {
|
||||
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;
|
||||
if (readResult == -1) {
|
||||
return false;
|
||||
} else {
|
||||
result.resize(static_cast<int>(readBytes));
|
||||
data = result;
|
||||
return true;
|
||||
}
|
||||
} while (readResult > 0);
|
||||
|
||||
if (readResult == -1) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
result.resize(static_cast<int>(readBytes));
|
||||
data = result;
|
||||
return true;
|
||||
|
||||
QString imageReaderFilter()
|
||||
{
|
||||
const QList<QByteArray> formats = QImageReader::supportedImageFormats();
|
||||
QStringList formatsStringList;
|
||||
|
||||
for (const QByteArray& format : formats) {
|
||||
for (int i = 0; i < format.size(); i++) {
|
||||
if (!QChar(format.at(i)).isLetterOrNumber()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
formatsStringList.append("*." + QString::fromLatin1(format).toLower());
|
||||
}
|
||||
|
||||
return formatsStringList.join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
QString imageReaderFilter()
|
||||
{
|
||||
const QList<QByteArray> formats = QImageReader::supportedImageFormats();
|
||||
QStringList formatsStringList;
|
||||
|
||||
for (const QByteArray& format : formats) {
|
||||
for (int i = 0; i < format.size(); i++) {
|
||||
if (!QChar(format.at(i)).isLetterOrNumber()) {
|
||||
continue;
|
||||
bool isHex(const QByteArray& ba)
|
||||
{
|
||||
for (char c : ba) {
|
||||
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
formatsStringList.append("*." + QString::fromLatin1(format).toLower());
|
||||
return true;
|
||||
}
|
||||
|
||||
return formatsStringList.join(" ");
|
||||
}
|
||||
bool isBase64(const QByteArray& ba)
|
||||
{
|
||||
QRegExp regexp(
|
||||
"^(?:[a-z0-9+/]{4})*(?:[a-z0-9+/]{3}=|[a-z0-9+/]{2}==)?$", Qt::CaseInsensitive, QRegExp::RegExp2);
|
||||
|
||||
bool isHex(const QByteArray& ba)
|
||||
{
|
||||
for (char c : ba) {
|
||||
if ( !( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) ) {
|
||||
return false;
|
||||
QString base64 = QString::fromLatin1(ba.constData(), ba.size());
|
||||
|
||||
return regexp.exactMatch(base64);
|
||||
}
|
||||
|
||||
void sleep(int ms)
|
||||
{
|
||||
Q_ASSERT(ms >= 0);
|
||||
|
||||
if (ms == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isBase64(const QByteArray& ba)
|
||||
{
|
||||
QRegExp regexp("^(?:[a-z0-9+/]{4})*(?:[a-z0-9+/]{3}=|[a-z0-9+/]{2}==)?$",
|
||||
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
|
||||
Sleep(uint(ms));
|
||||
Sleep(uint(ms));
|
||||
#else
|
||||
timespec ts;
|
||||
ts.tv_sec = ms / 1000;
|
||||
ts.tv_nsec = (ms % 1000) * 1000 * 1000;
|
||||
nanosleep(&ts, nullptr);
|
||||
timespec ts;
|
||||
ts.tv_sec = ms / 1000;
|
||||
ts.tv_nsec = (ms % 1000) * 1000 * 1000;
|
||||
nanosleep(&ts, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void wait(int ms)
|
||||
{
|
||||
Q_ASSERT(ms >= 0);
|
||||
|
||||
if (ms == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
void wait(int ms)
|
||||
{
|
||||
Q_ASSERT(ms >= 0);
|
||||
|
||||
if (ms <= 50) {
|
||||
QCoreApplication::processEvents(QEventLoop::AllEvents, ms);
|
||||
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));
|
||||
}
|
||||
}
|
||||
if (ms == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
void disableCoreDumps()
|
||||
{
|
||||
// default to true
|
||||
// there is no point in printing a warning if this is not implemented on the platform
|
||||
bool success = true;
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
|
||||
if (ms <= 50) {
|
||||
QCoreApplication::processEvents(QEventLoop::AllEvents, ms);
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
void disableCoreDumps()
|
||||
{
|
||||
// default to true
|
||||
// there is no point in printing a warning if this is not implemented on the platform
|
||||
bool success = true;
|
||||
|
||||
#if defined(HAVE_RLIMIT_CORE)
|
||||
struct rlimit limit;
|
||||
limit.rlim_cur = 0;
|
||||
limit.rlim_max = 0;
|
||||
success = success && (setrlimit(RLIMIT_CORE, &limit) == 0);
|
||||
struct rlimit limit;
|
||||
limit.rlim_cur = 0;
|
||||
limit.rlim_max = 0;
|
||||
success = success && (setrlimit(RLIMIT_CORE, &limit) == 0);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_PR_SET_DUMPABLE)
|
||||
success = success && (prctl(PR_SET_DUMPABLE, 0) == 0);
|
||||
success = success && (prctl(PR_SET_DUMPABLE, 0) == 0);
|
||||
#endif
|
||||
|
||||
// Mac OS X
|
||||
// Mac OS X
|
||||
#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
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
success = success && createWindowsDACL();
|
||||
success = success && createWindowsDACL();
|
||||
#endif
|
||||
|
||||
if (!success) {
|
||||
qWarning("Unable to disable core dumps.");
|
||||
if (!success) {
|
||||
qWarning("Unable to disable core dumps.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setupSearchPaths()
|
||||
{
|
||||
void setupSearchPaths()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
// Make sure Windows doesn't load DLLs from the current working directory
|
||||
SetDllDirectoryA("");
|
||||
SetSearchPathMode(BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE);
|
||||
// Make sure Windows doesn't load DLLs from the current working directory
|
||||
SetDllDirectoryA("");
|
||||
SetSearchPathMode(BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// SeDebugPrivilege or SeTakeOwnershipPrivilege and circumvent the DACL.
|
||||
//
|
||||
bool createWindowsDACL()
|
||||
{
|
||||
bool bSuccess = false;
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// SeDebugPrivilege or SeTakeOwnershipPrivilege and circumvent the DACL.
|
||||
//
|
||||
bool createWindowsDACL()
|
||||
{
|
||||
bool bSuccess = false;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// Process token and user
|
||||
HANDLE hToken = nullptr;
|
||||
PTOKEN_USER pTokenUser = nullptr;
|
||||
DWORD cbBufferSize = 0;
|
||||
// Process token and user
|
||||
HANDLE hToken = nullptr;
|
||||
PTOKEN_USER pTokenUser = nullptr;
|
||||
DWORD cbBufferSize = 0;
|
||||
|
||||
// Access control list
|
||||
PACL pACL = nullptr;
|
||||
DWORD cbACL = 0;
|
||||
// Access control list
|
||||
PACL pACL = nullptr;
|
||||
DWORD cbACL = 0;
|
||||
|
||||
// Open the access token associated with the calling process
|
||||
if (!OpenProcessToken(
|
||||
GetCurrentProcess(),
|
||||
TOKEN_QUERY,
|
||||
&hToken
|
||||
)) {
|
||||
goto Cleanup;
|
||||
}
|
||||
// Open the access token associated with the calling process
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Retrieve the token information in a TOKEN_USER structure
|
||||
GetTokenInformation(
|
||||
hToken,
|
||||
TokenUser,
|
||||
nullptr,
|
||||
0,
|
||||
&cbBufferSize
|
||||
);
|
||||
// Retrieve the token information in a TOKEN_USER structure
|
||||
GetTokenInformation(hToken, TokenUser, nullptr, 0, &cbBufferSize);
|
||||
|
||||
pTokenUser = static_cast<PTOKEN_USER>(HeapAlloc(GetProcessHeap(), 0, cbBufferSize));
|
||||
if (pTokenUser == nullptr) {
|
||||
goto Cleanup;
|
||||
}
|
||||
pTokenUser = static_cast<PTOKEN_USER>(HeapAlloc(GetProcessHeap(), 0, cbBufferSize));
|
||||
if (pTokenUser == nullptr) {
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
if (!GetTokenInformation(
|
||||
hToken,
|
||||
TokenUser,
|
||||
pTokenUser,
|
||||
cbBufferSize,
|
||||
&cbBufferSize
|
||||
)) {
|
||||
goto Cleanup;
|
||||
}
|
||||
if (!GetTokenInformation(hToken, TokenUser, pTokenUser, cbBufferSize, &cbBufferSize)) {
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
if (!IsValidSid(pTokenUser->User.Sid)) {
|
||||
goto Cleanup;
|
||||
}
|
||||
if (!IsValidSid(pTokenUser->User.Sid)) {
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Calculate the amount of memory that must be allocated for the DACL
|
||||
cbACL = sizeof(ACL)
|
||||
+ sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid);
|
||||
// Calculate the amount of memory that must be allocated for the DACL
|
||||
cbACL = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid);
|
||||
|
||||
// Create and initialize an ACL
|
||||
pACL = static_cast<PACL>(HeapAlloc(GetProcessHeap(), 0, cbACL));
|
||||
if (pACL == nullptr) {
|
||||
goto Cleanup;
|
||||
}
|
||||
// Create and initialize an ACL
|
||||
pACL = static_cast<PACL>(HeapAlloc(GetProcessHeap(), 0, cbACL));
|
||||
if (pACL == nullptr) {
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) {
|
||||
goto Cleanup;
|
||||
}
|
||||
if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) {
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Add allowed access control entries, everything else is denied
|
||||
if (!AddAccessAllowedAce(
|
||||
pACL,
|
||||
ACL_REVISION,
|
||||
SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE, // same as protected process
|
||||
pTokenUser->User.Sid // pointer to the trustee's SID
|
||||
)) {
|
||||
goto Cleanup;
|
||||
}
|
||||
// Add allowed access control entries, everything else is denied
|
||||
if (!AddAccessAllowedAce(
|
||||
pACL,
|
||||
ACL_REVISION,
|
||||
SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE, // same as protected process
|
||||
pTokenUser->User.Sid // pointer to the trustee's SID
|
||||
)) {
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Set discretionary access control list
|
||||
bSuccess = ERROR_SUCCESS == SetSecurityInfo(
|
||||
GetCurrentProcess(), // object handle
|
||||
SE_KERNEL_OBJECT, // type of object
|
||||
DACL_SECURITY_INFORMATION, // change only the objects DACL
|
||||
nullptr, nullptr, // do not change owner or group
|
||||
pACL, // DACL specified
|
||||
nullptr // do not change SACL
|
||||
);
|
||||
// Set discretionary access control list
|
||||
bSuccess = ERROR_SUCCESS == SetSecurityInfo(GetCurrentProcess(), // object handle
|
||||
SE_KERNEL_OBJECT, // type of object
|
||||
DACL_SECURITY_INFORMATION, // change only the objects DACL
|
||||
nullptr,
|
||||
nullptr, // do not change owner or group
|
||||
pACL, // DACL specified
|
||||
nullptr // do not change SACL
|
||||
);
|
||||
|
||||
Cleanup:
|
||||
Cleanup:
|
||||
|
||||
if (pACL != nullptr) {
|
||||
HeapFree(GetProcessHeap(), 0, pACL);
|
||||
}
|
||||
if (pTokenUser != nullptr) {
|
||||
HeapFree(GetProcessHeap(), 0, pTokenUser);
|
||||
}
|
||||
if (hToken != nullptr) {
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
if (pACL != nullptr) {
|
||||
HeapFree(GetProcessHeap(), 0, pACL);
|
||||
}
|
||||
if (pTokenUser != nullptr) {
|
||||
HeapFree(GetProcessHeap(), 0, pTokenUser);
|
||||
}
|
||||
if (hToken != nullptr) {
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
#endif
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
} // namespace Tools
|
||||
|
@ -29,33 +29,33 @@
|
||||
|
||||
class QIODevice;
|
||||
|
||||
namespace Tools {
|
||||
|
||||
QString humanReadableFileSize(qint64 bytes);
|
||||
bool hasChild(const QObject* parent, const QObject* child);
|
||||
bool readFromDevice(QIODevice* device, QByteArray& data, int size = 16384);
|
||||
bool readAllFromDevice(QIODevice* device, QByteArray& data);
|
||||
QString imageReaderFilter();
|
||||
bool isHex(const QByteArray& ba);
|
||||
bool isBase64(const QByteArray& ba);
|
||||
void sleep(int ms);
|
||||
void wait(int ms);
|
||||
void disableCoreDumps();
|
||||
void setupSearchPaths();
|
||||
bool createWindowsDACL();
|
||||
|
||||
template <typename RandomAccessIterator, typename T>
|
||||
RandomAccessIterator binaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T& value)
|
||||
namespace Tools
|
||||
{
|
||||
RandomAccessIterator it = std::lower_bound(begin, end, value);
|
||||
|
||||
if ((it == end) || (value < *it)) {
|
||||
return end;
|
||||
QString humanReadableFileSize(qint64 bytes);
|
||||
bool hasChild(const QObject* parent, const QObject* child);
|
||||
bool readFromDevice(QIODevice* device, QByteArray& data, int size = 16384);
|
||||
bool readAllFromDevice(QIODevice* device, QByteArray& data);
|
||||
QString imageReaderFilter();
|
||||
bool isHex(const QByteArray& ba);
|
||||
bool isBase64(const QByteArray& ba);
|
||||
void sleep(int ms);
|
||||
void wait(int ms);
|
||||
void disableCoreDumps();
|
||||
void setupSearchPaths();
|
||||
bool createWindowsDACL();
|
||||
|
||||
template <typename RandomAccessIterator, typename T>
|
||||
RandomAccessIterator binaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T& value)
|
||||
{
|
||||
RandomAccessIterator it = std::lower_bound(begin, end, value);
|
||||
|
||||
if ((it == end) || (value < *it)) {
|
||||
return end;
|
||||
} else {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tools
|
||||
|
||||
|
@ -22,8 +22,8 @@
|
||||
#include <QDir>
|
||||
#include <QLibraryInfo>
|
||||
#include <QLocale>
|
||||
#include <QTranslator>
|
||||
#include <QRegularExpression>
|
||||
#include <QTranslator>
|
||||
|
||||
#include "config-keepassx.h"
|
||||
#include "core/Config.h"
|
||||
@ -47,8 +47,7 @@ void Translator::installTranslators()
|
||||
#ifdef QT_DEBUG
|
||||
QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR),
|
||||
#endif
|
||||
filePath()->dataPath("translations")
|
||||
};
|
||||
filePath()->dataPath("translations")};
|
||||
|
||||
bool translationsLoaded = false;
|
||||
for (const QString& path : paths) {
|
||||
@ -72,10 +71,9 @@ QList<QPair<QString, QString>> Translator::availableLanguages()
|
||||
#ifdef QT_DEBUG
|
||||
QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR),
|
||||
#endif
|
||||
filePath()->dataPath("translations")
|
||||
};
|
||||
filePath()->dataPath("translations")};
|
||||
|
||||
QList<QPair<QString, QString> > languages;
|
||||
QList<QPair<QString, QString>> languages;
|
||||
languages.append(QPair<QString, QString>("system", "System default"));
|
||||
|
||||
QRegularExpression regExp("^keepassx_([a-zA-Z_]+)\\.qm$", QRegularExpression::CaseInsensitiveOption);
|
||||
@ -138,7 +136,8 @@ bool Translator::installQtTranslator(const QString& language, const QString& pat
|
||||
QScopedPointer<QTranslator> qtTranslator(new QTranslator(qApp));
|
||||
if (qtTranslator->load(QString("qtbase_%1").arg(language), path)) {
|
||||
return QCoreApplication::installTranslator(qtTranslator.take());
|
||||
} else if (qtTranslator->load(QString("qtbase_%1").arg(language), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) {
|
||||
} else if (qtTranslator->load(QString("qtbase_%1").arg(language),
|
||||
QLibraryInfo::location(QLibraryInfo::TranslationsPath))) {
|
||||
return QCoreApplication::installTranslator(qtTranslator.take());
|
||||
}
|
||||
return false;
|
||||
|
@ -22,8 +22,8 @@
|
||||
#include "crypto/Random.h"
|
||||
|
||||
const int Uuid::Length = 16;
|
||||
const QRegExp Uuid::HexRegExp = QRegExp(QString("^[0-9A-F]{%1}$").arg(QString::number(Uuid::Length * 2)),
|
||||
Qt::CaseInsensitive);
|
||||
const QRegExp Uuid::HexRegExp =
|
||||
QRegExp(QString("^[0-9A-F]{%1}$").arg(QString::number(Uuid::Length * 2)), Qt::CaseInsensitive);
|
||||
|
||||
Uuid::Uuid()
|
||||
: m_data(Length, 0)
|
||||
@ -120,5 +120,5 @@ QDataStream& operator>>(QDataStream& stream, Uuid& uuid)
|
||||
|
||||
bool Uuid::isUuid(const QString& uuid)
|
||||
{
|
||||
return Uuid::HexRegExp.exactMatch(uuid);
|
||||
return Uuid::HexRegExp.exactMatch(uuid);
|
||||
}
|
||||
|
@ -19,8 +19,8 @@
|
||||
#define KEEPASSX_UUID_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QRegExp>
|
||||
#include <QString>
|
||||
|
||||
class Uuid
|
||||
{
|
||||
|
@ -116,7 +116,8 @@ bool Crypto::checkAlgorithms()
|
||||
|
||||
bool Crypto::selfTest()
|
||||
{
|
||||
return testSha256() && testSha512() && testAes256Cbc() && testAes256Ecb() && testTwofish() && testSalsa20() && testChaCha20();
|
||||
return testSha256() && testSha512() && testAes256Cbc() && testAes256Ecb() && testTwofish() && testSalsa20()
|
||||
&& testChaCha20();
|
||||
}
|
||||
|
||||
void Crypto::raiseError(const QString& str)
|
||||
@ -127,8 +128,8 @@ void Crypto::raiseError(const QString& str)
|
||||
|
||||
bool Crypto::testSha256()
|
||||
{
|
||||
QByteArray sha256Test = CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
CryptoHash::Sha256);
|
||||
QByteArray sha256Test =
|
||||
CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", CryptoHash::Sha256);
|
||||
|
||||
if (sha256Test != QByteArray::fromHex("248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1")) {
|
||||
raiseError("SHA-256 mismatch.");
|
||||
@ -140,10 +141,11 @@ bool Crypto::testSha256()
|
||||
|
||||
bool Crypto::testSha512()
|
||||
{
|
||||
QByteArray sha512Test = CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
CryptoHash::Sha512);
|
||||
QByteArray sha512Test =
|
||||
CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", CryptoHash::Sha512);
|
||||
|
||||
if (sha512Test != QByteArray::fromHex("204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445")) {
|
||||
if (sha512Test != QByteArray::fromHex("204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b"
|
||||
"07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445")) {
|
||||
raiseError("SHA-512 mismatch.");
|
||||
return false;
|
||||
}
|
||||
@ -262,7 +264,6 @@ bool Crypto::testTwofish()
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
SymmetricCipher twofishDecrypt(SymmetricCipher::Twofish, SymmetricCipher::Cbc, SymmetricCipher::Decrypt);
|
||||
if (!twofishDecrypt.init(key, iv)) {
|
||||
raiseError(twofishEncrypt.errorString());
|
||||
@ -289,8 +290,7 @@ bool Crypto::testSalsa20()
|
||||
QByteArray salsa20Cipher = QByteArray::fromHex("B4C0AFA503BE7FC29A62058166D56F8F");
|
||||
bool ok;
|
||||
|
||||
SymmetricCipher salsa20Stream(SymmetricCipher::Salsa20, SymmetricCipher::Stream,
|
||||
SymmetricCipher::Encrypt);
|
||||
SymmetricCipher salsa20Stream(SymmetricCipher::Salsa20, SymmetricCipher::Stream, SymmetricCipher::Encrypt);
|
||||
if (!salsa20Stream.init(salsa20Key, salsa20iv)) {
|
||||
raiseError(salsa20Stream.errorString());
|
||||
return false;
|
||||
@ -309,15 +309,17 @@ bool Crypto::testSalsa20()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Crypto::testChaCha20() {
|
||||
bool Crypto::testChaCha20()
|
||||
{
|
||||
QByteArray chacha20Key = QByteArray::fromHex("0000000000000000000000000000000000000000000000000000000000000000");
|
||||
QByteArray chacha20iv = QByteArray::fromHex("0000000000000000");
|
||||
QByteArray chacha20Plain = QByteArray::fromHex("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
|
||||
QByteArray chacha20Cipher = QByteArray::fromHex("76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586");
|
||||
QByteArray chacha20Plain = QByteArray::fromHex("0000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000");
|
||||
QByteArray chacha20Cipher = QByteArray::fromHex("76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da"
|
||||
"41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586");
|
||||
bool ok;
|
||||
|
||||
SymmetricCipher chacha20Stream(SymmetricCipher::ChaCha20, SymmetricCipher::Stream,
|
||||
SymmetricCipher::Encrypt);
|
||||
SymmetricCipher chacha20Stream(SymmetricCipher::ChaCha20, SymmetricCipher::Stream, SymmetricCipher::Encrypt);
|
||||
if (!chacha20Stream.init(chacha20Key, chacha20iv)) {
|
||||
raiseError(chacha20Stream.errorString());
|
||||
return false;
|
||||
|
@ -89,7 +89,6 @@ Random::Random(RandomBackend* backend)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void RandomBackendGcrypt::randomize(void* data, int len)
|
||||
{
|
||||
Q_ASSERT(Crypto::initalized());
|
||||
|
@ -25,7 +25,9 @@ class RandomBackend
|
||||
{
|
||||
public:
|
||||
virtual void randomize(void* data, int len) = 0;
|
||||
virtual ~RandomBackend() {}
|
||||
virtual ~RandomBackend()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class Random
|
||||
@ -56,7 +58,8 @@ private:
|
||||
Q_DISABLE_COPY(Random)
|
||||
};
|
||||
|
||||
inline Random* randomGen() {
|
||||
inline Random* randomGen()
|
||||
{
|
||||
return Random::instance();
|
||||
}
|
||||
|
||||
|
@ -22,9 +22,9 @@
|
||||
#include <QScopedPointer>
|
||||
#include <QString>
|
||||
|
||||
#include "core/Uuid.h"
|
||||
#include "crypto/SymmetricCipherBackend.h"
|
||||
#include "format/KeePass2.h"
|
||||
#include "core/Uuid.h"
|
||||
|
||||
class SymmetricCipher
|
||||
{
|
||||
|
@ -23,7 +23,9 @@
|
||||
class SymmetricCipherBackend
|
||||
{
|
||||
public:
|
||||
virtual ~SymmetricCipherBackend() {}
|
||||
virtual ~SymmetricCipherBackend()
|
||||
{
|
||||
}
|
||||
virtual bool init() = 0;
|
||||
virtual bool setKey(const QByteArray& key) = 0;
|
||||
virtual bool setIv(const QByteArray& iv) = 0;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user