Merge branch 'master' into develop
This commit is contained in:
@@ -275,6 +275,7 @@ bool Database::writeDatabase(QIODevice* device, QString* error)
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray oldTransformedKey = m_data.transformedMasterKey;
|
||||
KeePass2Writer writer;
|
||||
setEmitModified(false);
|
||||
writer.writeDatabase(device, this);
|
||||
@@ -287,6 +288,15 @@ bool Database::writeDatabase(QIODevice* device, QString* error)
|
||||
return false;
|
||||
}
|
||||
|
||||
Q_ASSERT(!m_data.transformedMasterKey.isEmpty());
|
||||
Q_ASSERT(m_data.transformedMasterKey != oldTransformedKey);
|
||||
if (m_data.transformedMasterKey.isEmpty() || m_data.transformedMasterKey == oldTransformedKey) {
|
||||
if (error) {
|
||||
*error = tr("Key not transformed. This is a bug, please report it to the developers!");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
markAsClean();
|
||||
return true;
|
||||
}
|
||||
@@ -307,16 +317,18 @@ bool Database::extract(QByteArray& xmlOutput, QString* error)
|
||||
|
||||
/**
|
||||
* Remove the old backup and replace it with a new one
|
||||
* backups are named <filename>.old.kdbx
|
||||
* backups are named <filename>.old.<extension>
|
||||
*
|
||||
* @param filePath Path to the file to backup
|
||||
* @return true on success
|
||||
*/
|
||||
bool Database::backupDatabase(const QString& filePath)
|
||||
{
|
||||
QString backupFilePath = filePath;
|
||||
auto re = QRegularExpression("\\.kdbx$|(?<!\\.kdbx)$", QRegularExpression::CaseInsensitiveOption);
|
||||
backupFilePath.replace(re, ".old.kdbx");
|
||||
static auto re = QRegularExpression("(\\.[^.]+)$");
|
||||
|
||||
auto match = re.match(filePath);
|
||||
auto backupFilePath = filePath;
|
||||
backupFilePath = backupFilePath.replace(re, "") + ".old" + match.captured(1);
|
||||
QFile::remove(backupFilePath);
|
||||
return QFile::copy(filePath, backupFilePath);
|
||||
}
|
||||
@@ -512,9 +524,13 @@ void Database::setCompressionAlgorithm(Database::CompressionAlgorithm algo)
|
||||
* @param key key to set and transform or nullptr to reset the key
|
||||
* @param updateChangedTime true to update database change time
|
||||
* @param updateTransformSalt true to update the transform salt
|
||||
* @param transformKey trigger the KDF after setting the key
|
||||
* @return true on success
|
||||
*/
|
||||
bool Database::setKey(const QSharedPointer<const CompositeKey>& key, bool updateChangedTime, bool updateTransformSalt)
|
||||
bool Database::setKey(const QSharedPointer<const CompositeKey>& key,
|
||||
bool updateChangedTime,
|
||||
bool updateTransformSalt,
|
||||
bool transformKey)
|
||||
{
|
||||
Q_ASSERT(!m_data.isReadOnly);
|
||||
|
||||
@@ -532,7 +548,9 @@ bool Database::setKey(const QSharedPointer<const CompositeKey>& key, bool update
|
||||
|
||||
QByteArray oldTransformedMasterKey = m_data.transformedMasterKey;
|
||||
QByteArray transformedMasterKey;
|
||||
if (!key->transform(*m_data.kdf, transformedMasterKey)) {
|
||||
if (!transformKey) {
|
||||
transformedMasterKey = oldTransformedMasterKey;
|
||||
} else if (!key->transform(*m_data.kdf, transformedMasterKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,8 @@ public:
|
||||
QSharedPointer<const CompositeKey> key() const;
|
||||
bool setKey(const QSharedPointer<const CompositeKey>& key,
|
||||
bool updateChangedTime = true,
|
||||
bool updateTransformSalt = false);
|
||||
bool updateTransformSalt = false,
|
||||
bool transformKey = true);
|
||||
QByteArray challengeResponseKey() const;
|
||||
bool challengeMasterSeed(const QByteArray& masterSeed);
|
||||
bool verifyKey(const QSharedPointer<CompositeKey>& key) const;
|
||||
|
||||
@@ -926,7 +926,7 @@ QString Entry::resolveReferencePlaceholderRecursive(const QString& placeholder,
|
||||
|
||||
Q_ASSERT(m_group);
|
||||
Q_ASSERT(m_group->database());
|
||||
const Entry* refEntry = m_group->findEntryBySearchTerm(searchText, searchInType);
|
||||
const Entry* refEntry = m_group->database()->rootGroup()->findEntryBySearchTerm(searchText, searchInType);
|
||||
|
||||
if (refEntry) {
|
||||
const QString wantedField = match.captured(EntryAttributes::WantedFieldGroupName);
|
||||
|
||||
@@ -67,6 +67,15 @@ QString EntryAttributes::value(const QString& key) const
|
||||
return m_attributes.value(key);
|
||||
}
|
||||
|
||||
QList<QString> EntryAttributes::values(const QList<QString>& keys) const
|
||||
{
|
||||
QList<QString> values;
|
||||
for (const QString& key : keys) {
|
||||
values.append(m_attributes.value(key));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
bool EntryAttributes::contains(const QString& key) const
|
||||
{
|
||||
return m_attributes.contains(key);
|
||||
|
||||
@@ -36,6 +36,7 @@ public:
|
||||
bool hasKey(const QString& key) const;
|
||||
QList<QString> customKeys() const;
|
||||
QString value(const QString& key) const;
|
||||
QList<QString> values(const QList<QString>& keys) const;
|
||||
bool contains(const QString& key) const;
|
||||
bool containsValue(const QString& value) const;
|
||||
bool isProtected(const QString& key) const;
|
||||
|
||||
@@ -28,31 +28,83 @@ EntrySearcher::EntrySearcher(bool caseSensitive)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Search group, and its children, by parsing the provided search
|
||||
* string for search terms.
|
||||
*
|
||||
* @param searchString search terms
|
||||
* @param baseGroup group to start search from, cannot be null
|
||||
* @param forceSearch ignore group search settings
|
||||
* @return list of entries that match the search terms
|
||||
*/
|
||||
QList<Entry*> EntrySearcher::search(const QString& searchString, const Group* baseGroup, bool forceSearch)
|
||||
{
|
||||
Q_ASSERT(baseGroup);
|
||||
|
||||
parseSearchTerms(searchString);
|
||||
return repeat(baseGroup, forceSearch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeat the last search starting from the given group
|
||||
*
|
||||
* @param baseGroup group to start search from, cannot be null
|
||||
* @param forceSearch ignore group search settings
|
||||
* @return list of entries that match the search terms
|
||||
*/
|
||||
QList<Entry*> EntrySearcher::repeat(const Group* baseGroup, bool forceSearch)
|
||||
{
|
||||
Q_ASSERT(baseGroup);
|
||||
|
||||
QList<Entry*> results;
|
||||
for (const auto group : baseGroup->groupsRecursive(true)) {
|
||||
if (forceSearch || group->resolveSearchingEnabled()) {
|
||||
results.append(searchEntries(searchString, group->entries()));
|
||||
for (auto* entry : group->entries()) {
|
||||
if (searchEntryImpl(entry)) {
|
||||
results.append(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search provided entries by parsing the search string
|
||||
* for search terms.
|
||||
*
|
||||
* @param searchString search terms
|
||||
* @param entries list of entries to include in the search
|
||||
* @return list of entries that match the search terms
|
||||
*/
|
||||
QList<Entry*> EntrySearcher::searchEntries(const QString& searchString, const QList<Entry*>& entries)
|
||||
{
|
||||
parseSearchTerms(searchString);
|
||||
return repeatEntries(entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeat the last search on the given entries
|
||||
*
|
||||
* @param entries list of entries to include in the search
|
||||
* @return list of entries that match the search terms
|
||||
*/
|
||||
QList<Entry*> EntrySearcher::repeatEntries(const QList<Entry*>& entries)
|
||||
{
|
||||
QList<Entry*> results;
|
||||
for (Entry* entry : entries) {
|
||||
if (searchEntryImpl(searchString, entry)) {
|
||||
for (auto* entry : entries) {
|
||||
if (searchEntryImpl(entry)) {
|
||||
results.append(entry);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the next search to be case sensitive or not
|
||||
*
|
||||
* @param state
|
||||
*/
|
||||
void EntrySearcher::setCaseSensitive(bool state)
|
||||
{
|
||||
m_caseSensitive = state;
|
||||
@@ -63,16 +115,15 @@ bool EntrySearcher::isCaseSensitive()
|
||||
return m_caseSensitive;
|
||||
}
|
||||
|
||||
bool EntrySearcher::searchEntryImpl(const QString& searchString, Entry* entry)
|
||||
bool EntrySearcher::searchEntryImpl(Entry* entry)
|
||||
{
|
||||
// Pre-load in case they are needed
|
||||
auto attributes = QStringList(entry->attributes()->keys());
|
||||
auto attributes_keys = entry->attributes()->customKeys();
|
||||
auto attributes = QStringList(attributes_keys + entry->attributes()->values(attributes_keys));
|
||||
auto attachments = QStringList(entry->attachments()->keys());
|
||||
|
||||
bool found;
|
||||
auto searchTerms = parseSearchTerms(searchString);
|
||||
|
||||
for (const auto& term : searchTerms) {
|
||||
for (const auto& term : m_searchTerms) {
|
||||
switch (term->field) {
|
||||
case Field::Title:
|
||||
found = term->regex.match(entry->resolvePlaceholder(entry->title())).hasMatch();
|
||||
@@ -112,10 +163,9 @@ bool EntrySearcher::searchEntryImpl(const QString& searchString, Entry* entry)
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<QSharedPointer<EntrySearcher::SearchTerm>> EntrySearcher::parseSearchTerms(const QString& searchString)
|
||||
void EntrySearcher::parseSearchTerms(const QString& searchString)
|
||||
{
|
||||
auto terms = QList<QSharedPointer<SearchTerm>>();
|
||||
|
||||
m_searchTerms.clear();
|
||||
auto results = m_termParser.globalMatch(searchString);
|
||||
while (results.hasNext()) {
|
||||
auto result = results.next();
|
||||
@@ -165,8 +215,6 @@ QList<QSharedPointer<EntrySearcher::SearchTerm>> EntrySearcher::parseSearchTerms
|
||||
}
|
||||
}
|
||||
|
||||
terms.append(term);
|
||||
m_searchTerms.append(term);
|
||||
}
|
||||
|
||||
return terms;
|
||||
}
|
||||
|
||||
@@ -31,14 +31,15 @@ public:
|
||||
explicit EntrySearcher(bool caseSensitive = false);
|
||||
|
||||
QList<Entry*> search(const QString& searchString, const Group* baseGroup, bool forceSearch = false);
|
||||
QList<Entry*> repeat(const Group* baseGroup, bool forceSearch = false);
|
||||
|
||||
QList<Entry*> searchEntries(const QString& searchString, const QList<Entry*>& entries);
|
||||
QList<Entry*> repeatEntries(const QList<Entry*>& entries);
|
||||
|
||||
void setCaseSensitive(bool state);
|
||||
bool isCaseSensitive();
|
||||
|
||||
private:
|
||||
bool searchEntryImpl(const QString& searchString, Entry* entry);
|
||||
|
||||
enum class Field
|
||||
{
|
||||
Undefined,
|
||||
@@ -59,10 +60,12 @@ private:
|
||||
bool exclude;
|
||||
};
|
||||
|
||||
QList<QSharedPointer<SearchTerm>> parseSearchTerms(const QString& searchString);
|
||||
bool searchEntryImpl(Entry* entry);
|
||||
void parseSearchTerms(const QString& searchString);
|
||||
|
||||
bool m_caseSensitive;
|
||||
QRegularExpression m_termParser;
|
||||
QList<QSharedPointer<SearchTerm>> m_searchTerms;
|
||||
|
||||
friend class TestEntrySearcher;
|
||||
};
|
||||
|
||||
@@ -123,6 +123,7 @@ BulkFileWatcher::BulkFileWatcher(QObject* parent)
|
||||
connect(&m_fileWatchUnblockTimer, SIGNAL(timeout()), this, SLOT(observeFileChanges()));
|
||||
connect(&m_pendingSignalsTimer, SIGNAL(timeout()), this, SLOT(emitSignals()));
|
||||
m_fileWatchUnblockTimer.setSingleShot(true);
|
||||
m_pendingSignalsTimer.setSingleShot(true);
|
||||
}
|
||||
|
||||
void BulkFileWatcher::clear()
|
||||
|
||||
@@ -1,8 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Felix Geyer <debfx@fobos.de>
|
||||
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "OSEventFilter.h"
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
#include "autotype/AutoType.h"
|
||||
#include "gui/MainWindow.h"
|
||||
#ifdef Q_OS_WIN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
OSEventFilter::OSEventFilter()
|
||||
{
|
||||
@@ -15,12 +37,18 @@ bool OSEventFilter::nativeEventFilter(const QByteArray& eventType, void* message
|
||||
#if defined(Q_OS_UNIX)
|
||||
if (eventType == QByteArrayLiteral("xcb_generic_event_t")) {
|
||||
#elif defined(Q_OS_WIN)
|
||||
if (eventType == QByteArrayLiteral("windows_generic_MSG")
|
||||
|| eventType == QByteArrayLiteral("windows_dispatcher_MSG")) {
|
||||
auto winmsg = static_cast<MSG*>(message);
|
||||
if (winmsg->message == WM_QUERYENDSESSION) {
|
||||
*result = 1;
|
||||
return true;
|
||||
} else if (winmsg->message == WM_ENDSESSION) {
|
||||
getMainWindow()->appExit();
|
||||
*result = 0;
|
||||
return true;
|
||||
} else if (eventType == QByteArrayLiteral("windows_generic_MSG")
|
||||
|| eventType == QByteArrayLiteral("windows_dispatcher_MSG")) {
|
||||
#endif
|
||||
int retCode = autoType()->callEventFilter(message);
|
||||
|
||||
return retCode == 1;
|
||||
return autoType()->callEventFilter(message) == 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Felix Geyer <debfx@fobos.de>
|
||||
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OSEVENTFILTER_H
|
||||
#define OSEVENTFILTER_H
|
||||
#include <QAbstractNativeEventFilter>
|
||||
|
||||
Reference in New Issue
Block a user