Skip to content

Commit

Permalink
Separate parsing of references from main removal process.
Browse files Browse the repository at this point in the history
  • Loading branch information
wgml committed Apr 7, 2018
1 parent b65cabd commit 46d3e90
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 144 deletions.
36 changes: 19 additions & 17 deletions src/core/Database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include <QTextStream>
#include <QTimer>
#include <QXmlStreamReader>
#include <algorithm>
#include <QtConcurrent>

#include "cli/Utils.h"
#include "core/Group.h"
Expand Down Expand Up @@ -201,29 +201,31 @@ Group* Database::findGroupRecursive(const Uuid& uuid, Group* group)
return nullptr;
}

namespace
QList<Entry*> Database::resolveReferences(const Uuid& uuid) const
{
QList<Entry*> resolveReferencesRecursive(const Uuid& uuid, const Group* group)
{
const QString usernameRef = Tools::usernameReference(uuid).toUpper();
const QString passwordRef = Tools::usernameReference(uuid).toUpper();
auto isReference = [&usernameRef, &passwordRef](const Entry* e) {
return e->username() == usernameRef || e->password() == passwordRef;
};
return resolveReferences(uuid, m_rootGroup);
}

QList<Entry*> result;
std::copy_if(group->entries().begin(), group->entries().end(), std::back_inserter(result), isReference);
QList<Entry*> Database::resolveReferences(const Uuid& uuid, const Group* group) const
{
auto isReference = [&uuid](const Entry* e) { return e->hasReferencesTo(uuid); };

for (Group* child : group->children())
result += resolveReferencesRecursive(uuid, child);
QList<Entry*> result = QtConcurrent::blockingFiltered(group->entries(), isReference);

return result;
for (Group* child : group->children()) {
result += resolveReferences(uuid, child);
}
} // namespace
return result;
}

QList<Entry*> Database::resolveReferences(const Uuid& uuid)
void Database::replaceReferencesWithValues(Entry* entry, QList<Entry*> references)
{
return resolveReferencesRecursive(uuid, m_rootGroup);
for (Entry* reference : references) {
for (const QString& key : EntryAttributes::DefaultAttributes) {
if (reference->isAttributeReferenceOf(key, entry->uuid()))
reference->setDefaultAttribute(key, entry->attribute(key));
}
}
}

QList<DeletedObject> Database::deletedObjects()
Expand Down
4 changes: 3 additions & 1 deletion src/core/Database.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ class Database : public QObject
Entry* resolveEntry(const Uuid& uuid);
Entry* resolveEntry(const QString& text, EntryReferenceType referenceType);
Group* resolveGroup(const Uuid& uuid);
QList<Entry*> resolveReferences(const Uuid& uuid);
QList<Entry*> resolveReferences(const Uuid& uuid) const;
QList<Entry*> resolveReferences(const Uuid& uuid, const Group* group) const;
void replaceReferencesWithValues(Entry* entry, QList<Entry*> references);
QList<DeletedObject> deletedObjects();
void addDeletedObject(const DeletedObject& delObj);
void addDeletedObject(const Uuid& uuid);
Expand Down
38 changes: 36 additions & 2 deletions src/core/Entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,11 +307,25 @@ QString Entry::notes() const
return m_attributes->value(EntryAttributes::NotesKey);
}

QString Entry::attribute(const QString& key) const
{
return m_attributes->value(key);
}

bool Entry::isExpired() const
{
return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < QDateTime::currentDateTimeUtc();
}

bool Entry::isAttributeReferenceOf(const QString& key, const Uuid& uuid) const
{
if (!m_attributes->isReference(key))
return false;

const QString ref = Tools::reference(uuid, key).toUpper();
return m_attributes->value(key) == ref;
}

bool Entry::hasReferences() const
{
const QList<QString> keyList = EntryAttributes::DefaultAttributes;
Expand All @@ -323,6 +337,16 @@ bool Entry::hasReferences() const
return false;
}

bool Entry::hasReferencesTo(const Uuid& uuid) const
{
const QList<QString> keyList = EntryAttributes::DefaultAttributes;
for (const QString& key : keyList) {
if (isAttributeReferenceOf(key, uuid))
return true;
}
return false;
}

EntryAttributes* Entry::attributes()
{
return m_attributes;
Expand Down Expand Up @@ -528,6 +552,16 @@ void Entry::setNotes(const QString& notes)
m_attributes->set(EntryAttributes::NotesKey, notes, m_attributes->isProtected(EntryAttributes::NotesKey));
}

void Entry::setDefaultAttribute(const QString& attribute, const QString& value)
{
Q_ASSERT(EntryAttributes::isDefaultAttribute(attribute));

if (!EntryAttributes::isDefaultAttribute(attribute))
return;

m_attributes->set(attribute, value, m_attributes->isProtected(attribute));
}

void Entry::setExpires(const bool& value)
{
if (m_data.timeInfo.expires() != value) {
Expand Down Expand Up @@ -652,12 +686,12 @@ Entry* Entry::clone(CloneFlags flags) const

if (flags & CloneUserAsRef) {
// Build the username reference
QString username = Tools::usernameReference(m_uuid);
QString username = Tools::reference(m_uuid, EntryAttributes::UserNameKey);
entry->m_attributes->set(EntryAttributes::UserNameKey, username.toUpper(), m_attributes->isProtected(EntryAttributes::UserNameKey));
}

if (flags & ClonePassAsRef) {
QString password = Tools::passwordReference(m_uuid);
QString password = Tools::reference(m_uuid, EntryAttributes::PasswordKey);
entry->m_attributes->set(EntryAttributes::PasswordKey, password.toUpper(), m_attributes->isProtected(EntryAttributes::PasswordKey));
}

Expand Down
4 changes: 4 additions & 0 deletions src/core/Entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,17 @@ class Entry : public QObject
QString username() const;
QString password() const;
QString notes() const;
QString attribute(const QString& key) const;
QString totp() const;
QString totpSeed() const;
quint8 totpDigits() const;
quint8 totpStep() const;

bool hasTotp() const;
bool isExpired() const;
bool isAttributeReferenceOf(const QString& key, const Uuid& uuid) const;
bool hasReferences() const;
bool hasReferencesTo(const Uuid& uuid) const;
EntryAttributes* attributes();
const EntryAttributes* attributes() const;
EntryAttachments* attachments();
Expand Down Expand Up @@ -132,6 +135,7 @@ class Entry : public QObject
void setUsername(const QString& username);
void setPassword(const QString& password);
void setNotes(const QString& notes);
void setDefaultAttribute(const QString& attribute, const QString& value);
void setExpires(const bool& value);
void setExpiryTime(const QDateTime& dateTime);
void setTotp(const QString& seed, quint8& step, quint8& digits);
Expand Down
24 changes: 16 additions & 8 deletions src/core/Tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <time.h> // for nanosleep()
#endif

#include "EntryAttributes.h"
#include "config-keepassx.h"

#if defined(HAVE_RLIMIT_CORE)
Expand Down Expand Up @@ -357,14 +358,21 @@ bool createWindowsDACL()
return bSuccess;
}

QString usernameReference(const Uuid& uuid)
QString reference(const Uuid& uuid, const QString& field)
{
return "{REF:U@I:" + uuid.toHex() + "}";
Q_ASSERT(EntryAttributes::DefaultAttributes.count(field) > 0);

if (field == EntryAttributes::TitleKey)
return "{REF:T@I:" + uuid.toHex() + "}";
if (field == EntryAttributes::UserNameKey)
return "{REF:U@I:" + uuid.toHex() + "}";
if (field == EntryAttributes::PasswordKey)
return "{REF:P@I:" + uuid.toHex() + "}";
if (field == EntryAttributes::URLKey)
return "{REF:A@I:" + uuid.toHex() + "}";
if (field == EntryAttributes::NotesKey)
return "{REF:N@I:" + uuid.toHex() + "}";

__builtin_unreachable();
}

QString passwordReference(const Uuid& uuid)
{
return "{REF:P@I:" + uuid.toHex() + "}";
}

} // namespace Tools
3 changes: 1 addition & 2 deletions src/core/Tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ void wait(int ms);
void disableCoreDumps();
void setupSearchPaths();
bool createWindowsDACL();
QString usernameReference(const Uuid& uuid);
QString passwordReference(const Uuid& uuid);
QString reference(const Uuid& uuid, const QString& field);

template <typename RandomAccessIterator, typename T>
RandomAccessIterator binaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T& value)
Expand Down
Loading

0 comments on commit 46d3e90

Please sign in to comment.