diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index 669be0ed1..ed8860835 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -45,6 +45,7 @@ Entry::Entry() m_data.totpStep = Totp::defaultStep; m_data.totpDigits = Totp::defaultDigits; + connect(m_attributes, SIGNAL(modified()), SLOT(updateTotp())); connect(m_attributes, SIGNAL(modified()), this, SIGNAL(modified())); connect(m_attributes, SIGNAL(defaultKeyModified()), SLOT(emitDataChanged())); connect(m_attachments, SIGNAL(modified()), this, SIGNAL(modified())); @@ -343,9 +344,8 @@ QString Entry::totp() const QString output = Totp::generateTotp(seed.toLatin1(), time, m_data.totpDigits, m_data.totpStep); return QString(output); - } else { - return QString(""); } + return {}; } void Entry::setTotp(const QString& seed, quint8& step, quint8& digits) @@ -388,23 +388,6 @@ QString Entry::totpSeed() const secret = m_attributes->value("TOTP Seed"); } - m_data.totpDigits = Totp::defaultDigits; - m_data.totpStep = Totp::defaultStep; - - if (m_attributes->hasKey("TOTP Settings")) { - // this regex must be kept in sync with the set of allowed short names Totp::shortNameToEncoder - QRegularExpression rx(QString("(\\d+);((?:\\d+)|S)")); - QRegularExpressionMatch m = rx.match(m_attributes->value("TOTP Settings")); - if (m.hasMatch()) { - m_data.totpStep = m.captured(1).toUInt(); - if (Totp::shortNameToEncoder.contains(m.captured(2))) { - m_data.totpDigits = Totp::shortNameToEncoder[m.captured(2)]; - } else { - m_data.totpDigits = m.captured(2).toUInt(); - } - } - } - return Totp::parseOtpString(secret, m_data.totpDigits, m_data.totpStep); } @@ -722,6 +705,33 @@ void Entry::updateModifiedSinceBegin() m_modifiedSinceBegin = true; } +/** + * Update TOTP data whenever entry attributes have changed. + */ +void Entry::updateTotp() +{ + m_data.totpDigits = Totp::defaultDigits; + m_data.totpStep = Totp::defaultStep; + + if (!m_attributes->hasKey("TOTP Settings")) { + return; + } + + // this regex must be kept in sync with the set of allowed short names Totp::shortNameToEncoder + QRegularExpression rx(QString("(\\d+);((?:\\d+)|S)")); + QRegularExpressionMatch m = rx.match(m_attributes->value("TOTP Settings")); + if (!m.hasMatch()) { + return; + } + + m_data.totpStep = static_cast(m.captured(1).toUInt()); + if (Totp::shortNameToEncoder.contains(m.captured(2))) { + m_data.totpDigits = Totp::shortNameToEncoder[m.captured(2)]; + } else { + m_data.totpDigits = static_cast(m.captured(2).toUInt()); + } +} + QString Entry::resolveMultiplePlaceholdersRecursive(const QString& str, int maxDepth) const { if (maxDepth <= 0) { diff --git a/src/core/Entry.h b/src/core/Entry.h index 266254e65..7b995b7ae 100644 --- a/src/core/Entry.h +++ b/src/core/Entry.h @@ -210,6 +210,7 @@ private slots: void emitDataChanged(); void updateTimeinfo(); void updateModifiedSinceBegin(); + void updateTotp(); private: QString resolveMultiplePlaceholdersRecursive(const QString& str, int maxDepth) const; diff --git a/src/gui/DetailsWidget.cpp b/src/gui/DetailsWidget.cpp index 44c29f8f8..9f0d2bfd8 100644 --- a/src/gui/DetailsWidget.cpp +++ b/src/gui/DetailsWidget.cpp @@ -20,16 +20,12 @@ #include "ui_DetailsWidget.h" #include -#include #include #include -#include #include "core/Config.h" #include "core/FilePath.h" -#include "core/TimeInfo.h" #include "gui/Clipboard.h" -#include "gui/DatabaseWidget.h" #include "entry/EntryAttachmentsModel.h" DetailsWidget::DetailsWidget(QWidget* parent) @@ -70,6 +66,9 @@ DetailsWidget::DetailsWidget(QWidget* parent) DetailsWidget::~DetailsWidget() { + if (m_timer) { + delete m_timer; + } } void DetailsWidget::getSelectedEntry(Entry* selectedEntry) @@ -154,13 +153,13 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry) if (m_currentEntry->hasTotp()) { m_step = m_currentEntry->totpStep(); - if (nullptr != m_timer) { - m_timer->stop(); + if (m_timer) { + delete m_timer; } - m_timer = new QTimer(this); + m_timer = new QTimer(selectedEntry); connect(m_timer, SIGNAL(timeout()), this, SLOT(updateTotp())); updateTotp(); - m_timer->start(m_step * 10); + m_timer->start(m_step * 1000); m_ui->totpButton->show(); } @@ -288,7 +287,7 @@ void DetailsWidget::updateTotp() QString firstHalf = totpCode.left(totpCode.size() / 2); QString secondHalf = totpCode.mid(totpCode.size() / 2); m_ui->totpLabel->setText(firstHalf + " " + secondHalf); - } else if (nullptr != m_timer) { + } else if (m_timer) { m_timer->stop(); } } diff --git a/src/gui/DetailsWidget.h b/src/gui/DetailsWidget.h index 832839bbb..2af184c48 100644 --- a/src/gui/DetailsWidget.h +++ b/src/gui/DetailsWidget.h @@ -20,6 +20,7 @@ #include "gui/DatabaseWidget.h" #include +#include namespace Ui { class DetailsWidget; @@ -67,7 +68,7 @@ private: Entry* m_currentEntry; Group* m_currentGroup; quint8 m_step; - QTimer* m_timer; + QPointer m_timer = nullptr; QWidget* m_attributesTabWidget; QWidget* m_attachmentsTabWidget; QWidget* m_autotypeTabWidget; diff --git a/src/gui/TotpDialog.cpp b/src/gui/TotpDialog.cpp index 474acf773..7325d2536 100644 --- a/src/gui/TotpDialog.cpp +++ b/src/gui/TotpDialog.cpp @@ -20,33 +20,24 @@ #include "ui_TotpDialog.h" #include "core/Config.h" -#include "core/Entry.h" -#include "gui/DatabaseWidget.h" #include "gui/Clipboard.h" -#include -#include -#include - TotpDialog::TotpDialog(DatabaseWidget* parent, Entry* entry) : QDialog(parent) , m_ui(new Ui::TotpDialog()) + , m_totpUpdateTimer(new QTimer(entry)) + , m_entry(entry) { - m_entry = entry; - m_parent = parent; - m_step = m_entry->totpStep(); - m_ui->setupUi(this); + m_step = m_entry->totpStep(); uCounter = resetCounter(); updateProgressBar(); - QTimer* timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(updateProgressBar())); - connect(timer, SIGNAL(timeout()), this, SLOT(updateSeconds())); - timer->start(m_step * 10); - + connect(m_totpUpdateTimer, SIGNAL(timeout()), this, SLOT(updateProgressBar())); + connect(m_totpUpdateTimer, SIGNAL(timeout()), this, SLOT(updateSeconds())); + m_totpUpdateTimer->start(m_step * 10); updateTotp(); setAttribute(Qt::WA_DeleteOnClose); @@ -61,7 +52,7 @@ void TotpDialog::copyToClipboard() { clipboard()->setText(m_entry->totp()); if (config()->get("MinimizeOnCopy").toBool()) { - m_parent->window()->showMinimized(); + qobject_cast(parent())->window()->showMinimized(); } } @@ -101,4 +92,7 @@ double TotpDialog::resetCounter() TotpDialog::~TotpDialog() { + if (m_totpUpdateTimer) { + delete m_totpUpdateTimer; + } } diff --git a/src/gui/TotpDialog.h b/src/gui/TotpDialog.h index 33eac6658..ce21a66fd 100644 --- a/src/gui/TotpDialog.h +++ b/src/gui/TotpDialog.h @@ -21,6 +21,8 @@ #include #include +#include +#include #include "core/Entry.h" #include "core/Database.h" #include "gui/DatabaseWidget.h" @@ -39,8 +41,9 @@ public: private: double uCounter; - quint8 m_step; + quint8 m_step = Totp::defaultStep; QScopedPointer m_ui; + QPointer m_totpUpdateTimer; private Q_SLOTS: void updateTotp(); @@ -51,7 +54,6 @@ private Q_SLOTS: protected: Entry* m_entry; - DatabaseWidget* m_parent; }; #endif // KEEPASSX_TOTPDIALOG_H