mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
Merge branch 'keepassx_master' into develop
This commit is contained in:
commit
7d165f133a
@ -157,7 +157,7 @@ void AutoType::performAutoType(const Entry* entry, QWidget* hideWindow, const QS
|
|||||||
|
|
||||||
QCoreApplication::processEvents(QEventLoop::AllEvents, 10);
|
QCoreApplication::processEvents(QEventLoop::AllEvents, 10);
|
||||||
|
|
||||||
Q_FOREACH (AutoTypeAction* action, actions) {
|
for (AutoTypeAction* action : asConst(actions)) {
|
||||||
if (m_plugin->activeWindow() != window) {
|
if (m_plugin->activeWindow() != window) {
|
||||||
qWarning("Active window changed, interrupting auto-type.");
|
qWarning("Active window changed, interrupting auto-type.");
|
||||||
break;
|
break;
|
||||||
@ -187,8 +187,9 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
|
|||||||
QList<Entry*> entryList;
|
QList<Entry*> entryList;
|
||||||
QHash<Entry*, QString> sequenceHash;
|
QHash<Entry*, QString> sequenceHash;
|
||||||
|
|
||||||
Q_FOREACH (Database* db, dbList) {
|
for (Database* db : dbList) {
|
||||||
Q_FOREACH (Entry* entry, db->rootGroup()->entriesRecursive()) {
|
const QList<Entry*> dbEntries = db->rootGroup()->entriesRecursive();
|
||||||
|
for (Entry* entry : dbEntries) {
|
||||||
QString sequence = autoTypeSequence(entry, windowTitle);
|
QString sequence = autoTypeSequence(entry, windowTitle);
|
||||||
if (!sequence.isEmpty()) {
|
if (!sequence.isEmpty()) {
|
||||||
entryList << entry;
|
entryList << entry;
|
||||||
@ -300,7 +301,7 @@ bool AutoType::parseActions(const QString& sequence, const Entry* entry, QList<A
|
|||||||
QString tmpl;
|
QString tmpl;
|
||||||
bool inTmpl = false;
|
bool inTmpl = false;
|
||||||
|
|
||||||
Q_FOREACH (const QChar& ch, sequence) {
|
for (const QChar& ch : sequence) {
|
||||||
// TODO: implement support for {{}, {}} and {DELAY=X}
|
// TODO: implement support for {{}, {}} and {DELAY=X}
|
||||||
|
|
||||||
if (inTmpl) {
|
if (inTmpl) {
|
||||||
@ -482,10 +483,10 @@ QList<AutoTypeAction*> AutoType::createActionFromTemplate(const QString& tmpl, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QString placeholder = QString("{%1}").arg(tmplName);
|
const QString placeholder = QString("{%1}").arg(tmplName);
|
||||||
QString resolved = entry->resolvePlaceholders(placeholder);
|
const QString resolved = entry->resolvePlaceholders(placeholder);
|
||||||
if (placeholder != resolved) {
|
if (placeholder != resolved) {
|
||||||
Q_FOREACH (const QChar& ch, resolved) {
|
for (const QChar& ch : resolved) {
|
||||||
if (ch == '\n') {
|
if (ch == '\n') {
|
||||||
list.append(new AutoTypeKey(Qt::Key_Enter));
|
list.append(new AutoTypeKey(Qt::Key_Enter));
|
||||||
}
|
}
|
||||||
@ -511,7 +512,8 @@ QString AutoType::autoTypeSequence(const Entry* entry, const QString& windowTitl
|
|||||||
QString sequence;
|
QString sequence;
|
||||||
if (!windowTitle.isEmpty()) {
|
if (!windowTitle.isEmpty()) {
|
||||||
bool match = false;
|
bool match = false;
|
||||||
Q_FOREACH (const AutoTypeAssociations::Association& assoc, entry->autoTypeAssociations()->getAll()) {
|
const QList<AutoTypeAssociations::Association> assocList = entry->autoTypeAssociations()->getAll();
|
||||||
|
for (const AutoTypeAssociations::Association& assoc : assocList) {
|
||||||
if (windowMatches(windowTitle, assoc.window)) {
|
if (windowMatches(windowTitle, assoc.window)) {
|
||||||
if (!assoc.sequence.isEmpty()) {
|
if (!assoc.sequence.isEmpty()) {
|
||||||
sequence = assoc.sequence;
|
sequence = assoc.sequence;
|
||||||
|
@ -70,7 +70,7 @@ bool WildcardMatcher::startOrEndDoesNotMatch(const QStringList& parts)
|
|||||||
bool WildcardMatcher::partsMatch(const QStringList& parts)
|
bool WildcardMatcher::partsMatch(const QStringList& parts)
|
||||||
{
|
{
|
||||||
int index = 0;
|
int index = 0;
|
||||||
Q_FOREACH (const QString& part, parts) {
|
for (const QString& part : parts) {
|
||||||
int matchIndex = getMatchIndex(part, index);
|
int matchIndex = getMatchIndex(part, index);
|
||||||
if (noMatchFound(matchIndex)) {
|
if (noMatchFound(matchIndex)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -344,7 +344,7 @@ QList<Window> AutoTypePlatformX11::widgetsToX11Windows(const QWidgetList& widget
|
|||||||
{
|
{
|
||||||
QList<Window> windows;
|
QList<Window> windows;
|
||||||
|
|
||||||
Q_FOREACH (const QWidget* widget, widgetList) {
|
for (const QWidget* widget : widgetList) {
|
||||||
windows.append(widget->effectiveWinId());
|
windows.append(widget->effectiveWinId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,14 +384,22 @@ bool AutoTypePlatformX11::isTopLevelWindow(Window window)
|
|||||||
int format;
|
int format;
|
||||||
unsigned long nitems;
|
unsigned long nitems;
|
||||||
unsigned long after;
|
unsigned long after;
|
||||||
unsigned char* data = nullptr;
|
unsigned char* data = Q_NULLPTR;
|
||||||
int retVal = XGetWindowProperty(m_dpy, window, m_atomWmState, 0, 0, False, AnyPropertyType, &type, &format,
|
int retVal = XGetWindowProperty(m_dpy, window, m_atomWmState, 0, 2, False, m_atomWmState, &type, &format,
|
||||||
&nitems, &after, &data);
|
&nitems, &after, &data);
|
||||||
if (data) {
|
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (retVal == 0 && data) {
|
||||||
|
if (type == m_atomWmState && format == 32 && nitems > 0) {
|
||||||
|
qint32 state = static_cast<qint32>(*data);
|
||||||
|
result = (state != WithdrawnState);
|
||||||
|
}
|
||||||
|
|
||||||
XFree(data);
|
XFree(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (retVal == 0) && type;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
KeySym AutoTypePlatformX11::charToKeySym(const QChar& ch)
|
KeySym AutoTypePlatformX11::charToKeySym(const QChar& ch)
|
||||||
|
@ -91,13 +91,15 @@ Entry* Database::resolveEntry(const Uuid& uuid)
|
|||||||
|
|
||||||
Entry* Database::recFindEntry(const Uuid& uuid, Group* group)
|
Entry* Database::recFindEntry(const Uuid& uuid, Group* group)
|
||||||
{
|
{
|
||||||
Q_FOREACH (Entry* entry, group->entries()) {
|
const QList<Entry*> entryList = group->entries();
|
||||||
|
for (Entry* entry : entryList) {
|
||||||
if (entry->uuid() == uuid) {
|
if (entry->uuid() == uuid) {
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Group* child, group->children()) {
|
const QList<Group*> children = group->children();
|
||||||
|
for (Group* child : children) {
|
||||||
Entry* result = recFindEntry(uuid, child);
|
Entry* result = recFindEntry(uuid, child);
|
||||||
if (result) {
|
if (result) {
|
||||||
return result;
|
return result;
|
||||||
@ -118,7 +120,8 @@ Group* Database::recFindGroup(const Uuid& uuid, Group* group)
|
|||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Group* child, group->children()) {
|
const QList<Group*> children = group->children();
|
||||||
|
for (Group* child : children) {
|
||||||
Group* result = recFindGroup(uuid, child);
|
Group* result = recFindGroup(uuid, child);
|
||||||
if (result) {
|
if (result) {
|
||||||
return result;
|
return result;
|
||||||
|
@ -371,7 +371,6 @@ const QList<Entry*>& Entry::historyItems() const
|
|||||||
void Entry::addHistoryItem(Entry* entry)
|
void Entry::addHistoryItem(Entry* entry)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!entry->parent());
|
Q_ASSERT(!entry->parent());
|
||||||
Q_ASSERT(entry->uuid() == uuid());
|
|
||||||
|
|
||||||
m_history.append(entry);
|
m_history.append(entry);
|
||||||
Q_EMIT modified();
|
Q_EMIT modified();
|
||||||
@ -383,7 +382,7 @@ void Entry::removeHistoryItems(const QList<Entry*>& historyEntries)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Entry* entry, historyEntries) {
|
for (Entry* entry : historyEntries) {
|
||||||
Q_ASSERT(!entry->parent());
|
Q_ASSERT(!entry->parent());
|
||||||
Q_ASSERT(entry->uuid() == uuid());
|
Q_ASSERT(entry->uuid() == uuid());
|
||||||
Q_ASSERT(m_history.contains(entry));
|
Q_ASSERT(m_history.contains(entry));
|
||||||
@ -432,8 +431,8 @@ void Entry::truncateHistory()
|
|||||||
if (size <= histMaxSize) {
|
if (size <= histMaxSize) {
|
||||||
size += historyItem->attributes()->attributesSize();
|
size += historyItem->attributes()->attributesSize();
|
||||||
|
|
||||||
QSet<QByteArray> newAttachments = historyItem->attachments()->values().toSet() - foundAttachements;
|
const QSet<QByteArray> newAttachments = historyItem->attachments()->values().toSet() - foundAttachements;
|
||||||
Q_FOREACH (const QByteArray& attachment, newAttachments) {
|
for (const QByteArray& attachment : newAttachments) {
|
||||||
size += attachment.size();
|
size += attachment.size();
|
||||||
}
|
}
|
||||||
foundAttachements += newAttachments;
|
foundAttachements += newAttachments;
|
||||||
@ -462,7 +461,7 @@ Entry* Entry::clone(CloneFlags flags) const
|
|||||||
entry->m_attachments->copyDataFrom(m_attachments);
|
entry->m_attachments->copyDataFrom(m_attachments);
|
||||||
entry->m_autoTypeAssociations->copyDataFrom(this->m_autoTypeAssociations);
|
entry->m_autoTypeAssociations->copyDataFrom(this->m_autoTypeAssociations);
|
||||||
if (flags & CloneIncludeHistory) {
|
if (flags & CloneIncludeHistory) {
|
||||||
Q_FOREACH (Entry* historyItem, m_history) {
|
for (Entry* historyItem : m_history) {
|
||||||
Entry* historyItemClone = historyItem->clone(flags & ~CloneIncludeHistory & ~CloneNewUuid);
|
Entry* historyItemClone = historyItem->clone(flags & ~CloneIncludeHistory & ~CloneNewUuid);
|
||||||
historyItemClone->setUpdateTimeinfo(false);
|
historyItemClone->setUpdateTimeinfo(false);
|
||||||
historyItemClone->setUuid(entry->uuid());
|
historyItemClone->setUuid(entry->uuid());
|
||||||
@ -509,7 +508,7 @@ void Entry::beginUpdate()
|
|||||||
m_modifiedSinceBegin = false;
|
m_modifiedSinceBegin = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entry::endUpdate()
|
bool Entry::endUpdate()
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_tmpHistoryItem);
|
Q_ASSERT(m_tmpHistoryItem);
|
||||||
if (m_modifiedSinceBegin) {
|
if (m_modifiedSinceBegin) {
|
||||||
@ -522,6 +521,8 @@ void Entry::endUpdate()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_tmpHistoryItem = nullptr;
|
m_tmpHistoryItem = nullptr;
|
||||||
|
|
||||||
|
return m_modifiedSinceBegin;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entry::updateModifiedSinceBegin()
|
void Entry::updateModifiedSinceBegin()
|
||||||
|
@ -133,7 +133,7 @@ public:
|
|||||||
* if the entry has been changed.
|
* if the entry has been changed.
|
||||||
*/
|
*/
|
||||||
void beginUpdate();
|
void beginUpdate();
|
||||||
void endUpdate();
|
bool endUpdate();
|
||||||
|
|
||||||
Group* group();
|
Group* group();
|
||||||
const Group* group() const;
|
const Group* group() const;
|
||||||
|
@ -44,7 +44,8 @@ bool EntryAttributes::hasKey(const QString& key) const
|
|||||||
QList<QString> EntryAttributes::customKeys()
|
QList<QString> EntryAttributes::customKeys()
|
||||||
{
|
{
|
||||||
QList<QString> customKeys;
|
QList<QString> customKeys;
|
||||||
Q_FOREACH (const QString& key, keys()) {
|
const QList<QString> keyList = keys();
|
||||||
|
for (const QString& key : keyList) {
|
||||||
if (!isDefaultAttribute(key)) {
|
if (!isDefaultAttribute(key)) {
|
||||||
customKeys.append(key);
|
customKeys.append(key);
|
||||||
}
|
}
|
||||||
@ -167,14 +168,16 @@ void EntryAttributes::copyCustomKeysFrom(const EntryAttributes* other)
|
|||||||
Q_EMIT aboutToBeReset();
|
Q_EMIT aboutToBeReset();
|
||||||
|
|
||||||
// remove all non-default keys
|
// remove all non-default keys
|
||||||
Q_FOREACH (const QString& key, keys()) {
|
const QList<QString> keyList = keys();
|
||||||
|
for (const QString& key : keyList) {
|
||||||
if (!isDefaultAttribute(key)) {
|
if (!isDefaultAttribute(key)) {
|
||||||
m_attributes.remove(key);
|
m_attributes.remove(key);
|
||||||
m_protectedAttributes.remove(key);
|
m_protectedAttributes.remove(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (const QString& key, other->keys()) {
|
const QList<QString> otherKeyList = other->keys();
|
||||||
|
for (const QString& key : otherKeyList) {
|
||||||
if (!isDefaultAttribute(key)) {
|
if (!isDefaultAttribute(key)) {
|
||||||
m_attributes.insert(key, other->value(key));
|
m_attributes.insert(key, other->value(key));
|
||||||
if (other->isProtected(key)) {
|
if (other->isProtected(key)) {
|
||||||
@ -194,7 +197,8 @@ bool EntryAttributes::areCustomKeysDifferent(const EntryAttributes* other)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (const QString& key, keys()) {
|
const QList<QString> keyList = keys();
|
||||||
|
for (const QString& key : keyList) {
|
||||||
if (isDefaultAttribute(key)) {
|
if (isDefaultAttribute(key)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -239,7 +243,7 @@ void EntryAttributes::clear()
|
|||||||
m_attributes.clear();
|
m_attributes.clear();
|
||||||
m_protectedAttributes.clear();
|
m_protectedAttributes.clear();
|
||||||
|
|
||||||
Q_FOREACH (const QString& key, DefaultAttributes) {
|
for (const QString& key : DefaultAttributes) {
|
||||||
m_attributes.insert(key, "");
|
m_attributes.insert(key, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,10 +34,13 @@ QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Grou
|
|||||||
{
|
{
|
||||||
QList<Entry*> searchResult;
|
QList<Entry*> searchResult;
|
||||||
|
|
||||||
Q_FOREACH (Entry* entry, group->entries()) {
|
const QList<Entry*> entryList = group->entries();
|
||||||
searchResult.append(matchEntry(searchTerm, entry, caseSensitivity));
|
for (Entry* entry : entryList) {
|
||||||
|
searchResult.append(matchEntry(searchTerm, entry, caseSensitivity));
|
||||||
}
|
}
|
||||||
Q_FOREACH (Group* childGroup, group->children()) {
|
|
||||||
|
const QList<Group*> children = group->children();
|
||||||
|
for (Group* childGroup : children) {
|
||||||
if (childGroup->searchingEnabled() != Group::Disable) {
|
if (childGroup->searchingEnabled() != Group::Disable) {
|
||||||
searchResult.append(searchEntries(searchTerm, childGroup, caseSensitivity));
|
searchResult.append(searchEntries(searchTerm, childGroup, caseSensitivity));
|
||||||
}
|
}
|
||||||
@ -49,8 +52,8 @@ QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Grou
|
|||||||
QList<Entry*> EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry,
|
QList<Entry*> EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry,
|
||||||
Qt::CaseSensitivity caseSensitivity)
|
Qt::CaseSensitivity caseSensitivity)
|
||||||
{
|
{
|
||||||
QStringList wordList = searchTerm.split(QRegExp("\\s"), QString::SkipEmptyParts);
|
const QStringList wordList = searchTerm.split(QRegExp("\\s"), QString::SkipEmptyParts);
|
||||||
Q_FOREACH (const QString& word, wordList) {
|
for (const QString& word : wordList) {
|
||||||
if (!wordMatch(word, entry, caseSensitivity)) {
|
if (!wordMatch(word, entry, caseSensitivity)) {
|
||||||
return QList<Entry*>();
|
return QList<Entry*>();
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <QLibrary>
|
#include <QLibrary>
|
||||||
|
|
||||||
#include "config-keepassx.h"
|
#include "config-keepassx.h"
|
||||||
|
#include "core/Global.h"
|
||||||
|
|
||||||
FilePath* FilePath::m_instance(nullptr);
|
FilePath* FilePath::m_instance(nullptr);
|
||||||
|
|
||||||
@ -40,7 +41,8 @@ QString FilePath::pluginPath(const QString& name)
|
|||||||
QStringList pluginPaths;
|
QStringList pluginPaths;
|
||||||
|
|
||||||
QDir buildDir(QCoreApplication::applicationDirPath() + "/autotype");
|
QDir buildDir(QCoreApplication::applicationDirPath() + "/autotype");
|
||||||
Q_FOREACH (const QString& dir, buildDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
|
const QStringList buildDirEntryList = buildDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
|
for (const QString& dir : buildDirEntryList) {
|
||||||
pluginPaths << QCoreApplication::applicationDirPath() + "/autotype/" + dir;
|
pluginPaths << QCoreApplication::applicationDirPath() + "/autotype/" + dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,10 +70,10 @@ QString FilePath::pluginPath(const QString& name)
|
|||||||
QStringList dirFilter;
|
QStringList dirFilter;
|
||||||
dirFilter << QString("*%1*").arg(name);
|
dirFilter << QString("*%1*").arg(name);
|
||||||
|
|
||||||
Q_FOREACH (const QString& path, pluginPaths) {
|
for (const QString& path : asConst(pluginPaths)) {
|
||||||
QStringList fileCandidates = QDir(path).entryList(dirFilter, QDir::Files);
|
const QStringList fileCandidates = QDir(path).entryList(dirFilter, QDir::Files);
|
||||||
|
|
||||||
Q_FOREACH (const QString& file, fileCandidates) {
|
for (const QString& file : fileCandidates) {
|
||||||
QString filePath = path + "/" + file;
|
QString filePath = path + "/" + file;
|
||||||
|
|
||||||
if (QLibrary::isLibrary(filePath)) {
|
if (QLibrary::isLibrary(filePath)) {
|
||||||
@ -103,10 +105,9 @@ QIcon FilePath::icon(const QString& category, const QString& name, bool fromThem
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (icon.isNull()) {
|
if (icon.isNull()) {
|
||||||
QList<int> pngSizes;
|
const QList<int> pngSizes = { 16, 22, 24, 32, 48, 64, 128 };
|
||||||
pngSizes << 16 << 22 << 24 << 32 << 48 << 64 << 128;
|
|
||||||
QString filename;
|
QString filename;
|
||||||
Q_FOREACH (int size, pngSizes) {
|
for (int size : pngSizes) {
|
||||||
filename = QString("%1/icons/application/%2x%2/%3.png").arg(m_dataPath, QString::number(size),
|
filename = QString("%1/icons/application/%2x%2/%3.png").arg(m_dataPath, QString::number(size),
|
||||||
combinedName);
|
combinedName);
|
||||||
if (QFile::exists(filename)) {
|
if (QFile::exists(filename)) {
|
||||||
@ -148,10 +149,9 @@ QIcon FilePath::onOffIcon(const QString& category, const QString& name)
|
|||||||
stateName = "on";
|
stateName = "on";
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<int> pngSizes;
|
const QList<int> pngSizes = { 16, 22, 24, 32, 48, 64, 128 };
|
||||||
pngSizes << 16 << 22 << 24 << 32 << 48 << 64 << 128;
|
|
||||||
QString filename;
|
QString filename;
|
||||||
Q_FOREACH (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").arg(m_dataPath, QString::number(size),
|
||||||
combinedName, stateName);
|
combinedName, stateName);
|
||||||
if (QFile::exists(filename)) {
|
if (QFile::exists(filename)) {
|
||||||
|
@ -36,4 +36,13 @@
|
|||||||
#define QUINT32_MAX 4294967295U
|
#define QUINT32_MAX 4294967295U
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
template <typename T> struct AddConst { typedef const T Type; };
|
||||||
|
|
||||||
|
// this adds const to non-const objects (like std::as_const)
|
||||||
|
template <typename T>
|
||||||
|
constexpr typename AddConst<T>::Type& asConst(T &t) noexcept { return t; }
|
||||||
|
// prevent rvalue arguments:
|
||||||
|
template <typename T>
|
||||||
|
void asConst(const T&&) = delete;
|
||||||
|
|
||||||
#endif // KEEPASSX_GLOBAL_H
|
#endif // KEEPASSX_GLOBAL_H
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "Group.h"
|
#include "Group.h"
|
||||||
|
|
||||||
#include "core/Config.h"
|
#include "core/Config.h"
|
||||||
|
#include "core/Global.h"
|
||||||
#include "core/DatabaseIcons.h"
|
#include "core/DatabaseIcons.h"
|
||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
|
|
||||||
@ -37,13 +38,13 @@ Group::~Group()
|
|||||||
{
|
{
|
||||||
// Destroy entries and children manually so DeletedObjects can be added
|
// Destroy entries and children manually so DeletedObjects can be added
|
||||||
// to database.
|
// to database.
|
||||||
QList<Entry*> entries = m_entries;
|
const QList<Entry*> entries = m_entries;
|
||||||
Q_FOREACH (Entry* entry, entries) {
|
for (Entry* entry : entries) {
|
||||||
delete entry;
|
delete entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<Group*> children = m_children;
|
const QList<Group*> children = m_children;
|
||||||
Q_FOREACH (Group* group, children) {
|
for (Group* group : children) {
|
||||||
delete group;
|
delete group;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,12 +428,12 @@ QList<Entry*> Group::entriesRecursive(bool includeHistoryItems) const
|
|||||||
entryList.append(m_entries);
|
entryList.append(m_entries);
|
||||||
|
|
||||||
if (includeHistoryItems) {
|
if (includeHistoryItems) {
|
||||||
Q_FOREACH (Entry* entry, m_entries) {
|
for (Entry* entry : m_entries) {
|
||||||
entryList.append(entry->historyItems());
|
entryList.append(entry->historyItems());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Group* group, m_children) {
|
for (Group* group : m_children) {
|
||||||
entryList.append(group->entriesRecursive(includeHistoryItems));
|
entryList.append(group->entriesRecursive(includeHistoryItems));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,7 +447,7 @@ QList<const Group*> Group::groupsRecursive(bool includeSelf) const
|
|||||||
groupList.append(this);
|
groupList.append(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (const Group* group, m_children) {
|
for (const Group* group : m_children) {
|
||||||
groupList.append(group->groupsRecursive(true));
|
groupList.append(group->groupsRecursive(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,7 +461,7 @@ QList<Group*> Group::groupsRecursive(bool includeSelf)
|
|||||||
groupList.append(this);
|
groupList.append(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Group* group, m_children) {
|
for (Group* group : asConst(m_children)) {
|
||||||
groupList.append(group->groupsRecursive(true));
|
groupList.append(group->groupsRecursive(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,13 +476,14 @@ QSet<Uuid> Group::customIconsRecursive() const
|
|||||||
result.insert(iconUuid());
|
result.insert(iconUuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Entry* entry, entriesRecursive(true)) {
|
const QList<Entry*> entryList = entriesRecursive(true);
|
||||||
|
for (Entry* entry : entryList) {
|
||||||
if (!entry->iconUuid().isNull()) {
|
if (!entry->iconUuid().isNull()) {
|
||||||
result.insert(entry->iconUuid());
|
result.insert(entry->iconUuid());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Group* group, m_children) {
|
for (Group* group : m_children) {
|
||||||
result.unite(group->customIconsRecursive());
|
result.unite(group->customIconsRecursive());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -497,13 +499,15 @@ Group* Group::clone(Entry::CloneFlags entryFlags) const
|
|||||||
clonedGroup->setUuid(Uuid::random());
|
clonedGroup->setUuid(Uuid::random());
|
||||||
clonedGroup->m_data = m_data;
|
clonedGroup->m_data = m_data;
|
||||||
|
|
||||||
Q_FOREACH (Entry* entry, entries()) {
|
const QList<Entry*> entryList = entries();
|
||||||
|
for (Entry* entry : entryList) {
|
||||||
Entry* clonedEntry = entry->clone(entryFlags);
|
Entry* clonedEntry = entry->clone(entryFlags);
|
||||||
clonedEntry->setGroup(clonedGroup);
|
clonedEntry->setGroup(clonedGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Group* groupChild, children()) {
|
const QList<Group*> childrenGroups = children();
|
||||||
Group* clonedGroupChild = groupChild->clone();
|
for (Group* groupChild : childrenGroups) {
|
||||||
|
Group* clonedGroupChild = groupChild->clone(entryFlags);
|
||||||
clonedGroupChild->setParent(clonedGroup);
|
clonedGroupChild->setParent(clonedGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -569,7 +573,7 @@ void Group::recSetDatabase(Database* db)
|
|||||||
disconnect(SIGNAL(modified()), m_db);
|
disconnect(SIGNAL(modified()), m_db);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Entry* entry, m_entries) {
|
for (Entry* entry : asConst(m_entries)) {
|
||||||
if (m_db) {
|
if (m_db) {
|
||||||
entry->disconnect(m_db);
|
entry->disconnect(m_db);
|
||||||
}
|
}
|
||||||
@ -591,7 +595,7 @@ void Group::recSetDatabase(Database* db)
|
|||||||
|
|
||||||
m_db = db;
|
m_db = db;
|
||||||
|
|
||||||
Q_FOREACH (Group* group, m_children) {
|
for (Group* group : asConst(m_children)) {
|
||||||
group->recSetDatabase(db);
|
group->recSetDatabase(db);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -609,11 +613,11 @@ void Group::cleanupParent()
|
|||||||
void Group::recCreateDelObjects()
|
void Group::recCreateDelObjects()
|
||||||
{
|
{
|
||||||
if (m_db) {
|
if (m_db) {
|
||||||
Q_FOREACH (Entry* entry, m_entries) {
|
for (Entry* entry : asConst(m_entries)) {
|
||||||
m_db->addDeletedObject(entry->uuid());
|
m_db->addDeletedObject(entry->uuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Group* group, m_children) {
|
for (Group* group : asConst(m_children)) {
|
||||||
group->recCreateDelObjects();
|
group->recCreateDelObjects();
|
||||||
}
|
}
|
||||||
m_db->addDeletedObject(m_uuid);
|
m_db->addDeletedObject(m_uuid);
|
||||||
|
@ -218,7 +218,7 @@ QHash<Uuid, QPixmap> Metadata::customIconsScaledPixmaps() const
|
|||||||
{
|
{
|
||||||
QHash<Uuid, QPixmap> result;
|
QHash<Uuid, QPixmap> result;
|
||||||
|
|
||||||
Q_FOREACH (const Uuid& uuid, m_customIconsOrder) {
|
for (const Uuid& uuid : m_customIconsOrder) {
|
||||||
result.insert(uuid, customIconScaledPixmap(uuid));
|
result.insert(uuid, customIconScaledPixmap(uuid));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,7 +427,7 @@ void Metadata::removeCustomIcon(const Uuid& uuid)
|
|||||||
|
|
||||||
void Metadata::copyCustomIcons(const QSet<Uuid>& iconList, const Metadata* otherMetadata)
|
void Metadata::copyCustomIcons(const QSet<Uuid>& iconList, const Metadata* otherMetadata)
|
||||||
{
|
{
|
||||||
Q_FOREACH (const Uuid& uuid, iconList) {
|
for (const Uuid& uuid : iconList) {
|
||||||
Q_ASSERT(otherMetadata->containsCustomIcon(uuid));
|
Q_ASSERT(otherMetadata->containsCustomIcon(uuid));
|
||||||
|
|
||||||
if (!containsCustomIcon(uuid) && otherMetadata->containsCustomIcon(uuid)) {
|
if (!containsCustomIcon(uuid) && otherMetadata->containsCustomIcon(uuid)) {
|
||||||
|
@ -45,11 +45,11 @@ QString PasswordGenerator::generatePassword() const
|
|||||||
{
|
{
|
||||||
Q_ASSERT(isValid());
|
Q_ASSERT(isValid());
|
||||||
|
|
||||||
QVector<PasswordGroup> groups = passwordGroups();
|
const QVector<PasswordGroup> groups = passwordGroups();
|
||||||
|
|
||||||
QVector<QChar> passwordChars;
|
QVector<QChar> passwordChars;
|
||||||
Q_FOREACH (const PasswordGroup& group, groups) {
|
for (const PasswordGroup& group : groups) {
|
||||||
Q_FOREACH (QChar ch, group) {
|
for (QChar ch : group) {
|
||||||
passwordChars.append(ch);
|
passwordChars.append(ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
#include "SignalMultiplexer.h"
|
#include "SignalMultiplexer.h"
|
||||||
|
|
||||||
|
#include "core/Global.h"
|
||||||
|
|
||||||
SignalMultiplexer::SignalMultiplexer()
|
SignalMultiplexer::SignalMultiplexer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -45,7 +47,7 @@ void SignalMultiplexer::setCurrentObject(QObject* object)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_currentObject) {
|
if (m_currentObject) {
|
||||||
Q_FOREACH (const Connection& con, m_connections) {
|
for (const Connection& con : asConst(m_connections)) {
|
||||||
disconnect(con);
|
disconnect(con);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,7 +55,7 @@ void SignalMultiplexer::setCurrentObject(QObject* object)
|
|||||||
m_currentObject = object;
|
m_currentObject = object;
|
||||||
|
|
||||||
if (object) {
|
if (object) {
|
||||||
Q_FOREACH (const Connection& con, m_connections) {
|
for (const Connection& con : asConst(m_connections)) {
|
||||||
connect(con);
|
connect(con);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,9 @@ bool hasChild(const QObject* parent, const QObject* child)
|
|||||||
if (!parent || !child) {
|
if (!parent || !child) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Q_FOREACH (QObject* c, parent->children()) {
|
|
||||||
|
const QObjectList children = parent->children();
|
||||||
|
for (QObject* c : children) {
|
||||||
if (child == c || hasChild(c, child)) {
|
if (child == c || hasChild(c, child)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -120,10 +122,10 @@ bool readAllFromDevice(QIODevice* device, QByteArray& data)
|
|||||||
|
|
||||||
QString imageReaderFilter()
|
QString imageReaderFilter()
|
||||||
{
|
{
|
||||||
QList<QByteArray> formats = QImageReader::supportedImageFormats();
|
const QList<QByteArray> formats = QImageReader::supportedImageFormats();
|
||||||
QStringList formatsStringList;
|
QStringList formatsStringList;
|
||||||
|
|
||||||
Q_FOREACH (const QByteArray& format, formats) {
|
for (const QByteArray& format : formats) {
|
||||||
for (int i = 0; i < format.size(); i++) {
|
for (int i = 0; i < format.size(); i++) {
|
||||||
if (!QChar(format.at(i)).isLetterOrNumber()) {
|
if (!QChar(format.at(i)).isLetterOrNumber()) {
|
||||||
continue;
|
continue;
|
||||||
@ -138,7 +140,7 @@ QString imageReaderFilter()
|
|||||||
|
|
||||||
bool isHex(const QByteArray& ba)
|
bool isHex(const QByteArray& ba)
|
||||||
{
|
{
|
||||||
Q_FOREACH (char c, ba) {
|
for (char c : ba) {
|
||||||
if ( !( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) ) {
|
if ( !( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -49,18 +49,20 @@ void Translator::installTranslator()
|
|||||||
|
|
||||||
QList<QPair<QString, QString> > Translator::availableLanguages()
|
QList<QPair<QString, QString> > Translator::availableLanguages()
|
||||||
{
|
{
|
||||||
QStringList paths;
|
const QStringList paths = {
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
paths.append(QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR));
|
QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR),
|
||||||
#endif
|
#endif
|
||||||
paths.append(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"));
|
||||||
|
|
||||||
QRegExp regExp("keepassx_([a-zA-Z_]+)\\.qm", Qt::CaseInsensitive, QRegExp::RegExp2);
|
QRegExp regExp("keepassx_([a-zA-Z_]+)\\.qm", Qt::CaseInsensitive, QRegExp::RegExp2);
|
||||||
Q_FOREACH (const QString& path, paths) {
|
for (const QString& path : paths) {
|
||||||
Q_FOREACH (const QString& filename, QDir(path).entryList()) {
|
const QStringList fileList = QDir(path).entryList();
|
||||||
|
for (const QString& filename : fileList) {
|
||||||
if (regExp.exactMatch(filename)) {
|
if (regExp.exactMatch(filename)) {
|
||||||
QString langcode = regExp.cap(1);
|
QString langcode = regExp.cap(1);
|
||||||
if (langcode == "en_plurals") {
|
if (langcode == "en_plurals") {
|
||||||
@ -85,13 +87,14 @@ QList<QPair<QString, QString> > Translator::availableLanguages()
|
|||||||
|
|
||||||
bool Translator::installTranslator(const QString& language)
|
bool Translator::installTranslator(const QString& language)
|
||||||
{
|
{
|
||||||
QStringList paths;
|
const QStringList paths = {
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
paths.append(QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR));
|
QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR),
|
||||||
#endif
|
#endif
|
||||||
paths.append(filePath()->dataPath("translations"));
|
filePath()->dataPath("translations")
|
||||||
|
};
|
||||||
|
|
||||||
Q_FOREACH (const QString& path, paths) {
|
for (const QString& path : paths) {
|
||||||
if (installTranslator(language, path)) {
|
if (installTranslator(language, path)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -116,7 +119,7 @@ bool Translator::installTranslator(const QString& language, const QString& path)
|
|||||||
bool Translator::installQtTranslator(const QString& language)
|
bool Translator::installQtTranslator(const QString& language)
|
||||||
{
|
{
|
||||||
QTranslator* qtTranslator = new QTranslator(qApp);
|
QTranslator* qtTranslator = new QTranslator(qApp);
|
||||||
if (qtTranslator->load(QString("%1/qt_%2").arg(QLibraryInfo::location(QLibraryInfo::TranslationsPath), language))) {
|
if (qtTranslator->load(QString("%1/qtbase_%2").arg(QLibraryInfo::location(QLibraryInfo::TranslationsPath), language))) {
|
||||||
QCoreApplication::installTranslator(qtTranslator);
|
QCoreApplication::installTranslator(qtTranslator);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -90,13 +90,11 @@ bool Crypto::checkAlgorithms()
|
|||||||
qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));
|
qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#ifdef GCRYPT_HAS_SALSA20
|
|
||||||
if (gcry_cipher_algo_info(GCRY_CIPHER_SALSA20, GCRYCTL_TEST_ALGO, nullptr, nullptr) != 0) {
|
if (gcry_cipher_algo_info(GCRY_CIPHER_SALSA20, GCRYCTL_TEST_ALGO, nullptr, nullptr) != 0) {
|
||||||
m_errorStr = "GCRY_CIPHER_SALSA20 not found.";
|
m_errorStr = "GCRY_CIPHER_SALSA20 not found.";
|
||||||
qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));
|
qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (gcry_md_test_algo(GCRY_MD_SHA256) != 0) {
|
if (gcry_md_test_algo(GCRY_MD_SHA256) != 0) {
|
||||||
m_errorStr = "GCRY_MD_SHA256 not found.";
|
m_errorStr = "GCRY_MD_SHA256 not found.";
|
||||||
qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));
|
qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));
|
||||||
|
@ -64,7 +64,8 @@ bool CsvExporter::writeGroup(QIODevice* device, const Group* group, QString grou
|
|||||||
}
|
}
|
||||||
groupPath.append(group->name());
|
groupPath.append(group->name());
|
||||||
|
|
||||||
Q_FOREACH (const Entry* entry, group->entries()) {
|
const QList<Entry*> entryList = group->entries();
|
||||||
|
for (const Entry* entry : entryList) {
|
||||||
QString line;
|
QString line;
|
||||||
|
|
||||||
addColumn(line, groupPath);
|
addColumn(line, groupPath);
|
||||||
@ -82,7 +83,8 @@ bool CsvExporter::writeGroup(QIODevice* device, const Group* group, QString grou
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (const Group* child, group->children()) {
|
const QList<Group*> children = group->children();
|
||||||
|
for (const Group* child : children) {
|
||||||
if (!writeGroup(device, child, groupPath)) {
|
if (!writeGroup(device, child, groupPath)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,7 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Entry* entry, entries) {
|
for (Entry* entry : asConst(entries)) {
|
||||||
if (isMetaStream(entry)) {
|
if (isMetaStream(entry)) {
|
||||||
parseMetaStream(entry);
|
parseMetaStream(entry);
|
||||||
|
|
||||||
@ -215,7 +215,8 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
|
|||||||
|
|
||||||
db->rootGroup()->setName(tr("Root"));
|
db->rootGroup()->setName(tr("Root"));
|
||||||
|
|
||||||
Q_FOREACH (Group* group, db->rootGroup()->children()) {
|
const QList<Group*> children = db->rootGroup()->children();
|
||||||
|
for (Group* group : children) {
|
||||||
if (group->name() == "Backup") {
|
if (group->name() == "Backup") {
|
||||||
group->setSearchingEnabled(Group::Disable);
|
group->setSearchingEnabled(Group::Disable);
|
||||||
group->setAutoTypeEnabled(Group::Disable);
|
group->setAutoTypeEnabled(Group::Disable);
|
||||||
@ -225,11 +226,12 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
|
|||||||
Q_ASSERT(m_tmpParent->children().isEmpty());
|
Q_ASSERT(m_tmpParent->children().isEmpty());
|
||||||
Q_ASSERT(m_tmpParent->entries().isEmpty());
|
Q_ASSERT(m_tmpParent->entries().isEmpty());
|
||||||
|
|
||||||
Q_FOREACH (Group* group, groups) {
|
for (Group* group : asConst(groups)) {
|
||||||
group->setUpdateTimeinfo(true);
|
group->setUpdateTimeinfo(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Entry* entry, m_db->rootGroup()->entriesRecursive()) {
|
const QList<Entry*> dbEntries = m_db->rootGroup()->entriesRecursive();
|
||||||
|
for (Entry* entry : dbEntries) {
|
||||||
entry->setUpdateTimeinfo(true);
|
entry->setUpdateTimeinfo(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,15 +300,14 @@ QString KeePass1Reader::errorString()
|
|||||||
SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const QByteArray& keyfileData,
|
SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const QByteArray& keyfileData,
|
||||||
qint64 contentPos)
|
qint64 contentPos)
|
||||||
{
|
{
|
||||||
QList<PasswordEncoding> encodings;
|
const QList<PasswordEncoding> encodings = { Windows1252, Latin1, UTF8 };
|
||||||
encodings << Windows1252 << Latin1 << UTF8;
|
|
||||||
|
|
||||||
QScopedPointer<SymmetricCipherStream> cipherStream;
|
QScopedPointer<SymmetricCipherStream> cipherStream;
|
||||||
QByteArray passwordData;
|
QByteArray passwordData;
|
||||||
QTextCodec* codec = QTextCodec::codecForName("Windows-1252");
|
QTextCodec* codec = QTextCodec::codecForName("Windows-1252");
|
||||||
QByteArray passwordDataCorrect = codec->fromUnicode(password);
|
QByteArray passwordDataCorrect = codec->fromUnicode(password);
|
||||||
|
|
||||||
Q_FOREACH (PasswordEncoding encoding, encodings) {
|
for (PasswordEncoding encoding : encodings) {
|
||||||
if (encoding == Windows1252) {
|
if (encoding == Windows1252) {
|
||||||
passwordData = passwordDataCorrect;
|
passwordData = passwordDataCorrect;
|
||||||
}
|
}
|
||||||
@ -727,7 +728,8 @@ void KeePass1Reader::parseNotes(const QString& rawNotes, Entry* entry)
|
|||||||
QStringList notes;
|
QStringList notes;
|
||||||
|
|
||||||
bool lastLineAutoType = false;
|
bool lastLineAutoType = false;
|
||||||
Q_FOREACH (QString line, rawNotes.split("\n")) {
|
const QStringList rawNotesLines = rawNotes.split("\n");
|
||||||
|
for (QString line : rawNotesLines) {
|
||||||
line.remove("\r");
|
line.remove("\r");
|
||||||
|
|
||||||
if (sequenceRegexp.exactMatch(line)) {
|
if (sequenceRegexp.exactMatch(line)) {
|
||||||
@ -769,8 +771,9 @@ void KeePass1Reader::parseNotes(const QString& rawNotes, Entry* entry)
|
|||||||
i.next();
|
i.next();
|
||||||
|
|
||||||
QString sequence = sequences.value(i.key());
|
QString sequence = sequences.value(i.key());
|
||||||
|
const QStringList windowList = i.value();
|
||||||
|
|
||||||
Q_FOREACH (const QString& window, i.value()) {
|
for (const QString& window : windowList) {
|
||||||
AutoTypeAssociations::Association assoc;
|
AutoTypeAssociations::Association assoc;
|
||||||
assoc.window = window;
|
assoc.window = window;
|
||||||
assoc.sequence = sequence;
|
assoc.sequence = sequence;
|
||||||
|
@ -192,7 +192,7 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke
|
|||||||
QByteArray headerHash = CryptoHash::hash(headerStream.storedData(), CryptoHash::Sha256);
|
QByteArray headerHash = CryptoHash::hash(headerStream.storedData(), CryptoHash::Sha256);
|
||||||
if (headerHash != xmlReader.headerHash()) {
|
if (headerHash != xmlReader.headerHash()) {
|
||||||
raiseError("Header doesn't match hash");
|
raiseError("Header doesn't match hash");
|
||||||
return nullptr;
|
return Q_NULLPTR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,17 +86,17 @@ void KeePass2XmlReader::readDatabase(QIODevice* device, Database* db, KeePass2Ra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<QString> poolKeys = m_binaryPool.keys().toSet();
|
const QSet<QString> poolKeys = m_binaryPool.keys().toSet();
|
||||||
QSet<QString> entryKeys = m_binaryMap.keys().toSet();
|
const QSet<QString> entryKeys = m_binaryMap.keys().toSet();
|
||||||
QSet<QString> unmappedKeys = entryKeys - poolKeys;
|
const QSet<QString> unmappedKeys = entryKeys - poolKeys;
|
||||||
QSet<QString> unusedKeys = poolKeys - entryKeys;
|
const QSet<QString> unusedKeys = poolKeys - entryKeys;
|
||||||
|
|
||||||
if (!unmappedKeys.isEmpty()) {
|
if (!unmappedKeys.isEmpty()) {
|
||||||
raiseError("Unmapped keys left.");
|
raiseError("Unmapped keys left.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_xml.error()) {
|
if (!m_xml.error()) {
|
||||||
Q_FOREACH (const QString& key, unusedKeys) {
|
for (const QString& key : unusedKeys) {
|
||||||
qWarning("KeePass2XmlReader::readDatabase: found unused key \"%s\"", qPrintable(key));
|
qWarning("KeePass2XmlReader::readDatabase: found unused key \"%s\"", qPrintable(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,7 +118,8 @@ void KeePass2XmlReader::readDatabase(QIODevice* device, Database* db, KeePass2Ra
|
|||||||
for (iEntry = m_entries.constBegin(); iEntry != m_entries.constEnd(); ++iEntry) {
|
for (iEntry = m_entries.constBegin(); iEntry != m_entries.constEnd(); ++iEntry) {
|
||||||
iEntry.value()->setUpdateTimeinfo(true);
|
iEntry.value()->setUpdateTimeinfo(true);
|
||||||
|
|
||||||
Q_FOREACH (Entry* histEntry, iEntry.value()->historyItems()) {
|
const QList<Entry*> historyItems = iEntry.value()->historyItems();
|
||||||
|
for (Entry* histEntry : historyItems) {
|
||||||
histEntry->setUpdateTimeinfo(true);
|
histEntry->setUpdateTimeinfo(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -614,11 +615,11 @@ Group* KeePass2XmlReader::parseGroup()
|
|||||||
raiseError("No group uuid found");
|
raiseError("No group uuid found");
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Group* child, children) {
|
for (Group* child : asConst(children)) {
|
||||||
child->setParent(group);
|
child->setParent(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Entry* entry, entries) {
|
for (Entry* entry : asConst(entries)) {
|
||||||
entry->setGroup(group);
|
entry->setGroup(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -777,11 +778,18 @@ Entry* KeePass2XmlReader::parseEntry(bool history)
|
|||||||
raiseError("No entry uuid found");
|
raiseError("No entry uuid found");
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Entry* historyItem, historyItems) {
|
for (Entry* historyItem : asConst(historyItems)) {
|
||||||
|
if (historyItem->uuid() != entry->uuid()) {
|
||||||
|
if (m_strictMode) {
|
||||||
|
raiseError("History element with different uuid");
|
||||||
|
} else {
|
||||||
|
historyItem->setUuid(entry->uuid());
|
||||||
|
}
|
||||||
|
}
|
||||||
entry->addHistoryItem(historyItem);
|
entry->addHistoryItem(historyItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (const StringPair& ref, binaryRefs) {
|
for (const StringPair& ref : asConst(binaryRefs)) {
|
||||||
m_binaryMap.insertMulti(ref.first, qMakePair(entry, ref.second));
|
m_binaryMap.insertMulti(ref.first, qMakePair(entry, ref.second));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,11 +82,12 @@ QString KeePass2XmlWriter::errorString()
|
|||||||
|
|
||||||
void KeePass2XmlWriter::generateIdMap()
|
void KeePass2XmlWriter::generateIdMap()
|
||||||
{
|
{
|
||||||
QList<Entry*> allEntries = m_db->rootGroup()->entriesRecursive(true);
|
const QList<Entry*> allEntries = m_db->rootGroup()->entriesRecursive(true);
|
||||||
int nextId = 0;
|
int nextId = 0;
|
||||||
|
|
||||||
Q_FOREACH (Entry* entry, allEntries) {
|
for (Entry* entry : allEntries) {
|
||||||
Q_FOREACH (const QString& key, entry->attachments()->keys()) {
|
const QList<QString> attachmentKeys = entry->attachments()->keys();
|
||||||
|
for (const QString& key : attachmentKeys) {
|
||||||
QByteArray data = entry->attachments()->value(key);
|
QByteArray data = entry->attachments()->value(key);
|
||||||
if (!m_idMap.contains(data)) {
|
if (!m_idMap.contains(data)) {
|
||||||
m_idMap.insert(data, nextId++);
|
m_idMap.insert(data, nextId++);
|
||||||
@ -149,7 +150,8 @@ void KeePass2XmlWriter::writeCustomIcons()
|
|||||||
{
|
{
|
||||||
m_xml.writeStartElement("CustomIcons");
|
m_xml.writeStartElement("CustomIcons");
|
||||||
|
|
||||||
Q_FOREACH (const Uuid& uuid, m_meta->customIconsOrder()) {
|
const QList<Uuid> customIconsOrder = m_meta->customIconsOrder();
|
||||||
|
for (const Uuid& uuid : customIconsOrder) {
|
||||||
writeIcon(uuid, m_meta->customIcon(uuid));
|
writeIcon(uuid, m_meta->customIcon(uuid));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +222,8 @@ void KeePass2XmlWriter::writeCustomData()
|
|||||||
m_xml.writeStartElement("CustomData");
|
m_xml.writeStartElement("CustomData");
|
||||||
|
|
||||||
QHash<QString, QString> customFields = m_meta->customFields();
|
QHash<QString, QString> customFields = m_meta->customFields();
|
||||||
Q_FOREACH (const QString& key, customFields.keys()) {
|
const QList<QString> keyList = customFields.keys();
|
||||||
|
for (const QString& key : keyList) {
|
||||||
writeCustomDataItem(key, customFields.value(key));
|
writeCustomDataItem(key, customFields.value(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,11 +276,13 @@ void KeePass2XmlWriter::writeGroup(const Group* group)
|
|||||||
|
|
||||||
writeUuid("LastTopVisibleEntry", group->lastTopVisibleEntry());
|
writeUuid("LastTopVisibleEntry", group->lastTopVisibleEntry());
|
||||||
|
|
||||||
Q_FOREACH (const Entry* entry, group->entries()) {
|
const QList<Entry*> entryList = group->entries();
|
||||||
|
for (const Entry* entry : entryList) {
|
||||||
writeEntry(entry);
|
writeEntry(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (const Group* child, group->children()) {
|
const QList<Group*> children = group->children();
|
||||||
|
for (const Group* child : children) {
|
||||||
writeGroup(child);
|
writeGroup(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +308,8 @@ void KeePass2XmlWriter::writeDeletedObjects()
|
|||||||
{
|
{
|
||||||
m_xml.writeStartElement("DeletedObjects");
|
m_xml.writeStartElement("DeletedObjects");
|
||||||
|
|
||||||
Q_FOREACH (const DeletedObject& delObj, m_db->deletedObjects()) {
|
const QList<DeletedObject> delObjList = m_db->deletedObjects();
|
||||||
|
for (const DeletedObject& delObj : delObjList) {
|
||||||
writeDeletedObject(delObj);
|
writeDeletedObject(delObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,7 +343,8 @@ void KeePass2XmlWriter::writeEntry(const Entry* entry)
|
|||||||
writeString("Tags", entry->tags());
|
writeString("Tags", entry->tags());
|
||||||
writeTimes(entry->timeInfo());
|
writeTimes(entry->timeInfo());
|
||||||
|
|
||||||
Q_FOREACH (const QString& key, entry->attributes()->keys()) {
|
const QList<QString> attributesKeyList = entry->attributes()->keys();
|
||||||
|
for (const QString& key : attributesKeyList) {
|
||||||
m_xml.writeStartElement("String");
|
m_xml.writeStartElement("String");
|
||||||
|
|
||||||
bool protect = ( ((key == "Title") && m_meta->protectTitle()) ||
|
bool protect = ( ((key == "Title") && m_meta->protectTitle()) ||
|
||||||
@ -379,7 +386,8 @@ void KeePass2XmlWriter::writeEntry(const Entry* entry)
|
|||||||
m_xml.writeEndElement();
|
m_xml.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (const QString& key, entry->attachments()->keys()) {
|
const QList<QString> attachmentsKeyList = entry->attachments()->keys();
|
||||||
|
for (const QString& key : attachmentsKeyList) {
|
||||||
m_xml.writeStartElement("Binary");
|
m_xml.writeStartElement("Binary");
|
||||||
|
|
||||||
writeString("Key", key);
|
writeString("Key", key);
|
||||||
@ -408,7 +416,8 @@ void KeePass2XmlWriter::writeAutoType(const Entry* entry)
|
|||||||
writeNumber("DataTransferObfuscation", entry->autoTypeObfuscation());
|
writeNumber("DataTransferObfuscation", entry->autoTypeObfuscation());
|
||||||
writeString("DefaultSequence", entry->defaultAutoTypeSequence());
|
writeString("DefaultSequence", entry->defaultAutoTypeSequence());
|
||||||
|
|
||||||
Q_FOREACH (const AutoTypeAssociations::Association& assoc, entry->autoTypeAssociations()->getAll()) {
|
const QList<AutoTypeAssociations::Association> autoTypeAssociations = entry->autoTypeAssociations()->getAll();
|
||||||
|
for (const AutoTypeAssociations::Association& assoc : autoTypeAssociations) {
|
||||||
writeAutoTypeAssoc(assoc);
|
writeAutoTypeAssoc(assoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,7 +439,7 @@ void KeePass2XmlWriter::writeEntryHistory(const Entry* entry)
|
|||||||
m_xml.writeStartElement("History");
|
m_xml.writeStartElement("History");
|
||||||
|
|
||||||
const QList<Entry*>& historyItems = entry->historyItems();
|
const QList<Entry*>& historyItems = entry->historyItems();
|
||||||
Q_FOREACH (const Entry* item, historyItems) {
|
for (const Entry* item : historyItems) {
|
||||||
writeEntry(item);
|
writeEntry(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,8 +139,8 @@ void DatabaseSettingsWidget::transformRoundsBenchmark()
|
|||||||
|
|
||||||
void DatabaseSettingsWidget::truncateHistories()
|
void DatabaseSettingsWidget::truncateHistories()
|
||||||
{
|
{
|
||||||
QList<Entry*> allEntries = m_db->rootGroup()->entriesRecursive(false);
|
const QList<Entry*> allEntries = m_db->rootGroup()->entriesRecursive(false);
|
||||||
Q_FOREACH (Entry* entry, allEntries) {
|
for (Entry* entry : allEntries) {
|
||||||
entry->truncateHistory();
|
entry->truncateHistory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,7 +223,7 @@ bool DatabaseTabWidget::closeDatabase(Database* db)
|
|||||||
if (dbName.right(1) == "*") {
|
if (dbName.right(1) == "*") {
|
||||||
dbName.chop(1);
|
dbName.chop(1);
|
||||||
}
|
}
|
||||||
if (dbStruct.dbWidget->isInEditMode() && db->hasKey()) {
|
if (dbStruct.dbWidget->isInEditMode() && db->hasKey() && dbStruct.dbWidget->isEditWidgetModified()) {
|
||||||
QMessageBox::StandardButton result =
|
QMessageBox::StandardButton result =
|
||||||
MessageBox::question(
|
MessageBox::question(
|
||||||
this, tr("Close?"),
|
this, tr("Close?"),
|
||||||
@ -296,7 +296,7 @@ bool DatabaseTabWidget::saveDatabase(Database* db)
|
|||||||
DatabaseManagerStruct& dbStruct = m_dbList[db];
|
DatabaseManagerStruct& dbStruct = m_dbList[db];
|
||||||
|
|
||||||
if (dbStruct.saveToFilename) {
|
if (dbStruct.saveToFilename) {
|
||||||
QSaveFile saveFile(dbStruct.filePath);
|
QSaveFile saveFile(dbStruct.canonicalFilePath);
|
||||||
if (saveFile.open(QIODevice::WriteOnly)) {
|
if (saveFile.open(QIODevice::WriteOnly)) {
|
||||||
m_writer.writeDatabase(&saveFile, db);
|
m_writer.writeDatabase(&saveFile, db);
|
||||||
if (m_writer.hasError()) {
|
if (m_writer.hasError()) {
|
||||||
@ -310,6 +310,11 @@ bool DatabaseTabWidget::saveDatabase(Database* db)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
MessageBox::critical(this, tr("Error"), tr("Writing the database failed.") + "\n\n"
|
||||||
|
+ saveFile.errorString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
dbStruct.modified = false;
|
dbStruct.modified = false;
|
||||||
updateTabName(db);
|
updateTabName(db);
|
||||||
@ -386,6 +391,9 @@ bool DatabaseTabWidget::saveDatabaseAs(Database* db)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// refresh fileinfo since the file didn't exist before
|
||||||
|
fileInfo.refresh();
|
||||||
|
|
||||||
dbStruct.modified = false;
|
dbStruct.modified = false;
|
||||||
dbStruct.saveToFilename = true;
|
dbStruct.saveToFilename = true;
|
||||||
dbStruct.readOnly = false;
|
dbStruct.readOnly = false;
|
||||||
@ -649,7 +657,7 @@ void DatabaseTabWidget::lockDatabases()
|
|||||||
// show the correct tab widget before we are asking questions about it
|
// show the correct tab widget before we are asking questions about it
|
||||||
setCurrentWidget(dbWidget);
|
setCurrentWidget(dbWidget);
|
||||||
|
|
||||||
if (mode == DatabaseWidget::EditMode) {
|
if (mode == DatabaseWidget::EditMode && dbWidget->isEditWidgetModified()) {
|
||||||
QMessageBox::StandardButton result =
|
QMessageBox::StandardButton result =
|
||||||
MessageBox::question(
|
MessageBox::question(
|
||||||
this, tr("Lock database"),
|
this, tr("Lock database"),
|
||||||
|
@ -194,6 +194,18 @@ bool DatabaseWidget::isInEditMode() const
|
|||||||
return currentMode() == DatabaseWidget::EditMode;
|
return currentMode() == DatabaseWidget::EditMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DatabaseWidget::isEditWidgetModified() const
|
||||||
|
{
|
||||||
|
if (currentWidget() == m_editEntryWidget) {
|
||||||
|
return m_editEntryWidget->hasBeenModified();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// other edit widget don't have a hasBeenModified() method yet
|
||||||
|
// assume that they already have been modified
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QList<int> DatabaseWidget::splitterSizes() const
|
QList<int> DatabaseWidget::splitterSizes() const
|
||||||
{
|
{
|
||||||
return m_splitter->sizes();
|
return m_splitter->sizes();
|
||||||
@ -311,7 +323,7 @@ void DatabaseWidget::deleteEntries()
|
|||||||
|
|
||||||
// get all entry pointers as the indexes change when removing multiple entries
|
// get all entry pointers as the indexes change when removing multiple entries
|
||||||
QList<Entry*> selectedEntries;
|
QList<Entry*> selectedEntries;
|
||||||
Q_FOREACH (const QModelIndex& index, selected) {
|
for (const QModelIndex& index : selected) {
|
||||||
selectedEntries.append(m_entryView->entryFromIndex(index));
|
selectedEntries.append(m_entryView->entryFromIndex(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,23 +347,33 @@ void DatabaseWidget::deleteEntries()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result == QMessageBox::Yes) {
|
if (result == QMessageBox::Yes) {
|
||||||
Q_FOREACH (Entry* entry, selectedEntries) {
|
for (Entry* entry : asConst(selectedEntries)) {
|
||||||
delete entry;
|
delete entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (selected.size() > 1) {
|
QMessageBox::StandardButton result;
|
||||||
QMessageBox::StandardButton result = MessageBox::question(
|
|
||||||
|
if (selected.size() == 1) {
|
||||||
|
result = MessageBox::question(
|
||||||
|
this, tr("Move entry to recycle bin?"),
|
||||||
|
tr("Do you really want to move entry \"%1\" to the recycle bin?")
|
||||||
|
.arg(selectedEntries.first()->title()),
|
||||||
|
QMessageBox::Yes | QMessageBox::No);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = MessageBox::question(
|
||||||
this, tr("Move entries to recycle bin?"),
|
this, tr("Move entries to recycle bin?"),
|
||||||
tr("Do you really want to move %n entry(s) to the recycle bin?", 0, selected.size()),
|
tr("Do you really want to move %n entry(s) to the recycle bin?", 0, selected.size()),
|
||||||
QMessageBox::Yes | QMessageBox::No);
|
QMessageBox::Yes | QMessageBox::No);
|
||||||
if (result == QMessageBox::No) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Entry* entry, selectedEntries) {
|
if (result == QMessageBox::No) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Entry* entry : asConst(selectedEntries)) {
|
||||||
m_db->recycleEntry(entry);
|
m_db->recycleEntry(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -493,7 +515,9 @@ void DatabaseWidget::deleteGroup()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool inRecylceBin = Tools::hasChild(m_db->metadata()->recycleBin(), currentGroup);
|
bool inRecylceBin = Tools::hasChild(m_db->metadata()->recycleBin(), currentGroup);
|
||||||
if (inRecylceBin || !m_db->metadata()->recycleBinEnabled()) {
|
bool isRecycleBin = (currentGroup == m_db->metadata()->recycleBin());
|
||||||
|
bool isRecycleBinSubgroup = Tools::hasChild(currentGroup, m_db->metadata()->recycleBin());
|
||||||
|
if (inRecylceBin || isRecycleBin || isRecycleBinSubgroup || !m_db->metadata()->recycleBinEnabled()) {
|
||||||
QMessageBox::StandardButton result = MessageBox::question(
|
QMessageBox::StandardButton result = MessageBox::question(
|
||||||
this, tr("Delete group?"),
|
this, tr("Delete group?"),
|
||||||
tr("Do you really want to delete the group \"%1\" for good?")
|
tr("Do you really want to delete the group \"%1\" for good?")
|
||||||
@ -659,8 +683,8 @@ void DatabaseWidget::unlockDatabase(bool accepted)
|
|||||||
|
|
||||||
replaceDatabase(static_cast<DatabaseOpenWidget*>(sender())->database());
|
replaceDatabase(static_cast<DatabaseOpenWidget*>(sender())->database());
|
||||||
|
|
||||||
QList<Group*> groups = m_db->rootGroup()->groupsRecursive(true);
|
const QList<Group*> groups = m_db->rootGroup()->groupsRecursive(true);
|
||||||
Q_FOREACH (Group* group, groups) {
|
for (Group* group : groups) {
|
||||||
if (group->uuid() == m_groupBeforeLock) {
|
if (group->uuid() == m_groupBeforeLock) {
|
||||||
m_groupView->setCurrentGroup(group);
|
m_groupView->setCurrentGroup(group);
|
||||||
break;
|
break;
|
||||||
@ -871,8 +895,7 @@ bool DatabaseWidget::dbHasKey() const
|
|||||||
bool DatabaseWidget::canDeleteCurrentGroup() const
|
bool DatabaseWidget::canDeleteCurrentGroup() const
|
||||||
{
|
{
|
||||||
bool isRootGroup = m_db->rootGroup() == m_groupView->currentGroup();
|
bool isRootGroup = m_db->rootGroup() == m_groupView->currentGroup();
|
||||||
bool isRecycleBin = m_db->metadata()->recycleBin() == m_groupView->currentGroup();
|
return !isRootGroup;
|
||||||
return !isRootGroup && !isRecycleBin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DatabaseWidget::isInSearchMode() const
|
bool DatabaseWidget::isInSearchMode() const
|
||||||
|
@ -74,6 +74,7 @@ public:
|
|||||||
QStringList customEntryAttributes() const;
|
QStringList customEntryAttributes() const;
|
||||||
bool isGroupSelected() const;
|
bool isGroupSelected() const;
|
||||||
bool isInEditMode() const;
|
bool isInEditMode() const;
|
||||||
|
bool isEditWidgetModified() const;
|
||||||
QList<int> splitterSizes() const;
|
QList<int> splitterSizes() const;
|
||||||
void setSplitterSizes(const QList<int>& sizes);
|
void setSplitterSizes(const QList<int>& sizes);
|
||||||
QList<int> entryHeaderViewSizes() const;
|
QList<int> entryHeaderViewSizes() const;
|
||||||
|
@ -124,10 +124,10 @@ void DatabaseWidgetStateSync::updateColumnSizes()
|
|||||||
|
|
||||||
QList<int> DatabaseWidgetStateSync::variantToIntList(const QVariant& variant)
|
QList<int> DatabaseWidgetStateSync::variantToIntList(const QVariant& variant)
|
||||||
{
|
{
|
||||||
QVariantList list = variant.toList();
|
const QVariantList list = variant.toList();
|
||||||
QList<int> result;
|
QList<int> result;
|
||||||
|
|
||||||
Q_FOREACH (const QVariant& var, list) {
|
for (const QVariant& var : list) {
|
||||||
bool ok;
|
bool ok;
|
||||||
int size = var.toInt(&ok);
|
int size = var.toInt(&ok);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
@ -146,7 +146,7 @@ QVariant DatabaseWidgetStateSync::intListToVariant(const QList<int>& list)
|
|||||||
{
|
{
|
||||||
QVariantList result;
|
QVariantList result;
|
||||||
|
|
||||||
Q_FOREACH (int value, list) {
|
for (int value : list) {
|
||||||
result.append(value);
|
result.append(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "ui_EditWidgetIcons.h"
|
#include "ui_EditWidgetIcons.h"
|
||||||
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
#include <QImageReader>
|
||||||
|
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
@ -60,11 +61,8 @@ EditWidgetIcons::~EditWidgetIcons()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
IconStruct EditWidgetIcons::save()
|
IconStruct EditWidgetIcons::state() const
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_database);
|
|
||||||
Q_ASSERT(!m_currentUuid.isNull());
|
|
||||||
|
|
||||||
IconStruct iconStruct;
|
IconStruct iconStruct;
|
||||||
if (m_ui->defaultIconsRadio->isChecked()) {
|
if (m_ui->defaultIconsRadio->isChecked()) {
|
||||||
QModelIndex index = m_ui->defaultIconsView->currentIndex();
|
QModelIndex index = m_ui->defaultIconsView->currentIndex();
|
||||||
@ -85,9 +83,13 @@ IconStruct EditWidgetIcons::save()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return iconStruct;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditWidgetIcons::reset()
|
||||||
|
{
|
||||||
m_database = nullptr;
|
m_database = nullptr;
|
||||||
m_currentUuid = Uuid();
|
m_currentUuid = Uuid();
|
||||||
return iconStruct;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditWidgetIcons::load(Uuid currentUuid, Database* database, IconStruct iconStruct)
|
void EditWidgetIcons::load(Uuid currentUuid, Database* database, IconStruct iconStruct)
|
||||||
@ -129,7 +131,10 @@ void EditWidgetIcons::addCustomIcon()
|
|||||||
QString filename = QFileDialog::getOpenFileName(
|
QString filename = QFileDialog::getOpenFileName(
|
||||||
this, tr("Select Image"), "", filter);
|
this, tr("Select Image"), "", filter);
|
||||||
if (!filename.isEmpty()) {
|
if (!filename.isEmpty()) {
|
||||||
QImage image(filename);
|
QImageReader imageReader(filename);
|
||||||
|
// detect from content, otherwise reading fails if file extension is wrong
|
||||||
|
imageReader.setDecideFormatFromContent(true);
|
||||||
|
QImage image = imageReader.read();
|
||||||
if (!image.isNull()) {
|
if (!image.isNull()) {
|
||||||
Uuid uuid = Uuid::random();
|
Uuid uuid = Uuid::random();
|
||||||
m_database->metadata()->addCustomIconScaled(uuid, image);
|
m_database->metadata()->addCustomIconScaled(uuid, image);
|
||||||
@ -139,7 +144,8 @@ void EditWidgetIcons::addCustomIcon()
|
|||||||
m_ui->customIconsView->setCurrentIndex(index);
|
m_ui->customIconsView->setCurrentIndex(index);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO: show error
|
MessageBox::critical(this, tr("Error"),
|
||||||
|
tr("Can't read icon:").append("\n").append(imageReader.errorString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,10 +159,10 @@ void EditWidgetIcons::removeCustomIcon()
|
|||||||
Uuid iconUuid = m_customIconModel->uuidFromIndex(index);
|
Uuid iconUuid = m_customIconModel->uuidFromIndex(index);
|
||||||
int iconUsedCount = 0;
|
int iconUsedCount = 0;
|
||||||
|
|
||||||
QList<Entry*> allEntries = m_database->rootGroup()->entriesRecursive(true);
|
const QList<Entry*> allEntries = m_database->rootGroup()->entriesRecursive(true);
|
||||||
QList<Entry*> historyEntriesWithSameIcon;
|
QList<Entry*> historyEntriesWithSameIcon;
|
||||||
|
|
||||||
Q_FOREACH (Entry* entry, allEntries) {
|
for (Entry* entry : allEntries) {
|
||||||
bool isHistoryEntry = !entry->group();
|
bool isHistoryEntry = !entry->group();
|
||||||
if (iconUuid == entry->iconUuid()) {
|
if (iconUuid == entry->iconUuid()) {
|
||||||
if (isHistoryEntry) {
|
if (isHistoryEntry) {
|
||||||
@ -168,15 +174,15 @@ void EditWidgetIcons::removeCustomIcon()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<Group*> allGroups = m_database->rootGroup()->groupsRecursive(true);
|
const QList<Group*> allGroups = m_database->rootGroup()->groupsRecursive(true);
|
||||||
Q_FOREACH (const Group* group, allGroups) {
|
for (const Group* group : allGroups) {
|
||||||
if (iconUuid == group->iconUuid() && m_currentUuid != group->uuid()) {
|
if (iconUuid == group->iconUuid() && m_currentUuid != group->uuid()) {
|
||||||
iconUsedCount++;
|
iconUsedCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iconUsedCount == 0) {
|
if (iconUsedCount == 0) {
|
||||||
Q_FOREACH (Entry* entry, historyEntriesWithSameIcon) {
|
for (Entry* entry : asConst(historyEntriesWithSameIcon)) {
|
||||||
entry->setUpdateTimeinfo(false);
|
entry->setUpdateTimeinfo(false);
|
||||||
entry->setIcon(0);
|
entry->setIcon(0);
|
||||||
entry->setUpdateTimeinfo(true);
|
entry->setUpdateTimeinfo(true);
|
||||||
|
@ -46,7 +46,8 @@ public:
|
|||||||
explicit EditWidgetIcons(QWidget* parent = nullptr);
|
explicit EditWidgetIcons(QWidget* parent = nullptr);
|
||||||
~EditWidgetIcons();
|
~EditWidgetIcons();
|
||||||
|
|
||||||
IconStruct save();
|
IconStruct state() const;
|
||||||
|
void reset();
|
||||||
void load(Uuid currentUuid, Database* database, IconStruct iconStruct);
|
void load(Uuid currentUuid, Database* database, IconStruct iconStruct);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
|
@ -269,8 +269,8 @@ void MainWindow::updateLastDatabasesMenu()
|
|||||||
{
|
{
|
||||||
m_ui->menuRecentDatabases->clear();
|
m_ui->menuRecentDatabases->clear();
|
||||||
|
|
||||||
QStringList lastDatabases = config()->get("LastDatabases", QVariant()).toStringList();
|
const QStringList lastDatabases = config()->get("LastDatabases", QVariant()).toStringList();
|
||||||
Q_FOREACH (const QString& database, lastDatabases) {
|
for (const QString& database : lastDatabases) {
|
||||||
QAction* action = m_ui->menuRecentDatabases->addAction(database);
|
QAction* action = m_ui->menuRecentDatabases->addAction(database);
|
||||||
action->setData(database);
|
action->setData(database);
|
||||||
m_lastDatabasesActions->addAction(action);
|
m_lastDatabasesActions->addAction(action);
|
||||||
@ -295,7 +295,8 @@ void MainWindow::updateCopyAttributesMenu()
|
|||||||
delete actions[i];
|
delete actions[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (const QString& key, dbWidget->customEntryAttributes()) {
|
const QStringList customEntryAttributes = dbWidget->customEntryAttributes();
|
||||||
|
for (const QString& key : customEntryAttributes) {
|
||||||
QAction* action = m_ui->menuEntryCopyAttribute->addAction(key);
|
QAction* action = m_ui->menuEntryCopyAttribute->addAction(key);
|
||||||
m_copyAdditionalAttributeActions->addAction(action);
|
m_copyAdditionalAttributeActions->addAction(action);
|
||||||
}
|
}
|
||||||
@ -372,12 +373,14 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DatabaseWidget::EditMode:
|
case DatabaseWidget::EditMode:
|
||||||
case DatabaseWidget::LockedMode:
|
case DatabaseWidget::LockedMode: {
|
||||||
Q_FOREACH (QAction* action, m_ui->menuEntries->actions()) {
|
const QList<QAction*> entryActions = m_ui->menuEntries->actions();
|
||||||
|
for (QAction* action : entryActions) {
|
||||||
action->setEnabled(false);
|
action->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (QAction* action, m_ui->menuGroups->actions()) {
|
const QList<QAction*> groupActions = m_ui->menuGroups->actions();
|
||||||
|
for (QAction* action : groupActions) {
|
||||||
action->setEnabled(false);
|
action->setEnabled(false);
|
||||||
}
|
}
|
||||||
m_ui->actionEntryCopyTitle->setEnabled(false);
|
m_ui->actionEntryCopyTitle->setEnabled(false);
|
||||||
@ -394,17 +397,20 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode)
|
|||||||
m_ui->actionDatabaseSaveAs->setEnabled(false);
|
m_ui->actionDatabaseSaveAs->setEnabled(false);
|
||||||
m_ui->actionExportCsv->setEnabled(false);
|
m_ui->actionExportCsv->setEnabled(false);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
}
|
}
|
||||||
m_ui->actionDatabaseClose->setEnabled(true);
|
m_ui->actionDatabaseClose->setEnabled(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Q_FOREACH (QAction* action, m_ui->menuEntries->actions()) {
|
const QList<QAction*> entryActions = m_ui->menuEntries->actions();
|
||||||
|
for (QAction* action : entryActions) {
|
||||||
action->setEnabled(false);
|
action->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (QAction* action, m_ui->menuGroups->actions()) {
|
const QList<QAction*> groupActions = m_ui->menuGroups->actions();
|
||||||
|
for (QAction* action : groupActions) {
|
||||||
action->setEnabled(false);
|
action->setEnabled(false);
|
||||||
}
|
}
|
||||||
m_ui->actionEntryCopyTitle->setEnabled(false);
|
m_ui->actionEntryCopyTitle->setEnabled(false);
|
||||||
|
@ -49,7 +49,7 @@ void PasswordComboBox::setEcho(bool echo)
|
|||||||
// Qt on Mac OS doesn't seem to know the generic monospace family (tested with 4.8.6)
|
// Qt on Mac OS doesn't seem to know the generic monospace family (tested with 4.8.6)
|
||||||
setStyleSheet("QComboBox { font-family: monospace,Menlo,Monaco; }");
|
setStyleSheet("QComboBox { font-family: monospace,Menlo,Monaco; }");
|
||||||
#else
|
#else
|
||||||
setStyleSheet("QComboBox { font-family: monospace,Courier; }");
|
setStyleSheet("QComboBox { font-family: monospace,Courier New; }");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -58,7 +58,7 @@ void PasswordEdit::updateStylesheet()
|
|||||||
// Qt on Mac OS doesn't seem to know the generic monospace family (tested with 4.8.6)
|
// Qt on Mac OS doesn't seem to know the generic monospace family (tested with 4.8.6)
|
||||||
stylesheet.append("font-family: monospace,Menlo,Monaco; ");
|
stylesheet.append("font-family: monospace,Menlo,Monaco; ");
|
||||||
#else
|
#else
|
||||||
stylesheet.append("font-family: monospace; ");
|
stylesheet.append("font-family: monospace,Courier New; ");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +88,14 @@ void PasswordGeneratorWidget::reset()
|
|||||||
updateGenerator();
|
updateGenerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PasswordGeneratorWidget::regeneratePassword()
|
||||||
|
{
|
||||||
|
if (m_generator->isValid()) {
|
||||||
|
QString password = m_generator->generatePassword();
|
||||||
|
m_ui->editNewPassword->setEditText(password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PasswordGeneratorWidget::updateApplyEnabled(const QString& password)
|
void PasswordGeneratorWidget::updateApplyEnabled(const QString& password)
|
||||||
{
|
{
|
||||||
m_ui->buttonApply->setEnabled(!password.isEmpty());
|
m_ui->buttonApply->setEnabled(!password.isEmpty());
|
||||||
@ -111,6 +119,10 @@ void PasswordGeneratorWidget::sliderMoved()
|
|||||||
|
|
||||||
void PasswordGeneratorWidget::spinBoxChanged()
|
void PasswordGeneratorWidget::spinBoxChanged()
|
||||||
{
|
{
|
||||||
|
if (m_updatingSpinBox) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Interlock so that we don't update twice - this causes issues as the spinbox can go higher than slider
|
// Interlock so that we don't update twice - this causes issues as the spinbox can go higher than slider
|
||||||
m_updatingSpinBox = true;
|
m_updatingSpinBox = true;
|
||||||
|
|
||||||
@ -161,12 +173,39 @@ PasswordGenerator::GeneratorFlags PasswordGeneratorWidget::generatorFlags()
|
|||||||
|
|
||||||
void PasswordGeneratorWidget::updateGenerator()
|
void PasswordGeneratorWidget::updateGenerator()
|
||||||
{
|
{
|
||||||
m_generator->setLength(m_ui->spinBoxLength->value());
|
PasswordGenerator::CharClasses classes = charClasses();
|
||||||
m_generator->setCharClasses(charClasses());
|
PasswordGenerator::GeneratorFlags flags = generatorFlags();
|
||||||
m_generator->setFlags(generatorFlags());
|
|
||||||
|
|
||||||
if (m_generator->isValid()) {
|
int minLength = 0;
|
||||||
QString password = m_generator->generatePassword();
|
if (flags.testFlag(PasswordGenerator::CharFromEveryGroup)) {
|
||||||
m_ui->editNewPassword->setEditText(password);
|
if (classes.testFlag(PasswordGenerator::LowerLetters)) {
|
||||||
|
minLength++;
|
||||||
|
}
|
||||||
|
if (classes.testFlag(PasswordGenerator::UpperLetters)) {
|
||||||
|
minLength++;
|
||||||
|
}
|
||||||
|
if (classes.testFlag(PasswordGenerator::Numbers)) {
|
||||||
|
minLength++;
|
||||||
|
}
|
||||||
|
if (classes.testFlag(PasswordGenerator::SpecialCharacters)) {
|
||||||
|
minLength++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
minLength = qMax(minLength, 1);
|
||||||
|
|
||||||
|
if (m_ui->spinBoxLength->value() < minLength) {
|
||||||
|
m_updatingSpinBox = true;
|
||||||
|
m_ui->spinBoxLength->setValue(minLength);
|
||||||
|
m_ui->sliderLength->setValue(minLength);
|
||||||
|
m_updatingSpinBox = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ui->spinBoxLength->setMinimum(minLength);
|
||||||
|
m_ui->sliderLength->setMinimum(minLength);
|
||||||
|
|
||||||
|
m_generator->setLength(m_ui->spinBoxLength->value());
|
||||||
|
m_generator->setCharClasses(classes);
|
||||||
|
m_generator->setFlags(flags);
|
||||||
|
|
||||||
|
regeneratePassword();
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ public:
|
|||||||
~PasswordGeneratorWidget();
|
~PasswordGeneratorWidget();
|
||||||
void loadSettings();
|
void loadSettings();
|
||||||
void reset();
|
void reset();
|
||||||
|
void regeneratePassword();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void newPassword(const QString& password);
|
void newPassword(const QString& password);
|
||||||
|
@ -414,55 +414,60 @@ void EditEntryWidget::saveEntry()
|
|||||||
// we don't want to create a new history item, if only the history has changed
|
// we don't want to create a new history item, if only the history has changed
|
||||||
m_entry->removeHistoryItems(m_historyModel->deletedEntries());
|
m_entry->removeHistoryItems(m_historyModel->deletedEntries());
|
||||||
|
|
||||||
|
m_autoTypeAssoc->removeEmpty();
|
||||||
|
|
||||||
if (!m_create) {
|
if (!m_create) {
|
||||||
m_entry->beginUpdate();
|
m_entry->beginUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_entry->setTitle(m_mainUi->titleEdit->text());
|
updateEntryData(m_entry);
|
||||||
m_entry->setUsername(m_mainUi->usernameEdit->text());
|
|
||||||
m_entry->setUrl(m_mainUi->urlEdit->text());
|
|
||||||
m_entry->setPassword(m_mainUi->passwordEdit->text());
|
|
||||||
m_entry->setExpires(m_mainUi->expireCheck->isChecked());
|
|
||||||
m_entry->setExpiryTime(m_mainUi->expireDatePicker->dateTime().toUTC());
|
|
||||||
|
|
||||||
m_entry->setNotes(m_mainUi->notesEdit->toPlainText());
|
|
||||||
|
|
||||||
m_entry->attributes()->copyCustomKeysFrom(m_entryAttributes);
|
|
||||||
m_entry->attachments()->copyDataFrom(m_entryAttachments);
|
|
||||||
|
|
||||||
IconStruct iconStruct = m_iconsWidget->save();
|
|
||||||
|
|
||||||
if (iconStruct.number < 0) {
|
|
||||||
m_entry->setIcon(Entry::DefaultIconNumber);
|
|
||||||
}
|
|
||||||
else if (iconStruct.uuid.isNull()) {
|
|
||||||
m_entry->setIcon(iconStruct.number);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_entry->setIcon(iconStruct.uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_entry->setAutoTypeEnabled(m_autoTypeUi->enableButton->isChecked());
|
|
||||||
if (m_autoTypeUi->inheritSequenceButton->isChecked()) {
|
|
||||||
m_entry->setDefaultAutoTypeSequence(QString());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_entry->setDefaultAutoTypeSequence(m_autoTypeUi->sequenceEdit->text());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_autoTypeAssoc->removeEmpty();
|
|
||||||
m_entry->autoTypeAssociations()->copyDataFrom(m_autoTypeAssoc);
|
|
||||||
|
|
||||||
if (!m_create) {
|
if (!m_create) {
|
||||||
m_entry->endUpdate();
|
m_entry->endUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
Q_EMIT editFinished(true);
|
Q_EMIT editFinished(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditEntryWidget::updateEntryData(Entry* entry) const
|
||||||
|
{
|
||||||
|
entry->setTitle(m_mainUi->titleEdit->text());
|
||||||
|
entry->setUsername(m_mainUi->usernameEdit->text());
|
||||||
|
entry->setUrl(m_mainUi->urlEdit->text());
|
||||||
|
entry->setPassword(m_mainUi->passwordEdit->text());
|
||||||
|
entry->setExpires(m_mainUi->expireCheck->isChecked());
|
||||||
|
entry->setExpiryTime(m_mainUi->expireDatePicker->dateTime().toUTC());
|
||||||
|
|
||||||
|
entry->setNotes(m_mainUi->notesEdit->toPlainText());
|
||||||
|
|
||||||
|
entry->attributes()->copyCustomKeysFrom(m_entryAttributes);
|
||||||
|
entry->attachments()->copyDataFrom(m_entryAttachments);
|
||||||
|
|
||||||
|
IconStruct iconStruct = m_iconsWidget->state();
|
||||||
|
|
||||||
|
if (iconStruct.number < 0) {
|
||||||
|
entry->setIcon(Entry::DefaultIconNumber);
|
||||||
|
}
|
||||||
|
else if (iconStruct.uuid.isNull()) {
|
||||||
|
entry->setIcon(iconStruct.number);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entry->setIcon(iconStruct.uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->setAutoTypeEnabled(m_autoTypeUi->enableButton->isChecked());
|
||||||
|
if (m_autoTypeUi->inheritSequenceButton->isChecked()) {
|
||||||
|
entry->setDefaultAutoTypeSequence(QString());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entry->setDefaultAutoTypeSequence(m_autoTypeUi->sequenceEdit->text());
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->autoTypeAssociations()->copyDataFrom(m_autoTypeAssoc);
|
||||||
|
}
|
||||||
|
|
||||||
void EditEntryWidget::cancel()
|
void EditEntryWidget::cancel()
|
||||||
{
|
{
|
||||||
if (m_history) {
|
if (m_history) {
|
||||||
@ -489,10 +494,28 @@ void EditEntryWidget::clear()
|
|||||||
m_entryAttachments->clear();
|
m_entryAttachments->clear();
|
||||||
m_autoTypeAssoc->clear();
|
m_autoTypeAssoc->clear();
|
||||||
m_historyModel->clear();
|
m_historyModel->clear();
|
||||||
|
m_iconsWidget->reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EditEntryWidget::hasBeenModified() const
|
||||||
|
{
|
||||||
|
// entry has been modified if a history item is to be deleted
|
||||||
|
if (!m_historyModel->deletedEntries().isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if updating the entry would modify it
|
||||||
|
QScopedPointer<Entry> entry(new Entry());
|
||||||
|
entry->copyDataFrom(m_entry);
|
||||||
|
|
||||||
|
entry->beginUpdate();
|
||||||
|
updateEntryData(entry.data());
|
||||||
|
return entry->endUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditEntryWidget::togglePasswordGeneratorButton(bool checked)
|
void EditEntryWidget::togglePasswordGeneratorButton(bool checked)
|
||||||
{
|
{
|
||||||
|
m_mainUi->passwordGenerator->regeneratePassword();
|
||||||
m_mainUi->passwordGenerator->setVisible(checked);
|
m_mainUi->passwordGenerator->setVisible(checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ public:
|
|||||||
void createPresetsMenu(QMenu* expirePresetsMenu);
|
void createPresetsMenu(QMenu* expirePresetsMenu);
|
||||||
QString entryTitle() const;
|
QString entryTitle() const;
|
||||||
void clear();
|
void clear();
|
||||||
|
bool hasBeenModified() const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void editFinished(bool accepted);
|
void editFinished(bool accepted);
|
||||||
@ -107,6 +108,7 @@ private:
|
|||||||
bool passwordsEqual();
|
bool passwordsEqual();
|
||||||
void setForms(const Entry* entry, bool restore = false);
|
void setForms(const Entry* entry, bool restore = false);
|
||||||
QMenu* createPresetsMenu();
|
QMenu* createPresetsMenu();
|
||||||
|
void updateEntryData(Entry* entry) const;
|
||||||
|
|
||||||
Entry* m_entry;
|
Entry* m_entry;
|
||||||
Database* m_database;
|
Database* m_database;
|
||||||
|
@ -232,7 +232,8 @@ void EntryAttributesModel::updateAttributes()
|
|||||||
{
|
{
|
||||||
m_attributes.clear();
|
m_attributes.clear();
|
||||||
|
|
||||||
Q_FOREACH (const QString& key, m_entryAttributes->keys()) {
|
const QList<QString> attributesKeyList = m_entryAttributes->keys();
|
||||||
|
for (const QString& key : attributesKeyList) {
|
||||||
if (!EntryAttributes::isDefaultAttribute(key)) {
|
if (!EntryAttributes::isDefaultAttribute(key)) {
|
||||||
m_attributes.append(key);
|
m_attributes.append(key);
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "EntryHistoryModel.h"
|
#include "EntryHistoryModel.h"
|
||||||
|
|
||||||
#include "core/Entry.h"
|
#include "core/Entry.h"
|
||||||
|
#include "core/Global.h"
|
||||||
|
|
||||||
EntryHistoryModel::EntryHistoryModel(QObject* parent)
|
EntryHistoryModel::EntryHistoryModel(QObject* parent)
|
||||||
: QAbstractTableModel(parent)
|
: QAbstractTableModel(parent)
|
||||||
@ -136,7 +137,7 @@ void EntryHistoryModel::deleteAll()
|
|||||||
|
|
||||||
beginRemoveRows(QModelIndex(), 0, m_historyEntries.size() - 1);
|
beginRemoveRows(QModelIndex(), 0, m_historyEntries.size() - 1);
|
||||||
|
|
||||||
Q_FOREACH (Entry* entry, m_historyEntries) {
|
for (Entry* entry : asConst(m_historyEntries)) {
|
||||||
m_deletedHistoryEntries << entry;
|
m_deletedHistoryEntries << entry;
|
||||||
}
|
}
|
||||||
m_historyEntries.clear();
|
m_historyEntries.clear();
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "core/DatabaseIcons.h"
|
#include "core/DatabaseIcons.h"
|
||||||
#include "core/Entry.h"
|
#include "core/Entry.h"
|
||||||
|
#include "core/Global.h"
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
|
|
||||||
@ -78,13 +79,14 @@ void EntryModel::setEntryList(const QList<Entry*>& entries)
|
|||||||
|
|
||||||
QSet<Database*> databases;
|
QSet<Database*> databases;
|
||||||
|
|
||||||
Q_FOREACH (Entry* entry, m_entries) {
|
for (Entry* entry : asConst(m_entries)) {
|
||||||
databases.insert(entry->group()->database());
|
databases.insert(entry->group()->database());
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (Database* db, databases) {
|
for (Database* db : asConst(databases)) {
|
||||||
Q_ASSERT(db);
|
Q_ASSERT(db);
|
||||||
Q_FOREACH (const Group* group, db->rootGroup()->groupsRecursive(true)) {
|
const QList<Group*> groupList = db->rootGroup()->groupsRecursive(true);
|
||||||
|
for (const Group* group : groupList) {
|
||||||
m_allGroups.append(group);
|
m_allGroups.append(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +95,7 @@ void EntryModel::setEntryList(const QList<Entry*>& entries)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (const Group* group, m_allGroups) {
|
for (const Group* group : asConst(m_allGroups)) {
|
||||||
makeConnections(group);
|
makeConnections(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +226,7 @@ QMimeData* EntryModel::mimeData(const QModelIndexList& indexes) const
|
|||||||
|
|
||||||
QSet<Entry*> seenEntries;
|
QSet<Entry*> seenEntries;
|
||||||
|
|
||||||
Q_FOREACH (const QModelIndex& index, indexes) {
|
for (const QModelIndex& index : indexes) {
|
||||||
if (!index.isValid()) {
|
if (!index.isValid()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -301,7 +303,7 @@ void EntryModel::severConnections()
|
|||||||
disconnect(m_group, nullptr, this, nullptr);
|
disconnect(m_group, nullptr, this, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH (const Group* group, m_allGroups) {
|
for (const Group* group : asConst(m_allGroups)) {
|
||||||
disconnect(group, nullptr, this, nullptr);
|
disconnect(group, nullptr, this, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ void EditGroupWidget::save()
|
|||||||
m_group->setDefaultAutoTypeSequence(m_mainUi->autoTypeSequenceCustomEdit->text());
|
m_group->setDefaultAutoTypeSequence(m_mainUi->autoTypeSequenceCustomEdit->text());
|
||||||
}
|
}
|
||||||
|
|
||||||
IconStruct iconStruct = m_editGroupWidgetIcons->save();
|
IconStruct iconStruct = m_editGroupWidgetIcons->state();
|
||||||
|
|
||||||
if (iconStruct.number < 0) {
|
if (iconStruct.number < 0) {
|
||||||
m_group->setIcon(Group::DefaultIconNumber);
|
m_group->setIcon(Group::DefaultIconNumber);
|
||||||
@ -144,6 +144,7 @@ void EditGroupWidget::clear()
|
|||||||
{
|
{
|
||||||
m_group = nullptr;
|
m_group = nullptr;
|
||||||
m_database = nullptr;
|
m_database = nullptr;
|
||||||
|
m_editGroupWidgetIcons->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditGroupWidget::addTriStateItems(QComboBox* comboBox, bool inheritDefault)
|
void EditGroupWidget::addTriStateItems(QComboBox* comboBox, bool inheritDefault)
|
||||||
|
@ -338,7 +338,7 @@ QMimeData* GroupModel::mimeData(const QModelIndexList& indexes) const
|
|||||||
|
|
||||||
QSet<Group*> seenGroups;
|
QSet<Group*> seenGroups;
|
||||||
|
|
||||||
Q_FOREACH (const QModelIndex& index, indexes) {
|
for (const QModelIndex& index : indexes) {
|
||||||
if (!index.isValid()) {
|
if (!index.isValid()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,8 @@ void GroupView::recInitExpanded(Group* group)
|
|||||||
expandGroup(group, group->isExpanded());
|
expandGroup(group, group->isExpanded());
|
||||||
m_updatingExpanded = false;
|
m_updatingExpanded = false;
|
||||||
|
|
||||||
Q_FOREACH (Group* child, group->children()) {
|
const QList<Group*> children = group->children();
|
||||||
|
for (Group* child : children) {
|
||||||
recInitExpanded(child);
|
recInitExpanded(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <QtConcurrent>
|
#include <QtConcurrent>
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
|
|
||||||
|
#include "core/Global.h"
|
||||||
#include "crypto/CryptoHash.h"
|
#include "crypto/CryptoHash.h"
|
||||||
#include "crypto/SymmetricCipher.h"
|
#include "crypto/SymmetricCipher.h"
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ CompositeKey& CompositeKey::operator=(const CompositeKey& key)
|
|||||||
|
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
Q_FOREACH (const Key* subKey, key.m_keys) {
|
for (const Key* subKey : asConst(key.m_keys)) {
|
||||||
addKey(*subKey);
|
addKey(*subKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +75,7 @@ QByteArray CompositeKey::rawKey() const
|
|||||||
{
|
{
|
||||||
CryptoHash cryptoHash(CryptoHash::Sha256);
|
CryptoHash cryptoHash(CryptoHash::Sha256);
|
||||||
|
|
||||||
Q_FOREACH (const Key* key, m_keys) {
|
for (const Key* key : m_keys) {
|
||||||
cryptoHash.addData(key->rawKey());
|
cryptoHash.addData(key->rawKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,8 +95,8 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (config()->get("OpenPreviousDatabasesOnStartup").toBool()) {
|
if (config()->get("OpenPreviousDatabasesOnStartup").toBool()) {
|
||||||
QStringList filenames = config()->get("LastOpenedDatabases").toStringList();
|
const QStringList filenames = config()->get("LastOpenedDatabases").toStringList();
|
||||||
Q_FOREACH (const QString& filename, filenames) {
|
for (const QString& filename : filenames) {
|
||||||
if (!filename.isEmpty() && QFile::exists(filename)) {
|
if (!filename.isEmpty() && QFile::exists(filename)) {
|
||||||
mainWindow.openDatabase(filename, QString(), QString());
|
mainWindow.openDatabase(filename, QString(), QString());
|
||||||
}
|
}
|
||||||
|
@ -385,7 +385,12 @@ void TestGroup::testClone()
|
|||||||
QVERIFY(clonedSubGroupEntry->uuid() != subGroupEntry->uuid());
|
QVERIFY(clonedSubGroupEntry->uuid() != subGroupEntry->uuid());
|
||||||
QCOMPARE(clonedSubGroupEntry->title(), QString("SubGroupEntry"));
|
QCOMPARE(clonedSubGroupEntry->title(), QString("SubGroupEntry"));
|
||||||
|
|
||||||
|
Group* clonedGroupKeepUuid = originalGroup->clone(Entry::CloneNoFlags);
|
||||||
|
QCOMPARE(clonedGroupKeepUuid->entries().at(0)->uuid(), originalGroupEntry->uuid());
|
||||||
|
QCOMPARE(clonedGroupKeepUuid->children().at(0)->entries().at(0)->uuid(), subGroupEntry->uuid());
|
||||||
|
|
||||||
delete clonedGroup;
|
delete clonedGroup;
|
||||||
|
delete clonedGroupKeepUuid;
|
||||||
delete db;
|
delete db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "TestKeePass2Writer.h"
|
#include "TestKeePass2Writer.h"
|
||||||
|
|
||||||
#include <QBuffer>
|
#include <QBuffer>
|
||||||
|
#include <QFile>
|
||||||
#include <QTest>
|
#include <QTest>
|
||||||
|
|
||||||
#include "config-keepassx-tests.h"
|
#include "config-keepassx-tests.h"
|
||||||
|
@ -406,6 +406,8 @@ void TestKeePass2XmlReader::testBroken_data()
|
|||||||
QTest::newRow("BrokenGroupReference (not strict)") << "BrokenGroupReference" << false << false;
|
QTest::newRow("BrokenGroupReference (not strict)") << "BrokenGroupReference" << false << false;
|
||||||
QTest::newRow("BrokenDeletedObjects (strict)") << "BrokenDeletedObjects" << true << true;
|
QTest::newRow("BrokenDeletedObjects (strict)") << "BrokenDeletedObjects" << true << true;
|
||||||
QTest::newRow("BrokenDeletedObjects (not strict)") << "BrokenDeletedObjects" << false << false;
|
QTest::newRow("BrokenDeletedObjects (not strict)") << "BrokenDeletedObjects" << false << false;
|
||||||
|
QTest::newRow("BrokenDifferentEntryHistoryUuid (strict)") << "BrokenDifferentEntryHistoryUuid" << true << true;
|
||||||
|
QTest::newRow("BrokenDifferentEntryHistoryUuid (not strict)") << "BrokenDifferentEntryHistoryUuid" << false << false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestKeePass2XmlReader::testEmptyUuids()
|
void TestKeePass2XmlReader::testEmptyUuids()
|
||||||
@ -486,6 +488,32 @@ void TestKeePass2XmlReader::testInvalidXmlChars()
|
|||||||
QCOMPARE(strToBytes(attrRead->value("SurrogateValid2")), strToBytes(strSurrogateValid2));
|
QCOMPARE(strToBytes(attrRead->value("SurrogateValid2")), strToBytes(strSurrogateValid2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestKeePass2XmlReader::testRepairUuidHistoryItem()
|
||||||
|
{
|
||||||
|
KeePass2XmlReader reader;
|
||||||
|
QString xmlFile = QString("%1/%2.xml").arg(KEEPASSX_TEST_DATA_DIR, "BrokenDifferentEntryHistoryUuid");
|
||||||
|
QVERIFY(QFile::exists(xmlFile));
|
||||||
|
QScopedPointer<Database> db(reader.readDatabase(xmlFile));
|
||||||
|
if (reader.hasError()) {
|
||||||
|
qWarning("Database read error: %s", qPrintable(reader.errorString()));
|
||||||
|
}
|
||||||
|
QVERIFY(!reader.hasError());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
QList<Entry*> entries = db.data()->rootGroup()->entries();
|
||||||
|
QCOMPARE(entries.size(), 1);
|
||||||
|
Entry* entry = entries.at(0);
|
||||||
|
|
||||||
|
QList<Entry*> historyItems = entry->historyItems();
|
||||||
|
QCOMPARE(historyItems.size(), 1);
|
||||||
|
Entry* historyItem = historyItems.at(0);
|
||||||
|
|
||||||
|
QVERIFY(!entry->uuid().isNull());
|
||||||
|
QVERIFY(!historyItem->uuid().isNull());
|
||||||
|
QCOMPARE(historyItem->uuid(), entry->uuid());
|
||||||
|
}
|
||||||
|
|
||||||
void TestKeePass2XmlReader::cleanupTestCase()
|
void TestKeePass2XmlReader::cleanupTestCase()
|
||||||
{
|
{
|
||||||
delete m_db;
|
delete m_db;
|
||||||
|
@ -43,6 +43,7 @@ private Q_SLOTS:
|
|||||||
void testBroken_data();
|
void testBroken_data();
|
||||||
void testEmptyUuids();
|
void testEmptyUuids();
|
||||||
void testInvalidXmlChars();
|
void testInvalidXmlChars();
|
||||||
|
void testRepairUuidHistoryItem();
|
||||||
void cleanupTestCase();
|
void cleanupTestCase();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
17
tests/data/BrokenDifferentEntryHistoryUuid.xml
Normal file
17
tests/data/BrokenDifferentEntryHistoryUuid.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
|
<KeePassFile>
|
||||||
|
<Root>
|
||||||
|
<Group>
|
||||||
|
<UUID>lmU+9n0aeESKZvcEze+bRg==</UUID>
|
||||||
|
<Name>Test</Name>
|
||||||
|
<Entry>
|
||||||
|
<UUID>MTExMTExMTExMTExMTExMQ==</UUID>
|
||||||
|
<History>
|
||||||
|
<Entry>
|
||||||
|
<UUID>MjIyMjIyMjIyMjIyMjIyMg==</UUID>
|
||||||
|
</Entry>
|
||||||
|
</History>
|
||||||
|
</Entry>
|
||||||
|
</Group>
|
||||||
|
</Root>
|
||||||
|
</KeePassFile>
|
@ -240,6 +240,7 @@ void TestGui::testSearch()
|
|||||||
QVERIFY(entryDeleteWidget->isEnabled());
|
QVERIFY(entryDeleteWidget->isEnabled());
|
||||||
QVERIFY(!m_db->metadata()->recycleBin());
|
QVERIFY(!m_db->metadata()->recycleBin());
|
||||||
|
|
||||||
|
MessageBox::setNextAnswer(QMessageBox::Yes);
|
||||||
QTest::mouseClick(entryDeleteWidget, Qt::LeftButton);
|
QTest::mouseClick(entryDeleteWidget, Qt::LeftButton);
|
||||||
|
|
||||||
QCOMPARE(entryView->model()->rowCount(), 3);
|
QCOMPARE(entryView->model()->rowCount(), 3);
|
||||||
|
Loading…
Reference in New Issue
Block a user