diff options
Diffstat (limited to 'src/corelib/io/qurl.cpp')
-rw-r--r-- | src/corelib/io/qurl.cpp | 169 |
1 files changed, 75 insertions, 94 deletions
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index f2e1f9bbc7..3a1433ec39 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -225,9 +225,14 @@ \value RemoveQuery The query part of the URL (following a '?' character) is removed. \value RemoveFragment + \value RemoveFilename The filename (i.e. everything after the last '/' in the path) is removed. + The trailing '/' is kept, unless StripTrailingSlash is set. + Only valid if RemovePath is not set. \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, @@ -321,6 +326,7 @@ #endif QT_BEGIN_NAMESPACE +extern QString qt_normalizePathSegments(const QString &name, bool allowUncPaths); // qdir.cpp inline static bool isHex(char c) { @@ -799,12 +805,26 @@ 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) + return; + thePath = path.left(slash+1); + } + // check if we need to remove trailing slashes + if ((options & QUrl::StripTrailingSlash) && !thePath.isEmpty() && thePath != QLatin1String("/") && thePath.endsWith(QLatin1Char('/'))) + thePath.chop(1); + if (appendingTo != Path && !(options & QUrl::EncodeDelimiters)) { - if (!qt_urlRecode(appendTo, path.constData(), path.constEnd(), options, decodedPathInUrlActions)) - appendTo += path; + if (!qt_urlRecode(appendTo, thePath.constData(), thePath.constEnd(), options, decodedPathInUrlActions)) + appendTo += thePath; } else { - appendToUser(appendTo, path, options, encodedPathActions, decodedPathInIsolationActions); + appendToUser(appendTo, thePath, options, encodedPathActions, decodedPathInIsolationActions); } } @@ -1059,7 +1079,7 @@ inline void QUrlPrivate::appendHost(QString &appendTo, QUrl::FormattingOptions o // this is either an IPv4Address or a reg-name // if it is a reg-name, it is already stored in Unicode form if (options == QUrl::EncodeUnicode) - appendTo += qt_ACE_do(host, ToAceOnly); + appendTo += qt_ACE_do(host, ToAceOnly, AllowLeadingDot); else appendTo += host; } @@ -1207,7 +1227,7 @@ inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl: return setHost(s, 0, s.length(), QUrl::StrictMode); } - s = qt_ACE_do(QString::fromRawData(begin, len), NormalizeAce); + s = qt_ACE_do(QString::fromRawData(begin, len), NormalizeAce, ForbidLeadingDot); if (s.isEmpty()) { setError(InvalidRegNameError, value); return false; @@ -1583,87 +1603,6 @@ inline void QUrlPrivate::validate() const } } } - -inline const QByteArray &QUrlPrivate::normalized() const -{ - if (QURL_HASFLAG(stateFlags, QUrlPrivate::Normalized)) - return encodedNormalized; - - QUrlPrivate *that = const_cast<QUrlPrivate *>(this); - QURL_SETFLAG(that->stateFlags, QUrlPrivate::Normalized); - - QUrlPrivate tmp = *this; - tmp.scheme = tmp.scheme.toLower(); - tmp.host = tmp.canonicalHost(); - - // ensure the encoded and normalized parts of the URL - tmp.ensureEncodedParts(); - if (tmp.encodedUserName.contains('%')) - q_normalizePercentEncoding(&tmp.encodedUserName, userNameExcludeChars); - if (tmp.encodedPassword.contains('%')) - q_normalizePercentEncoding(&tmp.encodedPassword, passwordExcludeChars); - if (tmp.encodedFragment.contains('%')) - q_normalizePercentEncoding(&tmp.encodedFragment, fragmentExcludeChars); - - if (tmp.encodedPath.contains('%')) { - // the path is a bit special: - // the slashes shouldn't be encoded or decoded. - // They should remain exactly like they are right now - // - // treat the path as a slash-separated sequence of pchar - QByteArray result; - result.reserve(tmp.encodedPath.length()); - if (tmp.encodedPath.startsWith('/')) - result.append('/'); - - const char *data = tmp.encodedPath.constData(); - int lastSlash = 0; - int nextSlash; - do { - ++lastSlash; - nextSlash = tmp.encodedPath.indexOf('/', lastSlash); - int len; - if (nextSlash == -1) - len = tmp.encodedPath.length() - lastSlash; - else - len = nextSlash - lastSlash; - - if (memchr(data + lastSlash, '%', len)) { - // there's at least one percent before the next slash - QByteArray block = QByteArray(data + lastSlash, len); - q_normalizePercentEncoding(&block, pathExcludeChars); - result.append(block); - } else { - // no percents in this path segment, append wholesale - result.append(data + lastSlash, len); - } - - // append the slash too, if it's there - if (nextSlash != -1) - result.append('/'); - - lastSlash = nextSlash; - } while (lastSlash != -1); - - tmp.encodedPath = result; - } - - if (!tmp.scheme.isEmpty()) // relative test - removeDotsFromPath(&tmp.encodedPath); - - int qLen = tmp.query.length(); - for (int i = 0; i < qLen; i++) { - if (qLen - i > 2 && tmp.query.at(i) == '%') { - ++i; - tmp.query[i] = qToLower(tmp.query.at(i)); - ++i; - tmp.query[i] = qToLower(tmp.query.at(i)); - } - } - encodedNormalized = tmp.toEncoded(); - - return encodedNormalized; -} #endif /*! @@ -2976,7 +2915,7 @@ QString QUrl::topLevelDomain(ComponentFormattingOptions options) const { QString tld = qTopLevelDomain(host()); if (options & EncodeUnicode) { - return qt_ACE_do(tld, ToAceOnly); + return qt_ACE_do(tld, ToAceOnly, AllowLeadingDot); } return tld; } @@ -3148,12 +3087,8 @@ QString QUrl::toString(FormattingOptions options) const url += QLatin1String("//"); } - if (!(options & QUrl::RemovePath)) { + if (!(options & QUrl::RemovePath)) d->appendPath(url, options, QUrlPrivate::FullUrl); - // check if we need to remove trailing slashes - if ((options & StripTrailingSlash) && !d->path.isEmpty() && d->path != QLatin1String("/") && url.endsWith(QLatin1Char('/'))) - url.chop(1); - } if (!(options & QUrl::RemoveQuery) && d->hasQuery()) { url += QLatin1Char('?'); @@ -3188,6 +3123,52 @@ QString QUrl::toDisplayString(FormattingOptions options) const } /*! + \since 5.2 + + Returns an adjusted version of the URL. + The output can be customized by passing flags with \a options. + + The encoding options from QUrl::ComponentFormattingOption don't make + much sense for this method, nor does QUrl::PreferLocalFile. + + This is always equivalent to QUrl(url.toString(options)). + + \sa FormattingOptions, toEncoded(), toString() +*/ +QUrl QUrl::adjusted(QUrl::FormattingOptions options) const +{ + if (!isValid()) { + // also catches isEmpty() + return QUrl(); + } + QUrl that = *this; + if (options & RemoveScheme) + that.setScheme(QString()); + if ((options & RemoveAuthority) == RemoveAuthority) { + that.setAuthority(QString()); + } else { + if ((options & RemoveUserInfo) == RemoveUserInfo) + that.setUserInfo(QString()); + else if (options & RemovePassword) + that.setPassword(QString()); + if (options & RemovePort) + that.setPort(-1); + } + if (options & RemoveQuery) + that.setQuery(QString()); + if (options & RemoveFragment) + that.setFragment(QString()); + if (options & RemovePath) { + that.setPath(QString()); + } else if (options & (StripTrailingSlash | RemoveFilename | NormalizePathSegments)) { + QString path; + d->appendPath(path, options, QUrlPrivate::Path); + that.setPath(path); + } + return that; +} + +/*! Returns the encoded representation of the URL if it's valid; otherwise an empty QByteArray is returned. The output can be customized by passing flags with \a options. @@ -3296,7 +3277,7 @@ QString QUrl::fromEncodedComponent_helper(const QByteArray &ba) */ QString QUrl::fromAce(const QByteArray &domain) { - return qt_ACE_do(QString::fromLatin1(domain), NormalizeAce); + return qt_ACE_do(QString::fromLatin1(domain), NormalizeAce, ForbidLeadingDot /*FIXME: make configurable*/); } /*! @@ -3317,7 +3298,7 @@ QString QUrl::fromAce(const QByteArray &domain) */ QByteArray QUrl::toAce(const QString &domain) { - QString result = qt_ACE_do(domain, ToAceOnly); + QString result = qt_ACE_do(domain, ToAceOnly, ForbidLeadingDot /*FIXME: make configurable*/); return result.toLatin1(); } |