QUrl: expand the square brackets encoding to decoded setPath() calls
Amends (reverts) commit 5e936b60fc921e21b8153a83113886a1de333b57, which forced the encoding of the square brackets ("[]") into their percent- encoded forms only in QUrl::fromLocalFile(). This commit expands the functionality to all uses of decoded paths by applying the change directly to recodeFromUser(). [ChangeLog][QtCore][QUrl] Square brackets ("[]") are now transformed to their percent-encoded forms ("%5B" and "%5D") when present as inputs to setPath(), setQuery(), and setFragment() if the parsing mode is QUrl::DecodedMode (the default). Pick-to: 6.8 Fixes: QTBUG-135433 Task-number: QTBUG-134073 See: https://bugs.kde.org/show_bug.cgi?id=502280 Change-Id: Id2b41559af08b5f228e4fffdb9c6f23120f856b5 Reviewed-by: David Faure <david.faure@kdab.com> (cherry picked from commit f3da9d3c858e8dc28a5dc91047b592ed5becbd62) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
bbe0b18b38
commit
01ff6e19f7
@ -748,32 +748,6 @@ static const ushort * const pathInIsolation = userNameInIsolation + 5;
|
||||
static const ushort * const queryInIsolation = userNameInIsolation + 6;
|
||||
static const ushort * const fragmentInIsolation = userNameInIsolation + 7;
|
||||
|
||||
static const ushort localPathFromUser[] = {
|
||||
// we force-decode some of the gen-delims, because
|
||||
// pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
||||
// the gen-delim lines are leave() in qt_urlRecode, so we don't need to
|
||||
// repeat them if we want to keep them decoded
|
||||
// decode(':'), // allowed
|
||||
// decode('@'), // allowed
|
||||
encode(']'),
|
||||
encode('['),
|
||||
// decode('/'), // special and allowed
|
||||
// decode('?'), // handled by path() and others
|
||||
// decode('#'), // ditto
|
||||
|
||||
// the rest is like pathInIsolation above
|
||||
decode('"'),
|
||||
decode('<'),
|
||||
decode('>'),
|
||||
decode('^'),
|
||||
decode('\\'),
|
||||
decode('|'),
|
||||
decode('{'),
|
||||
decode('}'),
|
||||
|
||||
0
|
||||
};
|
||||
|
||||
static const ushort userNameInUserInfo[] = {
|
||||
encode(':'), // 0
|
||||
decode('@'), // 1
|
||||
@ -833,9 +807,11 @@ static const ushort * const pathInUrl = userNameInUrl + 5;
|
||||
static const ushort * const queryInUrl = userNameInUrl + 6;
|
||||
static const ushort * const fragmentInUrl = userNameInUrl + 6;
|
||||
|
||||
static inline void parseDecodedComponent(QString &data)
|
||||
static inline void parseDecodedComponent(QString &data, QUrlPrivate::Section section)
|
||||
{
|
||||
data.replace(u'%', "%25"_L1);
|
||||
if (section != QUrlPrivate::Host)
|
||||
data.replace(u'[', "%5B"_L1).replace(u']', "%5D"_L1);
|
||||
}
|
||||
|
||||
static inline QString
|
||||
@ -2135,7 +2111,7 @@ void QUrl::setUserName(const QString &userName, ParsingMode mode)
|
||||
|
||||
QString data = userName;
|
||||
if (mode == DecodedMode) {
|
||||
parseDecodedComponent(data);
|
||||
parseDecodedComponent(data, QUrlPrivate::UserName);
|
||||
mode = TolerantMode;
|
||||
}
|
||||
|
||||
@ -2198,7 +2174,7 @@ void QUrl::setPassword(const QString &password, ParsingMode mode)
|
||||
|
||||
QString data = password;
|
||||
if (mode == DecodedMode) {
|
||||
parseDecodedComponent(data);
|
||||
parseDecodedComponent(data, QUrlPrivate::Password);
|
||||
mode = TolerantMode;
|
||||
}
|
||||
|
||||
@ -2260,7 +2236,7 @@ void QUrl::setHost(const QString &host, ParsingMode mode)
|
||||
|
||||
QString data = host;
|
||||
if (mode == DecodedMode) {
|
||||
parseDecodedComponent(data);
|
||||
parseDecodedComponent(data, QUrlPrivate::Host);
|
||||
mode = TolerantMode;
|
||||
}
|
||||
|
||||
@ -2385,7 +2361,7 @@ void QUrl::setPath(const QString &path, ParsingMode mode)
|
||||
|
||||
QString data = path;
|
||||
if (mode == DecodedMode) {
|
||||
parseDecodedComponent(data);
|
||||
parseDecodedComponent(data, QUrlPrivate::Path);
|
||||
mode = TolerantMode;
|
||||
}
|
||||
|
||||
@ -2521,7 +2497,7 @@ void QUrl::setQuery(const QString &query, ParsingMode mode)
|
||||
|
||||
QString data = query;
|
||||
if (mode == DecodedMode) {
|
||||
parseDecodedComponent(data);
|
||||
parseDecodedComponent(data, QUrlPrivate::Query);
|
||||
mode = TolerantMode;
|
||||
}
|
||||
|
||||
@ -2619,7 +2595,7 @@ void QUrl::setFragment(const QString &fragment, ParsingMode mode)
|
||||
|
||||
QString data = fragment;
|
||||
if (mode == DecodedMode) {
|
||||
parseDecodedComponent(data);
|
||||
parseDecodedComponent(data, QUrlPrivate::Fragment);
|
||||
mode = TolerantMode;
|
||||
}
|
||||
|
||||
@ -3386,11 +3362,7 @@ QUrl QUrl::fromLocalFile(const QString &localFile)
|
||||
}
|
||||
|
||||
url.setScheme(scheme);
|
||||
|
||||
// not directly using setPath here, as we do a few more transforms
|
||||
parseDecodedComponent(deslashified);
|
||||
if (!qt_urlRecode(url.d->path, deslashified, {}, localPathFromUser))
|
||||
url.d->path = std::move(deslashified);
|
||||
url.setPath(deslashified, DecodedMode);
|
||||
|
||||
return url;
|
||||
}
|
||||
|
@ -1422,6 +1422,11 @@ void tst_QUrl::toLocalFile()
|
||||
url.setPath(url.path(QUrl::PrettyDecoded), QUrl::TolerantMode);
|
||||
QCOMPARE(url.toLocalFile(), theFile);
|
||||
QCOMPARE(url.isLocalFile(), !theFile.isEmpty());
|
||||
|
||||
// local file paths can be fully decoded without loss
|
||||
url.setPath(url.path());
|
||||
QCOMPARE(url.toLocalFile(), theFile);
|
||||
QCOMPARE(url.isLocalFile(), !theFile.isEmpty());
|
||||
}
|
||||
|
||||
void tst_QUrl::fromLocalFile_data()
|
||||
@ -1508,6 +1513,11 @@ void tst_QUrl::fromLocalFile()
|
||||
url.setPath(url.path(QUrl::PrettyDecoded), QUrl::TolerantMode);
|
||||
QCOMPARE(url.toString(QUrl::DecodeReserved), theUrl);
|
||||
QCOMPARE(url.path(), thePath);
|
||||
|
||||
// local file paths can be fully decoded without loss
|
||||
url.setPath(url.path());
|
||||
QCOMPARE(url.toString(QUrl::DecodeReserved), theUrl);
|
||||
QCOMPARE(url.path(), thePath);
|
||||
}
|
||||
|
||||
void tst_QUrl::fromLocalFileNormalize_data()
|
||||
@ -4150,24 +4160,25 @@ void tst_QUrl::setComponents_data()
|
||||
<< int(Scheme) << "http%61" << Decoded << false
|
||||
<< PrettyDecoded << "" << "";
|
||||
QTest::newRow("username-encode") << QUrl("http://example.com")
|
||||
<< int(UserName) << "h%61llo:world" << Decoded << true
|
||||
<< PrettyDecoded << "h%2561llo:world" << "http://h%2561llo%3Aworld@example.com";
|
||||
<< int(UserName) << "h%61llo[:]world" << Decoded << true
|
||||
<< PrettyDecoded << "h%2561llo[:]world" << "http://h%2561llo%5B%3A%5Dworld@example.com";
|
||||
QTest::newRow("password-encode") << QUrl("http://example.com")
|
||||
<< int(Password) << "h%61llo:world@" << Decoded << true
|
||||
<< PrettyDecoded << "h%2561llo:world@" << "http://:h%2561llo:world%40@example.com";
|
||||
<< int(Password) << "h%61llo[:]world@" << Decoded << true
|
||||
<< PrettyDecoded << "h%2561llo[:]world@" << "http://:h%2561llo%5B:%5Dworld%40@example.com";
|
||||
// '%' characters are not permitted in the hostname, these test that it fails to set anything
|
||||
QTest::newRow("invalid-host-encode") << QUrl("http://example.com")
|
||||
<< int(Host) << "ex%61mple.com" << Decoded << false
|
||||
<< PrettyDecoded << QString() << QString();
|
||||
// square brackets are force-encoded from decoded forms in the path, query, and fragment
|
||||
QTest::newRow("path-encode") << QUrl("http://example.com/foo")
|
||||
<< int(Path) << "/bar%23" << Decoded << true
|
||||
<< PrettyDecoded << "/bar%2523" << "http://example.com/bar%2523";
|
||||
<< int(Path) << "/ba[r]%23" << Decoded << true
|
||||
<< PrettyDecoded << "/ba%5Br%5D%2523" << "http://example.com/ba%5Br%5D%2523";
|
||||
QTest::newRow("query-encode") << QUrl("http://example.com/foo?q")
|
||||
<< int(Query) << "bar%23" << Decoded << true
|
||||
<< PrettyDecoded << "bar%2523" << "http://example.com/foo?bar%2523";
|
||||
<< int(Query) << "ba[r]%23" << Decoded << true
|
||||
<< PrettyDecoded << "ba%5Br%5D%2523" << "http://example.com/foo?ba%5Br%5D%2523";
|
||||
QTest::newRow("fragment-encode") << QUrl("http://example.com/foo#z")
|
||||
<< int(Fragment) << "bar%23" << Decoded << true
|
||||
<< PrettyDecoded << "bar%2523" << "http://example.com/foo#bar%2523";
|
||||
<< int(Fragment) << "ba[r]%23" << Decoded << true
|
||||
<< PrettyDecoded << "ba%5Br%5D%2523" << "http://example.com/foo#ba%5Br%5D%2523";
|
||||
// force decoding
|
||||
QTest::newRow("username-decode") << QUrl("http://example.com")
|
||||
<< int(UserName) << "hello%3Aworld%25" << Tolerant << true
|
||||
@ -4176,8 +4187,8 @@ void tst_QUrl::setComponents_data()
|
||||
<< int(Password) << "}}>b9o%25kR(" << Tolerant << true
|
||||
<< FullyDecoded << "}}>b9o%kR(" << "http://:%7D%7D%3Eb9o%25kR(@example.com";
|
||||
QTest::newRow("path-decode") << QUrl("http://example.com/")
|
||||
<< int(Path) << "/bar%25foo" << Tolerant << true
|
||||
<< FullyDecoded << "/bar%foo" << "http://example.com/bar%25foo";
|
||||
<< int(Path) << "/bar%25[foo]" << Tolerant << true
|
||||
<< FullyDecoded << "/bar%[foo]" << "http://example.com/bar%25[foo]";
|
||||
QTest::newRow("query-decode") << QUrl("http://example.com/foo?qq")
|
||||
<< int(Query) << "bar%25foo" << Tolerant << true
|
||||
<< FullyDecoded << "bar%foo" << "http://example.com/foo?bar%25foo";
|
||||
|
Loading…
x
Reference in New Issue
Block a user