mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-01-11 15:29:51 -05:00
Support Entry History and DeletedObjects.
This commit is contained in:
parent
5efccf32c9
commit
3193adc215
@ -99,3 +99,13 @@ Group* Database::recFindGroup(const Uuid& uuid, Group* group)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<DeletedObject> Database::deletedObjects()
|
||||||
|
{
|
||||||
|
return m_deletedObjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Database::addDeletedObject(const DeletedObject& delObj)
|
||||||
|
{
|
||||||
|
m_deletedObjects.append(delObj);
|
||||||
|
}
|
||||||
|
@ -27,6 +27,12 @@
|
|||||||
|
|
||||||
class Metadata;
|
class Metadata;
|
||||||
|
|
||||||
|
struct DeletedObject
|
||||||
|
{
|
||||||
|
Uuid uuid;
|
||||||
|
QDateTime deletionTime;
|
||||||
|
};
|
||||||
|
|
||||||
class Database : public QObject
|
class Database : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -41,6 +47,8 @@ public:
|
|||||||
QImage customIcon(const Uuid& uuid) const;
|
QImage customIcon(const Uuid& uuid) const;
|
||||||
Entry* resolveEntry(const Uuid& uuid);
|
Entry* resolveEntry(const Uuid& uuid);
|
||||||
Group* resolveGroup(const Uuid& uuid);
|
Group* resolveGroup(const Uuid& uuid);
|
||||||
|
QList<DeletedObject> deletedObjects();
|
||||||
|
void addDeletedObject(const DeletedObject& delObj);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void groupDataChanged(Group* group);
|
void groupDataChanged(Group* group);
|
||||||
@ -57,6 +65,7 @@ private:
|
|||||||
Group* m_rootGroup;
|
Group* m_rootGroup;
|
||||||
QHash<Uuid, QImage> m_customIcons;
|
QHash<Uuid, QImage> m_customIcons;
|
||||||
DbAttribute m_unhandledAttirbute;
|
DbAttribute m_unhandledAttirbute;
|
||||||
|
QList<DeletedObject> m_deletedObjects;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // KEEPASSX_DATABASE_H
|
#endif // KEEPASSX_DATABASE_H
|
||||||
|
@ -29,6 +29,7 @@ Entry::Entry()
|
|||||||
Entry::~Entry()
|
Entry::~Entry()
|
||||||
{
|
{
|
||||||
// TODO notify group
|
// TODO notify group
|
||||||
|
qDeleteAll(m_history);
|
||||||
}
|
}
|
||||||
|
|
||||||
Uuid Entry::uuid() const
|
Uuid Entry::uuid() const
|
||||||
@ -236,6 +237,23 @@ void Entry::setNotes(const QString& notes)
|
|||||||
addAttribute("Notes", notes);
|
addAttribute("Notes", notes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<Entry*> Entry::historyItems()
|
||||||
|
{
|
||||||
|
return m_history;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QList<Entry*>& Entry::historyItems() const
|
||||||
|
{
|
||||||
|
return m_history;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entry::addHistoryItem(Entry* entry)
|
||||||
|
{
|
||||||
|
Q_ASSERT(!entry->parent());
|
||||||
|
|
||||||
|
m_history.append(entry);
|
||||||
|
}
|
||||||
|
|
||||||
void Entry::setGroup(Group* group)
|
void Entry::setGroup(Group* group)
|
||||||
{
|
{
|
||||||
if (m_group) {
|
if (m_group) {
|
||||||
|
@ -81,8 +81,13 @@ public:
|
|||||||
void setPassword(const QString& password);
|
void setPassword(const QString& password);
|
||||||
void setNotes(const QString& notes);
|
void setNotes(const QString& notes);
|
||||||
|
|
||||||
|
QList<Entry*> historyItems();
|
||||||
|
const QList<Entry*>& historyItems() const;
|
||||||
|
void addHistoryItem(Entry* entry);
|
||||||
|
|
||||||
void setGroup(Group* group);
|
void setGroup(Group* group);
|
||||||
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void dataChanged(Entry* entry);
|
void dataChanged(Entry* entry);
|
||||||
|
|
||||||
@ -101,6 +106,7 @@ private:
|
|||||||
QHash<QString, QString> m_attributes;
|
QHash<QString, QString> m_attributes;
|
||||||
QHash<QString, QByteArray> m_binaries;
|
QHash<QString, QByteArray> m_binaries;
|
||||||
|
|
||||||
|
QList<Entry*> m_history;
|
||||||
Group* m_group;
|
Group* m_group;
|
||||||
const Database* m_db;
|
const Database* m_db;
|
||||||
};
|
};
|
||||||
|
@ -228,8 +228,7 @@ void Parser::parseRoot()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_xml.name() == "DeletedObjects") {
|
else if (m_xml.name() == "DeletedObjects") {
|
||||||
// TODO implement
|
parseDeletedObjects();
|
||||||
skipCurrentElement();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
skipCurrentElement();
|
skipCurrentElement();
|
||||||
@ -325,7 +324,7 @@ Group* Parser::parseGroup()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_xml.name() == "Entry") {
|
else if (m_xml.name() == "Entry") {
|
||||||
Entry* newEntry = parseEntry();
|
Entry* newEntry = parseEntry(false);
|
||||||
if (newEntry) {
|
if (newEntry) {
|
||||||
newEntry->setGroup(group);
|
newEntry->setGroup(group);
|
||||||
}
|
}
|
||||||
@ -338,7 +337,48 @@ Group* Parser::parseGroup()
|
|||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry* Parser::parseEntry()
|
void Parser::parseDeletedObjects()
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "DeletedObjects");
|
||||||
|
|
||||||
|
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
||||||
|
if (m_xml.name() == "DeletedObject") {
|
||||||
|
parseDeletedObject();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipCurrentElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parser::parseDeletedObject()
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "DeletedObject");
|
||||||
|
|
||||||
|
DeletedObject delObj;
|
||||||
|
|
||||||
|
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
||||||
|
if (m_xml.name() == "UUID") {
|
||||||
|
Uuid uuid = readUuid();
|
||||||
|
if (uuid.isNull()) {
|
||||||
|
raiseError();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delObj.uuid = uuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_xml.name() == "DeletionTime") {
|
||||||
|
delObj.deletionTime = readDateTime();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipCurrentElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_db->addDeletedObject(delObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry* Parser::parseEntry(bool history)
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Entry");
|
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Entry");
|
||||||
|
|
||||||
@ -350,8 +390,13 @@ Entry* Parser::parseEntry()
|
|||||||
raiseError();
|
raiseError();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
entry = getEntry(uuid);
|
if (history) {
|
||||||
}
|
entry = new Entry();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entry = getEntry(uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (m_xml.name() == "IconID") {
|
else if (m_xml.name() == "IconID") {
|
||||||
int iconId = readNumber();
|
int iconId = readNumber();
|
||||||
@ -389,7 +434,12 @@ Entry* Parser::parseEntry()
|
|||||||
parseAutoType(entry);
|
parseAutoType(entry);
|
||||||
}
|
}
|
||||||
else if (m_xml.name() == "History") {
|
else if (m_xml.name() == "History") {
|
||||||
parseEntryHistory();
|
if (history) {
|
||||||
|
raiseError();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parseEntryHistory(entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
skipCurrentElement();
|
skipCurrentElement();
|
||||||
@ -477,14 +527,14 @@ void Parser::parseAutoTypeAssoc(Entry *entry)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::parseEntryHistory()
|
void Parser::parseEntryHistory(Entry* entry)
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "History");
|
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "History");
|
||||||
|
|
||||||
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
||||||
if (m_xml.name() == "Entry") {
|
if (m_xml.name() == "Entry") {
|
||||||
// TODO implement
|
Entry* historyItem = parseEntry(true);
|
||||||
skipCurrentElement();
|
entry->addHistoryItem(historyItem);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
skipCurrentElement();
|
skipCurrentElement();
|
||||||
|
@ -48,12 +48,14 @@ private:
|
|||||||
void parseCustomData();
|
void parseCustomData();
|
||||||
void parseRoot();
|
void parseRoot();
|
||||||
Group* parseGroup();
|
Group* parseGroup();
|
||||||
Entry* parseEntry();
|
void parseDeletedObjects();
|
||||||
|
void parseDeletedObject();
|
||||||
|
Entry* parseEntry(bool history);
|
||||||
void parseEntryString(Entry* entry);
|
void parseEntryString(Entry* entry);
|
||||||
void parseEntryBinary(Entry* entry);
|
void parseEntryBinary(Entry* entry);
|
||||||
void parseAutoType(Entry* entry);
|
void parseAutoType(Entry* entry);
|
||||||
void parseAutoTypeAssoc(Entry* entry);
|
void parseAutoTypeAssoc(Entry* entry);
|
||||||
void parseEntryHistory();
|
void parseEntryHistory(Entry* entry);
|
||||||
TimeInfo parseTimes();
|
TimeInfo parseTimes();
|
||||||
|
|
||||||
QString readString();
|
QString readString();
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include <QtCore/QBuffer>
|
#include <QtCore/QBuffer>
|
||||||
#include <QtCore/QFile>
|
#include <QtCore/QFile>
|
||||||
|
|
||||||
#include "core/Database.h"
|
|
||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
|
|
||||||
Writer::Writer(Database* db)
|
Writer::Writer(Database* db)
|
||||||
@ -29,7 +28,7 @@ Writer::Writer(Database* db)
|
|||||||
, m_meta(db->metadata())
|
, m_meta(db->metadata())
|
||||||
{
|
{
|
||||||
m_xml.setAutoFormatting(true);
|
m_xml.setAutoFormatting(true);
|
||||||
m_xml.setAutoFormattingIndent(-1);
|
m_xml.setAutoFormattingIndent(-1); // 1 tab
|
||||||
m_xml.setCodec("UTF-8");
|
m_xml.setCodec("UTF-8");
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -140,7 +139,11 @@ void Writer::writeRoot()
|
|||||||
m_xml.writeStartElement("Root");
|
m_xml.writeStartElement("Root");
|
||||||
|
|
||||||
writeGroup(m_db->rootGroup());
|
writeGroup(m_db->rootGroup());
|
||||||
|
|
||||||
m_xml.writeStartElement("DeletedObjects");
|
m_xml.writeStartElement("DeletedObjects");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
m_xml.writeEndElement();
|
m_xml.writeEndElement();
|
||||||
|
|
||||||
m_xml.writeEndElement();
|
m_xml.writeEndElement();
|
||||||
@ -215,6 +218,27 @@ void Writer::writeTimes(const TimeInfo& ti)
|
|||||||
m_xml.writeEndElement();
|
m_xml.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Writer::writeDeletedObjects()
|
||||||
|
{
|
||||||
|
m_xml.writeStartElement("DeletedObjects");
|
||||||
|
|
||||||
|
Q_FOREACH (const DeletedObject& delObj, m_db->deletedObjects()) {
|
||||||
|
writeDeletedObject(delObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_xml.writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Writer::writeDeletedObject(const DeletedObject& delObj)
|
||||||
|
{
|
||||||
|
m_xml.writeStartElement("DeletedObject");
|
||||||
|
|
||||||
|
writeUuid("UUID", delObj.uuid);
|
||||||
|
writeDateTime("DeletionTime", delObj.deletionTime);
|
||||||
|
|
||||||
|
m_xml.writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
void Writer::writeEntry(const Entry* entry)
|
void Writer::writeEntry(const Entry* entry)
|
||||||
{
|
{
|
||||||
m_xml.writeStartElement("Entry");
|
m_xml.writeStartElement("Entry");
|
||||||
@ -278,8 +302,10 @@ void Writer::writeEntryHistory(const Entry* entry)
|
|||||||
{
|
{
|
||||||
m_xml.writeStartElement("History");
|
m_xml.writeStartElement("History");
|
||||||
|
|
||||||
// TODO implement
|
const QList<Entry*>& historyItems = entry->historyItems();
|
||||||
Q_UNUSED(entry);
|
Q_FOREACH (const Entry* item, historyItems) {
|
||||||
|
writeEntry(item);
|
||||||
|
}
|
||||||
|
|
||||||
m_xml.writeEndElement();
|
m_xml.writeEndElement();
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,11 @@
|
|||||||
#include <QtGui/QColor>
|
#include <QtGui/QColor>
|
||||||
#include <QtGui/QImage>
|
#include <QtGui/QImage>
|
||||||
|
|
||||||
|
#include "core/Database.h"
|
||||||
#include "core/Entry.h"
|
#include "core/Entry.h"
|
||||||
#include "core/TimeInfo.h"
|
#include "core/TimeInfo.h"
|
||||||
#include "core/Uuid.h"
|
#include "core/Uuid.h"
|
||||||
|
|
||||||
class Database;
|
|
||||||
class Group;
|
class Group;
|
||||||
class Metadata;
|
class Metadata;
|
||||||
|
|
||||||
@ -49,6 +49,8 @@ private:
|
|||||||
void writeRoot();
|
void writeRoot();
|
||||||
void writeGroup(const Group* group);
|
void writeGroup(const Group* group);
|
||||||
void writeTimes(const TimeInfo& ti);
|
void writeTimes(const TimeInfo& ti);
|
||||||
|
void writeDeletedObjects();
|
||||||
|
void writeDeletedObject(const DeletedObject& delObj);
|
||||||
void writeEntry(const Entry* entry);
|
void writeEntry(const Entry* entry);
|
||||||
void writeAutoType(const Entry* entry);
|
void writeAutoType(const Entry* entry);
|
||||||
void writeAutoTypeAssoc(const AutoTypeAssociation& assoc);
|
void writeAutoTypeAssoc(const AutoTypeAssociation& assoc);
|
||||||
|
Loading…
Reference in New Issue
Block a user