From 7a8d4577f19fbfbab3777232763e7452332812ab Mon Sep 17 00:00:00 2001 From: Sebastien Fricker Date: Sat, 3 May 2014 16:59:41 +0200 Subject: [PATCH] Automatic reload of a database when it get modified When the database if modified by an other instance of KeePassX, KeePassX detect it and reload automatically the database. --- src/CMakeLists.txt | 2 + src/core/Database.cpp | 6 +++ src/core/Database.h | 1 + src/core/FileSystemWatcher.cpp | 75 ++++++++++++++++++++++++++++++++++ src/core/FileSystemWatcher.h | 47 +++++++++++++++++++++ src/gui/DatabaseWidget.cpp | 28 +++++++++++++ src/gui/DatabaseWidget.h | 3 ++ 7 files changed, 162 insertions(+) create mode 100644 src/core/FileSystemWatcher.cpp create mode 100644 src/core/FileSystemWatcher.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d57153e5f..d221418d3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -29,6 +29,7 @@ set(keepassx_SOURCES autotype/test/AutoTypeTestInterface.h core/AutoTypeAssociations.cpp core/Config.cpp + core/FileSystemWatcher.cpp core/Database.cpp core/DatabaseIcons.cpp core/Endian.cpp @@ -136,6 +137,7 @@ set(keepassx_MOC autotype/AutoTypeSelectView.h autotype/ShortcutWidget.h autotype/WindowSelectComboBox.h + core/FileSystemWatcher.h core/AutoTypeAssociations.h core/Config.h core/Database.h diff --git a/src/core/Database.cpp b/src/core/Database.cpp index 4c888eab9..91189d66d 100644 --- a/src/core/Database.cpp +++ b/src/core/Database.cpp @@ -297,3 +297,9 @@ void Database::startModifiedTimer() } m_timer->start(150); } + +const CompositeKey & Database::key() const +{ + return m_data.key; +} + diff --git a/src/core/Database.h b/src/core/Database.h index 0ee9a9659..70f43fba2 100644 --- a/src/core/Database.h +++ b/src/core/Database.h @@ -87,6 +87,7 @@ public: QByteArray transformSeed() const; quint64 transformRounds() const; QByteArray transformedMasterKey() const; + const CompositeKey & key() const; void setCipher(const Uuid& cipher); void setCompressionAlgo(Database::CompressionAlgorithm algo); diff --git a/src/core/FileSystemWatcher.cpp b/src/core/FileSystemWatcher.cpp new file mode 100644 index 000000000..93b4f6f3f --- /dev/null +++ b/src/core/FileSystemWatcher.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2012 Felix Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "FileSystemWatcher.h" +#include +#include +#include + +FileSystemWatcher::FileSystemWatcher (): QFileSystemWatcher ( ) +{ + connect(this,SIGNAL( fileChanged ( const QString & )), + this,SLOT( fileChangedSlot ( const QString & ))); + connect(this,SIGNAL( directoryChanged ( const QString & )), + this,SLOT( directoryChangedSlot ( const QString & ))); +} + +void FileSystemWatcher::watchFile(const QString &file) +{ + _file=file; + if (!files().isEmpty()) + removePaths(files()); + if (!directories().isEmpty()) + removePaths(directories()); + QFileInfo fileInfo(file); + if (fileInfo.exists()) + addPath(file); + QString filePath=fileInfo.absoluteDir().path(); + QFileInfo filePathInfo(filePath); + if (filePathInfo.exists()) + addPath(filePath); +} + +void FileSystemWatcher::stopWatching() +{ + watchFile( QString() ); +} + +void FileSystemWatcher::fileChangedSlot ( const QString & ) +{ + QFileInfo fileInfo(_file); + if ( fileInfo.exists() ) + fileChanged(); +} + +void FileSystemWatcher::directoryChangedSlot ( const QString & ) +{ + if (!files().contains(_file)) + { + QFileInfo fileInfo(_file); + if ( fileInfo.exists() ) + { + addPath(_file); + fileChanged(); + } + } +} + +FileSystemWatcher::~FileSystemWatcher() +{ +} + diff --git a/src/core/FileSystemWatcher.h b/src/core/FileSystemWatcher.h new file mode 100644 index 000000000..4721a98b7 --- /dev/null +++ b/src/core/FileSystemWatcher.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012 Felix Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef FILE_SYSTEM_WATCHER_H +#define FILE_SYSTEM_WATCHER_H +#include +#include +#include + + +class FileSystemWatcher : public QFileSystemWatcher +{ + Q_OBJECT ; + +public: + FileSystemWatcher (); + void watchFile( const QString & ); + void stopWatching(); + + virtual ~FileSystemWatcher(); + +private: + QString _file; + +private Q_SLOTS: + void directoryChangedSlot ( const QString & ); + void fileChangedSlot ( const QString & ); +Q_SIGNALS: + void fileChanged(); +}; + +#endif + diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 419028ab8..1dc694f69 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -22,9 +22,11 @@ #include #include #include +#include #include #include #include +#include #include "autotype/AutoType.h" #include "core/Config.h" @@ -32,6 +34,7 @@ #include "core/Group.h" #include "core/Metadata.h" #include "core/Tools.h" +#include "format/KeePass2Reader.h" #include "gui/ChangeMasterKeyWidget.h" #include "gui/Clipboard.h" #include "gui/DatabaseOpenWidget.h" @@ -159,6 +162,7 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) connect(m_searchUi->searchEdit, SIGNAL(returnPressed()), m_entryView, SLOT(setFocus())); connect(m_searchTimer, SIGNAL(timeout()), this, SLOT(search())); connect(closeAction, SIGNAL(triggered()), this, SLOT(closeSearch())); + connect( &m_file_watcher, SIGNAL( fileChanged() ), this, SLOT( databaseModifedExternally() ) ); setCurrentWidget(m_mainWidget); } @@ -580,8 +584,10 @@ void DatabaseWidget::openDatabase(bool accepted) m_databaseOpenWidget = Q_NULLPTR; delete m_keepass1OpenWidget; m_keepass1OpenWidget = Q_NULLPTR; + m_file_watcher.watchFile( m_filename ); } else { + m_file_watcher.stopWatching(); if (m_databaseOpenWidget->database()) { delete m_databaseOpenWidget->database(); } @@ -811,3 +817,25 @@ void DatabaseWidget::updateFilename(const QString& fileName) { m_filename = fileName; } + +void DatabaseWidget::databaseModifedExternally() +{ + if ( database() == Q_NULLPTR ) + return; + + KeePass2Reader reader; + QFile file(m_filename); + if (!file.open(QIODevice::ReadOnly)) { + // TODO: error message + return; + } + Database* db = reader.readDatabase(&file, database()->key() ); + if ( db ) + { + Database* oldDb = m_db; + m_db = db; + m_groupView->changeDatabase(m_db); + Q_EMIT databaseChanged(m_db); + delete oldDb; + } +} diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index b535a9b8f..a83f3206a 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -24,6 +24,7 @@ #include "core/Global.h" #include "gui/entry/EntryModel.h" +#include "core/FileSystemWatcher.h" class ChangeMasterKeyWidget; class DatabaseOpenWidget; @@ -118,6 +119,7 @@ private Q_SLOTS: void switchToGroupEdit(Group* entry, bool create); void updateMasterKey(bool accepted); void openDatabase(bool accepted); + void databaseModifedExternally(); void unlockDatabase(bool accepted); void emitCurrentModeChanged(); void clearLastGroup(Group* group); @@ -152,6 +154,7 @@ private: QTimer* m_searchTimer; QWidget* widgetBeforeLock; QString m_filename; + FileSystemWatcher m_file_watcher; }; #endif // KEEPASSX_DATABASEWIDGET_H