Read all database attachments even if duplicated

* Fixes #3048
* Certain programs that read/write KDBX4 files do not consolidate duplicate attachments into a single binary. This is against the KDBX4 specification. This change ensures KeePassXC will at least read the database in its entirety and not lose information. Upon saving the database in KeePassXC, the duplicate attachment binaries will be reduced to single binaries per the specification.
This commit is contained in:
Jonathan White 2019-05-25 09:13:43 -04:00
parent 7ce6f9d3b1
commit 6d5c6c7d17
2 changed files with 4 additions and 21 deletions

View File

@ -35,7 +35,7 @@ bool Kdbx4Reader::readDatabaseImpl(QIODevice* device,
{ {
Q_ASSERT(m_kdbxVersion == KeePass2::FILE_VERSION_4); Q_ASSERT(m_kdbxVersion == KeePass2::FILE_VERSION_4);
m_binaryPoolInverse.clear(); m_binaryPool.clear();
if (hasError()) { if (hasError()) {
return false; return false;
@ -273,11 +273,7 @@ bool Kdbx4Reader::readInnerHeaderField(QIODevice* device)
return false; return false;
} }
auto data = fieldData.mid(1); auto data = fieldData.mid(1);
if (m_binaryPoolInverse.contains(data)) { m_binaryPool.insert(QString::number(m_binaryPool.size()), data);
qWarning("Skipping duplicate binary record");
break;
}
m_binaryPoolInverse.insert(data, QString::number(m_binaryPoolInverse.size()));
break; break;
} }
} }
@ -422,17 +418,5 @@ QVariantMap Kdbx4Reader::readVariantMap(QIODevice* device)
*/ */
QHash<QString, QByteArray> Kdbx4Reader::binaryPool() const QHash<QString, QByteArray> Kdbx4Reader::binaryPool() const
{ {
QHash<QString, QByteArray> binaryPool; return m_binaryPool;
for (auto it = m_binaryPoolInverse.cbegin(); it != m_binaryPoolInverse.cend(); ++it) {
binaryPool.insert(it.value(), it.key());
}
return binaryPool;
}
/**
* @return mapping from binary data to attachment keys
*/
QHash<QByteArray, QString> Kdbx4Reader::binaryPoolInverse() const
{
return m_binaryPoolInverse;
} }

View File

@ -34,7 +34,6 @@ public:
const QByteArray& headerData, const QByteArray& headerData,
QSharedPointer<const CompositeKey> key, QSharedPointer<const CompositeKey> key,
Database* db) override; Database* db) override;
QHash<QByteArray, QString> binaryPoolInverse() const;
QHash<QString, QByteArray> binaryPool() const; QHash<QString, QByteArray> binaryPool() const;
protected: protected:
@ -44,7 +43,7 @@ private:
bool readInnerHeaderField(QIODevice* device); bool readInnerHeaderField(QIODevice* device);
QVariantMap readVariantMap(QIODevice* device); QVariantMap readVariantMap(QIODevice* device);
QHash<QByteArray, QString> m_binaryPoolInverse; QHash<QString, QByteArray> m_binaryPool;
}; };
#endif // KEEPASSX_KDBX4READER_H #endif // KEEPASSX_KDBX4READER_H