More work on the parser and Entry/Group data structures.

This commit is contained in:
Felix Geyer 2010-08-12 21:38:59 +02:00
parent 3e3c23e4ad
commit dae532d659
14 changed files with 851 additions and 136 deletions

View File

@ -28,8 +28,75 @@ Database::Database(const QString& filename)
} }
Group* Database::rootGroup()
{
return m_rootGroup;
}
void Database::setRootGroup(Group* group)
{
m_rootGroup = group;
group->setParent(this);
}
Metadata* Database::metadata()
{
return m_metadata;
}
void Database::open() void Database::open()
{ {
Parser* parser = new Parser(this); Parser* parser = new Parser(this);
parser->parse(m_filename); parser->parse(m_filename);
} }
QImage Database::icon(int number)
{
// TODO implement
return QImage();
}
QImage Database::customIcon(const Uuid& uuid)
{
return m_customIcons[uuid];
}
Entry* Database::resolveEntry(const Uuid& uuid)
{
return recFindEntry(uuid, m_rootGroup);
}
Entry* Database::recFindEntry(const Uuid& uuid, Group* group)
{
Q_FOREACH (Entry* entry, group->entries()) {
if (entry->uuid() == uuid)
return entry;
}
Q_FOREACH (Group* child, group->children()) {
Entry* result = recFindEntry(uuid, child);
if (result)
return result;
}
return 0;
}
Group* Database::resolveGroup(const Uuid& uuid)
{
return recFindGroup(uuid, m_rootGroup);
}
Group* Database::recFindGroup(const Uuid& uuid, Group* group)
{
if (group->uuid() == uuid)
return group;
Q_FOREACH (Group* child, group->children()) {
Group* result = recFindGroup(uuid, child);
if (result)
return result;
}
return 0;
}

View File

@ -27,20 +27,30 @@
class Metadata; class Metadata;
class Database class Database : public QObject
{ {
Q_OBJECT
public: public:
Database(const QString& filename); Database(const QString& filename);
Group* rootGroup(); Group* rootGroup();
void setRootGroup(Group* group);
Metadata* metadata();
static QImage icon(int number);
QImage customIcon(const Uuid& uuid);
Entry* resolveEntry(const Uuid& uuid);
Group* resolveGroup(const Uuid& uuid);
private: private:
void open(); void open();
Entry* recFindEntry(const Uuid& uuid, Group* group);
Group* recFindGroup(const Uuid& uuid, Group* group);
QString m_filename; QString m_filename;
Metadata* m_metadata; Metadata* m_metadata;
Group* m_rootGroup; Group* m_rootGroup;
QHash<Uuid, QImage> customImages; QHash<Uuid, QImage> m_customIcons;
DbAttribute unhandledAttirbute; DbAttribute m_unhandledAttirbute;
}; };
#endif // KEEPASSX_DATABASE_H #endif // KEEPASSX_DATABASE_H

View File

@ -17,6 +17,145 @@
#include "Entry.h" #include "Entry.h"
Entry::Entry() #include "Group.h"
Entry::Entry() : m_group(0)
{ {
} }
Uuid Entry::uuid() const
{
return m_uuid;
}
QImage Entry::icon() const
{
// TODO implement
}
QColor Entry::foregroundColor() const
{
return m_foregroundColor;
}
QColor Entry::backgroundColor() const
{
return m_backgroundColor;
}
QString Entry::overrideUrl() const
{
return m_overrideUrl;
}
TimeInfo Entry::timeInfo() const
{
return m_timeInfo;
}
bool Entry::autoTypeEnabled() const
{
return m_autoTypeEnabled;
}
int Entry::autoTypeObfuscation() const
{
return m_autoTypeObfuscation;
}
QString Entry::defaultAutoTypeSequence() const
{
return m_defaultAutoTypeSequence;
}
const QList<AutoTypeAssociation>& Entry::autoTypeAssociations() const
{
return m_autoTypeAssociations;
}
const QHash<QString, QString>& Entry::attributes() const
{
return m_attributes;
}
const QHash<QString, QByteArray>& Entry::attachments() const
{
return m_binaries;
}
void Entry::setUuid(const Uuid& uuid)
{
m_uuid = uuid;
}
void Entry::setIcon(int iconNumber)
{
m_iconNumber = iconNumber;
m_customIcon = Uuid();
}
void Entry::setIcon(const Uuid& uuid)
{
m_iconNumber = 0;
m_customIcon = uuid;
}
void Entry::setForegroundColor(const QColor& color)
{
m_foregroundColor = color;
}
void Entry::setBackgroundColor(const QColor& color)
{
m_backgroundColor = color;
}
void Entry::setOverrideUrl(const QString& url)
{
m_overrideUrl = url;
}
void Entry::setTimeInfo(const TimeInfo& timeInfo)
{
m_timeInfo = timeInfo;
}
void Entry::setAutoTypeEnabled(bool enable)
{
m_autoTypeEnabled = enable;
}
void Entry::setAutoTypeObfuscation(int obfuscation)
{
m_autoTypeObfuscation = obfuscation;
}
void Entry::setDefaultAutoTypeSequence(const QString& sequence)
{
m_defaultAutoTypeSequence = sequence;
}
void Entry::addAutoTypeAssociation(const AutoTypeAssociation& assoc)
{
m_autoTypeAssociations << assoc;
}
void Entry::addAttribute(const QString& key, const QString& value)
{
m_attributes.insert(key, value);
}
void Entry::addAttachment(const QString& key, const QByteArray& value)
{
m_binaries.insert(key, value);
}
void Entry::setGroup(Group* group)
{
if (m_group) {
group->removeEntry(this);
}
group->addEntry(this);
m_group = group;
QObject::setParent(group);
}

View File

@ -18,21 +18,73 @@
#ifndef KEEPASSX_ENTRY_H #ifndef KEEPASSX_ENTRY_H
#define KEEPASSX_ENTRY_H #define KEEPASSX_ENTRY_H
#include <QtCore/QHash>
#include <QtCore/QUrl>
#include <QtGui/QColor>
#include <QtGui/QImage>
#include "TimeInfo.h"
#include "Uuid.h" #include "Uuid.h"
#include <QtCore/QHash> class Group;
class Entry struct AutoTypeAssociation
{ {
QString window;
QString sequence;
};
class Entry : public QObject
{
Q_OBJECT
public: public:
Entry(); Entry();
Uuid uuid() const;
QImage icon() const;
QColor foregroundColor() const;
QColor backgroundColor() const;
QString overrideUrl() const;
TimeInfo timeInfo() const;
bool autoTypeEnabled() const;
int autoTypeObfuscation() const;
QString defaultAutoTypeSequence() const;
const QList<AutoTypeAssociation>& autoTypeAssociations() const;
const QHash<QString, QString>& attributes() const;
const QHash<QString, QByteArray>& attachments() const;
void setUuid(const Uuid& uuid);
void setIcon(int iconNumber);
void setIcon(const Uuid& uuid);
void setForegroundColor(const QColor& color);
void setBackgroundColor(const QColor& color);
void setOverrideUrl(const QString& url);
void setTimeInfo(const TimeInfo& timeInfo);
void setAutoTypeEnabled(bool enable);
void setAutoTypeObfuscation(int obfuscation);
void setDefaultAutoTypeSequence(const QString& sequence);
void addAutoTypeAssociation(const AutoTypeAssociation& assoc);
void addAttribute(const QString& key, const QString& value);
void addAttachment(const QString& key, const QByteArray& value);
void setGroup(Group* group);
private: private:
Uuid m_uuid; Uuid m_uuid;
int m_icon; int m_iconNumber;
Uuid m_customIcon; Uuid m_customIcon;
QColor m_foregroundColor;
QColor m_backgroundColor;
QString m_overrideUrl;
TimeInfo m_timeInfo;
bool m_autoTypeEnabled;
int m_autoTypeObfuscation;
QString m_defaultAutoTypeSequence;
QList<AutoTypeAssociation> m_autoTypeAssociations;
QHash<QString, QString> m_attributes; QHash<QString, QString> m_attributes;
QHash<QString, QByteArray> m_binaries; QHash<QString, QByteArray> m_binaries;
Group* m_group;
}; };
#endif // KEEPASSX_ENTRY_H #endif // KEEPASSX_ENTRY_H

View File

@ -20,3 +20,139 @@
#include "Group.h" #include "Group.h"
#include "Database.h"
Group::Group() : m_parent(0)
{
}
Uuid Group::uuid() const
{
return m_uuid;
}
QString Group::name() const
{
return m_name;
}
QString Group::notes() const
{
return m_notes;
}
QImage Group::icon() const
{
if (m_iconNumber == 0)
return m_db->customIcon(m_customIcon);
else
return Database::icon(m_iconNumber);
}
TimeInfo Group::timeInfo() const
{
return m_timeInfo;
}
bool Group::isExpanded() const
{
return m_isExpanded;
}
QString Group::defaultAutoTypeSequence() const
{
return m_defaultAutoTypeSequence;
}
Entry* Group::lastTopVisibleEntry() const
{
return m_lastTopVisibleEntry;
}
void Group::setUuid(const Uuid& uuid)
{
m_uuid = uuid;
}
void Group::setName(const QString& name)
{
m_name = name;
}
void Group::setNotes(const QString& notes)
{
m_notes = notes;
}
void Group::setIcon(int iconNumber)
{
m_iconNumber = iconNumber;
m_customIcon = Uuid();
}
void Group::setIcon(const Uuid& uuid)
{
m_iconNumber = 0;
m_customIcon = uuid;
}
void Group::setTimeInfo(const TimeInfo& timeInfo)
{
m_timeInfo = timeInfo;
}
void Group::setExpanded(bool expanded)
{
m_isExpanded = expanded;
}
void Group::setDefaultAutoTypeSequence(const QString& sequence)
{
m_defaultAutoTypeSequence = sequence;
}
void Group::setLastTopVisibleEntry(Entry* entry)
{
m_lastTopVisibleEntry = entry;
}
void Group::setParent(Group* parent)
{
if (m_parent) {
m_parent->m_children.removeAll(this);
}
m_db = parent->m_db;
QObject::setParent(parent);
}
void Group::setParent(Database* db)
{
if (m_db) {
m_db->setRootGroup(0);
}
m_parent = 0;
m_db = db;
QObject::setParent(db);
}
QList<Group*> Group::children() const
{
return m_children;
}
QList<Entry*> Group::entries() const
{
return m_entries;
}
void Group::addEntry(Entry *entry)
{
m_entries << entry;
}
void Group::removeEntry(Entry* entry)
{
m_entries.removeAll(entry);
}

View File

@ -18,19 +18,62 @@
#ifndef KEEPASSX_GROUP_H #ifndef KEEPASSX_GROUP_H
#define KEEPASSX_GROUP_H #define KEEPASSX_GROUP_H
#include <QtGui/QImage>
#include "Entry.h" #include "Entry.h"
#include "TimeInfo.h"
#include "Uuid.h" #include "Uuid.h"
class Group { class Database;
class Group : public QObject
{
Q_OBJECT
public:
Group();
Uuid uuid() const;
QString name() const;
QString notes() const;
QImage icon() const;
TimeInfo timeInfo() const;
bool isExpanded() const;
QString defaultAutoTypeSequence() const;
Entry* lastTopVisibleEntry() const;
void setUuid(const Uuid& uuid);
void setName(const QString& name);
void setNotes(const QString& notes);
void setIcon(int iconNumber);
void setIcon(const Uuid& uuid);
void setTimeInfo(const TimeInfo& timeInfo);
void setExpanded(bool expanded);
void setDefaultAutoTypeSequence(const QString& sequence);
void setLastTopVisibleEntry(Entry* entry);
void setParent(Group* parent);
void setParent(Database* db);
QList<Group*> children() const;
QList<Entry*> entries() const;
void addEntry(Entry* entry);
void removeEntry(Entry* entry);
private: private:
Database* m_db;
Uuid m_uuid; Uuid m_uuid;
QString m_name; QString m_name;
QString m_notes; QString m_notes;
int m_icon; int m_iconNumber;
Uuid m_customIcon; Uuid m_customIcon;
TimeInfo m_timeInfo;
bool m_isExpanded; bool m_isExpanded;
QString m_defaultAutoTypeSequence;
Entry* m_lastTopVisibleEntry;
QList<Group*> m_children;
QList<Entry*> m_entries;
QList<Entry> m_children; Group* m_parent;
}; };
#endif // KEEPASSX_GROUP_H #endif // KEEPASSX_GROUP_H

View File

@ -24,112 +24,117 @@ Metadata::Metadata()
QString Metadata::generator() const QString Metadata::generator() const
{ {
return m_generator; return m_generator;
}; }
QString Metadata::name() const QString Metadata::name() const
{ {
return m_name; return m_name;
}; }
QDateTime Metadata::nameChanged() const QDateTime Metadata::nameChanged() const
{ {
return m_nameChanged; return m_nameChanged;
}; }
QString Metadata::description() const QString Metadata::description() const
{ {
return m_description; return m_description;
}; }
QDateTime Metadata::descriptionChanged() const QDateTime Metadata::descriptionChanged() const
{ {
return m_descriptionChanged; return m_descriptionChanged;
}; }
QString Metadata::defaultUserName() const QString Metadata::defaultUserName() const
{ {
return m_defaultUserName; return m_defaultUserName;
}; }
QDateTime Metadata::defaultUserNameChanged() const
{
return m_defaultUserNameChanged;
}
int Metadata::maintenanceHistoryDays() const int Metadata::maintenanceHistoryDays() const
{ {
return m_maintenanceHistoryDays; return m_maintenanceHistoryDays;
}; }
bool Metadata::protectTitle() const bool Metadata::protectTitle() const
{ {
return m_protectTitle; return m_protectTitle;
}; }
bool Metadata::protectUsername() const bool Metadata::protectUsername() const
{ {
return m_protectUsername; return m_protectUsername;
}; }
bool Metadata::protectPassword() const bool Metadata::protectPassword() const
{ {
return m_protectPassword; return m_protectPassword;
}; }
bool Metadata::protectUrl() const bool Metadata::protectUrl() const
{ {
return m_protectUrl; return m_protectUrl;
}; }
bool Metadata::protectNotes() const bool Metadata::protectNotes() const
{ {
return m_protectNotes; return m_protectNotes;
}; }
bool Metadata::autoEnableVisualHiding() const bool Metadata::autoEnableVisualHiding() const
{ {
return m_autoEnableVisualHiding; return m_autoEnableVisualHiding;
}; }
QHash<Uuid, QImage> Metadata::customIcons() const QHash<Uuid, QImage> Metadata::customIcons() const
{ {
return m_customIcons; return m_customIcons;
}; }
bool Metadata::recycleBinEnabled() const bool Metadata::recycleBinEnabled() const
{ {
return m_recycleBinEnabled; return m_recycleBinEnabled;
}; }
Uuid Metadata::recycleBinUuid() const Uuid Metadata::recycleBinUuid() const
{ {
return m_recycleBinUuid; return m_recycleBinUuid;
}; }
QDateTime Metadata::recycleBinChanged() const QDateTime Metadata::recycleBinChanged() const
{ {
return m_recycleBinChanged; return m_recycleBinChanged;
}; }
Uuid Metadata::entryTemplatesGroup() const Uuid Metadata::entryTemplatesGroup() const
{ {
return m_entryTemplatesGroup; return m_entryTemplatesGroup;
}; }
QDateTime Metadata::entryTemplatesGroupChanged() const QDateTime Metadata::entryTemplatesGroupChanged() const
{ {
return m_entryTemplatesGroupChanged; return m_entryTemplatesGroupChanged;
}; }
Uuid Metadata::lastSelectedGroup() const Uuid Metadata::lastSelectedGroup() const
{ {
return m_lastSelectedGroup; return m_lastSelectedGroup;
}; }
Uuid Metadata::lastTopVisibleGroup() const Uuid Metadata::lastTopVisibleGroup() const
{ {
return m_lastTopVisibleGroup; return m_lastTopVisibleGroup;
}; }
QHash<QString, QString> Metadata::customFields() const QHash<QString, QString> Metadata::customFields() const
{ {
return m_customFields; return m_customFields;
}; }
void Metadata::setGenerator(const QString& value) void Metadata::setGenerator(const QString& value)
{ {
@ -161,6 +166,11 @@ void Metadata::setDefaultUserName(const QString& value)
m_defaultUserName = value; m_defaultUserName = value;
} }
void Metadata::setDefaultUserNameChanged(const QDateTime& value)
{
m_defaultUserNameChanged = value;
}
void Metadata::setMaintenanceHistoryDays(int value) void Metadata::setMaintenanceHistoryDays(int value)
{ {
m_maintenanceHistoryDays = value; m_maintenanceHistoryDays = value;

View File

@ -35,6 +35,7 @@ public:
QString description() const; QString description() const;
QDateTime descriptionChanged() const; QDateTime descriptionChanged() const;
QString defaultUserName() const; QString defaultUserName() const;
QDateTime defaultUserNameChanged() const;
int maintenanceHistoryDays() const; int maintenanceHistoryDays() const;
bool protectTitle() const; bool protectTitle() const;
bool protectUsername() const; bool protectUsername() const;
@ -58,6 +59,7 @@ public:
void setDescription(const QString& value); void setDescription(const QString& value);
void setDescriptionChanged(const QDateTime& value); void setDescriptionChanged(const QDateTime& value);
void setDefaultUserName(const QString& value); void setDefaultUserName(const QString& value);
void setDefaultUserNameChanged(const QDateTime& value);
void setMaintenanceHistoryDays(int value); void setMaintenanceHistoryDays(int value);
void setProtectTitle(bool value); void setProtectTitle(bool value);
void setProtectUsername(bool value); void setProtectUsername(bool value);
@ -84,6 +86,7 @@ private:
QString m_description; QString m_description;
QDateTime m_descriptionChanged; QDateTime m_descriptionChanged;
QString m_defaultUserName; QString m_defaultUserName;
QDateTime m_defaultUserNameChanged;
int m_maintenanceHistoryDays; int m_maintenanceHistoryDays;
bool m_protectTitle; bool m_protectTitle;

View File

@ -19,9 +19,13 @@
#include <QtCore/QFile> #include <QtCore/QFile>
#include "Database.h"
#include "Metadata.h"
Parser::Parser(Database* db) Parser::Parser(Database* db)
{ {
m_db = db; m_db = db;
m_meta = db->metadata();
} }
bool Parser::parse(const QString& filename) bool Parser::parse(const QString& filename)
@ -30,16 +34,22 @@ bool Parser::parse(const QString& filename)
file.open(QIODevice::ReadOnly | QIODevice::Text); file.open(QIODevice::ReadOnly | QIODevice::Text);
m_xml.setDevice(&file); m_xml.setDevice(&file);
m_tmpParent = new Group();
if (m_xml.readNextStartElement()) { if (!m_xml.error() && m_xml.readNextStartElement()) {
if (m_xml.name() == "KeePassFile") { if (m_xml.name() == "KeePassFile") {
parseKeePassFile(); parseKeePassFile();
} }
else { else {
m_xml.raiseError(tr("Invalid database file")); raiseError();
} }
} }
if (!m_tmpParent->children().isEmpty()) {
delete m_tmpParent;
raiseError();
}
return !m_xml.error(); return !m_xml.error();
} }
@ -47,7 +57,7 @@ void Parser::parseKeePassFile()
{ {
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "KeePassFile"); Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "KeePassFile");
while (m_xml.readNextStartElement()) { while (!m_xml.error() && m_xml.readNextStartElement()) {
if (m_xml.name() == "Meta") { if (m_xml.name() == "Meta") {
parseMeta(); parseMeta();
} }
@ -55,7 +65,7 @@ void Parser::parseKeePassFile()
parseRoot(); parseRoot();
} }
else { else {
m_xml.raiseError(tr("Invalid database file")); m_xml.skipCurrentElement();
} }
} }
} }
@ -64,30 +74,30 @@ void Parser::parseMeta()
{ {
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Meta"); Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Meta");
while (m_xml.readNextStartElement()) { while (!m_xml.error() && m_xml.readNextStartElement()) {
if (m_xml.name() == "Generator") { if (m_xml.name() == "Generator") {
m_meta->setGenerator(readString());
} }
else if (m_xml.name() == "DatabaseName") { else if (m_xml.name() == "DatabaseName") {
m_meta->setName(readString());
} }
else if (m_xml.name() == "DatabaseNameChanged") { else if (m_xml.name() == "DatabaseNameChanged") {
m_meta->setNameChanged(readDateTime());
} }
else if (m_xml.name() == "DatabaseDescription") { else if (m_xml.name() == "DatabaseDescription") {
m_meta->setDescription(readString());
} }
else if (m_xml.name() == "DatabaseDescriptionChanged") { else if (m_xml.name() == "DatabaseDescriptionChanged") {
m_meta->setDescriptionChanged(readDateTime());
} }
else if (m_xml.name() == "DefaultUserName") { else if (m_xml.name() == "DefaultUserName") {
m_meta->setDefaultUserName(readString());
} }
else if (m_xml.name() == "DefaultUserNameChanged") { else if (m_xml.name() == "DefaultUserNameChanged") {
m_meta->setDefaultUserNameChanged(readDateTime());
} }
else if (m_xml.name() == "MaintenanceHistoryDays") { else if (m_xml.name() == "MaintenanceHistoryDays") {
m_meta->setMaintenanceHistoryDays(readNumber());
} }
else if (m_xml.name() == "MemoryProtection") { else if (m_xml.name() == "MemoryProtection") {
parseMemoryProtection(); parseMemoryProtection();
@ -96,25 +106,25 @@ void Parser::parseMeta()
parseCustomIcons(); parseCustomIcons();
} }
else if (m_xml.name() == "RecycleBinEnabled") { else if (m_xml.name() == "RecycleBinEnabled") {
m_meta->setRecycleBinEnabled(readBool());
} }
else if (m_xml.name() == "RecycleBinUUID") { else if (m_xml.name() == "RecycleBinUUID") {
m_meta->setRecycleBinUuid(readUuid());
} }
else if (m_xml.name() == "RecycleBinChanged") { else if (m_xml.name() == "RecycleBinChanged") {
m_meta->setRecycleBinChanged(readDateTime());
} }
else if (m_xml.name() == "EntryTemplatesGroup") { else if (m_xml.name() == "EntryTemplatesGroup") {
m_meta->setEntryTemplatesGroup(readUuid());
} }
else if (m_xml.name() == "EntryTemplatesGroupChanged") { else if (m_xml.name() == "EntryTemplatesGroupChanged") {
m_meta->setEntryTemplatesGroupChanged(readDateTime());
} }
else if (m_xml.name() == "LastSelectedGroup") { else if (m_xml.name() == "LastSelectedGroup") {
m_meta->setLastSelectedGroup(readUuid());
} }
else if (m_xml.name() == "LastTopVisibleGroup") { else if (m_xml.name() == "LastTopVisibleGroup") {
m_meta->setLastTopVisibleGroup(readUuid());
} }
else if (m_xml.name() == "CustomData") { else if (m_xml.name() == "CustomData") {
parseCustomData(); parseCustomData();
@ -129,24 +139,24 @@ void Parser::parseMemoryProtection()
{ {
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "MemoryProtection"); Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "MemoryProtection");
while (m_xml.readNextStartElement()) { while (!m_xml.error() && m_xml.readNextStartElement()) {
if (m_xml.name() == "ProtectTitle") { if (m_xml.name() == "ProtectTitle") {
m_meta->setProtectTitle(readBool());
} }
else if (m_xml.name() == "ProtectUserName") { else if (m_xml.name() == "ProtectUserName") {
m_meta->setProtectUsername(readBool());
} }
else if (m_xml.name() == "ProtectPassword") { else if (m_xml.name() == "ProtectPassword") {
m_meta->setProtectPassword(readBool());
} }
else if (m_xml.name() == "ProtectURL") { else if (m_xml.name() == "ProtectURL") {
m_meta->setProtectUrl(readBool());
} }
else if (m_xml.name() == "ProtectNotes") { else if (m_xml.name() == "ProtectNotes") {
m_meta->setProtectNotes(readBool());
} }
else if (m_xml.name() == "AutoEnableVisualHiding") { else if (m_xml.name() == "AutoEnableVisualHiding") {
m_meta->setAutoEnableVisualHiding(readBool());
} }
else { else {
m_xml.skipCurrentElement(); m_xml.skipCurrentElement();
@ -158,7 +168,7 @@ void Parser::parseCustomIcons()
{ {
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "CustomIcons"); Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "CustomIcons");
while (m_xml.readNextStartElement()) { while (!m_xml.error() && m_xml.readNextStartElement()) {
if (m_xml.name() == "Icon") { if (m_xml.name() == "Icon") {
parseIcon(); parseIcon();
} }
@ -172,12 +182,15 @@ void Parser::parseIcon()
{ {
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Icon"); Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Icon");
while (m_xml.readNextStartElement()) { Uuid uuid;
while (!m_xml.error() && m_xml.readNextStartElement()) {
if (m_xml.name() == "UUID") { if (m_xml.name() == "UUID") {
uuid = readUuid();
} }
else if (m_xml.name() == "Data") { else if (m_xml.name() == "Data") {
QImage image;
image.loadFromData(readBinary());
m_meta->addCustomIcon(uuid, image);
} }
else { else {
m_xml.skipCurrentElement(); m_xml.skipCurrentElement();
@ -196,12 +209,15 @@ void Parser::parseRoot()
{ {
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Root"); Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Root");
while (m_xml.readNextStartElement()) { while (!m_xml.error() && m_xml.readNextStartElement()) {
if (m_xml.name() == "Group") { if (m_xml.name() == "Group") {
parseGroup(); Group* rootGroup = parseGroup();
if (rootgroup) {
rootGroup->setParent(m_db);
}
} }
else if (m_xml.name() == "DeletedObjects") { else if (m_xml.name() == "DeletedObjects") {
// ????????????????? // TODO implement
} }
else { else {
m_xml.skipCurrentElement(); m_xml.skipCurrentElement();
@ -209,87 +225,125 @@ void Parser::parseRoot()
} }
} }
void Parser::parseGroup() Group* Parser::parseGroup()
{ {
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Group"); Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Group");
while (m_xml.readNextStartElement()) { Group* group = 0;
while (!m_xml.error() && m_xml.readNextStartElement()) {
if (m_xml.name() == "UUID") { if (m_xml.name() == "UUID") {
Uuid uuid = readUuid();
if (uuid.isNull()) {
raiseError();
}
else {
group = getGroup(uuid);
}
} }
else if (m_xml.name() == "Name") { else if (m_xml.name() == "Name") {
group->setName(readString());
} }
else if (m_xml.name() == "Notes") { else if (m_xml.name() == "Notes") {
group->setNotes(readString());
} }
else if (m_xml.name() == "IconID") { else if (m_xml.name() == "IconID") {
int iconId = readNumber();
if (iconId != 0)
group->setIcon(iconId);
}
else if (m_xml.name() == "CustomIconUUID") {
Uuid uuid = readUuid();
if (!uuid.isNull()) {
group->setIcon(uuid);
}
} }
else if (m_xml.name() == "Times") { else if (m_xml.name() == "Times") {
parseTimes(); group->setTimeInfo(parseTimes());
} }
else if (m_xml.name() == "IsExpanded") { else if (m_xml.name() == "IsExpanded") {
group->setExpanded(readBool());
} }
else if (m_xml.name() == "DefaultAutoTypeSequence") { else if (m_xml.name() == "DefaultAutoTypeSequence") {
group->setDefaultAutoTypeSequence(readString());
} }
else if (m_xml.name() == "EnableAutoType") { else if (m_xml.name() == "EnableAutoType") {
// TODO implement
} }
else if (m_xml.name() == "EnableSearching") { else if (m_xml.name() == "EnableSearching") {
// TODO implement
} }
else if (m_xml.name() == "LastTopVisibleEntry") { else if (m_xml.name() == "LastTopVisibleEntry") {
Uuid uuid = readUuid();
if (uuid.isNull())
group->setLastTopVisibleEntry(0);
else
group->setLastTopVisibleEntry(getEntry(uuid));
} }
else if (m_xml.name() == "Group") { else if (m_xml.name() == "Group") {
parseGroup(); Group* newGroup = parseGroup();
if (newGroup) {
newGroup->setParent(group);
}
} }
else if (m_xml.name() == "Entry") { else if (m_xml.name() == "Entry") {
parseEntry(); Entry* newEntry = parseEntry();
if (newEntry) {
newEntry->setGroup(group);
}
} }
else { else {
m_xml.skipCurrentElement(); m_xml.skipCurrentElement();
} }
} }
return group;
} }
void Parser::parseEntry() Entry* Parser::parseEntry()
{ {
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Entry"); Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Entry");
while (m_xml.readNextStartElement()) { Entry* entry = 0;
while (!m_xml.error() && m_xml.readNextStartElement()) {
if (m_xml.name() == "UUID") { if (m_xml.name() == "UUID") {
Uuid uuid = readUuid();
if (uuid.isNull()) {
raiseError();
}
else {
entry = getEntry(uuid);
}
} }
else if (m_xml.name() == "IconID") { else if (m_xml.name() == "IconID") {
int iconId = readNumber();
if (iconId != 0)
entry->setIcon(iconId);
} }
else if (m_xml.name() == "CustomIconUUID") { else if (m_xml.name() == "CustomIconUUID") {
Uuid uuid = readUuid();
if (!uuid.isNull())
entry->setIcon(uuid);
} }
else if (m_xml.name() == "ForegroundColor") { else if (m_xml.name() == "ForegroundColor") {
entry->setForegroundColor(readColor());
} }
else if (m_xml.name() == "BackgroundColor") { else if (m_xml.name() == "BackgroundColor") {
entry->setBackgroundColor(readColor());
} }
else if (m_xml.name() == "OverrideURL") { else if (m_xml.name() == "OverrideURL") {
entry->setOverrideUrl(readString());
} }
else if (m_xml.name() == "Times") { else if (m_xml.name() == "Times") {
parseTimes(); entry->setTimeInfo(parseTimes());
} }
else if (m_xml.name() == "String") { else if (m_xml.name() == "String") {
parseEntryString(); parseEntryString(entry);
} }
else if (m_xml.name() == "Binary") { else if (m_xml.name() == "Binary") {
parseEntryBinary(); parseEntryBinary(entry);
} }
else if (m_xml.name() == "AutoType") { else if (m_xml.name() == "AutoType") {
parseAutoType(); parseAutoType(entry);
} }
else if (m_xml.name() == "History") { else if (m_xml.name() == "History") {
parseEntryHistory(); parseEntryHistory();
@ -300,16 +354,17 @@ void Parser::parseEntry()
} }
} }
void Parser::parseEntryString() void Parser::parseEntryString(Entry *entry)
{ {
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "String"); Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "String");
while (m_xml.readNextStartElement()) { QString key;
while (!m_xml.error() && m_xml.readNextStartElement()) {
if (m_xml.name() == "Key") { if (m_xml.name() == "Key") {
key = readString();
} }
else if (m_xml.name() == "Value") { else if (m_xml.name() == "Value") {
entry->addAttribute(key, readString());
} }
else { else {
m_xml.skipCurrentElement(); m_xml.skipCurrentElement();
@ -317,16 +372,17 @@ void Parser::parseEntryString()
} }
} }
void Parser::parseEntryBinary() void Parser::parseEntryBinary(Entry *entry)
{ {
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Binary"); Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Binary");
while (m_xml.readNextStartElement()) { QString key;
while (!m_xml.error() && m_xml.readNextStartElement()) {
if (m_xml.name() == "Key") { if (m_xml.name() == "Key") {
key = readString();
} }
else if (m_xml.name() == "Value") { else if (m_xml.name() == "Value") {
entry->addAttachment(key, readBinary());
} }
else { else {
m_xml.skipCurrentElement(); m_xml.skipCurrentElement();
@ -334,19 +390,22 @@ void Parser::parseEntryBinary()
} }
} }
void Parser::parseAutoType() void Parser::parseAutoType(Entry* entry)
{ {
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "AutoType"); Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "AutoType");
while (m_xml.readNextStartElement()) { while (!m_xml.error() && m_xml.readNextStartElement()) {
if (m_xml.name() == "Enabled") { if (m_xml.name() == "Enabled") {
entry->setAutoTypeEnabled(readBool());
} }
else if (m_xml.name() == "DataTransferObfuscation") { else if (m_xml.name() == "DataTransferObfuscation") {
entry->setAutoTypeObfuscation(readNumber());
}
else if (m_xml.name() == "DefaultSequence") {
entry->setDefaultAutoTypeSequence(readString());
} }
else if (m_xml.name() == "Association") { else if (m_xml.name() == "Association") {
parseAutoTypeAssoc(); parseAutoTypeAssoc(entry);
} }
else { else {
m_xml.skipCurrentElement(); m_xml.skipCurrentElement();
@ -354,16 +413,18 @@ void Parser::parseAutoType()
} }
} }
void Parser::parseAutoTypeAssoc() void Parser::parseAutoTypeAssoc(Entry *entry)
{ {
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Association"); Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Association");
while (m_xml.readNextStartElement()) { AutoTypeAssociation assoc;
while (!m_xml.error() && m_xml.readNextStartElement()) {
if (m_xml.name() == "Window") { if (m_xml.name() == "Window") {
assoc.window = readString();
} }
else if (m_xml.name() == "KeystrokeSequence") { else if (m_xml.name() == "KeystrokeSequence") {
assoc.sequence = readString();
entry->addAutoTypeAssociation(assoc);
} }
else { else {
m_xml.skipCurrentElement(); m_xml.skipCurrentElement();
@ -375,9 +436,9 @@ void Parser::parseEntryHistory()
{ {
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "History"); Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "History");
while (m_xml.readNextStartElement()) { while (!m_xml.error() && m_xml.readNextStartElement()) {
if (m_xml.name() == "Entry") { if (m_xml.name() == "Entry") {
parseEntry(); // TODO implement
} }
else { else {
m_xml.skipCurrentElement(); m_xml.skipCurrentElement();
@ -385,36 +446,39 @@ void Parser::parseEntryHistory()
} }
} }
void Parser::parseTimes() TimeInfo Parser::parseTimes()
{ {
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Times"); Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Times");
while (m_xml.readNextStartElement()) { TimeInfo timeInfo;
while (!m_xml.error() && m_xml.readNextStartElement()) {
if (m_xml.name() == "LastModificationTime") { if (m_xml.name() == "LastModificationTime") {
timeInfo.setLastModificationTime(readDateTime());
} }
else if (m_xml.name() == "CreationTime") { else if (m_xml.name() == "CreationTime") {
timeInfo.setCreationTime(readDateTime());
} }
else if (m_xml.name() == "LastAccessTime") { else if (m_xml.name() == "LastAccessTime") {
timeInfo.setLastAccessTime(readDateTime());
} }
else if (m_xml.name() == "ExpiryTime") { else if (m_xml.name() == "ExpiryTime") {
timeInfo.setExpiryTime(readDateTime());
} }
else if (m_xml.name() == "Expires") { else if (m_xml.name() == "Expires") {
timeInfo.setExpires(readBool());
} }
else if (m_xml.name() == "UsageCount") { else if (m_xml.name() == "UsageCount") {
timeInfo.setUsageCount(readNumber());
} }
else if (m_xml.name() == "LocationChanged") { else if (m_xml.name() == "LocationChanged") {
timeInfo.setLocationChanged(readDateTime());
} }
else { else {
m_xml.skipCurrentElement(); m_xml.skipCurrentElement();
} }
} }
return timeInfo;
} }
QString Parser::readString() QString Parser::readString()
@ -433,7 +497,7 @@ bool Parser::readBool()
return false; return false;
} }
else { else {
// TODO error raiseError();
} }
} }
@ -443,23 +507,102 @@ QDateTime Parser::readDateTime()
QDateTime dt = QDateTime::fromString(str, Qt::ISODate); QDateTime dt = QDateTime::fromString(str, Qt::ISODate);
if (!dt.isValid()) { if (!dt.isValid()) {
// TODO error raiseError();
} }
return dt; return dt;
} }
int Parser::readInt() QColor Parser::readColor()
{ {
// TODO QString colorStr = readString();
if (colorStr.length() != 7 || colorStr[0] != '#') {
raiseError();
return QColor();
}
QColor color;
for (int i=0; i<= 2; i++) {
QString rgbPartStr = colorStr.mid(1 + 2*i, 2);
bool ok;
int rgbPart = rgbPartStr.toInt(&ok);
if (!ok || rgbPart > 255) {
raiseError();
return QColor();
}
if (i == 0) {
color.setRed(rgbPart);
}
else if (i == 1) {
color.setGreen(rgbPart);
}
else {
color.setBlue(rgbPart);
}
}
return color;
}
int Parser::readNumber()
{
bool ok;
int result = readString().toInt(&ok);
if (!ok) {
raiseError();
}
return result;
} }
Uuid Parser::readUuid() Uuid Parser::readUuid()
{ {
// TODO QByteArray uuidBin = readBinary();
if (uuidBin.length() != Uuid::length) {
raiseError();
return Uuid();
}
else {
return Uuid(readBinary());
}
} }
QByteArray Parser::readBinary() QByteArray Parser::readBinary()
{ {
// TODO return QByteArray::fromBase64(readString().toAscii());
}
Group* Parser::getGroup(const Uuid& uuid)
{
Q_FOREACH (Group* group, m_groups) {
if (group->uuid() == uuid) {
return group;
}
}
Group* group = new Group();
group->setUuid(uuid);
group->setParent(m_tmpParent);
m_groups << group;
return group;
}
Entry* Parser::getEntry(const Uuid& uuid)
{
Q_FOREACH (Entry* entry, m_entries) {
if (entry->uuid() == uuid) {
return entry;
}
}
Entry* entry = new Entry();
entry->setUuid(uuid);
entry->setGroup(m_tmpParent);
m_entries << entry;
return entry;
}
void Parser::raiseError()
{
m_xml.raiseError(tr("Invalid database file"));
} }

View File

@ -20,10 +20,14 @@
#include <QtCore/QDateTime> #include <QtCore/QDateTime>
#include <QtCore/QXmlStreamReader> #include <QtCore/QXmlStreamReader>
#include <QtGui/QColor>
#include "Uuid.h" #include "Uuid.h"
class Database; class Database;
class Entry;
class Group;
class Metadata;
class Parser : public QObject class Parser : public QObject
{ {
@ -41,24 +45,33 @@ private:
void parseIcon(); void parseIcon();
void parseCustomData(); void parseCustomData();
void parseRoot(); void parseRoot();
void parseGroup(); Group* parseGroup();
void parseEntry(); Entry* parseEntry();
void parseEntryString(); void parseEntryString(Entry* entry);
void parseEntryBinary(); void parseEntryBinary(Entry* entry);
void parseAutoType(); void parseAutoType(Entry* entry);
void parseAutoTypeAssoc(); void parseAutoTypeAssoc(Entry* entry);
void parseEntryHistory(); void parseEntryHistory();
void parseTimes(); TimeInfo parseTimes();
QString readString(); QString readString();
bool readBool(); bool readBool();
QDateTime readDateTime(); QDateTime readDateTime();
int readInt(); QColor readColor();
int readNumber();
Uuid readUuid(); Uuid readUuid();
QByteArray readBinary(); QByteArray readBinary();
Group* getGroup(const Uuid& uuid);
Entry* getEntry(const Uuid& uuid);
void raiseError();
QXmlStreamReader m_xml; QXmlStreamReader m_xml;
Database* m_db; Database* m_db;
Metadata* m_meta;
Group* m_tmpParent;
QList<Group*> m_groups;
QList<Entry*> m_entries;
}; };
#endif // KEEPASSX_PARSER_H #endif // KEEPASSX_PARSER_H

View File

@ -20,3 +20,72 @@
TimeInfo::TimeInfo() TimeInfo::TimeInfo()
{ {
} }
QDateTime TimeInfo::lastModificationTime() const
{
return m_lastModificationTime;
}
QDateTime TimeInfo::creationTime() const
{
return m_creationTime;
}
QDateTime TimeInfo::lastAccessTime() const
{
return m_lastAccessTime;
}
QDateTime TimeInfo::expiryTime() const
{
return m_expiryTime;
}
bool TimeInfo::expires() const
{
return m_expires;
}
int TimeInfo::usageCount() const
{
return m_usageCount;
}
QDateTime TimeInfo::locationChanged() const
{
return m_locationChanged;
}
void TimeInfo::setLastModificationTime(const QDateTime& dateTime)
{
m_lastModificationTime = dateTime;
}
void TimeInfo::setCreationTime(const QDateTime& dateTime)
{
m_creationTime = dateTime;
}
void TimeInfo::setLastAccessTime(const QDateTime& dateTime)
{
m_lastAccessTime = dateTime;
}
void TimeInfo::setExpiryTime(const QDateTime& dateTime)
{
m_expiryTime = dateTime;
}
void TimeInfo::setExpires(bool expires)
{
m_expires = expires;
}
void TimeInfo::setUsageCount(int count)
{
m_usageCount = count;
}
void TimeInfo::setLocationChanged(const QDateTime& dateTime)
{
m_locationChanged = dateTime;
}

View File

@ -18,10 +18,37 @@
#ifndef KEEPASSX_DBTIMEINFO_H #ifndef KEEPASSX_DBTIMEINFO_H
#define KEEPASSX_DBTIMEINFO_H #define KEEPASSX_DBTIMEINFO_H
#include <QtCore/QDateTime>
class TimeInfo class TimeInfo
{ {
public: public:
TimeInfo(); TimeInfo();
QDateTime lastModificationTime() const;
QDateTime creationTime() const;
QDateTime lastAccessTime() const;
QDateTime expiryTime() const;
bool expires() const;
int usageCount() const;
QDateTime locationChanged() const;
void setLastModificationTime(const QDateTime& dateTime);
void setCreationTime(const QDateTime& dateTime);
void setLastAccessTime(const QDateTime& dateTime);
void setExpiryTime(const QDateTime& dateTime);
void setExpires(bool expires);
void setUsageCount(int count);
void setLocationChanged(const QDateTime& dateTime);
private:
QDateTime m_lastModificationTime;
QDateTime m_creationTime;
QDateTime m_lastAccessTime;
QDateTime m_expiryTime;
bool m_expires;
int m_usageCount;
QDateTime m_locationChanged;
}; };
#endif // KEEPASSX_DBTIMEINFO_H #endif // KEEPASSX_DBTIMEINFO_H

View File

@ -17,11 +17,13 @@
#include "Uuid.h" #include "Uuid.h"
Uuid::Uuid() : m_data(16, 0) const int Uuid::length = 16;
Uuid::Uuid() : m_data(length, 0)
{ {
} }
Uuid::Uuid(bool generate) : m_data(16, 0) Uuid::Uuid(bool generate) : m_data(length, 0)
{ {
if (generate) { if (generate) {
while (isNull()) { while (isNull()) {

View File

@ -32,6 +32,7 @@ public:
bool isNull() const; bool isNull() const;
bool operator==(const Uuid& other) const; bool operator==(const Uuid& other) const;
bool operator!=(const Uuid& other) const; bool operator!=(const Uuid& other) const;
static const int length;
private: private:
QByteArray m_data; QByteArray m_data;