Add robustness against null models
[novacoin.git] / src / qt / askpassphrasedialog.cpp
1 #include "askpassphrasedialog.h"
2 #include "ui_askpassphrasedialog.h"
3
4 #include "guiconstants.h"
5 #include "walletmodel.h"
6
7 #include <QMessageBox>
8 #include <QPushButton>
9
10 AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) :
11     QDialog(parent),
12     ui(new Ui::AskPassphraseDialog),
13     mode(mode),
14     model(0)
15 {
16     ui->setupUi(this);
17     ui->passEdit1->setMaxLength(MAX_PASSPHRASE_SIZE);
18     ui->passEdit2->setMaxLength(MAX_PASSPHRASE_SIZE);
19     ui->passEdit3->setMaxLength(MAX_PASSPHRASE_SIZE);
20
21     switch(mode)
22     {
23         case Encrypt: // Ask passphrase x2
24             ui->passLabel1->hide();
25             ui->passEdit1->hide();
26             ui->warningLabel->setText(tr("Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>."));
27             setWindowTitle(tr("Encrypt wallet"));
28             break;
29         case Unlock: // Ask passphrase
30             ui->warningLabel->setText(tr("This operation needs your wallet passphrase to unlock the wallet."));
31             ui->passLabel2->hide();
32             ui->passEdit2->hide();
33             ui->passLabel3->hide();
34             ui->passEdit3->hide();
35             setWindowTitle(tr("Unlock wallet"));
36             break;
37         case Decrypt:   // Ask passphrase
38             ui->warningLabel->setText(tr("This operation needs your wallet passphrase to decrypt the wallet."));
39             ui->passLabel2->hide();
40             ui->passEdit2->hide();
41             ui->passLabel3->hide();
42             ui->passEdit3->hide();
43             setWindowTitle(tr("Decrypt wallet"));
44             break;
45         case ChangePass: // Ask old passphrase + new passphrase x2
46             setWindowTitle(tr("Change passphrase"));
47             ui->warningLabel->setText(tr("Enter the old and new passphrase to the wallet."));
48             break;
49     }
50     resize(minimumSize()); // Get rid of extra space in dialog
51
52     textChanged();
53     connect(ui->passEdit1, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
54     connect(ui->passEdit2, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
55     connect(ui->passEdit3, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
56 }
57
58 AskPassphraseDialog::~AskPassphraseDialog()
59 {
60     // Attempt to overwrite text so that they do not linger around in memory
61     ui->passEdit1->setText(QString(" ").repeated(ui->passEdit1->text().size()));
62     ui->passEdit2->setText(QString(" ").repeated(ui->passEdit2->text().size()));
63     ui->passEdit3->setText(QString(" ").repeated(ui->passEdit3->text().size()));
64     delete ui;
65 }
66
67 void AskPassphraseDialog::setModel(WalletModel *model)
68 {
69     this->model = model;
70 }
71
72 void AskPassphraseDialog::accept()
73 {
74     std::string oldpass, newpass1, newpass2;
75     if(!model)
76         return;
77     // TODO: mlock memory / munlock on return so they will not be swapped out, really need "mlockedstring" wrapper class to do this safely
78     oldpass.reserve(MAX_PASSPHRASE_SIZE);
79     newpass1.reserve(MAX_PASSPHRASE_SIZE);
80     newpass2.reserve(MAX_PASSPHRASE_SIZE);
81     oldpass.assign(ui->passEdit1->text().toStdString());
82     newpass1.assign(ui->passEdit2->text().toStdString());
83     newpass2.assign(ui->passEdit3->text().toStdString());
84
85     switch(mode)
86     {
87     case Encrypt: {
88         if(newpass1.empty() || newpass2.empty())
89         {
90             // Cannot encrypt with empty passphrase
91             break;
92         }
93         QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm wallet encryption"),
94                  tr("WARNING: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>!\nAre you sure you wish to encrypt your wallet?"),
95                  QMessageBox::Yes|QMessageBox::Cancel,
96                  QMessageBox::Cancel);
97         if(retval == QMessageBox::Yes)
98         {
99             if(newpass1 == newpass2)
100             {
101                 if(model->setWalletEncrypted(true, newpass1))
102                 {
103                     QMessageBox::warning(this, tr("Wallet encrypted"),
104                                          tr("Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer."));
105                 }
106                 else
107                 {
108                     QMessageBox::critical(this, tr("Wallet encryption failed"),
109                                          tr("Wallet encryption failed due to an internal error. Your wallet was not encrypted."));
110                 }
111                 QDialog::accept(); // Success
112             }
113             else
114             {
115                 QMessageBox::critical(this, tr("Wallet encryption failed"),
116                                      tr("The supplied passphrases do not match."));
117             }
118         }
119         else
120         {
121             QDialog::reject(); // Cancelled
122         }
123         } break;
124     case Unlock:
125         if(!model->setWalletLocked(false, oldpass))
126         {
127             QMessageBox::critical(this, tr("Wallet unlock failed"),
128                                   tr("The passphrase entered for the wallet decryption was incorrect."));
129         }
130         else
131         {
132             QDialog::accept(); // Success
133         }
134         break;
135     case Decrypt:
136         if(!model->setWalletEncrypted(false, oldpass))
137         {
138             QMessageBox::critical(this, tr("Wallet decryption failed"),
139                                   tr("The passphrase entered for the wallet decryption was incorrect."));
140         }
141         else
142         {
143             QDialog::accept(); // Success
144         }
145         break;
146     case ChangePass:
147         if(newpass1 == newpass2)
148         {
149             if(model->changePassphrase(oldpass, newpass1))
150             {
151                 QMessageBox::information(this, tr("Wallet encrypted"),
152                                      tr("Wallet passphrase was succesfully changed."));
153                 QDialog::accept(); // Success
154             }
155             else
156             {
157                 QMessageBox::critical(this, tr("Wallet encryption failed"),
158                                      tr("The passphrase entered for the wallet decryption was incorrect."));
159             }
160         }
161         else
162         {
163             QMessageBox::critical(this, tr("Wallet encryption failed"),
164                                  tr("The supplied passphrases do not match."));
165         }
166         break;
167     }
168 }
169
170 void AskPassphraseDialog::textChanged()
171 {
172     // Validate input, set Ok button to enabled when accepable
173     bool acceptable = false;
174     switch(mode)
175     {
176     case Encrypt: // New passphrase x2
177         acceptable = !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty();
178         break;
179     case Unlock: // Old passphrase x1
180     case Decrypt:
181         acceptable = !ui->passEdit1->text().isEmpty();
182         break;
183     case ChangePass: // Old passphrase x1, new passphrase x2
184         acceptable = !ui->passEdit1->text().isEmpty() && !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty();
185         break;
186     }
187     ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(acceptable);
188 }