File indexing completed on 2024-05-19 04:58:38
0001 /* ============================================================ 0002 * Falkon - Qt web browser 0003 * Copyright (C) 2013-2018 David Rosca <nowrep@gmail.com> 0004 * 0005 * This program is free software: you can redistribute it and/or modify 0006 * it under the terms of the GNU General Public License as published by 0007 * the Free Software Foundation, either version 3 of the License, or 0008 * (at your option) any later version. 0009 * 0010 * This program is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 * GNU General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU General Public License 0016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0017 * ============================================================ */ 0018 #include "passwordmanager.h" 0019 #include "passwordbackends/passwordbackend.h" 0020 #include "passwordbackends/databasepasswordbackend.h" 0021 #include "passwordbackends/databaseencryptedpasswordbackend.h" 0022 #include "settings.h" 0023 0024 #include <QVector> 0025 #include <QDataStream> 0026 0027 static const int passwordEntryVersion = 2; 0028 0029 QDataStream &operator <<(QDataStream &stream, const PasswordEntry &entry) 0030 { 0031 stream << passwordEntryVersion; 0032 stream << entry.host; 0033 stream << entry.id; 0034 stream << entry.username; 0035 stream << entry.password; 0036 stream << entry.data; 0037 stream << entry.updated; 0038 0039 return stream; 0040 } 0041 0042 QDataStream &operator >>(QDataStream &stream, PasswordEntry &entry) 0043 { 0044 int version; 0045 stream >> version; 0046 0047 if (version != passwordEntryVersion) { 0048 return stream; 0049 } 0050 0051 stream >> entry.host; 0052 stream >> entry.id; 0053 stream >> entry.username; 0054 stream >> entry.password; 0055 stream >> entry.data; 0056 stream >> entry.updated; 0057 0058 return stream; 0059 } 0060 0061 PasswordManager::PasswordManager(QObject* parent) 0062 : QObject(parent) 0063 , m_loaded(false) 0064 , m_backend(nullptr) 0065 , m_databaseBackend(new DatabasePasswordBackend) 0066 , m_databaseEncryptedBackend(new DatabaseEncryptedPasswordBackend) 0067 { 0068 m_backends[QSL("database")] = m_databaseBackend; 0069 m_backends[QSL("database-encrypted")] = m_databaseEncryptedBackend; 0070 } 0071 0072 void PasswordManager::loadSettings() 0073 { 0074 Settings settings; 0075 settings.beginGroup(QSL("PasswordManager")); 0076 QString backendId = settings.value(QSL("Backend"), QSL("database")).toString(); 0077 settings.endGroup(); 0078 0079 if (m_backend) { 0080 m_backend->setActive(false); 0081 } 0082 m_backend = m_backends[m_backends.contains(backendId) ? backendId : QSL("database")]; 0083 m_backend->setActive(true); 0084 } 0085 0086 QStringList PasswordManager::getUsernames(const QUrl &url) 0087 { 0088 ensureLoaded(); 0089 return m_backend->getUsernames(url); 0090 } 0091 0092 QVector<PasswordEntry> PasswordManager::getEntries(const QUrl &url) 0093 { 0094 ensureLoaded(); 0095 return m_backend->getEntries(url); 0096 } 0097 0098 QVector<PasswordEntry> PasswordManager::getAllEntries() 0099 { 0100 ensureLoaded(); 0101 return m_backend->getAllEntries(); 0102 } 0103 0104 void PasswordManager::addEntry(const PasswordEntry &entry) 0105 { 0106 ensureLoaded(); 0107 m_backend->addEntry(entry); 0108 } 0109 0110 bool PasswordManager::updateEntry(const PasswordEntry &entry) 0111 { 0112 ensureLoaded(); 0113 return m_backend->updateEntry(entry); 0114 } 0115 0116 void PasswordManager::updateLastUsed(PasswordEntry &entry) 0117 { 0118 ensureLoaded(); 0119 m_backend->updateLastUsed(entry); 0120 } 0121 0122 void PasswordManager::removeEntry(const PasswordEntry &entry) 0123 { 0124 ensureLoaded(); 0125 m_backend->removeEntry(entry); 0126 } 0127 0128 void PasswordManager::removeAllEntries() 0129 { 0130 ensureLoaded(); 0131 m_backend->removeAll(); 0132 } 0133 0134 QHash<QString, PasswordBackend*> PasswordManager::availableBackends() 0135 { 0136 ensureLoaded(); 0137 return m_backends; 0138 } 0139 0140 PasswordBackend* PasswordManager::activeBackend() 0141 { 0142 ensureLoaded(); 0143 return m_backend; 0144 } 0145 0146 void PasswordManager::switchBackend(const QString &backendID) 0147 { 0148 PasswordBackend* backend = m_backends.value(backendID); 0149 0150 if (!backend) { 0151 return; 0152 } 0153 0154 if (m_backend) { 0155 m_backend->setActive(false); 0156 } 0157 0158 m_backend = backend; 0159 m_backend->setActive(true); 0160 0161 Settings settings; 0162 settings.beginGroup(QSL("PasswordManager")); 0163 settings.setValue(QSL("Backend"), backendID); 0164 settings.endGroup(); 0165 0166 Q_EMIT passwordBackendChanged(); 0167 } 0168 0169 bool PasswordManager::registerBackend(const QString &id, PasswordBackend* backend) 0170 { 0171 if (m_backends.contains(id)) { 0172 return false; 0173 } 0174 0175 m_backends[id] = backend; 0176 return true; 0177 } 0178 0179 void PasswordManager::unregisterBackend(PasswordBackend* backend) 0180 { 0181 const QString key = m_backends.key(backend); 0182 m_backends.remove(key); 0183 0184 if (m_backend == backend) { 0185 m_backend = m_databaseBackend; 0186 } 0187 } 0188 0189 QString PasswordManager::createHost(const QUrl &url) 0190 { 0191 QString host = url.host(); 0192 0193 if (host.isEmpty()) { 0194 host = url.toString(); 0195 } 0196 0197 if (url.port() != -1) { 0198 host.append(QLatin1Char(':')); 0199 host.append(QString::number(url.port())); 0200 } 0201 0202 return host; 0203 } 0204 0205 QByteArray PasswordManager::urlEncodePassword(const QString &password) 0206 { 0207 // Exclude space to properly decode to + 0208 QByteArray encodedPass = QUrl::toPercentEncoding(password, " "); 0209 encodedPass.replace(' ', '+'); // space has to be encoded to + 0210 encodedPass.replace('~', "%7E"); // ~ is unreserved char, needs to be manually encoded 0211 return encodedPass; 0212 } 0213 0214 void PasswordManager::ensureLoaded() 0215 { 0216 if (!m_loaded) { 0217 loadSettings(); 0218 m_loaded = true; 0219 } 0220 } 0221 0222 PasswordManager::~PasswordManager() 0223 { 0224 delete m_databaseBackend; 0225 delete m_databaseEncryptedBackend; 0226 }