1 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net>
2
3 This file is part of the Trojita Qt IMAP e-mail client,
4 http://trojita.flaska.net/
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of
9 the License or (at your option) version 3 or any later version
10 accepted by the membership of KDE e.V. (or its successor approved
11 by the membership of KDE e.V.), which shall act as a proxy
12 defined in Section 14 of version 3 of the license.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "PasswordWatcher.h"
24 #include "Plugins/PluginManager.h"
25
26 namespace UiUtils {
27
PasswordWatcher(QObject * parent,Plugins::PluginManager * manager,const QString & accountName,const QString & accountType)28 PasswordWatcher::PasswordWatcher(QObject *parent, Plugins::PluginManager *manager, const QString &accountName, const QString &accountType) :
29 QObject(parent), m_manager(manager), m_isStorageEncrypted(false), m_pendingActions(0), m_didReadOk(false), m_didWriteOk(false),
30 m_accountName(accountName), m_accountType(accountType)
31 {
32 connect(m_manager, &Plugins::PluginManager::pluginsChanged, this, &PasswordWatcher::backendMaybeChanged);
33 }
34
progressMessage() const35 QString PasswordWatcher::progressMessage() const
36 {
37 return m_progressMessage;
38 }
39
isStorageEncrypted() const40 bool PasswordWatcher::isStorageEncrypted() const
41 {
42 return m_isStorageEncrypted;
43 }
44
isWaitingForPlugin() const45 bool PasswordWatcher::isWaitingForPlugin() const
46 {
47 return m_pendingActions > 0;
48 }
49
isPluginAvailable() const50 bool PasswordWatcher::isPluginAvailable() const
51 {
52 return m_manager->password();
53 }
54
password() const55 QString PasswordWatcher::password() const
56 {
57 return m_password;
58 }
59
didReadOk() const60 bool PasswordWatcher::didReadOk() const
61 {
62 return m_didReadOk;
63 }
64
didWriteOk() const65 bool PasswordWatcher::didWriteOk() const
66 {
67 return m_didWriteOk;
68 }
69
reloadPassword()70 void PasswordWatcher::reloadPassword()
71 {
72 m_didReadOk = false;
73 m_password = QString();
74 ++m_pendingActions;
75 if (Plugins::PasswordPlugin *plugin = m_manager->password()) {
76 if (Plugins::PasswordJob *job = plugin->requestPassword(m_accountName, m_accountType)) {
77 m_isStorageEncrypted = plugin->features() & Plugins::PasswordPlugin::FeatureEncryptedStorage;
78 connect(job, &Plugins::PasswordJob::passwordAvailable, this, &PasswordWatcher::passwordRetrieved);
79 connect(job, &Plugins::PasswordJob::error, this, &PasswordWatcher::passwordReadingFailed);
80 job->setAutoDelete(true);
81 job->start();
82 m_progressMessage = tr("Loading password from plugin %1...").arg(m_manager->passwordPlugin());
83 emit stateChanged();
84 return;
85 } else {
86 m_progressMessage = tr("Cannot read password via plugin %1").arg(m_manager->passwordPlugin());
87 }
88 } else {
89 m_progressMessage = tr("Password plugin is not available.");
90 }
91
92 // error handling
93 // There's actually no pending action now
94 --m_pendingActions;
95 emit stateChanged();
96 emit readingFailed(m_progressMessage);
97 }
98
passwordRetrieved(const QString & password)99 void PasswordWatcher::passwordRetrieved(const QString &password)
100 {
101 m_password = password;
102 m_progressMessage.clear();
103 --m_pendingActions;
104 m_didReadOk = true;
105 emit stateChanged();
106 emit readingDone();
107 }
108
passwordReadingFailed(const Plugins::PasswordJob::Error errorCode,const QString & errorMessage)109 void PasswordWatcher::passwordReadingFailed(const Plugins::PasswordJob::Error errorCode, const QString &errorMessage)
110 {
111 --m_pendingActions;
112 m_didReadOk = false;
113 switch (errorCode) {
114 case Plugins::PasswordJob::NoSuchPassword:
115 m_progressMessage.clear();
116 break;
117 case Plugins::PasswordJob::Stopped:
118 case Plugins::PasswordJob::UnknownError:
119 {
120 QString msg = tr("Password reading failed: %1").arg(errorMessage);
121 m_progressMessage = msg;
122 emit readingFailed(msg);
123 break;
124 }
125 }
126 emit stateChanged();
127 }
128
passwordWritten()129 void PasswordWatcher::passwordWritten()
130 {
131 --m_pendingActions;
132 m_progressMessage.clear();
133 m_didWriteOk = true;
134 emit stateChanged();
135 emit savingDone();
136 }
137
passwordWritingFailed(const Plugins::PasswordJob::Error errorCode,const QString & errorMessage)138 void PasswordWatcher::passwordWritingFailed(const Plugins::PasswordJob::Error errorCode, const QString &errorMessage)
139 {
140 --m_pendingActions;
141 m_didWriteOk = false;
142 switch (errorCode) {
143 case Plugins::PasswordJob::NoSuchPassword:
144 Q_ASSERT(false);
145 break;
146 case Plugins::PasswordJob::Stopped:
147 case Plugins::PasswordJob::UnknownError:
148 {
149 QString msg = tr("Password writing failed: %1").arg(errorMessage);
150 m_progressMessage = msg;
151 emit savingFailed(msg);
152 break;
153 }
154 }
155 emit stateChanged();
156 }
157
setPassword(const QString & password)158 void PasswordWatcher::setPassword(const QString &password)
159 {
160 m_didWriteOk = false;
161 ++m_pendingActions;
162 if (Plugins::PasswordPlugin *plugin = m_manager->password()) {
163 if (Plugins::PasswordJob *job = plugin->storePassword(m_accountName, m_accountType, password)) {
164 connect(job, &Plugins::PasswordJob::passwordStored, this, &PasswordWatcher::passwordWritten);
165 connect(job, &Plugins::PasswordJob::error, this, &PasswordWatcher::passwordWritingFailed);
166 job->setAutoDelete(true);
167 job->start();
168 m_progressMessage = tr("Saving password from plugin %1...").arg(m_manager->passwordPlugin());
169 emit stateChanged();
170 return;
171 } else {
172 m_progressMessage = tr("Cannot save password via plugin %1").arg(m_manager->passwordPlugin());
173 }
174 } else {
175 m_progressMessage = tr("Password plugin is not available.");
176 }
177
178 // error handling
179 --m_pendingActions;
180 emit stateChanged();
181 emit savingFailed(m_progressMessage);
182 }
183
184 }
185