mirror of
https://invent.kde.org/network/falkon.git
synced 2024-12-20 02:36:34 +01:00
[Code] Renamed AutoFillModel + new class PageFormCompleter.
This commit is contained in:
parent
21d2c57dd8
commit
498f24add1
@ -1,6 +1,6 @@
|
||||
/* ============================================================
|
||||
* QupZilla - WebKit based browser
|
||||
* Copyright (C) 2010-2012 David Rosca <nowrep@gmail.com>
|
||||
* Copyright (C) 2010-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
|
||||
@ -30,7 +30,7 @@
|
||||
#include "pluginproxy.h"
|
||||
#include "bookmarksmodel.h"
|
||||
#include "downloadmanager.h"
|
||||
#include "autofillmodel.h"
|
||||
#include "autofill.h"
|
||||
#include "adblockmanager.h"
|
||||
#include "desktopnotificationsfactory.h"
|
||||
#include "iconprovider.h"
|
||||
@ -770,10 +770,10 @@ DownloadManager* MainApplication::downManager()
|
||||
return m_downloadManager;
|
||||
}
|
||||
|
||||
AutoFillModel* MainApplication::autoFill()
|
||||
AutoFill* MainApplication::autoFill()
|
||||
{
|
||||
if (!m_autofill) {
|
||||
m_autofill = new AutoFillModel(getWindow());
|
||||
m_autofill = new AutoFill(getWindow());
|
||||
}
|
||||
return m_autofill;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ============================================================
|
||||
* QupZilla - WebKit based browser
|
||||
* Copyright (C) 2010-2012 David Rosca <nowrep@gmail.com>
|
||||
* Copyright (C) 2010-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
|
||||
@ -42,7 +42,7 @@ class Updater;
|
||||
class PluginProxy;
|
||||
class BookmarksModel;
|
||||
class DownloadManager;
|
||||
class AutoFillModel;
|
||||
class AutoFill;
|
||||
class DesktopNotificationsFactory;
|
||||
class IconProvider;
|
||||
class SearchEnginesManager;
|
||||
@ -102,7 +102,7 @@ public:
|
||||
PluginProxy* plugins();
|
||||
BookmarksModel* bookmarksModel();
|
||||
DownloadManager* downManager();
|
||||
AutoFillModel* autoFill();
|
||||
AutoFill* autoFill();
|
||||
SearchEnginesManager* searchEnginesManager();
|
||||
QNetworkDiskCache* networkCache();
|
||||
DesktopNotificationsFactory* desktopNotifications();
|
||||
@ -157,7 +157,7 @@ private:
|
||||
PluginProxy* m_plugins;
|
||||
BookmarksModel* m_bookmarksModel;
|
||||
DownloadManager* m_downloadManager;
|
||||
AutoFillModel* m_autofill;
|
||||
AutoFill* m_autofill;
|
||||
QNetworkDiskCache* m_networkCache;
|
||||
DesktopNotificationsFactory* m_desktopNotifications;
|
||||
SearchEnginesManager* m_searchEnginesManager;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ============================================================
|
||||
* QupZilla - WebKit based browser
|
||||
* Copyright (C) 2010-2012 David Rosca <nowrep@gmail.com>
|
||||
* Copyright (C) 2010-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
|
||||
@ -37,7 +37,7 @@
|
||||
#include "siteinfo.h"
|
||||
#include "preferences.h"
|
||||
#include "networkmanager.h"
|
||||
#include "autofillmodel.h"
|
||||
#include "autofill.h"
|
||||
#include "networkmanagerproxy.h"
|
||||
#include "rssmanager.h"
|
||||
#include "mainapplication.h"
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ============================================================
|
||||
* QupZilla - WebKit based browser
|
||||
* Copyright (C) 2010-2012 David Rosca <nowrep@gmail.com>
|
||||
* Copyright (C) 2010-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
|
||||
@ -36,7 +36,7 @@ class TabbedWebView;
|
||||
class LineEdit;
|
||||
class SearchToolBar;
|
||||
class BookmarksToolbar;
|
||||
class AutoFillModel;
|
||||
class AutoFill;
|
||||
class MainApplication;
|
||||
class WebTab;
|
||||
class AdBlockIcon;
|
||||
|
@ -15,13 +15,14 @@
|
||||
* 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 "autofillmodel.h"
|
||||
#include "autofill.h"
|
||||
#include "qupzilla.h"
|
||||
#include "webpage.h"
|
||||
#include "tabbedwebview.h"
|
||||
#include "popupwebview.h"
|
||||
#include "mainapplication.h"
|
||||
#include "autofillnotification.h"
|
||||
#include "pageformcompleter.h"
|
||||
#include "databasewriter.h"
|
||||
#include "settings.h"
|
||||
|
||||
@ -34,7 +35,7 @@
|
||||
#include <QUrlQuery>
|
||||
#endif
|
||||
|
||||
AutoFillModel::AutoFillModel(QupZilla* mainClass, QObject* parent)
|
||||
AutoFill::AutoFill(QupZilla* mainClass, QObject* parent)
|
||||
: QObject(parent)
|
||||
, p_QupZilla(mainClass)
|
||||
, m_isStoring(false)
|
||||
@ -42,7 +43,7 @@ AutoFillModel::AutoFillModel(QupZilla* mainClass, QObject* parent)
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
void AutoFillModel::loadSettings()
|
||||
void AutoFill::loadSettings()
|
||||
{
|
||||
Settings settings;
|
||||
settings.beginGroup("Web-Browser-Settings");
|
||||
@ -50,7 +51,7 @@ void AutoFillModel::loadSettings()
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
bool AutoFillModel::isStored(const QUrl &url)
|
||||
bool AutoFill::isStored(const QUrl &url)
|
||||
{
|
||||
if (!isStoringEnabled(url)) {
|
||||
return false;
|
||||
@ -73,7 +74,7 @@ bool AutoFillModel::isStored(const QUrl &url)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AutoFillModel::isStoringEnabled(const QUrl &url)
|
||||
bool AutoFill::isStoringEnabled(const QUrl &url)
|
||||
{
|
||||
if (!m_isStoring) {
|
||||
return false;
|
||||
@ -96,7 +97,7 @@ bool AutoFillModel::isStoringEnabled(const QUrl &url)
|
||||
return true;
|
||||
}
|
||||
|
||||
void AutoFillModel::blockStoringfor(const QUrl &url)
|
||||
void AutoFill::blockStoringfor(const QUrl &url)
|
||||
{
|
||||
QString server = url.host();
|
||||
if (server.isEmpty()) {
|
||||
@ -109,7 +110,7 @@ void AutoFillModel::blockStoringfor(const QUrl &url)
|
||||
mApp->dbWriter()->executeQuery(query);
|
||||
}
|
||||
|
||||
QString AutoFillModel::getUsername(const QUrl &url)
|
||||
QString AutoFill::getUsername(const QUrl &url)
|
||||
{
|
||||
QString server = url.host();
|
||||
if (server.isEmpty()) {
|
||||
@ -125,7 +126,7 @@ QString AutoFillModel::getUsername(const QUrl &url)
|
||||
return query.value(0).toString();
|
||||
}
|
||||
|
||||
QString AutoFillModel::getPassword(const QUrl &url)
|
||||
QString AutoFill::getPassword(const QUrl &url)
|
||||
{
|
||||
QString server = url.host();
|
||||
if (server.isEmpty()) {
|
||||
@ -142,7 +143,7 @@ QString AutoFillModel::getPassword(const QUrl &url)
|
||||
}
|
||||
|
||||
///HTTP Authorization
|
||||
void AutoFillModel::addEntry(const QUrl &url, const QString &name, const QString &pass)
|
||||
void AutoFill::addEntry(const QUrl &url, const QString &name, const QString &pass)
|
||||
{
|
||||
QSqlQuery query;
|
||||
query.prepare("SELECT username FROM autofill WHERE server=?");
|
||||
@ -166,7 +167,7 @@ void AutoFillModel::addEntry(const QUrl &url, const QString &name, const QString
|
||||
}
|
||||
|
||||
///WEB Form
|
||||
void AutoFillModel::addEntry(const QUrl &url, const QByteArray &data, const QString &user, const QString &pass)
|
||||
void AutoFill::addEntry(const QUrl &url, const PageFormData &formData)
|
||||
{
|
||||
QSqlQuery query;
|
||||
query.prepare("SELECT data FROM autofill WHERE server=?");
|
||||
@ -184,13 +185,13 @@ void AutoFillModel::addEntry(const QUrl &url, const QByteArray &data, const QStr
|
||||
|
||||
query.prepare("INSERT INTO autofill (server, data, username, password) VALUES (?,?,?,?)");
|
||||
query.bindValue(0, server);
|
||||
query.bindValue(1, data);
|
||||
query.bindValue(2, user);
|
||||
query.bindValue(3, pass);
|
||||
query.bindValue(1, formData.postData);
|
||||
query.bindValue(2, formData.username);
|
||||
query.bindValue(3, formData.password);
|
||||
mApp->dbWriter()->executeQuery(query);
|
||||
}
|
||||
|
||||
void AutoFillModel::completePage(WebPage* page)
|
||||
void AutoFill::completePage(WebPage* page)
|
||||
{
|
||||
if (!page) {
|
||||
return;
|
||||
@ -201,15 +202,6 @@ void AutoFillModel::completePage(WebPage* page)
|
||||
return;
|
||||
}
|
||||
|
||||
QWebElementCollection inputs;
|
||||
QList<QWebFrame*> frames;
|
||||
frames.append(page->mainFrame());
|
||||
while (!frames.isEmpty()) {
|
||||
QWebFrame* frame = frames.takeFirst();
|
||||
inputs.append(frame->findAllElements("input"));
|
||||
frames += frame->childFrames();
|
||||
}
|
||||
|
||||
QString server = pageUrl.host();
|
||||
if (server.isEmpty()) {
|
||||
server = pageUrl.toString();
|
||||
@ -225,52 +217,17 @@ void AutoFillModel::completePage(WebPage* page)
|
||||
return;
|
||||
}
|
||||
|
||||
// Why not to use encodedQueryItems = QByteArrays ?
|
||||
// Because we need to filter "+" characters that must be spaces
|
||||
// (not real "+" characters "%2B")
|
||||
//
|
||||
// DO NOT TOUCH! It works now with both Qt 4 & Qt 5 ...
|
||||
#if QT_VERSION >= 0x050000
|
||||
QueryItems arguments = QUrlQuery(QUrl::fromEncoded("http://bla.com/?" + data)).queryItems();
|
||||
#else
|
||||
data.replace('+', ' ');
|
||||
QueryItems arguments = QUrl::fromEncoded("http://bla.com/?" + data).queryItems();
|
||||
#endif
|
||||
for (int i = 0; i < arguments.count(); i++) {
|
||||
QString key = arguments.at(i).first;
|
||||
QString value = arguments.at(i).second;
|
||||
#if QT_VERSION >= 0x050000
|
||||
key.replace(QLatin1Char('+'), QLatin1Char(' '));
|
||||
value.replace(QLatin1Char('+'), QLatin1Char(' '));
|
||||
#endif
|
||||
key = QUrl::fromEncoded(key.toUtf8()).toString();
|
||||
value = QUrl::fromEncoded(value.toUtf8()).toString();
|
||||
|
||||
for (int i = 0; i < inputs.count(); i++) {
|
||||
QWebElement element = inputs.at(i);
|
||||
const QString &typeAttr = element.attribute("type");
|
||||
|
||||
if (typeAttr != QLatin1String("text") && typeAttr != QLatin1String("password")
|
||||
&& typeAttr != QLatin1String("email") && !typeAttr.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key == element.attribute("name")) {
|
||||
element.setAttribute("value", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
PageFormCompleter completer(page);
|
||||
completer.completePage(data);
|
||||
}
|
||||
|
||||
void AutoFillModel::post(const QNetworkRequest &request, const QByteArray &outgoingData)
|
||||
void AutoFill::post(const QNetworkRequest &request, const QByteArray &outgoingData)
|
||||
{
|
||||
// Don't save in private browsing
|
||||
if (mApp->isPrivateSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QByteArray &data = convertWebKitFormBoundaryIfNecessary(outgoingData);
|
||||
|
||||
QVariant v = request.attribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 100));
|
||||
WebPage* webPage = static_cast<WebPage*>(v.value<void*>());
|
||||
if (!WebPage::isPointerSafeToUse(webPage)) {
|
||||
@ -281,6 +238,8 @@ void AutoFillModel::post(const QNetworkRequest &request, const QByteArray &outgo
|
||||
return;
|
||||
}
|
||||
|
||||
PageFormCompleter completer(webPage);
|
||||
|
||||
// v = request.attribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 101));
|
||||
// QWebPage::NavigationType type = (QWebPage::NavigationType)v.toInt();
|
||||
|
||||
@ -288,170 +247,18 @@ void AutoFillModel::post(const QNetworkRequest &request, const QByteArray &outgo
|
||||
// return;
|
||||
// }
|
||||
|
||||
QString usernameName;
|
||||
QString usernameValue;
|
||||
QString passwordName;
|
||||
QString passwordValue;
|
||||
|
||||
const QUrl &siteUrl = webPage->url();
|
||||
const PageFormData &formData = completer.extractFormData(outgoingData);
|
||||
|
||||
if (!isStoringEnabled(siteUrl)) {
|
||||
if (!isStoringEnabled(siteUrl) || isStored(siteUrl) || !formData.found) {
|
||||
return;
|
||||
}
|
||||
|
||||
QWebElementCollection allForms; // All form elements on page
|
||||
QWebElement foundForm; // Sent form element
|
||||
|
||||
QList<QWebFrame*> frames;
|
||||
frames.append(webPage->mainFrame()); // Find all form elements
|
||||
while (!frames.isEmpty()) {
|
||||
QWebFrame* frame = frames.takeFirst();
|
||||
allForms.append(frame->findAllElements("form"));
|
||||
frames += frame->childFrames();
|
||||
}
|
||||
|
||||
foreach(const QWebElement & formElement, allForms) {
|
||||
foreach(const QWebElement & inputElement, formElement.findAll("input[type=\"password\"]")) {
|
||||
passwordName = inputElement.attribute("name");
|
||||
passwordValue = getValueFromData(data, inputElement);
|
||||
|
||||
if (!passwordValue.isEmpty() && dataContains(data, passwordName)) {
|
||||
foundForm = formElement;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundForm.isNull()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Return if data for this page is already stored or no password element found in sent data
|
||||
if (foundForm.isNull() || isStored(siteUrl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to find username, we suppose that username is first not empty input[type=text] in form
|
||||
// Tell me better solution. Maybe first try to find name="user", name="username" ?
|
||||
|
||||
bool found = false;
|
||||
QStringList selectors;
|
||||
selectors << "input[type=\"text\"][name*=\"user\"]"
|
||||
<< "input[type=\"text\"][name*=\"name\"]"
|
||||
<< "input[type=\"text\"]"
|
||||
<< "input[type=\"email\"]"
|
||||
<< "input:not([type=\"hidden\"])";
|
||||
|
||||
foreach(const QString & selector, selectors) {
|
||||
foreach(const QWebElement & element, foundForm.findAll(selector)) {
|
||||
usernameName = element.attribute("name");
|
||||
usernameValue = getValueFromData(data, element);
|
||||
|
||||
if (!usernameName.isEmpty() && !usernameValue.isEmpty()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AutoFillNotification* aWidget = new AutoFillNotification(siteUrl, data, usernameValue, passwordValue);
|
||||
AutoFillNotification* aWidget = new AutoFillNotification(siteUrl, formData);
|
||||
webView->addNotification(aWidget);
|
||||
}
|
||||
|
||||
QString AutoFillModel::getValueFromData(const QByteArray &data, QWebElement element)
|
||||
{
|
||||
QString name = element.attribute("name");
|
||||
if (name.isEmpty()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString value = element.evaluateJavaScript("this.value").toString();
|
||||
if (value.isEmpty()) {
|
||||
#if QT_VERSION >= 0x050000
|
||||
QueryItems queryItems = QUrlQuery(QUrl::fromEncoded("http://a.b/?" + data)).queryItems();
|
||||
#else
|
||||
QueryItems queryItems = QUrl::fromEncoded("http://a.b/?" + data).queryItems();
|
||||
#endif
|
||||
for (int i = 0; i < queryItems.count(); i++) {
|
||||
QueryItem item = queryItems.at(i);
|
||||
|
||||
if (item.first == name) {
|
||||
value = item.second.toUtf8();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
QByteArray AutoFillModel::convertWebKitFormBoundaryIfNecessary(const QByteArray &data)
|
||||
{
|
||||
/* Sometimes, data are passed in this format:
|
||||
|
||||
------WebKitFormBoundary0bBp3bFMdGwqanMp
|
||||
Content-Disposition: form-data; name="name-of-attribute"
|
||||
|
||||
value-of-attribute
|
||||
------WebKitFormBoundary0bBp3bFMdGwqanMp--
|
||||
|
||||
So this function converts this format into url
|
||||
*/
|
||||
|
||||
if (!data.contains(QByteArray("------WebKitFormBoundary"))) {
|
||||
return data;
|
||||
}
|
||||
|
||||
QByteArray formatedData;
|
||||
QRegExp rx("name=\"(.*)------WebKitFormBoundary");
|
||||
rx.setMinimal(true);
|
||||
|
||||
int pos = 0;
|
||||
while ((pos = rx.indexIn(data, pos)) != -1) {
|
||||
QString string = rx.cap(1);
|
||||
pos += rx.matchedLength();
|
||||
|
||||
int endOfAttributeName = string.indexOf(QLatin1Char('"'));
|
||||
if (endOfAttributeName == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString attrName = string.left(endOfAttributeName);
|
||||
QString attrValue = string.mid(endOfAttributeName + 1).trimmed().remove(QLatin1Char('\n'));
|
||||
|
||||
if (attrName.isEmpty() || attrValue.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
formatedData.append(attrName + "=" + attrValue + "&");
|
||||
}
|
||||
|
||||
return formatedData;
|
||||
}
|
||||
|
||||
bool AutoFillModel::dataContains(const QByteArray &data, const QString &attributeName)
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
QueryItems queryItems = QUrlQuery(QUrl::fromEncoded("http://a.b/?" + data)).queryItems();
|
||||
#else
|
||||
QueryItems queryItems = QUrl::fromEncoded("http://a.b/?" + data).queryItems();
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < queryItems.count(); i++) {
|
||||
QueryItem item = queryItems.at(i);
|
||||
|
||||
if (item.first == attributeName) {
|
||||
return !item.second.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray AutoFillModel::exportPasswords()
|
||||
QByteArray AutoFill::exportPasswords()
|
||||
{
|
||||
QByteArray output;
|
||||
|
||||
@ -487,7 +294,7 @@ QByteArray AutoFillModel::exportPasswords()
|
||||
return output;
|
||||
}
|
||||
|
||||
bool AutoFillModel::importPasswords(const QByteArray &data)
|
||||
bool AutoFill::importPasswords(const QByteArray &data)
|
||||
{
|
||||
QSqlDatabase db = QSqlDatabase::database();
|
||||
db.transaction();
|
@ -1,6 +1,6 @@
|
||||
/* ============================================================
|
||||
* QupZilla - WebKit based browser
|
||||
* Copyright (C) 2010-2012 David Rosca <nowrep@gmail.com>
|
||||
* Copyright (C) 2010-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
|
||||
@ -29,14 +29,12 @@ class QNetworkRequest;
|
||||
|
||||
class QupZilla;
|
||||
class WebPage;
|
||||
struct PageFormData;
|
||||
|
||||
class QT_QUPZILLA_EXPORT AutoFillModel : public QObject
|
||||
class QT_QUPZILLA_EXPORT AutoFill : public QObject
|
||||
{
|
||||
public:
|
||||
typedef QPair<QString, QString> QueryItem;
|
||||
typedef QList<QPair<QString, QString> > QueryItems;
|
||||
|
||||
explicit AutoFillModel(QupZilla* mainClass, QObject* parent = 0);
|
||||
explicit AutoFill(QupZilla* mainClass, QObject* parent = 0);
|
||||
|
||||
void loadSettings();
|
||||
|
||||
@ -47,7 +45,7 @@ public:
|
||||
QString getUsername(const QUrl &url);
|
||||
QString getPassword(const QUrl &url);
|
||||
void addEntry(const QUrl &url, const QString &name, const QString &pass);
|
||||
void addEntry(const QUrl &url, const QByteArray &data, const QString &user, const QString &pass);
|
||||
void addEntry(const QUrl &url, const PageFormData &formData);
|
||||
|
||||
void post(const QNetworkRequest &request, const QByteArray &outgoingData);
|
||||
void completePage(WebPage* frame);
|
||||
@ -56,10 +54,6 @@ public:
|
||||
static bool importPasswords(const QByteArray &data);
|
||||
|
||||
private:
|
||||
bool dataContains(const QByteArray &data, const QString &attributeName);
|
||||
QString getValueFromData(const QByteArray &data, QWebElement element);
|
||||
QByteArray convertWebKitFormBoundaryIfNecessary(const QByteArray &data);
|
||||
|
||||
QupZilla* p_QupZilla;
|
||||
bool m_isStoring;
|
||||
|
@ -17,18 +17,16 @@
|
||||
* ============================================================ */
|
||||
#include "autofillnotification.h"
|
||||
#include "ui_autofillnotification.h"
|
||||
#include "autofillmodel.h"
|
||||
#include "autofill.h"
|
||||
#include "mainapplication.h"
|
||||
#include "animatedwidget.h"
|
||||
#include "iconprovider.h"
|
||||
|
||||
AutoFillNotification::AutoFillNotification(const QUrl &url, const QByteArray &data, const QString &user, const QString &pass, QWidget* parent)
|
||||
: AnimatedWidget(AnimatedWidget::Down, 300, parent)
|
||||
AutoFillNotification::AutoFillNotification(const QUrl &url, const PageFormData &formData)
|
||||
: AnimatedWidget(AnimatedWidget::Down, 300, 0)
|
||||
, ui(new Ui::AutoFillWidget)
|
||||
, m_url(url)
|
||||
, m_data(data)
|
||||
, m_user(user)
|
||||
, m_pass(pass)
|
||||
, m_formData(formData)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
ui->setupUi(widget());
|
||||
@ -41,8 +39,8 @@ AutoFillNotification::AutoFillNotification(const QUrl &url, const QByteArray &da
|
||||
hostPart = tr("on %1").arg(url.host());
|
||||
}
|
||||
|
||||
if (!user.isEmpty()) {
|
||||
userPart = tr("for <b>%1</b>").arg(user);
|
||||
if (!m_formData.username.isEmpty()) {
|
||||
userPart = tr("for <b>%1</b>").arg(m_formData.username);
|
||||
}
|
||||
|
||||
ui->label->setText(tr("Do you want QupZilla to remember the password %1 %2?").arg(userPart, hostPart));
|
||||
@ -63,7 +61,7 @@ void AutoFillNotification::never()
|
||||
|
||||
void AutoFillNotification::remember()
|
||||
{
|
||||
mApp->autoFill()->addEntry(m_url, m_data, m_user, m_pass);
|
||||
mApp->autoFill()->addEntry(m_url, m_formData);
|
||||
hide();
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ============================================================
|
||||
* QupZilla - WebKit based browser
|
||||
* Copyright (C) 2010-2012 David Rosca <nowrep@gmail.com>
|
||||
* Copyright (C) 2010-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
|
||||
@ -22,6 +22,7 @@
|
||||
|
||||
#include "qz_namespace.h"
|
||||
#include "animatedwidget.h"
|
||||
#include "pageformcompleter.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
@ -29,12 +30,13 @@ class AutoFillWidget;
|
||||
}
|
||||
|
||||
class AnimatedWidget;
|
||||
|
||||
class QT_QUPZILLA_EXPORT AutoFillNotification : public AnimatedWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AutoFillNotification(const QUrl &url, const QByteArray &data, const QString &user, const QString &pass, QWidget* parent = 0);
|
||||
explicit AutoFillNotification(const QUrl &url, const PageFormData &formData);
|
||||
~AutoFillNotification();
|
||||
|
||||
private slots:
|
||||
@ -43,10 +45,9 @@ private slots:
|
||||
|
||||
private:
|
||||
Ui::AutoFillWidget* ui;
|
||||
|
||||
QUrl m_url;
|
||||
QByteArray m_data;
|
||||
QString m_user;
|
||||
QString m_pass;
|
||||
PageFormData m_formData;
|
||||
};
|
||||
|
||||
#endif // AUTOFILLWIDGET_H
|
||||
|
259
src/lib/autofill/pageformcompleter.cpp
Normal file
259
src/lib/autofill/pageformcompleter.cpp
Normal file
@ -0,0 +1,259 @@
|
||||
/* ============================================================
|
||||
* 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 "pageformcompleter.h"
|
||||
|
||||
#include <QWebPage>
|
||||
#include <QWebFrame>
|
||||
#include <QWebElement>
|
||||
|
||||
PageFormCompleter::PageFormCompleter(QWebPage* page)
|
||||
: m_page(page)
|
||||
{
|
||||
}
|
||||
|
||||
PageFormData PageFormCompleter::extractFormData(const QByteArray &postData) const
|
||||
{
|
||||
QString usernameName;
|
||||
QString usernameValue;
|
||||
QString passwordName;
|
||||
QString passwordValue;
|
||||
|
||||
QWebElementCollection allForms;
|
||||
QWebElement foundForm;
|
||||
|
||||
QByteArray data = convertWebKitFormBoundaryIfNecessary(postData);
|
||||
PageFormData formData = {false, QString(), QString(), data};
|
||||
|
||||
/* Find all form elements in page (in all frames) */
|
||||
QList<QWebFrame*> frames;
|
||||
frames.append(m_page->mainFrame());
|
||||
while (!frames.isEmpty()) {
|
||||
QWebFrame* frame = frames.takeFirst();
|
||||
allForms.append(frame->findAllElements("form"));
|
||||
frames += frame->childFrames();
|
||||
}
|
||||
|
||||
/* Find form that contains password value sent in data */
|
||||
foreach(const QWebElement & formElement, allForms) {
|
||||
foreach(const QWebElement & inputElement, formElement.findAll("input[type=\"password\"]")) {
|
||||
passwordName = inputElement.attribute("name");
|
||||
passwordValue = getValueFromData(data, inputElement);
|
||||
|
||||
if (!passwordValue.isEmpty() && dataContains(data, passwordName)) {
|
||||
foundForm = formElement;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundForm.isNull()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundForm.isNull()) {
|
||||
return formData;
|
||||
}
|
||||
|
||||
/* Try to find username (or email) field in the form. */
|
||||
bool found = false;
|
||||
QStringList selectors;
|
||||
selectors << "input[type=\"text\"][name*=\"user\"]"
|
||||
<< "input[type=\"text\"][name*=\"name\"]"
|
||||
<< "input[type=\"text\"]"
|
||||
<< "input[type=\"email\"]"
|
||||
<< "input:not([type=\"hidden\"])";
|
||||
|
||||
foreach(const QString & selector, selectors) {
|
||||
foreach(const QWebElement & element, foundForm.findAll(selector)) {
|
||||
usernameName = element.attribute("name");
|
||||
usernameValue = getValueFromData(data, element);
|
||||
|
||||
if (!usernameName.isEmpty() && !usernameValue.isEmpty()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return formData;
|
||||
}
|
||||
|
||||
formData.found = true;
|
||||
formData.username = usernameValue;
|
||||
formData.password = passwordValue;
|
||||
|
||||
return formData;
|
||||
}
|
||||
|
||||
void PageFormCompleter::completePage(const QByteArray &data) const
|
||||
{
|
||||
const QueryItems &queryItems = createQueryItems(data);
|
||||
|
||||
/* Input types that are being completed */
|
||||
QStringList inputTypes;
|
||||
inputTypes << "text" << "password" << "email";
|
||||
|
||||
/* Find all input elements in the page */
|
||||
QWebElementCollection inputs;
|
||||
QList<QWebFrame*> frames;
|
||||
frames.append(m_page->mainFrame());
|
||||
while (!frames.isEmpty()) {
|
||||
QWebFrame* frame = frames.takeFirst();
|
||||
inputs.append(frame->findAllElements("input"));
|
||||
frames += frame->childFrames();
|
||||
}
|
||||
|
||||
for (int i = 0; i < queryItems.count(); i++) {
|
||||
const QString &key = queryItems.at(i).first;
|
||||
const QString &value = queryItems.at(i).second;
|
||||
|
||||
/* Is it really necessary?
|
||||
key = QUrl::fromEncoded(key.toUtf8()).toString();
|
||||
value = QUrl::fromEncoded(value.toUtf8()).toString();
|
||||
*/
|
||||
|
||||
for (int i = 0; i < inputs.count(); i++) {
|
||||
QWebElement element = inputs.at(i);
|
||||
const QString &typeAttr = element.attribute("type");
|
||||
|
||||
if (!inputTypes.contains(typeAttr) && !typeAttr.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key == element.attribute("name")) {
|
||||
element.setAttribute("value", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PageFormCompleter::dataContains(const QByteArray &data, const QString &attributeName) const
|
||||
{
|
||||
const QueryItems &queryItems = createQueryItems(data);
|
||||
|
||||
for (int i = 0; i < queryItems.count(); i++) {
|
||||
const QueryItem &item = queryItems.at(i);
|
||||
|
||||
if (item.first == attributeName) {
|
||||
return !item.second.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString PageFormCompleter::getValueFromData(const QByteArray &data, QWebElement element) const
|
||||
{
|
||||
QString name = element.attribute("name");
|
||||
if (name.isEmpty()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString value = element.evaluateJavaScript("this.value").toString();
|
||||
|
||||
if (!value.isEmpty()) {
|
||||
return value;
|
||||
}
|
||||
|
||||
const QueryItems &queryItems = createQueryItems(data);
|
||||
|
||||
for (int i = 0; i < queryItems.count(); i++) {
|
||||
const QueryItem &item = queryItems.at(i);
|
||||
|
||||
if (item.first == name) {
|
||||
value = item.second.toUtf8();
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
QByteArray PageFormCompleter::convertWebKitFormBoundaryIfNecessary(const QByteArray &data) const
|
||||
{
|
||||
/* Sometimes, data are passed in this format:
|
||||
*
|
||||
* ------WebKitFormBoundary0bBp3bFMdGwqanMp
|
||||
* Content-Disposition: form-data; name="name-of-attribute"
|
||||
*
|
||||
* value-of-attribute
|
||||
* ------WebKitFormBoundary0bBp3bFMdGwqanMp--
|
||||
*
|
||||
* So this function converts this format into name=value& format
|
||||
*/
|
||||
|
||||
if (!data.contains(QByteArray("------WebKitFormBoundary"))) {
|
||||
return data;
|
||||
}
|
||||
|
||||
QByteArray formatedData;
|
||||
QRegExp rx("name=\"(.*)------WebKitFormBoundary");
|
||||
rx.setMinimal(true);
|
||||
|
||||
int pos = 0;
|
||||
while ((pos = rx.indexIn(data, pos)) != -1) {
|
||||
QString string = rx.cap(1);
|
||||
pos += rx.matchedLength();
|
||||
|
||||
int endOfAttributeName = string.indexOf(QLatin1Char('"'));
|
||||
if (endOfAttributeName == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString attrName = string.left(endOfAttributeName);
|
||||
QString attrValue = string.mid(endOfAttributeName + 1).trimmed().remove(QLatin1Char('\n'));
|
||||
|
||||
if (attrName.isEmpty() || attrValue.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
formatedData.append(attrName + "=" + attrValue + "&");
|
||||
}
|
||||
|
||||
return formatedData;
|
||||
}
|
||||
|
||||
PageFormCompleter::QueryItems PageFormCompleter::createQueryItems(const QByteArray &data) const
|
||||
{
|
||||
/* Why not to use encodedQueryItems = QByteArrays ?
|
||||
* Because we need to filter "+" characters that must be spaces
|
||||
* (not real "+" characters "%2B")
|
||||
*
|
||||
* DO NOT TOUCH! It works now with both Qt 4 & Qt 5 ...
|
||||
*/
|
||||
#if QT_VERSION >= 0x050000
|
||||
QueryItems arguments = QUrlQuery(QUrl::fromEncoded("http://foo.com/?" + data)).queryItems();
|
||||
#else
|
||||
QByteArray dataCopy = data;
|
||||
dataCopy.replace('+', ' ');
|
||||
QueryItems arguments = QUrl::fromEncoded("http://foo.com/?" + dataCopy).queryItems();
|
||||
#endif
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
for (int i = 0; i < arguments.count(); i++) {
|
||||
arguments[i].first.replace(QLatin1Char('+'), QLatin1Char(' '));
|
||||
arguments[i].second.replace(QLatin1Char('+'), QLatin1Char(' '));
|
||||
}
|
||||
#endif
|
||||
|
||||
return arguments;
|
||||
}
|
57
src/lib/autofill/pageformcompleter.h
Normal file
57
src/lib/autofill/pageformcompleter.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* ============================================================
|
||||
* 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 PAGEFORMCOMPLETER_H
|
||||
#define PAGEFORMCOMPLETER_H
|
||||
|
||||
#include <QPair>
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
|
||||
#include "qz_namespace.h"
|
||||
|
||||
class QWebPage;
|
||||
class QWebElement;
|
||||
|
||||
struct PageFormData {
|
||||
bool found;
|
||||
QString username;
|
||||
QString password;
|
||||
QByteArray postData;
|
||||
};
|
||||
|
||||
class PageFormCompleter
|
||||
{
|
||||
public:
|
||||
explicit PageFormCompleter(QWebPage* page);
|
||||
|
||||
PageFormData extractFormData(const QByteArray &postData) const;
|
||||
void completePage(const QByteArray &data) const;
|
||||
|
||||
private:
|
||||
typedef QPair<QString, QString> QueryItem;
|
||||
typedef QList<QPair<QString, QString> > QueryItems;
|
||||
|
||||
bool dataContains(const QByteArray &data, const QString &attributeName) const;
|
||||
QString getValueFromData(const QByteArray &data, QWebElement element) const;
|
||||
QByteArray convertWebKitFormBoundaryIfNecessary(const QByteArray &data) const;
|
||||
QueryItems createQueryItems(const QByteArray &data) const;
|
||||
|
||||
QWebPage* m_page;
|
||||
};
|
||||
|
||||
#endif // PAGEFORMCOMPLETER_H
|
@ -48,7 +48,6 @@ SOURCES += \
|
||||
app/qupzilla.cpp \
|
||||
app/mainapplication.cpp \
|
||||
app/autosaver.cpp \
|
||||
autofill/autofillmodel.cpp \
|
||||
preferences/autofillmanager.cpp \
|
||||
bookmarks/bookmarkstoolbar.cpp \
|
||||
bookmarks/bookmarksmanager.cpp \
|
||||
@ -199,7 +198,9 @@ SOURCES += \
|
||||
tools/listitemdelegate.cpp \
|
||||
bookmarks/bookmarkstree.cpp \
|
||||
tools/html5permissions/html5permissionsmanager.cpp \
|
||||
tools/html5permissions/html5permissionsnotification.cpp
|
||||
tools/html5permissions/html5permissionsnotification.cpp \
|
||||
autofill/pageformcompleter.cpp \
|
||||
autofill/autofill.cpp
|
||||
|
||||
HEADERS += \
|
||||
webview/tabpreview.h \
|
||||
@ -208,7 +209,6 @@ HEADERS += \
|
||||
app/qupzilla.h \
|
||||
app/mainapplication.h \
|
||||
app/autosaver.h \
|
||||
autofill/autofillmodel.h \
|
||||
preferences/autofillmanager.h \
|
||||
bookmarks/bookmarkstoolbar.h \
|
||||
bookmarks/bookmarksmanager.h \
|
||||
@ -361,7 +361,9 @@ HEADERS += \
|
||||
tools/listitemdelegate.h \
|
||||
bookmarks/bookmarkstree.h \
|
||||
tools/html5permissions/html5permissionsmanager.h \
|
||||
tools/html5permissions/html5permissionsnotification.h
|
||||
tools/html5permissions/html5permissionsnotification.h \
|
||||
autofill/pageformcompleter.h \
|
||||
autofill/autofill.h
|
||||
|
||||
FORMS += \
|
||||
preferences/autofillmanager.ui \
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ============================================================
|
||||
* QupZilla - WebKit based browser
|
||||
* Copyright (C) 2010-2012 David Rosca <nowrep@gmail.com>
|
||||
* Copyright (C) 2010-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
|
||||
@ -17,7 +17,7 @@
|
||||
* ============================================================ */
|
||||
#include "networkmanager.h"
|
||||
#include "qupzilla.h"
|
||||
#include "autofillmodel.h"
|
||||
#include "autofill.h"
|
||||
#include "networkmanagerproxy.h"
|
||||
#include "mainapplication.h"
|
||||
#include "webpage.h"
|
||||
@ -281,7 +281,7 @@ void NetworkManager::authentication(QNetworkReply* reply, QAuthenticator* auth)
|
||||
formLa->addRow(save);
|
||||
|
||||
formLa->addWidget(box);
|
||||
AutoFillModel* fill = mApp->autoFill();
|
||||
AutoFill* fill = mApp->autoFill();
|
||||
if (fill->isStored(reply->url())) {
|
||||
save->setChecked(true);
|
||||
user->setText(fill->getUsername(reply->url()));
|
||||
|
@ -62,7 +62,8 @@ void PopupWebPage::slotGeometryChangeRequested(const QRect &rect)
|
||||
*/
|
||||
|
||||
if (rect.isValid()
|
||||
#if QTWEBKIT_FROM_2_3
|
||||
//#if QTWEBKIT_FROM_2_3
|
||||
#if 0
|
||||
&& rect.size() != QSize(100, 100)
|
||||
#endif
|
||||
) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ============================================================
|
||||
* QupZilla - WebKit based browser
|
||||
* Copyright (C) 2010-2012 David Rosca <nowrep@gmail.com>
|
||||
* Copyright (C) 2010-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
|
||||
@ -16,7 +16,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* ============================================================ */
|
||||
#include "autofillmanager.h"
|
||||
#include "autofillmodel.h"
|
||||
#include "autofill.h"
|
||||
#include "ui_autofillmanager.h"
|
||||
|
||||
#include <QMenu>
|
||||
@ -224,7 +224,7 @@ void AutoFillManager::importPasswords()
|
||||
return;
|
||||
}
|
||||
|
||||
bool status = AutoFillModel::importPasswords(file.readAll());
|
||||
bool status = AutoFill::importPasswords(file.readAll());
|
||||
file.close();
|
||||
|
||||
ui->importExportLabel->setText(status ? tr("Successfully imported") : tr("Error while importing!"));
|
||||
@ -244,7 +244,7 @@ void AutoFillManager::exportPasswords()
|
||||
return;
|
||||
}
|
||||
|
||||
file.write(AutoFillModel::exportPasswords());
|
||||
file.write(AutoFill::exportPasswords());
|
||||
file.close();
|
||||
|
||||
ui->importExportLabel->setText(tr("Successfully exported"));
|
||||
|
@ -39,7 +39,7 @@
|
||||
#include "thememanager.h"
|
||||
#include "acceptlanguage.h"
|
||||
#include "qztools.h"
|
||||
#include "autofillmodel.h"
|
||||
#include "autofill.h"
|
||||
#include "settings.h"
|
||||
#include "tabbedwebview.h"
|
||||
#include "clearprivatedata.h"
|
||||
|
@ -198,7 +198,7 @@ QString QzTools::getFileNameFromUrl(const QUrl &url)
|
||||
QString fileName = url.toString(QUrl::RemoveFragment | QUrl::RemoveQuery | QUrl::RemoveScheme | QUrl::RemovePort);
|
||||
|
||||
if (fileName.endsWith(QLatin1Char('/'))) {
|
||||
fileName = fileName.mid(0, fileName.length() - 1);
|
||||
fileName = fileName.mid(0, fileName.length() - 1);
|
||||
}
|
||||
|
||||
if (fileName.indexOf(QLatin1Char('/')) != -1) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ============================================================
|
||||
* QupZilla - WebKit based browser
|
||||
* Copyright (C) 2010-2012 David Rosca <nowrep@gmail.com>
|
||||
* Copyright (C) 2010-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
|
||||
@ -22,7 +22,7 @@
|
||||
#include "qztools.h"
|
||||
#include "iconprovider.h"
|
||||
#include "history.h"
|
||||
#include "autofillmodel.h"
|
||||
#include "autofill.h"
|
||||
#include "pluginproxy.h"
|
||||
#include "downloadmanager.h"
|
||||
#include "sourceviewer.h"
|
||||
|
Loading…
Reference in New Issue
Block a user