Implemented database file hidden attribute preservation on Windows (#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>
This commit is contained in:
Drwsburah 2024-03-31 19:48:57 +01:00 committed by GitHub
parent db0b659a53
commit 812bb606c7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 0 deletions

View File

@ -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()
@ -280,6 +284,11 @@ 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);
@ -287,6 +296,13 @@ bool Database::saveAs(const QString& filePath, SaveAction action, const QString&
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

View File

@ -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");
@ -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));