mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-12-27 00:09:53 -05:00
Merge pull request #1388 from hicknhack-software/hotfix/1387_entry-size
Add extend entry-size calculation (resolved #1387)
This commit is contained in:
commit
50beac2baf
@ -103,6 +103,15 @@ int AutoTypeAssociations::size() const
|
||||
return m_associations.size();
|
||||
}
|
||||
|
||||
int AutoTypeAssociations::associationsSize() const
|
||||
{
|
||||
int size = 0;
|
||||
for (const Association &association : m_associations) {
|
||||
size += association.sequence.toUtf8().size() + association.window.toUtf8().size();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void AutoTypeAssociations::clear()
|
||||
{
|
||||
m_associations.clear();
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
AutoTypeAssociations::Association get(int index) const;
|
||||
QList<AutoTypeAssociations::Association> getAll() const;
|
||||
int size() const;
|
||||
int associationsSize() const;
|
||||
void clear();
|
||||
|
||||
private:
|
||||
|
@ -582,22 +582,24 @@ void Entry::truncateHistory()
|
||||
int histMaxSize = db->metadata()->historyMaxSize();
|
||||
if (histMaxSize > -1) {
|
||||
int size = 0;
|
||||
QSet<QByteArray> foundAttachments = attachments()->values().toSet();
|
||||
QSet<QByteArray> foundAttachments = attachments()->values();
|
||||
|
||||
QMutableListIterator<Entry*> i(m_history);
|
||||
i.toBack();
|
||||
const QRegularExpression delimiter(",|:|;");
|
||||
while (i.hasPrevious()) {
|
||||
Entry* historyItem = i.previous();
|
||||
|
||||
// don't calculate size if it's already above the maximum
|
||||
if (size <= histMaxSize) {
|
||||
size += historyItem->attributes()->attributesSize();
|
||||
|
||||
const QSet<QByteArray> newAttachments = historyItem->attachments()->values().toSet() - foundAttachments;
|
||||
for (const QByteArray& attachment : newAttachments) {
|
||||
size += attachment.size();
|
||||
size += historyItem->autoTypeAssociations()->associationsSize();
|
||||
size += historyItem->attachments()->attachmentsSize();
|
||||
const QStringList tags = historyItem->tags().split(delimiter, QString::SkipEmptyParts);
|
||||
for (const QString& tag : tags) {
|
||||
size += tag.toUtf8().size();
|
||||
}
|
||||
foundAttachments += newAttachments;
|
||||
foundAttachments += historyItem->attachments()->values();
|
||||
}
|
||||
|
||||
if (size > histMaxSize) {
|
||||
@ -633,7 +635,7 @@ Entry* Entry::clone(CloneFlags flags) const
|
||||
entry->m_attributes->set(EntryAttributes::PasswordKey, password.toUpper(), m_attributes->isProtected(EntryAttributes::PasswordKey));
|
||||
}
|
||||
|
||||
entry->m_autoTypeAssociations->copyDataFrom(this->m_autoTypeAssociations);
|
||||
entry->m_autoTypeAssociations->copyDataFrom(m_autoTypeAssociations);
|
||||
if (flags & CloneIncludeHistory) {
|
||||
for (Entry* historyItem : m_history) {
|
||||
Entry* historyItemClone = historyItem->clone(flags & ~CloneIncludeHistory & ~CloneNewUuid);
|
||||
@ -679,6 +681,7 @@ void Entry::beginUpdate()
|
||||
m_tmpHistoryItem->m_data = m_data;
|
||||
m_tmpHistoryItem->m_attributes->copyDataFrom(m_attributes);
|
||||
m_tmpHistoryItem->m_attachments->copyDataFrom(m_attachments);
|
||||
m_tmpHistoryItem->m_autoTypeAssociations->copyDataFrom(m_autoTypeAssociations);
|
||||
|
||||
m_modifiedSinceBegin = false;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "EntryAttachments.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QSet>
|
||||
|
||||
EntryAttachments::EntryAttachments(QObject* parent)
|
||||
: QObject(parent)
|
||||
@ -34,9 +35,9 @@ bool EntryAttachments::hasKey(const QString& key) const
|
||||
return m_attachments.contains(key);
|
||||
}
|
||||
|
||||
QList<QByteArray> EntryAttachments::values() const
|
||||
QSet<QByteArray> EntryAttachments::values() const
|
||||
{
|
||||
return m_attachments.values();
|
||||
return m_attachments.values().toSet();
|
||||
}
|
||||
|
||||
QByteArray EntryAttachments::value(const QString& key) const
|
||||
@ -151,3 +152,12 @@ bool EntryAttachments::operator!=(const EntryAttachments& other) const
|
||||
{
|
||||
return m_attachments != other.m_attachments;
|
||||
}
|
||||
|
||||
int EntryAttachments::attachmentsSize() const
|
||||
{
|
||||
int size = 0;
|
||||
for (auto it = m_attachments.constBegin(); it != m_attachments.constEnd(); ++it) {
|
||||
size += it.key().toUtf8().size() + it.value().size();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
explicit EntryAttachments(QObject* parent = nullptr);
|
||||
QList<QString> keys() const;
|
||||
bool hasKey(const QString& key) const;
|
||||
QList<QByteArray> values() const;
|
||||
QSet<QByteArray> values() const;
|
||||
QByteArray value(const QString& key) const;
|
||||
void set(const QString& key, const QByteArray& value);
|
||||
void remove(const QString& key);
|
||||
@ -41,6 +41,7 @@ public:
|
||||
void copyDataFrom(const EntryAttachments* other);
|
||||
bool operator==(const EntryAttachments& other) const;
|
||||
bool operator!=(const EntryAttachments& other) const;
|
||||
int attachmentsSize() const;
|
||||
|
||||
signals:
|
||||
void modified();
|
||||
|
@ -283,14 +283,11 @@ void EntryAttributes::clear()
|
||||
emit modified();
|
||||
}
|
||||
|
||||
int EntryAttributes::attributesSize()
|
||||
int EntryAttributes::attributesSize() const
|
||||
{
|
||||
int size = 0;
|
||||
|
||||
QMapIterator<QString, QString> i(m_attributes);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
size += i.value().toUtf8().size();
|
||||
for (auto it = m_attributes.constBegin(); it != m_attributes.constEnd(); ++it) {
|
||||
size += it.key().toUtf8().size() + it.value().toUtf8().size();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
void copyCustomKeysFrom(const EntryAttributes* other);
|
||||
bool areCustomKeysDifferent(const EntryAttributes* other);
|
||||
void clear();
|
||||
int attributesSize();
|
||||
int attributesSize() const;
|
||||
void copyDataFrom(const EntryAttributes* other);
|
||||
bool operator==(const EntryAttributes& other) const;
|
||||
bool operator!=(const EntryAttributes& other) const;
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#include <QTest>
|
||||
|
||||
#include "core/Database.h"
|
||||
#include "core/Entry.h"
|
||||
#include "core/Group.h"
|
||||
#include "crypto/Crypto.h"
|
||||
@ -48,6 +47,7 @@ void TestEntry::testHistoryItemDeletion()
|
||||
|
||||
delete entry;
|
||||
}
|
||||
|
||||
void TestEntry::testCopyDataFrom()
|
||||
{
|
||||
Entry* entry = new Entry();
|
||||
|
@ -288,14 +288,14 @@ void TestModified::testEntrySets()
|
||||
delete db;
|
||||
}
|
||||
|
||||
void TestModified::testHistoryItem()
|
||||
void TestModified::testHistoryItems()
|
||||
{
|
||||
Entry* entry = new Entry();
|
||||
QScopedPointer<Entry> entry(new Entry());
|
||||
QDateTime created = entry->timeInfo().creationTime();
|
||||
entry->setUuid(Uuid::random());
|
||||
entry->setTitle("a");
|
||||
entry->setTags("a");
|
||||
EntryAttributes* attributes = new EntryAttributes();
|
||||
QScopedPointer<EntryAttributes> attributes(new EntryAttributes());
|
||||
attributes->copyCustomKeysFrom(entry->attributes());
|
||||
|
||||
Entry* historyEntry;
|
||||
@ -338,15 +338,12 @@ void TestModified::testHistoryItem()
|
||||
|
||||
attributes->set("k", "myvalue");
|
||||
entry->beginUpdate();
|
||||
entry->attributes()->copyCustomKeysFrom(attributes);
|
||||
entry->attributes()->copyCustomKeysFrom(attributes.data());
|
||||
entry->endUpdate();
|
||||
QCOMPARE(entry->historyItems().size(), ++historyItemsSize);
|
||||
QVERIFY(!entry->historyItems().at(historyItemsSize - 1)->attributes()->keys().contains("k"));
|
||||
|
||||
delete attributes;
|
||||
delete entry;
|
||||
|
||||
Database* db = new Database();
|
||||
QScopedPointer<Database> db(new Database());
|
||||
Group* root = db->rootGroup();
|
||||
db->metadata()->setHistoryMaxItems(3);
|
||||
db->metadata()->setHistoryMaxSize(-1);
|
||||
@ -400,12 +397,16 @@ void TestModified::testHistoryItem()
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->historyItems().size(), 0);
|
||||
|
||||
db->metadata()->setHistoryMaxItems(-1);
|
||||
db->metadata()->setHistoryMaxSize(17000);
|
||||
const int historyMaxSize = 19000;
|
||||
|
||||
db->metadata()->setHistoryMaxItems(-1);
|
||||
db->metadata()->setHistoryMaxSize(historyMaxSize);
|
||||
|
||||
const QString key("test");
|
||||
entry2->beginUpdate();
|
||||
entry2->attachments()->set("test", QByteArray(18000, 'X'));
|
||||
entry2->attachments()->set(key, QByteArray(18000, 'X'));
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->attachments()->attachmentsSize(), 18000 + key.size());
|
||||
QCOMPARE(entry2->historyItems().size(), 1);
|
||||
|
||||
historyEntry2 = entry2->historyItems().at(0);
|
||||
@ -417,53 +418,167 @@ void TestModified::testHistoryItem()
|
||||
QCOMPARE(entry2->historyItems().size(), 2);
|
||||
|
||||
entry2->beginUpdate();
|
||||
entry2->attachments()->remove("test");
|
||||
entry2->attachments()->remove(key);
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->historyItems().size(), 0);
|
||||
QCOMPARE(entry2->attachments()->attachmentsSize(), 0);
|
||||
QCOMPARE(entry2->historyItems().size(), 1);
|
||||
|
||||
entry2->beginUpdate();
|
||||
entry2->attachments()->set("test2", QByteArray(6000, 'a'));
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->historyItems().size(), 1);
|
||||
QCOMPARE(entry2->attachments()->attachmentsSize(), 6000 + key.size() + 1);
|
||||
QCOMPARE(entry2->historyItems().size(), 2);
|
||||
|
||||
entry2->beginUpdate();
|
||||
entry2->attachments()->set("test3", QByteArray(6000, 'b'));
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->attachments()->attachmentsSize(), 12000 + (key.size() + 1) * 2);
|
||||
QCOMPARE(entry2->historyItems().size(), 2);
|
||||
|
||||
entry2->beginUpdate();
|
||||
entry2->attachments()->set("test4", QByteArray(6000, 'c'));
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->attachments()->attachmentsSize(), 18000 + (key.size() + 1) * 3);
|
||||
QCOMPARE(entry2->historyItems().size(), 3);
|
||||
|
||||
entry2->beginUpdate();
|
||||
entry2->attachments()->set("test5", QByteArray(6000, 'd'));
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->historyItems().size(), 4);
|
||||
|
||||
Entry* entry3 = new Entry();
|
||||
entry3->setGroup(root);
|
||||
QCOMPARE(entry3->historyItems().size(), 0);
|
||||
|
||||
entry3->beginUpdate();
|
||||
entry3->attachments()->set("test", QByteArray(6000, 'a'));
|
||||
entry3->endUpdate();
|
||||
QCOMPARE(entry3->historyItems().size(), 1);
|
||||
|
||||
entry3->beginUpdate();
|
||||
entry3->attachments()->set("test", QByteArray(6000, 'b'));
|
||||
entry3->endUpdate();
|
||||
QCOMPARE(entry3->historyItems().size(), 2);
|
||||
|
||||
entry3->beginUpdate();
|
||||
entry3->attachments()->set("test", QByteArray(6000, 'c'));
|
||||
entry3->endUpdate();
|
||||
QCOMPARE(entry3->historyItems().size(), 3);
|
||||
|
||||
entry3->beginUpdate();
|
||||
entry3->attachments()->set("test", QByteArray(6000, 'd'));
|
||||
entry3->endUpdate();
|
||||
QCOMPARE(entry3->historyItems().size(), 2);
|
||||
|
||||
delete db;
|
||||
QCOMPARE(entry2->attachments()->attachmentsSize(), 24000 + (key.size() + 1) * 4);
|
||||
QCOMPARE(entry2->historyItems().size(), 1);
|
||||
}
|
||||
|
||||
void TestModified::testHistoryMaxSize()
|
||||
{
|
||||
QScopedPointer<Database> db(new Database());
|
||||
const QString key("test");
|
||||
|
||||
|
||||
auto entry1 = new Entry();
|
||||
entry1->setGroup(db->rootGroup());
|
||||
QCOMPARE(entry1->historyItems().size(), 0);
|
||||
|
||||
const int reservedSize1 = entry1->attributes()->attributesSize();
|
||||
db->metadata()->setHistoryMaxItems(-1);
|
||||
db->metadata()->setHistoryMaxSize(18000 + key.size() * 3 + reservedSize1 * 4);
|
||||
|
||||
entry1->beginUpdate();
|
||||
entry1->attachments()->set(key, QByteArray(6000, 'a'));
|
||||
entry1->endUpdate();
|
||||
QCOMPARE(entry1->attachments()->attachmentsSize(), 6000 + key.size());
|
||||
QCOMPARE(entry1->historyItems().size(), 1);
|
||||
|
||||
entry1->beginUpdate();
|
||||
entry1->attachments()->set(key, QByteArray(6000, 'b'));
|
||||
entry1->endUpdate();
|
||||
QCOMPARE(entry1->attachments()->attachmentsSize(), 6000 + key.size());
|
||||
QCOMPARE(entry1->historyItems().size(), 2);
|
||||
|
||||
entry1->beginUpdate();
|
||||
entry1->attachments()->set(key, QByteArray(6000, 'c'));
|
||||
entry1->endUpdate();
|
||||
QCOMPARE(entry1->attachments()->attachmentsSize(), 6000 + key.size());
|
||||
QCOMPARE(entry1->historyItems().size(), 3);
|
||||
|
||||
entry1->beginUpdate();
|
||||
entry1->attachments()->set(key, QByteArray(6000, 'd'));
|
||||
entry1->endUpdate();
|
||||
QCOMPARE(entry1->attachments()->attachmentsSize(), 6000 + key.size());
|
||||
QCOMPARE(entry1->historyItems().size(), 4);
|
||||
|
||||
|
||||
auto entry2 = new Entry();
|
||||
entry2->setGroup(db->rootGroup());
|
||||
QCOMPARE(entry2->historyItems().size(), 0);
|
||||
|
||||
const int historyMaxSize = 17000;
|
||||
const int reservedSize2 = entry2->attributes()->attributesSize();
|
||||
db->metadata()->setHistoryMaxSize(historyMaxSize);
|
||||
|
||||
entry2->beginUpdate();
|
||||
entry2->attachments()->set(key, QByteArray(historyMaxSize - key.size() - reservedSize2 + 1, 'a'));
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->attachments()->attachmentsSize(), historyMaxSize - reservedSize2 + 1);
|
||||
QCOMPARE(entry2->historyItems().size(), 1);
|
||||
|
||||
// history size overflow
|
||||
entry2->beginUpdate();
|
||||
entry2->attachments()->set(key, QByteArray(historyMaxSize - key.size() - reservedSize2 + 1, 'b'));
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->historyItems().size(), 0);
|
||||
|
||||
entry2->beginUpdate();
|
||||
entry2->attachments()->remove(key);
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->attachments()->attachmentsSize(), 0);
|
||||
QCOMPARE(entry2->historyItems().size(), 0);
|
||||
|
||||
entry2->beginUpdate();
|
||||
entry2->attachments()->set(key, QByteArray(historyMaxSize - key.size() - reservedSize2 + 1, 'a'));
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->attachments()->attachmentsSize(), historyMaxSize - reservedSize2 + 1);
|
||||
QCOMPARE(entry2->historyItems().size(), 1);
|
||||
|
||||
// history size overflow
|
||||
entry2->beginUpdate();
|
||||
entry2->attachments()->set(key, QByteArray(historyMaxSize - key.size() - reservedSize2 + 1, 'b'));
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->historyItems().size(), 0);
|
||||
|
||||
entry2->beginUpdate();
|
||||
entry2->attachments()->remove(key);
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->attachments()->attachmentsSize(), 0);
|
||||
QCOMPARE(entry2->historyItems().size(), 0);
|
||||
|
||||
entry2->beginUpdate();
|
||||
entry2->setTags(QByteArray(historyMaxSize - reservedSize2 + 1, 'a'));
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->tags().size(), historyMaxSize - reservedSize2 + 1);
|
||||
QCOMPARE(entry2->historyItems().size(), 1);
|
||||
|
||||
// history size overflow
|
||||
entry2->beginUpdate();
|
||||
entry2->setTags(QByteArray(historyMaxSize - reservedSize2 + 1, 'b'));
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->historyItems().size(), 0);
|
||||
|
||||
entry2->beginUpdate();
|
||||
entry2->setTags("");
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->historyItems().size(), 0);
|
||||
|
||||
entry2->beginUpdate();
|
||||
entry2->attributes()->set(key, QByteArray(historyMaxSize - key.size() - reservedSize2 + 1, 'a'));
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->attributes()->attributesSize(), historyMaxSize + 1);
|
||||
QCOMPARE(entry2->historyItems().size(), 1);
|
||||
|
||||
// history size overflow
|
||||
entry2->beginUpdate();
|
||||
entry2->attributes()->set(key, QByteArray(historyMaxSize - key.size() - reservedSize2 + 1, 'b'));
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->attributes()->attributesSize(), historyMaxSize + 1);
|
||||
QCOMPARE(entry2->historyItems().size(), 0);
|
||||
|
||||
entry2->beginUpdate();
|
||||
entry2->attributes()->remove(key);
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->attributes()->attributesSize(), reservedSize2);
|
||||
QCOMPARE(entry2->historyItems().size(), 0);
|
||||
|
||||
entry2->beginUpdate();
|
||||
AutoTypeAssociations::Association association;
|
||||
association.window = key;
|
||||
association.sequence = QByteArray(historyMaxSize - key.size() - reservedSize2 + 1, 'a');
|
||||
entry2->autoTypeAssociations()->add(association);
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->autoTypeAssociations()->associationsSize(), historyMaxSize - reservedSize2 + 1);
|
||||
QCOMPARE(entry2->historyItems().size(), 1);
|
||||
|
||||
entry2->beginUpdate();
|
||||
entry2->autoTypeAssociations()->remove(0);
|
||||
entry2->endUpdate();
|
||||
QCOMPARE(entry2->autoTypeAssociations()->associationsSize(), 0);
|
||||
QCOMPARE(entry2->historyItems().size(), 0);
|
||||
}
|
||||
|
@ -29,7 +29,8 @@ private slots:
|
||||
void testSignals();
|
||||
void testGroupSets();
|
||||
void testEntrySets();
|
||||
void testHistoryItem();
|
||||
void testHistoryItems();
|
||||
void testHistoryMaxSize();
|
||||
};
|
||||
|
||||
#endif // KEEPASSX_TESTMODIFIED_H
|
||||
|
Loading…
Reference in New Issue
Block a user