diff --git a/src/lib/autofill/pageformcompleter.cpp b/src/lib/autofill/pageformcompleter.cpp index 5cc5a30be..14c9c038a 100644 --- a/src/lib/autofill/pageformcompleter.cpp +++ b/src/lib/autofill/pageformcompleter.cpp @@ -20,6 +20,7 @@ #include #include #include +#include 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 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: diff --git a/src/lib/autofill/pageformcompleter.h b/src/lib/autofill/pageformcompleter.h index 0d8155151..6aad265e9 100644 --- a/src/lib/autofill/pageformcompleter.h +++ b/src/lib/autofill/pageformcompleter.h @@ -46,8 +46,8 @@ private: typedef QPair QueryItem; typedef QList > 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; diff --git a/tests/autotests/formcompletertest.cpp b/tests/autotests/formcompletertest.cpp index a31175f0a..a4d546ad1 100644 --- a/tests/autotests/formcompletertest.cpp +++ b/tests/autotests/formcompletertest.cpp @@ -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("
" - "" - "" + "" + "" "" "
"); @@ -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 = "
" + "" + "" + "" + "
"; + + QString html2 = "
" + "" + "" + "" + "
"; + + 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) diff --git a/tests/autotests/formcompletertest.h b/tests/autotests/formcompletertest.h index cc7060fb0..125483cf1 100644 --- a/tests/autotests/formcompletertest.h +++ b/tests/autotests/formcompletertest.h @@ -40,6 +40,7 @@ private slots: void extractFormTest1(); void extractFormTest2(); + void extractFormTest3(); private: void completeWithData(const QString &html, const QByteArray &data);