Revert "QUrl::resolved: switch to using qt_normalizePathSegments"
This reverts commit e7bcf41c0b23d83cfb31f966454945c705589a99. Reason for revert: Causes Qt.resolvedUrl() to misbehave in QML. Task-number: QTBUG-128940 Change-Id: I698338d4789ffef5c5a0f08391372b428d4fffb0 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
50933122a2
commit
c023016ffd
@ -73,7 +73,7 @@ static qsizetype rootLength(QStringView name, bool allowUncPaths)
|
|||||||
return len > 2 && name.at(2) == u'/' ? 3 : 2;
|
return len > 2 && name.at(2) == u'/' ? 3 : 2;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (len && name.at(0) == u'/')
|
if (name.at(0) == u'/')
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1524,6 +1524,111 @@ inline QString QUrlPrivate::mergePaths(const QString &relativePath) const
|
|||||||
return newPath;
|
return newPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
From http://www.ietf.org/rfc/rfc3986.txt, 5.2.4: Remove dot segments
|
||||||
|
|
||||||
|
Removes unnecessary ../ and ./ from the path. Used for normalizing
|
||||||
|
the URL.
|
||||||
|
|
||||||
|
This code has a Qt-specific extension to handle empty path segments (a.k.a.
|
||||||
|
multiple slashes like "a//b"). We try to keep them wherever possible
|
||||||
|
because with some protocols they are meaningful, but we still consider them
|
||||||
|
to be a single directory transition for "." or ".." (e.g., "a/b//c" +
|
||||||
|
"../" is "a/"). See tst_QUrl::resolved() for the expected behavior.
|
||||||
|
*/
|
||||||
|
static void removeDotsFromPath(QString *path)
|
||||||
|
{
|
||||||
|
// The input buffer is initialized with the now-appended path
|
||||||
|
// components and the output buffer is initialized to the empty
|
||||||
|
// string.
|
||||||
|
const QChar *in = path->constBegin();
|
||||||
|
|
||||||
|
// Scan the input for a "." or ".." segment. If there isn't any, then we
|
||||||
|
// don't need to modify this path at all.
|
||||||
|
qsizetype i = 0, n = path->size();
|
||||||
|
for (bool lastWasSlash = true; i < n; ++i) {
|
||||||
|
if (lastWasSlash && in[i] == u'.') {
|
||||||
|
if (i + 1 == n || in[i + 1] == u'/')
|
||||||
|
break;
|
||||||
|
if (in[i + 1] == u'.' && (i + 2 == n || in[i + 2] == u'/'))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lastWasSlash = in[i] == u'/';
|
||||||
|
}
|
||||||
|
if (i == n)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QChar *out = path->data();
|
||||||
|
const QChar *end = out + path->size();
|
||||||
|
out += i;
|
||||||
|
in = out;
|
||||||
|
|
||||||
|
// We implement a modified algorithm compared to RFC 3986, for efficiency.
|
||||||
|
do {
|
||||||
|
#if 0 // to see in the debugger
|
||||||
|
QStringView output(path->constBegin(), out);
|
||||||
|
QStringView input(in, end);
|
||||||
|
#endif
|
||||||
|
// First, copy any preceding slashes, so we can look at the segment's
|
||||||
|
// content.
|
||||||
|
while (in < end && in[0] == u'/') {
|
||||||
|
*out++ = *in++;
|
||||||
|
|
||||||
|
// Note: we may exit this loop with in == end, in which case we
|
||||||
|
// *shouldn't* dereference *in. But since we are pointing to a
|
||||||
|
// detached, non-empty QString, we know there's a u'\0' at the end.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is this path segment either "." or ".."?
|
||||||
|
enum { Nothing, Dot, DotDot } type = Nothing;
|
||||||
|
if (in[0] == u'.') {
|
||||||
|
if (in + 1 == end || in[1] == u'/')
|
||||||
|
type = Dot;
|
||||||
|
else if (in[1] == u'.' && (in + 2 == end || in[2] == u'/'))
|
||||||
|
type = DotDot;
|
||||||
|
}
|
||||||
|
if (type != Nothing) {
|
||||||
|
// If it is either, we skip it and remove any preceding slashes (if
|
||||||
|
// any) from the output. If it is "..", we remove the segment
|
||||||
|
// before that and its preceding slashes (if any) too.
|
||||||
|
const QChar *start = path->constBegin();
|
||||||
|
if (type == DotDot) {
|
||||||
|
while (out > start && *--out != u'/')
|
||||||
|
;
|
||||||
|
while (out > start && *--out == u'/')
|
||||||
|
;
|
||||||
|
++in; // the first dot
|
||||||
|
}
|
||||||
|
|
||||||
|
in += 2; // one dot and either one slash or the terminating null
|
||||||
|
while (out > start && *--out != u'/')
|
||||||
|
;
|
||||||
|
|
||||||
|
// And then replace the segment with "/", unless it would make a
|
||||||
|
// relative path become absolute.
|
||||||
|
if (out != start) {
|
||||||
|
// Replacing with a slash won't make the path absolute.
|
||||||
|
*out++ = u'/';
|
||||||
|
} else if (*start == u'/') {
|
||||||
|
// The path is already absolute.
|
||||||
|
++out;
|
||||||
|
} else {
|
||||||
|
// The path is relative, so we must skip any follow-on slashes
|
||||||
|
// to make sure the next iteration of the loop won't copy them,
|
||||||
|
// which would make the path become absolute.
|
||||||
|
while (in < end && *in == u'/')
|
||||||
|
++in;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it is neither, then we copy this segment.
|
||||||
|
while (in < end && in->unicode() != '/')
|
||||||
|
*out++ = *in++;
|
||||||
|
} while (in < end);
|
||||||
|
path->truncate(out - path->constBegin());
|
||||||
|
}
|
||||||
|
|
||||||
// Authority-less URLs cannot have paths starting with double slashes (see
|
// Authority-less URLs cannot have paths starting with double slashes (see
|
||||||
// QUrlPrivate::validityError). We refuse to turn a valid URL into invalid by
|
// QUrlPrivate::validityError). We refuse to turn a valid URL into invalid by
|
||||||
// way of QUrl::resolved().
|
// way of QUrl::resolved().
|
||||||
@ -2712,7 +2817,7 @@ QUrl QUrl::resolved(const QUrl &relative) const
|
|||||||
else
|
else
|
||||||
t.d->sectionIsPresent &= ~QUrlPrivate::Fragment;
|
t.d->sectionIsPresent &= ~QUrlPrivate::Fragment;
|
||||||
|
|
||||||
qt_normalizePathSegments(&t.d->path, isLocalFile() ? QDirPrivate::DefaultNormalization : QDirPrivate::RemotePath);
|
removeDotsFromPath(&t.d->path);
|
||||||
if (!t.d->hasAuthority())
|
if (!t.d->hasAuthority())
|
||||||
fixupNonAuthorityPath(&t.d->path);
|
fixupNonAuthorityPath(&t.d->path);
|
||||||
|
|
||||||
|
@ -600,7 +600,7 @@ void tst_QUrl::setUrl()
|
|||||||
|
|
||||||
QUrl url2("../../////kdebase/konqueror");
|
QUrl url2("../../////kdebase/konqueror");
|
||||||
QCOMPARE(url.resolved(url2).toString(),
|
QCOMPARE(url.resolved(url2).toString(),
|
||||||
QString::fromLatin1("file:///usr/local/src/kde2/kdebase/konqueror"));
|
QString::fromLatin1("file:///usr/local/src/kde2/////kdebase/konqueror"));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -929,16 +929,16 @@ void tst_QUrl::resolving_data()
|
|||||||
QTest::newRow(".-on-//") << "http://a/b/c//" << "." << "http://a/b/c//";
|
QTest::newRow(".-on-//") << "http://a/b/c//" << "." << "http://a/b/c//";
|
||||||
QTest::newRow("./-on-//") << "http://a/b/c//" << "./" << "http://a/b/c//";
|
QTest::newRow("./-on-//") << "http://a/b/c//" << "./" << "http://a/b/c//";
|
||||||
QTest::newRow(".//-on-//") << "http://a/b/c//" << ".//" << "http://a/b/c///"; // weird but correct
|
QTest::newRow(".//-on-//") << "http://a/b/c//" << ".//" << "http://a/b/c///"; // weird but correct
|
||||||
QTest::newRow("..-on-//") << "http://a/b/c//" << ".." << "http://a/b/c/";
|
QTest::newRow("..-on-//") << "http://a/b/c//" << ".." << "http://a/b/";
|
||||||
QTest::newRow("../-on-//") << "http://a/b/c//" << "../" << "http://a/b/c/";
|
QTest::newRow("../-on-//") << "http://a/b/c//" << "../" << "http://a/b/";
|
||||||
QTest::newRow("..//-on-//") << "http://a/b/c//" << "..//" << "http://a/b/c//";
|
QTest::newRow("..//-on-//") << "http://a/b/c//" << "..//" << "http://a/b//";
|
||||||
QTest::newRow("../g-on-//") << "http://a/b/c//" << "../g" << "http://a/b/c/g";
|
QTest::newRow("../g-on-//") << "http://a/b/c//" << "../g" << "http://a/b/g";
|
||||||
QTest::newRow("..//g-on-//") << "http://a/b/c//" << "..//g" << "http://a/b/c//g";
|
QTest::newRow("..//g-on-//") << "http://a/b/c//" << "..//g" << "http://a/b//g";
|
||||||
QTest::newRow("../..-on-//") << "http://a/b/c//" << "../.." << "http://a/b/";
|
QTest::newRow("../..-on-//") << "http://a/b/c//" << "../.." << "http://a/";
|
||||||
QTest::newRow("../../-on-//") << "http://a/b/c//" << "../../" << "http://a/b/";
|
QTest::newRow("../../-on-//") << "http://a/b/c//" << "../../" << "http://a/";
|
||||||
QTest::newRow("../..//-on-//") << "http://a/b/c//" << "../..//" << "http://a/b//";
|
QTest::newRow("../..//-on-//") << "http://a/b/c//" << "../..//" << "http://a//";
|
||||||
QTest::newRow("../../g-on-//") << "http://a/b/c//" << "../../g" << "http://a/b/g";
|
QTest::newRow("../../g-on-//") << "http://a/b/c//" << "../../g" << "http://a/g";
|
||||||
QTest::newRow("../..//g-on-//") << "http://a/b/c//" << "../..//g" << "http://a/b//g";
|
QTest::newRow("../..//g-on-//") << "http://a/b/c//" << "../..//g" << "http://a//g";
|
||||||
|
|
||||||
// 5.4.2 Abnormal Examples (http://www.ietf.org/rfc/rfc3986.txt)
|
// 5.4.2 Abnormal Examples (http://www.ietf.org/rfc/rfc3986.txt)
|
||||||
|
|
||||||
@ -4432,7 +4432,6 @@ void tst_QUrl::normalizeRemotePaths()
|
|||||||
QCOMPARE(url.adjusted(QUrl::NormalizePathSegments).toString(), expected);
|
QCOMPARE(url.adjusted(QUrl::NormalizePathSegments).toString(), expected);
|
||||||
QCOMPARE(url.adjusted(QUrl::NormalizePathSegments | QUrl::RemoveFilename).toString(),
|
QCOMPARE(url.adjusted(QUrl::NormalizePathSegments | QUrl::RemoveFilename).toString(),
|
||||||
expectedNoFilename);
|
expectedNoFilename);
|
||||||
QCOMPARE(url.resolved(QUrl(".")).toString(), expectedNoFilename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QUrl)
|
QTEST_MAIN(tst_QUrl)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user