Formatting the code.

This commit is contained in:
Louis-Bertrand Varin 2018-03-31 16:01:30 -04:00
parent 74efc57369
commit 8324d03f0a
294 changed files with 3796 additions and 3740 deletions

View file

@ -20,7 +20,7 @@
#include <QApplication> #include <QApplication>
#include <QPluginLoader> #include <QPluginLoader>
#include <QRegularExpression> #include <QRegularExpression>
#include "config-keepassx.h" #include "config-keepassx.h"
@ -304,8 +304,8 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
auto* msgBox = new QMessageBox(); auto* msgBox = new QMessageBox();
msgBox->setAttribute(Qt::WA_DeleteOnClose); msgBox->setAttribute(Qt::WA_DeleteOnClose);
msgBox->setWindowTitle(tr("Auto-Type - KeePassXC")); msgBox->setWindowTitle(tr("Auto-Type - KeePassXC"));
msgBox->setText(tr("Couldn't find an entry that matches the window title:").append("\n\n") msgBox->setText(
.append(windowTitle)); tr("Couldn't find an entry that matches the window title:").append("\n\n").append(windowTitle));
msgBox->setIcon(QMessageBox::Information); msgBox->setIcon(QMessageBox::Information);
msgBox->setStandardButtons(QMessageBox::Ok); msgBox->setStandardButtons(QMessageBox::Ok);
msgBox->show(); msgBox->show();
@ -323,8 +323,7 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
auto* selectDialog = new AutoTypeSelectDialog(); auto* selectDialog = new AutoTypeSelectDialog();
// connect slots, both of which must unlock the m_inGlobalAutoTypeDialog mutex // connect slots, both of which must unlock the m_inGlobalAutoTypeDialog mutex
connect(selectDialog, SIGNAL(matchActivated(AutoTypeMatch)), connect(selectDialog, SIGNAL(matchActivated(AutoTypeMatch)), SLOT(performAutoTypeFromGlobal(AutoTypeMatch)));
SLOT(performAutoTypeFromGlobal(AutoTypeMatch)));
connect(selectDialog, SIGNAL(rejected()), SLOT(autoTypeRejectedFromGlobal())); connect(selectDialog, SIGNAL(rejected()), SLOT(autoTypeRejectedFromGlobal()));
selectDialog->setMatchList(matchList); selectDialog->setMatchList(matchList);
@ -449,11 +448,11 @@ QList<AutoTypeAction*> AutoType::createActionFromTemplate(const QString& tmpl, c
list.append(new AutoTypeKey(Qt::Key_Left)); list.append(new AutoTypeKey(Qt::Key_Left));
} else if (tmplName.compare("right", Qt::CaseInsensitive) == 0) { } else if (tmplName.compare("right", Qt::CaseInsensitive) == 0) {
list.append(new AutoTypeKey(Qt::Key_Right)); list.append(new AutoTypeKey(Qt::Key_Right));
} else if (tmplName.compare("insert", Qt::CaseInsensitive) == 0 || } else if (tmplName.compare("insert", Qt::CaseInsensitive) == 0
tmplName.compare("ins", Qt::CaseInsensitive) == 0) { || tmplName.compare("ins", Qt::CaseInsensitive) == 0) {
list.append(new AutoTypeKey(Qt::Key_Insert)); list.append(new AutoTypeKey(Qt::Key_Insert));
} else if (tmplName.compare("delete", Qt::CaseInsensitive) == 0 || } else if (tmplName.compare("delete", Qt::CaseInsensitive) == 0
tmplName.compare("del", Qt::CaseInsensitive) == 0) { || tmplName.compare("del", Qt::CaseInsensitive) == 0) {
list.append(new AutoTypeKey(Qt::Key_Delete)); list.append(new AutoTypeKey(Qt::Key_Delete));
} else if (tmplName.compare("home", Qt::CaseInsensitive) == 0) { } else if (tmplName.compare("home", Qt::CaseInsensitive) == 0) {
list.append(new AutoTypeKey(Qt::Key_Home)); 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)); list.append(new AutoTypeKey(Qt::Key_PageUp));
} else if (tmplName.compare("pgdown", Qt::CaseInsensitive) == 0) { } else if (tmplName.compare("pgdown", Qt::CaseInsensitive) == 0) {
list.append(new AutoTypeKey(Qt::Key_PageDown)); list.append(new AutoTypeKey(Qt::Key_PageDown));
} else if (tmplName.compare("backspace", Qt::CaseInsensitive) == 0 || } else if (tmplName.compare("backspace", Qt::CaseInsensitive) == 0
tmplName.compare("bs", Qt::CaseInsensitive) == 0 || tmplName.compare("bksp", Qt::CaseInsensitive) == 0) { || tmplName.compare("bs", Qt::CaseInsensitive) == 0
|| tmplName.compare("bksp", Qt::CaseInsensitive) == 0) {
list.append(new AutoTypeKey(Qt::Key_Backspace)); list.append(new AutoTypeKey(Qt::Key_Backspace));
} else if (tmplName.compare("break", Qt::CaseInsensitive) == 0) { } else if (tmplName.compare("break", Qt::CaseInsensitive) == 0) {
list.append(new AutoTypeKey(Qt::Key_Pause)); 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() && if (config()->get("AutoTypeEntryTitleMatch").toBool()
windowMatchesTitle(windowTitle, entry->resolvePlaceholder(entry->title()))) { && windowMatchesTitle(windowTitle, entry->resolvePlaceholder(entry->title()))) {
sequenceList.append(entry->effectiveAutoTypeSequence()); sequenceList.append(entry->effectiveAutoTypeSequence());
} }
if (config()->get("AutoTypeEntryURLMatch").toBool() && if (config()->get("AutoTypeEntryURLMatch").toBool()
windowMatchesUrl(windowTitle, entry->resolvePlaceholder(entry->url()))) { && windowMatchesUrl(windowTitle, entry->resolvePlaceholder(entry->url()))) {
sequenceList.append(entry->effectiveAutoTypeSequence()); sequenceList.append(entry->effectiveAutoTypeSequence());
} }
@ -605,7 +605,7 @@ QList<QString> AutoType::autoTypeSequences(const Entry* entry, const QString& wi
return sequenceList; return sequenceList;
} }
} else { } else {
sequenceList.append(entry->effectiveAutoTypeSequence()); sequenceList.append(entry->effectiveAutoTypeSequence());
} }
return sequenceList; return sequenceList;
@ -659,7 +659,7 @@ bool AutoType::checkSyntax(const QString& string)
QString allowRepetition = "(?:\\s\\d+)?"; QString allowRepetition = "(?:\\s\\d+)?";
// the ":" allows custom commands with syntax S:Field // the ":" allows custom commands with syntax S:Field
// exclude BEEP otherwise will be checked as valid // 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 specialLiterals = "[\\^\\%\\(\\)~\\{\\}\\[\\]\\+]" + allowRepetition;
QString functionKeys = "(?:F[1-9]" + allowRepetition + "|F1[0-2])" + allowRepetition; QString functionKeys = "(?:F[1-9]" + allowRepetition + "|F1[0-2])" + allowRepetition;
QString numpad = "NUMPAD\\d" + allowRepetition; QString numpad = "NUMPAD\\d" + allowRepetition;
@ -673,9 +673,21 @@ bool AutoType::checkSyntax(const QString& string)
// a normal string not in parentheses // a normal string not in parentheses
QString fixedStrings = "[^\\^\\%~\\+@\\{\\}]*"; QString fixedStrings = "[^\\^\\%~\\+@\\{\\}]*";
QRegularExpression autoTypeSyntax("^(?:" + shortcutKeys + "|" + fixedStrings + "|\\{(?:" + normalCommands + "|" + specialLiterals + QRegularExpression autoTypeSyntax(
"|" + functionKeys + "|" + numpad + "|" + delay + "|" + beep + "|" + vkey + ")\\}|\\{" + customAttributes + "\\})*$", "^(?:" + shortcutKeys + "|" + fixedStrings + "|\\{(?:" + normalCommands + "|" + specialLiterals + "|"
QRegularExpression::CaseInsensitiveOption); + functionKeys
+ "|"
+ numpad
+ "|"
+ delay
+ "|"
+ beep
+ "|"
+ vkey
+ ")\\}|\\{"
+ customAttributes
+ "\\})*$",
QRegularExpression::CaseInsensitiveOption);
QRegularExpressionMatch match = autoTypeSyntax.match(string); QRegularExpressionMatch match = autoTypeSyntax.match(string);
return match.hasMatch(); return match.hasMatch();
} }
@ -686,7 +698,7 @@ bool AutoType::checkSyntax(const QString& string)
bool AutoType::checkHighDelay(const QString& string) bool AutoType::checkHighDelay(const QString& string)
{ {
// 5 digit numbers(10 seconds) are too much // 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); QRegularExpressionMatch match = highDelay.match(string);
return match.hasMatch(); return match.hasMatch();
} }
@ -697,7 +709,7 @@ bool AutoType::checkHighDelay(const QString& string)
bool AutoType::checkSlowKeypress(const QString& string) bool AutoType::checkSlowKeypress(const QString& string)
{ {
// 3 digit numbers(100 milliseconds) are too much // 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); QRegularExpressionMatch match = slowKeypress.match(string);
return match.hasMatch(); return match.hasMatch();
} }
@ -724,7 +736,9 @@ bool AutoType::verifyAutoTypeSyntax(const QString& sequence)
return false; return false;
} else if (AutoType::checkHighDelay(sequence)) { } else if (AutoType::checkHighDelay(sequence)) {
QMessageBox::StandardButton reply; 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?")); tr("This Auto-Type command contains a very long delay. Do you really want to proceed?"));
if (reply == QMessageBox::No) { if (reply == QMessageBox::No) {
@ -732,7 +746,9 @@ bool AutoType::verifyAutoTypeSyntax(const QString& sequence)
} }
} else if (AutoType::checkSlowKeypress(sequence)) { } else if (AutoType::checkSlowKeypress(sequence)) {
QMessageBox::StandardButton reply; 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?")); tr("This Auto-Type command contains very slow key presses. Do you really want to proceed?"));
if (reply == QMessageBox::No) { if (reply == QMessageBox::No) {
@ -740,8 +756,9 @@ bool AutoType::verifyAutoTypeSyntax(const QString& sequence)
} }
} else if (AutoType::checkHighRepetition(sequence)) { } else if (AutoType::checkHighRepetition(sequence)) {
QMessageBox::StandardButton reply; QMessageBox::StandardButton reply;
reply = QMessageBox::question(nullptr, tr("Auto-Type"), reply =
tr("This Auto-Type command contains arguments which are repeated very often. Do you really want to proceed?")); 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) { if (reply == QMessageBox::No) {
return false; return false;

View file

@ -19,10 +19,10 @@
#ifndef KEEPASSX_AUTOTYPE_H #ifndef KEEPASSX_AUTOTYPE_H
#define KEEPASSX_AUTOTYPE_H #define KEEPASSX_AUTOTYPE_H
#include <QMutex>
#include <QObject> #include <QObject>
#include <QStringList> #include <QStringList>
#include <QWidget> #include <QWidget>
#include <QMutex>
#include "core/AutoTypeMatch.h" #include "core/AutoTypeMatch.h"
@ -47,8 +47,7 @@ public:
static bool checkSlowKeypress(const QString& string); static bool checkSlowKeypress(const QString& string);
static bool checkHighDelay(const QString& string); static bool checkHighDelay(const QString& string);
static bool verifyAutoTypeSyntax(const QString& sequence); static bool verifyAutoTypeSyntax(const QString& sequence);
void performAutoType(const Entry* entry, void performAutoType(const Entry* entry, QWidget* hideWindow = nullptr);
QWidget* hideWindow = nullptr);
inline bool isAvailable() inline bool isAvailable()
{ {

View file

@ -34,7 +34,6 @@ void AutoTypeChar::accept(AutoTypeExecutor* executor)
executor->execChar(this); executor->execChar(this);
} }
AutoTypeKey::AutoTypeKey(Qt::Key key) AutoTypeKey::AutoTypeKey(Qt::Key key)
: key(key) : key(key)
{ {
@ -50,7 +49,6 @@ void AutoTypeKey::accept(AutoTypeExecutor* executor)
executor->execKey(this); executor->execKey(this);
} }
AutoTypeDelay::AutoTypeDelay(int delayMs) AutoTypeDelay::AutoTypeDelay(int delayMs)
: delayMs(delayMs) : delayMs(delayMs)
{ {
@ -66,7 +64,6 @@ void AutoTypeDelay::accept(AutoTypeExecutor* executor)
executor->execDelay(this); executor->execDelay(this);
} }
AutoTypeClearField::AutoTypeClearField() AutoTypeClearField::AutoTypeClearField()
{ {
} }
@ -81,7 +78,6 @@ void AutoTypeClearField::accept(AutoTypeExecutor* executor)
executor->execClearField(this); executor->execClearField(this);
} }
void AutoTypeExecutor::execDelay(AutoTypeDelay* action) void AutoTypeExecutor::execDelay(AutoTypeDelay* action)
{ {
Tools::wait(action->delayMs); Tools::wait(action->delayMs);

View file

@ -19,8 +19,8 @@
#define KEEPASSX_AUTOTYPEACTION_H #define KEEPASSX_AUTOTYPEACTION_H
#include <QChar> #include <QChar>
#include <Qt>
#include <QObject> #include <QObject>
#include <Qt>
#include "core/Global.h" #include "core/Global.h"
@ -29,7 +29,9 @@ class AutoTypeExecutor;
class KEEPASSX_EXPORT AutoTypeAction class KEEPASSX_EXPORT AutoTypeAction
{ {
public: public:
virtual ~AutoTypeAction() {} virtual ~AutoTypeAction()
{
}
virtual AutoTypeAction* clone() = 0; virtual AutoTypeAction* clone() = 0;
virtual void accept(AutoTypeExecutor* executor) = 0; virtual void accept(AutoTypeExecutor* executor) = 0;
}; };
@ -75,7 +77,9 @@ public:
class KEEPASSX_EXPORT AutoTypeExecutor class KEEPASSX_EXPORT AutoTypeExecutor
{ {
public: public:
virtual ~AutoTypeExecutor() {} virtual ~AutoTypeExecutor()
{
}
virtual void execChar(AutoTypeChar* action) = 0; virtual void execChar(AutoTypeChar* action) = 0;
virtual void execKey(AutoTypeKey* action) = 0; virtual void execKey(AutoTypeKey* action) = 0;
virtual void execDelay(AutoTypeDelay* action); virtual void execDelay(AutoTypeDelay* action);

View file

@ -25,7 +25,9 @@
class AutoTypePlatformInterface class AutoTypePlatformInterface
{ {
public: public:
virtual ~AutoTypePlatformInterface() {} virtual ~AutoTypePlatformInterface()
{
}
virtual bool isAvailable() = 0; virtual bool isAvailable() = 0;
virtual QStringList windowTitles() = 0; virtual QStringList windowTitles() = 0;
virtual WId activeWindow() = 0; virtual WId activeWindow() = 0;
@ -35,7 +37,9 @@ public:
virtual int platformEventFilter(void* event) = 0; virtual int platformEventFilter(void* event) = 0;
virtual int initialTimeout() = 0; virtual int initialTimeout() = 0;
virtual bool raiseWindow(WId window) = 0; virtual bool raiseWindow(WId window) = 0;
virtual void unload() {} virtual void unload()
{
}
virtual AutoTypeExecutor* createExecutor() = 0; virtual AutoTypeExecutor* createExecutor() = 0;

View file

@ -61,7 +61,7 @@ AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent)
connect(m_view, SIGNAL(activated(QModelIndex)), SLOT(emitMatchActivated(QModelIndex))); connect(m_view, SIGNAL(activated(QModelIndex)), SLOT(emitMatchActivated(QModelIndex)));
connect(m_view, SIGNAL(clicked(QModelIndex)), SLOT(emitMatchActivated(QModelIndex))); connect(m_view, SIGNAL(clicked(QModelIndex)), SLOT(emitMatchActivated(QModelIndex)));
connect(m_view->model(), SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(matchRemoved())); connect(m_view->model(), SIGNAL(rowsRemoved(QModelIndex, int, int)), SLOT(matchRemoved()));
connect(m_view, SIGNAL(rejected()), SLOT(reject())); connect(m_view, SIGNAL(rejected()), SLOT(reject()));
layout->addWidget(m_view); layout->addWidget(m_view);
@ -109,7 +109,7 @@ void AutoTypeSelectDialog::matchRemoved()
if (m_rejected) { if (m_rejected) {
return; return;
} }
if (m_view->model()->rowCount() == 0) { if (m_view->model()->rowCount() == 0) {
reject(); reject();
} }

View file

@ -36,8 +36,7 @@ void AutoTypeSelectView::mouseMoveEvent(QMouseEvent* event)
if (index.isValid()) { if (index.isValid()) {
setCurrentIndex(index); setCurrentIndex(index);
setCursor(Qt::PointingHandCursor); setCursor(Qt::PointingHandCursor);
} } else {
else {
unsetCursor(); unsetCursor();
} }

View file

@ -50,8 +50,7 @@ void ShortcutWidget::setShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
if (autoType()->registerGlobalShortcut(m_key, m_modifiers)) { if (autoType()->registerGlobalShortcut(m_key, m_modifiers)) {
setStyleSheet(""); setStyleSheet("");
} } else {
else {
setStyleSheet("background-color: #FF9696;"); setStyleSheet("background-color: #FF9696;");
} }
} }
@ -112,14 +111,12 @@ void ShortcutWidget::keyEvent(QKeyEvent* event)
if (!release && !keyIsModifier) { if (!release && !keyIsModifier) {
if (modifiers != 0) { if (modifiers != 0) {
setShortcut(key, modifiers); setShortcut(key, modifiers);
} } else {
else {
resetShortcut(); resetShortcut();
setStyleSheet(""); setStyleSheet("");
displayShortcut(key, modifiers); displayShortcut(key, modifiers);
} }
} } else {
else {
if (m_locked) { if (m_locked) {
resetShortcut(); resetShortcut();
setStyleSheet(""); setStyleSheet("");

View file

@ -33,8 +33,7 @@ bool WildcardMatcher::match(const QString& pattern)
if (patternContainsWildcard()) { if (patternContainsWildcard()) {
return matchWithWildcards(); return matchWithWildcards();
} } else {
else {
return patternEqualsText(); return patternEqualsText();
} }
} }
@ -63,8 +62,7 @@ bool WildcardMatcher::matchWithWildcards()
bool WildcardMatcher::startOrEndDoesNotMatch(const QStringList& parts) bool WildcardMatcher::startOrEndDoesNotMatch(const QStringList& parts)
{ {
return !m_text.startsWith(parts.first(), Sensitivity) || return !m_text.startsWith(parts.first(), Sensitivity) || !m_text.endsWith(parts.last(), Sensitivity);
!m_text.endsWith(parts.last(), Sensitivity);
} }
bool WildcardMatcher::partsMatch(const QStringList& parts) bool WildcardMatcher::partsMatch(const QStringList& parts)

View file

@ -20,13 +20,11 @@
#include <QtPlugin> #include <QtPlugin>
#include "autotype/AutoTypePlatformPlugin.h"
#include "autotype/AutoTypeAction.h" #include "autotype/AutoTypeAction.h"
#include "autotype/AutoTypePlatformPlugin.h"
#include "autotype/test/AutoTypeTestInterface.h" #include "autotype/test/AutoTypeTestInterface.h"
class AutoTypePlatformTest : public QObject, class AutoTypePlatformTest : public QObject, public AutoTypePlatformInterface, public AutoTypeTestInterface
public AutoTypePlatformInterface,
public AutoTypeTestInterface
{ {
Q_OBJECT Q_OBJECT
Q_PLUGIN_METADATA(IID "org.keepassx.AutoTypePlatformInterface") Q_PLUGIN_METADATA(IID "org.keepassx.AutoTypePlatformInterface")

View file

@ -23,7 +23,9 @@
class AutoTypeTestInterface class AutoTypeTestInterface
{ {
public: public:
virtual ~AutoTypeTestInterface() {} virtual ~AutoTypeTestInterface()
{
}
virtual void setActiveWindowTitle(const QString& title) = 0; virtual void setActiveWindowTitle(const QString& title) = 0;
virtual QString actionChars() = 0; virtual QString actionChars() = 0;

View file

@ -94,7 +94,7 @@ void AutoTypePlatformWin::unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModi
// //
int AutoTypePlatformWin::platformEventFilter(void* event) 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) { if (msg->message == WM_HOTKEY && msg->wParam == HOTKEY_ID) {
emit globalShortcutTriggered(); emit globalShortcutTriggered();
@ -480,17 +480,14 @@ BOOL AutoTypePlatformWin::isAltTabWindow(HWND hwnd)
// //
// Window title enum proc // Window title enum proc
// //
BOOL CALLBACK AutoTypePlatformWin::windowTitleEnumProc( BOOL CALLBACK AutoTypePlatformWin::windowTitleEnumProc(_In_ HWND hwnd, _In_ LPARAM lParam)
_In_ HWND hwnd,
_In_ LPARAM lParam
)
{ {
if (!isAltTabWindow(hwnd)) { if (!isAltTabWindow(hwnd)) {
// Skip window // Skip window
return TRUE; return TRUE;
} }
QStringList *list = reinterpret_cast<QStringList *>(lParam); QStringList* list = reinterpret_cast<QStringList*>(lParam);
QString title = windowTitle(hwnd); QString title = windowTitle(hwnd);
if (!title.isEmpty()) { if (!title.isEmpty()) {
@ -508,7 +505,7 @@ QString AutoTypePlatformWin::windowTitle(HWND hwnd)
wchar_t title[MAX_WINDOW_TITLE_LENGTH]; wchar_t title[MAX_WINDOW_TITLE_LENGTH];
int count = ::GetWindowTextW(hwnd, 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);
} }
// //

View file

@ -22,8 +22,8 @@
#include <QtPlugin> #include <QtPlugin>
#include <Windows.h> #include <Windows.h>
#include "autotype/AutoTypePlatformPlugin.h"
#include "autotype/AutoTypeAction.h" #include "autotype/AutoTypeAction.h"
#include "autotype/AutoTypePlatformPlugin.h"
class AutoTypePlatformWin : public QObject, public AutoTypePlatformInterface class AutoTypePlatformWin : public QObject, public AutoTypePlatformInterface
{ {
@ -72,4 +72,3 @@ private:
}; };
#endif // KEEPASSX_AUTOTYPEWINDOWS_H #endif // KEEPASSX_AUTOTYPEWINDOWS_H

View file

@ -40,11 +40,14 @@ AutoTypePlatformX11::AutoTypePlatformX11()
m_atomUtf8String = XInternAtom(m_dpy, "UTF8_STRING", True); m_atomUtf8String = XInternAtom(m_dpy, "UTF8_STRING", True);
m_atomNetActiveWindow = XInternAtom(m_dpy, "_NET_ACTIVE_WINDOW", True); m_atomNetActiveWindow = XInternAtom(m_dpy, "_NET_ACTIVE_WINDOW", True);
m_classBlacklist << "desktop_window" << "gnome-panel"; // Gnome m_classBlacklist << "desktop_window"
m_classBlacklist << "kdesktop" << "kicker"; // KDE 3 << "gnome-panel"; // Gnome
m_classBlacklist << "kdesktop"
<< "kicker"; // KDE 3
m_classBlacklist << "Plasma"; // KDE 4 m_classBlacklist << "Plasma"; // KDE 4
m_classBlacklist << "plasmashell"; // KDE 5 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_currentGlobalKey = static_cast<Qt::Key>(0);
m_currentGlobalModifiers = 0; m_currentGlobalModifiers = 0;
@ -146,12 +149,9 @@ bool AutoTypePlatformX11::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifi
startCatchXErrors(); startCatchXErrors();
XGrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow, True, GrabModeAsync, GrabModeAsync); XGrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow, True, GrabModeAsync, GrabModeAsync);
XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow, True, GrabModeAsync, XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow, True, GrabModeAsync, GrabModeAsync);
GrabModeAsync); XGrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow, True, GrabModeAsync, GrabModeAsync);
XGrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow, True, GrabModeAsync, XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow, True, GrabModeAsync, GrabModeAsync);
GrabModeAsync);
XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow, True,
GrabModeAsync, GrabModeAsync);
stopCatchXErrors(); stopCatchXErrors();
if (!m_xErrorOccurred) { if (!m_xErrorOccurred) {
@ -160,8 +160,7 @@ bool AutoTypePlatformX11::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifi
m_currentGlobalKeycode = keycode; m_currentGlobalKeycode = keycode;
m_currentGlobalNativeModifiers = nativeModifiers; m_currentGlobalNativeModifiers = nativeModifiers;
return true; return true;
} } else {
else {
unregisterGlobalShortcut(key, modifiers); unregisterGlobalShortcut(key, modifiers);
return false; return false;
} }
@ -211,29 +210,26 @@ int AutoTypePlatformX11::platformEventFilter(void* event)
if (type == XCB_KEY_PRESS || type == XCB_KEY_RELEASE) { if (type == XCB_KEY_PRESS || type == XCB_KEY_RELEASE) {
xcb_key_press_event_t* keyPressEvent = static_cast<xcb_key_press_event_t*>(event); xcb_key_press_event_t* keyPressEvent = static_cast<xcb_key_press_event_t*>(event);
if (keyPressEvent->detail == m_currentGlobalKeycode if (keyPressEvent->detail == m_currentGlobalKeycode
&& (keyPressEvent->state & m_modifierMask) == m_currentGlobalNativeModifiers && (keyPressEvent->state & m_modifierMask) == m_currentGlobalNativeModifiers
&& (!QApplication::activeWindow() || QApplication::activeWindow()->isMinimized()) && (!QApplication::activeWindow() || QApplication::activeWindow()->isMinimized())
&& m_loaded) { && m_loaded) {
if (type == XCB_KEY_PRESS) { if (type == XCB_KEY_PRESS) {
emit globalShortcutTriggered(); emit globalShortcutTriggered();
} }
return 1; 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); xcb_mapping_notify_event_t* mappingNotifyEvent = static_cast<xcb_mapping_notify_event_t*>(event);
if (mappingNotifyEvent->request == XCB_MAPPING_KEYBOARD if (mappingNotifyEvent->request == XCB_MAPPING_KEYBOARD
|| mappingNotifyEvent->request == XCB_MAPPING_MODIFIER) || mappingNotifyEvent->request == XCB_MAPPING_MODIFIER) {
{
XMappingEvent xMappingEvent; XMappingEvent xMappingEvent;
memset(&xMappingEvent, 0, sizeof(xMappingEvent)); memset(&xMappingEvent, 0, sizeof(xMappingEvent));
xMappingEvent.type = MappingNotify; xMappingEvent.type = MappingNotify;
xMappingEvent.display = m_dpy; xMappingEvent.display = m_dpy;
if (mappingNotifyEvent->request == XCB_MAPPING_KEYBOARD) { if (mappingNotifyEvent->request == XCB_MAPPING_KEYBOARD) {
xMappingEvent.request = MappingKeyboard; xMappingEvent.request = MappingKeyboard;
} } else {
else {
xMappingEvent.request = MappingModifier; xMappingEvent.request = MappingModifier;
} }
xMappingEvent.first_keycode = mappingNotifyEvent->first_keycode; 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 // 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, int retVal = XGetWindowProperty(
&type, &format, &nitems, &after, &data); m_dpy, window, m_atomNetWmName, 0, 1000, False, m_atomUtf8String, &type, &format, &nitems, &after, &data);
if ((retVal == 0) && data) { if ((retVal == 0) && data) {
title = QString::fromUtf8(reinterpret_cast<char*>(data)); title = QString::fromUtf8(reinterpret_cast<char*>(data));
} } else {
else {
XTextProperty textProp; XTextProperty textProp;
retVal = XGetTextProperty(m_dpy, window, &textProp, m_atomWmName); retVal = XGetTextProperty(m_dpy, window, &textProp, m_atomWmName);
if ((retVal != 0) && textProp.value) { if ((retVal != 0) && textProp.value) {
@ -278,12 +273,10 @@ QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist)
if (textProp.encoding == m_atomUtf8String) { if (textProp.encoding == m_atomUtf8String) {
title = QString::fromUtf8(reinterpret_cast<char*>(textProp.value)); title = QString::fromUtf8(reinterpret_cast<char*>(textProp.value));
} } else if ((XmbTextPropertyToTextList(m_dpy, &textProp, &textList, &count) == 0) && textList
else if ((XmbTextPropertyToTextList(m_dpy, &textProp, &textList, &count) == 0) && (count > 0)) {
&& textList && (count > 0)) {
title = QString::fromLocal8Bit(textList[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)); title = QString::fromLocal8Bit(reinterpret_cast<char*>(textProp.value));
} }
@ -386,8 +379,8 @@ bool AutoTypePlatformX11::isTopLevelWindow(Window window)
unsigned long nitems; unsigned long nitems;
unsigned long after; unsigned long after;
unsigned char* data = Q_NULLPTR; unsigned char* data = Q_NULLPTR;
int retVal = XGetWindowProperty(m_dpy, window, m_atomWmState, 0, 2, False, m_atomWmState, &type, &format, int retVal = XGetWindowProperty(
&nitems, &after, &data); m_dpy, window, m_atomWmState, 0, 2, False, m_atomWmState, &type, &format, &nitems, &after, &data);
bool result = false; bool result = false;
@ -408,15 +401,12 @@ KeySym AutoTypePlatformX11::charToKeySym(const QChar& ch)
ushort unicode = ch.unicode(); ushort unicode = ch.unicode();
/* first check for Latin-1 characters (1:1 mapping) */ /* first check for Latin-1 characters (1:1 mapping) */
if ((unicode >= 0x0020 && unicode <= 0x007e) if ((unicode >= 0x0020 && unicode <= 0x007e) || (unicode >= 0x00a0 && unicode <= 0x00ff)) {
|| (unicode >= 0x00a0 && unicode <= 0x00ff)) {
return unicode; return unicode;
} }
/* mapping table generated from keysymdef.h */ /* mapping table generated from keysymdef.h */
const uint* match = Tools::binaryFind(m_unicodeToKeysymKeys, const uint* match = Tools::binaryFind(m_unicodeToKeysymKeys, m_unicodeToKeysymKeys + m_unicodeToKeysymLen, unicode);
m_unicodeToKeysymKeys + m_unicodeToKeysymLen,
unicode);
int index = match - m_unicodeToKeysymKeys; int index = match - m_unicodeToKeysymKeys;
if (index != m_unicodeToKeysymLen) { if (index != m_unicodeToKeysymLen) {
return m_unicodeToKeysymValues[index]; return m_unicodeToKeysymValues[index];
@ -483,8 +473,7 @@ KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key)
default: default:
if (key >= Qt::Key_F1 && key <= Qt::Key_F16) { if (key >= Qt::Key_F1 && key <= Qt::Key_F16) {
return XK_F1 + (key - Qt::Key_F1); return XK_F1 + (key - Qt::Key_F1);
} } else {
else {
return NoSymbol; return NoSymbol;
} }
} }
@ -493,13 +482,13 @@ KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key)
/* /*
* Update the keyboard and modifier mapping. * Update the keyboard and modifier mapping.
* We need the KeyboardMapping for AddKeysym. * 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() void AutoTypePlatformX11::updateKeymap()
{ {
int keycode, inx; int keycode, inx;
int mod_index, mod_key; int mod_index, mod_key;
XModifierKeymap *modifiers; XModifierKeymap* modifiers;
if (m_xkb) { if (m_xkb) {
XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True); XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True);
@ -507,10 +496,9 @@ void AutoTypePlatformX11::updateKeymap()
m_xkb = getKeyboard(); m_xkb = getKeyboard();
XDisplayKeycodes(m_dpy, &m_minKeycode, &m_maxKeycode); XDisplayKeycodes(m_dpy, &m_minKeycode, &m_maxKeycode);
if (m_keysymTable != NULL) XFree(m_keysymTable); if (m_keysymTable != NULL)
m_keysymTable = XGetKeyboardMapping(m_dpy, XFree(m_keysymTable);
m_minKeycode, m_maxKeycode - m_minKeycode + 1, m_keysymTable = XGetKeyboardMapping(m_dpy, m_minKeycode, m_maxKeycode - m_minKeycode + 1, &m_keysymPerKeycode);
&m_keysymPerKeycode);
/* determine the keycode to use for remapped keys */ /* determine the keycode to use for remapped keys */
inx = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode; inx = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode;
@ -518,16 +506,16 @@ void AutoTypePlatformX11::updateKeymap()
for (keycode = m_minKeycode; keycode <= m_maxKeycode; keycode++) { for (keycode = m_minKeycode; keycode <= m_maxKeycode; keycode++) {
inx = (keycode - m_minKeycode) * m_keysymPerKeycode; inx = (keycode - m_minKeycode) * m_keysymPerKeycode;
if (m_keysymTable[inx] == NoSymbol) { if (m_keysymTable[inx] == NoSymbol) {
m_remapKeycode = keycode; m_remapKeycode = keycode;
m_currentRemapKeysym = NoSymbol; m_currentRemapKeysym = NoSymbol;
break; break;
} }
} }
} }
/* determine the keycode to use for modifiers */ /* determine the keycode to use for modifiers */
modifiers = XGetModifierMapping(m_dpy); 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; m_modifier_keycode[mod_index] = 0;
for (mod_key = 0; mod_key < modifiers->max_keypermod; mod_key++) { for (mod_key = 0; mod_key < modifiers->max_keypermod; mod_key++) {
keycode = modifiers->modifiermap[mod_index * 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; return 0;
} }
int inx = (m_remapKeycode- m_minKeycode) * m_keysymPerKeycode; int inx = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode;
m_keysymTable[inx] = keysym; m_keysymTable[inx] = keysym;
m_currentRemapKeysym = keysym; m_currentRemapKeysym = keysym;
@ -644,7 +632,7 @@ int AutoTypePlatformX11::AddKeysym(KeySym keysym)
void AutoTypePlatformX11::SendKeyEvent(unsigned keycode, bool press) void AutoTypePlatformX11::SendKeyEvent(unsigned keycode, bool press)
{ {
XSync(m_dpy, False); XSync(m_dpy, False);
int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler); int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler);
XTestFakeKeyEvent(m_dpy, keycode, press, 0); XTestFakeKeyEvent(m_dpy, keycode, press, 0);
XFlush(m_dpy); XFlush(m_dpy);
@ -659,7 +647,7 @@ void AutoTypePlatformX11::SendKeyEvent(unsigned keycode, bool press)
void AutoTypePlatformX11::SendModifiers(unsigned int mask, bool press) void AutoTypePlatformX11::SendModifiers(unsigned int mask, bool press)
{ {
int mod_index; 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)) { if (mask & (1 << mod_index)) {
SendKeyEvent(m_modifier_keycode[mod_index], press); 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 * Determines the keycode and modifier mask for the given
* keysym. * keysym.
*/ */
int AutoTypePlatformX11::GetKeycode(KeySym keysym, unsigned int *mask) int AutoTypePlatformX11::GetKeycode(KeySym keysym, unsigned int* mask)
{ {
int keycode = XKeysymToKeycode(m_dpy, keysym); int keycode = XKeysymToKeycode(m_dpy, keysym);
@ -688,15 +676,15 @@ int AutoTypePlatformX11::GetKeycode(KeySym keysym, unsigned int *mask)
return 0; 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; int shift, mod;
unsigned int mods_rtrn; unsigned int mods_rtrn;
/* determine whether there is a combination of the modifiers /* determine whether there is a combination of the modifiers
(Mod1-Mod5) with or without shift which returns keysym */ (Mod1-Mod5) with or without shift which returns keysym */
for (shift = 0; shift < 2; shift ++) { for (shift = 0; shift < 2; shift++) {
for (mod = ControlMapIndex; mod <= Mod5MapIndex; mod ++) { for (mod = ControlMapIndex; mod <= Mod5MapIndex; mod++) {
KeySym keysym_rtrn; KeySym keysym_rtrn;
*mask = (mod == ControlMapIndex) ? shift : shift | (1 << mod); *mask = (mod == ControlMapIndex) ? shift : shift | (1 << mod);
XkbTranslateKeyCode(m_xkb, keycode, *mask, &mods_rtrn, &keysym_rtrn); XkbTranslateKeyCode(m_xkb, keycode, *mask, &mods_rtrn, &keysym_rtrn);
@ -709,8 +697,6 @@ bool AutoTypePlatformX11::keysymModifiers(KeySym keysym, int keycode, unsigned i
return false; return false;
} }
/* /*
* Send sequence of KeyPressed/KeyReleased events to the focused * Send sequence of KeyPressed/KeyReleased events to the focused
* window to simulate keyboard. If modifiers (shift, control, etc) * window to simulate keyboard. If modifiers (shift, control, etc)
@ -753,7 +739,7 @@ void AutoTypePlatformX11::SendKey(KeySym keysym, unsigned int modifiers)
if (!modifiers) { if (!modifiers) {
// check every release_check_mask individually if it affects the keysym we would generate // 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 // 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)) { if (release_check_mask & (1 << mod_index)) {
unsigned int mods_rtrn; unsigned int mods_rtrn;
KeySym keysym_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 // finally check if the combination of pressed modifiers that we chose to ignore affects the keysym
unsigned int mods_rtrn; unsigned int mods_rtrn;
KeySym keysym_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) { if (keysym_rtrn != keysym) {
// oh well, release all the modifiers we don't want // oh well, release all the modifiers we don't want
release_mask = release_check_mask; release_mask = release_check_mask;
@ -810,7 +797,6 @@ int AutoTypePlatformX11::MyErrorHandler(Display* my_dpy, XErrorEvent* event)
return 0; return 0;
} }
AutoTypeExecutorX11::AutoTypeExecutorX11(AutoTypePlatformX11* platform) AutoTypeExecutorX11::AutoTypeExecutorX11(AutoTypePlatformX11* platform)
: m_platform(platform) : m_platform(platform)
{ {
@ -844,7 +830,6 @@ void AutoTypeExecutorX11::execClearField(AutoTypeClearField* action = nullptr)
nanosleep(&ts, nullptr); nanosleep(&ts, nullptr);
} }
int AutoTypePlatformX11::initialTimeout() int AutoTypePlatformX11::initialTimeout()
{ {
return 500; return 500;
@ -870,15 +855,12 @@ bool AutoTypePlatformX11::raiseWindow(WId window)
QWidget* activeWindow = QApplication::activeWindow(); QWidget* activeWindow = QApplication::activeWindow();
if (activeWindow) { if (activeWindow) {
event.xclient.data.l[2] = activeWindow->internalWinId(); event.xclient.data.l[2] = activeWindow->internalWinId();
} } else {
else {
event.xclient.data.l[2] = 0; event.xclient.data.l[2] = 0;
} }
event.xclient.data.l[3] = 0; event.xclient.data.l[3] = 0;
event.xclient.data.l[4] = 0; event.xclient.data.l[4] = 0;
XSendEvent(m_dpy, m_rootWindow, False, XSendEvent(m_dpy, m_rootWindow, False, SubstructureRedirectMask | SubstructureNotifyMask, &event);
SubstructureRedirectMask | SubstructureNotifyMask,
&event);
XFlush(m_dpy); XFlush(m_dpy);
return true; return true;

View file

@ -22,16 +22,16 @@
#include <QApplication> #include <QApplication>
#include <QSet> #include <QSet>
#include <QtPlugin>
#include <QWidget> #include <QWidget>
#include <QX11Info> #include <QX11Info>
#include <QtPlugin>
#include <X11/XKBlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/extensions/XTest.h> #include <X11/extensions/XTest.h>
#include <X11/XKBlib.h>
#include "autotype/AutoTypePlatformPlugin.h"
#include "autotype/AutoTypeAction.h" #include "autotype/AutoTypeAction.h"
#include "autotype/AutoTypePlatformPlugin.h"
#define N_MOD_INDICES (Mod5MapIndex + 1) #define N_MOD_INDICES (Mod5MapIndex + 1)
@ -81,8 +81,8 @@ private:
void AddModifier(KeySym keysym); void AddModifier(KeySym keysym);
void SendKeyEvent(unsigned keycode, bool press); void SendKeyEvent(unsigned keycode, bool press);
void SendModifiers(unsigned int mask, bool press); void SendModifiers(unsigned int mask, bool press);
int GetKeycode(KeySym keysym, unsigned int *mask); int GetKeycode(KeySym keysym, unsigned int* mask);
bool keysymModifiers(KeySym keysym, int keycode, unsigned int *mask); bool keysymModifiers(KeySym keysym, int keycode, unsigned int* mask);
static int MyErrorHandler(Display* my_dpy, XErrorEvent* event); static int MyErrorHandler(Display* my_dpy, XErrorEvent* event);

11
src/browser/BrowserAccessControlDialog.cpp Executable file → Normal file
View file

@ -17,12 +17,12 @@
*/ */
#include "BrowserAccessControlDialog.h" #include "BrowserAccessControlDialog.h"
#include "ui_BrowserAccessControlDialog.h"
#include "core/Entry.h" #include "core/Entry.h"
#include "ui_BrowserAccessControlDialog.h"
BrowserAccessControlDialog::BrowserAccessControlDialog(QWidget* parent) : BrowserAccessControlDialog::BrowserAccessControlDialog(QWidget* parent)
QDialog(parent), : QDialog(parent)
ui(new Ui::BrowserAccessControlDialog()) , ui(new Ui::BrowserAccessControlDialog())
{ {
this->setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); this->setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
@ -38,7 +38,8 @@ BrowserAccessControlDialog::~BrowserAccessControlDialog()
void BrowserAccessControlDialog::setUrl(const QString& url) void BrowserAccessControlDialog::setUrl(const QString& url)
{ {
ui->label->setText(QString(tr("%1 has requested access to passwords for the following item(s).\n" 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) void BrowserAccessControlDialog::setItems(const QList<Entry*>& items)

5
src/browser/BrowserAccessControlDialog.h Executable file → Normal file
View file

@ -24,8 +24,9 @@
class Entry; class Entry;
namespace Ui { namespace Ui
class BrowserAccessControlDialog; {
class BrowserAccessControlDialog;
} }
class BrowserAccessControlDialog : public QDialog class BrowserAccessControlDialog : public QDialog

82
src/browser/BrowserAction.cpp Executable file → Normal file
View file

@ -16,21 +16,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <QJsonDocument>
#include <QJsonParseError>
#include "BrowserAction.h" #include "BrowserAction.h"
#include "BrowserSettings.h" #include "BrowserSettings.h"
#include "config-keepassx.h"
#include "sodium.h" #include "sodium.h"
#include "sodium/crypto_box.h" #include "sodium/crypto_box.h"
#include "sodium/randombytes.h" #include "sodium/randombytes.h"
#include "config-keepassx.h" #include <QJsonDocument>
#include <QJsonParseError>
BrowserAction::BrowserAction(BrowserService& browserService) : BrowserAction::BrowserAction(BrowserService& browserService)
m_mutex(QMutex::Recursive), : m_mutex(QMutex::Recursive)
m_browserService(browserService), , m_browserService(browserService)
m_associated(false) , m_associated(false)
{ {
} }
QJsonObject BrowserAction::readResponse(const QJsonObject& json) QJsonObject BrowserAction::readResponse(const QJsonObject& json)
@ -62,7 +61,6 @@ QJsonObject BrowserAction::readResponse(const QJsonObject& json)
return handleAction(json); return handleAction(json);
} }
// Private functions // Private functions
/////////////////////// ///////////////////////
@ -80,7 +78,7 @@ QJsonObject BrowserAction::handleAction(const QJsonObject& json)
} else if (action.compare("associate", Qt::CaseSensitive) == 0) { } else if (action.compare("associate", Qt::CaseSensitive) == 0) {
return handleAssociate(json, action); return handleAssociate(json, action);
} else if (action.compare("test-associate", Qt::CaseSensitive) == 0) { } 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) { } else if (action.compare("get-logins", Qt::CaseSensitive) == 0) {
return handleGetLogins(json, action); return handleGetLogins(json, action);
} else if (action.compare("generate-password", Qt::CaseSensitive) == 0) { } else if (action.compare("generate-password", Qt::CaseSensitive) == 0) {
@ -270,7 +268,7 @@ QJsonObject BrowserAction::handleGeneratePassword(const QJsonObject& json, const
QJsonArray arr; QJsonArray arr;
QJsonObject passwd; QJsonObject passwd;
passwd["login"] = QString::number(password.length() * 8); //bits; passwd["login"] = QString::number(password.length() * 8); // bits;
passwd["password"] = password; passwd["password"] = password;
arr.append(passwd); arr.append(passwd);
@ -386,31 +384,49 @@ QJsonObject BrowserAction::buildResponse(const QString& action, const QJsonObjec
QString BrowserAction::getErrorMessage(const int errorCode) const QString BrowserAction::getErrorMessage(const int errorCode) const
{ {
switch (errorCode) { switch (errorCode) {
case ERROR_KEEPASS_DATABASE_NOT_OPENED: return QObject::tr("Database not opened"); case ERROR_KEEPASS_DATABASE_NOT_OPENED:
case ERROR_KEEPASS_DATABASE_HASH_NOT_RECEIVED: return QObject::tr("Database hash not available"); return QObject::tr("Database not opened");
case ERROR_KEEPASS_CLIENT_PUBLIC_KEY_NOT_RECEIVED: return QObject::tr("Client public key not received"); case ERROR_KEEPASS_DATABASE_HASH_NOT_RECEIVED:
case ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE: return QObject::tr("Cannot decrypt message"); return QObject::tr("Database hash not available");
case ERROR_KEEPASS_TIMEOUT_OR_NOT_CONNECTED: return QObject::tr("Timeout or cannot connect to KeePassXC"); case ERROR_KEEPASS_CLIENT_PUBLIC_KEY_NOT_RECEIVED:
case ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED: return QObject::tr("Action cancelled or denied"); return QObject::tr("Client public key not received");
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_CANNOT_DECRYPT_MESSAGE:
case ERROR_KEEPASS_ASSOCIATION_FAILED: return QObject::tr("KeePassXC association failed, try again"); return QObject::tr("Cannot decrypt message");
case ERROR_KEEPASS_KEY_CHANGE_FAILED: return QObject::tr("Key change was not successful"); case ERROR_KEEPASS_TIMEOUT_OR_NOT_CONNECTED:
case ERROR_KEEPASS_ENCRYPTION_KEY_UNRECOGNIZED: return QObject::tr("Encryption key is not recognized"); return QObject::tr("Timeout or cannot connect to KeePassXC");
case ERROR_KEEPASS_NO_SAVED_DATABASES_FOUND: return QObject::tr("No saved databases found"); case ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED:
case ERROR_KEEPASS_INCORRECT_ACTION: return QObject::tr("Incorrect action"); return QObject::tr("Action cancelled or denied");
case ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED: return QObject::tr("Empty message received"); case ERROR_KEEPASS_CANNOT_ENCRYPT_MESSAGE:
case ERROR_KEEPASS_NO_URL_PROVIDED: return QObject::tr("No URL provided"); return QObject::tr("Cannot encrypt message or public key not found. Is Native Messaging enabled in KeePassXC?");
case ERROR_KEEPASS_NO_LOGINS_FOUND: return QObject::tr("No logins found"); case ERROR_KEEPASS_ASSOCIATION_FAILED:
default: return QObject::tr("Unknown error"); 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() QString BrowserAction::getDatabaseHash()
{ {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
QByteArray hash = QCryptographicHash::hash( QByteArray hash =
(m_browserService.getDatabaseRootUuid() + m_browserService.getDatabaseRecycleBinUuid()).toUtf8(), QCryptographicHash::hash(
QCryptographicHash::Sha256).toHex(); (m_browserService.getDatabaseRootUuid() + m_browserService.getDatabaseRecycleBinUuid()).toUtf8(),
QCryptographicHash::Sha256)
.toHex();
return QString(hash); 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) { 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())); QByteArray res = getQByteArray(e.data(), (crypto_box_MACBYTES + ma.length()));
return res.toBase64(); return res.toBase64();
} }
return QString(); 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) { 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(); return QByteArray();

73
src/browser/BrowserAction.h Executable file → Normal file
View file

@ -19,32 +19,33 @@
#ifndef BROWSERACTION_H #ifndef BROWSERACTION_H
#define BROWSERACTION_H #define BROWSERACTION_H
#include <QtCore> #include "BrowserService.h"
#include <QObject>
#include <QJsonObject> #include <QJsonObject>
#include <QMutex> #include <QMutex>
#include "BrowserService.h" #include <QObject>
#include <QtCore>
class BrowserAction : public QObject class BrowserAction : public QObject
{ {
Q_OBJECT Q_OBJECT
enum { enum
ERROR_KEEPASS_DATABASE_NOT_OPENED = 1, {
ERROR_KEEPASS_DATABASE_HASH_NOT_RECEIVED = 2, ERROR_KEEPASS_DATABASE_NOT_OPENED = 1,
ERROR_KEEPASS_CLIENT_PUBLIC_KEY_NOT_RECEIVED = 3, ERROR_KEEPASS_DATABASE_HASH_NOT_RECEIVED = 2,
ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE = 4, ERROR_KEEPASS_CLIENT_PUBLIC_KEY_NOT_RECEIVED = 3,
ERROR_KEEPASS_TIMEOUT_OR_NOT_CONNECTED = 5, ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE = 4,
ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED = 6, ERROR_KEEPASS_TIMEOUT_OR_NOT_CONNECTED = 5,
ERROR_KEEPASS_CANNOT_ENCRYPT_MESSAGE = 7, ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED = 6,
ERROR_KEEPASS_ASSOCIATION_FAILED = 8, ERROR_KEEPASS_CANNOT_ENCRYPT_MESSAGE = 7,
ERROR_KEEPASS_KEY_CHANGE_FAILED = 9, ERROR_KEEPASS_ASSOCIATION_FAILED = 8,
ERROR_KEEPASS_ENCRYPTION_KEY_UNRECOGNIZED = 10, ERROR_KEEPASS_KEY_CHANGE_FAILED = 9,
ERROR_KEEPASS_NO_SAVED_DATABASES_FOUND = 11, ERROR_KEEPASS_ENCRYPTION_KEY_UNRECOGNIZED = 10,
ERROR_KEEPASS_INCORRECT_ACTION = 12, ERROR_KEEPASS_NO_SAVED_DATABASES_FOUND = 11,
ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED = 13, ERROR_KEEPASS_INCORRECT_ACTION = 12,
ERROR_KEEPASS_NO_URL_PROVIDED = 14, ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED = 13,
ERROR_KEEPASS_NO_LOGINS_FOUND = 15 ERROR_KEEPASS_NO_URL_PROVIDED = 14,
ERROR_KEEPASS_NO_LOGINS_FOUND = 15
}; };
public: public:
@ -54,8 +55,8 @@ public:
QJsonObject readResponse(const QJsonObject& json); QJsonObject readResponse(const QJsonObject& json);
public slots: public slots:
void removeSharedEncryptionKeys(); void removeSharedEncryptionKeys();
void removeStoredPermissions(); void removeStoredPermissions();
private: private:
QJsonObject handleAction(const QJsonObject& json); QJsonObject handleAction(const QJsonObject& json);
@ -71,28 +72,28 @@ private:
QJsonObject buildMessage(const QString& nonce) const; QJsonObject buildMessage(const QString& nonce) const;
QJsonObject buildResponse(const QString& action, const QJsonObject& message, const QString& nonce); QJsonObject buildResponse(const QString& action, const QJsonObject& message, const QString& nonce);
QJsonObject getErrorReply(const QString& action, const int errorCode) const; QJsonObject getErrorReply(const QString& action, const int errorCode) const;
QString getErrorMessage(const int errorCode) const; QString getErrorMessage(const int errorCode) const;
QString getDatabaseHash(); 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()); QJsonObject decryptMessage(const QString& message, const QString& nonce, const QString& action = QString());
QString encrypt(const QString plaintext, const QString nonce); QString encrypt(const QString plaintext, const QString nonce);
QByteArray decrypt(const QString encrypted, const QString nonce); QByteArray decrypt(const QString encrypted, const QString nonce);
QString getBase64FromKey(const uchar* array, const uint len); QString getBase64FromKey(const uchar* array, const uint len);
QByteArray getQByteArray(const uchar* array, const uint len) const; QByteArray getQByteArray(const uchar* array, const uint len) const;
QJsonObject getJsonObject(const uchar* pArray, const uint len) const; QJsonObject getJsonObject(const uchar* pArray, const uint len) const;
QJsonObject getJsonObject(const QByteArray ba) const; QJsonObject getJsonObject(const QByteArray ba) const;
QByteArray base64Decode(const QString str); QByteArray base64Decode(const QString str);
QString incrementNonce(const QString& nonce); QString incrementNonce(const QString& nonce);
private: private:
QMutex m_mutex; QMutex m_mutex;
BrowserService& m_browserService; BrowserService& m_browserService;
QString m_clientPublicKey; QString m_clientPublicKey;
QString m_publicKey; QString m_publicKey;
QString m_secretKey; QString m_secretKey;
bool m_associated; bool m_associated;
}; };
#endif // BROWSERACTION_H #endif // BROWSERACTION_H

12
src/browser/BrowserClients.cpp Executable file → Normal file
View file

@ -16,13 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <QJsonValue>
#include <QJsonParseError>
#include "BrowserClients.h" #include "BrowserClients.h"
#include <QJsonParseError>
#include <QJsonValue>
BrowserClients::BrowserClients(BrowserService& browserService) : BrowserClients::BrowserClients(BrowserService& browserService)
m_mutex(QMutex::Recursive), : m_mutex(QMutex::Recursive)
m_browserService(browserService) , m_browserService(browserService)
{ {
m_clients.reserve(1000); m_clients.reserve(1000);
} }
@ -63,7 +63,7 @@ QString BrowserClients::getClientID(const QJsonObject& json) const
BrowserClients::ClientPtr BrowserClients::getClient(const QString& clientID) BrowserClients::ClientPtr BrowserClients::getClient(const QString& clientID)
{ {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
for (const auto &i : m_clients) { for (const auto& i : m_clients) {
if (i->clientID.compare(clientID, Qt::CaseSensitive) == 0) { if (i->clientID.compare(clientID, Qt::CaseSensitive) == 0) {
return i; return i;
} }

35
src/browser/BrowserClients.h Executable file → Normal file
View file

@ -19,22 +19,27 @@
#ifndef BROWSERCLIENTS_H #ifndef BROWSERCLIENTS_H
#define BROWSERCLIENTS_H #define BROWSERCLIENTS_H
#include <QJsonObject>
#include <QMutex>
#include <QVector>
#include <QSharedPointer>
#include <QLocalSocket>
#include "BrowserAction.h" #include "BrowserAction.h"
#include <QJsonObject>
#include <QLocalSocket>
#include <QMutex>
#include <QSharedPointer>
#include <QVector>
class BrowserClients class BrowserClients
{ {
struct Client { struct Client
Client(const QString& id, QSharedPointer<BrowserAction> ba) : clientID(id), browserAction(ba) {} {
QString clientID; Client(const QString& id, QSharedPointer<BrowserAction> ba)
QSharedPointer<BrowserAction> browserAction; : clientID(id)
, browserAction(ba)
{
}
QString clientID;
QSharedPointer<BrowserAction> browserAction;
}; };
typedef QSharedPointer<Client> ClientPtr; typedef QSharedPointer<Client> ClientPtr;
public: public:
BrowserClients(BrowserService& browserService); BrowserClients(BrowserService& browserService);
@ -44,13 +49,13 @@ public:
private: private:
QJsonObject byteArrayToJson(const QByteArray& arr) const; QJsonObject byteArrayToJson(const QByteArray& arr) const;
QString getClientID(const QJsonObject& json) const; QString getClientID(const QJsonObject& json) const;
ClientPtr getClient(const QString& clientID); ClientPtr getClient(const QString& clientID);
private: private:
QMutex m_mutex; QMutex m_mutex;
QVector<ClientPtr> m_clients; QVector<ClientPtr> m_clients;
BrowserService& m_browserService; BrowserService& m_browserService;
}; };
#endif // BROWSERCLIENTS_H #endif // BROWSERCLIENTS_H

View file

@ -17,15 +17,14 @@
*/ */
#include "BrowserEntryConfig.h" #include "BrowserEntryConfig.h"
#include <QtCore>
#include "core/Entry.h" #include "core/Entry.h"
#include "core/EntryAttributes.h" #include "core/EntryAttributes.h"
#include <QtCore>
static const char KEEPASSBROWSER_NAME[] = "KeePassXC-Browser Settings"; static const char KEEPASSBROWSER_NAME[] = "KeePassXC-Browser Settings";
BrowserEntryConfig::BrowserEntryConfig(QObject* parent)
BrowserEntryConfig::BrowserEntryConfig(QObject* parent) : : QObject(parent)
QObject(parent)
{ {
} }

View file

@ -19,11 +19,11 @@
#ifndef BROWSERENTRYCONFIG_H #ifndef BROWSERENTRYCONFIG_H
#define BROWSERENTRYCONFIG_H #define BROWSERENTRYCONFIG_H
#include "Variant.h"
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QSet>
#include <QtCore/QString> #include <QtCore/QString>
#include <QtCore/QStringList> #include <QtCore/QStringList>
#include <QtCore/QSet>
#include "Variant.h"
class Entry; class Entry;
@ -31,8 +31,8 @@ class BrowserEntryConfig : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QStringList Allow READ allowedHosts WRITE setAllowedHosts) Q_PROPERTY(QStringList Allow READ allowedHosts WRITE setAllowedHosts)
Q_PROPERTY(QStringList Deny READ deniedHosts WRITE setDeniedHosts ) Q_PROPERTY(QStringList Deny READ deniedHosts WRITE setDeniedHosts)
Q_PROPERTY(QString Realm READ realm WRITE setRealm ) Q_PROPERTY(QString Realm READ realm WRITE setRealm)
public: public:
BrowserEntryConfig(QObject* object = 0); BrowserEntryConfig(QObject* object = 0);
@ -54,7 +54,7 @@ private:
QSet<QString> m_allowedHosts; QSet<QString> m_allowedHosts;
QSet<QString> m_deniedHosts; QSet<QString> m_deniedHosts;
QString m_realm; QString m_realm;
}; };
#endif // BROWSERENTRYCONFIG_H #endif // BROWSERENTRYCONFIG_H

21
src/browser/BrowserOptionDialog.cpp Executable file → Normal file
View file

@ -18,23 +18,24 @@
*/ */
#include "BrowserOptionDialog.h" #include "BrowserOptionDialog.h"
#include "ui_BrowserOptionDialog.h"
#include "config-keepassx.h"
#include "BrowserSettings.h" #include "BrowserSettings.h"
#include "config-keepassx.h"
#include "core/FilePath.h" #include "core/FilePath.h"
#include "ui_BrowserOptionDialog.h"
#include <QMessageBox>
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox>
BrowserOptionDialog::BrowserOptionDialog(QWidget* parent) : BrowserOptionDialog::BrowserOptionDialog(QWidget* parent)
QWidget(parent), : QWidget(parent)
m_ui(new Ui::BrowserOptionDialog()) , m_ui(new Ui::BrowserOptionDialog())
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
connect(m_ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SIGNAL(removeSharedEncryptionKeys())); connect(m_ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SIGNAL(removeSharedEncryptionKeys()));
connect(m_ui->removeStoredPermissions, SIGNAL(clicked()), this, SIGNAL(removeStoredPermissions())); 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->setCloseButtonVisible(false);
m_ui->warningWidget->setAutoHideTimeout(-1); m_ui->warningWidget->setAutoHideTimeout(-1);
@ -95,7 +96,8 @@ void BrowserOptionDialog::loadSettings()
m_ui->enableBrowserSupport->setChecked(false); m_ui->enableBrowserSupport->setChecked(false);
m_ui->enableBrowserSupport->setEnabled(false); m_ui->enableBrowserSupport->setEnabled(false);
m_ui->browserGlobalWarningWidget->showMessage( 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->setCloseButtonVisible(false);
m_ui->browserGlobalWarningWidget->setAutoHideTimeout(-1); m_ui->browserGlobalWarningWidget->setAutoHideTimeout(-1);
#endif #endif
@ -134,7 +136,8 @@ void BrowserOptionDialog::showProxyLocationFileDialog()
#else #else
QString fileTypeFilter(QString("%1 (*)").arg(tr("Executable Files"))); QString fileTypeFilter(QString("%1 (*)").arg(tr("Executable Files")));
#endif #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(), QFileInfo(QCoreApplication::applicationDirPath()).filePath(),
fileTypeFilter); fileTypeFilter);
m_ui->customProxyLocation->setText(proxyLocation); m_ui->customProxyLocation->setText(proxyLocation);

7
src/browser/BrowserOptionDialog.h Executable file → Normal file
View file

@ -20,11 +20,12 @@
#ifndef BROWSEROPTIONDIALOG_H #ifndef BROWSEROPTIONDIALOG_H
#define BROWSEROPTIONDIALOG_H #define BROWSEROPTIONDIALOG_H
#include <QWidget>
#include <QScopedPointer> #include <QScopedPointer>
#include <QWidget>
namespace Ui { namespace Ui
class BrowserOptionDialog; {
class BrowserOptionDialog;
} }
class BrowserOptionDialog : public QWidget class BrowserOptionDialog : public QWidget

View file

@ -17,41 +17,43 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <QJsonArray>
#include <QInputDialog>
#include <QProgressDialog>
#include <QMessageBox>
#include "BrowserService.h" #include "BrowserService.h"
#include "BrowserSettings.h"
#include "BrowserEntryConfig.h"
#include "BrowserAccessControlDialog.h" #include "BrowserAccessControlDialog.h"
#include "BrowserEntryConfig.h"
#include "BrowserSettings.h"
#include "core/Database.h" #include "core/Database.h"
#include "core/Group.h"
#include "core/EntrySearcher.h" #include "core/EntrySearcher.h"
#include "core/Group.h"
#include "core/Metadata.h" #include "core/Metadata.h"
#include "core/Uuid.h"
#include "core/PasswordGenerator.h" #include "core/PasswordGenerator.h"
#include "core/Uuid.h"
#include "gui/MainWindow.h" #include "gui/MainWindow.h"
#include <QInputDialog>
#include <QJsonArray>
#include <QMessageBox>
#include <QProgressDialog>
// de887cc3-0363-43b8-974b-5911b8816224 // de887cc3-0363-43b8-974b-5911b8816224
static const unsigned char KEEPASSXCBROWSER_UUID_DATA[] = { static const unsigned char KEEPASSXCBROWSER_UUID_DATA[] =
0xde, 0x88, 0x7c, 0xc3, 0x03, 0x63, 0x43, 0xb8, {0xde, 0x88, 0x7c, 0xc3, 0x03, 0x63, 0x43, 0xb8, 0x97, 0x4b, 0x59, 0x11, 0xb8, 0x81, 0x62, 0x24};
0x97, 0x4b, 0x59, 0x11, 0xb8, 0x81, 0x62, 0x24 static const Uuid KEEPASSXCBROWSER_UUID =
}; Uuid(QByteArray::fromRawData(reinterpret_cast<const char*>(KEEPASSXCBROWSER_UUID_DATA),
static const Uuid KEEPASSXCBROWSER_UUID = Uuid(QByteArray::fromRawData(reinterpret_cast<const char *>(KEEPASSXCBROWSER_UUID_DATA), sizeof(KEEPASSXCBROWSER_UUID_DATA))); sizeof(KEEPASSXCBROWSER_UUID_DATA)));
static const char KEEPASSXCBROWSER_NAME[] = "KeePassXC-Browser Settings"; static const char KEEPASSXCBROWSER_NAME[] = "KeePassXC-Browser Settings";
static const char ASSOCIATE_KEY_PREFIX[] = "Public Key: "; static const char ASSOCIATE_KEY_PREFIX[] = "Public Key: ";
static const char KEEPASSXCBROWSER_GROUP_NAME[] = "KeePassXC-Browser Passwords"; 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) : BrowserService::BrowserService(DatabaseTabWidget* parent)
m_dbTabWidget(parent), : m_dbTabWidget(parent)
m_dialogActive(false) , m_dialogActive(false)
{ {
connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), this, SLOT(databaseLocked(DatabaseWidget*))); connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), this, SLOT(databaseLocked(DatabaseWidget*)));
connect(m_dbTabWidget, SIGNAL(databaseUnlocked(DatabaseWidget*)), this, SLOT(databaseUnlocked(DatabaseWidget*))); connect(m_dbTabWidget, SIGNAL(databaseUnlocked(DatabaseWidget*)), this, SLOT(databaseUnlocked(DatabaseWidget*)));
connect(m_dbTabWidget, SIGNAL(activateDatabaseChanged(DatabaseWidget*)), this, SLOT(activateDatabaseChanged(DatabaseWidget*))); connect(m_dbTabWidget,
SIGNAL(activateDatabaseChanged(DatabaseWidget*)),
this,
SLOT(activateDatabaseChanged(DatabaseWidget*)));
} }
bool BrowserService::isDatabaseOpened() const bool BrowserService::isDatabaseOpened() const
@ -62,7 +64,6 @@ bool BrowserService::isDatabaseOpened() const
} }
return dbWidget->currentMode() == DatabaseWidget::ViewMode || dbWidget->currentMode() == DatabaseWidget::EditMode; return dbWidget->currentMode() == DatabaseWidget::ViewMode || dbWidget->currentMode() == DatabaseWidget::EditMode;
} }
bool BrowserService::openDatabase(bool triggerUnlock) bool BrowserService::openDatabase(bool triggerUnlock)
@ -167,9 +168,8 @@ QString BrowserService::storeKey(const QString& key)
QString id; QString id;
if (thread() != QThread::currentThread()) { if (thread() != QThread::currentThread()) {
QMetaObject::invokeMethod(this, "storeKey", Qt::BlockingQueuedConnection, QMetaObject::invokeMethod(
Q_RETURN_ARG(QString, id), this, "storeKey", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, id), Q_ARG(const QString&, key));
Q_ARG(const QString&, key));
return id; return id;
} }
@ -185,8 +185,8 @@ QString BrowserService::storeKey(const QString& key)
QInputDialog keyDialog; QInputDialog keyDialog;
keyDialog.setWindowTitle(tr("KeePassXC: New key association request")); keyDialog.setWindowTitle(tr("KeePassXC: New key association request"));
keyDialog.setLabelText(tr("You have received an association request for the above key.\n\n" 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" "If you would like to allow it access to your KeePassXC database,\n"
"give it a unique name to identify and accept it.")); "give it a unique name to identify and accept it."));
keyDialog.setOkButtonText(tr("Save and allow access")); keyDialog.setOkButtonText(tr("Save and allow access"));
keyDialog.setWindowFlags(keyDialog.windowFlags() | Qt::WindowStaysOnTopHint); keyDialog.setWindowFlags(keyDialog.windowFlags() | Qt::WindowStaysOnTopHint);
keyDialog.show(); keyDialog.show();
@ -202,7 +202,8 @@ QString BrowserService::storeKey(const QString& key)
contains = config->attributes()->contains(QLatin1String(ASSOCIATE_KEY_PREFIX) + id); contains = config->attributes()->contains(QLatin1String(ASSOCIATE_KEY_PREFIX) + id);
if (contains) { 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\" " tr("A shared encryption key with the name \"%1\" "
"already exists.\nDo you want to overwrite it?") "already exists.\nDo you want to overwrite it?")
.arg(id), .arg(id),
@ -224,11 +225,16 @@ QString BrowserService::getKey(const QString& id)
return config->attributes()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + 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; QJsonArray result;
if (thread() != QThread::currentThread()) { if (thread() != QThread::currentThread()) {
QMetaObject::invokeMethod(this, "findMatchingEntries", Qt::BlockingQueuedConnection, QMetaObject::invokeMethod(this,
"findMatchingEntries",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QJsonArray, result), Q_RETURN_ARG(QJsonArray, result),
Q_ARG(const QString&, id), Q_ARG(const QString&, id),
Q_ARG(const QString&, url), Q_ARG(const QString&, url),
@ -283,7 +289,12 @@ QJsonArray BrowserService::findMatchingEntries(const QString& id, const QString&
return result; 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(); Group* group = findCreateAddEntryGroup();
if (!group) { if (!group) {
@ -313,10 +324,16 @@ void BrowserService::addEntry(const QString&, const QString& login, const QStrin
config.save(entry); 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()) { 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&, id),
Q_ARG(const QString&, uuid), Q_ARG(const QString&, uuid),
Q_ARG(const QString&, login), Q_ARG(const QString&, login),
@ -339,13 +356,15 @@ void BrowserService::updateEntry(const QString& id, const QString& uuid, const Q
return; return;
} }
if (username.compare(login, Qt::CaseSensitive) != 0 || entry->password().compare(password, Qt::CaseSensitive) != 0) { if (username.compare(login, Qt::CaseSensitive) != 0
|| entry->password().compare(password, Qt::CaseSensitive) != 0) {
QMessageBox::StandardButton dialogResult = QMessageBox::No; QMessageBox::StandardButton dialogResult = QMessageBox::No;
if (!BrowserSettings::alwaysAllowUpdate()) { if (!BrowserSettings::alwaysAllowUpdate()) {
dialogResult = QMessageBox::warning(0, tr("KeePassXC: Update Entry"), dialogResult = QMessageBox::warning(
tr("Do you want to update the information in %1 - %2?") 0,
.arg(QUrl(url).host()).arg(username), tr("KeePassXC: Update Entry"),
QMessageBox::Yes|QMessageBox::No); 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) { if (BrowserSettings::alwaysAllowUpdate() || dialogResult == QMessageBox::Yes) {
@ -370,11 +389,10 @@ QList<Entry*> BrowserService::searchEntries(Database* db, const QString& hostnam
QString url = entry->url(); QString url = entry->url();
// Filter to match hostname in Title and Url fields // Filter to match hostname in Title and Url fields
if ((!title.isEmpty() && hostname.contains(title)) if ((!title.isEmpty() && hostname.contains(title)) || (!url.isEmpty() && hostname.contains(url))
|| (!url.isEmpty() && hostname.contains(url))
|| (matchUrlScheme(title) && hostname.endsWith(QUrl(title).host())) || (matchUrlScheme(title) && hostname.endsWith(QUrl(title).host()))
|| (matchUrlScheme(url) && hostname.endsWith(QUrl(url).host())) ) { || (matchUrlScheme(url) && hostname.endsWith(QUrl(url).host()))) {
entries.append(entry); entries.append(entry);
} }
} }
@ -413,7 +431,8 @@ QList<Entry*> BrowserService::searchEntries(const QString& text)
void BrowserService::removeSharedEncryptionKeys() void BrowserService::removeSharedEncryptionKeys()
{ {
if (!isDatabaseOpened()) { if (!isDatabaseOpened()) {
QMessageBox::critical(0, tr("KeePassXC: Database locked!"), QMessageBox::critical(0,
tr("KeePassXC: Database locked!"),
tr("The active database is locked!\n" tr("The active database is locked!\n"
"Please unlock the selected database or choose another one which is unlocked."), "Please unlock the selected database or choose another one which is unlocked."),
QMessageBox::Ok); QMessageBox::Ok);
@ -422,7 +441,8 @@ void BrowserService::removeSharedEncryptionKeys()
Entry* entry = getConfigEntry(); Entry* entry = getConfigEntry();
if (!entry) { 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."), tr("The active database does not contain a settings entry."),
QMessageBox::Ok); QMessageBox::Ok);
return; return;
@ -436,7 +456,8 @@ void BrowserService::removeSharedEncryptionKeys()
} }
if (keysToRemove.isEmpty()) { 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."), tr("No shared encryption keys found in KeePassXC settings."),
QMessageBox::Ok); QMessageBox::Ok);
return; return;
@ -449,16 +470,17 @@ void BrowserService::removeSharedEncryptionKeys()
entry->endUpdate(); entry->endUpdate();
const int count = keysToRemove.count(); 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), tr("Successfully removed %n encryption key(s) from KeePassXC settings.", "", count),
QMessageBox::Ok); QMessageBox::Ok);
} }
void BrowserService::removeStoredPermissions() void BrowserService::removeStoredPermissions()
{ {
if (!isDatabaseOpened()) { if (!isDatabaseOpened()) {
QMessageBox::critical(0, tr("KeePassXC: Database locked!"), QMessageBox::critical(0,
tr("KeePassXC: Database locked!"),
tr("The active database is locked!\n" tr("The active database is locked!\n"
"Please unlock the selected database or choose another one which is unlocked."), "Please unlock the selected database or choose another one which is unlocked."),
QMessageBox::Ok); QMessageBox::Ok);
@ -492,11 +514,13 @@ void BrowserService::removeStoredPermissions()
progress.reset(); progress.reset();
if (counter > 0) { 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), tr("Successfully removed permissions from %n entry(s).", "", counter),
QMessageBox::Ok); QMessageBox::Ok);
} else { } 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."), tr("The active database does not contain an entry with permissions."),
QMessageBox::Ok); QMessageBox::Ok);
} }
@ -510,7 +534,8 @@ QList<Entry*> BrowserService::sortEntries(QList<Entry*>& pwEntries, const QStrin
} }
const QString submitUrl = url.toString(QUrl::StripTrailingSlash); 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; QMultiMap<int, const Entry*> priorities;
for (const Entry* entry : pwEntries) { for (const Entry* entry : pwEntries) {
@ -529,7 +554,11 @@ QList<Entry*> BrowserService::sortEntries(QList<Entry*>& pwEntries, const QStrin
return pwEntries; 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) { if (pwEntriesToConfirm.isEmpty() || m_dialogActive) {
return false; return false;
@ -593,7 +622,8 @@ QJsonObject BrowserService::prepareEntry(const Entry* entry)
return res; 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; BrowserEntryConfig config;
if (!config.load(entry)) { if (!config.load(entry)) {
@ -623,7 +653,8 @@ Group* BrowserService::findCreateAddEntryGroup()
return nullptr; 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)) { for (const Group* g : rootGroup->groupsRecursive(true)) {
if (g->name() == groupName) { if (g->name() == groupName) {
@ -639,14 +670,18 @@ Group* BrowserService::findCreateAddEntryGroup()
return group; 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()); QUrl url(entry->url());
if (url.scheme().isEmpty()) { if (url.scheme().isEmpty()) {
url.setScheme("http"); url.setScheme("http");
} }
const QString entryURL = url.toString(QUrl::StripTrailingSlash); 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) { if (submitUrl == entryURL) {
return 100; return 100;

View file

@ -20,63 +20,86 @@
#ifndef BROWSERSERVICE_H #ifndef BROWSERSERVICE_H
#define BROWSERSERVICE_H #define BROWSERSERVICE_H
#include <QtCore>
#include <QObject>
#include "gui/DatabaseTabWidget.h"
#include "core/Entry.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 class BrowserService : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit BrowserService(DatabaseTabWidget* parent); explicit BrowserService(DatabaseTabWidget* parent);
bool isDatabaseOpened() const; bool isDatabaseOpened() const;
bool openDatabase(bool triggerUnlock); bool openDatabase(bool triggerUnlock);
QString getDatabaseRootUuid(); QString getDatabaseRootUuid();
QString getDatabaseRecycleBinUuid(); QString getDatabaseRecycleBinUuid();
Entry* getConfigEntry(bool create = false); Entry* getConfigEntry(bool create = false);
QString getKey(const QString& id); 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); void addEntry(const QString& id,
QList<Entry*> searchEntries(Database* db, const QString& hostname); const QString& login,
QList<Entry*> searchEntries(const QString& text); const QString& password,
void removeSharedEncryptionKeys(); const QString& url,
void removeStoredPermissions(); 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: public slots:
QJsonArray findMatchingEntries(const QString& id, const QString& url, const QString& submitUrl, const QString& realm); QJsonArray
QString storeKey(const QString& key); findMatchingEntries(const QString& id, const QString& url, const QString& submitUrl, const QString& realm);
void updateEntry(const QString& id, const QString& uuid, const QString& login, const QString& password, const QString& url); QString storeKey(const QString& key);
void databaseLocked(DatabaseWidget* dbWidget); void updateEntry(const QString& id,
void databaseUnlocked(DatabaseWidget* dbWidget); const QString& uuid,
void activateDatabaseChanged(DatabaseWidget* dbWidget); const QString& login,
void lockDatabase(); const QString& password,
const QString& url);
void databaseLocked(DatabaseWidget* dbWidget);
void databaseUnlocked(DatabaseWidget* dbWidget);
void activateDatabaseChanged(DatabaseWidget* dbWidget);
void lockDatabase();
signals: signals:
void databaseLocked(); void databaseLocked();
void databaseUnlocked(); void databaseUnlocked();
void databaseChanged(); void databaseChanged();
private: private:
enum Access { Denied, Unknown, Allowed}; enum Access
{
Denied,
Unknown,
Allowed
};
private: private:
QList<Entry*> sortEntries(QList<Entry*>& pwEntries, const QString& host, const QString& submitUrl); 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); bool confirmEntries(QList<Entry*>& pwEntriesToConfirm,
QJsonObject prepareEntry(const Entry* entry); const QString& url,
Access checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm); const QString& host,
Group* findCreateAddEntryGroup(); const QString& submitHost,
int sortPriority(const Entry* entry, const QString &host, const QString& submitUrl, const QString& baseSubmitUrl) const; const QString& realm);
bool matchUrlScheme(const QString& url); QJsonObject prepareEntry(const Entry* entry);
bool removeFirstDomain(QString& hostname); Access checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm);
Database* getDatabase(); 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: private:
DatabaseTabWidget* const m_dbTabWidget; DatabaseTabWidget* const m_dbTabWidget;
bool m_dialogActive; bool m_dialogActive;
}; };
#endif // BROWSERSERVICE_H #endif // BROWSERSERVICE_H

36
src/browser/BrowserSettings.cpp Executable file → Normal file
View file

@ -177,36 +177,48 @@ void BrowserSettings::setUpdateBinaryPath(bool enabled)
config()->set("Browser/UpdateBinaryPath", enabled); config()->set("Browser/UpdateBinaryPath", enabled);
} }
bool BrowserSettings::chromeSupport() { bool BrowserSettings::chromeSupport()
{
return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::CHROME); return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::CHROME);
} }
void BrowserSettings::setChromeSupport(bool enabled) { void BrowserSettings::setChromeSupport(bool enabled)
m_hostInstaller.installBrowser(HostInstaller::SupportedBrowsers::CHROME, enabled, supportBrowserProxy(), customProxyLocation()); {
m_hostInstaller.installBrowser(
HostInstaller::SupportedBrowsers::CHROME, enabled, supportBrowserProxy(), customProxyLocation());
} }
bool BrowserSettings::chromiumSupport() { bool BrowserSettings::chromiumSupport()
{
return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::CHROMIUM); return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::CHROMIUM);
} }
void BrowserSettings::setChromiumSupport(bool enabled) { void BrowserSettings::setChromiumSupport(bool enabled)
m_hostInstaller.installBrowser(HostInstaller::SupportedBrowsers::CHROMIUM, enabled, supportBrowserProxy(), customProxyLocation()); {
m_hostInstaller.installBrowser(
HostInstaller::SupportedBrowsers::CHROMIUM, enabled, supportBrowserProxy(), customProxyLocation());
} }
bool BrowserSettings::firefoxSupport() { bool BrowserSettings::firefoxSupport()
{
return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::FIREFOX); return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::FIREFOX);
} }
void BrowserSettings::setFirefoxSupport(bool enabled) { void BrowserSettings::setFirefoxSupport(bool enabled)
m_hostInstaller.installBrowser(HostInstaller::SupportedBrowsers::FIREFOX, enabled, supportBrowserProxy(), customProxyLocation()); {
m_hostInstaller.installBrowser(
HostInstaller::SupportedBrowsers::FIREFOX, enabled, supportBrowserProxy(), customProxyLocation());
} }
bool BrowserSettings::vivaldiSupport() { bool BrowserSettings::vivaldiSupport()
{
return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::VIVALDI); return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::VIVALDI);
} }
void BrowserSettings::setVivaldiSupport(bool enabled) { void BrowserSettings::setVivaldiSupport(bool enabled)
m_hostInstaller.installBrowser(HostInstaller::SupportedBrowsers::VIVALDI, enabled, supportBrowserProxy(), customProxyLocation()); {
m_hostInstaller.installBrowser(
HostInstaller::SupportedBrowsers::VIVALDI, enabled, supportBrowserProxy(), customProxyLocation());
} }
bool BrowserSettings::passwordUseNumbers() bool BrowserSettings::passwordUseNumbers()

12
src/browser/BrowserSettings.h Executable file → Normal file
View file

@ -20,9 +20,9 @@
#ifndef BROWSERSETTINGS_H #ifndef BROWSERSETTINGS_H
#define BROWSERSETTINGS_H #define BROWSERSETTINGS_H
#include "core/PasswordGenerator.h"
#include "core/PassphraseGenerator.h"
#include "HostInstaller.h" #include "HostInstaller.h"
#include "core/PassphraseGenerator.h"
#include "core/PasswordGenerator.h"
class BrowserSettings class BrowserSettings
{ {
@ -30,9 +30,9 @@ public:
static bool isEnabled(); static bool isEnabled();
static void setEnabled(bool enabled); static void setEnabled(bool enabled);
static bool showNotification(); //TODO!! static bool showNotification(); // TODO!!
static void setShowNotification(bool showNotification); static void setShowNotification(bool showNotification);
static bool bestMatchOnly(); //TODO!! static bool bestMatchOnly(); // TODO!!
static void setBestMatchOnly(bool bestMatchOnly); static void setBestMatchOnly(bool bestMatchOnly);
static bool unlockDatabase(); static bool unlockDatabase();
static void setUnlockDatabase(bool unlockDatabase); static void setUnlockDatabase(bool unlockDatabase);
@ -46,7 +46,7 @@ public:
static void setAlwaysAllowAccess(bool alwaysAllowAccess); static void setAlwaysAllowAccess(bool alwaysAllowAccess);
static bool alwaysAllowUpdate(); static bool alwaysAllowUpdate();
static void setAlwaysAllowUpdate(bool alwaysAllowUpdate); static void setAlwaysAllowUpdate(bool alwaysAllowUpdate);
static bool searchInAllDatabases();//TODO!! static bool searchInAllDatabases(); // TODO!!
static void setSearchInAllDatabases(bool searchInAllDatabases); static void setSearchInAllDatabases(bool searchInAllDatabases);
static bool supportKphFields(); static bool supportKphFields();
static void setSupportKphFields(bool supportKphFields); static void setSupportKphFields(bool supportKphFields);
@ -88,7 +88,7 @@ public:
static void setPasswordEveryGroup(bool everyGroup); static void setPasswordEveryGroup(bool everyGroup);
static bool passwordExcludeAlike(); static bool passwordExcludeAlike();
static void setPasswordExcludeAlike(bool excludeAlike); static void setPasswordExcludeAlike(bool excludeAlike);
static int passwordLength(); static int passwordLength();
static void setPasswordLength(int length); static void setPasswordLength(int length);
static PasswordGenerator::CharClasses passwordCharClasses(); static PasswordGenerator::CharClasses passwordCharClasses();
static PasswordGenerator::GeneratorFlags passwordGeneratorFlags(); static PasswordGenerator::GeneratorFlags passwordGeneratorFlags();

View file

@ -18,43 +18,45 @@
#include "HostInstaller.h" #include "HostInstaller.h"
#include "config-keepassx.h" #include "config-keepassx.h"
#include <QCoreApplication>
#include <QDir> #include <QDir>
#include <QFile> #include <QFile>
#include <QStandardPaths>
#include <QJsonArray> #include <QJsonArray>
#include <QJsonDocument> #include <QJsonDocument>
#include <QCoreApplication>
#include <QProcessEnvironment>
#include <QMessageBox> #include <QMessageBox>
#include <QProcessEnvironment>
#include <QStandardPaths>
const QString HostInstaller::HOST_NAME = "org.keepassxc.keepassxc_browser"; const QString HostInstaller::HOST_NAME = "org.keepassxc.keepassxc_browser";
const QStringList HostInstaller::ALLOWED_ORIGINS = QStringList() const QStringList HostInstaller::ALLOWED_ORIGINS = QStringList()
<< "chrome-extension://iopaggbpplllidnfmcghoonnokmjoicf/" << "chrome-extension://iopaggbpplllidnfmcghoonnokmjoicf/"
<< "chrome-extension://oboonakemofpalcgghocfoadofidjkkk/"; << "chrome-extension://oboonakemofpalcgghocfoadofidjkkk/";
const QStringList HostInstaller::ALLOWED_EXTENSIONS = QStringList() const QStringList HostInstaller::ALLOWED_EXTENSIONS = QStringList() << "keepassxc-browser@keepassxc.org";
<< "keepassxc-browser@keepassxc.org";
#if defined(Q_OS_OSX) #if defined(Q_OS_OSX)
const QString HostInstaller::TARGET_DIR_CHROME = "/Library/Application Support/Google/Chrome/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_CHROMIUM = "/Library/Application Support/Chromium/NativeMessagingHosts";
const QString HostInstaller::TARGET_DIR_FIREFOX = "/Library/Application Support/Mozilla/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_VIVALDI = "/Library/Application Support/Vivaldi/NativeMessagingHosts";
#elif defined(Q_OS_LINUX) #elif defined(Q_OS_LINUX)
const QString HostInstaller::TARGET_DIR_CHROME = "/.config/google-chrome/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_CHROMIUM = "/.config/chromium/NativeMessagingHosts";
const QString HostInstaller::TARGET_DIR_FIREFOX = "/.mozilla/native-messaging-hosts"; const QString HostInstaller::TARGET_DIR_FIREFOX = "/.mozilla/native-messaging-hosts";
const QString HostInstaller::TARGET_DIR_VIVALDI = "/.config/vivaldi/NativeMessagingHosts"; const QString HostInstaller::TARGET_DIR_VIVALDI = "/.config/vivaldi/NativeMessagingHosts";
#elif defined(Q_OS_WIN) #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_CHROME =
const QString HostInstaller::TARGET_DIR_CHROMIUM = "HKEY_CURRENT_USER\\Software\\Chromium\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME; "HKEY_CURRENT_USER\\Software\\Google\\Chrome\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME;
const QString HostInstaller::TARGET_DIR_FIREFOX = "HKEY_CURRENT_USER\\Software\\Mozilla\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME; const QString HostInstaller::TARGET_DIR_CHROMIUM =
const QString HostInstaller::TARGET_DIR_VIVALDI = "HKEY_CURRENT_USER\\Software\\Vivaldi\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME; "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 #endif
HostInstaller::HostInstaller() HostInstaller::HostInstaller()
{ {
} }
bool HostInstaller::checkIfInstalled(SupportedBrowsers browser) bool HostInstaller::checkIfInstalled(SupportedBrowsers browser)
@ -68,34 +70,39 @@ bool HostInstaller::checkIfInstalled(SupportedBrowsers browser)
#endif #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) { if (enabled) {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
// Create a registry key // Create a registry key
QSettings settings(getTargetPath(browser), QSettings::NativeFormat); QSettings settings(getTargetPath(browser), QSettings::NativeFormat);
if (!registryEntryFound(settings)) { if (!registryEntryFound(settings)) {
settings.setValue("Default", getPath(browser)); settings.setValue("Default", getPath(browser));
} }
#endif #endif
// Always create the script file // Always create the script file
QJsonObject script = constructFile(browser, proxy, location); QJsonObject script = constructFile(browser, proxy, location);
if (!saveFile(browser, script)) { if (!saveFile(browser, script)) {
QMessageBox::critical(0, tr("KeePassXC: Cannot save file!"), QMessageBox::critical(0,
tr("Cannot save the native messaging script file."), QMessageBox::Ok); tr("KeePassXC: Cannot save file!"),
} tr("Cannot save the native messaging script file."),
} else { QMessageBox::Ok);
// Remove the script file }
QString fileName = getPath(browser); } else {
QFile::remove(fileName); // Remove the script file
#ifdef Q_OS_WIN QString fileName = getPath(browser);
// Remove the registry entry QFile::remove(fileName);
QSettings settings(getTargetPath(browser), QSettings::NativeFormat); #ifdef Q_OS_WIN
if (registryEntryFound(settings)) { // Remove the registry entry
settings.remove("Default"); QSettings settings(getTargetPath(browser), QSettings::NativeFormat);
} if (registryEntryFound(settings)) {
#endif settings.remove("Default");
} }
#endif
}
} }
void HostInstaller::updateBinaryPaths(const bool& proxy, const QString& location) 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 QString HostInstaller::getTargetPath(SupportedBrowsers browser) const
{ {
switch (browser) { switch (browser) {
case SupportedBrowsers::CHROME: return HostInstaller::TARGET_DIR_CHROME; case SupportedBrowsers::CHROME:
case SupportedBrowsers::CHROMIUM: return HostInstaller::TARGET_DIR_CHROMIUM; return HostInstaller::TARGET_DIR_CHROME;
case SupportedBrowsers::FIREFOX: return HostInstaller::TARGET_DIR_FIREFOX; case SupportedBrowsers::CHROMIUM:
case SupportedBrowsers::VIVALDI: return HostInstaller::TARGET_DIR_VIVALDI; return HostInstaller::TARGET_DIR_CHROMIUM;
default: return QString(); 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 QString HostInstaller::getBrowserName(SupportedBrowsers browser) const
{ {
switch (browser) { switch (browser) {
case SupportedBrowsers::CHROME: return "chrome"; case SupportedBrowsers::CHROME:
case SupportedBrowsers::CHROMIUM: return "chromium"; return "chrome";
case SupportedBrowsers::FIREFOX: return "firefox"; case SupportedBrowsers::CHROMIUM:
case SupportedBrowsers::VIVALDI: return "vivaldi"; return "chromium";
default: return QString(); 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)); QString winPath = QString("%1/%2_%3.json").arg(userPath, HostInstaller::HOST_NAME, getBrowserName(browser));
winPath.replace("/","\\"); winPath.replace("/", "\\");
return winPath; return winPath;
#else #else
QString path = getTargetPath(browser); QString path = getTargetPath(browser);
@ -184,16 +201,16 @@ QJsonObject HostInstaller::constructFile(SupportedBrowsers browser, const bool&
path = QFileInfo(QCoreApplication::applicationFilePath()).absoluteFilePath(); path = QFileInfo(QCoreApplication::applicationFilePath()).absoluteFilePath();
} }
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
path.replace("/","\\"); path.replace("/", "\\");
#endif #endif
#endif // #ifdef KEEPASSXC_DIST_APPIMAGE #endif // #ifdef KEEPASSXC_DIST_APPIMAGE
QJsonObject script; QJsonObject script;
script["name"] = HostInstaller::HOST_NAME; script["name"] = HostInstaller::HOST_NAME;
script["description"] = "KeePassXC integration with native messaging support"; script["description"] = "KeePassXC integration with native messaging support";
script["path"] = path; script["path"] = path;
script["type"] = "stdio"; script["type"] = "stdio";
QJsonArray arr; QJsonArray arr;
if (browser == SupportedBrowsers::FIREFOX) { if (browser == SupportedBrowsers::FIREFOX) {

View file

@ -19,8 +19,8 @@
#ifndef HOSTINSTALLER_H #ifndef HOSTINSTALLER_H
#define HOSTINSTALLER_H #define HOSTINSTALLER_H
#include <QObject>
#include <QJsonObject> #include <QJsonObject>
#include <QObject>
#include <QSettings> #include <QSettings>
class HostInstaller : public QObject class HostInstaller : public QObject
@ -28,27 +28,31 @@ class HostInstaller : public QObject
Q_OBJECT Q_OBJECT
public: public:
enum SupportedBrowsers : int { enum SupportedBrowsers : int
CHROME = 0, {
CHROMIUM = 1, CHROME = 0,
FIREFOX = 2, CHROMIUM = 1,
VIVALDI = 3 FIREFOX = 2,
VIVALDI = 3
}; };
public: public:
HostInstaller(); HostInstaller();
bool checkIfInstalled(SupportedBrowsers browser); 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 = ""); void updateBinaryPaths(const bool& proxy, const QString& location = "");
private: private:
QString getTargetPath(SupportedBrowsers browser) const; QString getTargetPath(SupportedBrowsers browser) const;
QString getBrowserName(SupportedBrowsers browser) const; QString getBrowserName(SupportedBrowsers browser) const;
QString getPath(SupportedBrowsers browser) const; QString getPath(SupportedBrowsers browser) const;
QString getInstallDir(SupportedBrowsers browser) const; QString getInstallDir(SupportedBrowsers browser) const;
QJsonObject constructFile(SupportedBrowsers browser, const bool& proxy, const QString& location); QJsonObject constructFile(SupportedBrowsers browser, const bool& proxy, const QString& location);
bool registryEntryFound(const QSettings& settings); bool registryEntryFound(const QSettings& settings);
bool saveFile(SupportedBrowsers browser, const QJsonObject& script); bool saveFile(SupportedBrowsers browser, const QJsonObject& script);
private: private:
static const QString HOST_NAME; static const QString HOST_NAME;

View file

@ -20,9 +20,9 @@
#include <QStandardPaths> #include <QStandardPaths>
#if defined(Q_OS_UNIX) && !defined(Q_OS_LINUX) #if defined(Q_OS_UNIX) && !defined(Q_OS_LINUX)
#include <sys/types.h>
#include <sys/event.h> #include <sys/event.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
@ -51,7 +51,7 @@ void NativeMessagingBase::newNativeMessage()
{ {
#if defined(Q_OS_UNIX) && !defined(Q_OS_LINUX) #if defined(Q_OS_UNIX) && !defined(Q_OS_LINUX)
struct kevent ev[1]; struct kevent ev[1];
struct timespec ts = { 5, 0 }; struct timespec ts = {5, 0};
int fd = kqueue(); int fd = kqueue();
if (fd == -1) { if (fd == -1) {
@ -123,7 +123,8 @@ void NativeMessagingBase::sendReply(const QString& reply)
if (!reply.isEmpty()) { if (!reply.isEmpty()) {
QByteArray bytes = reply.toUtf8(); QByteArray bytes = reply.toUtf8();
uint len = bytes.size(); 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; 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 // Use XDG_RUNTIME_DIR instead of /tmp/ if it's available
QString path = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation) + "/kpxc_server"; QString path = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation) + "/kpxc_server";
return path.isEmpty() ? "/tmp/kpxc_server" : path; return path.isEmpty() ? "/tmp/kpxc_server" : path;
#else // Q_OS_MAC and others #else // Q_OS_MAC and others
return "/tmp/kpxc_server"; return "/tmp/kpxc_server";
#endif #endif
} }

View file

@ -19,16 +19,16 @@
#ifndef NATIVEMESSAGINGBASE_H #ifndef NATIVEMESSAGINGBASE_H
#define NATIVEMESSAGINGBASE_H #define NATIVEMESSAGINGBASE_H
#include <QObject> #include <QAtomicInteger>
#include <QJsonObject>
#include <QJsonDocument>
#include <QFuture> #include <QFuture>
#include <QtConcurrent/QtConcurrent> #include <QJsonDocument>
#include <QMutex> #include <QJsonObject>
#include <QSocketNotifier>
#include <QLocalServer> #include <QLocalServer>
#include <QLocalSocket> #include <QLocalSocket>
#include <QAtomicInteger> #include <QMutex>
#include <QObject>
#include <QSocketNotifier>
#include <QtConcurrent/QtConcurrent>
#include <iostream> #include <iostream>
#include <unistd.h> #include <unistd.h>
@ -41,21 +41,21 @@ public:
~NativeMessagingBase() = default; ~NativeMessagingBase() = default;
protected slots: protected slots:
void newNativeMessage(); void newNativeMessage();
protected: protected:
virtual void readLength() = 0; virtual void readLength() = 0;
virtual void readStdIn(const quint32 length) = 0; virtual void readStdIn(const quint32 length) = 0;
void readNativeMessages(); void readNativeMessages();
QString jsonToString(const QJsonObject& json) const; QString jsonToString(const QJsonObject& json) const;
void sendReply(const QJsonObject& json); void sendReply(const QJsonObject& json);
void sendReply(const QString& reply); void sendReply(const QString& reply);
QString getLocalServerPath() const; QString getLocalServerPath() const;
protected: protected:
QAtomicInteger<quint8> m_running; QAtomicInteger<quint8> m_running;
QSharedPointer<QSocketNotifier> m_notifier; 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
View file

@ -16,18 +16,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "NativeMessagingHost.h"
#include "BrowserSettings.h"
#include "sodium.h"
#include <QMutexLocker> #include <QMutexLocker>
#include <QtNetwork> #include <QtNetwork>
#include <iostream> #include <iostream>
#include "sodium.h"
#include "NativeMessagingHost.h"
#include "BrowserSettings.h"
NativeMessagingHost::NativeMessagingHost(DatabaseTabWidget* parent) : NativeMessagingHost::NativeMessagingHost(DatabaseTabWidget* parent)
NativeMessagingBase(), : NativeMessagingBase()
m_mutex(QMutex::Recursive), , m_mutex(QMutex::Recursive)
m_browserClients(m_browserService), , m_browserClients(m_browserService)
m_browserService(parent) , m_browserService(parent)
{ {
m_localServer.reset(new QLocalServer(this)); m_localServer.reset(new QLocalServer(this));
m_localServer->setSocketOptions(QLocalServer::UserAccessOption); m_localServer->setSocketOptions(QLocalServer::UserAccessOption);
@ -61,12 +61,14 @@ void NativeMessagingHost::run()
// Update KeePassXC/keepassxc-proxy binary paths to Native Messaging scripts // Update KeePassXC/keepassxc-proxy binary paths to Native Messaging scripts
if (BrowserSettings::updateBinaryPath()) { if (BrowserSettings::updateBinaryPath()) {
BrowserSettings::updateBinaryPaths(BrowserSettings::useCustomProxy() ? BrowserSettings::customProxyLocation() : ""); BrowserSettings::updateBinaryPaths(BrowserSettings::useCustomProxy() ? BrowserSettings::customProxyLocation()
: "");
} }
m_running.store(true); m_running.store(true);
#ifdef Q_OS_WIN #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 #endif
if (BrowserSettings::supportBrowserProxy()) { if (BrowserSettings::supportBrowserProxy()) {
@ -101,7 +103,7 @@ void NativeMessagingHost::readLength()
if (!std::cin.eof() && length > 0) { if (!std::cin.eof() && length > 0) {
readStdIn(length); readStdIn(length);
} else { } else {
m_notifier->setEnabled(false); m_notifier->setEnabled(false);
} }
} }

42
src/browser/NativeMessagingHost.h Executable file → Normal file
View file

@ -19,9 +19,9 @@
#ifndef NATIVEMESSAGINGHOST_H #ifndef NATIVEMESSAGINGHOST_H
#define NATIVEMESSAGINGHOST_H #define NATIVEMESSAGINGHOST_H
#include "NativeMessagingBase.h"
#include "BrowserClients.h" #include "BrowserClients.h"
#include "BrowserService.h" #include "BrowserService.h"
#include "NativeMessagingBase.h"
#include "gui/DatabaseTabWidget.h" #include "gui/DatabaseTabWidget.h"
class NativeMessagingHost : public NativeMessagingBase class NativeMessagingHost : public NativeMessagingBase
@ -31,37 +31,37 @@ class NativeMessagingHost : public NativeMessagingBase
typedef QList<QLocalSocket*> SocketList; typedef QList<QLocalSocket*> SocketList;
public: public:
explicit NativeMessagingHost(DatabaseTabWidget* parent = 0); explicit NativeMessagingHost(DatabaseTabWidget* parent = 0);
~NativeMessagingHost(); ~NativeMessagingHost();
int init(); int init();
void run(); void run();
void stop(); void stop();
public slots: public slots:
void removeSharedEncryptionKeys(); void removeSharedEncryptionKeys();
void removeStoredPermissions(); void removeStoredPermissions();
signals: signals:
void quit(); void quit();
private: private:
void readLength(); void readLength();
void readStdIn(const quint32 length); void readStdIn(const quint32 length);
void sendReplyToAllClients(const QJsonObject& json); void sendReplyToAllClients(const QJsonObject& json);
private slots: private slots:
void databaseLocked(); void databaseLocked();
void databaseUnlocked(); void databaseUnlocked();
void newLocalConnection(); void newLocalConnection();
void newLocalMessage(); void newLocalMessage();
void disconnectSocket(); void disconnectSocket();
private: private:
QMutex m_mutex; QMutex m_mutex;
BrowserClients m_browserClients; BrowserClients m_browserClients;
BrowserService m_browserService; BrowserService m_browserService;
QSharedPointer<QLocalServer> m_localServer; QSharedPointer<QLocalServer> m_localServer;
SocketList m_socketList; SocketList m_socketList;
}; };
#endif // NATIVEMESSAGINGHOST_H #endif // NATIVEMESSAGINGHOST_H

View file

@ -20,6 +20,7 @@
#include <QtCore> #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 #endif // VARIANT_H

View file

@ -42,14 +42,15 @@ int Diceware::execute(const QStringList& arguments)
QCommandLineParser parser; QCommandLineParser parser;
parser.setApplicationDescription(this->description); parser.setApplicationDescription(this->description);
QCommandLineOption words(QStringList() << "W" << "words", QCommandLineOption words(QStringList() << "W"
QObject::tr("Word count for the diceware passphrase."), << "words",
QObject::tr("count")); QObject::tr("Word count for the diceware passphrase."),
QObject::tr("count"));
parser.addOption(words); parser.addOption(words);
QCommandLineOption wordlistFile(QStringList() << "w" QCommandLineOption wordlistFile(QStringList() << "w"
<< "word-list", << "word-list",
QObject::tr("Wordlist for the diceware generator.\n[Default: EFF English]"), QObject::tr("Wordlist for the diceware generator.\n[Default: EFF English]"),
QObject::tr("path")); QObject::tr("path"));
parser.addOption(wordlistFile); parser.addOption(wordlistFile);
parser.process(arguments); parser.process(arguments);
@ -78,7 +79,7 @@ int Diceware::execute(const QStringList& arguments)
outputTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli diceware"); outputTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli diceware");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
QString password = dicewareGenerator.generatePassphrase(); QString password = dicewareGenerator.generatePassphrase();
outputTextStream << password << endl; outputTextStream << password << endl;

View file

@ -115,8 +115,9 @@ int Edit::execute(const QStringList& arguments)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (parser.value("username").isEmpty() && parser.value("url").isEmpty() && parser.value("title").isEmpty() && if (parser.value("username").isEmpty() && parser.value("url").isEmpty() && parser.value("title").isEmpty()
!parser.isSet(prompt) && !parser.isSet(generate)) { && !parser.isSet(prompt)
&& !parser.isSet(generate)) {
qCritical("Not changing any field for entry %s.", qPrintable(entryPath)); qCritical("Not changing any field for entry %s.", qPrintable(entryPath));
return EXIT_FAILURE; return EXIT_FAILURE;
} }

View file

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

View file

@ -42,24 +42,20 @@ int Generate::execute(const QStringList& arguments)
QCommandLineParser parser; QCommandLineParser parser;
parser.setApplicationDescription(this->description); parser.setApplicationDescription(this->description);
QCommandLineOption len(QStringList() << "L" << "length", QCommandLineOption len(QStringList() << "L"
QObject::tr("Length of the generated password."), << "length",
QObject::tr("length")); QObject::tr("Length of the generated password."),
QObject::tr("length"));
parser.addOption(len); parser.addOption(len);
QCommandLineOption lower(QStringList() << "l", QCommandLineOption lower(QStringList() << "l", QObject::tr("Use lowercase characters in the generated password."));
QObject::tr("Use lowercase characters in the generated password."));
parser.addOption(lower); parser.addOption(lower);
QCommandLineOption upper(QStringList() << "u", QCommandLineOption upper(QStringList() << "u", QObject::tr("Use uppercase characters in the generated password."));
QObject::tr("Use uppercase characters in the generated password."));
parser.addOption(upper); parser.addOption(upper);
QCommandLineOption numeric(QStringList() << "n", QCommandLineOption numeric(QStringList() << "n", QObject::tr("Use numbers in the generated password."));
QObject::tr("Use numbers in the generated password."));
parser.addOption(numeric); parser.addOption(numeric);
QCommandLineOption special(QStringList() << "s", QCommandLineOption special(QStringList() << "s", QObject::tr("Use special characters in the generated password."));
QObject::tr("Use special characters in the generated password."));
parser.addOption(special); parser.addOption(special);
QCommandLineOption extended(QStringList() << "e", QCommandLineOption extended(QStringList() << "e", QObject::tr("Use extended ASCII in the generated password."));
QObject::tr("Use extended ASCII in the generated password."));
parser.addOption(extended); parser.addOption(extended);
parser.process(arguments); parser.process(arguments);
@ -81,19 +77,19 @@ int Generate::execute(const QStringList& arguments)
PasswordGenerator::CharClasses classes = 0x0; PasswordGenerator::CharClasses classes = 0x0;
if (parser.isSet(lower)) { if (parser.isSet(lower)) {
classes |= PasswordGenerator::LowerLetters; classes |= PasswordGenerator::LowerLetters;
} }
if (parser.isSet(upper)) { if (parser.isSet(upper)) {
classes |= PasswordGenerator::UpperLetters; classes |= PasswordGenerator::UpperLetters;
} }
if (parser.isSet(numeric)) { if (parser.isSet(numeric)) {
classes |= PasswordGenerator::Numbers; classes |= PasswordGenerator::Numbers;
} }
if (parser.isSet(special)) { if (parser.isSet(special)) {
classes |= PasswordGenerator::SpecialCharacters; classes |= PasswordGenerator::SpecialCharacters;
} }
if (parser.isSet(extended)) { if (parser.isSet(extended)) {
classes |= PasswordGenerator::EASCII; classes |= PasswordGenerator::EASCII;
} }
passwordGenerator.setCharClasses(classes); passwordGenerator.setCharClasses(classes);

View file

@ -49,12 +49,14 @@ int Show::execute(const QStringList& arguments)
QObject::tr("Key file of the database."), QObject::tr("Key file of the database."),
QObject::tr("path")); QObject::tr("path"));
parser.addOption(keyFile); parser.addOption(keyFile);
QCommandLineOption attributes(QStringList() << "a" QCommandLineOption attributes(
<< "attributes", QStringList() << "a"
QObject::tr("Names of the attributes to show. " << "attributes",
"This option can be specified more than once, with each attribute shown one-per-line in the given order. " QObject::tr(
"If no attributes are specified, a summary of the default attributes is given."), "Names of the attributes to show. "
QObject::tr("attribute")); "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.addOption(attributes);
parser.addPositionalArgument("entry", QObject::tr("Name of the entry to show.")); parser.addPositionalArgument("entry", QObject::tr("Name of the entry to show."));
parser.process(arguments); parser.process(arguments);

View file

@ -22,42 +22,42 @@
#include <QFutureWatcher> #include <QFutureWatcher>
#include <QtConcurrent> #include <QtConcurrent>
/** /**
* Asynchronously run computations outside the GUI thread. * Asynchronously run computations outside the GUI thread.
*/ */
namespace AsyncTask namespace AsyncTask
{ {
/** /**
* Wait for the given future without blocking the event loop. * Wait for the given future without blocking the event loop.
* *
* @param future future to wait for * @param future future to wait for
* @return async task result * @return async task result
*/ */
template<typename FunctionObject> template <typename FunctionObject>
typename std::result_of<FunctionObject()>::type waitForFuture(QFuture<typename std::result_of<FunctionObject()>::type> future) 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; QEventLoop loop;
QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit())); QFutureWatcher<typename std::result_of<FunctionObject()>::type> watcher;
watcher.setFuture(future); QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec(); watcher.setFuture(future);
return future.result(); loop.exec();
} return future.result();
}
/** /**
* Run a given task and wait for it to finish without blocking the event loop. * Run a given task and wait for it to finish without blocking the event loop.
* *
* @param task std::function object to run * @param task std::function object to run
* @return async task result * @return async task result
*/ */
template<typename FunctionObject> template <typename FunctionObject>
typename std::result_of<FunctionObject()>::type runAndWaitForFuture(FunctionObject task) typename std::result_of<FunctionObject()>::type runAndWaitForFuture(FunctionObject task)
{ {
return waitForFuture<FunctionObject>(QtConcurrent::run(task)); return waitForFuture<FunctionObject>(QtConcurrent::run(task));
} }
}; // namespace AsyncTask }; // namespace AsyncTask
#endif //KEEPASSXC_ASYNCTASK_HPP #endif // KEEPASSXC_ASYNCTASK_HPP

View file

@ -27,7 +27,6 @@ bool AutoTypeAssociations::Association::operator!=(const AutoTypeAssociations::A
return window != other.window || sequence != other.sequence; return window != other.window || sequence != other.sequence;
} }
AutoTypeAssociations::AutoTypeAssociations(QObject* parent) AutoTypeAssociations::AutoTypeAssociations(QObject* parent)
: QObject(parent) : QObject(parent)
{ {
@ -106,7 +105,7 @@ int AutoTypeAssociations::size() const
int AutoTypeAssociations::associationsSize() const int AutoTypeAssociations::associationsSize() const
{ {
int size = 0; int size = 0;
for (const Association &association : m_associations) { for (const Association& association : m_associations) {
size += association.sequence.toUtf8().size() + association.window.toUtf8().size(); size += association.sequence.toUtf8().size() + association.window.toUtf8().size();
} }
return size; return size;

View file

@ -19,14 +19,16 @@
#include "AutoTypeMatch.h" #include "AutoTypeMatch.h"
AutoTypeMatch::AutoTypeMatch() AutoTypeMatch::AutoTypeMatch()
: entry(nullptr), : entry(nullptr)
sequence() , sequence()
{} {
}
AutoTypeMatch::AutoTypeMatch(Entry* entry, QString sequence) AutoTypeMatch::AutoTypeMatch(Entry* entry, QString sequence)
: entry(entry), : entry(entry)
sequence(sequence) , sequence(sequence)
{} {
}
bool AutoTypeMatch::operator==(const AutoTypeMatch& other) const bool AutoTypeMatch::operator==(const AutoTypeMatch& other) const
{ {

View file

@ -21,8 +21,8 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <QDir> #include <QDir>
#include <QSettings> #include <QSettings>
#include <QTemporaryFile>
#include <QStandardPaths> #include <QStandardPaths>
#include <QTemporaryFile>
Config* Config::m_instance(nullptr); Config* Config::m_instance(nullptr);
@ -80,7 +80,7 @@ Config::Config(QObject* parent)
QString userPath; QString userPath;
QString homePath = QDir::homePath(); 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 // we can't use QStandardPaths on X11 as it uses XDG_DATA_HOME instead of XDG_CONFIG_HOME
QByteArray env = qgetenv("XDG_CONFIG_HOME"); QByteArray env = qgetenv("XDG_CONFIG_HOME");
if (env.isEmpty()) { if (env.isEmpty()) {
@ -95,17 +95,17 @@ Config::Config(QObject* parent)
} }
userPath += "/keepassxc/"; userPath += "/keepassxc/";
#else #else
userPath = QDir::fromNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DataLocation)); userPath = QDir::fromNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
// storageLocation() appends the application name ("/keepassxc") to the end // storageLocation() appends the application name ("/keepassxc") to the end
userPath += "/"; userPath += "/";
#endif #endif
#ifdef QT_DEBUG #ifdef QT_DEBUG
userPath += "keepassxc_debug.ini"; userPath += "keepassxc_debug.ini";
#else #else
userPath += "keepassxc.ini"; userPath += "keepassxc.ini";
#endif #endif
init(userPath); init(userPath);
} }

View file

@ -26,7 +26,7 @@ class QSettings;
class Config : public QObject class Config : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
Q_DISABLE_COPY(Config) Q_DISABLE_COPY(Config)
@ -54,7 +54,8 @@ private:
QHash<QString, QVariant> m_defaults; QHash<QString, QVariant> m_defaults;
}; };
inline Config* config() { inline Config* config()
{
return Config::instance(); return Config::instance();
} }

View file

@ -18,8 +18,8 @@
#include "CsvParser.h" #include "CsvParser.h"
#include <QTextCodec>
#include <QObject> #include <QObject>
#include <QTextCodec>
#include "core/Tools.h" #include "core/Tools.h"
@ -44,21 +44,24 @@ CsvParser::CsvParser()
m_ts.setCodec("UTF-8"); m_ts.setCodec("UTF-8");
} }
CsvParser::~CsvParser() { CsvParser::~CsvParser()
{
m_csv.close(); m_csv.close();
} }
bool CsvParser::isFileLoaded() { bool CsvParser::isFileLoaded()
{
return m_isFileLoaded; return m_isFileLoaded;
} }
bool CsvParser::reparse() { bool CsvParser::reparse()
{
reset(); reset();
return parseFile(); return parseFile();
} }
bool CsvParser::parse(QFile* device)
bool CsvParser::parse(QFile *device) { {
clear(); clear();
if (nullptr == device) { if (nullptr == device) {
appendStatusMsg(QObject::tr("NULL device"), true); appendStatusMsg(QObject::tr("NULL device"), true);
@ -69,7 +72,8 @@ bool CsvParser::parse(QFile *device) {
return parseFile(); return parseFile();
} }
bool CsvParser::readFile(QFile *device) { bool CsvParser::readFile(QFile* device)
{
if (device->isOpen()) if (device->isOpen())
device->close(); device->close();
@ -77,20 +81,20 @@ bool CsvParser::readFile(QFile *device) {
if (!Tools::readAllFromDevice(device, m_array)) { if (!Tools::readAllFromDevice(device, m_array)) {
appendStatusMsg(QObject::tr("error reading from device"), true); appendStatusMsg(QObject::tr("error reading from device"), true);
m_isFileLoaded = false; m_isFileLoaded = false;
} } else {
else {
device->close(); device->close();
m_array.replace("\r\n", "\n"); m_array.replace("\r\n", "\n");
m_array.replace("\r", "\n"); m_array.replace("\r", "\n");
if (0 == m_array.size()) if (0 == m_array.size())
appendStatusMsg(QObject::tr("file empty").append("\n")); appendStatusMsg(QObject::tr("file empty").append("\n"));
m_isFileLoaded = true; m_isFileLoaded = true;
} }
return m_isFileLoaded; return m_isFileLoaded;
} }
void CsvParser::reset() { void CsvParser::reset()
{
m_ch = 0; m_ch = 0;
m_currCol = 1; m_currCol = 1;
m_currRow = 1; m_currRow = 1;
@ -101,21 +105,23 @@ void CsvParser::reset() {
m_statusMsg = ""; m_statusMsg = "";
m_ts.seek(0); m_ts.seek(0);
m_table.clear(); m_table.clear();
//the following are users' concern :) // the following are users' concern :)
//m_comment = '#'; // m_comment = '#';
//m_backslashSyntax = false; // m_backslashSyntax = false;
//m_comment = '#'; // m_comment = '#';
//m_qualifier = '"'; // m_qualifier = '"';
//m_separator = ','; // m_separator = ',';
} }
void CsvParser::clear() { void CsvParser::clear()
{
reset(); reset();
m_isFileLoaded = false; m_isFileLoaded = false;
m_array.clear(); m_array.clear();
} }
bool CsvParser::parseFile() { bool CsvParser::parseFile()
{
parseRecord(); parseRecord();
while (!m_isEof) { while (!m_isEof) {
if (!skipEndline()) if (!skipEndline())
@ -128,7 +134,8 @@ bool CsvParser::parseFile() {
return m_isGood; return m_isGood;
} }
void CsvParser::parseRecord() { void CsvParser::parseRecord()
{
CsvRow row; CsvRow row;
if (isComment()) { if (isComment()) {
skipLine(); skipLine();
@ -151,19 +158,21 @@ void CsvParser::parseRecord() {
m_currCol++; m_currCol++;
} }
void CsvParser::parseField(CsvRow& row) { void CsvParser::parseField(CsvRow& row)
{
QString field; QString field;
peek(m_ch); peek(m_ch);
if (!isTerminator(m_ch)) { if (!isTerminator(m_ch)) {
if (isQualifier(m_ch)) if (isQualifier(m_ch))
parseQuoted(field); parseQuoted(field);
else else
parseSimple(field); parseSimple(field);
} }
row.push_back(field); row.push_back(field);
} }
void CsvParser::parseSimple(QString &s) { void CsvParser::parseSimple(QString& s)
{
QChar c; QChar c;
getChar(c); getChar(c);
while ((isText(c)) && (!m_isEof)) { while ((isText(c)) && (!m_isEof)) {
@ -174,16 +183,18 @@ void CsvParser::parseSimple(QString &s) {
ungetChar(); ungetChar();
} }
void CsvParser::parseQuoted(QString &s) { void CsvParser::parseQuoted(QString& s)
//read and discard initial qualifier (e.g. quote) {
// read and discard initial qualifier (e.g. quote)
getChar(m_ch); getChar(m_ch);
parseEscaped(s); parseEscaped(s);
//getChar(m_ch); // getChar(m_ch);
if (!isQualifier(m_ch)) if (!isQualifier(m_ch))
appendStatusMsg(QObject::tr("missing closing quote"), true); appendStatusMsg(QObject::tr("missing closing quote"), true);
} }
void CsvParser::parseEscaped(QString &s) { void CsvParser::parseEscaped(QString& s)
{
parseEscapedText(s); parseEscapedText(s);
while (processEscapeMark(s, m_ch)) while (processEscapeMark(s, m_ch))
parseEscapedText(s); parseEscapedText(s);
@ -191,7 +202,8 @@ void CsvParser::parseEscaped(QString &s) {
ungetChar(); ungetChar();
} }
void CsvParser::parseEscapedText(QString &s) { void CsvParser::parseEscapedText(QString& s)
{
getChar(m_ch); getChar(m_ch);
while ((!isQualifier(m_ch)) && !m_isEof) { while ((!isQualifier(m_ch)) && !m_isEof) {
s.append(m_ch); 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; QChar buf;
peek(buf); peek(buf);
QChar c2; QChar c2;
if (true == m_isBackslashSyntax) { if (true == m_isBackslashSyntax) {
//escape-character syntax, e.g. \" // escape-character syntax, e.g. \"
if (c != '\\') { if (c != '\\') {
return false; return false;
} }
//consume (and append) second qualifier // consume (and append) second qualifier
getChar(c2); getChar(c2);
if (m_isEof) { if (m_isEof) {
c2='\\'; c2 = '\\';
s.append('\\'); s.append('\\');
return false; return false;
} else { } else {
@ -219,11 +232,11 @@ bool CsvParser::processEscapeMark(QString &s, QChar c) {
return true; return true;
} }
} else { } else {
//double quote syntax, e.g. "" // double quote syntax, e.g. ""
if (!isQualifier(c)) if (!isQualifier(c))
return false; return false;
peek(c2); peek(c2);
if (!m_isEof) { //not EOF, can read one char if (!m_isEof) { // not EOF, can read one char
if (isQualifier(c2)) { if (isQualifier(c2)) {
s.append(c2); s.append(c2);
getChar(c2); getChar(c2);
@ -234,10 +247,11 @@ bool CsvParser::processEscapeMark(QString &s, QChar c) {
} }
} }
void CsvParser::fillColumns() { void CsvParser::fillColumns()
//fill shorter rows with empty placeholder columns {
// fill shorter rows with empty placeholder columns
for (int i = 0; i < m_table.size(); ++i) { 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) { if (gap > 0) {
CsvRow r = m_table.at(i); CsvRow r = m_table.at(i);
for (int j = 0; j < gap; ++j) { 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.readLine();
m_ts.seek(m_ts.pos() - 1); m_ts.seek(m_ts.pos() - 1);
} }
bool CsvParser::skipEndline() { bool CsvParser::skipEndline()
{
getChar(m_ch); getChar(m_ch);
return (m_ch == '\n'); return (m_ch == '\n');
} }
void CsvParser::getChar(QChar& c)
void CsvParser::getChar(QChar& c) { {
m_isEof = m_ts.atEnd(); m_isEof = m_ts.atEnd();
if (!m_isEof) { if (!m_isEof) {
m_lastPos = m_ts.pos(); 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)) { if (!m_ts.seek(m_lastPos)) {
qWarning("CSV Parser: unget lower bound exceeded"); qWarning("CSV Parser: unget lower bound exceeded");
m_isGood = false; m_isGood = false;
} }
} }
void CsvParser::peek(QChar& c) { void CsvParser::peek(QChar& c)
{
getChar(c); getChar(c);
if (!m_isEof) if (!m_isEof)
ungetChar(); ungetChar();
} }
bool CsvParser::isQualifier(const QChar &c) const { bool CsvParser::isQualifier(const QChar& c) const
{
if (true == m_isBackslashSyntax && (c != m_qualifier)) if (true == m_isBackslashSyntax && (c != m_qualifier))
return (c == '\\'); return (c == '\\');
else else
return (c == m_qualifier); return (c == m_qualifier);
} }
bool CsvParser::isComment() { bool CsvParser::isComment()
{
bool result = false; bool result = false;
QChar c2; QChar c2;
qint64 pos = m_ts.pos(); qint64 pos = m_ts.pos();
do getChar(c2); do
getChar(c2);
while ((isSpace(c2) || isTab(c2)) && (!m_isEof)); while ((isSpace(c2) || isTab(c2)) && (!m_isEof));
if (c2 == m_comment) if (c2 == m_comment)
@ -301,84 +322,100 @@ bool CsvParser::isComment() {
return result; return result;
} }
bool CsvParser::isText(QChar c) const { bool CsvParser::isText(QChar c) const
return !( (isCRLF(c)) || (isSeparator(c)) ); {
return !((isCRLF(c)) || (isSeparator(c)));
} }
bool CsvParser::isEmptyRow(CsvRow row) const { bool CsvParser::isEmptyRow(CsvRow row) const
{
CsvRow::const_iterator it = row.constBegin(); CsvRow::const_iterator it = row.constBegin();
for (; it != row.constEnd(); ++it) for (; it != row.constEnd(); ++it)
if ( ((*it) != "\n") && ((*it) != "") ) if (((*it) != "\n") && ((*it) != ""))
return false; return false;
return true; return true;
} }
bool CsvParser::isCRLF(const QChar &c) const { bool CsvParser::isCRLF(const QChar& c) const
{
return (c == '\n'); return (c == '\n');
} }
bool CsvParser::isSpace(const QChar &c) const { bool CsvParser::isSpace(const QChar& c) const
{
return (c == ' '); return (c == ' ');
} }
bool CsvParser::isTab(const QChar &c) const { bool CsvParser::isTab(const QChar& c) const
{
return (c == '\t'); return (c == '\t');
} }
bool CsvParser::isSeparator(const QChar &c) const { bool CsvParser::isSeparator(const QChar& c) const
{
return (c == m_separator); 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')); return (isSeparator(c) || (c == '\n') || (c == '\r'));
} }
void CsvParser::setBackslashSyntax(bool set) { void CsvParser::setBackslashSyntax(bool set)
{
m_isBackslashSyntax = set; m_isBackslashSyntax = set;
} }
void CsvParser::setComment(const QChar &c) { void CsvParser::setComment(const QChar& c)
{
m_comment = c.unicode(); m_comment = c.unicode();
} }
void CsvParser::setCodec(const QString &s) { void CsvParser::setCodec(const QString& s)
{
m_ts.setCodec(QTextCodec::codecForName(s.toLocal8Bit())); m_ts.setCodec(QTextCodec::codecForName(s.toLocal8Bit()));
} }
void CsvParser::setFieldSeparator(const QChar &c) { void CsvParser::setFieldSeparator(const QChar& c)
{
m_separator = c.unicode(); m_separator = c.unicode();
} }
void CsvParser::setTextQualifier(const QChar &c) { void CsvParser::setTextQualifier(const QChar& c)
{
m_qualifier = c.unicode(); m_qualifier = c.unicode();
} }
int CsvParser::getFileSize() const { int CsvParser::getFileSize() const
{
return m_csv.size(); return m_csv.size();
} }
const CsvTable CsvParser::getCsvTable() const { const CsvTable CsvParser::getCsvTable() const
{
return m_table; return m_table;
} }
QString CsvParser::getStatus() const { QString CsvParser::getStatus() const
{
return m_statusMsg; return m_statusMsg;
} }
int CsvParser::getCsvCols() const { int CsvParser::getCsvCols() const
{
if ((m_table.size() > 0) && (m_table.at(0).size() > 0)) if ((m_table.size() > 0) && (m_table.at(0).size() > 0))
return m_table.at(0).size(); return m_table.at(0).size();
else return 0; else
return 0;
} }
int CsvParser::getCsvRows() const { int CsvParser::getCsvRows() const
{
return m_table.size(); return m_table.size();
} }
void CsvParser::appendStatusMsg(QString s, bool isCritical)
void CsvParser::appendStatusMsg(QString s, bool isCritical) { {
m_statusMsg += QObject::tr("%1: (row, col) %2,%3") m_statusMsg += QObject::tr("%1: (row, col) %2,%3").arg(s, m_currRow, m_currCol).append("\n");
.arg(s, m_currRow, m_currCol)
.append("\n");
m_isGood = !isCritical; m_isGood = !isCritical;
} }

View file

@ -19,28 +19,29 @@
#ifndef KEEPASSX_CSVPARSER_H #ifndef KEEPASSX_CSVPARSER_H
#define KEEPASSX_CSVPARSER_H #define KEEPASSX_CSVPARSER_H
#include <QFile>
#include <QBuffer> #include <QBuffer>
#include <QFile>
#include <QQueue> #include <QQueue>
#include <QTextStream> #include <QTextStream>
typedef QStringList CsvRow; typedef QStringList CsvRow;
typedef QList<CsvRow> CsvTable; typedef QList<CsvRow> CsvTable;
class CsvParser { class CsvParser
{
public: public:
CsvParser(); CsvParser();
~CsvParser(); ~CsvParser();
//read data from device and parse it // read data from device and parse it
bool parse(QFile *device); bool parse(QFile* device);
bool isFileLoaded(); bool isFileLoaded();
//reparse the same buffer (device is not opened again) // reparse the same buffer (device is not opened again)
bool reparse(); bool reparse();
void setCodec(const QString &s); void setCodec(const QString& s);
void setComment(const QChar &c); void setComment(const QChar& c);
void setFieldSeparator(const QChar &c); void setFieldSeparator(const QChar& c);
void setTextQualifier(const QChar &c); void setTextQualifier(const QChar& c);
void setBackslashSyntax(bool set); void setBackslashSyntax(bool set);
int getFileSize() const; int getFileSize() const;
int getCsvRows() const; int getCsvRows() const;
@ -52,45 +53,45 @@ protected:
CsvTable m_table; CsvTable m_table;
private: private:
QByteArray m_array; QByteArray m_array;
QBuffer m_csv; QBuffer m_csv;
QChar m_ch; QChar m_ch;
QChar m_comment; QChar m_comment;
unsigned int m_currCol; unsigned int m_currCol;
unsigned int m_currRow; unsigned int m_currRow;
bool m_isBackslashSyntax; bool m_isBackslashSyntax;
bool m_isEof; bool m_isEof;
bool m_isFileLoaded; bool m_isFileLoaded;
bool m_isGood; bool m_isGood;
qint64 m_lastPos; qint64 m_lastPos;
int m_maxCols; int m_maxCols;
QChar m_qualifier; QChar m_qualifier;
QChar m_separator; QChar m_separator;
QString m_statusMsg; QString m_statusMsg;
QTextStream m_ts; QTextStream m_ts;
void getChar(QChar &c); void getChar(QChar& c);
void ungetChar(); void ungetChar();
void peek(QChar &c); void peek(QChar& c);
void fillColumns(); void fillColumns();
bool isTerminator(const QChar &c) const; bool isTerminator(const QChar& c) const;
bool isSeparator(const QChar &c) const; bool isSeparator(const QChar& c) const;
bool isQualifier(const QChar &c) const; bool isQualifier(const QChar& c) const;
bool processEscapeMark(QString &s, QChar c); bool processEscapeMark(QString& s, QChar c);
bool isText(QChar c) const; bool isText(QChar c) const;
bool isComment(); bool isComment();
bool isCRLF(const QChar &c) const; bool isCRLF(const QChar& c) const;
bool isSpace(const QChar &c) const; bool isSpace(const QChar& c) const;
bool isTab(const QChar &c) const; bool isTab(const QChar& c) const;
bool isEmptyRow(CsvRow row) const; bool isEmptyRow(CsvRow row) const;
bool parseFile(); bool parseFile();
void parseRecord(); void parseRecord();
void parseField(CsvRow &row); void parseField(CsvRow& row);
void parseSimple(QString &s); void parseSimple(QString& s);
void parseQuoted(QString &s); void parseQuoted(QString& s);
void parseEscaped(QString &s); void parseEscaped(QString& s);
void parseEscapedText(QString &s); void parseEscapedText(QString& s);
bool readFile(QFile *device); bool readFile(QFile* device);
void reset(); void reset();
void clear(); void clear();
bool skipEndline(); bool skipEndline();
@ -98,5 +99,4 @@ private:
void appendStatusMsg(QString s, bool isCritical = false); void appendStatusMsg(QString s, bool isCritical = false);
}; };
#endif //CSVPARSER_H #endif // CSVPARSER_H

View file

@ -54,7 +54,7 @@ void CustomData::set(const QString& key, const QString& value)
if (addAttribute) { if (addAttribute) {
emit aboutToBeAdded(key); emit aboutToBeAdded(key);
} }
if (addAttribute || changeValue) { if (addAttribute || changeValue) {
m_data.insert(key, value); m_data.insert(key, value);

View file

@ -25,7 +25,7 @@
class CustomData : public QObject class CustomData : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CustomData(QObject* parent = nullptr); explicit CustomData(QObject* parent = nullptr);
@ -45,7 +45,6 @@ public:
bool operator==(const CustomData& other) const; bool operator==(const CustomData& other) const;
bool operator!=(const CustomData& other) const; bool operator!=(const CustomData& other) const;
signals: signals:
void modified(); void modified();
void aboutToBeAdded(const QString& key); void aboutToBeAdded(const QString& key);

View file

@ -32,8 +32,8 @@
#include "format/KeePass2.h" #include "format/KeePass2.h"
#include "format/KeePass2Reader.h" #include "format/KeePass2Reader.h"
#include "format/KeePass2Writer.h" #include "format/KeePass2Writer.h"
#include "keys/PasswordKey.h"
#include "keys/FileKey.h" #include "keys/FileKey.h"
#include "keys/PasswordKey.h"
QHash<Uuid, Database*> Database::m_uuidMap; 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) 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\""); "Can't search entry with \"referenceType\" parameter equal to \"Unknown\"");
bool found = false; bool found = false;
@ -335,7 +336,6 @@ void Database::setPublicCustomData(const QVariantMap& customData)
m_data.publicCustomData = customData; m_data.publicCustomData = customData;
} }
void Database::createRecycleBin() void Database::createRecycleBin()
{ {
Group* recycleBin = Group::createRecycleBin(); Group* recycleBin = Group::createRecycleBin();
@ -407,7 +407,6 @@ void Database::setEmitModified(bool value)
m_emitModified = value; m_emitModified = value;
} }
Uuid Database::uuid() Uuid Database::uuid()
{ {
return m_uuid; return m_uuid;

View file

@ -23,8 +23,8 @@
#include <QHash> #include <QHash>
#include <QObject> #include <QObject>
#include "crypto/kdf/Kdf.h"
#include "core/Uuid.h" #include "core/Uuid.h"
#include "crypto/kdf/Kdf.h"
#include "keys/CompositeKey.h" #include "keys/CompositeKey.h"
class Entry; class Entry;
@ -101,8 +101,7 @@ public:
void setCipher(const Uuid& cipher); void setCipher(const Uuid& cipher);
void setCompressionAlgo(Database::CompressionAlgorithm algo); void setCompressionAlgo(Database::CompressionAlgorithm algo);
void setKdf(QSharedPointer<Kdf> kdf); void setKdf(QSharedPointer<Kdf> kdf);
bool setKey(const CompositeKey& key, bool updateChangedTime = true, bool setKey(const CompositeKey& key, bool updateChangedTime = true, bool updateTransformSalt = false);
bool updateTransformSalt = false);
bool hasKey() const; bool hasKey() const;
bool verifyKey(const CompositeKey& key) const; bool verifyKey(const CompositeKey& key) const;
QVariantMap& publicCustomData(); QVariantMap& publicCustomData();

View file

@ -106,8 +106,7 @@ QImage DatabaseIcons::icon(int index)
if (!m_iconCache[index].isNull()) { if (!m_iconCache[index].isNull()) {
return m_iconCache[index]; return m_iconCache[index];
} } else {
else {
QString iconPath = QString("icons/database/").append(m_indexToName[index]); QString iconPath = QString("icons/database/").append(m_indexToName[index]);
QImage icon(filePath()->dataPath(iconPath)); QImage icon(filePath()->dataPath(iconPath));

View file

@ -46,7 +46,8 @@ private:
Q_DISABLE_COPY(DatabaseIcons) Q_DISABLE_COPY(DatabaseIcons)
}; };
inline DatabaseIcons* databaseIcons() { inline DatabaseIcons* databaseIcons()
{
return DatabaseIcons::instance(); return DatabaseIcons::instance();
} }

View file

@ -20,59 +20,55 @@
#define KEEPASSX_ENDIAN_H #define KEEPASSX_ENDIAN_H
#include <QByteArray> #include <QByteArray>
#include <QIODevice>
#include <QSysInfo> #include <QSysInfo>
#include <QtEndian> #include <QtEndian>
#include <QIODevice>
namespace Endian namespace Endian
{ {
template<typename SizedQInt> template <typename SizedQInt> SizedQInt bytesToSizedInt(const QByteArray& ba, QSysInfo::Endian byteOrder)
SizedQInt bytesToSizedInt(const QByteArray& ba, QSysInfo::Endian byteOrder) {
{ Q_ASSERT(ba.size() == sizeof(SizedQInt));
Q_ASSERT(ba.size() == sizeof(SizedQInt));
if (byteOrder == QSysInfo::LittleEndian) { if (byteOrder == QSysInfo::LittleEndian) {
return qFromLittleEndian<SizedQInt>(reinterpret_cast<const uchar*>(ba.constData())); return qFromLittleEndian<SizedQInt>(reinterpret_cast<const uchar*>(ba.constData()));
} }
return qFromBigEndian<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()));
} }
return ba; template <typename SizedQInt> SizedQInt readSizedInt(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok)
} {
QByteArray ba = device->read(sizeof(SizedQInt));
template<typename SizedQInt> if (ba.size() != sizeof(SizedQInt)) {
bool writeSizedInt(SizedQInt num, QIODevice* device, QSysInfo::Endian byteOrder) *ok = false;
{ return 0;
QByteArray ba = sizedIntToBytes<SizedQInt>(num, byteOrder); }
qint64 bytesWritten = device->write(ba); *ok = true;
return (bytesWritten == ba.size()); 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 } // namespace Endian

View file

@ -32,7 +32,6 @@ const int Entry::ResolveMaximumDepth = 10;
const QString Entry::AutoTypeSequenceUsername = "{USERNAME}{ENTER}"; const QString Entry::AutoTypeSequenceUsername = "{USERNAME}{ENTER}";
const QString Entry::AutoTypeSequencePassword = "{PASSWORD}{ENTER}"; const QString Entry::AutoTypeSequencePassword = "{PASSWORD}{ENTER}";
Entry::Entry() Entry::Entry()
: m_attributes(new EntryAttributes(this)) : m_attributes(new EntryAttributes(this))
, m_attachments(new EntryAttachments(this)) , m_attachments(new EntryAttachments(this))
@ -78,8 +77,7 @@ template <class T> inline bool Entry::set(T& property, const T& value)
property = value; property = value;
emit modified(); emit modified();
return true; return true;
} } else {
else {
return false; return false;
} }
} }
@ -129,14 +127,12 @@ QImage Entry::icon() const
{ {
if (m_data.customIcon.isNull()) { if (m_data.customIcon.isNull()) {
return databaseIcons()->icon(m_data.iconNumber); return databaseIcons()->icon(m_data.iconNumber);
} } else {
else {
Q_ASSERT(database()); Q_ASSERT(database());
if (database()) { if (database()) {
return database()->metadata()->customIcon(m_data.customIcon); return database()->metadata()->customIcon(m_data.customIcon);
} } else {
else {
return QImage(); return QImage();
} }
} }
@ -146,14 +142,12 @@ QPixmap Entry::iconPixmap() const
{ {
if (m_data.customIcon.isNull()) { if (m_data.customIcon.isNull()) {
return databaseIcons()->iconPixmap(m_data.iconNumber); return databaseIcons()->iconPixmap(m_data.iconNumber);
} } else {
else {
Q_ASSERT(database()); Q_ASSERT(database());
if (database()) { if (database()) {
return database()->metadata()->customIconPixmap(m_data.customIcon); return database()->metadata()->customIconPixmap(m_data.customIcon);
} } else {
else {
return QPixmap(); return QPixmap();
} }
} }
@ -164,8 +158,7 @@ QPixmap Entry::iconScaledPixmap() const
if (m_data.customIcon.isNull()) { if (m_data.customIcon.isNull()) {
// built-in icons are 16x16 so don't need to be scaled // built-in icons are 16x16 so don't need to be scaled
return databaseIcons()->iconPixmap(m_data.iconNumber); return databaseIcons()->iconPixmap(m_data.iconNumber);
} } else {
else {
Q_ASSERT(database()); Q_ASSERT(database());
return database()->metadata()->customIconScaledPixmap(m_data.customIcon); return database()->metadata()->customIconScaledPixmap(m_data.customIcon);
@ -381,7 +374,7 @@ void Entry::setTotp(const QString& seed, quint8& step, quint8& digits)
} }
QString data; 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")) { if (m_attributes->hasKey("otp")) {
data = QString("key=%1&step=%2&size=%3").arg(seed).arg(step).arg(enc.digits == 0 ? digits : enc.digits); 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) void Entry::setUrl(const QString& url)
{ {
bool remove = url != m_attributes->value(EntryAttributes::URLKey) && bool remove = url != m_attributes->value(EntryAttributes::URLKey)
(m_attributes->value(EntryAttributes::RememberCmdExecAttr) == "1" || && (m_attributes->value(EntryAttributes::RememberCmdExecAttr) == "1"
m_attributes->value(EntryAttributes::RememberCmdExecAttr) == "0"); || m_attributes->value(EntryAttributes::RememberCmdExecAttr) == "0");
if (remove) { if (remove) {
m_attributes->remove(EntryAttributes::RememberCmdExecAttr); m_attributes->remove(EntryAttributes::RememberCmdExecAttr);
} }
@ -640,8 +633,7 @@ Entry* Entry::clone(CloneFlags flags) const
entry->setUpdateTimeinfo(false); entry->setUpdateTimeinfo(false);
if (flags & CloneNewUuid) { if (flags & CloneNewUuid) {
entry->m_uuid = Uuid::random(); entry->m_uuid = Uuid::random();
} } else {
else {
entry->m_uuid = m_uuid; entry->m_uuid = m_uuid;
} }
entry->m_data = m_data; entry->m_data = m_data;
@ -652,12 +644,14 @@ Entry* Entry::clone(CloneFlags flags) const
if (flags & CloneUserAsRef) { if (flags & CloneUserAsRef) {
// Build the username reference // Build the username reference
QString username = "{REF:U@I:" + m_uuid.toHex() + "}"; 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) { if (flags & ClonePassAsRef) {
QString password = "{REF:P@I:" + m_uuid.toHex() + "}"; 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); entry->m_autoTypeAssociations->copyDataFrom(m_autoTypeAssociations);
@ -719,8 +713,7 @@ bool Entry::endUpdate()
m_tmpHistoryItem->setUpdateTimeinfo(true); m_tmpHistoryItem->setUpdateTimeinfo(true);
addHistoryItem(m_tmpHistoryItem); addHistoryItem(m_tmpHistoryItem);
truncateHistory(); truncateHistory();
} } else {
else {
delete m_tmpHistoryItem; delete m_tmpHistoryItem;
} }
@ -933,8 +926,8 @@ void Entry::setGroup(Group* group)
// copy custom icon to the new database // copy custom icon to the new database
if (!iconUuid().isNull() && group->database() if (!iconUuid().isNull() && group->database()
&& m_group->database()->metadata()->containsCustomIcon(iconUuid()) && m_group->database()->metadata()->containsCustomIcon(iconUuid())
&& !group->database()->metadata()->containsCustomIcon(iconUuid())) { && !group->database()->metadata()->containsCustomIcon(iconUuid())) {
group->database()->metadata()->addCustomIcon(iconUuid(), icon()); group->database()->metadata()->addCustomIcon(iconUuid(), icon());
} }
} }
@ -959,8 +952,7 @@ const Database* Entry::database() const
{ {
if (m_group) { if (m_group) {
return m_group->database(); return m_group->database();
} } else {
else {
return nullptr; return nullptr;
} }
} }
@ -1028,26 +1020,25 @@ Entry::PlaceholderType Entry::placeholderType(const QString& placeholder) const
return PlaceholderType::Reference; return PlaceholderType::Reference;
} }
static const QMap<QString, PlaceholderType> placeholders { static const QMap<QString, PlaceholderType> placeholders{
{ QStringLiteral("{TITLE}"), PlaceholderType::Title }, {QStringLiteral("{TITLE}"), PlaceholderType::Title},
{ QStringLiteral("{USERNAME}"), PlaceholderType::UserName }, {QStringLiteral("{USERNAME}"), PlaceholderType::UserName},
{ QStringLiteral("{PASSWORD}"), PlaceholderType::Password }, {QStringLiteral("{PASSWORD}"), PlaceholderType::Password},
{ QStringLiteral("{NOTES}"), PlaceholderType::Notes }, {QStringLiteral("{NOTES}"), PlaceholderType::Notes},
{ QStringLiteral("{TOTP}"), PlaceholderType::Totp }, {QStringLiteral("{TOTP}"), PlaceholderType::Totp},
{ QStringLiteral("{URL}"), PlaceholderType::Url }, {QStringLiteral("{URL}"), PlaceholderType::Url},
{ QStringLiteral("{URL:RMVSCM}"), PlaceholderType::UrlWithoutScheme }, {QStringLiteral("{URL:RMVSCM}"), PlaceholderType::UrlWithoutScheme},
{ QStringLiteral("{URL:WITHOUTSCHEME}"), PlaceholderType::UrlWithoutScheme }, {QStringLiteral("{URL:WITHOUTSCHEME}"), PlaceholderType::UrlWithoutScheme},
{ QStringLiteral("{URL:SCM}"), PlaceholderType::UrlScheme }, {QStringLiteral("{URL:SCM}"), PlaceholderType::UrlScheme},
{ QStringLiteral("{URL:SCHEME}"), PlaceholderType::UrlScheme }, {QStringLiteral("{URL:SCHEME}"), PlaceholderType::UrlScheme},
{ QStringLiteral("{URL:HOST}"), PlaceholderType::UrlHost }, {QStringLiteral("{URL:HOST}"), PlaceholderType::UrlHost},
{ QStringLiteral("{URL:PORT}"), PlaceholderType::UrlPort }, {QStringLiteral("{URL:PORT}"), PlaceholderType::UrlPort},
{ QStringLiteral("{URL:PATH}"), PlaceholderType::UrlPath }, {QStringLiteral("{URL:PATH}"), PlaceholderType::UrlPath},
{ QStringLiteral("{URL:QUERY}"), PlaceholderType::UrlQuery }, {QStringLiteral("{URL:QUERY}"), PlaceholderType::UrlQuery},
{ QStringLiteral("{URL:FRAGMENT}"), PlaceholderType::UrlFragment }, {QStringLiteral("{URL:FRAGMENT}"), PlaceholderType::UrlFragment},
{ QStringLiteral("{URL:USERINFO}"), PlaceholderType::UrlUserInfo }, {QStringLiteral("{URL:USERINFO}"), PlaceholderType::UrlUserInfo},
{ QStringLiteral("{URL:USERNAME}"), PlaceholderType::UrlUserName }, {QStringLiteral("{URL:USERNAME}"), PlaceholderType::UrlUserName},
{ QStringLiteral("{URL:PASSWORD}"), PlaceholderType::UrlPassword } {QStringLiteral("{URL:PASSWORD}"), PlaceholderType::UrlPassword}};
};
return placeholders.value(placeholder.toUpper(), PlaceholderType::Unknown); return placeholders.value(placeholder.toUpper(), PlaceholderType::Unknown);
} }
@ -1062,7 +1053,7 @@ QString Entry::resolveUrl(const QString& url) const
if (newUrl.startsWith("cmd://")) { if (newUrl.startsWith("cmd://")) {
QStringList cmdList = newUrl.split(" "); 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) // Don't pass arguments to the resolveUrl function (they look like URL's)
if (!cmdList[i].startsWith("-") && !cmdList[i].startsWith("/")) { if (!cmdList[i].startsWith("-") && !cmdList[i].startsWith("/")) {
return resolveUrl(cmdList[i].remove(QRegExp("'|\""))); return resolveUrl(cmdList[i].remove(QRegExp("'|\"")));

View file

@ -37,7 +37,8 @@
class Database; class Database;
class Group; class Group;
enum class EntryReferenceType { enum class EntryReferenceType
{
Unknown, Unknown,
Title, Title,
UserName, UserName,
@ -142,18 +143,20 @@ public:
void removeHistoryItems(const QList<Entry*>& historyEntries); void removeHistoryItems(const QList<Entry*>& historyEntries);
void truncateHistory(); void truncateHistory();
enum CloneFlag { enum CloneFlag
CloneNoFlags = 0, {
CloneNewUuid = 1, // generate a random uuid for the clone CloneNoFlags = 0,
CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time CloneNewUuid = 1, // generate a random uuid for the clone
CloneIncludeHistory = 4, // clone the history items CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time
CloneRenameTitle = 8, // add "-Clone" after the original title CloneIncludeHistory = 4, // clone the history items
CloneUserAsRef = 16, // Add the user as a reference to the original entry CloneRenameTitle = 8, // add "-Clone" after the original title
ClonePassAsRef = 32, // Add the password as a reference to the original entry 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) Q_DECLARE_FLAGS(CloneFlags, CloneFlag)
enum class PlaceholderType { enum class PlaceholderType
{
NotPlaceholder, NotPlaceholder,
Unknown, Unknown,
Title, Title,

View file

@ -17,8 +17,8 @@
#include "EntryAttachments.h" #include "EntryAttachments.h"
#include <QStringList>
#include <QSet> #include <QSet>
#include <QStringList>
EntryAttachments::EntryAttachments(QObject* parent) EntryAttachments::EntryAttachments(QObject* parent)
: QObject(parent) : QObject(parent)
@ -61,8 +61,7 @@ void EntryAttachments::set(const QString& key, const QByteArray& value)
if (addAttachment) { if (addAttachment) {
emit added(key); emit added(key);
} } else {
else {
emit keyModified(key); emit keyModified(key);
} }
@ -74,8 +73,7 @@ void EntryAttachments::set(const QString& key, const QByteArray& value)
void EntryAttachments::remove(const QString& key) void EntryAttachments::remove(const QString& key)
{ {
if (!m_attachments.contains(key)) { if (!m_attachments.contains(key)) {
Q_ASSERT_X(false, "EntryAttachments::remove", Q_ASSERT_X(false, "EntryAttachments::remove", qPrintable(QString("Can't find attachment for key %1").arg(key)));
qPrintable(QString("Can't find attachment for key %1").arg(key)));
return; return;
} }
@ -94,10 +92,10 @@ void EntryAttachments::remove(const QStringList& keys)
} }
bool isModified = false; bool isModified = false;
for (const QString &key: keys) { for (const QString& key : keys) {
if (!m_attachments.contains(key)) { if (!m_attachments.contains(key)) {
Q_ASSERT_X(false, "EntryAttachments::remove", Q_ASSERT_X(
qPrintable(QString("Can't find attachment for key %1").arg(key))); false, "EntryAttachments::remove", qPrintable(QString("Can't find attachment for key %1").arg(key)));
continue; continue;
} }

View file

@ -23,8 +23,8 @@ const QString EntryAttributes::UserNameKey = "UserName";
const QString EntryAttributes::PasswordKey = "Password"; const QString EntryAttributes::PasswordKey = "Password";
const QString EntryAttributes::URLKey = "URL"; const QString EntryAttributes::URLKey = "URL";
const QString EntryAttributes::NotesKey = "Notes"; const QString EntryAttributes::NotesKey = "Notes";
const QStringList EntryAttributes::DefaultAttributes(QStringList() << TitleKey << UserNameKey const QStringList EntryAttributes::DefaultAttributes(QStringList() << TitleKey << UserNameKey << PasswordKey << URLKey
<< PasswordKey << URLKey << NotesKey); << NotesKey);
const QString EntryAttributes::WantedFieldGroupName = "WantedField"; const QString EntryAttributes::WantedFieldGroupName = "WantedField";
const QString EntryAttributes::SearchInGroupName = "SearchIn"; const QString EntryAttributes::SearchInGroupName = "SearchIn";
@ -113,8 +113,7 @@ void EntryAttributes::set(const QString& key, const QString& value, bool protect
emitModified = true; emitModified = true;
} }
m_protectedAttributes.insert(key); m_protectedAttributes.insert(key);
} } else if (m_protectedAttributes.remove(key)) {
else if (m_protectedAttributes.remove(key)) {
emitModified = true; emitModified = true;
} }
@ -124,11 +123,9 @@ void EntryAttributes::set(const QString& key, const QString& value, bool protect
if (defaultAttribute && changeValue) { if (defaultAttribute && changeValue) {
emit defaultKeyModified(); emit defaultKeyModified();
} } else if (addAttribute) {
else if (addAttribute) {
emit added(key); emit added(key);
} } else if (emitModified) {
else if (emitModified) {
emit customKeyModified(key); emit customKeyModified(key);
} }
} }
@ -249,21 +246,19 @@ void EntryAttributes::copyDataFrom(const EntryAttributes* other)
bool EntryAttributes::operator==(const EntryAttributes& other) const bool EntryAttributes::operator==(const EntryAttributes& other) const
{ {
return (m_attributes == other.m_attributes return (m_attributes == other.m_attributes && m_protectedAttributes == other.m_protectedAttributes);
&& m_protectedAttributes == other.m_protectedAttributes);
} }
bool EntryAttributes::operator!=(const EntryAttributes& other) const bool EntryAttributes::operator!=(const EntryAttributes& other) const
{ {
return (m_attributes != other.m_attributes return (m_attributes != other.m_attributes || m_protectedAttributes != other.m_protectedAttributes);
|| m_protectedAttributes != other.m_protectedAttributes);
} }
QRegularExpressionMatch EntryAttributes::matchReference(const QString& text) QRegularExpressionMatch EntryAttributes::matchReference(const QString& text)
{ {
static QRegularExpression referenceRegExp( static QRegularExpression referenceRegExp(
"\\{REF:(?<WantedField>[TUPANI])@(?<SearchIn>[TUPANIO]):(?<SearchText>[^}]+)\\}", "\\{REF:(?<WantedField>[TUPANI])@(?<SearchIn>[TUPANIO]):(?<SearchText>[^}]+)\\}",
QRegularExpression::CaseInsensitiveOption); QRegularExpression::CaseInsensitiveOption);
return referenceRegExp.match(text); return referenceRegExp.match(text);
} }

View file

@ -20,8 +20,7 @@
#include "core/Group.h" #include "core/Group.h"
QList<Entry*> EntrySearcher::search(const QString& searchTerm, const Group* group, QList<Entry*> EntrySearcher::search(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity)
Qt::CaseSensitivity caseSensitivity)
{ {
if (!group->resolveSearchingEnabled()) { if (!group->resolveSearchingEnabled()) {
return QList<Entry*>(); return QList<Entry*>();
@ -30,14 +29,14 @@ QList<Entry*> EntrySearcher::search(const QString& searchTerm, const Group* grou
return searchEntries(searchTerm, group, caseSensitivity); return searchEntries(searchTerm, group, caseSensitivity);
} }
QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Group* group, QList<Entry*>
Qt::CaseSensitivity caseSensitivity) EntrySearcher::searchEntries(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity)
{ {
QList<Entry*> searchResult; QList<Entry*> searchResult;
const QList<Entry*> entryList = group->entries(); const QList<Entry*> entryList = group->entries();
for (Entry* entry : entryList) { for (Entry* entry : entryList) {
searchResult.append(matchEntry(searchTerm, entry, caseSensitivity)); searchResult.append(matchEntry(searchTerm, entry, caseSensitivity));
} }
const QList<Group*> children = group->children(); const QList<Group*> children = group->children();
@ -54,8 +53,7 @@ QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Grou
return searchResult; return searchResult;
} }
QList<Entry*> EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry, QList<Entry*> EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry, Qt::CaseSensitivity caseSensitivity)
Qt::CaseSensitivity caseSensitivity)
{ {
const QStringList wordList = searchTerm.split(QRegExp("\\s"), QString::SkipEmptyParts); const QStringList wordList = searchTerm.split(QRegExp("\\s"), QString::SkipEmptyParts);
for (const QString& word : wordList) { 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) bool EntrySearcher::wordMatch(const QString& word, Entry* entry, Qt::CaseSensitivity caseSensitivity)
{ {
return entry->resolvePlaceholder(entry->title()).contains(word, caseSensitivity) || return entry->resolvePlaceholder(entry->title()).contains(word, caseSensitivity)
entry->resolvePlaceholder(entry->username()).contains(word, caseSensitivity) || || entry->resolvePlaceholder(entry->username()).contains(word, caseSensitivity)
entry->resolvePlaceholder(entry->url()).contains(word, caseSensitivity) || || entry->resolvePlaceholder(entry->url()).contains(word, caseSensitivity)
entry->resolvePlaceholder(entry->notes()).contains(word, caseSensitivity); || entry->resolvePlaceholder(entry->notes()).contains(word, caseSensitivity);
} }
bool EntrySearcher::matchGroup(const QString& searchTerm, const Group* group, Qt::CaseSensitivity 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) bool EntrySearcher::wordMatch(const QString& word, const Group* group, Qt::CaseSensitivity caseSensitivity)
{ {
return group->name().contains(word, caseSensitivity) || return group->name().contains(word, caseSensitivity) || group->notes().contains(word, caseSensitivity);
group->notes().contains(word, caseSensitivity);
} }

View file

@ -21,7 +21,6 @@
#include <QString> #include <QString>
class Group; class Group;
class Entry; class Entry;

View file

@ -8,7 +8,9 @@ class Exporter
{ {
public: public:
virtual Database* exportGroup(Group* group) = 0; virtual Database* exportGroup(Group* group) = 0;
virtual ~Exporter() {} virtual ~Exporter()
{
}
}; };
#endif // KEEPASSX_EXPORTER_H #endif // KEEPASSX_EXPORTER_H

View file

@ -23,8 +23,8 @@
#include <QLibrary> #include <QLibrary>
#include "config-keepassx.h" #include "config-keepassx.h"
#include "core/Global.h"
#include "core/Config.h" #include "core/Config.h"
#include "core/Global.h"
FilePath* FilePath::m_instance(nullptr); FilePath* FilePath::m_instance(nullptr);
@ -32,8 +32,7 @@ QString FilePath::dataPath(const QString& name)
{ {
if (name.isEmpty() || name.startsWith('/')) { if (name.isEmpty() || name.startsWith('/')) {
return m_dataPath + name; return m_dataPath + name;
} } else {
else {
return m_dataPath + "/" + name; return m_dataPath + "/" + name;
} }
} }
@ -61,14 +60,12 @@ QString FilePath::pluginPath(const QString& name)
if (configuredPluginDir != ".") { if (configuredPluginDir != ".") {
if (QDir(configuredPluginDir).isAbsolute()) { if (QDir(configuredPluginDir).isAbsolute()) {
pluginPaths << configuredPluginDir; pluginPaths << configuredPluginDir;
} } else {
else { QString relativePluginDir =
QString relativePluginDir = QString("%1/../%2") QString("%1/../%2").arg(QCoreApplication::applicationDirPath(), configuredPluginDir);
.arg(QCoreApplication::applicationDirPath(), configuredPluginDir);
pluginPaths << QDir(relativePluginDir).canonicalPath(); pluginPaths << QDir(relativePluginDir).canonicalPath();
QString absolutePluginDir = QString("%1/%2") QString absolutePluginDir = QString("%1/%2").arg(KEEPASSX_PREFIX_DIR, configuredPluginDir);
.arg(KEEPASSX_PREFIX_DIR, configuredPluginDir);
pluginPaths << QDir(absolutePluginDir).canonicalPath(); pluginPaths << QDir(absolutePluginDir).canonicalPath();
} }
} }
@ -151,11 +148,11 @@ QIcon FilePath::icon(const QString& category, const QString& name, bool fromThem
} }
if (icon.isNull()) { 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; QString filename;
for (int size : pngSizes) { for (int size : pngSizes) {
filename = QString("%1/icons/application/%2x%2/%3.png").arg(m_dataPath, QString::number(size), filename =
combinedName); QString("%1/icons/application/%2x%2/%3.png").arg(m_dataPath, QString::number(size), combinedName);
if (QFile::exists(filename)) { if (QFile::exists(filename)) {
icon.addFile(filename, QSize(size, size)); icon.addFile(filename, QSize(size, size));
} }
@ -189,17 +186,16 @@ QIcon FilePath::onOffIcon(const QString& category, const QString& name)
if (i == 0) { if (i == 0) {
state = QIcon::Off; state = QIcon::Off;
stateName = "off"; stateName = "off";
} } else {
else {
state = QIcon::On; state = QIcon::On;
stateName = "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; QString filename;
for (int size : pngSizes) { for (int size : pngSizes) {
filename = QString("%1/icons/application/%2x%2/%3-%4.png").arg(m_dataPath, QString::number(size), filename = QString("%1/icons/application/%2x%2/%3-%4.png")
combinedName, stateName); .arg(m_dataPath, QString::number(size), combinedName, stateName);
if (QFile::exists(filename)) { if (QFile::exists(filename)) {
icon.addFile(filename, QSize(size, size), QIcon::Normal, state); icon.addFile(filename, QSize(size, size), QIcon::Normal, state);
} }
@ -229,10 +225,8 @@ FilePath::FilePath()
#endif #endif
#if defined(Q_OS_UNIX) && !(defined(Q_OS_MAC) && defined(WITH_APP_BUNDLE)) #if defined(Q_OS_UNIX) && !(defined(Q_OS_MAC) && defined(WITH_APP_BUNDLE))
else if (isDataDirAbsolute && testSetDir(KEEPASSX_DATA_DIR)) { 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(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(KEEPASSX_PREFIX_DIR, KEEPASSX_DATA_DIR))) {
} }
#endif #endif
#if defined(Q_OS_MAC) && defined(WITH_APP_BUNDLE) #if defined(Q_OS_MAC) && defined(WITH_APP_BUNDLE)
@ -249,8 +243,7 @@ FilePath::FilePath()
if (m_dataPath.isEmpty()) { if (m_dataPath.isEmpty()) {
qWarning("FilePath::DataPath: can't find data dir"); qWarning("FilePath::DataPath: can't find data dir");
} } else {
else {
m_dataPath = QDir::cleanPath(m_dataPath); 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")) { if (QFile::exists(dir + "/icons/database/C00_Password.png")) {
m_dataPath = dir; m_dataPath = dir;
return true; return true;
} } else {
else {
return false; return false;
} }
} }

View file

@ -50,7 +50,8 @@ private:
Q_DISABLE_COPY(FilePath) Q_DISABLE_COPY(FilePath)
}; };
inline FilePath* filePath() { inline FilePath* filePath()
{
return FilePath::instance(); return FilePath::instance();
} }

View file

@ -23,26 +23,30 @@
#include <QtGlobal> #include <QtGlobal>
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
# if defined(KEEPASSX_BUILDING_CORE) #if defined(KEEPASSX_BUILDING_CORE)
# define KEEPASSX_EXPORT Q_DECL_IMPORT #define KEEPASSX_EXPORT Q_DECL_IMPORT
# else
# define KEEPASSX_EXPORT Q_DECL_EXPORT
# endif
#else #else
# define KEEPASSX_EXPORT Q_DECL_EXPORT #define KEEPASSX_EXPORT Q_DECL_EXPORT
#endif
#else
#define KEEPASSX_EXPORT Q_DECL_EXPORT
#endif #endif
#ifndef QUINT32_MAX #ifndef QUINT32_MAX
#define QUINT32_MAX 4294967295U #define QUINT32_MAX 4294967295U
#endif #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) // this adds const to non-const objects (like std::as_const)
template <typename T> template <typename T> constexpr typename AddConst<T>::Type& asConst(T& t) noexcept
constexpr typename AddConst<T>::Type& asConst(T &t) noexcept { return t; } {
return t;
}
// prevent rvalue arguments: // prevent rvalue arguments:
template <typename T> template <typename T> void asConst(const T&&) = delete;
void asConst(const T&&) = delete;
#endif // KEEPASSX_GLOBAL_H #endif // KEEPASSX_GLOBAL_H

View file

@ -27,10 +27,10 @@ const int Group::DefaultIconNumber = 48;
const int Group::RecycleBinIconNumber = 43; const int Group::RecycleBinIconNumber = 43;
const QString Group::RootAutoTypeSequence = "{USERNAME}{TAB}{PASSWORD}{ENTER}"; const QString Group::RootAutoTypeSequence = "{USERNAME}{TAB}{PASSWORD}{ENTER}";
Group::CloneFlags Group::DefaultCloneFlags = static_cast<Group::CloneFlags>( Group::CloneFlags Group::DefaultCloneFlags =
Group::CloneNewUuid | Group::CloneResetTimeInfo | Group::CloneIncludeEntries); static_cast<Group::CloneFlags>(Group::CloneNewUuid | Group::CloneResetTimeInfo | Group::CloneIncludeEntries);
Entry::CloneFlags Group::DefaultEntryCloneFlags = static_cast<Entry::CloneFlags>( Entry::CloneFlags Group::DefaultEntryCloneFlags =
Entry::CloneNewUuid | Entry::CloneResetTimeInfo); static_cast<Entry::CloneFlags>(Entry::CloneNewUuid | Entry::CloneResetTimeInfo);
Group::Group() Group::Group()
: m_customData(new CustomData(this)) : m_customData(new CustomData(this))
@ -81,7 +81,8 @@ Group* Group::createRecycleBin()
return recycleBin; 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) { if (property != value) {
property = value; property = value;
emit modified(); emit modified();
@ -123,14 +124,12 @@ QImage Group::icon() const
{ {
if (m_data.customIcon.isNull()) { if (m_data.customIcon.isNull()) {
return databaseIcons()->icon(m_data.iconNumber); return databaseIcons()->icon(m_data.iconNumber);
} } else {
else {
Q_ASSERT(m_db); Q_ASSERT(m_db);
if (m_db) { if (m_db) {
return m_db->metadata()->customIcon(m_data.customIcon); return m_db->metadata()->customIcon(m_data.customIcon);
} } else {
else {
return QImage(); return QImage();
} }
} }
@ -140,14 +139,12 @@ QPixmap Group::iconPixmap() const
{ {
if (m_data.customIcon.isNull()) { if (m_data.customIcon.isNull()) {
return databaseIcons()->iconPixmap(m_data.iconNumber); return databaseIcons()->iconPixmap(m_data.iconNumber);
} } else {
else {
Q_ASSERT(m_db); Q_ASSERT(m_db);
if (m_db) { if (m_db) {
return m_db->metadata()->customIconPixmap(m_data.customIcon); return m_db->metadata()->customIconPixmap(m_data.customIcon);
} } else {
else {
return QPixmap(); return QPixmap();
} }
} }
@ -158,14 +155,12 @@ QPixmap Group::iconScaledPixmap() const
if (m_data.customIcon.isNull()) { if (m_data.customIcon.isNull()) {
// built-in icons are 16x16 so don't need to be scaled // built-in icons are 16x16 so don't need to be scaled
return databaseIcons()->iconPixmap(m_data.iconNumber); return databaseIcons()->iconPixmap(m_data.iconNumber);
} } else {
else {
Q_ASSERT(m_db); Q_ASSERT(m_db);
if (m_db) { if (m_db) {
return m_db->metadata()->customIconScaledPixmap(m_data.customIcon); return m_db->metadata()->customIconScaledPixmap(m_data.customIcon);
} } else {
else {
return QPixmap(); return QPixmap();
} }
} }
@ -401,9 +396,8 @@ void Group::setParent(Group* parent, int index)
recCreateDelObjects(); recCreateDelObjects();
// copy custom icon to the new database // copy custom icon to the new database
if (!iconUuid().isNull() && parent->m_db if (!iconUuid().isNull() && parent->m_db && m_db->metadata()->containsCustomIcon(iconUuid())
&& m_db->metadata()->containsCustomIcon(iconUuid()) && !parent->m_db->metadata()->containsCustomIcon(iconUuid())) {
&& !parent->m_db->metadata()->containsCustomIcon(iconUuid())) {
parent->m_db->metadata()->addCustomIcon(iconUuid(), icon()); parent->m_db->metadata()->addCustomIcon(iconUuid(), icon());
} }
} }
@ -414,8 +408,7 @@ void Group::setParent(Group* parent, int index)
emit aboutToAdd(this, index); emit aboutToAdd(this, index);
Q_ASSERT(index <= parent->m_children.size()); Q_ASSERT(index <= parent->m_children.size());
parent->m_children.insert(index, this); parent->m_children.insert(index, this);
} } else {
else {
emit aboutToMove(this, parent, index); emit aboutToMove(this, parent, index);
m_parent->m_children.removeAll(this); m_parent->m_children.removeAll(this);
m_parent = parent; m_parent = parent;
@ -432,8 +425,7 @@ void Group::setParent(Group* parent, int index)
if (!moveWithinDatabase) { if (!moveWithinDatabase) {
emit added(); emit added();
} } else {
else {
emit moved(); emit moved();
} }
} }
@ -457,7 +449,7 @@ QStringList Group::hierarchy() const
const Group* group = this; const Group* group = this;
const Group* parent = m_parent; const Group* parent = m_parent;
hierarchy.prepend(group->name()); hierarchy.prepend(group->name());
while (parent) { while (parent) {
group = group->parentGroup(); group = group->parentGroup();
parent = group->parentGroup(); parent = group->parentGroup();
@ -733,7 +725,6 @@ void Group::merge(const Group* other)
resolveGroupConflict(existingGroup, group); resolveGroupConflict(existingGroup, group);
existingGroup->merge(group); existingGroup->merge(group);
} }
} }
emit modified(); emit modified();
@ -849,9 +840,9 @@ void Group::recSetDatabase(Database* db)
disconnect(SIGNAL(dataChanged(Group*)), m_db); disconnect(SIGNAL(dataChanged(Group*)), m_db);
disconnect(SIGNAL(aboutToRemove(Group*)), m_db); disconnect(SIGNAL(aboutToRemove(Group*)), m_db);
disconnect(SIGNAL(removed()), 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(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(moved()), m_db);
disconnect(SIGNAL(modified()), 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(dataChanged(Group*)), db, SIGNAL(groupDataChanged(Group*)));
connect(this, SIGNAL(aboutToRemove(Group*)), db, SIGNAL(groupAboutToRemove(Group*))); connect(this, SIGNAL(aboutToRemove(Group*)), db, SIGNAL(groupAboutToRemove(Group*)));
connect(this, SIGNAL(removed()), db, SIGNAL(groupRemoved())); 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(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(moved()), db, SIGNAL(groupMoved()));
connect(this, SIGNAL(modified()), db, SIGNAL(modifiedImmediate())); connect(this, SIGNAL(modified()), db, SIGNAL(modifiedImmediate()));
} }
@ -910,8 +901,7 @@ void Group::recCreateDelObjects()
void Group::markOlderEntry(Entry* entry) void Group::markOlderEntry(Entry* entry)
{ {
entry->attributes()->set( entry->attributes()->set(
"merged", "merged", tr("older entry merged from database \"%1\"").arg(entry->group()->database()->metadata()->name()));
tr("older entry merged from database \"%1\"").arg(entry->group()->database()->metadata()->name()));
} }
bool Group::resolveSearchingEnabled() const bool Group::resolveSearchingEnabled() const
@ -920,8 +910,7 @@ bool Group::resolveSearchingEnabled() const
case Inherit: case Inherit:
if (!m_parent) { if (!m_parent) {
return true; return true;
} } else {
else {
return m_parent->resolveSearchingEnabled(); return m_parent->resolveSearchingEnabled();
} }
case Enable: case Enable:
@ -940,8 +929,7 @@ bool Group::resolveAutoTypeEnabled() const
case Inherit: case Inherit:
if (!m_parent) { if (!m_parent) {
return true; return true;
} } else {
else {
return m_parent->resolveAutoTypeEnabled(); return m_parent->resolveAutoTypeEnabled();
} }
case Enable: case Enable:
@ -1003,13 +991,12 @@ void Group::resolveGroupConflict(Group* existingGroup, Group* otherGroup)
existingGroup->setName(otherGroup->name()); existingGroup->setName(otherGroup->name());
existingGroup->setNotes(otherGroup->notes()); existingGroup->setNotes(otherGroup->notes());
if (otherGroup->iconNumber() == 0) { if (otherGroup->iconNumber() == 0) {
existingGroup->setIcon(otherGroup->iconUuid()); existingGroup->setIcon(otherGroup->iconUuid());
} else { } else {
existingGroup->setIcon(otherGroup->iconNumber()); existingGroup->setIcon(otherGroup->iconNumber());
} }
existingGroup->setExpiryTime(otherGroup->timeInfo().expiryTime()); existingGroup->setExpiryTime(otherGroup->timeInfo().expiryTime());
} }
} }
QStringList Group::locate(QString locateTerm, QString currentPath) QStringList Group::locate(QString locateTerm, QString currentPath)
@ -1059,5 +1046,4 @@ Entry* Group::addEntryWithPath(QString entryPath)
entry->setGroup(group); entry->setGroup(group);
return entry; return entry;
} }

View file

@ -24,9 +24,9 @@
#include <QPixmapCache> #include <QPixmapCache>
#include <QPointer> #include <QPointer>
#include "core/CustomData.h"
#include "core/Database.h" #include "core/Database.h"
#include "core/Entry.h" #include "core/Entry.h"
#include "core/CustomData.h"
#include "core/TimeInfo.h" #include "core/TimeInfo.h"
#include "core/Uuid.h" #include "core/Uuid.h"
@ -35,14 +35,26 @@ class Group : public QObject
Q_OBJECT Q_OBJECT
public: public:
enum TriState { Inherit, Enable, Disable }; enum TriState
enum MergeMode { ModeInherit, KeepBoth, KeepNewer, KeepExisting }; {
Inherit,
Enable,
Disable
};
enum MergeMode
{
ModeInherit,
KeepBoth,
KeepNewer,
KeepExisting
};
enum CloneFlag { enum CloneFlag
CloneNoFlags = 0, {
CloneNewUuid = 1, // generate a random uuid for the clone CloneNoFlags = 0,
CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time CloneNewUuid = 1, // generate a random uuid for the clone
CloneIncludeEntries = 4, // clone the group entries CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time
CloneIncludeEntries = 4, // clone the group entries
}; };
Q_DECLARE_FLAGS(CloneFlags, CloneFlag) Q_DECLARE_FLAGS(CloneFlags, CloneFlag)

View file

@ -56,9 +56,9 @@ bool InactivityTimer::eventFilter(QObject* watched, QEvent* event)
{ {
const QEvent::Type type = event->type(); const QEvent::Type type = event->type();
if ( (type >= QEvent::MouseButtonPress && type <= QEvent::KeyRelease) if ((type >= QEvent::MouseButtonPress && type <= QEvent::KeyRelease)
|| (type >= QEvent::HoverEnter && type <= QEvent::HoverMove) || (type >= QEvent::HoverEnter && type <= QEvent::HoverMove)
|| (type == QEvent::Wheel) ) { || (type == QEvent::Wheel)) {
m_timer->start(); m_timer->start();
} }

View file

@ -20,12 +20,15 @@
#include <QList> #include <QList>
template <typename T> template <typename T> class ListDeleter
class ListDeleter
{ {
public: public:
inline explicit ListDeleter(QList<T>* list) : m_list(list) {} inline explicit ListDeleter(QList<T>* list)
inline ~ListDeleter() { : m_list(list)
{
}
inline ~ListDeleter()
{
qDeleteAll(*m_list); qDeleteAll(*m_list);
} }

View file

@ -17,9 +17,13 @@
#include "MacPasteboard.h" #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")) { if (mimetype == QLatin1String("text/plain")) {
return QLatin1String("public.utf8-plain-text"); return QLatin1String("public.utf8-plain-text");
} else if (mimetype == QLatin1String("application/x-nspasteboard-concealed-type")) { } else if (mimetype == QLatin1String("application/x-nspasteboard-concealed-type")) {
@ -38,15 +42,15 @@ QString MacPasteboard::flavorFor(const QString& mimetype) {
if (cs == QLatin1String("system")) { if (cs == QLatin1String("system")) {
return QLatin1String("public.utf8-plain-text"); return QLatin1String("public.utf8-plain-text");
} else if (cs == QLatin1String("iso-10646-ucs-2") || } else if (cs == QLatin1String("iso-10646-ucs-2") || cs == QLatin1String("utf16")) {
cs == QLatin1String("utf16")) {
return QLatin1String("public.utf16-plain-text"); return QLatin1String("public.utf16-plain-text");
} }
} }
return QString(); return QString();
} }
QString MacPasteboard::mimeFor(QString flavor) { QString MacPasteboard::mimeFor(QString flavor)
{
if (flavor == QLatin1String("public.utf8-plain-text")) if (flavor == QLatin1String("public.utf8-plain-text"))
return QLatin1String("text/plain"); return QLatin1String("text/plain");
if (flavor == QLatin1String("org.nspasteboard.ConcealedType")) if (flavor == QLatin1String("org.nspasteboard.ConcealedType"))
@ -56,13 +60,15 @@ QString MacPasteboard::mimeFor(QString flavor) {
return QString(); return QString();
} }
bool MacPasteboard::canConvert(const QString& mimetype, QString flavor) { bool MacPasteboard::canConvert(const QString& mimetype, QString flavor)
{
Q_UNUSED(mimetype); Q_UNUSED(mimetype);
Q_UNUSED(flavor); Q_UNUSED(flavor);
return true; 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) if (data.count() > 1)
qWarning("QMime::convertToMime: Cannot handle multiple member data"); qWarning("QMime::convertToMime: Cannot handle multiple member data");
const QByteArray& firstData = data.first(); 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")) { } else if (flavor == QLatin1String("public.utf16-plain-text")) {
ret = QTextCodec::codecForName("UTF-16")->toUnicode(firstData); ret = QTextCodec::codecForName("UTF-16")->toUnicode(firstData);
} else { } else {
qWarning("QMime::convertToMime: unhandled mimetype: %s", qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
qPrintable(mimetype));
} }
return ret; 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; QList<QByteArray> ret;
QString string = data.toString(); QString string = data.toString();
if (flavor == QLatin1String("public.utf8-plain-text")) 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)); ret.append(QTextCodec::codecForName("UTF-16")->fromUnicode(string));
return ret; return ret;
} }

View file

@ -19,20 +19,23 @@
#define KEEPASSXC_MACPASTEBOARD_H #define KEEPASSXC_MACPASTEBOARD_H
#include <QMacPasteboardMime> #include <QMacPasteboardMime>
#include <QTextCodec>
#include <QObject> #include <QObject>
#include <QTextCodec>
class MacPasteboard : public QObject, public QMacPasteboardMime class MacPasteboard : public QObject, public QMacPasteboardMime
{ {
public: public:
explicit MacPasteboard() : QMacPasteboardMime(MIME_ALL) {} explicit MacPasteboard()
: QMacPasteboardMime(MIME_ALL)
{
}
QString convertorName() override; 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 mimeFor(QString flav) override;
QString flavorFor(const QString &mime) override; QString flavorFor(const QString& mime) override;
QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav) override; QVariant convertToMime(const QString& mime, QList<QByteArray> data, QString flav) override;
QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav) override; QList<QByteArray> convertFromMime(const QString& mime, QVariant data, QString flav) override;
}; };
#endif // KEEPASSXC_MACPASTEBOARD_H #endif // KEEPASSXC_MACPASTEBOARD_H

View file

@ -15,8 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <QtCore/QCryptographicHash>
#include "Metadata.h" #include "Metadata.h"
#include <QtCore/QCryptographicHash>
#include "core/Entry.h" #include "core/Entry.h"
#include "core/Group.h" #include "core/Group.h"
@ -61,13 +61,13 @@ template <class P, class V> bool Metadata::set(P& property, const V& value)
property = value; property = value;
emit modified(); emit modified();
return true; return true;
} } else {
else {
return false; 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) { if (property != value) {
property = value; property = value;
if (m_updateDatetime) { if (m_updateDatetime) {
@ -75,8 +75,7 @@ template <class P, class V> bool Metadata::set(P& property, const V& value, QDat
} }
emit modified(); emit modified();
return true; return true;
} } else {
else {
return false; return false;
} }
} }
@ -402,10 +401,8 @@ void Metadata::addCustomIconScaled(const Uuid& uuid, const QImage& icon)
// scale down to 128x128 if icon is larger // scale down to 128x128 if icon is larger
if (icon.width() > 128 || icon.height() > 128) { if (icon.width() > 128 || icon.height() > 128) {
iconScaled = icon.scaled(QSize(128, 128), Qt::KeepAspectRatio, iconScaled = icon.scaled(QSize(128, 128), Qt::KeepAspectRatio, Qt::SmoothTransformation);
Qt::SmoothTransformation); } else {
}
else {
iconScaled = icon; iconScaled = icon;
} }
@ -433,7 +430,7 @@ void Metadata::removeCustomIcon(const Uuid& uuid)
emit modified(); emit modified();
} }
Uuid Metadata::findCustomIcon(const QImage &candidate) Uuid Metadata::findCustomIcon(const QImage& candidate)
{ {
QByteArray hash = hashImage(candidate); QByteArray hash = hashImage(candidate);
return m_customIconsHashes.value(hash, Uuid()); return m_customIconsHashes.value(hash, Uuid());

View file

@ -26,8 +26,8 @@
#include <QPixmapCache> #include <QPixmapCache>
#include <QPointer> #include <QPointer>
#include "core/Uuid.h"
#include "core/CustomData.h" #include "core/CustomData.h"
#include "core/Uuid.h"
class Database; class Database;
class Group; class Group;

View file

@ -17,12 +17,12 @@
#include "PassphraseGenerator.h" #include "PassphraseGenerator.h"
#include <cmath>
#include <QFile> #include <QFile>
#include <QTextStream> #include <QTextStream>
#include <cmath>
#include "crypto/Random.h"
#include "core/FilePath.h" #include "core/FilePath.h"
#include "crypto/Random.h"
const char* PassphraseGenerator::DefaultSeparator = " "; const char* PassphraseGenerator::DefaultSeparator = " ";
const char* PassphraseGenerator::DefaultWordList = "eff_large.wordlist"; const char* PassphraseGenerator::DefaultWordList = "eff_large.wordlist";
@ -52,7 +52,6 @@ void PassphraseGenerator::setWordCount(int wordCount)
// safe default if something goes wrong // safe default if something goes wrong
m_wordCount = DefaultWordCount; m_wordCount = DefaultWordCount;
} }
} }
void PassphraseGenerator::setWordList(const QString& path) void PassphraseGenerator::setWordList(const QString& path)
@ -82,7 +81,8 @@ void PassphraseGenerator::setDefaultWordList()
setWordList(path); setWordList(path);
} }
void PassphraseGenerator::setWordSeparator(const QString& separator) { void PassphraseGenerator::setWordSeparator(const QString& separator)
{
m_separator = separator; m_separator = separator;
} }
@ -91,7 +91,7 @@ QString PassphraseGenerator::generatePassphrase() const
Q_ASSERT(isValid()); Q_ASSERT(isValid());
// In case there was an error loading the wordlist // In case there was an error loading the wordlist
if(m_wordlist.length() == 0) { if (m_wordlist.length() == 0) {
return QString(); return QString();
} }
@ -107,7 +107,7 @@ QString PassphraseGenerator::generatePassphrase() const
bool PassphraseGenerator::isValid() const bool PassphraseGenerator::isValid() const
{ {
if (m_wordCount == 0) { if (m_wordCount == 0) {
return false; return false;
} }
return m_wordlist.size() >= 1000; return m_wordlist.size() >= 1000;

View file

@ -45,7 +45,7 @@ void PasswordGenerator::setLength(int length)
void PasswordGenerator::setCharClasses(const CharClasses& classes) void PasswordGenerator::setCharClasses(const CharClasses& classes)
{ {
if (classes == 0) { if (classes == 0) {
m_classes = DefaultCharset; m_classes = DefaultCharset;
return; return;
} }
m_classes = classes; m_classes = classes;
@ -92,8 +92,7 @@ QString PasswordGenerator::generatePassword() const
password[i] = password[j]; password[i] = password[j];
password[j] = tmp; password[j] = tmp;
} }
} } else {
else {
for (int i = 0; i < m_length; i++) { for (int i = 0; i < m_length; i++) {
int pos = randomGen()->randomUInt(passwordChars.size()); int pos = randomGen()->randomUInt(passwordChars.size());
@ -110,7 +109,7 @@ int PasswordGenerator::getbits() const
int bits = 0; int bits = 0;
QVector<QChar> passwordChars; QVector<QChar> passwordChars;
for (const PasswordGroup& group: groups) { for (const PasswordGroup& group : groups) {
bits += group.size(); bits += group.size();
} }
@ -119,13 +118,11 @@ int PasswordGenerator::getbits() const
return bits; return bits;
} }
bool PasswordGenerator::isValid() const bool PasswordGenerator::isValid() const
{ {
if (m_classes == 0) { if (m_classes == 0) {
return false; return false;
} } else if (m_length == 0) {
else if (m_length == 0) {
return false; return false;
} }

View file

@ -30,20 +30,20 @@ class PasswordGenerator
public: public:
enum CharClass enum CharClass
{ {
LowerLetters = 0x1, LowerLetters = 0x1,
UpperLetters = 0x2, UpperLetters = 0x2,
Numbers = 0x4, Numbers = 0x4,
SpecialCharacters = 0x8, SpecialCharacters = 0x8,
EASCII = 0x10, EASCII = 0x10,
DefaultCharset = LowerLetters | UpperLetters | Numbers DefaultCharset = LowerLetters | UpperLetters | Numbers
}; };
Q_DECLARE_FLAGS(CharClasses, CharClass) Q_DECLARE_FLAGS(CharClasses, CharClass)
enum GeneratorFlag enum GeneratorFlag
{ {
ExcludeLookAlike = 0x1, ExcludeLookAlike = 0x1,
CharFromEveryGroup = 0x2, CharFromEveryGroup = 0x2,
DefaultFlags = ExcludeLookAlike | CharFromEveryGroup DefaultFlags = ExcludeLookAlike | CharFromEveryGroup
}; };
Q_DECLARE_FLAGS(GeneratorFlags, GeneratorFlag) Q_DECLARE_FLAGS(GeneratorFlags, GeneratorFlag)

View file

@ -18,11 +18,13 @@
#include "ScreenLockListener.h" #include "ScreenLockListener.h"
#include "ScreenLockListenerPrivate.h" #include "ScreenLockListenerPrivate.h"
ScreenLockListener::ScreenLockListener(QWidget* parent): ScreenLockListener::ScreenLockListener(QWidget* parent)
QObject(parent){ : QObject(parent)
{
m_listener = ScreenLockListenerPrivate::instance(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()
{
} }

View file

@ -21,7 +21,8 @@
class ScreenLockListenerPrivate; class ScreenLockListenerPrivate;
class ScreenLockListener : public QObject { class ScreenLockListener : public QObject
{
Q_OBJECT Q_OBJECT
public: public:

View file

@ -22,60 +22,54 @@
#include <QDBusReply> #include <QDBusReply>
#include <QProcessEnvironment> #include <QProcessEnvironment>
ScreenLockListenerDBus::ScreenLockListenerDBus(QWidget *parent): ScreenLockListenerDBus::ScreenLockListenerDBus(QWidget* parent)
ScreenLockListenerPrivate(parent) : ScreenLockListenerPrivate(parent)
{ {
QDBusConnection sessionBus = QDBusConnection::sessionBus(); QDBusConnection sessionBus = QDBusConnection::sessionBus();
QDBusConnection systemBus = QDBusConnection::systemBus(); QDBusConnection systemBus = QDBusConnection::systemBus();
sessionBus.connect( sessionBus.connect("org.freedesktop.ScreenSaver", // service
"org.freedesktop.ScreenSaver", // service "/org/freedesktop/ScreenSaver", // path
"/org/freedesktop/ScreenSaver", // path "org.freedesktop.ScreenSaver", // interface
"org.freedesktop.ScreenSaver", // interface "ActiveChanged", // signal name
"ActiveChanged", // signal name this, // receiver
this, //receiver SLOT(freedesktopScreenSaver(bool)));
SLOT(freedesktopScreenSaver(bool)));
sessionBus.connect( sessionBus.connect("org.gnome.ScreenSaver", // service
"org.gnome.ScreenSaver", // service "/org/gnome/ScreenSaver", // path
"/org/gnome/ScreenSaver", // path "org.gnome.ScreenSaver", // interface
"org.gnome.ScreenSaver", // interface "ActiveChanged", // signal name
"ActiveChanged", // signal name this, // receiver
this, //receiver SLOT(freedesktopScreenSaver(bool)));
SLOT(freedesktopScreenSaver(bool)));
sessionBus.connect( sessionBus.connect("org.gnome.SessionManager", // service
"org.gnome.SessionManager", // service "/org/gnome/SessionManager/Presence", // path
"/org/gnome/SessionManager/Presence", // path "org.gnome.SessionManager.Presence", // interface
"org.gnome.SessionManager.Presence", // interface "StatusChanged", // signal name
"StatusChanged", // signal name this, // receiver
this, //receiver SLOT(gnomeSessionStatusChanged(uint)));
SLOT(gnomeSessionStatusChanged(uint)));
systemBus.connect( systemBus.connect("org.freedesktop.login1", // service
"org.freedesktop.login1", // service "/org/freedesktop/login1", // path
"/org/freedesktop/login1", // path "org.freedesktop.login1.Manager", // interface
"org.freedesktop.login1.Manager", // interface "PrepareForSleep", // signal name
"PrepareForSleep", // signal name this, // receiver
this, //receiver SLOT(logindPrepareForSleep(bool)));
SLOT(logindPrepareForSleep(bool)));
QString sessionId = QProcessEnvironment::systemEnvironment().value("XDG_SESSION_ID"); QString sessionId = QProcessEnvironment::systemEnvironment().value("XDG_SESSION_ID");
systemBus.connect( systemBus.connect("", // service
"", // service QString("/org/freedesktop/login1/session/") + sessionId, // path
QString("/org/freedesktop/login1/session/") + sessionId, // path "org.freedesktop.login1.Session", // interface
"org.freedesktop.login1.Session", // interface "Lock", // signal name
"Lock", // signal name this, // receiver
this, //receiver SLOT(unityLocked()));
SLOT(unityLocked()));
sessionBus.connect( sessionBus.connect("com.canonical.Unity", // service
"com.canonical.Unity", // service "/com/canonical/Unity/Session", // path
"/com/canonical/Unity/Session", // path "com.canonical.Unity.Session", // interface
"com.canonical.Unity.Session", // interface "Locked", // signal name
"Locked", // signal name this, // receiver
this, //receiver SLOT(unityLocked()));
SLOT(unityLocked()));
} }
void ScreenLockListenerDBus::gnomeSessionStatusChanged(uint status) void ScreenLockListenerDBus::gnomeSessionStatusChanged(uint status)

View file

@ -17,15 +17,15 @@
#ifndef SCREENLOCKLISTENERDBUS_H #ifndef SCREENLOCKLISTENERDBUS_H
#define SCREENLOCKLISTENERDBUS_H #define SCREENLOCKLISTENERDBUS_H
#include "ScreenLockListenerPrivate.h"
#include <QObject> #include <QObject>
#include <QWidget> #include <QWidget>
#include "ScreenLockListenerPrivate.h"
class ScreenLockListenerDBus : public ScreenLockListenerPrivate class ScreenLockListenerDBus : public ScreenLockListenerPrivate
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ScreenLockListenerDBus(QWidget *parent = 0); explicit ScreenLockListenerDBus(QWidget* parent = 0);
private slots: private slots:
void gnomeSessionStatusChanged(uint status); void gnomeSessionStatusChanged(uint status);

View file

@ -25,7 +25,7 @@
#endif #endif
ScreenLockListenerPrivate::ScreenLockListenerPrivate(QWidget* parent) ScreenLockListenerPrivate::ScreenLockListenerPrivate(QWidget* parent)
: QObject(parent) : QObject(parent)
{ {
} }

View file

@ -25,7 +25,7 @@
* See https://msdn.microsoft.com/en-us/library/aa383841(v=vs.85).aspx * See https://msdn.microsoft.com/en-us/library/aa383841(v=vs.85).aspx
* See https://blogs.msdn.microsoft.com/oldnewthing/20060104-50/?p=32783 * See https://blogs.msdn.microsoft.com/oldnewthing/20060104-50/?p=32783
*/ */
ScreenLockListenerWin::ScreenLockListenerWin(QWidget* parent) ScreenLockListenerWin::ScreenLockListenerWin(QWidget* parent)
: ScreenLockListenerPrivate(parent) : ScreenLockListenerPrivate(parent)
, QAbstractNativeEventFilter() , QAbstractNativeEventFilter()
{ {
@ -36,20 +36,17 @@ ScreenLockListenerWin::ScreenLockListenerWin(QWidget* parent)
// This call requests a notification from windows when a laptop is closed // This call requests a notification from windows when a laptop is closed
HPOWERNOTIFY hPnotify = RegisterPowerSettingNotification( HPOWERNOTIFY hPnotify = RegisterPowerSettingNotification(
reinterpret_cast<HWND>(parent->winId()), reinterpret_cast<HWND>(parent->winId()), &GUID_LIDSWITCH_STATE_CHANGE, DEVICE_NOTIFY_WINDOW_HANDLE);
&GUID_LIDSWITCH_STATE_CHANGE, DEVICE_NOTIFY_WINDOW_HANDLE);
m_powerNotificationHandle = reinterpret_cast<void*>(hPnotify); m_powerNotificationHandle = reinterpret_cast<void*>(hPnotify);
// This call requests a notification for session changes // This call requests a notification for session changes
if (!WTSRegisterSessionNotification( if (!WTSRegisterSessionNotification(reinterpret_cast<HWND>(parent->winId()), NOTIFY_FOR_THIS_SESSION)) {
reinterpret_cast<HWND>(parent->winId()),
NOTIFY_FOR_THIS_SESSION)) {
} }
} }
ScreenLockListenerWin::~ScreenLockListenerWin() ScreenLockListenerWin::~ScreenLockListenerWin()
{ {
HWND h= reinterpret_cast<HWND>(static_cast<QWidget*>(parent())->winId()); HWND h = reinterpret_cast<HWND>(static_cast<QWidget*>(parent())->winId());
WTSUnRegisterSessionNotification(h); WTSUnRegisterSessionNotification(h);
if (m_powerNotificationHandle) { if (m_powerNotificationHandle) {

View file

@ -17,9 +17,9 @@
#ifndef SCREENLOCKLISTENERWIN_H #ifndef SCREENLOCKLISTENERWIN_H
#define SCREENLOCKLISTENERWIN_H #define SCREENLOCKLISTENERWIN_H
#include <QAbstractNativeEventFilter>
#include <QObject> #include <QObject>
#include <QWidget> #include <QWidget>
#include <QAbstractNativeEventFilter>
#include "ScreenLockListenerPrivate.h" #include "ScreenLockListenerPrivate.h"
@ -29,10 +29,10 @@ class ScreenLockListenerWin : public ScreenLockListenerPrivate, public QAbstract
public: public:
explicit ScreenLockListenerWin(QWidget* parent = 0); explicit ScreenLockListenerWin(QWidget* parent = 0);
~ScreenLockListenerWin(); ~ScreenLockListenerWin();
virtual bool nativeEventFilter(const QByteArray &eventType, void* message, long*) override; virtual bool nativeEventFilter(const QByteArray& eventType, void* message, long*) override;
private: private:
void* m_powerNotificationHandle ; void* m_powerNotificationHandle;
}; };
#endif // SCREENLOCKLISTENERWIN_H #endif // SCREENLOCKLISTENERWIN_H

View file

@ -131,8 +131,7 @@ void SignalMultiplexer::connect(const Connection& con)
if (con.sender) { if (con.sender) {
QObject::connect(con.sender, con.signal, m_currentObject, con.slot); QObject::connect(con.sender, con.signal, m_currentObject, con.slot);
} } else {
else {
QObject::connect(m_currentObject, con.signal, con.receiver, con.slot); QObject::connect(m_currentObject, con.signal, con.receiver, con.slot);
} }
} }
@ -143,8 +142,7 @@ void SignalMultiplexer::disconnect(const Connection& con)
if (con.sender) { if (con.sender) {
QObject::disconnect(con.sender, con.signal, m_currentObject, con.slot); QObject::disconnect(con.sender, con.signal, m_currentObject, con.slot);
} } else {
else {
QObject::disconnect(m_currentObject, con.signal, con.receiver, con.slot); QObject::disconnect(m_currentObject, con.signal, con.receiver, con.slot);
} }
} }

View file

@ -19,10 +19,9 @@
#include <QDateTime> #include <QDateTime>
QDateTime operator+(const QDateTime& dateTime, const TimeDelta& delta) { QDateTime operator+(const QDateTime& dateTime, const TimeDelta& delta)
return dateTime.addDays(delta.getDays()) {
.addMonths(delta.getMonths()) return dateTime.addDays(delta.getDays()).addMonths(delta.getMonths()).addYears(delta.getYears());
.addYears(delta.getYears());
} }
TimeDelta TimeDelta::fromDays(int days) TimeDelta TimeDelta::fromDays(int days)

View file

@ -20,16 +20,16 @@
#include "Tools.h" #include "Tools.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QImageReader>
#include <QIODevice> #include <QIODevice>
#include <QImageReader>
#include <QLocale> #include <QLocale>
#include <QStringList> #include <QStringList>
#include <QElapsedTimer> #include <QElapsedTimer>
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <aclapi.h> // for SetSecurityInfo()
#include <windows.h> // for Sleep(), SetDllDirectoryA(), SetSearchPathMode(), ... #include <windows.h> // for Sleep(), SetDllDirectoryA(), SetSearchPathMode(), ...
#include <aclapi.h> // for SetSecurityInfo()
#endif #endif
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
@ -47,314 +47,298 @@
#endif #endif
#ifdef HAVE_PT_DENY_ATTACH #ifdef HAVE_PT_DENY_ATTACH
#include <sys/types.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <sys/types.h>
#endif #endif
namespace Tools { namespace Tools
QString humanReadableFileSize(qint64 bytes)
{ {
double size = bytes;
QStringList units = QStringList() << "B" << "KiB" << "MiB" << "GiB"; QString humanReadableFileSize(qint64 bytes)
int i = 0; {
int maxI = units.size() - 1; double size = bytes;
while ((size >= 1024) && (i < maxI)) { QStringList units = QStringList() << "B"
size /= 1024; << "KiB"
i++; << "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) const QObjectList children = parent->children();
{ for (QObject* c : children) {
if (!parent || !child) { if (child == c || hasChild(c, child)) {
return true;
}
}
return false; return false;
} }
const QObjectList children = parent->children(); bool readFromDevice(QIODevice* device, QByteArray& data, int size)
for (QObject* c : children) { {
if (child == c || hasChild(c, child)) { 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 true;
} }
} }
return false;
}
bool readFromDevice(QIODevice* device, QByteArray& data, int size) bool readAllFromDevice(QIODevice* device, QByteArray& data)
{ {
QByteArray buffer; QByteArray result;
buffer.resize(size); 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) {
if (readResult == -1) { return false;
return false; } else {
} result.resize(static_cast<int>(readBytes));
else { data = result;
buffer.resize(readResult); return true;
data = buffer;
return true;
}
}
bool readAllFromDevice(QIODevice* device, QByteArray& data)
{
QByteArray result;
qint64 readBytes = 0;
qint64 readResult;
do {
result.resize(result.size() + 16384);
readResult = device->read(result.data() + readBytes, result.size() - readBytes);
if (readResult > 0) {
readBytes += readResult;
} }
} while (readResult > 0);
if (readResult == -1) {
return false;
} }
else {
result.resize(static_cast<int>(readBytes)); QString imageReaderFilter()
data = result; {
return true; 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() bool isHex(const QByteArray& ba)
{ {
const QList<QByteArray> formats = QImageReader::supportedImageFormats(); for (char c : ba) {
QStringList formatsStringList; if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) {
return false;
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 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) QString base64 = QString::fromLatin1(ba.constData(), ba.size());
{
for (char c : ba) { return regexp.exactMatch(base64);
if ( !( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) ) { }
return false;
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 #ifdef Q_OS_WIN
Sleep(uint(ms)); Sleep(uint(ms));
#else #else
timespec ts; timespec ts;
ts.tv_sec = ms / 1000; ts.tv_sec = ms / 1000;
ts.tv_nsec = (ms % 1000) * 1000 * 1000; ts.tv_nsec = (ms % 1000) * 1000 * 1000;
nanosleep(&ts, nullptr); nanosleep(&ts, nullptr);
#endif #endif
}
void wait(int ms)
{
Q_ASSERT(ms >= 0);
if (ms == 0) {
return;
} }
QElapsedTimer timer; void wait(int ms)
timer.start(); {
Q_ASSERT(ms >= 0);
if (ms <= 50) { if (ms == 0) {
QCoreApplication::processEvents(QEventLoop::AllEvents, ms); return;
sleep(qMax(ms - static_cast<int>(timer.elapsed()), 0)); }
}
else {
int timeLeft;
do {
timeLeft = ms - timer.elapsed();
if (timeLeft > 0) {
QCoreApplication::processEvents(QEventLoop::AllEvents, timeLeft);
sleep(10);
}
} while (!timer.hasExpired(ms));
}
}
void disableCoreDumps() QElapsedTimer timer;
{ timer.start();
// default to true
// there is no point in printing a warning if this is not implemented on the platform if (ms <= 50) {
bool success = true; 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) #if defined(HAVE_RLIMIT_CORE)
struct rlimit limit; struct rlimit limit;
limit.rlim_cur = 0; limit.rlim_cur = 0;
limit.rlim_max = 0; limit.rlim_max = 0;
success = success && (setrlimit(RLIMIT_CORE, &limit) == 0); success = success && (setrlimit(RLIMIT_CORE, &limit) == 0);
#endif #endif
#if defined(HAVE_PR_SET_DUMPABLE) #if defined(HAVE_PR_SET_DUMPABLE)
success = success && (prctl(PR_SET_DUMPABLE, 0) == 0); success = success && (prctl(PR_SET_DUMPABLE, 0) == 0);
#endif #endif
// Mac OS X // Mac OS X
#ifdef HAVE_PT_DENY_ATTACH #ifdef HAVE_PT_DENY_ATTACH
success = success && (ptrace(PT_DENY_ATTACH, 0, 0, 0) == 0); success = success && (ptrace(PT_DENY_ATTACH, 0, 0, 0) == 0);
#endif #endif
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
success = success && createWindowsDACL(); success = success && createWindowsDACL();
#endif #endif
if (!success) { if (!success) {
qWarning("Unable to disable core dumps."); qWarning("Unable to disable core dumps.");
}
} }
}
void setupSearchPaths() void setupSearchPaths()
{ {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
// Make sure Windows doesn't load DLLs from the current working directory // Make sure Windows doesn't load DLLs from the current working directory
SetDllDirectoryA(""); SetDllDirectoryA("");
SetSearchPathMode(BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE); SetSearchPathMode(BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE);
#endif #endif
} }
// //
// This function grants the user associated with the process token minimal access rights and // This function grants the user associated with the process token minimal access rights and
// denies everything else on Windows. This includes PROCESS_QUERY_INFORMATION and // denies everything else on Windows. This includes PROCESS_QUERY_INFORMATION and
// PROCESS_VM_READ access rights that are required for MiniDumpWriteDump() or ReadProcessMemory(). // PROCESS_VM_READ access rights that are required for MiniDumpWriteDump() or ReadProcessMemory().
// We do this using a discretionary access control list (DACL). Effectively this prevents // We do this using a discretionary access control list (DACL). Effectively this prevents
// crash dumps and disallows other processes from accessing our memory. This works as long // crash dumps and disallows other processes from accessing our memory. This works as long
// as you do not have admin privileges, since then you are able to grant yourself the // as you do not have admin privileges, since then you are able to grant yourself the
// SeDebugPrivilege or SeTakeOwnershipPrivilege and circumvent the DACL. // SeDebugPrivilege or SeTakeOwnershipPrivilege and circumvent the DACL.
// //
bool createWindowsDACL() bool createWindowsDACL()
{ {
bool bSuccess = false; bool bSuccess = false;
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
// Process token and user // Process token and user
HANDLE hToken = nullptr; HANDLE hToken = nullptr;
PTOKEN_USER pTokenUser = nullptr; PTOKEN_USER pTokenUser = nullptr;
DWORD cbBufferSize = 0; DWORD cbBufferSize = 0;
// Access control list // Access control list
PACL pACL = nullptr; PACL pACL = nullptr;
DWORD cbACL = 0; DWORD cbACL = 0;
// Open the access token associated with the calling process // Open the access token associated with the calling process
if (!OpenProcessToken( if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
GetCurrentProcess(), goto Cleanup;
TOKEN_QUERY, }
&hToken
)) {
goto Cleanup;
}
// Retrieve the token information in a TOKEN_USER structure // Retrieve the token information in a TOKEN_USER structure
GetTokenInformation( GetTokenInformation(hToken, TokenUser, nullptr, 0, &cbBufferSize);
hToken,
TokenUser,
nullptr,
0,
&cbBufferSize
);
pTokenUser = static_cast<PTOKEN_USER>(HeapAlloc(GetProcessHeap(), 0, cbBufferSize)); pTokenUser = static_cast<PTOKEN_USER>(HeapAlloc(GetProcessHeap(), 0, cbBufferSize));
if (pTokenUser == nullptr) { if (pTokenUser == nullptr) {
goto Cleanup; goto Cleanup;
} }
if (!GetTokenInformation( if (!GetTokenInformation(hToken, TokenUser, pTokenUser, cbBufferSize, &cbBufferSize)) {
hToken, goto Cleanup;
TokenUser, }
pTokenUser,
cbBufferSize,
&cbBufferSize
)) {
goto Cleanup;
}
if (!IsValidSid(pTokenUser->User.Sid)) { if (!IsValidSid(pTokenUser->User.Sid)) {
goto Cleanup; goto Cleanup;
} }
// Calculate the amount of memory that must be allocated for the DACL // Calculate the amount of memory that must be allocated for the DACL
cbACL = sizeof(ACL) cbACL = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid);
+ sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid);
// Create and initialize an ACL // Create and initialize an ACL
pACL = static_cast<PACL>(HeapAlloc(GetProcessHeap(), 0, cbACL)); pACL = static_cast<PACL>(HeapAlloc(GetProcessHeap(), 0, cbACL));
if (pACL == nullptr) { if (pACL == nullptr) {
goto Cleanup; goto Cleanup;
} }
if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) { if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) {
goto Cleanup; goto Cleanup;
} }
// Add allowed access control entries, everything else is denied // Add allowed access control entries, everything else is denied
if (!AddAccessAllowedAce( if (!AddAccessAllowedAce(
pACL, pACL,
ACL_REVISION, ACL_REVISION,
SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE, // same as protected process SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE, // same as protected process
pTokenUser->User.Sid // pointer to the trustee's SID pTokenUser->User.Sid // pointer to the trustee's SID
)) { )) {
goto Cleanup; goto Cleanup;
} }
// Set discretionary access control list // Set discretionary access control list
bSuccess = ERROR_SUCCESS == SetSecurityInfo( bSuccess = ERROR_SUCCESS == SetSecurityInfo(GetCurrentProcess(), // object handle
GetCurrentProcess(), // object handle SE_KERNEL_OBJECT, // type of object
SE_KERNEL_OBJECT, // type of object DACL_SECURITY_INFORMATION, // change only the objects DACL
DACL_SECURITY_INFORMATION, // change only the objects DACL nullptr,
nullptr, nullptr, // do not change owner or group nullptr, // do not change owner or group
pACL, // DACL specified pACL, // DACL specified
nullptr // do not change SACL nullptr // do not change SACL
); );
Cleanup: Cleanup:
if (pACL != nullptr) { if (pACL != nullptr) {
HeapFree(GetProcessHeap(), 0, pACL); HeapFree(GetProcessHeap(), 0, pACL);
} }
if (pTokenUser != nullptr) { if (pTokenUser != nullptr) {
HeapFree(GetProcessHeap(), 0, pTokenUser); HeapFree(GetProcessHeap(), 0, pTokenUser);
} }
if (hToken != nullptr) { if (hToken != nullptr) {
CloseHandle(hToken); CloseHandle(hToken);
} }
#endif #endif
return bSuccess; return bSuccess;
} }
} // namespace Tools } // namespace Tools

View file

@ -29,33 +29,33 @@
class QIODevice; class QIODevice;
namespace Tools { 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)
{ {
RandomAccessIterator it = std::lower_bound(begin, end, value);
if ((it == end) || (value < *it)) { QString humanReadableFileSize(qint64 bytes);
return end; 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 } // namespace Tools

View file

@ -22,8 +22,8 @@
#include <QDir> #include <QDir>
#include <QLibraryInfo> #include <QLibraryInfo>
#include <QLocale> #include <QLocale>
#include <QTranslator>
#include <QRegularExpression> #include <QRegularExpression>
#include <QTranslator>
#include "config-keepassx.h" #include "config-keepassx.h"
#include "core/Config.h" #include "core/Config.h"
@ -47,8 +47,7 @@ void Translator::installTranslators()
#ifdef QT_DEBUG #ifdef QT_DEBUG
QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR), QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR),
#endif #endif
filePath()->dataPath("translations") filePath()->dataPath("translations")};
};
bool translationsLoaded = false; bool translationsLoaded = false;
for (const QString& path : paths) { for (const QString& path : paths) {
@ -72,10 +71,9 @@ QList<QPair<QString, QString>> Translator::availableLanguages()
#ifdef QT_DEBUG #ifdef QT_DEBUG
QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR), QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR),
#endif #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")); languages.append(QPair<QString, QString>("system", "System default"));
QRegularExpression regExp("^keepassx_([a-zA-Z_]+)\\.qm$", QRegularExpression::CaseInsensitiveOption); 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)); QScopedPointer<QTranslator> qtTranslator(new QTranslator(qApp));
if (qtTranslator->load(QString("qtbase_%1").arg(language), path)) { if (qtTranslator->load(QString("qtbase_%1").arg(language), path)) {
return QCoreApplication::installTranslator(qtTranslator.take()); 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 QCoreApplication::installTranslator(qtTranslator.take());
} }
return false; return false;

View file

@ -22,8 +22,8 @@
#include "crypto/Random.h" #include "crypto/Random.h"
const int Uuid::Length = 16; const int Uuid::Length = 16;
const QRegExp Uuid::HexRegExp = QRegExp(QString("^[0-9A-F]{%1}$").arg(QString::number(Uuid::Length * 2)), const QRegExp Uuid::HexRegExp =
Qt::CaseInsensitive); QRegExp(QString("^[0-9A-F]{%1}$").arg(QString::number(Uuid::Length * 2)), Qt::CaseInsensitive);
Uuid::Uuid() Uuid::Uuid()
: m_data(Length, 0) : m_data(Length, 0)
@ -120,5 +120,5 @@ QDataStream& operator>>(QDataStream& stream, Uuid& uuid)
bool Uuid::isUuid(const QString& uuid) bool Uuid::isUuid(const QString& uuid)
{ {
return Uuid::HexRegExp.exactMatch(uuid); return Uuid::HexRegExp.exactMatch(uuid);
} }

View file

@ -19,8 +19,8 @@
#define KEEPASSX_UUID_H #define KEEPASSX_UUID_H
#include <QByteArray> #include <QByteArray>
#include <QString>
#include <QRegExp> #include <QRegExp>
#include <QString>
class Uuid class Uuid
{ {

View file

@ -116,7 +116,8 @@ bool Crypto::checkAlgorithms()
bool Crypto::selfTest() 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) void Crypto::raiseError(const QString& str)
@ -127,8 +128,8 @@ void Crypto::raiseError(const QString& str)
bool Crypto::testSha256() bool Crypto::testSha256()
{ {
QByteArray sha256Test = CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", QByteArray sha256Test =
CryptoHash::Sha256); CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", CryptoHash::Sha256);
if (sha256Test != QByteArray::fromHex("248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1")) { if (sha256Test != QByteArray::fromHex("248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1")) {
raiseError("SHA-256 mismatch."); raiseError("SHA-256 mismatch.");
@ -140,10 +141,11 @@ bool Crypto::testSha256()
bool Crypto::testSha512() bool Crypto::testSha512()
{ {
QByteArray sha512Test = CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", QByteArray sha512Test =
CryptoHash::Sha512); CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", CryptoHash::Sha512);
if (sha512Test != QByteArray::fromHex("204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445")) { if (sha512Test != QByteArray::fromHex("204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b"
"07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445")) {
raiseError("SHA-512 mismatch."); raiseError("SHA-512 mismatch.");
return false; return false;
} }
@ -262,7 +264,6 @@ bool Crypto::testTwofish()
return false; return false;
} }
SymmetricCipher twofishDecrypt(SymmetricCipher::Twofish, SymmetricCipher::Cbc, SymmetricCipher::Decrypt); SymmetricCipher twofishDecrypt(SymmetricCipher::Twofish, SymmetricCipher::Cbc, SymmetricCipher::Decrypt);
if (!twofishDecrypt.init(key, iv)) { if (!twofishDecrypt.init(key, iv)) {
raiseError(twofishEncrypt.errorString()); raiseError(twofishEncrypt.errorString());
@ -289,8 +290,7 @@ bool Crypto::testSalsa20()
QByteArray salsa20Cipher = QByteArray::fromHex("B4C0AFA503BE7FC29A62058166D56F8F"); QByteArray salsa20Cipher = QByteArray::fromHex("B4C0AFA503BE7FC29A62058166D56F8F");
bool ok; bool ok;
SymmetricCipher salsa20Stream(SymmetricCipher::Salsa20, SymmetricCipher::Stream, SymmetricCipher salsa20Stream(SymmetricCipher::Salsa20, SymmetricCipher::Stream, SymmetricCipher::Encrypt);
SymmetricCipher::Encrypt);
if (!salsa20Stream.init(salsa20Key, salsa20iv)) { if (!salsa20Stream.init(salsa20Key, salsa20iv)) {
raiseError(salsa20Stream.errorString()); raiseError(salsa20Stream.errorString());
return false; return false;
@ -309,15 +309,17 @@ bool Crypto::testSalsa20()
return true; return true;
} }
bool Crypto::testChaCha20() { bool Crypto::testChaCha20()
{
QByteArray chacha20Key = QByteArray::fromHex("0000000000000000000000000000000000000000000000000000000000000000"); QByteArray chacha20Key = QByteArray::fromHex("0000000000000000000000000000000000000000000000000000000000000000");
QByteArray chacha20iv = QByteArray::fromHex("0000000000000000"); QByteArray chacha20iv = QByteArray::fromHex("0000000000000000");
QByteArray chacha20Plain = QByteArray::fromHex("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); QByteArray chacha20Plain = QByteArray::fromHex("0000000000000000000000000000000000000000000000000000000000000000000"
QByteArray chacha20Cipher = QByteArray::fromHex("76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586"); "0000000000000000000000000000000000000000000000000000000000000");
QByteArray chacha20Cipher = QByteArray::fromHex("76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da"
"41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586");
bool ok; bool ok;
SymmetricCipher chacha20Stream(SymmetricCipher::ChaCha20, SymmetricCipher::Stream, SymmetricCipher chacha20Stream(SymmetricCipher::ChaCha20, SymmetricCipher::Stream, SymmetricCipher::Encrypt);
SymmetricCipher::Encrypt);
if (!chacha20Stream.init(chacha20Key, chacha20iv)) { if (!chacha20Stream.init(chacha20Key, chacha20iv)) {
raiseError(chacha20Stream.errorString()); raiseError(chacha20Stream.errorString());
return false; return false;

View file

@ -89,7 +89,6 @@ Random::Random(RandomBackend* backend)
{ {
} }
void RandomBackendGcrypt::randomize(void* data, int len) void RandomBackendGcrypt::randomize(void* data, int len)
{ {
Q_ASSERT(Crypto::initalized()); Q_ASSERT(Crypto::initalized());

View file

@ -25,7 +25,9 @@ class RandomBackend
{ {
public: public:
virtual void randomize(void* data, int len) = 0; virtual void randomize(void* data, int len) = 0;
virtual ~RandomBackend() {} virtual ~RandomBackend()
{
}
}; };
class Random class Random
@ -56,7 +58,8 @@ private:
Q_DISABLE_COPY(Random) Q_DISABLE_COPY(Random)
}; };
inline Random* randomGen() { inline Random* randomGen()
{
return Random::instance(); return Random::instance();
} }

View file

@ -22,9 +22,9 @@
#include <QScopedPointer> #include <QScopedPointer>
#include <QString> #include <QString>
#include "core/Uuid.h"
#include "crypto/SymmetricCipherBackend.h" #include "crypto/SymmetricCipherBackend.h"
#include "format/KeePass2.h" #include "format/KeePass2.h"
#include "core/Uuid.h"
class SymmetricCipher class SymmetricCipher
{ {

View file

@ -23,7 +23,9 @@
class SymmetricCipherBackend class SymmetricCipherBackend
{ {
public: public:
virtual ~SymmetricCipherBackend() {} virtual ~SymmetricCipherBackend()
{
}
virtual bool init() = 0; virtual bool init() = 0;
virtual bool setKey(const QByteArray& key) = 0; virtual bool setKey(const QByteArray& key) = 0;
virtual bool setIv(const QByteArray& iv) = 0; virtual bool setIv(const QByteArray& iv) = 0;

View file

@ -20,7 +20,8 @@
#include "config-keepassx.h" #include "config-keepassx.h"
#include "crypto/Crypto.h" #include "crypto/Crypto.h"
SymmetricCipherGcrypt::SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode, SymmetricCipherGcrypt::SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo,
SymmetricCipher::Mode mode,
SymmetricCipher::Direction direction) SymmetricCipher::Direction direction)
: m_ctx(nullptr) : m_ctx(nullptr)
, m_algo(gcryptAlgo(algo)) , m_algo(gcryptAlgo(algo))
@ -84,8 +85,8 @@ void SymmetricCipherGcrypt::setErrorString(gcry_error_t err)
const char* gcryptError = gcry_strerror(err); const char* gcryptError = gcry_strerror(err);
const char* gcryptErrorSource = gcry_strsource(err); const char* gcryptErrorSource = gcry_strsource(err);
m_errorString = QString("%1/%2").arg(QString::fromLocal8Bit(gcryptErrorSource), m_errorString =
QString::fromLocal8Bit(gcryptError)); QString("%1/%2").arg(QString::fromLocal8Bit(gcryptErrorSource), QString::fromLocal8Bit(gcryptError));
} }
bool SymmetricCipherGcrypt::init() bool SymmetricCipherGcrypt::init()
@ -94,7 +95,7 @@ bool SymmetricCipherGcrypt::init()
gcry_error_t error; gcry_error_t error;
if(m_ctx != nullptr) if (m_ctx != nullptr)
gcry_cipher_close(m_ctx); gcry_cipher_close(m_ctx);
error = gcry_cipher_open(&m_ctx, m_algo, m_mode, 0); error = gcry_cipher_open(&m_ctx, m_algo, m_mode, 0);
if (error != 0) { if (error != 0) {

View file

@ -23,10 +23,11 @@
#include "crypto/SymmetricCipher.h" #include "crypto/SymmetricCipher.h"
#include "crypto/SymmetricCipherBackend.h" #include "crypto/SymmetricCipherBackend.h"
class SymmetricCipherGcrypt: public SymmetricCipherBackend class SymmetricCipherGcrypt : public SymmetricCipherBackend
{ {
public: public:
SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode, SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo,
SymmetricCipher::Mode mode,
SymmetricCipher::Direction direction); SymmetricCipher::Direction direction);
~SymmetricCipherGcrypt(); ~SymmetricCipherGcrypt();

View file

@ -31,4 +31,4 @@
#include <argon2.h> #include <argon2.h>
#endif //KEEPASSXC_CRYPTO_ARGON2_H #endif // KEEPASSXC_CRYPTO_ARGON2_H

View file

@ -19,8 +19,8 @@
#include <QtConcurrent> #include <QtConcurrent>
#include "format/KeePass2.h"
#include "crypto/CryptoHash.h" #include "crypto/CryptoHash.h"
#include "format/KeePass2.h"
AesKdf::AesKdf() AesKdf::AesKdf()
: Kdf::Kdf(KeePass2::KDF_AES_KDBX4) : Kdf::Kdf(KeePass2::KDF_AES_KDBX4)
@ -35,7 +35,7 @@ AesKdf::AesKdf(bool legacyKdbx3)
{ {
} }
bool AesKdf::processParameters(const QVariantMap &p) bool AesKdf::processParameters(const QVariantMap& p)
{ {
bool ok; bool ok;
int rounds = p.value(KeePass2::KDFPARAM_AES_ROUNDS).toInt(&ok); int rounds = p.value(KeePass2::KDFPARAM_AES_ROUNDS).toInt(&ok);
@ -84,8 +84,7 @@ bool AesKdf::transform(const QByteArray& raw, QByteArray& result) const
bool AesKdf::transformKeyRaw(const QByteArray& key, const QByteArray& seed, int rounds, QByteArray* result) bool AesKdf::transformKeyRaw(const QByteArray& key, const QByteArray& seed, int rounds, QByteArray* result)
{ {
QByteArray iv(16, 0); QByteArray iv(16, 0);
SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Ecb, SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Ecb, SymmetricCipher::Encrypt);
SymmetricCipher::Encrypt);
if (!cipher.init(seed, iv)) { if (!cipher.init(seed, iv)) {
qWarning("AesKdf::transformKeyRaw: error in SymmetricCipher::init: %s", cipher.errorString().toUtf8().data()); qWarning("AesKdf::transformKeyRaw: error in SymmetricCipher::init: %s", cipher.errorString().toUtf8().data());
return false; return false;

View file

@ -20,7 +20,7 @@
#include "Kdf.h" #include "Kdf.h"
class AesKdf: public Kdf class AesKdf : public Kdf
{ {
public: public:
AesKdf(); AesKdf();
@ -35,10 +35,8 @@ protected:
int benchmarkImpl(int msec) const override; int benchmarkImpl(int msec) const override;
private: private:
static bool transformKeyRaw(const QByteArray& key, static bool
const QByteArray& seed, transformKeyRaw(const QByteArray& key, const QByteArray& seed, int rounds, QByteArray* result) Q_REQUIRED_RESULT;
int rounds,
QByteArray* result) Q_REQUIRED_RESULT;
}; };
#endif // KEEPASSX_AESKDF_H #endif // KEEPASSX_AESKDF_H

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