1
mirror of https://invent.kde.org/network/falkon.git synced 2024-11-11 01:22:10 +01:00

[Code] Renamed AutoFillModel + new class PageFormCompleter.

This commit is contained in:
nowrep 2013-01-24 17:47:50 +01:00
parent 21d2c57dd8
commit 498f24add1
17 changed files with 390 additions and 271 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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"

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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();
}

View File

@ -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

View 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;
}

View 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

View File

@ -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 \

View File

@ -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()));

View File

@ -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
) {

View File

@ -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"));

View File

@ -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"

View File

@ -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) {

View File

@ -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"