1
mirror of https://invent.kde.org/network/falkon.git synced 2024-09-21 09:42:10 +02:00

PageFormCompleter: Improved detecting sent form.

Also added new test.
This commit is contained in:
nowrep 2013-01-26 11:09:25 +01:00
parent c1c1b4130e
commit 3caf5535cd
4 changed files with 56 additions and 41 deletions

View File

@ -20,6 +20,7 @@
#include <QWebPage>
#include <QWebFrame>
#include <QWebElement>
#include <QDebug>
PageFormCompleter::PageFormCompleter(QWebPage* page)
: m_page(page)
@ -39,6 +40,11 @@ PageFormData PageFormCompleter::extractFormData(const QByteArray &postData) cons
QByteArray data = convertWebKitFormBoundaryIfNecessary(postData);
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) */
QList<QWebFrame*> frames;
frames.append(m_page->mainFrame());
@ -48,13 +54,16 @@ PageFormData PageFormCompleter::extractFormData(const QByteArray &postData) cons
frames += frame->childFrames();
}
const QueryItems &queryItems = createQueryItems(data);
/* Find form that contains password value sent in data */
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");
passwordValue = getValueFromData(data, inputElement);
passwordValue = inputElement.evaluateJavaScript("this.value").toString();
if (!passwordValue.isEmpty() && dataContains(data, passwordName)) {
if (queryItemsContains(queryItems, passwordName, passwordValue)) {
foundForm = formElement;
break;
}
@ -79,9 +88,10 @@ PageFormData PageFormCompleter::extractFormData(const QByteArray &postData) cons
<< "input:not([type=\"hidden\"])";
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");
usernameValue = getValueFromData(data, element);
usernameValue = element.evaluateJavaScript("this.value").toString();
if (!usernameName.isEmpty() && !usernameValue.isEmpty()) {
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++) {
const QueryItem &item = queryItems.at(i);
if (item.first == attributeName) {
return !item.second.isEmpty();
return item.second == attributeValue;
}
}
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:

View File

@ -46,8 +46,8 @@ 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;
bool queryItemsContains(const QueryItems &queryItems, const QString &attributeName,
const QString &attributeValue) const;
QByteArray convertWebKitFormBoundaryIfNecessary(const QByteArray &data) const;
QueryItems createQueryItems(const QByteArray &data) const;

View File

@ -145,13 +145,14 @@ void FormCompleterTest::extractFormTest1()
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'>"
"<input id='id1' type='text' name='username' value='+ě ++ éí§`]|~đ11 +!:'>"
"<input id='id2' type='password' name='password' value='+ěš asn~đ°#&# |\€'>"
"<input id='id1' type='text' name='use¶ _namč' value='+ě ++ éí§`]|~đ11 +!:'>"
"<input id='id2' type='password' name='pA ]sQ +word' value='+ěš asn~đ°#&# |€'>"
"<input type='submit' value='submit' name='submit'>"
"</form>");
@ -159,7 +160,33 @@ void FormCompleterTest::extractFormTest2()
QVERIFY(form.found == true);
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)

View File

@ -40,6 +40,7 @@ private slots:
void extractFormTest1();
void extractFormTest2();
void extractFormTest3();
private:
void completeWithData(const QString &html, const QByteArray &data);