QUrl: add NormalizePathSegments to UrlFormattingOptions
This is a bit like QDir::cleanPath(), but for URL paths. The code is shared with QDir::cleanPath(), by extracting the common parts it into a helper, qt_normalizePathSegments(). Change-Id: I7133c5e4aa2bf17fba98af13eb5371afba64197a Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
659f62981f
commit
a7bc4e8494
@ -2005,25 +2005,14 @@ bool QDir::match(const QString &filter, const QString &fileName)
|
||||
#endif // QT_NO_REGEXP
|
||||
|
||||
/*!
|
||||
Returns \a path with directory separators normalized (converted to "/") and
|
||||
redundant ones removed, and "."s and ".."s resolved (as far as possible).
|
||||
Returns \a path with redundant directory separators removed,
|
||||
and "."s and ".."s resolved (as far as possible).
|
||||
|
||||
Symbolic links are kept. This function does not return the
|
||||
canonical path, but rather the simplest version of the input.
|
||||
For example, "./local" becomes "local", "local/../bin" becomes
|
||||
"bin" and "/local/usr/../bin" becomes "/local/bin".
|
||||
|
||||
\sa absolutePath(), canonicalPath()
|
||||
This method is shared with QUrl, so it doesn't deal with QDir::separator(),
|
||||
nor does it remove the trailing slash, if any.
|
||||
*/
|
||||
QString QDir::cleanPath(const QString &path)
|
||||
QString qt_normalizePathSegments(const QString &name, bool allowUncPaths)
|
||||
{
|
||||
if (path.isEmpty())
|
||||
return path;
|
||||
QString name = path;
|
||||
QChar dir_separator = separator();
|
||||
if (dir_separator != QLatin1Char('/'))
|
||||
name.replace(dir_separator, QLatin1Char('/'));
|
||||
|
||||
int used = 0, levels = 0;
|
||||
const int len = name.length();
|
||||
QVarLengthArray<QChar> outVector(len);
|
||||
@ -2033,10 +2022,8 @@ QString QDir::cleanPath(const QString &path)
|
||||
for (int i = 0, last = -1, iwrite = 0; i < len; ++i) {
|
||||
if (p[i] == QLatin1Char('/')) {
|
||||
while (i+1 < len && p[i+1] == QLatin1Char('/')) {
|
||||
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) //allow unc paths
|
||||
if (!i)
|
||||
if (allowUncPaths && i == 0)
|
||||
break;
|
||||
#endif
|
||||
i++;
|
||||
}
|
||||
bool eaten = false;
|
||||
@ -2099,8 +2086,6 @@ QString QDir::cleanPath(const QString &path)
|
||||
eaten = true;
|
||||
#endif
|
||||
last = -1;
|
||||
} else if (last != -1 && i == len-1) {
|
||||
eaten = true;
|
||||
} else {
|
||||
levels++;
|
||||
}
|
||||
@ -2126,6 +2111,36 @@ QString QDir::cleanPath(const QString &path)
|
||||
}
|
||||
|
||||
QString ret = (used == len ? name : QString(out, used));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \a path with directory separators normalized (converted to "/") and
|
||||
redundant ones removed, and "."s and ".."s resolved (as far as possible).
|
||||
|
||||
Symbolic links are kept. This function does not return the
|
||||
canonical path, but rather the simplest version of the input.
|
||||
For example, "./local" becomes "local", "local/../bin" becomes
|
||||
"bin" and "/local/usr/../bin" becomes "/local/bin".
|
||||
|
||||
\sa absolutePath(), canonicalPath()
|
||||
*/
|
||||
QString QDir::cleanPath(const QString &path)
|
||||
{
|
||||
if (path.isEmpty())
|
||||
return path;
|
||||
QString name = path;
|
||||
QChar dir_separator = separator();
|
||||
if (dir_separator != QLatin1Char('/'))
|
||||
name.replace(dir_separator, QLatin1Char('/'));
|
||||
|
||||
bool allowUncPaths = false;
|
||||
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) //allow unc paths
|
||||
allowUncPaths = true;
|
||||
#endif
|
||||
|
||||
QString ret = qt_normalizePathSegments(name, allowUncPaths);
|
||||
|
||||
// Strip away last slash except for root directories
|
||||
if (ret.length() > 1 && ret.endsWith(QLatin1Char('/'))) {
|
||||
#if defined (Q_OS_WIN)
|
||||
|
@ -231,6 +231,8 @@
|
||||
\value PreferLocalFile If the URL is a local file according to isLocalFile()
|
||||
and contains no query or fragment, a local file path is returned.
|
||||
\value StripTrailingSlash The trailing slash is removed if one is present.
|
||||
\value NormalizePathSegments Modifies the path to remove redundant directory separators,
|
||||
and to resolve "."s and ".."s (as far as possible).
|
||||
|
||||
Note that the case folding rules in \l{RFC 3491}{Nameprep}, which QUrl
|
||||
conforms to, require host names to always be converted to lower case,
|
||||
@ -324,6 +326,7 @@
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
extern QString qt_normalizePathSegments(const QString &name, bool allowUncPaths); // qdir.cpp
|
||||
|
||||
inline static bool isHex(char c)
|
||||
{
|
||||
@ -803,6 +806,9 @@ inline void QUrlPrivate::appendPassword(QString &appendTo, QUrl::FormattingOptio
|
||||
inline void QUrlPrivate::appendPath(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const
|
||||
{
|
||||
QString thePath = path;
|
||||
if (options & QUrl::NormalizePathSegments) {
|
||||
thePath = qt_normalizePathSegments(path, false);
|
||||
}
|
||||
if (options & QUrl::RemoveFilename) {
|
||||
const int slash = path.lastIndexOf(QLatin1Char('/'));
|
||||
if (slash == -1)
|
||||
@ -3235,7 +3241,7 @@ QUrl QUrl::adjusted(QUrl::FormattingOptions options) const
|
||||
that.setFragment(QString());
|
||||
if (options & RemovePath) {
|
||||
that.setPath(QString());
|
||||
} else if (options & (StripTrailingSlash | RemoveFilename)) {
|
||||
} else if (options & (StripTrailingSlash | RemoveFilename | NormalizePathSegments)) {
|
||||
QString path;
|
||||
d->appendPath(path, options, QUrlPrivate::Path);
|
||||
that.setPath(path);
|
||||
|
@ -141,7 +141,8 @@ public:
|
||||
// 0x100 was a private code in Qt 4, keep unused for a while
|
||||
PreferLocalFile = 0x200,
|
||||
StripTrailingSlash = 0x400,
|
||||
RemoveFilename = 0x800
|
||||
RemoveFilename = 0x800,
|
||||
NormalizePathSegments = 0x1000
|
||||
};
|
||||
|
||||
enum ComponentFormattingOption {
|
||||
|
@ -298,6 +298,17 @@ void tst_QUrl::comparison()
|
||||
QEXPECT_FAIL("", "Normalization not implemented, will probably not be implemented like this", Continue);
|
||||
QCOMPARE(url3, url4);
|
||||
|
||||
QUrl url3bis = QUrl::fromEncoded("example://a/b/c/%7Bfoo%7D/");
|
||||
QUrl url3bisNoSlash = QUrl::fromEncoded("example://a/b/c/%7Bfoo%7D");
|
||||
QUrl url4bis = QUrl::fromEncoded("example://a/.//b/../b/c//%7Bfoo%7D/");
|
||||
QCOMPARE(url4bis.adjusted(QUrl::NormalizePathSegments), url3bis);
|
||||
QCOMPARE(url4bis.adjusted(QUrl::NormalizePathSegments | QUrl::StripTrailingSlash), url3bisNoSlash);
|
||||
|
||||
QUrl url4EncodedDots = QUrl("example://a/.//b/%2E%2E%2F/b/c/");
|
||||
QCOMPARE(QString::fromLatin1(url4EncodedDots.toEncoded()), QString::fromLatin1("example://a/.//b/..%2F/b/c/"));
|
||||
QCOMPARE(url4EncodedDots.toString(), QString("example://a/.//b/..%2F/b/c/"));
|
||||
QCOMPARE(url4EncodedDots.adjusted(QUrl::NormalizePathSegments).toString(), QString("example://a/b/..%2F/b/c/"));
|
||||
|
||||
// 6.2.2.1 Make sure hexdecimal characters in percent encoding are
|
||||
// treated case-insensitively
|
||||
QUrl url5;
|
||||
|
Loading…
Reference in New Issue
Block a user