X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=blobdiff_plain;f=src%2Fqt%2Faskpassphrasedialog.cpp;h=6569989ac4a51ed9b8ad5d6410f9da4f259f85bf;hp=b52acf4545e3817b244ab602d13e2df124a71ab6;hb=8037df7fbad6c5886b2fb3e643233db8dd7a45ec;hpb=142e5056cd8a62df838e9a3afee0f718faffd72b diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index b52acf4..6569989 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -2,22 +2,32 @@ #include "ui_askpassphrasedialog.h" #include "guiconstants.h" +#include "dialogwindowflags.h" #include "walletmodel.h" #include #include +#include + +extern bool fWalletUnlockMintOnly; AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) : - QDialog(parent), + QDialog(parent, DIALOGWINDOWHINTS), ui(new Ui::AskPassphraseDialog), mode(mode), - model(0) + model(0), + fCapsLock(false) { ui->setupUi(this); ui->passEdit1->setMaxLength(MAX_PASSPHRASE_SIZE); ui->passEdit2->setMaxLength(MAX_PASSPHRASE_SIZE); ui->passEdit3->setMaxLength(MAX_PASSPHRASE_SIZE); + // Setup Caps Lock detection. + ui->passEdit1->installEventFilter(this); + ui->passEdit2->installEventFilter(this); + ui->passEdit3->installEventFilter(this); + switch(mode) { case Encrypt: // Ask passphrase x2 @@ -27,6 +37,7 @@ AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) : setWindowTitle(tr("Encrypt wallet")); break; case Unlock: // Ask passphrase + case UnlockMining: ui->warningLabel->setText(tr("This operation needs your wallet passphrase to unlock the wallet.")); ui->passLabel2->hide(); ui->passEdit2->hide(); @@ -56,10 +67,7 @@ AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) : AskPassphraseDialog::~AskPassphraseDialog() { - // Attempt to overwrite text so that they do not linger around in memory - ui->passEdit1->setText(QString(" ").repeated(ui->passEdit1->text().size())); - ui->passEdit2->setText(QString(" ").repeated(ui->passEdit2->text().size())); - ui->passEdit3->setText(QString(" ").repeated(ui->passEdit3->text().size())); + secureClearPassFields(); delete ui; } @@ -70,16 +78,19 @@ void AskPassphraseDialog::setModel(WalletModel *model) void AskPassphraseDialog::accept() { - std::string oldpass, newpass1, newpass2; + SecureString oldpass, newpass1, newpass2; if(!model) return; - // TODO: mlock memory / munlock on return so they will not be swapped out, really need "mlockedstring" wrapper class to do this safely oldpass.reserve(MAX_PASSPHRASE_SIZE); newpass1.reserve(MAX_PASSPHRASE_SIZE); newpass2.reserve(MAX_PASSPHRASE_SIZE); - oldpass.assign(ui->passEdit1->text().toStdString()); - newpass1.assign(ui->passEdit2->text().toStdString()); - newpass2.assign(ui->passEdit3->text().toStdString()); + // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string) + // Alternately, find a way to make this input mlock()'d to begin with. + oldpass.assign(ui->passEdit1->text().toStdString().c_str()); + newpass1.assign(ui->passEdit2->text().toStdString().c_str()); + newpass2.assign(ui->passEdit3->text().toStdString().c_str()); + + secureClearPassFields(); switch(mode) { @@ -90,7 +101,7 @@ void AskPassphraseDialog::accept() break; } QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm wallet encryption"), - tr("WARNING: If you encrypt your wallet and lose your passphrase, you will LOSE ALL OF YOUR BITCOINS!\nAre you sure you wish to encrypt your wallet?"), + tr("Warning: If you encrypt your wallet and lose your passphrase, you will LOSE ALL OF YOUR COINS!") + "

" + tr("Are you sure you wish to encrypt your wallet?"), QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Cancel); if(retval == QMessageBox::Yes) @@ -100,7 +111,16 @@ void AskPassphraseDialog::accept() if(model->setWalletEncrypted(true, newpass1)) { QMessageBox::warning(this, tr("Wallet encrypted"), - tr("Bitcoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.")); + "" + + tr("NovaCoin will close now to finish the encryption process. " + "Remember that encrypting your wallet cannot fully protect " + "your coins from being stolen by malware infecting your computer.") + + "

" + + tr("IMPORTANT: Any previous backups you have made of your wallet file " + "should be replaced with the newly generated, encrypted wallet file. " + "For security reasons, previous backups of the unencrypted wallet file " + "will become useless as soon as you start using the new, encrypted wallet.") + + "
"); QApplication::quit(); } else @@ -132,6 +152,18 @@ void AskPassphraseDialog::accept() QDialog::accept(); // Success } break; + case UnlockMining: + if(!model->setWalletLocked(false, oldpass)) + { + QMessageBox::critical(this, tr("Wallet unlock failed"), + tr("The passphrase entered for the wallet decryption was incorrect.")); + } + else + { + QDialog::accept(); // Success + fWalletUnlockMintOnly = true; + } + break; case Decrypt: if(!model->setWalletEncrypted(false, oldpass)) { @@ -140,7 +172,11 @@ void AskPassphraseDialog::accept() } else { - QDialog::accept(); // Success + QMessageBox::warning(this, tr("Wallet decrypted"), + "" + + tr("NovaCoin will close now to finish the decryption process. ") + + ""); + QApplication::quit(); } break; case ChangePass: @@ -149,7 +185,7 @@ void AskPassphraseDialog::accept() if(model->changePassphrase(oldpass, newpass1)) { QMessageBox::information(this, tr("Wallet encrypted"), - tr("Wallet passphrase was succesfully changed.")); + tr("Wallet passphrase was successfully changed.")); QDialog::accept(); // Success } else @@ -169,7 +205,7 @@ void AskPassphraseDialog::accept() void AskPassphraseDialog::textChanged() { - // Validate input, set Ok button to enabled when accepable + // Validate input, set Ok button to enabled when acceptable bool acceptable = false; switch(mode) { @@ -177,6 +213,7 @@ void AskPassphraseDialog::textChanged() acceptable = !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty(); break; case Unlock: // Old passphrase x1 + case UnlockMining: case Decrypt: acceptable = !ui->passEdit1->text().isEmpty(); break; @@ -186,3 +223,60 @@ void AskPassphraseDialog::textChanged() } ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(acceptable); } + +bool AskPassphraseDialog::event(QEvent *event) +{ + // Detect Caps Lock key press. + if (event->type() == QEvent::KeyPress) { + QKeyEvent *ke = static_cast(event); + if (ke->key() == Qt::Key_CapsLock) { + fCapsLock = !fCapsLock; + } + if (fCapsLock) { + ui->capsLabel->setText(tr("Warning: The Caps Lock key is on!")); + } else { + ui->capsLabel->clear(); + } + } + return QWidget::event(event); +} + +bool AskPassphraseDialog::eventFilter(QObject *object, QEvent *event) +{ + /* Detect Caps Lock. + * There is no good OS-independent way to check a key state in Qt, but we + * can detect Caps Lock by checking for the following condition: + * Shift key is down and the result is a lower case character, or + * Shift key is not down and the result is an upper case character. + */ + if (event->type() == QEvent::KeyPress) { + QKeyEvent *ke = static_cast(event); + QString str = ke->text(); + if (str.length() != 0) { + const QChar *psz = str.unicode(); + bool fShift = (ke->modifiers() & Qt::ShiftModifier) != 0; + if ((fShift && psz->isLower()) || (!fShift && psz->isUpper())) { + fCapsLock = true; + ui->capsLabel->setText(tr("Warning: The Caps Lock key is on!")); + } else if (psz->isLetter()) { + fCapsLock = false; + ui->capsLabel->clear(); + } + } + } + return QDialog::eventFilter(object, event); +} + +static void SecureClearQLineEdit(QLineEdit* edit) +{ + // Attempt to overwrite text so that they do not linger around in memory + edit->setText(QString(" ").repeated(edit->text().size())); + edit->clear(); +} + +void AskPassphraseDialog::secureClearPassFields() +{ + SecureClearQLineEdit(ui->passEdit1); + SecureClearQLineEdit(ui->passEdit2); + SecureClearQLineEdit(ui->passEdit3); +} \ No newline at end of file