Falkon Develop
Cross-platform Qt-based web browser
passwordmanager.cpp
Go to the documentation of this file.
1/* ============================================================
2* Falkon - Qt web browser
3* Copyright (C) 2013-2018 David Rosca <nowrep@gmail.com>
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License as published by
7* the Free Software Foundation, either version 3 of the License, or
8* (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program. If not, see <http://www.gnu.org/licenses/>.
17* ============================================================ */
18#include "passwordmanager.h"
22#include "settings.h"
23
24#include <QVector>
25#include <QDataStream>
26
27static const int passwordEntryVersion = 2;
28
29QDataStream &operator <<(QDataStream &stream, const PasswordEntry &entry)
30{
31 stream << passwordEntryVersion;
32 stream << entry.host;
33 stream << entry.id;
34 stream << entry.username;
35 stream << entry.password;
36 stream << entry.data;
37 stream << entry.updated;
38
39 return stream;
40}
41
42QDataStream &operator >>(QDataStream &stream, PasswordEntry &entry)
43{
44 int version;
45 stream >> version;
46
47 if (version != passwordEntryVersion) {
48 return stream;
49 }
50
51 stream >> entry.host;
52 stream >> entry.id;
53 stream >> entry.username;
54 stream >> entry.password;
55 stream >> entry.data;
56 stream >> entry.updated;
57
58 return stream;
59}
60
62 : QObject(parent)
63 , m_loaded(false)
64 , m_backend(nullptr)
65 , m_databaseBackend(new DatabasePasswordBackend)
66 , m_databaseEncryptedBackend(new DatabaseEncryptedPasswordBackend)
67{
68 m_backends[QSL("database")] = m_databaseBackend;
69 m_backends[QSL("database-encrypted")] = m_databaseEncryptedBackend;
70}
71
73{
74 Settings settings;
75 settings.beginGroup(QSL("PasswordManager"));
76 QString backendId = settings.value(QSL("Backend"), QSL("database")).toString();
77 settings.endGroup();
78
79 if (m_backend) {
80 m_backend->setActive(false);
81 }
82 m_backend = m_backends[m_backends.contains(backendId) ? backendId : QSL("database")];
83 m_backend->setActive(true);
84}
85
86QStringList PasswordManager::getUsernames(const QUrl &url)
87{
88 ensureLoaded();
89 return m_backend->getUsernames(url);
90}
91
92QVector<PasswordEntry> PasswordManager::getEntries(const QUrl &url)
93{
94 ensureLoaded();
95 return m_backend->getEntries(url);
96}
97
98QVector<PasswordEntry> PasswordManager::getAllEntries()
99{
100 ensureLoaded();
101 return m_backend->getAllEntries();
102}
103
105{
106 ensureLoaded();
107 m_backend->addEntry(entry);
108}
109
111{
112 ensureLoaded();
113 return m_backend->updateEntry(entry);
114}
115
117{
118 ensureLoaded();
119 m_backend->updateLastUsed(entry);
120}
121
123{
124 ensureLoaded();
125 m_backend->removeEntry(entry);
126}
127
129{
130 ensureLoaded();
131 m_backend->removeAll();
132}
133
134QHash<QString, PasswordBackend*> PasswordManager::availableBackends()
135{
136 ensureLoaded();
137 return m_backends;
138}
139
141{
142 ensureLoaded();
143 return m_backend;
144}
145
146void PasswordManager::switchBackend(const QString &backendID)
147{
148 PasswordBackend* backend = m_backends.value(backendID);
149
150 if (!backend) {
151 return;
152 }
153
154 if (m_backend) {
155 m_backend->setActive(false);
156 }
157
158 m_backend = backend;
159 m_backend->setActive(true);
160
161 Settings settings;
162 settings.beginGroup(QSL("PasswordManager"));
163 settings.setValue(QSL("Backend"), backendID);
164 settings.endGroup();
165
166 Q_EMIT passwordBackendChanged();
167}
168
169bool PasswordManager::registerBackend(const QString &id, PasswordBackend* backend)
170{
171 if (m_backends.contains(id)) {
172 return false;
173 }
174
175 m_backends[id] = backend;
176 return true;
177}
178
180{
181 const QString key = m_backends.key(backend);
182 m_backends.remove(key);
183
184 if (m_backend == backend) {
185 m_backend = m_databaseBackend;
186 }
187}
188
189QString PasswordManager::createHost(const QUrl &url)
190{
191 QString host = url.host();
192
193 if (host.isEmpty()) {
194 host = url.toString();
195 }
196
197 if (url.port() != -1) {
198 host.append(QLatin1Char(':'));
199 host.append(QString::number(url.port()));
200 }
201
202 return host;
203}
204
205QByteArray PasswordManager::urlEncodePassword(const QString &password)
206{
207 // Exclude space to properly decode to +
208 QByteArray encodedPass = QUrl::toPercentEncoding(password, " ");
209 encodedPass.replace(' ', '+'); // space has to be encoded to +
210 encodedPass.replace('~', "%7E"); // ~ is unreserved char, needs to be manually encoded
211 return encodedPass;
212}
213
214void PasswordManager::ensureLoaded()
215{
216 if (!m_loaded) {
217 loadSettings();
218 m_loaded = true;
219 }
220}
221
223{
224 delete m_databaseBackend;
225 delete m_databaseEncryptedBackend;
226}
virtual bool updateEntry(const PasswordEntry &entry)=0
virtual void addEntry(const PasswordEntry &entry)=0
virtual QVector< PasswordEntry > getAllEntries()=0
virtual void removeAll()=0
virtual QStringList getUsernames(const QUrl &url)
virtual void removeEntry(const PasswordEntry &entry)=0
virtual void updateLastUsed(PasswordEntry &entry)=0
virtual QVector< PasswordEntry > getEntries(const QUrl &url)=0
virtual void setActive(bool active)
bool updateEntry(const PasswordEntry &entry)
static QString createHost(const QUrl &url)
void switchBackend(const QString &backendID)
void removeEntry(const PasswordEntry &entry)
QStringList getUsernames(const QUrl &url)
static QByteArray urlEncodePassword(const QString &password)
bool registerBackend(const QString &id, PasswordBackend *backend)
void passwordBackendChanged()
PasswordManager(QObject *parent=nullptr)
void unregisterBackend(PasswordBackend *backend)
QVector< PasswordEntry > getEntries(const QUrl &url)
void updateLastUsed(PasswordEntry &entry)
PasswordBackend * activeBackend()
QVector< PasswordEntry > getAllEntries()
void addEntry(const PasswordEntry &entry)
QHash< QString, PasswordBackend * > availableBackends()
void beginGroup(const QString &prefix)
Definition: settings.cpp:79
void endGroup()
Definition: settings.cpp:84
QVariant value(const QString &key, const QVariant &defaultValue=QVariant())
Definition: settings.cpp:74
void setValue(const QString &key, const QVariant &defaultValue=QVariant())
Definition: settings.cpp:69
QDataStream & operator>>(QDataStream &stream, PasswordEntry &entry)
QDataStream & operator<<(QDataStream &stream, const PasswordEntry &entry)
#define QSL(x)
Definition: qzcommon.h:40
QString password
QString host
QByteArray data
QString username
int updated
QVariant id