1
mirror of https://invent.kde.org/network/falkon.git synced 2024-12-20 18:56:34 +01:00

[AutoFill] Rewritten password management to support multiple backends.

This commit is contained in:
nowrep 2013-05-14 17:25:55 +02:00
parent b9e6fdac4b
commit bd315afe9e
20 changed files with 458 additions and 204 deletions

View File

@ -874,7 +874,7 @@ DownloadManager* MainApplication::downManager()
AutoFill* MainApplication::autoFill() AutoFill* MainApplication::autoFill()
{ {
if (!m_autofill) { if (!m_autofill) {
m_autofill = new AutoFill(getWindow()); m_autofill = new AutoFill(this);
} }
return m_autofill; return m_autofill;
} }

View File

@ -25,6 +25,7 @@
#include "pageformcompleter.h" #include "pageformcompleter.h"
#include "databasewriter.h" #include "databasewriter.h"
#include "settings.h" #include "settings.h"
#include "passwordmanager.h"
#include <QXmlStreamWriter> #include <QXmlStreamWriter>
#include <QXmlStreamReader> #include <QXmlStreamReader>
@ -35,9 +36,9 @@
#include <QUrlQuery> #include <QUrlQuery>
#endif #endif
AutoFill::AutoFill(QupZilla* mainClass, QObject* parent) AutoFill::AutoFill(QObject* parent)
: QObject(parent) : QObject(parent)
, p_QupZilla(mainClass) , m_manager(new PasswordManager(this))
, m_isStoring(false) , m_isStoring(false)
{ {
loadSettings(); loadSettings();
@ -57,21 +58,7 @@ bool AutoFill::isStored(const QUrl &url)
return false; return false;
} }
QString server = url.host(); return !m_manager->getEntries(url).isEmpty();
if (server.isEmpty()) {
server = url.toString();
}
QSqlQuery query;
query.prepare("SELECT count(id) FROM autofill WHERE server=?");
query.addBindValue(server);
query.exec();
query.next();
if (query.value(0).toInt() > 0) {
return true;
}
return false;
} }
bool AutoFill::isStoringEnabled(const QUrl &url) bool AutoFill::isStoringEnabled(const QUrl &url)
@ -89,12 +76,9 @@ bool AutoFill::isStoringEnabled(const QUrl &url)
query.prepare("SELECT count(id) FROM autofill_exceptions WHERE server=?"); query.prepare("SELECT count(id) FROM autofill_exceptions WHERE server=?");
query.addBindValue(server); query.addBindValue(server);
query.exec(); query.exec();
query.next(); query.next();
if (query.value(0).toInt() > 0) {
return false; return query.value(0).toInt() <= 0;
}
return true;
} }
void AutoFill::blockStoringforUrl(const QUrl &url) void AutoFill::blockStoringforUrl(const QUrl &url)
@ -110,155 +94,60 @@ void AutoFill::blockStoringforUrl(const QUrl &url)
mApp->dbWriter()->executeQuery(query); mApp->dbWriter()->executeQuery(query);
} }
AutoFillData AutoFill::getFirstFormData(const QUrl &url) QVector<PasswordEntry> AutoFill::getFormData(const QUrl &url)
{ {
const QVector<AutoFillData> &list = getFormData(url, 1); return m_manager->getEntries(url);
if (list.isEmpty()) {
AutoFillData data;
data.id = -1;
return data;
} }
return list.first(); void AutoFill::updateLastUsed(const PasswordEntry &data)
}
QVector<AutoFillData> AutoFill::getFormData(const QUrl &url, int limit)
{ {
QVector<AutoFillData> list; m_manager->updateLastUsed(data);
QString server = url.host();
if (server.isEmpty()) {
server = url.toString();
} }
QString queryString = "SELECT id, username, password, data FROM autofill " // HTTP Authorization
"WHERE server=? ORDER BY last_used DESC";
if (limit > 0) {
queryString.append(QLatin1String(" LIMIT ?"));
}
QSqlQuery query;
query.prepare(queryString);
query.addBindValue(server);
if (limit > 0) {
query.addBindValue(limit);
}
query.exec();
while (query.next()) {
AutoFillData data;
data.id = query.value(0).toInt();
data.username = query.value(1).toString();
data.password = query.value(2).toString();
data.postData = query.value(3).toByteArray();
list.append(data);
}
return list;
}
void AutoFill::updateLastUsed(int id)
{
if (id < 0) {
return;
}
QSqlQuery query;
query.prepare("UPDATE autofill SET last_used=strftime('%s', 'now') WHERE id=?");
query.addBindValue(id);
query.exec();
}
///HTTP Authorization
void AutoFill::addEntry(const QUrl &url, const QString &name, const QString &pass) void AutoFill::addEntry(const QUrl &url, const QString &name, const QString &pass)
{ {
QSqlQuery query; PasswordEntry entry;
QString server = url.host(); entry.url = url;
if (server.isEmpty()) { entry.username = name;
server = url.toString(); entry.password = pass;
m_manager->addEntry(entry);
} }
// Multiple-usernames for HTTP Authorization not supported // WEB Form
query.prepare("SELECT username FROM autofill WHERE server=?");
query.addBindValue(server);
query.exec();
if (query.next()) {
return;
}
query.prepare("INSERT INTO autofill (server, username, password, last_used) "
"VALUES (?,?,?,strftime('%s', 'now'))");
query.bindValue(0, server);
query.bindValue(1, name);
query.bindValue(2, pass);
mApp->dbWriter()->executeQuery(query);
}
///WEB Form
void AutoFill::addEntry(const QUrl &url, const PageFormData &formData) void AutoFill::addEntry(const QUrl &url, const PageFormData &formData)
{ {
QString server = url.host(); PasswordEntry entry;
if (server.isEmpty()) { entry.url = url;
server = url.toString(); entry.username = formData.username;
} entry.password = formData.password;
QSqlQuery query; m_manager->addEntry(entry);
query.prepare("INSERT INTO autofill (server, data, username, password, last_used) "
"VALUES (?,?,?,?,strftime('%s', 'now'))");
query.bindValue(0, server);
query.bindValue(1, formData.postData);
query.bindValue(2, formData.username);
query.bindValue(3, formData.password);
mApp->dbWriter()->executeQuery(query);
} }
// HTTP Authorization
void AutoFill::updateEntry(const QUrl &url, const QString &name, const QString &pass) void AutoFill::updateEntry(const QUrl &url, const QString &name, const QString &pass)
{ {
QSqlQuery query; PasswordEntry entry;
QString server = url.host(); entry.url = url;
if (server.isEmpty()) { entry.username = name;
server = url.toString(); entry.password = pass;
m_manager->updateEntry(entry);
} }
query.prepare("SELECT username FROM autofill WHERE server=?"); // WEB Form
query.addBindValue(server); void AutoFill::updateEntry(const PasswordEntry &entry)
query.exec();
if (!query.next()) {
return;
}
query.prepare("UPDATE autofill SET username=?, password=? WHERE server=?");
query.bindValue(0, name);
query.bindValue(1, pass);
query.bindValue(2, server);
mApp->dbWriter()->executeQuery(query);
}
void AutoFill::updateEntry(const PageFormData &formData, const AutoFillData &updateData)
{ {
QSqlQuery query; m_manager->updateEntry(entry);
query.prepare("UPDATE autofill SET data=?, username=?, password=? WHERE id=?");
query.addBindValue(formData.postData);
query.addBindValue(formData.username);
query.addBindValue(formData.password);
query.addBindValue(updateData.id);
mApp->dbWriter()->executeQuery(query);
} }
// If password was filled in the page, returns all saved passwords on this page // If password was filled in the page, returns all saved passwords on this page
QVector<AutoFillData> AutoFill::completePage(WebPage* page) QVector<PasswordEntry> AutoFill::completePage(WebPage* page)
{ {
bool completed = false; bool completed = false;
QVector<AutoFillData> list; QVector<PasswordEntry> list;
if (!page) { if (!page) {
return list; return list;
@ -272,10 +161,10 @@ QVector<AutoFillData> AutoFill::completePage(WebPage* page)
list = getFormData(pageUrl); list = getFormData(pageUrl);
if (!list.isEmpty()) { if (!list.isEmpty()) {
const AutoFillData data = getFirstFormData(pageUrl); const PasswordEntry entry = list.first();
PageFormCompleter completer(page); PageFormCompleter completer(page);
completed = completer.completePage(data.postData); completed = completer.completePage(entry.data);
} }
if (!completed) { if (!completed) {
@ -311,24 +200,27 @@ void AutoFill::post(const QNetworkRequest &request, const QByteArray &outgoingDa
PageFormCompleter completer(webPage); PageFormCompleter completer(webPage);
const PageFormData formData = completer.extractFormData(outgoingData); const PageFormData formData = completer.extractFormData(outgoingData);
if (!formData.found) { if (!formData.isValid()) {
return; return;
} }
AutoFillData updateData = { -1, QString(), QString(), QByteArray() }; PasswordEntry updateData = { -1, QUrl(), QString(), QString(), QByteArray() };
if (isStored(siteUrl)) { if (isStored(siteUrl)) {
const QVector<AutoFillData> &list = getFormData(siteUrl); const QVector<PasswordEntry> &list = getFormData(siteUrl);
foreach (const AutoFillData &data, list) { foreach (const PasswordEntry &data, list) {
if (data.username == formData.username) { if (data.username == formData.username) {
updateLastUsed(data.id); updateLastUsed(data);
if (data.password == formData.password) { if (data.password == formData.password) {
return; return;
} }
updateData = data; updateData = data;
updateData.username = formData.username;
updateData.password = formData.password;
updateData.data = formData.postData;
break; break;
} }
} }

View File

@ -29,23 +29,14 @@ class QNetworkRequest;
class QupZilla; class QupZilla;
class WebPage; class WebPage;
class PasswordManager;
struct PageFormData; struct PageFormData;
struct PasswordEntry;
struct AutoFillData {
int id;
QString username;
QString password;
QByteArray postData;
bool isValid() const {
return id > -1;
}
};
class QT_QUPZILLA_EXPORT AutoFill : public QObject class QT_QUPZILLA_EXPORT AutoFill : public QObject
{ {
public: public:
explicit AutoFill(QupZilla* mainClass, QObject* parent = 0); explicit AutoFill(QObject* parent = 0);
void loadSettings(); void loadSettings();
@ -53,30 +44,26 @@ public:
bool isStoringEnabled(const QUrl &url); bool isStoringEnabled(const QUrl &url);
void blockStoringforUrl(const QUrl &url); void blockStoringforUrl(const QUrl &url);
AutoFillData getFirstFormData(const QUrl &url); QVector<PasswordEntry> getFormData(const QUrl &url);
QVector<AutoFillData> getFormData(const QUrl &url, int limit = 0);
void updateLastUsed(int id); void updateLastUsed(const PasswordEntry &data);
void addEntry(const QUrl &url, const QString &name, const QString &pass); void addEntry(const QUrl &url, const QString &name, const QString &pass);
void addEntry(const QUrl &url, const PageFormData &formData); void addEntry(const QUrl &url, const PageFormData &formData);
void updateEntry(const QUrl &url, const QString &name, const QString &pass); void updateEntry(const QUrl &url, const QString &name, const QString &pass);
void updateEntry(const PageFormData &formData, const AutoFillData &updateData); void updateEntry(const PasswordEntry &entry);
void post(const QNetworkRequest &request, const QByteArray &outgoingData); void post(const QNetworkRequest &request, const QByteArray &outgoingData);
QVector<AutoFillData> completePage(WebPage* page); QVector<PasswordEntry> completePage(WebPage* page);
static QByteArray exportPasswords(); static QByteArray exportPasswords();
static bool importPasswords(const QByteArray &data); static bool importPasswords(const QByteArray &data);
private: private:
QupZilla* p_QupZilla; PasswordManager* m_manager;
bool m_isStoring; bool m_isStoring;
}; };
// Hint to QVector to use std::realloc on item moving
Q_DECLARE_TYPEINFO(AutoFillData, Q_MOVABLE_TYPE);
#endif // AUTOFILLMODEL_H #endif // AUTOFILLMODEL_H

View File

@ -37,7 +37,7 @@ void AutoFillIcon::setWebView(WebView* view)
m_view = view; m_view = view;
} }
void AutoFillIcon::setFormData(const QVector<AutoFillData> &data) void AutoFillIcon::setFormData(const QVector<PasswordEntry> &data)
{ {
m_data = data; m_data = data;
} }

View File

@ -20,7 +20,7 @@
#include "qz_namespace.h" #include "qz_namespace.h"
#include "clickablelabel.h" #include "clickablelabel.h"
#include "autofill.h" #include "passwordmanager.h"
class WebView; class WebView;
@ -32,7 +32,7 @@ public:
explicit AutoFillIcon(QWidget* parent = 0); explicit AutoFillIcon(QWidget* parent = 0);
void setWebView(WebView* view); void setWebView(WebView* view);
void setFormData(const QVector<AutoFillData> &data); void setFormData(const QVector<PasswordEntry> &data);
private slots: private slots:
void iconClicked(); void iconClicked();
@ -43,7 +43,7 @@ private:
WebView* m_view; WebView* m_view;
QVector<AutoFillData> m_data; QVector<PasswordEntry> m_data;
}; };

View File

@ -22,7 +22,7 @@
#include "animatedwidget.h" #include "animatedwidget.h"
#include "iconprovider.h" #include "iconprovider.h"
AutoFillNotification::AutoFillNotification(const QUrl &url, const PageFormData &formData, const AutoFillData &updateData) AutoFillNotification::AutoFillNotification(const QUrl &url, const PageFormData &formData, const PasswordEntry &updateData)
: AnimatedWidget(AnimatedWidget::Down, 300, 0) : AnimatedWidget(AnimatedWidget::Down, 300, 0)
, ui(new Ui::AutoFillNotification) , ui(new Ui::AutoFillNotification)
, m_url(url) , m_url(url)
@ -68,7 +68,7 @@ AutoFillNotification::AutoFillNotification(const QUrl &url, const PageFormData &
void AutoFillNotification::update() void AutoFillNotification::update()
{ {
mApp->autoFill()->updateEntry(m_formData, m_updateData); mApp->autoFill()->updateEntry(m_updateData);
hide(); hide();
} }

View File

@ -23,6 +23,7 @@
#include "qz_namespace.h" #include "qz_namespace.h"
#include "animatedwidget.h" #include "animatedwidget.h"
#include "pageformcompleter.h" #include "pageformcompleter.h"
#include "passwordmanager.h"
#include "autofill.h" #include "autofill.h"
namespace Ui namespace Ui
@ -39,7 +40,7 @@ class QT_QUPZILLA_EXPORT AutoFillNotification : public AnimatedWidget
public: public:
explicit AutoFillNotification(const QUrl &url, explicit AutoFillNotification(const QUrl &url,
const PageFormData &formData, const PageFormData &formData,
const AutoFillData &updateData); const PasswordEntry &updateData);
~AutoFillNotification(); ~AutoFillNotification();
private slots: private slots:
@ -52,7 +53,7 @@ private:
QUrl m_url; QUrl m_url;
PageFormData m_formData; PageFormData m_formData;
AutoFillData m_updateData; PasswordEntry m_updateData;
}; };
#endif // AUTOFILLNOTIFICATION_H #endif // AUTOFILLNOTIFICATION_H

View File

@ -33,12 +33,12 @@ AutoFillWidget::AutoFillWidget(WebView* view, QWidget* parent)
ui->setupUi(this); ui->setupUi(this);
} }
void AutoFillWidget::setFormData(const QVector<AutoFillData> &data) void AutoFillWidget::setFormData(const QVector<PasswordEntry> &data)
{ {
m_data = data; m_data = data;
for (int i = 0; i < data.count(); ++i) { for (int i = 0; i < data.count(); ++i) {
const AutoFillData d = data.at(i); const PasswordEntry d = data.at(i);
if (d.username.isEmpty()) { if (d.username.isEmpty()) {
continue; continue;
} }
@ -67,10 +67,10 @@ void AutoFillWidget::loginToPage()
int index = button->property("data-index").toInt(&ok); int index = button->property("data-index").toInt(&ok);
if (ok && QzTools::vectorContainsIndex(m_data, index)) { if (ok && QzTools::vectorContainsIndex(m_data, index)) {
const AutoFillData data = m_data.at(index); const PasswordEntry entry = m_data.at(index);
PageFormCompleter completer(m_view->page()); PageFormCompleter completer(m_view->page());
completer.completePage(data.postData); completer.completePage(entry.data);
} }
close(); close();

View File

@ -30,7 +30,7 @@ class AutoFillWidget;
} }
class WebView; class WebView;
struct AutoFillData; struct PasswordEntry;
class QT_QUPZILLA_EXPORT AutoFillWidget : public LocationBarPopup class QT_QUPZILLA_EXPORT AutoFillWidget : public LocationBarPopup
{ {
@ -40,7 +40,7 @@ public:
explicit AutoFillWidget(WebView* view, QWidget* parent = 0); explicit AutoFillWidget(WebView* view, QWidget* parent = 0);
~AutoFillWidget(); ~AutoFillWidget();
void setFormData(const QVector<AutoFillData> &data); void setFormData(const QVector<PasswordEntry> &data);
private slots: private slots:
void loginToPage(); void loginToPage();
@ -49,7 +49,7 @@ private:
Ui::AutoFillWidget* ui; Ui::AutoFillWidget* ui;
WebView* m_view; WebView* m_view;
QVector<AutoFillData> m_data; QVector<PasswordEntry> m_data;
}; };
#endif // AUTOFILLWIDGET_H #endif // AUTOFILLWIDGET_H

View File

@ -0,0 +1,125 @@
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2013 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "databasepasswordbackend.h"
#include "mainapplication.h"
#include "databasewriter.h"
#include <QVector>
#include <QSqlQuery>
DatabasePasswordBackend::DatabasePasswordBackend()
{
}
QVector<PasswordEntry> DatabasePasswordBackend::getEntries(const QUrl &url)
{
QVector<PasswordEntry> list;
QString server = url.host();
if (server.isEmpty()) {
server = url.toString();
}
QString query = "SELECT id, username, password, data FROM autofill "
"WHERE server=? ORDER BY last_used DESC";
QSqlQuery sqlQuery;
sqlQuery.prepare(query);
sqlQuery.addBindValue(server);
sqlQuery.exec();
while (sqlQuery.next()) {
PasswordEntry data;
data.id = sqlQuery.value(0);
data.url = url;
data.username = sqlQuery.value(1).toString();
data.password = sqlQuery.value(2).toString();
data.data = sqlQuery.value(3).toByteArray();
list.append(data);
}
return list;
}
void DatabasePasswordBackend::addEntry(const PasswordEntry &entry)
{
QString server = entry.url.host();
if (server.isEmpty()) {
server = entry.url.toString();
}
// Data is empty only for HTTP/FTP authorization
if (entry.data.isEmpty()) {
// Multiple-usernames for HTTP/FTP authorization not supported
QSqlQuery query;
query.prepare("SELECT username FROM autofill WHERE server=?");
query.addBindValue(server);
query.exec();
if (query.next()) {
return;
}
}
QSqlQuery query;
query.prepare("INSERT INTO autofill (server, data, username, password, last_used) "
"VALUES (?,?,?,?,strftime('%s', 'now'))");
query.bindValue(0, server);
query.bindValue(1, entry.data);
query.bindValue(2, entry.username);
query.bindValue(3, entry.password);
mApp->dbWriter()->executeQuery(query);
}
void DatabasePasswordBackend::updateEntry(const PasswordEntry &entry)
{
QSqlQuery query;
// Data is empty only for HTTP/FTP authorization
if (entry.data.isEmpty()) {
QString server = entry.url.host();
if (server.isEmpty()) {
server = entry.url.toString();
}
query.prepare("UPDATE autofill SET username=?, password=? WHERE server=?");
query.bindValue(0, entry.username);
query.bindValue(1, entry.password);
query.bindValue(2, server);
}
else {
query.prepare("UPDATE autofill SET data=?, username=?, password=? WHERE id=?");
query.addBindValue(entry.data);
query.addBindValue(entry.username);
query.addBindValue(entry.password);
query.addBindValue(entry.id);
}
mApp->dbWriter()->executeQuery(query);
}
void DatabasePasswordBackend::updateLastUsed(const PasswordEntry &entry)
{
QSqlQuery query;
query.prepare("UPDATE autofill SET last_used=strftime('%s', 'now') WHERE id=?");
query.addBindValue(entry.id);
mApp->dbWriter()->executeQuery(query);
}

View File

@ -0,0 +1,35 @@
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2013 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#ifndef DATABASEPASSWORDBACKEND_H
#define DATABASEPASSWORDBACKEND_H
#include "passwordbackend.h"
class DatabasePasswordBackend : public PasswordBackend
{
public:
explicit DatabasePasswordBackend();
QVector<PasswordEntry> getEntries(const QUrl &url);
void addEntry(const PasswordEntry &entry);
void updateEntry(const PasswordEntry &entry);
void updateLastUsed(const PasswordEntry &entry);
};
#endif // DATABASEPASSWORDBACKEND_H

View File

@ -0,0 +1,36 @@
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2013 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#ifndef PASSWORDBACKEND_H
#define PASSWORDBACKEND_H
#include "passwordmanager.h"
class PasswordBackend
{
public:
explicit PasswordBackend() { }
virtual ~PasswordBackend() { }
virtual QVector<PasswordEntry> getEntries(const QUrl &url) = 0;
virtual void addEntry(const PasswordEntry &entry) = 0;
virtual void updateEntry(const PasswordEntry &entry) = 0;
virtual void updateLastUsed(const PasswordEntry &entry) = 0;
};
#endif // PASSWORDBACKEND_H

View File

@ -37,7 +37,7 @@ PageFormData PageFormCompleter::extractFormData(const QByteArray &postData) cons
QString passwordValue; QString passwordValue;
QByteArray data = convertWebKitFormBoundaryIfNecessary(postData); QByteArray data = convertWebKitFormBoundaryIfNecessary(postData);
PageFormData formData = {false, QString(), QString(), data}; PageFormData formData = {QString(), QString(), data};
if (data.isEmpty() || !data.contains('=')) { if (data.isEmpty() || !data.contains('=')) {
return formData; return formData;
@ -83,7 +83,6 @@ PageFormData PageFormCompleter::extractFormData(const QByteArray &postData) cons
return formData; return formData;
} }
formData.found = true;
formData.username = usernameValue; formData.username = usernameValue;
formData.password = passwordValue; formData.password = passwordValue;

View File

@ -29,10 +29,13 @@ class QWebElement;
class QWebElementCollection; class QWebElementCollection;
struct PageFormData { struct PageFormData {
bool found;
QString username; QString username;
QString password; QString password;
QByteArray postData; QByteArray postData;
bool isValid() const {
return !password.isEmpty();
}
}; };
class PageFormCompleter class PageFormCompleter

View File

@ -0,0 +1,95 @@
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2013 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "passwordmanager.h"
#include "backends/passwordbackend.h"
#include "backends/databasepasswordbackend.h"
#include "settings.h"
#include <QVector>
PasswordManager::PasswordManager(QObject* parent)
: QObject(parent)
, m_backend(0)
, m_loaded(false)
, m_databaseBackend(new DatabasePasswordBackend)
{
m_backends["database"] = m_databaseBackend;
}
void PasswordManager::loadSettings()
{
Settings settings;
settings.beginGroup("PasswordManager");
QString backendId = settings.value("Backend", "database").toString();
settings.endGroup();
m_backend = m_backends[m_backends.contains(backendId) ? backendId : "database"];
}
QVector<PasswordEntry> PasswordManager::getEntries(const QUrl &url)
{
ensureLoaded();
return m_backend->getEntries(url);
}
void PasswordManager::addEntry(const PasswordEntry &entry)
{
ensureLoaded();
m_backend->addEntry(entry);
}
void PasswordManager::updateEntry(const PasswordEntry &entry)
{
ensureLoaded();
m_backend->updateEntry(entry);
}
void PasswordManager::updateLastUsed(const PasswordEntry &entry)
{
ensureLoaded();
m_backend->updateLastUsed(entry);
}
bool PasswordManager::registerBackend(const QString &id, PasswordBackend* backend)
{
if (m_backends.contains(id)) {
return false;
}
m_backends[id] = backend;
return true;
}
void PasswordManager::unregisterBackend(PasswordBackend* backend)
{
const QString &key = m_backends.key(backend);
m_backends.remove(key);
}
void PasswordManager::ensureLoaded()
{
if (!m_loaded) {
loadSettings();
m_loaded = true;
}
}
PasswordManager::~PasswordManager()
{
delete m_databaseBackend;
}

View File

@ -0,0 +1,74 @@
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2013 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#ifndef PASSWORDMANAGER_H
#define PASSWORDMANAGER_H
#include <QObject>
#include <QUrl>
#include <QVariant>
#include "qz_namespace.h"
class PasswordBackend;
class DatabasePasswordBackend;
struct PasswordEntry {
QVariant id;
QUrl url;
QString username;
QString password;
QByteArray data;
bool isValid() const {
return !password.isEmpty();
}
};
class QT_QUPZILLA_EXPORT PasswordManager : public QObject
{
Q_OBJECT
public:
explicit PasswordManager(QObject* parent = 0);
~PasswordManager();
void loadSettings();
QVector<PasswordEntry> getEntries(const QUrl &url);
void addEntry(const PasswordEntry &entry);
void updateEntry(const PasswordEntry &entry);
void updateLastUsed(const PasswordEntry &entry);
bool registerBackend(const QString &id, PasswordBackend* backend);
void unregisterBackend(PasswordBackend* backend);
private:
void ensureLoaded();
PasswordBackend* m_backend;
bool m_loaded;
DatabasePasswordBackend* m_databaseBackend;
QHash<QString, PasswordBackend*> m_backends;
};
// Hint to QVector to use std::realloc on item moving
Q_DECLARE_TYPEINFO(PasswordEntry, Q_MOVABLE_TYPE);
#endif // PASSWORDMANAGER_H

View File

@ -215,7 +215,9 @@ SOURCES += \
tools/actioncopy.cpp \ tools/actioncopy.cpp \
network/pac/proxyautoconfig.cpp \ network/pac/proxyautoconfig.cpp \
network/pac/pacmanager.cpp \ network/pac/pacmanager.cpp \
tools/delayedfilewatcher.cpp tools/delayedfilewatcher.cpp \
autofill/passwordmanager.cpp \
autofill/backends/databasepasswordbackend.cpp
HEADERS += \ HEADERS += \
webview/tabpreview.h \ webview/tabpreview.h \
@ -391,7 +393,10 @@ HEADERS += \
network/pac/proxyautoconfig.h \ network/pac/proxyautoconfig.h \
network/pac/pacmanager.h \ network/pac/pacmanager.h \
network/pac/pacdatetime.h \ network/pac/pacdatetime.h \
tools/delayedfilewatcher.h tools/delayedfilewatcher.h \
autofill/passwordmanager.h \
autofill/backends/passwordbackend.h \
autofill/backends/databasepasswordbackend.h
FORMS += \ FORMS += \
preferences/autofillmanager.ui \ preferences/autofillmanager.ui \

View File

@ -30,6 +30,7 @@
#include "acceptlanguage.h" #include "acceptlanguage.h"
#include "cabundleupdater.h" #include "cabundleupdater.h"
#include "settings.h" #include "settings.h"
#include "passwordmanager.h"
#include "schemehandlers/adblockschemehandler.h" #include "schemehandlers/adblockschemehandler.h"
#include "schemehandlers/qupzillaschemehandler.h" #include "schemehandlers/qupzillaschemehandler.h"
#include "schemehandlers/fileschemehandler.h" #include "schemehandlers/fileschemehandler.h"
@ -291,13 +292,13 @@ void NetworkManager::authentication(QNetworkReply* reply, QAuthenticator* auth)
QString storedUser; QString storedUser;
QString storedPassword; QString storedPassword;
if (fill->isStored(reply->url())) { if (fill->isStored(reply->url())) {
const AutoFillData &data = fill->getFirstFormData(reply->url()); const QVector<PasswordEntry> &data = fill->getFormData(reply->url());
if (data.isValid()) { if (!data.isEmpty()) {
save->setChecked(true); save->setChecked(true);
shouldUpdateEntry = true; shouldUpdateEntry = true;
storedUser = data.username; storedUser = data.first().username;
storedPassword = data.password; storedPassword = data.first().password;
user->setText(storedUser); user->setText(storedUser);
pass->setText(storedPassword); pass->setText(storedPassword);
} }

View File

@ -27,6 +27,7 @@
#include "widget.h" #include "widget.h"
#include "qztools.h" #include "qztools.h"
#include "speeddial.h" #include "speeddial.h"
#include "autofill.h"
#include "popupwebpage.h" #include "popupwebpage.h"
#include "popupwebview.h" #include "popupwebview.h"
#include "networkmanagerproxy.h" #include "networkmanagerproxy.h"
@ -254,7 +255,7 @@ void WebPage::finished()
} }
// Autofill // Autofill
m_autoFillData = mApp->autoFill()->completePage(this); m_passwordEntries = mApp->autoFill()->completePage(this);
// AdBlock // AdBlock
cleanBlockedObjects(); cleanBlockedObjects();
@ -593,12 +594,12 @@ QVector<WebPage::AdBlockedEntry> WebPage::adBlockedEntries() const
bool WebPage::hasMultipleUsernames() const bool WebPage::hasMultipleUsernames() const
{ {
return m_autoFillData.count() > 1; return m_passwordEntries.count() > 1;
} }
QVector<AutoFillData> WebPage::autoFillData() const QVector<PasswordEntry> WebPage::autoFillData() const
{ {
return m_autoFillData; return m_passwordEntries;
} }
void WebPage::cleanBlockedObjects() void WebPage::cleanBlockedObjects()

View File

@ -23,7 +23,7 @@
#include <QVector> #include <QVector>
#include "qz_namespace.h" #include "qz_namespace.h"
#include "autofill.h" #include "passwordmanager.h"
class QWebSecurityOrigin; class QWebSecurityOrigin;
class QEventLoop; class QEventLoop;
@ -67,7 +67,7 @@ public:
QVector<AdBlockedEntry> adBlockedEntries() const; QVector<AdBlockedEntry> adBlockedEntries() const;
bool hasMultipleUsernames() const; bool hasMultipleUsernames() const;
QVector<AutoFillData> autoFillData() const; QVector<PasswordEntry> autoFillData() const;
void scheduleAdjustPage(); void scheduleAdjustPage();
bool isRunningLoop(); bool isRunningLoop();
@ -138,7 +138,7 @@ private:
QSslCertificate m_sslCert; QSslCertificate m_sslCert;
QVector<QSslCertificate> m_rejectedSslCerts; QVector<QSslCertificate> m_rejectedSslCerts;
QVector<AdBlockedEntry> m_adBlockedEntries; QVector<AdBlockedEntry> m_adBlockedEntries;
QVector<AutoFillData> m_autoFillData; QVector<PasswordEntry> m_passwordEntries;
QWebPage::NavigationType m_lastRequestType; QWebPage::NavigationType m_lastRequestType;
QUrl m_lastRequestUrl; QUrl m_lastRequestUrl;