diff --git a/src/core/Database.cpp b/src/core/Database.cpp index 355d7c191..5ddb273a7 100644 --- a/src/core/Database.cpp +++ b/src/core/Database.cpp @@ -99,3 +99,13 @@ Group* Database::recFindGroup(const Uuid& uuid, Group* group) return 0; } + +QList Database::deletedObjects() +{ + return m_deletedObjects; +} + +void Database::addDeletedObject(const DeletedObject& delObj) +{ + m_deletedObjects.append(delObj); +} diff --git a/src/core/Database.h b/src/core/Database.h index d474d03ab..19e129948 100644 --- a/src/core/Database.h +++ b/src/core/Database.h @@ -27,6 +27,12 @@ class Metadata; +struct DeletedObject +{ + Uuid uuid; + QDateTime deletionTime; +}; + class Database : public QObject { Q_OBJECT @@ -41,6 +47,8 @@ public: QImage customIcon(const Uuid& uuid) const; Entry* resolveEntry(const Uuid& uuid); Group* resolveGroup(const Uuid& uuid); + QList deletedObjects(); + void addDeletedObject(const DeletedObject& delObj); Q_SIGNALS: void groupDataChanged(Group* group); @@ -57,6 +65,7 @@ private: Group* m_rootGroup; QHash m_customIcons; DbAttribute m_unhandledAttirbute; + QList m_deletedObjects; }; #endif // KEEPASSX_DATABASE_H diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index 4c812f06c..ee1ddf549 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -29,6 +29,7 @@ Entry::Entry() Entry::~Entry() { // TODO notify group + qDeleteAll(m_history); } Uuid Entry::uuid() const @@ -236,6 +237,23 @@ void Entry::setNotes(const QString& notes) addAttribute("Notes", notes); } +QList Entry::historyItems() +{ + return m_history; +} + +const QList& Entry::historyItems() const +{ + return m_history; +} + +void Entry::addHistoryItem(Entry* entry) +{ + Q_ASSERT(!entry->parent()); + + m_history.append(entry); +} + void Entry::setGroup(Group* group) { if (m_group) { diff --git a/src/core/Entry.h b/src/core/Entry.h index 3776aa236..ad3f22d3b 100644 --- a/src/core/Entry.h +++ b/src/core/Entry.h @@ -81,8 +81,13 @@ public: void setPassword(const QString& password); void setNotes(const QString& notes); + QList historyItems(); + const QList& historyItems() const; + void addHistoryItem(Entry* entry); + void setGroup(Group* group); + Q_SIGNALS: void dataChanged(Entry* entry); @@ -101,6 +106,7 @@ private: QHash m_attributes; QHash m_binaries; + QList m_history; Group* m_group; const Database* m_db; }; diff --git a/src/core/Parser.cpp b/src/core/Parser.cpp index 10369b00d..c2652db55 100644 --- a/src/core/Parser.cpp +++ b/src/core/Parser.cpp @@ -228,8 +228,7 @@ void Parser::parseRoot() } } else if (m_xml.name() == "DeletedObjects") { - // TODO implement - skipCurrentElement(); + parseDeletedObjects(); } else { skipCurrentElement(); @@ -325,7 +324,7 @@ Group* Parser::parseGroup() } } else if (m_xml.name() == "Entry") { - Entry* newEntry = parseEntry(); + Entry* newEntry = parseEntry(false); if (newEntry) { newEntry->setGroup(group); } @@ -338,7 +337,48 @@ Group* Parser::parseGroup() 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"); @@ -350,8 +390,13 @@ Entry* Parser::parseEntry() raiseError(); } else { - entry = getEntry(uuid); - } + if (history) { + entry = new Entry(); + } + else { + entry = getEntry(uuid); + } + } } else if (m_xml.name() == "IconID") { int iconId = readNumber(); @@ -389,7 +434,12 @@ Entry* Parser::parseEntry() parseAutoType(entry); } else if (m_xml.name() == "History") { - parseEntryHistory(); + if (history) { + raiseError(); + } + else { + parseEntryHistory(entry); + } } else { 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"); while (!m_xml.error() && m_xml.readNextStartElement()) { if (m_xml.name() == "Entry") { - // TODO implement - skipCurrentElement(); + Entry* historyItem = parseEntry(true); + entry->addHistoryItem(historyItem); } else { skipCurrentElement(); diff --git a/src/core/Parser.h b/src/core/Parser.h index 72c1d75c6..0d2e5c933 100644 --- a/src/core/Parser.h +++ b/src/core/Parser.h @@ -48,12 +48,14 @@ private: void parseCustomData(); void parseRoot(); Group* parseGroup(); - Entry* parseEntry(); + void parseDeletedObjects(); + void parseDeletedObject(); + Entry* parseEntry(bool history); void parseEntryString(Entry* entry); void parseEntryBinary(Entry* entry); void parseAutoType(Entry* entry); void parseAutoTypeAssoc(Entry* entry); - void parseEntryHistory(); + void parseEntryHistory(Entry* entry); TimeInfo parseTimes(); QString readString(); diff --git a/src/core/Writer.cpp b/src/core/Writer.cpp index 6adf0e28c..4b8fa9273 100644 --- a/src/core/Writer.cpp +++ b/src/core/Writer.cpp @@ -20,7 +20,6 @@ #include #include -#include "core/Database.h" #include "core/Metadata.h" Writer::Writer(Database* db) @@ -29,7 +28,7 @@ Writer::Writer(Database* db) , m_meta(db->metadata()) { m_xml.setAutoFormatting(true); - m_xml.setAutoFormattingIndent(-1); + m_xml.setAutoFormattingIndent(-1); // 1 tab m_xml.setCodec("UTF-8"); } @@ -140,7 +139,11 @@ void Writer::writeRoot() m_xml.writeStartElement("Root"); writeGroup(m_db->rootGroup()); + m_xml.writeStartElement("DeletedObjects"); + + + m_xml.writeEndElement(); m_xml.writeEndElement(); @@ -215,6 +218,27 @@ void Writer::writeTimes(const TimeInfo& ti) 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) { m_xml.writeStartElement("Entry"); @@ -278,8 +302,10 @@ void Writer::writeEntryHistory(const Entry* entry) { m_xml.writeStartElement("History"); - // TODO implement - Q_UNUSED(entry); + const QList& historyItems = entry->historyItems(); + Q_FOREACH (const Entry* item, historyItems) { + writeEntry(item); + } m_xml.writeEndElement(); } diff --git a/src/core/Writer.h b/src/core/Writer.h index a60565959..eeffe9b2f 100644 --- a/src/core/Writer.h +++ b/src/core/Writer.h @@ -23,11 +23,11 @@ #include #include +#include "core/Database.h" #include "core/Entry.h" #include "core/TimeInfo.h" #include "core/Uuid.h" -class Database; class Group; class Metadata; @@ -49,6 +49,8 @@ private: void writeRoot(); void writeGroup(const Group* group); void writeTimes(const TimeInfo& ti); + void writeDeletedObjects(); + void writeDeletedObject(const DeletedObject& delObj); void writeEntry(const Entry* entry); void writeAutoType(const Entry* entry); void writeAutoTypeAssoc(const AutoTypeAssociation& assoc);