Fix saving database backup file

* Fixes #11831
* Also fixes weird issues like saving backup of a backup due to function reuse
This commit is contained in:
Jonathan White 2025-03-10 20:31:18 -04:00
parent 33a3796074
commit 418397fb28
No known key found for this signature in database
GPG Key ID: 440FC65F2E0C6E01
2 changed files with 39 additions and 35 deletions

View File

@ -2825,6 +2825,10 @@ Disable safe saves and try again?</source>
<source>Database file on disk cannot be unlocked with current credentials.&lt;br&gt;Enter new credentials and/or present hardware key to continue.</source> <source>Database file on disk cannot be unlocked with current credentials.&lt;br&gt;Enter new credentials and/or present hardware key to continue.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Failed to save backup database: %1</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>EditEntryWidget</name> <name>EditEntryWidget</name>

View File

@ -2615,12 +2615,11 @@ bool DatabaseWidget::performSave(QString& errorMessage, const QString& fileName)
*/ */
bool DatabaseWidget::saveBackup() bool DatabaseWidget::saveBackup()
{ {
while (true) {
QString oldFilePath = m_db->filePath(); QString oldFilePath = m_db->filePath();
if (!QFileInfo::exists(oldFilePath)) { if (!QFileInfo::exists(oldFilePath)) {
QString defaultFileName = config()->get(Config::DefaultDatabaseFileName).toString(); QString defaultFileName = config()->get(Config::DefaultDatabaseFileName).toString();
oldFilePath = QDir::toNativeSeparators( oldFilePath =
FileDialog::getLastDir("db") + "/" QDir::toNativeSeparators(FileDialog::getLastDir("db") + "/"
+ (defaultFileName.isEmpty() ? tr("Passwords").append(".kdbx") : defaultFileName)); + (defaultFileName.isEmpty() ? tr("Passwords").append(".kdbx") : defaultFileName));
} }
@ -2629,31 +2628,32 @@ bool DatabaseWidget::saveBackup()
FileDialog::getLastDir("backup", oldFilePath), FileDialog::getLastDir("backup", oldFilePath),
tr("KeePass 2 Database").append(" (*.kdbx)")); tr("KeePass 2 Database").append(" (*.kdbx)"));
if (!newFilePath.isEmpty()) { // Early out if we canceled the file selection
// Ensure we don't recurse back into this function if (newFilePath.isEmpty()) {
m_db->setFilePath(newFilePath); return false;
m_saveAttempts = 0;
bool modified = m_db->isModified();
if (!save()) {
// Failed to save, try again
m_db->setFilePath(oldFilePath);
continue;
} }
// Record modified state so we can restore after save
bool modified = m_db->isModified();
QString error;
bool ok = m_db->saveAs(newFilePath, Database::DirectWrite, {}, &error);
// Restore database to original state
m_db->setFilePath(oldFilePath); m_db->setFilePath(oldFilePath);
if (modified) { if (modified) {
// Source database is marked as clean when copy is saved, even if source has unsaved changes // Source database is marked as clean when copy is saved, even if source has unsaved changes
m_db->markAsModified(); m_db->markAsModified();
} }
FileDialog::saveLastDir("backup", newFilePath, true);
return true;
}
// Canceled file selection if (!ok) {
// Failed to save backup, post the error
showErrorMessage(tr("Failed to save backup database: %1").arg(error));
return false; return false;
} }
FileDialog::saveLastDir("backup", newFilePath, true);
return true;
} }
void DatabaseWidget::showMessage(const QString& text, void DatabaseWidget::showMessage(const QString& text,