mirror of
https://invent.kde.org/network/falkon.git
synced 2024-12-20 10:46:35 +01:00
PageFormCompleter: Improved detecting sent form.
Also added new test.
This commit is contained in:
parent
c1c1b4130e
commit
3caf5535cd
@ -20,6 +20,7 @@
|
|||||||
#include <QWebPage>
|
#include <QWebPage>
|
||||||
#include <QWebFrame>
|
#include <QWebFrame>
|
||||||
#include <QWebElement>
|
#include <QWebElement>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
PageFormCompleter::PageFormCompleter(QWebPage* page)
|
PageFormCompleter::PageFormCompleter(QWebPage* page)
|
||||||
: m_page(page)
|
: m_page(page)
|
||||||
@ -39,6 +40,11 @@ PageFormData PageFormCompleter::extractFormData(const QByteArray &postData) cons
|
|||||||
QByteArray data = convertWebKitFormBoundaryIfNecessary(postData);
|
QByteArray data = convertWebKitFormBoundaryIfNecessary(postData);
|
||||||
PageFormData formData = {false, QString(), QString(), data};
|
PageFormData formData = {false, QString(), QString(), data};
|
||||||
|
|
||||||
|
if (!data.contains('=')) {
|
||||||
|
qDebug() << "PageFormCompleter: Invalid form data" << data;
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find all form elements in page (in all frames) */
|
/* Find all form elements in page (in all frames) */
|
||||||
QList<QWebFrame*> frames;
|
QList<QWebFrame*> frames;
|
||||||
frames.append(m_page->mainFrame());
|
frames.append(m_page->mainFrame());
|
||||||
@ -48,13 +54,16 @@ PageFormData PageFormCompleter::extractFormData(const QByteArray &postData) cons
|
|||||||
frames += frame->childFrames();
|
frames += frame->childFrames();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QueryItems &queryItems = createQueryItems(data);
|
||||||
|
|
||||||
/* Find form that contains password value sent in data */
|
/* Find form that contains password value sent in data */
|
||||||
foreach(const QWebElement & formElement, allForms) {
|
foreach(const QWebElement & formElement, allForms) {
|
||||||
foreach(const QWebElement & inputElement, formElement.findAll("input[type=\"password\"]")) {
|
const QWebElementCollection &inputs = formElement.findAll("input[type=\"password\"]");
|
||||||
|
foreach(QWebElement inputElement, inputs) {
|
||||||
passwordName = inputElement.attribute("name");
|
passwordName = inputElement.attribute("name");
|
||||||
passwordValue = getValueFromData(data, inputElement);
|
passwordValue = inputElement.evaluateJavaScript("this.value").toString();
|
||||||
|
|
||||||
if (!passwordValue.isEmpty() && dataContains(data, passwordName)) {
|
if (queryItemsContains(queryItems, passwordName, passwordValue)) {
|
||||||
foundForm = formElement;
|
foundForm = formElement;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -79,9 +88,10 @@ PageFormData PageFormCompleter::extractFormData(const QByteArray &postData) cons
|
|||||||
<< "input:not([type=\"hidden\"])";
|
<< "input:not([type=\"hidden\"])";
|
||||||
|
|
||||||
foreach(const QString & selector, selectors) {
|
foreach(const QString & selector, selectors) {
|
||||||
foreach(const QWebElement & element, foundForm.findAll(selector)) {
|
const QWebElementCollection &inputs = foundForm.findAll(selector);
|
||||||
|
foreach(QWebElement element, inputs) {
|
||||||
usernameName = element.attribute("name");
|
usernameName = element.attribute("name");
|
||||||
usernameValue = getValueFromData(data, element);
|
usernameValue = element.evaluateJavaScript("this.value").toString();
|
||||||
|
|
||||||
if (!usernameName.isEmpty() && !usernameValue.isEmpty()) {
|
if (!usernameName.isEmpty() && !usernameValue.isEmpty()) {
|
||||||
found = true;
|
found = true;
|
||||||
@ -147,47 +157,24 @@ void PageFormCompleter::completePage(const QByteArray &data) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PageFormCompleter::dataContains(const QByteArray &data, const QString &attributeName) const
|
bool PageFormCompleter::queryItemsContains(const QueryItems &queryItems, const QString &attributeName,
|
||||||
|
const QString &attributeValue) const
|
||||||
{
|
{
|
||||||
const QueryItems &queryItems = createQueryItems(data);
|
if (attributeName.isEmpty() || attributeValue.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < queryItems.count(); i++) {
|
for (int i = 0; i < queryItems.count(); i++) {
|
||||||
const QueryItem &item = queryItems.at(i);
|
const QueryItem &item = queryItems.at(i);
|
||||||
|
|
||||||
if (item.first == attributeName) {
|
if (item.first == attributeName) {
|
||||||
return !item.second.isEmpty();
|
return item.second == attributeValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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
|
QByteArray PageFormCompleter::convertWebKitFormBoundaryIfNecessary(const QByteArray &data) const
|
||||||
{
|
{
|
||||||
/* Sometimes, data are passed in this format:
|
/* Sometimes, data are passed in this format:
|
||||||
|
@ -46,8 +46,8 @@ private:
|
|||||||
typedef QPair<QString, QString> QueryItem;
|
typedef QPair<QString, QString> QueryItem;
|
||||||
typedef QList<QPair<QString, QString> > QueryItems;
|
typedef QList<QPair<QString, QString> > QueryItems;
|
||||||
|
|
||||||
bool dataContains(const QByteArray &data, const QString &attributeName) const;
|
bool queryItemsContains(const QueryItems &queryItems, const QString &attributeName,
|
||||||
QString getValueFromData(const QByteArray &data, QWebElement element) const;
|
const QString &attributeValue) const;
|
||||||
QByteArray convertWebKitFormBoundaryIfNecessary(const QByteArray &data) const;
|
QByteArray convertWebKitFormBoundaryIfNecessary(const QByteArray &data) const;
|
||||||
QueryItems createQueryItems(const QByteArray &data) const;
|
QueryItems createQueryItems(const QByteArray &data) const;
|
||||||
|
|
||||||
|
@ -145,13 +145,14 @@ void FormCompleterTest::extractFormTest1()
|
|||||||
|
|
||||||
void FormCompleterTest::extractFormTest2()
|
void FormCompleterTest::extractFormTest2()
|
||||||
{
|
{
|
||||||
// Test special characters
|
// Test special characters (even in input name)
|
||||||
|
|
||||||
QByteArray data = "username=tst_username&password=tst_password";
|
QByteArray data = "use%C2%B6+_nam%C4%8D=%2B%C4%9B+%2B%2B+%C3%A9%C3%AD%C2%A7%60%5D%7C%7E%C4%9111+%2B%21%3A"
|
||||||
|
"&pA+%5DsQ+%2Bword=%2B%C4%9B%C5%A1+asn%7E%C4%91%C2%B0%23%26%23+%7C%E2%82%AC";
|
||||||
|
|
||||||
QString html = QString::fromUtf8("<form name='form1' method='post' action='foo.php'>"
|
QString html = QString::fromUtf8("<form name='form1' method='post' action='foo.php'>"
|
||||||
"<input id='id1' type='text' name='username' value='+ě ++ éí§`]|~đ11 +!:'>"
|
"<input id='id1' type='text' name='use¶ _namč' value='+ě ++ éí§`]|~đ11 +!:'>"
|
||||||
"<input id='id2' type='password' name='password' value='+ěš asn~đ°#&# |\€'>"
|
"<input id='id2' type='password' name='pA ]sQ +word' value='+ěš asn~đ°#&# |€'>"
|
||||||
"<input type='submit' value='submit' name='submit'>"
|
"<input type='submit' value='submit' name='submit'>"
|
||||||
"</form>");
|
"</form>");
|
||||||
|
|
||||||
@ -159,7 +160,33 @@ void FormCompleterTest::extractFormTest2()
|
|||||||
|
|
||||||
QVERIFY(form.found == true);
|
QVERIFY(form.found == true);
|
||||||
QCOMPARE(form.username, QString::fromUtf8("+ě ++ éí§`]|~đ11 +!:"));
|
QCOMPARE(form.username, QString::fromUtf8("+ě ++ éí§`]|~đ11 +!:"));
|
||||||
QCOMPARE(form.password, QString::fromUtf8("+ěš asn~đ°#&# |\€"));
|
QCOMPARE(form.password, QString::fromUtf8("+ěš asn~đ°#&# |€"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FormCompleterTest::extractFormTest3()
|
||||||
|
{
|
||||||
|
// Test detecting sent form between 2 identical forms
|
||||||
|
// but only one form is filled with correct data
|
||||||
|
|
||||||
|
QByteArray data = "username=tst_username&password=tst_password";
|
||||||
|
|
||||||
|
QString html = "<form name='form1' method='post' action='foo.php'>"
|
||||||
|
"<input id='id1' type='text' name='username' value='wrong_username'>"
|
||||||
|
"<input id='id2' type='password' name='password' value='wrong_password'>"
|
||||||
|
"<input type='submit' value='submit' name='submit'>"
|
||||||
|
"</form>";
|
||||||
|
|
||||||
|
QString html2 = "<form name='form2' method='post' action='foo2.php'>"
|
||||||
|
"<input id='id3' type='text' name='username' value='tst_username'>"
|
||||||
|
"<input id='id4' type='password' name='password' value='tst_password'>"
|
||||||
|
"<input type='submit' value='submit' name='submit'>"
|
||||||
|
"</form>";
|
||||||
|
|
||||||
|
PageFormData form = extractFormData(html + html2, data);
|
||||||
|
|
||||||
|
QVERIFY(form.found == true);
|
||||||
|
QCOMPARE(form.username, QString("tst_username"));
|
||||||
|
QCOMPARE(form.password, QString("tst_password"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormCompleterTest::completeWithData(const QString &html, const QByteArray &data)
|
void FormCompleterTest::completeWithData(const QString &html, const QByteArray &data)
|
||||||
|
@ -40,6 +40,7 @@ private slots:
|
|||||||
|
|
||||||
void extractFormTest1();
|
void extractFormTest1();
|
||||||
void extractFormTest2();
|
void extractFormTest2();
|
||||||
|
void extractFormTest3();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void completeWithData(const QString &html, const QByteArray &data);
|
void completeWithData(const QString &html, const QByteArray &data);
|
||||||
|
Loading…
Reference in New Issue
Block a user