Support TIMEOTP autotype and entry placeholder (#13117)

* Additional fix for #7263 to support KeePass2 placeholder for TOTP

---------

Co-authored-by: Janek Bevendorff <janek@keepassxc.org>
This commit is contained in:
Jonathan White 2026-03-08 23:17:36 -04:00 committed by Janek Bevendorff
parent bc5875f101
commit 552e9e6aec
No known key found for this signature in database
GPG key ID: 2CF41D2AA8438F99
4 changed files with 25 additions and 3 deletions

View file

@ -645,7 +645,7 @@ AutoType::parseSequence(const QString& entrySequence, const Entry* entry, QStrin
} else if (placeholder == "clearfield") {
// Platform-specific field clearing
actions << QSharedPointer<AutoTypeClearField>::create();
} else if (placeholder == "totp") {
} else if (placeholder == "totp" || placeholder == "timeotp") {
if (entry->hasValidTotp()) {
// Calculate TOTP at the time of typing including delays
bool isValid = false;

View file

@ -1585,6 +1585,7 @@ Entry::PlaceholderType Entry::placeholderType(const QString& placeholder) const
{QStringLiteral("{PASSWORD}"), PlaceholderType::Password},
{QStringLiteral("{NOTES}"), PlaceholderType::Notes},
{QStringLiteral("{TOTP}"), PlaceholderType::Totp},
{QStringLiteral("{TIMEOTP}"), PlaceholderType::Totp},
{QStringLiteral("{URL}"), PlaceholderType::Url},
{QStringLiteral("{UUID}"), PlaceholderType::Uuid},
{QStringLiteral("{URL:RMVSCM}"), PlaceholderType::UrlWithoutScheme},

View file

@ -19,6 +19,7 @@
#include "TestAutoType.h"
#include <QPluginLoader>
#include <QRegularExpression>
#include <QTest>
#include "autotype/AutoType.h"
@ -473,7 +474,7 @@ void TestAutoType::testAutoTypeEmptyWindowAssociation()
QVERIFY(assoc.isEmpty());
}
void TestAutoType::testAutoTypeTotpDelay()
void TestAutoType::testAutoTypeTotp()
{
// Get the TOTP time step in milliseconds
auto totpStep = m_entry1->totpSettings()->step * 1000;
@ -492,4 +493,24 @@ void TestAutoType::testAutoTypeTotpDelay()
QString("Typed TOTP (%1) should differ from current TOTP (%2) due to delay")
.arg(totpParts[0], totpParts[1])
.toLatin1());
m_test->clearActions();
// Test TIMEOTP placeholder (KeePass2 Compatibility)
m_autoType->performAutoTypeWithSequence(m_entry1, "{TIMEOTP}");
typedChars = m_test->actionChars();
QCOMPARE(typedChars.size(), m_entry1->totpSettings()->digits);
// Verify that the typedchars are all numbers
QRegularExpression re("^\\d+$");
QVERIFY(re.match(typedChars).hasMatch());
m_test->clearActions();
// Test that TIMEOTP also works as an entry placeholder
m_entry1->setPassword("{TIMEOTP}");
m_autoType->performAutoTypeWithSequence(m_entry1, "{PASSWORD}");
typedChars = m_test->actionChars();
QCOMPARE(typedChars.size(), m_entry1->totpSettings()->digits);
// Verify that the typedchars are all numbers
QVERIFY(re.match(typedChars).hasMatch());
}

View file

@ -52,7 +52,7 @@ private slots:
void testAutoTypeSyntaxChecks();
void testAutoTypeEffectiveSequences();
void testAutoTypeEmptyWindowAssociation();
void testAutoTypeTotpDelay();
void testAutoTypeTotp();
private:
AutoTypePlatformInterface* m_platform;