2013-03-10 17:23:10 -04:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2013 Felix Geyer <debfx@fobos.de>
|
2022-01-30 10:59:29 -05:00
|
|
|
* Copyright (C) 2022 KeePassXC Team <team@keepassxc.org>
|
2013-03-10 17:23:10 -04:00
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 2 or (at your option)
|
|
|
|
* version 3 of the License.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "PasswordGeneratorWidget.h"
|
|
|
|
#include "ui_PasswordGeneratorWidget.h"
|
|
|
|
|
2021-10-17 02:53:25 -04:00
|
|
|
#include <QCloseEvent>
|
2017-03-04 09:10:50 -05:00
|
|
|
#include <QDir>
|
2021-04-18 22:37:12 -04:00
|
|
|
#include <QShortcut>
|
2020-07-19 09:30:00 -04:00
|
|
|
#include <QTimer>
|
2014-01-12 17:33:36 -05:00
|
|
|
|
2013-06-28 22:29:03 -04:00
|
|
|
#include "core/Config.h"
|
2020-02-01 08:42:34 -05:00
|
|
|
#include "core/PasswordHealth.h"
|
2020-03-08 20:27:16 -04:00
|
|
|
#include "core/Resources.h"
|
2017-05-28 13:47:33 -04:00
|
|
|
#include "gui/Clipboard.h"
|
2021-11-04 23:02:33 -04:00
|
|
|
#include "gui/FileDialog.h"
|
2020-10-05 20:41:00 -04:00
|
|
|
#include "gui/Icons.h"
|
2021-11-04 23:02:33 -04:00
|
|
|
#include "gui/MessageBox.h"
|
2020-04-11 11:01:50 -04:00
|
|
|
#include "gui/styles/StateColorPalette.h"
|
2013-06-28 22:29:03 -04:00
|
|
|
|
2013-03-10 17:23:10 -04:00
|
|
|
PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent)
|
|
|
|
: QWidget(parent)
|
2017-03-04 09:10:50 -05:00
|
|
|
, m_passwordGenerator(new PasswordGenerator())
|
|
|
|
, m_dicewareGenerator(new PassphraseGenerator())
|
2013-03-10 17:23:10 -04:00
|
|
|
, m_ui(new Ui::PasswordGeneratorWidget())
|
|
|
|
{
|
|
|
|
m_ui->setupUi(this);
|
2013-03-12 17:42:06 -04:00
|
|
|
|
2020-10-05 20:41:00 -04:00
|
|
|
m_ui->buttonGenerate->setIcon(icons()->icon("refresh"));
|
2020-03-08 22:22:01 -04:00
|
|
|
m_ui->buttonGenerate->setToolTip(
|
|
|
|
tr("Regenerate password (%1)").arg(m_ui->buttonGenerate->shortcut().toString(QKeySequence::NativeText)));
|
2020-10-05 20:41:00 -04:00
|
|
|
m_ui->buttonCopy->setIcon(icons()->icon("clipboard-text"));
|
2021-11-04 23:02:33 -04:00
|
|
|
m_ui->buttonDeleteWordList->setIcon(icons()->icon("trash"));
|
|
|
|
m_ui->buttonAddWordList->setIcon(icons()->icon("document-new"));
|
2020-03-08 22:22:01 -04:00
|
|
|
m_ui->buttonClose->setShortcut(Qt::Key_Escape);
|
2014-01-12 17:33:36 -05:00
|
|
|
|
2021-04-18 22:37:12 -04:00
|
|
|
// Add two shortcuts to save the form CTRL+Enter and CTRL+S
|
|
|
|
auto shortcut = new QShortcut(Qt::CTRL + Qt::Key_Return, this);
|
|
|
|
connect(shortcut, &QShortcut::activated, this, [this] { applyPassword(); });
|
|
|
|
shortcut = new QShortcut(Qt::CTRL + Qt::Key_S, this);
|
|
|
|
connect(shortcut, &QShortcut::activated, this, [this] { applyPassword(); });
|
|
|
|
|
2017-06-04 15:06:27 -04:00
|
|
|
connect(m_ui->editNewPassword, SIGNAL(textChanged(QString)), SLOT(updateButtonsEnabled(QString)));
|
2016-11-23 21:59:24 -05:00
|
|
|
connect(m_ui->editNewPassword, SIGNAL(textChanged(QString)), SLOT(updatePasswordStrength(QString)));
|
2020-03-08 22:22:01 -04:00
|
|
|
connect(m_ui->buttonAdvancedMode, SIGNAL(toggled(bool)), SLOT(setAdvancedMode(bool)));
|
2018-06-10 22:37:09 -04:00
|
|
|
connect(m_ui->buttonAddHex, SIGNAL(clicked()), SLOT(excludeHexChars()));
|
2019-11-16 11:51:56 -05:00
|
|
|
connect(m_ui->editAdditionalChars, SIGNAL(textChanged(QString)), SLOT(updateGenerator()));
|
2018-06-10 22:37:09 -04:00
|
|
|
connect(m_ui->editExcludedChars, SIGNAL(textChanged(QString)), SLOT(updateGenerator()));
|
2016-11-23 21:59:24 -05:00
|
|
|
connect(m_ui->buttonApply, SIGNAL(clicked()), SLOT(applyPassword()));
|
2017-05-28 13:47:33 -04:00
|
|
|
connect(m_ui->buttonCopy, SIGNAL(clicked()), SLOT(copyPassword()));
|
2017-03-04 09:10:50 -05:00
|
|
|
connect(m_ui->buttonGenerate, SIGNAL(clicked()), SLOT(regeneratePassword()));
|
2021-11-04 23:02:33 -04:00
|
|
|
connect(m_ui->buttonDeleteWordList, SIGNAL(clicked()), SLOT(deleteWordList()));
|
|
|
|
connect(m_ui->buttonAddWordList, SIGNAL(clicked()), SLOT(addWordList()));
|
2020-06-04 08:11:12 -04:00
|
|
|
connect(m_ui->buttonClose, SIGNAL(clicked()), SIGNAL(closed()));
|
2013-03-12 17:42:06 -04:00
|
|
|
|
2020-03-08 22:22:01 -04:00
|
|
|
connect(m_ui->sliderLength, SIGNAL(valueChanged(int)), SLOT(passwordLengthChanged(int)));
|
|
|
|
connect(m_ui->spinBoxLength, SIGNAL(valueChanged(int)), SLOT(passwordLengthChanged(int)));
|
2014-01-12 17:33:36 -05:00
|
|
|
|
2020-03-08 22:22:01 -04:00
|
|
|
connect(m_ui->sliderWordCount, SIGNAL(valueChanged(int)), SLOT(passphraseLengthChanged(int)));
|
|
|
|
connect(m_ui->spinBoxWordCount, SIGNAL(valueChanged(int)), SLOT(passphraseLengthChanged(int)));
|
2017-03-04 09:10:50 -05:00
|
|
|
|
2017-03-16 20:43:50 -04:00
|
|
|
connect(m_ui->editWordSeparator, SIGNAL(textChanged(QString)), SLOT(updateGenerator()));
|
2017-03-04 09:10:50 -05:00
|
|
|
connect(m_ui->comboBoxWordList, SIGNAL(currentIndexChanged(int)), SLOT(updateGenerator()));
|
2014-01-12 17:33:36 -05:00
|
|
|
connect(m_ui->optionButtons, SIGNAL(buttonClicked(int)), SLOT(updateGenerator()));
|
2017-03-04 09:10:50 -05:00
|
|
|
connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(updateGenerator()));
|
2019-05-24 18:23:19 -04:00
|
|
|
connect(m_ui->wordCaseComboBox, SIGNAL(currentIndexChanged(int)), SLOT(updateGenerator()));
|
2014-01-12 17:33:36 -05:00
|
|
|
|
2017-01-27 11:44:40 -05:00
|
|
|
// set font size of password quality and entropy labels dynamically to 80% of
|
|
|
|
// the default font size, but make it no smaller than 8pt
|
2016-11-23 21:59:24 -05:00
|
|
|
QFont defaultFont;
|
2017-01-27 11:44:40 -05:00
|
|
|
int smallerSize = static_cast<int>(defaultFont.pointSize() * 0.8f);
|
|
|
|
if (smallerSize >= 8) {
|
|
|
|
defaultFont.setPointSize(smallerSize);
|
|
|
|
m_ui->entropyLabel->setFont(defaultFont);
|
|
|
|
m_ui->strengthLabel->setFont(defaultFont);
|
|
|
|
}
|
2017-03-04 09:10:50 -05:00
|
|
|
|
2017-03-16 20:43:50 -04:00
|
|
|
// set default separator to Space
|
2018-02-05 06:31:13 -05:00
|
|
|
m_ui->editWordSeparator->setText(PassphraseGenerator::DefaultSeparator);
|
2017-03-04 09:10:50 -05:00
|
|
|
|
2019-05-24 18:23:19 -04:00
|
|
|
// add passphrase generator case options
|
|
|
|
m_ui->wordCaseComboBox->addItem(tr("lower case"), PassphraseGenerator::LOWERCASE);
|
|
|
|
m_ui->wordCaseComboBox->addItem(tr("UPPER CASE"), PassphraseGenerator::UPPERCASE);
|
|
|
|
m_ui->wordCaseComboBox->addItem(tr("Title Case"), PassphraseGenerator::TITLECASE);
|
|
|
|
|
2021-11-04 23:02:33 -04:00
|
|
|
// load system-wide wordlists
|
2020-03-08 20:27:16 -04:00
|
|
|
QDir path(resources()->wordlistPath(""));
|
2021-11-04 23:02:33 -04:00
|
|
|
for (const auto& fileName : path.entryList(QDir::Files)) {
|
|
|
|
m_ui->comboBoxWordList->addItem(tr("(SYSTEM)") + " " + fileName, fileName);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_firstCustomWordlistIndex = m_ui->comboBoxWordList->count();
|
|
|
|
|
|
|
|
// load user-provided wordlists
|
|
|
|
path = QDir(resources()->userWordlistPath(""));
|
|
|
|
for (const auto& fileName : path.entryList(QDir::Files)) {
|
|
|
|
m_ui->comboBoxWordList->addItem(fileName, path.absolutePath() + QDir::separator() + fileName);
|
2017-03-16 19:44:51 -04:00
|
|
|
}
|
2017-12-12 03:15:23 -05:00
|
|
|
|
2013-06-28 22:29:03 -04:00
|
|
|
loadSettings();
|
2013-03-10 17:23:10 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
PasswordGeneratorWidget::~PasswordGeneratorWidget()
|
|
|
|
{
|
2013-03-12 17:42:06 -04:00
|
|
|
}
|
|
|
|
|
2021-10-17 02:53:25 -04:00
|
|
|
void PasswordGeneratorWidget::closeEvent(QCloseEvent* event)
|
|
|
|
{
|
|
|
|
// Emits closed signal when clicking X from title bar
|
|
|
|
emit closed();
|
|
|
|
event->accept();
|
|
|
|
}
|
|
|
|
|
2020-03-18 22:54:49 -04:00
|
|
|
PasswordGeneratorWidget* PasswordGeneratorWidget::popupGenerator(QWidget* parent)
|
|
|
|
{
|
2020-03-22 19:40:19 -04:00
|
|
|
auto pwGenerator = new PasswordGeneratorWidget(parent);
|
|
|
|
pwGenerator->setWindowModality(Qt::ApplicationModal);
|
|
|
|
pwGenerator->setWindowFlags(Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
|
|
|
|
pwGenerator->setStandaloneMode(false);
|
|
|
|
|
2020-06-04 08:11:12 -04:00
|
|
|
connect(pwGenerator, SIGNAL(closed()), pwGenerator, SLOT(deleteLater()));
|
2020-03-22 19:40:19 -04:00
|
|
|
|
|
|
|
pwGenerator->show();
|
|
|
|
pwGenerator->raise();
|
|
|
|
pwGenerator->activateWindow();
|
|
|
|
pwGenerator->adjustSize();
|
|
|
|
|
|
|
|
return pwGenerator;
|
|
|
|
}
|
|
|
|
|
2013-06-28 22:29:03 -04:00
|
|
|
void PasswordGeneratorWidget::loadSettings()
|
|
|
|
{
|
2017-03-04 09:10:50 -05:00
|
|
|
// Password config
|
2020-04-25 19:31:38 -04:00
|
|
|
m_ui->checkBoxLower->setChecked(config()->get(Config::PasswordGenerator_LowerCase).toBool());
|
|
|
|
m_ui->checkBoxUpper->setChecked(config()->get(Config::PasswordGenerator_UpperCase).toBool());
|
|
|
|
m_ui->checkBoxNumbers->setChecked(config()->get(Config::PasswordGenerator_Numbers).toBool());
|
|
|
|
m_ui->editAdditionalChars->setText(config()->get(Config::PasswordGenerator_AdditionalChars).toString());
|
|
|
|
m_ui->editExcludedChars->setText(config()->get(Config::PasswordGenerator_ExcludedChars).toString());
|
|
|
|
|
2020-07-19 09:30:00 -04:00
|
|
|
bool advanced = config()->get(Config::PasswordGenerator_AdvancedMode).toBool();
|
|
|
|
if (advanced) {
|
|
|
|
m_ui->checkBoxSpecialChars->setChecked(config()->get(Config::PasswordGenerator_Logograms).toBool());
|
|
|
|
} else {
|
|
|
|
m_ui->checkBoxSpecialChars->setChecked(config()->get(Config::PasswordGenerator_SpecialChars).toBool());
|
|
|
|
}
|
2020-03-08 22:22:01 -04:00
|
|
|
|
2020-04-25 19:31:38 -04:00
|
|
|
m_ui->checkBoxBraces->setChecked(config()->get(Config::PasswordGenerator_Braces).toBool());
|
|
|
|
m_ui->checkBoxQuotes->setChecked(config()->get(Config::PasswordGenerator_Quotes).toBool());
|
|
|
|
m_ui->checkBoxPunctuation->setChecked(config()->get(Config::PasswordGenerator_Punctuation).toBool());
|
|
|
|
m_ui->checkBoxDashes->setChecked(config()->get(Config::PasswordGenerator_Dashes).toBool());
|
|
|
|
m_ui->checkBoxMath->setChecked(config()->get(Config::PasswordGenerator_Math).toBool());
|
2020-07-19 09:30:00 -04:00
|
|
|
|
2020-04-25 19:31:38 -04:00
|
|
|
m_ui->checkBoxExtASCII->setChecked(config()->get(Config::PasswordGenerator_EASCII).toBool());
|
|
|
|
m_ui->checkBoxExcludeAlike->setChecked(config()->get(Config::PasswordGenerator_ExcludeAlike).toBool());
|
|
|
|
m_ui->checkBoxEnsureEvery->setChecked(config()->get(Config::PasswordGenerator_EnsureEvery).toBool());
|
|
|
|
m_ui->spinBoxLength->setValue(config()->get(Config::PasswordGenerator_Length).toInt());
|
2017-03-04 09:10:50 -05:00
|
|
|
|
|
|
|
// Diceware config
|
2020-04-25 19:31:38 -04:00
|
|
|
m_ui->spinBoxWordCount->setValue(config()->get(Config::PasswordGenerator_WordCount).toInt());
|
|
|
|
m_ui->editWordSeparator->setText(config()->get(Config::PasswordGenerator_WordSeparator).toString());
|
2021-11-04 23:02:33 -04:00
|
|
|
int i = m_ui->comboBoxWordList->findData(config()->get(Config::PasswordGenerator_WordList).toString());
|
|
|
|
if (i > -1) {
|
|
|
|
m_ui->comboBoxWordList->setCurrentIndex(i);
|
|
|
|
}
|
2020-04-25 19:31:38 -04:00
|
|
|
m_ui->wordCaseComboBox->setCurrentIndex(config()->get(Config::PasswordGenerator_WordCase).toInt());
|
2017-03-04 09:10:50 -05:00
|
|
|
|
|
|
|
// Password or diceware?
|
2020-04-25 19:31:38 -04:00
|
|
|
m_ui->tabWidget->setCurrentIndex(config()->get(Config::PasswordGenerator_Type).toInt());
|
2020-07-19 09:30:00 -04:00
|
|
|
|
|
|
|
// Set advanced mode
|
|
|
|
m_ui->buttonAdvancedMode->setChecked(advanced);
|
|
|
|
setAdvancedMode(advanced);
|
2020-08-25 18:30:52 -04:00
|
|
|
updateGenerator();
|
2013-06-28 22:29:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void PasswordGeneratorWidget::saveSettings()
|
2013-03-12 17:42:06 -04:00
|
|
|
{
|
2017-03-04 09:10:50 -05:00
|
|
|
// Password config
|
2020-07-19 09:30:00 -04:00
|
|
|
config()->set(Config::PasswordGenerator_LowerCase, m_ui->checkBoxLower->isChecked());
|
|
|
|
config()->set(Config::PasswordGenerator_UpperCase, m_ui->checkBoxUpper->isChecked());
|
|
|
|
config()->set(Config::PasswordGenerator_Numbers, m_ui->checkBoxNumbers->isChecked());
|
|
|
|
config()->set(Config::PasswordGenerator_EASCII, m_ui->checkBoxExtASCII->isChecked());
|
|
|
|
|
|
|
|
config()->set(Config::PasswordGenerator_AdvancedMode, m_ui->buttonAdvancedMode->isChecked());
|
|
|
|
if (m_ui->buttonAdvancedMode->isChecked()) {
|
|
|
|
config()->set(Config::PasswordGenerator_Logograms, m_ui->checkBoxSpecialChars->isChecked());
|
2020-10-24 07:44:05 -04:00
|
|
|
} else {
|
|
|
|
config()->set(Config::PasswordGenerator_SpecialChars, m_ui->checkBoxSpecialChars->isChecked());
|
2018-06-10 22:37:09 -04:00
|
|
|
}
|
2020-04-25 19:31:38 -04:00
|
|
|
config()->set(Config::PasswordGenerator_Braces, m_ui->checkBoxBraces->isChecked());
|
|
|
|
config()->set(Config::PasswordGenerator_Punctuation, m_ui->checkBoxPunctuation->isChecked());
|
|
|
|
config()->set(Config::PasswordGenerator_Quotes, m_ui->checkBoxQuotes->isChecked());
|
|
|
|
config()->set(Config::PasswordGenerator_Dashes, m_ui->checkBoxDashes->isChecked());
|
|
|
|
config()->set(Config::PasswordGenerator_Math, m_ui->checkBoxMath->isChecked());
|
2020-07-19 09:30:00 -04:00
|
|
|
|
2020-06-04 08:11:12 -04:00
|
|
|
config()->set(Config::PasswordGenerator_AdditionalChars, m_ui->editAdditionalChars->text());
|
2020-04-25 19:31:38 -04:00
|
|
|
config()->set(Config::PasswordGenerator_ExcludedChars, m_ui->editExcludedChars->text());
|
|
|
|
config()->set(Config::PasswordGenerator_ExcludeAlike, m_ui->checkBoxExcludeAlike->isChecked());
|
|
|
|
config()->set(Config::PasswordGenerator_EnsureEvery, m_ui->checkBoxEnsureEvery->isChecked());
|
|
|
|
config()->set(Config::PasswordGenerator_Length, m_ui->spinBoxLength->value());
|
2017-03-04 09:10:50 -05:00
|
|
|
|
|
|
|
// Diceware config
|
2020-04-25 19:31:38 -04:00
|
|
|
config()->set(Config::PasswordGenerator_WordCount, m_ui->spinBoxWordCount->value());
|
|
|
|
config()->set(Config::PasswordGenerator_WordSeparator, m_ui->editWordSeparator->text());
|
2021-11-04 23:02:33 -04:00
|
|
|
config()->set(Config::PasswordGenerator_WordList, m_ui->comboBoxWordList->currentData());
|
2020-04-25 19:31:38 -04:00
|
|
|
config()->set(Config::PasswordGenerator_WordCase, m_ui->wordCaseComboBox->currentIndex());
|
2017-03-04 09:10:50 -05:00
|
|
|
|
|
|
|
// Password or diceware?
|
2020-04-25 19:31:38 -04:00
|
|
|
config()->set(Config::PasswordGenerator_Type, m_ui->tabWidget->currentIndex());
|
2013-06-28 22:29:03 -04:00
|
|
|
}
|
2013-03-12 17:42:06 -04:00
|
|
|
|
2020-02-25 18:02:46 -05:00
|
|
|
void PasswordGeneratorWidget::setPasswordLength(int length)
|
2013-06-28 22:29:03 -04:00
|
|
|
{
|
2018-09-25 20:44:19 -04:00
|
|
|
if (length > 0) {
|
|
|
|
m_ui->spinBoxLength->setValue(length);
|
|
|
|
} else {
|
2020-04-25 19:31:38 -04:00
|
|
|
m_ui->spinBoxLength->setValue(config()->get(Config::PasswordGenerator_Length).toInt());
|
2018-09-25 20:44:19 -04:00
|
|
|
}
|
2013-03-12 17:42:06 -04:00
|
|
|
}
|
|
|
|
|
2016-11-23 21:59:24 -05:00
|
|
|
void PasswordGeneratorWidget::setStandaloneMode(bool standalone)
|
|
|
|
{
|
2017-06-04 15:06:27 -04:00
|
|
|
m_standalone = standalone;
|
2016-11-23 21:59:24 -05:00
|
|
|
if (standalone) {
|
2020-03-08 22:22:01 -04:00
|
|
|
m_ui->buttonApply->setVisible(false);
|
2018-05-13 17:21:43 -04:00
|
|
|
setPasswordVisible(true);
|
2016-11-23 21:59:24 -05:00
|
|
|
} else {
|
2020-03-08 22:22:01 -04:00
|
|
|
m_ui->buttonApply->setVisible(true);
|
2016-11-23 21:59:24 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-17 22:16:45 -05:00
|
|
|
QString PasswordGeneratorWidget::getGeneratedPassword()
|
|
|
|
{
|
|
|
|
return m_ui->editNewPassword->text();
|
|
|
|
}
|
|
|
|
|
2016-08-06 05:29:47 -04:00
|
|
|
void PasswordGeneratorWidget::regeneratePassword()
|
2017-12-12 03:15:23 -05:00
|
|
|
{
|
2017-03-04 09:10:50 -05:00
|
|
|
if (m_ui->tabWidget->currentIndex() == Password) {
|
|
|
|
if (m_passwordGenerator->isValid()) {
|
|
|
|
QString password = m_passwordGenerator->generatePassword();
|
|
|
|
m_ui->editNewPassword->setText(password);
|
|
|
|
updatePasswordStrength(password);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (m_dicewareGenerator->isValid()) {
|
|
|
|
QString password = m_dicewareGenerator->generatePassphrase();
|
|
|
|
m_ui->editNewPassword->setText(password);
|
|
|
|
updatePasswordStrength(password);
|
|
|
|
}
|
2016-08-06 05:29:47 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-04 15:06:27 -04:00
|
|
|
void PasswordGeneratorWidget::updateButtonsEnabled(const QString& password)
|
2013-03-12 17:42:06 -04:00
|
|
|
{
|
2017-06-04 15:06:27 -04:00
|
|
|
if (!m_standalone) {
|
|
|
|
m_ui->buttonApply->setEnabled(!password.isEmpty());
|
|
|
|
}
|
|
|
|
m_ui->buttonCopy->setEnabled(!password.isEmpty());
|
2013-03-12 17:42:06 -04:00
|
|
|
}
|
|
|
|
|
2016-11-23 21:59:24 -05:00
|
|
|
void PasswordGeneratorWidget::updatePasswordStrength(const QString& password)
|
|
|
|
{
|
2020-02-01 08:42:34 -05:00
|
|
|
PasswordHealth health(password);
|
|
|
|
if (m_ui->tabWidget->currentIndex() == Diceware) {
|
|
|
|
// Diceware estimates entropy differently
|
|
|
|
health = PasswordHealth(m_dicewareGenerator->estimateEntropy());
|
2020-09-21 21:32:49 -04:00
|
|
|
|
|
|
|
m_ui->charactersInPassphraseLabel->setText(QString::number(password.length()));
|
2017-03-04 09:10:50 -05:00
|
|
|
}
|
|
|
|
|
2020-02-01 08:42:34 -05:00
|
|
|
m_ui->entropyLabel->setText(tr("Entropy: %1 bit").arg(QString::number(health.entropy(), 'f', 2)));
|
2016-11-23 21:59:24 -05:00
|
|
|
|
2020-02-01 08:42:34 -05:00
|
|
|
m_ui->entropyProgressBar->setValue(std::min(int(health.entropy()), m_ui->entropyProgressBar->maximum()));
|
2016-11-23 21:59:24 -05:00
|
|
|
|
2020-02-01 08:42:34 -05:00
|
|
|
colorStrengthIndicator(health);
|
2016-11-23 21:59:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void PasswordGeneratorWidget::applyPassword()
|
2013-03-12 17:42:06 -04:00
|
|
|
{
|
2016-11-23 21:59:24 -05:00
|
|
|
saveSettings();
|
2022-01-30 10:59:29 -05:00
|
|
|
m_passwordGenerated = true;
|
2017-03-10 09:58:42 -05:00
|
|
|
emit appliedPassword(m_ui->editNewPassword->text());
|
2020-06-04 08:11:12 -04:00
|
|
|
emit closed();
|
2014-01-12 17:33:36 -05:00
|
|
|
}
|
2013-03-12 17:42:06 -04:00
|
|
|
|
2017-05-28 13:47:33 -04:00
|
|
|
void PasswordGeneratorWidget::copyPassword()
|
|
|
|
{
|
|
|
|
clipboard()->setText(m_ui->editNewPassword->text());
|
|
|
|
}
|
|
|
|
|
2020-03-08 22:22:01 -04:00
|
|
|
void PasswordGeneratorWidget::passwordLengthChanged(int length)
|
2014-01-12 17:33:36 -05:00
|
|
|
{
|
2020-03-08 22:22:01 -04:00
|
|
|
m_ui->spinBoxLength->blockSignals(true);
|
|
|
|
m_ui->sliderLength->blockSignals(true);
|
2013-03-12 17:42:06 -04:00
|
|
|
|
2020-03-08 22:22:01 -04:00
|
|
|
m_ui->spinBoxLength->setValue(length);
|
|
|
|
m_ui->sliderLength->setValue(length);
|
2014-01-12 17:33:36 -05:00
|
|
|
|
2020-03-08 22:22:01 -04:00
|
|
|
m_ui->spinBoxLength->blockSignals(false);
|
|
|
|
m_ui->sliderLength->blockSignals(false);
|
2014-01-12 17:33:36 -05:00
|
|
|
|
|
|
|
updateGenerator();
|
2013-03-12 17:42:06 -04:00
|
|
|
}
|
|
|
|
|
2020-03-08 22:22:01 -04:00
|
|
|
void PasswordGeneratorWidget::passphraseLengthChanged(int length)
|
2017-03-04 09:10:50 -05:00
|
|
|
{
|
2020-03-08 22:22:01 -04:00
|
|
|
m_ui->spinBoxWordCount->blockSignals(true);
|
|
|
|
m_ui->sliderWordCount->blockSignals(true);
|
2017-03-04 09:10:50 -05:00
|
|
|
|
2020-03-08 22:22:01 -04:00
|
|
|
m_ui->spinBoxWordCount->setValue(length);
|
|
|
|
m_ui->sliderWordCount->setValue(length);
|
2017-03-04 09:10:50 -05:00
|
|
|
|
2020-03-08 22:22:01 -04:00
|
|
|
m_ui->spinBoxWordCount->blockSignals(false);
|
|
|
|
m_ui->sliderWordCount->blockSignals(false);
|
2017-03-04 09:10:50 -05:00
|
|
|
|
|
|
|
updateGenerator();
|
|
|
|
}
|
|
|
|
|
2018-05-13 17:21:43 -04:00
|
|
|
void PasswordGeneratorWidget::setPasswordVisible(bool visible)
|
2016-11-23 21:59:24 -05:00
|
|
|
{
|
2018-05-13 17:21:43 -04:00
|
|
|
m_ui->editNewPassword->setShowPassword(visible);
|
2016-11-23 21:59:24 -05:00
|
|
|
}
|
|
|
|
|
2018-05-13 17:21:43 -04:00
|
|
|
bool PasswordGeneratorWidget::isPasswordVisible() const
|
|
|
|
{
|
2020-03-08 22:22:01 -04:00
|
|
|
return m_ui->editNewPassword->isPasswordVisible();
|
2018-05-13 17:21:43 -04:00
|
|
|
}
|
|
|
|
|
2022-01-30 10:59:29 -05:00
|
|
|
bool PasswordGeneratorWidget::isPasswordGenerated() const
|
|
|
|
{
|
|
|
|
return m_passwordGenerated;
|
|
|
|
}
|
|
|
|
|
2021-11-04 23:02:33 -04:00
|
|
|
void PasswordGeneratorWidget::deleteWordList()
|
|
|
|
{
|
|
|
|
if (m_ui->comboBoxWordList->currentIndex() < m_firstCustomWordlistIndex) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QFile file(m_ui->comboBoxWordList->currentData().toString());
|
|
|
|
if (!file.exists()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto result = MessageBox::question(this,
|
|
|
|
tr("Confirm Delete Wordlist"),
|
|
|
|
tr("Do you really want to delete the wordlist \"%1\"?").arg(file.fileName()),
|
|
|
|
MessageBox::Delete | MessageBox::Cancel,
|
|
|
|
MessageBox::Cancel);
|
|
|
|
if (result != MessageBox::Delete) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!file.remove()) {
|
|
|
|
MessageBox::critical(this, tr("Failed to delete wordlist"), file.errorString());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_ui->comboBoxWordList->removeItem(m_ui->comboBoxWordList->currentIndex());
|
|
|
|
updateGenerator();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PasswordGeneratorWidget::addWordList()
|
|
|
|
{
|
|
|
|
auto filter = QString("%1 (*.txt *.asc *.wordlist);;%2 (*)").arg(tr("Wordlists"), tr("All files"));
|
|
|
|
auto filePath = fileDialog()->getOpenFileName(this, tr("Select Custom Wordlist"), "", filter);
|
|
|
|
if (filePath.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// create directory for user-specified wordlists, if necessary
|
|
|
|
QDir destDir(resources()->userWordlistPath(""));
|
|
|
|
destDir.mkpath(".");
|
|
|
|
|
|
|
|
// check if destination wordlist already exists
|
|
|
|
QString fileName = QFileInfo(filePath).fileName();
|
|
|
|
QString destPath = destDir.absolutePath() + QDir::separator() + fileName;
|
|
|
|
QFile dest(destPath);
|
|
|
|
if (dest.exists()) {
|
|
|
|
auto response = MessageBox::warning(this,
|
|
|
|
tr("Overwrite Wordlist?"),
|
|
|
|
tr("Wordlist \"%1\" already exists as a custom wordlist.\n"
|
|
|
|
"Do you want to overwrite it?")
|
|
|
|
.arg(fileName),
|
|
|
|
MessageBox::Overwrite | MessageBox::Cancel,
|
|
|
|
MessageBox::Cancel);
|
|
|
|
if (response != MessageBox::Overwrite) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!dest.remove()) {
|
|
|
|
MessageBox::critical(this, tr("Failed to delete wordlist"), dest.errorString());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy wordlist to destination path and add corresponding item to the combo box
|
|
|
|
QFile file(filePath);
|
|
|
|
if (!file.copy(destPath)) {
|
|
|
|
MessageBox::critical(this, tr("Failed to add wordlist"), file.errorString());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto index = m_ui->comboBoxWordList->findData(destPath);
|
|
|
|
if (index == -1) {
|
|
|
|
m_ui->comboBoxWordList->addItem(fileName, destPath);
|
|
|
|
index = m_ui->comboBoxWordList->count() - 1;
|
|
|
|
}
|
|
|
|
m_ui->comboBoxWordList->setCurrentIndex(index);
|
|
|
|
|
|
|
|
// update the password generator
|
|
|
|
updateGenerator();
|
|
|
|
}
|
|
|
|
|
2020-07-19 09:30:00 -04:00
|
|
|
void PasswordGeneratorWidget::setAdvancedMode(bool advanced)
|
2018-06-10 22:37:09 -04:00
|
|
|
{
|
2020-07-19 09:30:00 -04:00
|
|
|
saveSettings();
|
|
|
|
|
|
|
|
if (advanced) {
|
|
|
|
m_ui->checkBoxSpecialChars->setText("# $ % && @ ^ ` ~");
|
|
|
|
m_ui->checkBoxSpecialChars->setToolTip(tr("Logograms"));
|
|
|
|
m_ui->checkBoxSpecialChars->setChecked(config()->get(Config::PasswordGenerator_Logograms).toBool());
|
2020-03-08 22:22:01 -04:00
|
|
|
} else {
|
2020-07-19 09:30:00 -04:00
|
|
|
m_ui->checkBoxSpecialChars->setText("/ * + && …");
|
|
|
|
m_ui->checkBoxSpecialChars->setToolTip(tr("Special Characters"));
|
|
|
|
m_ui->checkBoxSpecialChars->setChecked(config()->get(Config::PasswordGenerator_SpecialChars).toBool());
|
2020-03-08 22:22:01 -04:00
|
|
|
}
|
2020-03-22 19:40:19 -04:00
|
|
|
|
2020-07-19 09:30:00 -04:00
|
|
|
m_ui->advancedContainer->setVisible(advanced);
|
|
|
|
m_ui->checkBoxBraces->setVisible(advanced);
|
|
|
|
m_ui->checkBoxPunctuation->setVisible(advanced);
|
|
|
|
m_ui->checkBoxQuotes->setVisible(advanced);
|
|
|
|
m_ui->checkBoxMath->setVisible(advanced);
|
|
|
|
m_ui->checkBoxDashes->setVisible(advanced);
|
|
|
|
|
|
|
|
if (!m_standalone) {
|
|
|
|
QTimer::singleShot(50, this, [this] { adjustSize(); });
|
|
|
|
}
|
2018-06-10 22:37:09 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void PasswordGeneratorWidget::excludeHexChars()
|
|
|
|
{
|
2021-06-07 04:41:14 -04:00
|
|
|
m_ui->editExcludedChars->setText("GHIJKLMNOPQRSTUVWXYZ");
|
2020-07-19 09:30:00 -04:00
|
|
|
m_ui->checkBoxNumbers->setChecked(true);
|
|
|
|
m_ui->checkBoxUpper->setChecked(true);
|
|
|
|
|
|
|
|
m_ui->checkBoxLower->setChecked(false);
|
|
|
|
m_ui->checkBoxSpecialChars->setChecked(false);
|
|
|
|
m_ui->checkBoxExtASCII->setChecked(false);
|
|
|
|
m_ui->checkBoxPunctuation->setChecked(false);
|
|
|
|
m_ui->checkBoxQuotes->setChecked(false);
|
|
|
|
m_ui->checkBoxDashes->setChecked(false);
|
|
|
|
m_ui->checkBoxMath->setChecked(false);
|
|
|
|
m_ui->checkBoxBraces->setChecked(false);
|
|
|
|
|
|
|
|
updateGenerator();
|
2018-06-10 22:37:09 -04:00
|
|
|
}
|
|
|
|
|
2020-02-01 08:42:34 -05:00
|
|
|
void PasswordGeneratorWidget::colorStrengthIndicator(const PasswordHealth& health)
|
2016-11-23 21:59:24 -05:00
|
|
|
{
|
|
|
|
// Take the existing stylesheet and convert the text and background color to arguments
|
|
|
|
QString style = m_ui->entropyProgressBar->styleSheet();
|
|
|
|
QRegularExpression re("(QProgressBar::chunk\\s*\\{.*?background-color:)[^;]+;",
|
2018-03-31 16:01:30 -04:00
|
|
|
QRegularExpression::CaseInsensitiveOption | QRegularExpression::DotMatchesEverythingOption);
|
2016-11-23 21:59:24 -05:00
|
|
|
style.replace(re, "\\1 %1;");
|
|
|
|
|
2020-04-11 11:01:50 -04:00
|
|
|
StateColorPalette statePalette;
|
2020-02-01 08:42:34 -05:00
|
|
|
switch (health.quality()) {
|
|
|
|
case PasswordHealth::Quality::Bad:
|
|
|
|
case PasswordHealth::Quality::Poor:
|
2020-04-11 11:01:50 -04:00
|
|
|
m_ui->entropyProgressBar->setStyleSheet(
|
|
|
|
style.arg(statePalette.color(StateColorPalette::HealthCritical).name()));
|
2018-01-20 07:47:30 -05:00
|
|
|
m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Poor", "Password quality")));
|
2020-02-01 08:42:34 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PasswordHealth::Quality::Weak:
|
2020-04-11 11:01:50 -04:00
|
|
|
m_ui->entropyProgressBar->setStyleSheet(style.arg(statePalette.color(StateColorPalette::HealthBad).name()));
|
2018-01-20 07:47:30 -05:00
|
|
|
m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Weak", "Password quality")));
|
2020-02-01 08:42:34 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PasswordHealth::Quality::Good:
|
2020-04-11 11:01:50 -04:00
|
|
|
m_ui->entropyProgressBar->setStyleSheet(style.arg(statePalette.color(StateColorPalette::HealthOk).name()));
|
2018-01-20 07:47:30 -05:00
|
|
|
m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Good", "Password quality")));
|
2020-02-01 08:42:34 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PasswordHealth::Quality::Excellent:
|
2020-04-11 11:01:50 -04:00
|
|
|
m_ui->entropyProgressBar->setStyleSheet(
|
|
|
|
style.arg(statePalette.color(StateColorPalette::HealthExcellent).name()));
|
2018-01-20 07:47:30 -05:00
|
|
|
m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Excellent", "Password quality")));
|
2020-02-01 08:42:34 -05:00
|
|
|
break;
|
2016-11-23 21:59:24 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-12 17:42:06 -04:00
|
|
|
PasswordGenerator::CharClasses PasswordGeneratorWidget::charClasses()
|
|
|
|
{
|
|
|
|
PasswordGenerator::CharClasses classes;
|
|
|
|
|
2020-07-19 09:30:00 -04:00
|
|
|
if (m_ui->checkBoxLower->isChecked()) {
|
|
|
|
classes |= PasswordGenerator::LowerLetters;
|
|
|
|
}
|
2013-03-12 17:42:06 -04:00
|
|
|
|
2020-07-19 09:30:00 -04:00
|
|
|
if (m_ui->checkBoxUpper->isChecked()) {
|
|
|
|
classes |= PasswordGenerator::UpperLetters;
|
|
|
|
}
|
2013-03-12 17:42:06 -04:00
|
|
|
|
2020-07-19 09:30:00 -04:00
|
|
|
if (m_ui->checkBoxNumbers->isChecked()) {
|
|
|
|
classes |= PasswordGenerator::Numbers;
|
|
|
|
}
|
2018-06-10 22:37:09 -04:00
|
|
|
|
2020-07-19 09:30:00 -04:00
|
|
|
if (m_ui->checkBoxExtASCII->isChecked()) {
|
|
|
|
classes |= PasswordGenerator::EASCII;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_ui->buttonAdvancedMode->isChecked()) {
|
2018-06-10 22:37:09 -04:00
|
|
|
if (m_ui->checkBoxSpecialChars->isChecked()) {
|
|
|
|
classes |= PasswordGenerator::SpecialCharacters;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (m_ui->checkBoxBraces->isChecked()) {
|
|
|
|
classes |= PasswordGenerator::Braces;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_ui->checkBoxPunctuation->isChecked()) {
|
|
|
|
classes |= PasswordGenerator::Punctuation;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_ui->checkBoxQuotes->isChecked()) {
|
|
|
|
classes |= PasswordGenerator::Quotes;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_ui->checkBoxDashes->isChecked()) {
|
|
|
|
classes |= PasswordGenerator::Dashes;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_ui->checkBoxMath->isChecked()) {
|
|
|
|
classes |= PasswordGenerator::Math;
|
|
|
|
}
|
|
|
|
|
2020-07-19 09:30:00 -04:00
|
|
|
if (m_ui->checkBoxSpecialChars->isChecked()) {
|
2018-06-10 22:37:09 -04:00
|
|
|
classes |= PasswordGenerator::Logograms;
|
|
|
|
}
|
2017-04-28 15:36:43 -04:00
|
|
|
}
|
|
|
|
|
2013-03-12 17:42:06 -04:00
|
|
|
return classes;
|
|
|
|
}
|
|
|
|
|
|
|
|
PasswordGenerator::GeneratorFlags PasswordGeneratorWidget::generatorFlags()
|
|
|
|
{
|
|
|
|
PasswordGenerator::GeneratorFlags flags;
|
|
|
|
|
2020-03-08 22:22:01 -04:00
|
|
|
if (m_ui->buttonAdvancedMode->isChecked()) {
|
|
|
|
if (m_ui->checkBoxExcludeAlike->isChecked()) {
|
|
|
|
flags |= PasswordGenerator::ExcludeLookAlike;
|
|
|
|
}
|
2013-03-12 17:42:06 -04:00
|
|
|
|
2020-03-08 22:22:01 -04:00
|
|
|
if (m_ui->checkBoxEnsureEvery->isChecked()) {
|
|
|
|
flags |= PasswordGenerator::CharFromEveryGroup;
|
|
|
|
}
|
2013-03-12 17:42:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return flags;
|
2013-03-10 17:23:10 -04:00
|
|
|
}
|
2014-01-12 17:33:36 -05:00
|
|
|
|
|
|
|
void PasswordGeneratorWidget::updateGenerator()
|
|
|
|
{
|
2017-03-04 09:10:50 -05:00
|
|
|
if (m_ui->tabWidget->currentIndex() == Password) {
|
2020-03-08 22:22:01 -04:00
|
|
|
auto classes = charClasses();
|
|
|
|
auto flags = generatorFlags();
|
2017-03-04 09:10:50 -05:00
|
|
|
|
2021-12-07 23:40:09 -05:00
|
|
|
m_passwordGenerator->setLength(m_ui->spinBoxLength->value());
|
2020-03-08 22:22:01 -04:00
|
|
|
if (m_ui->buttonAdvancedMode->isChecked()) {
|
2021-12-07 23:40:09 -05:00
|
|
|
m_passwordGenerator->setCharClasses(classes);
|
|
|
|
m_passwordGenerator->setCustomCharacterSet(m_ui->editAdditionalChars->text());
|
|
|
|
m_passwordGenerator->setCustomCharacterSet(m_ui->editExcludedChars->text());
|
2020-03-08 22:22:01 -04:00
|
|
|
} else {
|
2021-12-07 23:40:09 -05:00
|
|
|
m_passwordGenerator->setCharClasses(classes);
|
2018-06-10 22:37:09 -04:00
|
|
|
}
|
2021-12-07 23:40:09 -05:00
|
|
|
m_passwordGenerator->setFlags(flags);
|
2017-03-04 09:10:50 -05:00
|
|
|
|
|
|
|
if (m_passwordGenerator->isValid()) {
|
|
|
|
m_ui->buttonGenerate->setEnabled(true);
|
|
|
|
} else {
|
|
|
|
m_ui->buttonGenerate->setEnabled(false);
|
2016-07-31 16:07:47 -04:00
|
|
|
}
|
2017-03-04 09:10:50 -05:00
|
|
|
} else {
|
2019-05-24 18:23:19 -04:00
|
|
|
m_dicewareGenerator->setWordCase(
|
|
|
|
static_cast<PassphraseGenerator::PassphraseWordCase>(m_ui->wordCaseComboBox->currentData().toInt()));
|
|
|
|
|
2017-03-04 16:28:41 -05:00
|
|
|
m_dicewareGenerator->setWordCount(m_ui->spinBoxWordCount->value());
|
2021-11-04 23:02:33 -04:00
|
|
|
auto path = m_ui->comboBoxWordList->currentData().toString();
|
|
|
|
if (m_ui->comboBoxWordList->currentIndex() < m_firstCustomWordlistIndex) {
|
|
|
|
path = resources()->wordlistPath(path);
|
|
|
|
m_ui->buttonDeleteWordList->setEnabled(false);
|
|
|
|
} else {
|
|
|
|
m_ui->buttonDeleteWordList->setEnabled(true);
|
2017-03-04 09:10:50 -05:00
|
|
|
}
|
2021-11-04 23:02:33 -04:00
|
|
|
m_dicewareGenerator->setWordList(path);
|
|
|
|
|
2017-03-21 19:04:36 -04:00
|
|
|
m_dicewareGenerator->setWordSeparator(m_ui->editWordSeparator->text());
|
2014-01-12 17:33:36 -05:00
|
|
|
|
2017-03-04 09:10:50 -05:00
|
|
|
if (m_dicewareGenerator->isValid()) {
|
|
|
|
m_ui->buttonGenerate->setEnabled(true);
|
|
|
|
} else {
|
|
|
|
m_ui->buttonGenerate->setEnabled(false);
|
|
|
|
}
|
2017-01-26 18:38:50 -05:00
|
|
|
}
|
|
|
|
|
2016-08-06 05:29:47 -04:00
|
|
|
regeneratePassword();
|
2014-01-12 17:33:36 -05:00
|
|
|
}
|