mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
Merge pull request #1414 from keepassxreboot/feature/1360-fix-totp-crash
Fix multiple TOTP issues, resolves #1360
This commit is contained in:
commit
83f1a53d32
@ -45,6 +45,7 @@ Entry::Entry()
|
|||||||
m_data.totpStep = Totp::defaultStep;
|
m_data.totpStep = Totp::defaultStep;
|
||||||
m_data.totpDigits = Totp::defaultDigits;
|
m_data.totpDigits = Totp::defaultDigits;
|
||||||
|
|
||||||
|
connect(m_attributes, SIGNAL(modified()), SLOT(updateTotp()));
|
||||||
connect(m_attributes, SIGNAL(modified()), this, SIGNAL(modified()));
|
connect(m_attributes, SIGNAL(modified()), this, SIGNAL(modified()));
|
||||||
connect(m_attributes, SIGNAL(defaultKeyModified()), SLOT(emitDataChanged()));
|
connect(m_attributes, SIGNAL(defaultKeyModified()), SLOT(emitDataChanged()));
|
||||||
connect(m_attachments, SIGNAL(modified()), this, SIGNAL(modified()));
|
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);
|
QString output = Totp::generateTotp(seed.toLatin1(), time, m_data.totpDigits, m_data.totpStep);
|
||||||
|
|
||||||
return QString(output);
|
return QString(output);
|
||||||
} else {
|
|
||||||
return QString("");
|
|
||||||
}
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entry::setTotp(const QString& seed, quint8& step, quint8& digits)
|
void Entry::setTotp(const QString& seed, quint8& step, quint8& digits)
|
||||||
@ -388,23 +388,6 @@ QString Entry::totpSeed() const
|
|||||||
secret = m_attributes->value("TOTP Seed");
|
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);
|
return Totp::parseOtpString(secret, m_data.totpDigits, m_data.totpStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -722,6 +705,33 @@ void Entry::updateModifiedSinceBegin()
|
|||||||
m_modifiedSinceBegin = true;
|
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<quint8>(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<quint8>(m.captured(2).toUInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString Entry::resolveMultiplePlaceholdersRecursive(const QString& str, int maxDepth) const
|
QString Entry::resolveMultiplePlaceholdersRecursive(const QString& str, int maxDepth) const
|
||||||
{
|
{
|
||||||
if (maxDepth <= 0) {
|
if (maxDepth <= 0) {
|
||||||
|
@ -210,6 +210,7 @@ private slots:
|
|||||||
void emitDataChanged();
|
void emitDataChanged();
|
||||||
void updateTimeinfo();
|
void updateTimeinfo();
|
||||||
void updateModifiedSinceBegin();
|
void updateModifiedSinceBegin();
|
||||||
|
void updateTotp();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString resolveMultiplePlaceholdersRecursive(const QString& str, int maxDepth) const;
|
QString resolveMultiplePlaceholdersRecursive(const QString& str, int maxDepth) const;
|
||||||
|
@ -20,16 +20,12 @@
|
|||||||
#include "ui_DetailsWidget.h"
|
#include "ui_DetailsWidget.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QTimer>
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QTemporaryFile>
|
|
||||||
|
|
||||||
#include "core/Config.h"
|
#include "core/Config.h"
|
||||||
#include "core/FilePath.h"
|
#include "core/FilePath.h"
|
||||||
#include "core/TimeInfo.h"
|
|
||||||
#include "gui/Clipboard.h"
|
#include "gui/Clipboard.h"
|
||||||
#include "gui/DatabaseWidget.h"
|
|
||||||
#include "entry/EntryAttachmentsModel.h"
|
#include "entry/EntryAttachmentsModel.h"
|
||||||
|
|
||||||
DetailsWidget::DetailsWidget(QWidget* parent)
|
DetailsWidget::DetailsWidget(QWidget* parent)
|
||||||
@ -70,6 +66,9 @@ DetailsWidget::DetailsWidget(QWidget* parent)
|
|||||||
|
|
||||||
DetailsWidget::~DetailsWidget()
|
DetailsWidget::~DetailsWidget()
|
||||||
{
|
{
|
||||||
|
if (m_timer) {
|
||||||
|
delete m_timer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DetailsWidget::getSelectedEntry(Entry* selectedEntry)
|
void DetailsWidget::getSelectedEntry(Entry* selectedEntry)
|
||||||
@ -154,13 +153,13 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry)
|
|||||||
if (m_currentEntry->hasTotp()) {
|
if (m_currentEntry->hasTotp()) {
|
||||||
m_step = m_currentEntry->totpStep();
|
m_step = m_currentEntry->totpStep();
|
||||||
|
|
||||||
if (nullptr != m_timer) {
|
if (m_timer) {
|
||||||
m_timer->stop();
|
delete m_timer;
|
||||||
}
|
}
|
||||||
m_timer = new QTimer(this);
|
m_timer = new QTimer(selectedEntry);
|
||||||
connect(m_timer, SIGNAL(timeout()), this, SLOT(updateTotp()));
|
connect(m_timer, SIGNAL(timeout()), this, SLOT(updateTotp()));
|
||||||
updateTotp();
|
updateTotp();
|
||||||
m_timer->start(m_step * 10);
|
m_timer->start(m_step * 1000);
|
||||||
m_ui->totpButton->show();
|
m_ui->totpButton->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,7 +287,7 @@ void DetailsWidget::updateTotp()
|
|||||||
QString firstHalf = totpCode.left(totpCode.size() / 2);
|
QString firstHalf = totpCode.left(totpCode.size() / 2);
|
||||||
QString secondHalf = totpCode.mid(totpCode.size() / 2);
|
QString secondHalf = totpCode.mid(totpCode.size() / 2);
|
||||||
m_ui->totpLabel->setText(firstHalf + " " + secondHalf);
|
m_ui->totpLabel->setText(firstHalf + " " + secondHalf);
|
||||||
} else if (nullptr != m_timer) {
|
} else if (m_timer) {
|
||||||
m_timer->stop();
|
m_timer->stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "gui/DatabaseWidget.h"
|
#include "gui/DatabaseWidget.h"
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class DetailsWidget;
|
class DetailsWidget;
|
||||||
@ -67,7 +68,7 @@ private:
|
|||||||
Entry* m_currentEntry;
|
Entry* m_currentEntry;
|
||||||
Group* m_currentGroup;
|
Group* m_currentGroup;
|
||||||
quint8 m_step;
|
quint8 m_step;
|
||||||
QTimer* m_timer;
|
QPointer<QTimer> m_timer = nullptr;
|
||||||
QWidget* m_attributesTabWidget;
|
QWidget* m_attributesTabWidget;
|
||||||
QWidget* m_attachmentsTabWidget;
|
QWidget* m_attachmentsTabWidget;
|
||||||
QWidget* m_autotypeTabWidget;
|
QWidget* m_autotypeTabWidget;
|
||||||
|
@ -20,33 +20,24 @@
|
|||||||
#include "ui_TotpDialog.h"
|
#include "ui_TotpDialog.h"
|
||||||
|
|
||||||
#include "core/Config.h"
|
#include "core/Config.h"
|
||||||
#include "core/Entry.h"
|
|
||||||
#include "gui/DatabaseWidget.h"
|
|
||||||
#include "gui/Clipboard.h"
|
#include "gui/Clipboard.h"
|
||||||
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QDateTime>
|
|
||||||
#include <QPushButton>
|
|
||||||
|
|
||||||
|
|
||||||
TotpDialog::TotpDialog(DatabaseWidget* parent, Entry* entry)
|
TotpDialog::TotpDialog(DatabaseWidget* parent, Entry* entry)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
, m_ui(new Ui::TotpDialog())
|
, 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_ui->setupUi(this);
|
||||||
|
|
||||||
|
m_step = m_entry->totpStep();
|
||||||
uCounter = resetCounter();
|
uCounter = resetCounter();
|
||||||
updateProgressBar();
|
updateProgressBar();
|
||||||
|
|
||||||
QTimer* timer = new QTimer(this);
|
connect(m_totpUpdateTimer, SIGNAL(timeout()), this, SLOT(updateProgressBar()));
|
||||||
connect(timer, SIGNAL(timeout()), this, SLOT(updateProgressBar()));
|
connect(m_totpUpdateTimer, SIGNAL(timeout()), this, SLOT(updateSeconds()));
|
||||||
connect(timer, SIGNAL(timeout()), this, SLOT(updateSeconds()));
|
m_totpUpdateTimer->start(m_step * 10);
|
||||||
timer->start(m_step * 10);
|
|
||||||
|
|
||||||
updateTotp();
|
updateTotp();
|
||||||
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
@ -61,7 +52,7 @@ void TotpDialog::copyToClipboard()
|
|||||||
{
|
{
|
||||||
clipboard()->setText(m_entry->totp());
|
clipboard()->setText(m_entry->totp());
|
||||||
if (config()->get("MinimizeOnCopy").toBool()) {
|
if (config()->get("MinimizeOnCopy").toBool()) {
|
||||||
m_parent->window()->showMinimized();
|
qobject_cast<DatabaseWidget*>(parent())->window()->showMinimized();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,4 +92,7 @@ double TotpDialog::resetCounter()
|
|||||||
|
|
||||||
TotpDialog::~TotpDialog()
|
TotpDialog::~TotpDialog()
|
||||||
{
|
{
|
||||||
|
if (m_totpUpdateTimer) {
|
||||||
|
delete m_totpUpdateTimer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <totp/totp.h>
|
||||||
#include "core/Entry.h"
|
#include "core/Entry.h"
|
||||||
#include "core/Database.h"
|
#include "core/Database.h"
|
||||||
#include "gui/DatabaseWidget.h"
|
#include "gui/DatabaseWidget.h"
|
||||||
@ -39,8 +41,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
double uCounter;
|
double uCounter;
|
||||||
quint8 m_step;
|
quint8 m_step = Totp::defaultStep;
|
||||||
QScopedPointer<Ui::TotpDialog> m_ui;
|
QScopedPointer<Ui::TotpDialog> m_ui;
|
||||||
|
QPointer<QTimer> m_totpUpdateTimer;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void updateTotp();
|
void updateTotp();
|
||||||
@ -51,7 +54,6 @@ private Q_SLOTS:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
Entry* m_entry;
|
Entry* m_entry;
|
||||||
DatabaseWidget* m_parent;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // KEEPASSX_TOTPDIALOG_H
|
#endif // KEEPASSX_TOTPDIALOG_H
|
||||||
|
Loading…
Reference in New Issue
Block a user