diff --git a/CHANGELOG b/CHANGELOG index 088b204c7..b967b4839 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,6 +4,7 @@ Version 1.4.0 * can now be compiled using Qt 5 * QtWebKit 2.3 new features - caret browsing, animated scrolling * added support for FTP listing files and downloading + * added support for saving passwords of multiple users per site * asking user whether to allow site to use notifications/geolocation * option to set JavaScript privacy permissions * option to specify default search engine used in locationbar diff --git a/src/lib/autofill/autofill.cpp b/src/lib/autofill/autofill.cpp index e1dea2211..053aa5e83 100644 --- a/src/lib/autofill/autofill.cpp +++ b/src/lib/autofill/autofill.cpp @@ -110,7 +110,21 @@ void AutoFill::blockStoringforUrl(const QUrl &url) mApp->dbWriter()->executeQuery(query); } -QList AutoFill::getFormData(const QUrl &url) +AutoFillData AutoFill::getFirstFormData(const QUrl &url) +{ + QList list = getFormData(url, 1); + + if (list.isEmpty()) { + AutoFillData data; + data.id = -1; + + return data; + } + + return list.first(); +} + +QList AutoFill::getFormData(const QUrl &url, int limit) { QList list; @@ -119,10 +133,20 @@ QList AutoFill::getFormData(const QUrl &url) server = url.toString(); } + QString queryString = "SELECT id, username, password, data FROM autofill " + "WHERE server=? ORDER BY last_used DESC"; + if (limit > 0) { + queryString.append(QLatin1String(" LIMIT ?")); + } + QSqlQuery query; - query.prepare("SELECT id, username, password, data FROM autofill " - "WHERE server=? ORDER BY last_used DESC"); + query.prepare(queryString); query.addBindValue(server); + + if (limit > 0) { + query.addBindValue(limit); + } + query.exec(); while (query.next()) { @@ -136,6 +160,7 @@ QList AutoFill::getFormData(const QUrl &url) } return list; + } void AutoFill::updateLastUsed(int id) @@ -224,27 +249,15 @@ void AutoFill::updateEntry(const QUrl &url, const QString &name, const QString & mApp->dbWriter()->executeQuery(query); } -void AutoFill::updateEntry(const QUrl &url, const PageFormData &formData) +void AutoFill::updateEntry(const PageFormData &formData, const AutoFillData &updateData) { QSqlQuery query; - QString server = url.host(); - if (server.isEmpty()) { - server = url.toString(); - } - - query.prepare("SELECT data FROM autofill WHERE server=?"); - query.addBindValue(server); - query.exec(); - - if (!query.next()) { - return; - } - - query.prepare("UPDATE autofill SET data=?, username=?, password=? WHERE server=?"); + query.prepare("UPDATE autofill SET data=?, username=?, password=? WHERE id=?"); query.addBindValue(formData.postData); query.addBindValue(formData.username); query.addBindValue(formData.password); - query.addBindValue(server); + query.addBindValue(updateData.id); + mApp->dbWriter()->executeQuery(query); } @@ -259,23 +272,12 @@ void AutoFill::completePage(WebPage* page) return; } - QString server = pageUrl.host(); - if (server.isEmpty()) { - server = pageUrl.toString(); - } + const AutoFillData data = getFirstFormData(pageUrl); - QSqlQuery query; - query.prepare("SELECT data FROM autofill WHERE server=?"); - query.addBindValue(server); - query.exec(); - query.next(); - QByteArray data = query.value(0).toByteArray(); - if (data.isEmpty()) { - return; + if (data.isValid()) { + PageFormCompleter completer(page); + completer.completePage(data.postData); } - - PageFormCompleter completer(page); - completer.completePage(data); } void AutoFill::post(const QNetworkRequest &request, const QByteArray &outgoingData) @@ -308,16 +310,23 @@ void AutoFill::post(const QNetworkRequest &request, const QByteArray &outgoingDa return; } - bool updateData = false; + AutoFillData updateData = { -1, QString(), QString(), QByteArray() }; + if (isStored(siteUrl)) { - const AutoFillData data = getFormData(siteUrl).first(); + const QList &list = getFormData(siteUrl); - if (data.username == formData.username && data.password == formData.password) { - updateLastUsed(data.id); - return; + foreach(const AutoFillData & data, list) { + if (data.username == formData.username) { + updateLastUsed(data.id); + + if (data.password == formData.password) { + return; + } + + updateData = data; + break; + } } - - updateData = true; } AutoFillNotification* aWidget = new AutoFillNotification(siteUrl, formData, updateData); diff --git a/src/lib/autofill/autofill.h b/src/lib/autofill/autofill.h index 2a87df807..c4bbc0476 100644 --- a/src/lib/autofill/autofill.h +++ b/src/lib/autofill/autofill.h @@ -36,6 +36,10 @@ struct AutoFillData { QString username; QString password; QByteArray postData; + + bool isValid() const { + return id > -1; + } }; class QT_QUPZILLA_EXPORT AutoFill : public QObject @@ -49,14 +53,16 @@ public: bool isStoringEnabled(const QUrl &url); void blockStoringforUrl(const QUrl &url); - QList getFormData(const QUrl &url); + AutoFillData getFirstFormData(const QUrl &url); + QList getFormData(const QUrl &url, int limit = 0); + void updateLastUsed(int id); void addEntry(const QUrl &url, const QString &name, const QString &pass); 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 PageFormData &formData); + void updateEntry(const PageFormData &formData, const AutoFillData &updateData); void post(const QNetworkRequest &request, const QByteArray &outgoingData); void completePage(WebPage* frame); diff --git a/src/lib/autofill/autofillnotification.cpp b/src/lib/autofill/autofillnotification.cpp index a6cdead24..67640da7b 100644 --- a/src/lib/autofill/autofillnotification.cpp +++ b/src/lib/autofill/autofillnotification.cpp @@ -22,12 +22,12 @@ #include "animatedwidget.h" #include "iconprovider.h" -AutoFillNotification::AutoFillNotification(const QUrl &url, const PageFormData &formData, bool updateData) +AutoFillNotification::AutoFillNotification(const QUrl &url, const PageFormData &formData, const AutoFillData &updateData) : AnimatedWidget(AnimatedWidget::Down, 300, 0) , ui(new Ui::AutoFillWidget) - , m_updateData(updateData) , m_url(url) , m_formData(formData) + , m_updateData(updateData) { setAttribute(Qt::WA_DeleteOnClose); ui->setupUi(widget()); @@ -44,8 +44,8 @@ AutoFillNotification::AutoFillNotification(const QUrl &url, const PageFormData & userPart = tr("for %1").arg(m_formData.username); } - if (updateData) { - ui->label->setText(tr("Do you want QupZilla to update saved password %1?").arg(hostPart)); + if (m_updateData.isValid()) { + ui->label->setText(tr("Do you want QupZilla to update saved password %1?").arg(userPart)); ui->remember->setVisible(false); ui->never->setVisible(false); @@ -67,7 +67,7 @@ AutoFillNotification::AutoFillNotification(const QUrl &url, const PageFormData & void AutoFillNotification::update() { - mApp->autoFill()->updateEntry(m_url, m_formData); + mApp->autoFill()->updateEntry(m_formData, m_updateData); hide(); } diff --git a/src/lib/autofill/autofillnotification.h b/src/lib/autofill/autofillnotification.h index 1cec5bfc4..0673626c9 100644 --- a/src/lib/autofill/autofillnotification.h +++ b/src/lib/autofill/autofillnotification.h @@ -23,6 +23,7 @@ #include "qz_namespace.h" #include "animatedwidget.h" #include "pageformcompleter.h" +#include "autofill.h" namespace Ui { @@ -37,7 +38,8 @@ class QT_QUPZILLA_EXPORT AutoFillNotification : public AnimatedWidget public: explicit AutoFillNotification(const QUrl &url, - const PageFormData &formData, bool updateData); + const PageFormData &formData, + const AutoFillData &updateData); ~AutoFillNotification(); private slots: @@ -48,9 +50,9 @@ private slots: private: Ui::AutoFillWidget* ui; - bool m_updateData; QUrl m_url; PageFormData m_formData; + AutoFillData m_updateData; }; #endif // AUTOFILLWIDGET_H diff --git a/src/lib/network/networkmanager.cpp b/src/lib/network/networkmanager.cpp index 77193af20..53b12222a 100644 --- a/src/lib/network/networkmanager.cpp +++ b/src/lib/network/networkmanager.cpp @@ -289,14 +289,16 @@ void NetworkManager::authentication(QNetworkReply* reply, QAuthenticator* auth) QString storedUser; QString storedPassword; if (fill->isStored(reply->url())) { - const AutoFillData &data = fill->getFormData(reply->url()).first(); + const AutoFillData &data = fill->getFirstFormData(reply->url()); - save->setChecked(true); - shouldUpdateEntry = true; - storedUser = data.username; - storedPassword = data.password; - user->setText(storedUser); - pass->setText(storedPassword); + if (data.isValid()) { + save->setChecked(true); + shouldUpdateEntry = true; + storedUser = data.username; + storedPassword = data.password; + user->setText(storedUser); + pass->setText(storedPassword); + } } emit wantsFocus(reply->url());