Skip to content

Commit

Permalink
QUrl: Test that we do correctly accept valid schemes
Browse files Browse the repository at this point in the history
... and reject invalid ones. There was one error: we accepted schemes
starting with pluses, dashes and dots.

Change-Id: Ie585843cfb684bc3b6e3fffd145cfe12227ec4ad
Reviewed-by: David Faure <[email protected]>
  • Loading branch information
thiagomacieira committed Jul 2, 2016
1 parent cf9b445 commit 4f3eb66
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 71 deletions.
10 changes: 6 additions & 4 deletions src/corelib/io/qurl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -978,10 +978,12 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro
needsLowercasing = i;
continue;
}
if (p[i] >= '0' && p[i] <= '9' && i > 0)
continue;
if (p[i] == '+' || p[i] == '-' || p[i] == '.')
continue;
if (i) {
if (p[i] >= '0' && p[i] <= '9')
continue;
if (p[i] == '+' || p[i] == '-' || p[i] == '.')
continue;
}

// found something else
// don't call setError needlessly:
Expand Down
162 changes: 95 additions & 67 deletions tests/auto/corelib/io/qurl/tst_qurl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ private slots:
void isValid();
void schemeValidator_data();
void schemeValidator();
void invalidSchemeValidator();
void setScheme_data();
void setScheme();
void strictParser_data();
void strictParser();
void tolerantParser();
Expand Down Expand Up @@ -2082,87 +2083,114 @@ void tst_QUrl::isValid()

void tst_QUrl::schemeValidator_data()
{
QTest::addColumn<QByteArray>("encodedUrl");
QTest::addColumn<QString>("input");
QTest::addColumn<bool>("result");
QTest::addColumn<QString>("toString");

QTest::newRow("empty") << QByteArray() << false << QString();

// ftp
QTest::newRow("ftp:") << QByteArray("ftp:") << true << QString("ftp:");
QTest::newRow("ftp://ftp.qt-project.org")
<< QByteArray("ftp://ftp.qt-project.org")
<< true << QString("ftp://ftp.qt-project.org");
QTest::newRow("ftp://ftp.qt-project.org/")
<< QByteArray("ftp://ftp.qt-project.org/")
<< true << QString("ftp://ftp.qt-project.org/");
QTest::newRow("ftp:/index.html")
<< QByteArray("ftp:/index.html")
<< false << QString();

// mailto
QTest::newRow("mailto:") << QByteArray("mailto:") << true << QString("mailto:");
QTest::newRow("mailto://smtp.trolltech.com/[email protected]")
<< QByteArray("mailto://smtp.trolltech.com/[email protected]") << false << QString();
QTest::newRow("mailto:") << QByteArray("mailto:") << true << QString("mailto:");
QTest::newRow("mailto:[email protected]")
<< QByteArray("mailto:[email protected]") << true << QString("mailto:[email protected]");
QTest::addColumn<QString>("scheme");

// file
QTest::newRow("file:") << QByteArray("file:/etc/passwd") << true << QString("file:///etc/passwd");
// scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )

QTest::newRow("empty") << QString() << false << QString();

// uncontroversial ones
QTest::newRow("ftp") << "ftp://ftp.example.com/" << true << "ftp";
QTest::newRow("http") << "http://www.example.com/" << true << "http";
QTest::newRow("mailto") << "mailto:[email protected]" << true << "mailto";
QTest::newRow("file-1slash") << "file:/etc/passwd" << true << "file";
QTest::newRow("file-2slashes") << "file://server/etc/passwd" << true << "file";
QTest::newRow("file-3slashes") << "file:///etc/passwd" << true << "file";

QTest::newRow("mailto+subject") << "mailto:[email protected]?subject=Hello%20World" << true << "mailto";
QTest::newRow("mailto+host") << "mailto://smtp.example.com/[email protected]" << true << "mailto";

// valid, but unexpected
QTest::newRow("ftp-nohost") << "ftp:/etc/passwd" << true << "ftp";
QTest::newRow("http-nohost") << "http:/etc/passwd" << true << "http";
QTest::newRow("mailto-nomail") << "mailto://smtp.example.com" << true << "mailto";

// schemes with numbers
QTest::newRow("digits") << "proto2://" << true << "proto2";

// schemes with dots, dashes, and pluses
QTest::newRow("svn+ssh") << "svn+ssh://svn.example.com" << true << "svn+ssh";
QTest::newRow("withdash") << "svn-ssh://svn.example.com" << true << "svn-ssh";
QTest::newRow("withdots") << "org.qt-project://qt-project.org" << true << "org.qt-project";

// lowercasing
QTest::newRow("FTP") << "FTP://ftp.example.com/" << true << "ftp";
QTest::newRow("HTTP") << "HTTP://www.example.com/" << true << "http";
QTest::newRow("MAILTO") << "MAILTO:[email protected]" << true << "mailto";
QTest::newRow("FILE") << "FILE:/etc/passwd" << true << "file";
QTest::newRow("SVN+SSH") << "SVN+SSH://svn.example.com" << true << "svn+ssh";
QTest::newRow("WITHDASH") << "SVN-SSH://svn.example.com" << true << "svn-ssh";
QTest::newRow("WITHDOTS") << "ORG.QT-PROJECT://qt-project.org" << true << "org.qt-project";

// invalid entries
QTest::newRow("start-digit") << "1http://example.com" << false << "1http";
QTest::newRow("start-plus") << "+ssh://[email protected]" << false << "+ssh";
QTest::newRow("start-dot") << ".org.example:///" << false << ".org.example";
QTest::newRow("with-space") << "a b://" << false << "a b";
QTest::newRow("with-non-ascii") << "\304\245\305\243\305\245\321\200://example.com" << false << "\304\245\305\243\305\245\321\200";
QTest::newRow("with-control1") << "http\1://example.com" << false << "http\1";
QTest::newRow("with-control127") << "http\177://example.com" << false << "http\177";
QTest::newRow("with-null") << QString::fromLatin1("http\0://example.com", 19) << false << QString::fromLatin1("http\0", 5);

QTest::newRow("percent-encoded") << "%68%74%%74%70://example.com" << false << "%68%74%%74%70";

static const char controls[] = "!\"$&'()*,;<=>[\\]^_`{|}~";
for (size_t i = 0; i < sizeof(controls) - 1; ++i)
QTest::newRow(("with-" + QByteArray(1, controls[i])).constData())
<< QString("pre%1post://example.com/").arg(QLatin1Char(controls[i]))
<< false << QString("pre%1post").arg(QLatin1Char(controls[i]));
}

void tst_QUrl::schemeValidator()
{
QFETCH(QByteArray, encodedUrl);
QFETCH(QString, input);
QFETCH(bool, result);
QFETCH(QString, toString);

QUrl url = QUrl::fromEncoded(encodedUrl);
QEXPECT_FAIL("ftp:/index.html", "high-level URL validation not reimplemented yet", Abort);
QEXPECT_FAIL("mailto://smtp.trolltech.com/[email protected]", "high-level URL validation not reimplemented yet", Abort);
QUrl url(input);
QCOMPARE(url.isValid(), result);
if (!result)
QVERIFY(url.toString().isEmpty());
}
if (result) {
QFETCH(QString, scheme);
QCOMPARE(url.scheme(), scheme);

void tst_QUrl::invalidSchemeValidator()
{
// test that if scheme does not start with an ALPHA, QUrl::isValid() returns false
{
QUrl url("1http://qt-project.org");
QVERIFY(url.scheme().isEmpty());
QVERIFY(url.path().startsWith("1http"));
}
{
QUrl url("http://qt-project.org");
url.setScheme("111http://qt-project.org");
QCOMPARE(url.isValid(), false);
QVERIFY(url.toString().isEmpty());
}
// non-ALPHA character at other positions in the scheme are ok
{
QUrl url("ht111tp://qt-project.org", QUrl::StrictMode);
// reconstruct with just the scheme:
url.setUrl(scheme + ':');
QVERIFY(url.isValid());
QCOMPARE(url.scheme(), QString("ht111tp"));
QVERIFY(!url.toString().isEmpty());
}
{
QUrl url("http://qt-project.org");
url.setScheme("ht123tp://qt-project.org");
QVERIFY(!url.isValid());
QCOMPARE(url.scheme(), scheme);
} else {
QVERIFY(url.toString().isEmpty());
url.setScheme("http");
QVERIFY(url.isValid());
QVERIFY(!url.toString().isEmpty());
}
{
QUrl url = QUrl::fromEncoded("ht321tp://qt-project.org", QUrl::StrictMode);
QVERIFY(url.isValid());
QVERIFY(!url.toString().isEmpty());
}
}

void tst_QUrl::setScheme_data()
{
schemeValidator_data();

// a couple more which wouldn't work in parsing a full URL
QTest::newRow("with-slash") << QString() << false << "http/";
QTest::newRow("with-question") << QString() << false << "http?";
QTest::newRow("with-hash") << QString() << false << "http#";
}

void tst_QUrl::setScheme()
{
QFETCH(QString, scheme);
QFETCH(bool, result);
QString expectedScheme;
if (result)
expectedScheme = scheme;

QUrl url;
url.setScheme(scheme);
QCOMPARE(url.isValid(), result);
QCOMPARE(url.scheme(), expectedScheme);

url.setScheme(scheme.toUpper());
QCOMPARE(url.isValid(), result);
QCOMPARE(url.scheme(), expectedScheme);
}

void tst_QUrl::strictParser_data()
{
QTest::addColumn<QString>("input");
Expand Down

0 comments on commit 4f3eb66

Please sign in to comment.