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