Wallet encryption part 2: ask passphrase when needed, add menu options
[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     // TODO: mlock memory / munlock on return so they will not be swapped out, really need "mlockedstring" wrapper class to do this safely
76     oldpass.reserve(MAX_PASSPHRASE_SIZE);
77     newpass1.reserve(MAX_PASSPHRASE_SIZE);
78     newpass2.reserve(MAX_PASSPHRASE_SIZE);
79     oldpass.assign(ui->passEdit1->text().toStdString());
80     newpass1.assign(ui->passEdit2->text().toStdString());
81     newpass2.assign(ui->passEdit3->text().toStdString());
82
83     switch(mode)
84     {
85     case Encrypt: {
86         if(newpass1.empty() || newpass2.empty())
87         {
88             // Cannot encrypt with empty passphrase
89             break;
90         }
91         QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm wallet encryption"),
92                  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?"),
93                  QMessageBox::Yes|QMessageBox::Cancel,
94                  QMessageBox::Cancel);
95         if(retval == QMessageBox::Yes)
96         {
97             if(newpass1 == newpass2)
98             {
99                 if(model->setWalletEncrypted(true, newpass1))
100                 {
101                     QMessageBox::warning(this, tr("Wallet encrypted"),
102                                          tr("Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer."));
103                 }
104                 else
105                 {
106                     QMessageBox::critical(this, tr("Wallet encryption failed"),
107                                          tr("Wallet encryption failed due to an internal error. Your wallet was not encrypted."));
108                 }
109                 QDialog::accept(); // Success
110             }
111             else
112             {
113                 QMessageBox::critical(this, tr("Wallet encryption failed"),
114                                      tr("The supplied passphrases do not match."));
115             }
116         }
117         else
118         {
119             QDialog::reject(); // Cancelled
120         }
121         } break;
122     case Unlock:
123         if(!model->setWalletLocked(false, oldpass))
124         {
125             QMessageBox::critical(this, tr("Wallet unlock failed"),
126                                   tr("The passphrase entered for the wallet decryption was incorrect."));
127         }
128         else
129         {
130             QDialog::accept(); // Success
131         }
132         break;
133     case Decrypt:
134         if(!model->setWalletEncrypted(false, oldpass))
135         {
136             QMessageBox::critical(this, tr("Wallet decryption failed"),
137                                   tr("The passphrase entered for the wallet decryption was incorrect."));
138         }
139         else
140         {
141             QDialog::accept(); // Success
142         }
143         break;
144     case ChangePass:
145         if(newpass1 == newpass2)
146         {
147             if(model->changePassphrase(oldpass, newpass1))
148             {
149                 QMessageBox::information(this, tr("Wallet encrypted"),
150                                      tr("Wallet passphrase was succesfully changed."));
151                 QDialog::accept(); // Success
152             }
153             else
154             {
155                 QMessageBox::critical(this, tr("Wallet encryption failed"),
156                                      tr("The passphrase entered for the wallet decryption was incorrect."));
157             }
158         }
159         else
160         {
161             QMessageBox::critical(this, tr("Wallet encryption failed"),
162                                  tr("The supplied passphrases do not match."));
163         }
164         break;
165     }
166 }
167
168 void AskPassphraseDialog::textChanged()
169 {
170     // Validate input, set Ok button to enabled when accepable
171     bool acceptable = false;
172     switch(mode)
173     {
174     case Encrypt: // New passphrase x2
175         acceptable = !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty();
176         break;
177     case Unlock: // Old passphrase x1
178     case Decrypt:
179         acceptable = !ui->passEdit1->text().isEmpty();
180         break;
181     case ChangePass: // Old passphrase x1, new passphrase x2
182         acceptable = !ui->passEdit1->text().isEmpty() && !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty();
183         break;
184     }
185     ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(acceptable);
186 }