QUrl: Keep one trailing slash when normalizing "file:///b/."
Removing the slash would be a drastic change in behavior. We can expect many people to rely on the trailing slash to string-append further path segments without inserting an extra slash. Amends commit e7bcf41c0b23d83cfb31f966454945c705589a99. Pick-to: 6.7 6.5 Fixes: QTBUG-128940 Change-Id: I71dfc957f383e4648b3b47a40aeb796d7237fb00 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> (cherry picked from commit 2addfa635d2f666d18ffc818f76eb673a6c787d1) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
fd3482ea97
commit
a3df6c36db
@ -2215,11 +2215,17 @@ bool QDir::match(const QString &filter, const QString &fileName)
|
||||
3) a sequence of "//" is treated as multiple path levels ("a/b//.." becomes
|
||||
"a/b/" and "a/b//../.." becomes "a/"), which matches the behavior
|
||||
observed in web browsers.
|
||||
|
||||
However, QUrl also uses local path mode for local URLs; with one exception:
|
||||
Even in local mode we leave one trailing slash for paths ending in "/." if
|
||||
the KeepLocalTrailingSlash flag is given. This reflects how QUrl needs to
|
||||
treat local URLs due to compatibility constraints.
|
||||
*/
|
||||
bool qt_normalizePathSegments(QString *path, QDirPrivate::PathNormalizations flags)
|
||||
{
|
||||
const bool allowUncPaths = flags.testAnyFlag(QDirPrivate::AllowUncPaths);
|
||||
const bool isRemote = flags.testAnyFlag(QDirPrivate::RemotePath);
|
||||
const bool keepLocalTrailingSlash = flags.testAnyFlags(QDirPrivate::KeepLocalTrailingSlash);
|
||||
const qsizetype prefixLength = rootLength(*path, allowUncPaths);
|
||||
|
||||
// RFC 3986 says: "The input buffer is initialized with the now-appended
|
||||
@ -2331,11 +2337,25 @@ bool qt_normalizePathSegments(QString *path, QDirPrivate::PathNormalizations fla
|
||||
}
|
||||
|
||||
if (out > start) {
|
||||
// backtrack one or all the slashes (so "/tmp///" -> "/tmp/")
|
||||
// Always backtrack one slash
|
||||
if (out[-1] == u'/' && in != end)
|
||||
--out;
|
||||
while (!isRemote && out > start && out[-1] == u'/')
|
||||
--out;
|
||||
|
||||
if (!isRemote) {
|
||||
bool removedAnySlashes = false;
|
||||
|
||||
// Backtrack all slashes ...
|
||||
while (out > start && out[-1] == u'/') {
|
||||
--out;
|
||||
removedAnySlashes = true;
|
||||
}
|
||||
|
||||
// ... except a trailing one if it exists and flag given
|
||||
if (removedAnySlashes && keepLocalTrailingSlash && out > start) {
|
||||
++out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (out == start) {
|
||||
// We've reached the root. Make sure we don't turn a relative path
|
||||
|
@ -30,7 +30,8 @@ public:
|
||||
enum PathNormalization {
|
||||
DefaultNormalization = 0x00,
|
||||
AllowUncPaths = 0x01,
|
||||
RemotePath = 0x02
|
||||
RemotePath = 0x02,
|
||||
KeepLocalTrailingSlash = 0x04,
|
||||
};
|
||||
Q_DECLARE_FLAGS(PathNormalizations, PathNormalization)
|
||||
Q_FLAGS(PathNormalizations)
|
||||
|
@ -911,7 +911,9 @@ inline void QUrlPrivate::appendPath(QString &appendTo, QUrl::FormattingOptions o
|
||||
{
|
||||
QString thePath = path;
|
||||
if (options & QUrl::NormalizePathSegments) {
|
||||
qt_normalizePathSegments(&thePath, isLocalFile() ? QDirPrivate::DefaultNormalization : QDirPrivate::RemotePath);
|
||||
qt_normalizePathSegments(
|
||||
&thePath,
|
||||
isLocalFile() ? QDirPrivate::KeepLocalTrailingSlash : QDirPrivate::RemotePath);
|
||||
}
|
||||
|
||||
QStringView thePathView(thePath);
|
||||
@ -2712,7 +2714,9 @@ QUrl QUrl::resolved(const QUrl &relative) const
|
||||
else
|
||||
t.d->sectionIsPresent &= ~QUrlPrivate::Fragment;
|
||||
|
||||
qt_normalizePathSegments(&t.d->path, isLocalFile() ? QDirPrivate::DefaultNormalization : QDirPrivate::RemotePath);
|
||||
qt_normalizePathSegments(
|
||||
&t.d->path,
|
||||
isLocalFile() ? QDirPrivate::KeepLocalTrailingSlash : QDirPrivate::RemotePath);
|
||||
if (!t.d->hasAuthority())
|
||||
fixupNonAuthorityPath(&t.d->path);
|
||||
|
||||
|
@ -1497,7 +1497,9 @@ void tst_QUrl::fromLocalFileNormalize_data()
|
||||
QTest::newRow("relative-dot-dot") << QString::fromLatin1("././a.txt") << QString::fromLatin1("file:././a.txt") << QString::fromLatin1("file:a.txt");
|
||||
QTest::newRow("relative-path-dotdot") << QString::fromLatin1("b/../a.txt") << QString::fromLatin1("file:b/../a.txt") << QString::fromLatin1("file:a.txt");
|
||||
QTest::newRow("absolute-path-dotdot") << QString::fromLatin1("/b/../a.txt") << QString::fromLatin1("file:///b/../a.txt") << QString::fromLatin1("file:///a.txt");
|
||||
QTest::newRow("absolute-path-dot") << QString::fromLatin1("/b/.") << QString::fromLatin1("file:///b/.") << QString::fromLatin1("file:///b");
|
||||
QTest::newRow("absolute-path-slash") << QString::fromLatin1("/b/") << QString::fromLatin1("file:///b/") << QString::fromLatin1("file:///b/");
|
||||
QTest::newRow("absolute-path-slahs-dot") << QString::fromLatin1("/b/.") << QString::fromLatin1("file:///b/.") << QString::fromLatin1("file:///b/");
|
||||
QTest::newRow("absolute-path-slahs-dot-slash") << QString::fromLatin1("/b/./") << QString::fromLatin1("file:///b/./") << QString::fromLatin1("file:///b/");
|
||||
}
|
||||
|
||||
void tst_QUrl::fromLocalFileNormalize()
|
||||
|
Loading…
x
Reference in New Issue
Block a user