mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
Fix backup file path substitution
Previously, in a pattern like "{TIME:yy} {TIME}", substituteBackupFilePath() would greedily use the entire string "yy} {TIME" as the format specifier for the first TIME template, instead of just "yy". Fix this, by adjusting the regular expression. This ends up changing the behaviour of a weird corner case that is covered in the tests, so change the test. I don't think anyone cares about that case, and I think the current behaviour is better there. Fixes #10505 (proved by adding a test case very similar to what was reported there).
This commit is contained in:
parent
34808a2caa
commit
dad8b1d2ea
@ -449,33 +449,32 @@ namespace Tools
|
||||
|
||||
QString substituteBackupFilePath(QString pattern, const QString& databasePath)
|
||||
{
|
||||
// Fail if substitution fails
|
||||
if (databasePath.isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Replace backup pattern
|
||||
QFileInfo dbFileInfo(databasePath);
|
||||
QString baseName = dbFileInfo.completeBaseName();
|
||||
const QString baseName = QFileInfo{databasePath}.completeBaseName();
|
||||
|
||||
pattern.replace(QString("{DB_FILENAME}"), baseName);
|
||||
pattern.replace(QStringLiteral("{DB_FILENAME}"), baseName);
|
||||
|
||||
auto re = QRegularExpression(R"(\{TIME(?::([^\\]*))?\})");
|
||||
const QDateTime now = Clock::currentDateTime();
|
||||
|
||||
const QRegularExpression re(R"(\{TIME(?::([^\\{}]*))?\})");
|
||||
auto match = re.match(pattern);
|
||||
while (match.hasMatch()) {
|
||||
// Extract time format specifier
|
||||
auto formatSpecifier = QString("dd_MM_yyyy_hh-mm-ss");
|
||||
// Extract time format specifier, or use default value if absent
|
||||
QString formatSpecifier = "dd_MM_yyyy_hh-mm-ss";
|
||||
if (!match.captured(1).isEmpty()) {
|
||||
formatSpecifier = match.captured(1);
|
||||
}
|
||||
auto replacement = Clock::currentDateTime().toString(formatSpecifier);
|
||||
const auto replacement = now.toString(formatSpecifier);
|
||||
pattern.replace(match.capturedStart(), match.capturedLength(), replacement);
|
||||
match = re.match(pattern);
|
||||
}
|
||||
|
||||
// Replace escaped braces
|
||||
pattern.replace("\\{", "{");
|
||||
pattern.replace("\\}", "}");
|
||||
pattern.replace(QStringLiteral("\\{"), QStringLiteral("{"));
|
||||
pattern.replace(QStringLiteral("\\}"), QStringLiteral("}"));
|
||||
|
||||
return pattern;
|
||||
}
|
||||
|
@ -150,6 +150,12 @@ void TestTools::testBackupFilePatternSubstitution_data()
|
||||
QTest::newRow("Default time pattern (empty formatter)")
|
||||
<< "{TIME:}" << DEFAULT_DB_FILE_PATH << DEFAULT_FORMATTED_TIME;
|
||||
QTest::newRow("Custom time pattern") << "{TIME:dd-ss}" << DEFAULT_DB_FILE_PATH << NOW.toString("dd-ss");
|
||||
QTest::newRow("Time pattern twice") << "{TIME:yy} {TIME}" << DEFAULT_DB_FILE_PATH
|
||||
<< NOW.toString("yy") + QStringLiteral(" ") + DEFAULT_FORMATTED_TIME;
|
||||
QTest::newRow("Complex custom time pattern")
|
||||
<< "./{TIME:yy}/{DB_FILENAME}_{TIME:yyyyMMdd_HHmmss}.old.kdbx" << DEFAULT_DB_FILE_PATH
|
||||
<< QStringLiteral("./") + NOW.toString("yy") + QStringLiteral("/") + DEFAULT_DB_FILE_NAME + QStringLiteral("_")
|
||||
+ NOW.toString("yyyyMMdd_HHmmss") + QStringLiteral(".old.kdbx");
|
||||
QTest::newRow("Invalid custom time pattern") << "{TIME:dd/-ss}" << DEFAULT_DB_FILE_PATH << NOW.toString("dd/-ss");
|
||||
QTest::newRow("Recursive substitution") << "{TIME:'{TIME}'}" << DEFAULT_DB_FILE_PATH << DEFAULT_FORMATTED_TIME;
|
||||
QTest::newRow("{DB_FILENAME} substitution")
|
||||
@ -161,7 +167,7 @@ void TestTools::testBackupFilePatternSubstitution_data()
|
||||
// Not relevant right now, added test anyway
|
||||
QTest::newRow("There should be no substitution loops") << "{DB_FILENAME}"
|
||||
<< "{TIME:'{DB_FILENAME}'}.ext"
|
||||
<< "{DB_FILENAME}";
|
||||
<< "{TIME:'{DB_FILENAME}'}";
|
||||
}
|
||||
|
||||
void TestTools::testBackupFilePatternSubstitution()
|
||||
|
Loading…
Reference in New Issue
Block a user