diff options
| author | Ahmad Samir <a.samirh78@gmail.com> | 2024-09-19 14:39:20 +0300 |
|---|---|---|
| committer | Ahmad Samir <a.samirh78@gmail.com> | 2024-10-04 20:08:35 +0300 |
| commit | ec894d694506fcce75fc9643f08dfb1c79f64c8b (patch) | |
| tree | 5126933088ed0a60b83ea3095e742d2172522296 /src/corelib | |
| parent | dc1d3abd7e852829b9bc81c1ba9565f40147402d (diff) | |
QDir: change qt_normalizePathSegments to preserve trailing '/'s
... for local URLs too.
For example normalizing "/Users/sam/troll/qt4.0/.." by following the
alogrithm at https://www.ietf.org/rfc/rfc3986.html#section-5.2.4:
- replace "/.." with a "/" in the input buffer, then remove the previous
path segment from the output buffer up to, and including, the
previous "/"
- next iteration will find the input buffer starting with a "/" which
is moved to the output buffer; the final result would be:
"/Users/sam/troll/"
Remove the KeepLocalTrailingSlash enumerator, it's become redundant with
this change.
De-duplicate a row in tst_QDir.
[ChangeLog][Important Behavior Change] Aligned how QDir and QUrl
normalize paths with respect to preserving a trailing slash. That is,
QDir::cleanPath("/b/.") and
QUrl("file:///b/.).toString(QUrl::NormalizePathSegments) will return
"/b/" and "file:///b/" respectively. For more details see:
https://www.ietf.org/rfc/rfc3986.html#section-5.2.4
Task-number: QTBUG-128940
Change-Id: Id5a4bdab14e7312a60b1b54de07e5d9f3e8aa40a
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib')
| -rw-r--r-- | src/corelib/io/qdir.cpp | 33 | ||||
| -rw-r--r-- | src/corelib/io/qdir_p.h | 1 | ||||
| -rw-r--r-- | src/corelib/io/qurl.cpp | 4 |
3 files changed, 9 insertions, 29 deletions
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index f10e1569473..a7e12eaae35 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -2223,16 +2223,12 @@ bool QDir::match(const QString &filter, const QString &fileName) "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. + As a Qt extension, for local URLs we treat multiple slashes as one slash. */ 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 @@ -2343,27 +2339,12 @@ bool qt_normalizePathSegments(QString *path, QDirPrivate::PathNormalizations fla ++in; // the one dot } - if (out > start) { - // Always backtrack one slash - if (out[-1] == u'/' && in != end) - --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; - } - } - } + // Not at 'end' yet, prepare for the next loop iteration by backtracking one slash. + // E.g.: /a/b/../c >>> /a/b/../c + // ^out ^out + // the next iteration will copy '/c' to the output buffer >>> /a/c + if (in != end && out > start && out[-1] == u'/') + --out; if (out == start) { // We've reached the root. Make sure we don't turn a relative path // to absolute or, in the case of local paths that are already diff --git a/src/corelib/io/qdir_p.h b/src/corelib/io/qdir_p.h index 3641d003bec..36a20c64723 100644 --- a/src/corelib/io/qdir_p.h +++ b/src/corelib/io/qdir_p.h @@ -31,7 +31,6 @@ public: DefaultNormalization = 0x00, AllowUncPaths = 0x01, RemotePath = 0x02, - KeepLocalTrailingSlash = 0x04, }; Q_DECLARE_FLAGS(PathNormalizations, PathNormalization) Q_FLAGS(PathNormalizations) diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 2b34c6b8bcb..7bd2288b8af 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -913,7 +913,7 @@ inline void QUrlPrivate::appendPath(QString &appendTo, QUrl::FormattingOptions o if (options & QUrl::NormalizePathSegments) { qt_normalizePathSegments( &thePath, - isLocalFile() ? QDirPrivate::KeepLocalTrailingSlash : QDirPrivate::RemotePath); + isLocalFile() ? QDirPrivate::DefaultNormalization : QDirPrivate::RemotePath); } QStringView thePathView(thePath); @@ -2716,7 +2716,7 @@ QUrl QUrl::resolved(const QUrl &relative) const qt_normalizePathSegments( &t.d->path, - isLocalFile() ? QDirPrivate::KeepLocalTrailingSlash : QDirPrivate::RemotePath); + isLocalFile() ? QDirPrivate::DefaultNormalization : QDirPrivate::RemotePath); if (!t.d->hasAuthority()) fixupNonAuthorityPath(&t.d->path); |
