Skip to content

Commit

Permalink
Implemented database file hidden attribute preservation on Windows (#…
Browse files Browse the repository at this point in the history
…10343)

* Implemented database file hidden attribute preservation on Windows

Implemented database file hidden attribute preservation on Windows by modifying the save function to check the hidden attribute of the original database before saving and then reapply it post-saving if running on Windows so that users can easily store their database in a hidden file without having to re-hide it every time it's modified.

Updated the TestDatabase::testSaveAs() unit test to first verify after the initial save that the database file is not hidden before hiding it then saving again and verifying that it is now hidden.

Signed-off-by: Drwsburah <Drwsburah@yahoo.com>
Co-authored-by: Jonathan White <support@dmapps.us>
  • Loading branch information
Drwsburah and droidmonkey authored Mar 31, 2024
1 parent db0b659 commit 812bb60
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/core/Database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
#include <QTemporaryFile>
#include <QTimer>

#ifdef Q_OS_WIN
#include <Windows.h>
#endif

QHash<QUuid, QPointer<Database>> Database::s_uuidMap;

Database::Database()
Expand Down Expand Up @@ -280,13 +284,25 @@ bool Database::saveAs(const QString& filePath, SaveAction action, const QString&
QFileInfo fileInfo(filePath);
auto realFilePath = fileInfo.exists() ? fileInfo.canonicalFilePath() : fileInfo.absoluteFilePath();
bool isNewFile = !QFile::exists(realFilePath);

#ifdef Q_OS_WIN
bool isHidden = fileInfo.isHidden();
#endif

bool ok = AsyncTask::runAndWaitForFuture([&] { return performSave(realFilePath, action, backupFilePath, error); });
if (ok) {
setFilePath(filePath);
markAsClean();
if (isNewFile) {
QFile::setPermissions(realFilePath, QFile::ReadUser | QFile::WriteUser);
}

#ifdef Q_OS_WIN
if (isHidden) {
SetFileAttributes(realFilePath.toStdString().c_str(), FILE_ATTRIBUTE_HIDDEN);
}
#endif

m_fileWatcher->start(realFilePath, 30, 1);
} else {
// Saving failed, don't rewatch file since it does not represent our database
Expand Down
11 changes: 11 additions & 0 deletions tests/TestDatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@
#include "format/KeePass2Writer.h"
#include "util/TemporaryFile.h"

#ifdef Q_OS_WIN
#include <QFileInfo>
#include <Windows.h>
#endif

QTEST_GUILESS_MAIN(TestDatabase)

static QString dbFileName = QStringLiteral(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase.kdbx");
Expand Down Expand Up @@ -118,6 +123,12 @@ void TestDatabase::testSaveAs()
QVERIFY(!db->isModified());
QCOMPARE(spyFilePathChanged.count(), 1);
QVERIFY(QFile::exists(newDbFileName));
#ifdef Q_OS_WIN
QVERIFY(!QFileInfo::QFileInfo(newDbFileName).isHidden());
SetFileAttributes(newDbFileName.toStdString().c_str(), FILE_ATTRIBUTE_HIDDEN);
QVERIFY2(db->saveAs(newDbFileName, Database::Atomic, QString(), &error), error.toLatin1());
QVERIFY(QFileInfo::QFileInfo(newDbFileName).isHidden());
#endif
QFile::remove(newDbFileName);
QVERIFY(!QFile::exists(newDbFileName));

Expand Down

0 comments on commit 812bb60

Please sign in to comment.