summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qurl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io/qurl.cpp')
-rw-r--r--src/corelib/io/qurl.cpp1264
1 files changed, 400 insertions, 864 deletions
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 1a266702eb..4360b5b076 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QUrl
@@ -50,14 +14,18 @@
\ingroup network
\ingroup shared
+ \compares weak
It can parse and construct URLs in both encoded and unencoded
form. QUrl also has support for internationalized domain names
(IDNs).
- The most common way to use QUrl is to initialize it via the
- constructor by passing a QString. Otherwise, setUrl() can also
- be used.
+ The most common way to use QUrl is to initialize it via the constructor by
+ passing a QString containing a full URL. QUrl objects can also be created
+ from a QByteArray containing a full URL using QUrl::fromEncoded(), or
+ heuristically from incomplete URLs using QUrl::fromUserInput(). The URL
+ representation can be obtained from a QUrl using either QUrl::toString() or
+ QUrl::toEncoded().
URLs can be represented in two forms: encoded or unencoded. The
unencoded representation is suitable for showing to users, but
@@ -390,6 +358,25 @@
*/
/*!
+ \enum QUrl::AceProcessingOption
+ \since 6.3
+
+ The ACE processing options control the way URLs are transformed to and from
+ ASCII-Compatible Encoding.
+
+ \value IgnoreIDNWhitelist Ignore the IDN whitelist when converting URLs
+ to Unicode.
+ \value AceTransitionalProcessing Use transitional processing described in UTS #46.
+ This allows better compatibility with IDNA 2003
+ specification.
+
+ The default is to use nontransitional processing and to allow non-ASCII
+ characters only inside URLs whose top-level domains are listed in the IDN whitelist.
+
+ \sa toAce(), fromAce(), idnWhitelist()
+*/
+
+/*!
\fn QUrl::QUrl(QUrl &&other)
Move-constructs a QUrl instance, making it point at the same
@@ -413,22 +400,21 @@
#include "qstringlist.h"
#include "qdebug.h"
#include "qhash.h"
-#include "qdir.h" // for QDir::fromNativeSeparators
#include "qdatastream.h"
#include "private/qipaddress_p.h"
#include "qurlquery.h"
#include "private/qdir_p.h"
-#include <private/qmemory_p.h>
+#include <private/qtools_p.h>
QT_BEGIN_NAMESPACE
-// in qstring.cpp:
-void qt_from_latin1(char16_t *dst, const char *str, size_t size) noexcept;
+using namespace Qt::StringLiterals;
+using namespace QtMiscUtils;
inline static bool isHex(char c)
{
c |= 0x20;
- return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
+ return isAsciiDigit(c) || (c >= 'a' && c <= 'f');
}
static inline QString ftpScheme()
@@ -509,8 +495,8 @@ public:
struct Error {
QString source;
+ qsizetype position;
ErrorCode code;
- int position;
};
QUrlPrivate();
@@ -523,11 +509,11 @@ public:
std::unique_ptr<Error> cloneError() const;
void clearError();
- void setError(ErrorCode errorCode, const QString &source, int supplement = -1);
- ErrorCode validityError(QString *source = nullptr, int *position = nullptr) const;
- bool validateComponent(Section section, const QString &input, int begin, int end);
+ void setError(ErrorCode errorCode, const QString &source, qsizetype supplement = -1);
+ ErrorCode validityError(QString *source = nullptr, qsizetype *position = nullptr) const;
+ bool validateComponent(Section section, const QString &input, qsizetype begin, qsizetype end);
bool validateComponent(Section section, const QString &input)
- { return validateComponent(section, input, 0, uint(input.length())); }
+ { return validateComponent(section, input, 0, input.size()); }
// no QString scheme() const;
void appendAuthority(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const;
@@ -540,15 +526,15 @@ public:
void appendFragment(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const;
// the "end" parameters are like STL iterators: they point to one past the last valid element
- bool setScheme(const QString &value, int len, bool doSetError);
- void setAuthority(const QString &auth, int from, int end, QUrl::ParsingMode mode);
- void setUserInfo(const QString &userInfo, int from, int end);
- void setUserName(const QString &value, int from, int end);
- void setPassword(const QString &value, int from, int end);
- bool setHost(const QString &value, int from, int end, QUrl::ParsingMode mode);
- void setPath(const QString &value, int from, int end);
- void setQuery(const QString &value, int from, int end);
- void setFragment(const QString &value, int from, int end);
+ bool setScheme(const QString &value, qsizetype len, bool doSetError);
+ void setAuthority(const QString &auth, qsizetype from, qsizetype end, QUrl::ParsingMode mode);
+ void setUserInfo(const QString &userInfo, qsizetype from, qsizetype end);
+ void setUserName(const QString &value, qsizetype from, qsizetype end);
+ void setPassword(const QString &value, qsizetype from, qsizetype end);
+ bool setHost(const QString &value, qsizetype from, qsizetype end, QUrl::ParsingMode mode);
+ void setPath(const QString &value, qsizetype from, qsizetype end);
+ void setQuery(const QString &value, qsizetype from, qsizetype end);
+ void setFragment(const QString &value, qsizetype from, qsizetype end);
inline bool hasScheme() const { return sectionIsPresent & Scheme; }
inline bool hasAuthority() const { return sectionIsPresent & Authority; }
@@ -617,7 +603,7 @@ inline QUrlPrivate::~QUrlPrivate()
std::unique_ptr<QUrlPrivate::Error> QUrlPrivate::cloneError() const
{
- return error ? qt_make_unique<Error>(*error) : nullptr;
+ return error ? std::make_unique<Error>(*error) : nullptr;
}
inline void QUrlPrivate::clearError()
@@ -625,13 +611,13 @@ inline void QUrlPrivate::clearError()
error.reset();
}
-inline void QUrlPrivate::setError(ErrorCode errorCode, const QString &source, int supplement)
+inline void QUrlPrivate::setError(ErrorCode errorCode, const QString &source, qsizetype supplement)
{
if (error) {
// don't overwrite an error set in a previous section during parsing
return;
}
- error = qt_make_unique<Error>();
+ error = std::make_unique<Error>();
error->code = errorCode;
error->source = source;
error->position = supplement;
@@ -816,11 +802,11 @@ static const ushort * const fragmentInUrl = userNameInUrl + 6;
static inline void parseDecodedComponent(QString &data)
{
- data.replace(QLatin1Char('%'), QLatin1String("%25"));
+ data.replace(u'%', "%25"_L1);
}
static inline QString
-recodeFromUser(const QString &input, const ushort *actions, int from, int to)
+recodeFromUser(const QString &input, const ushort *actions, qsizetype from, qsizetype to)
{
QString output;
const QChar *begin = input.constData() + from;
@@ -836,14 +822,16 @@ recodeFromUser(const QString &input, const ushort *actions, int from, int to)
static inline void appendToUser(QString &appendTo, QStringView value, QUrl::FormattingOptions options,
const ushort *actions)
{
- // Test ComponentFormattingOptions, ignore FormattingOptions.
- if ((options & 0xFFFF0000) == QUrl::PrettyDecoded) {
+ // The stored value is already QUrl::PrettyDecoded, so there's nothing to
+ // do if that's what the user asked for (test only
+ // ComponentFormattingOptions, ignore FormattingOptions).
+ if ((options & 0xFFFF0000) == QUrl::PrettyDecoded ||
+ !qt_urlRecode(appendTo, value, options, actions))
appendTo += value;
- return;
- }
- if (!qt_urlRecode(appendTo, value, options, actions))
- appendTo += value;
+ // copy nullness, if necessary, because QString::operator+=(QStringView) doesn't
+ if (appendTo.isNull() && !value.isNull())
+ appendTo.detach();
}
inline void QUrlPrivate::appendAuthority(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const
@@ -853,11 +841,11 @@ inline void QUrlPrivate::appendAuthority(QString &appendTo, QUrl::FormattingOpti
// add '@' only if we added anything
if (hasUserName() || (hasPassword() && (options & QUrl::RemovePassword) == 0))
- appendTo += QLatin1Char('@');
+ appendTo += u'@';
}
appendHost(appendTo, options);
if (!(options & QUrl::RemovePort) && port != -1)
- appendTo += QLatin1Char(':') + QString::number(port);
+ appendTo += u':' + QString::number(port);
}
inline void QUrlPrivate::appendUserInfo(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const
@@ -899,7 +887,7 @@ inline void QUrlPrivate::appendUserInfo(QString &appendTo, QUrl::FormattingOptio
if (options & QUrl::RemovePassword || !hasPassword()) {
return;
} else {
- appendTo += QLatin1Char(':');
+ appendTo += u':';
if (!qt_urlRecode(appendTo, password, options, passwordActions))
appendTo += password;
}
@@ -928,14 +916,14 @@ inline void QUrlPrivate::appendPath(QString &appendTo, QUrl::FormattingOptions o
QStringView thePathView(thePath);
if (options & QUrl::RemoveFilename) {
- const int slash = path.lastIndexOf(QLatin1Char('/'));
+ const qsizetype slash = path.lastIndexOf(u'/');
if (slash == -1)
return;
thePathView = QStringView{path}.left(slash + 1);
}
// check if we need to remove trailing slashes
if (options & QUrl::StripTrailingSlash) {
- while (thePathView.length() > 1 && thePathView.endsWith(QLatin1Char('/')))
+ while (thePathView.size() > 1 && thePathView.endsWith(u'/'))
thePathView.chop(1);
}
@@ -958,7 +946,7 @@ inline void QUrlPrivate::appendQuery(QString &appendTo, QUrl::FormattingOptions
// setXXX functions
-inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetError)
+inline bool QUrlPrivate::setScheme(const QString &value, qsizetype len, bool doSetError)
{
// schemes are strictly RFC-compliant:
// scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
@@ -974,17 +962,17 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro
sectionIsPresent |= Scheme;
// validate it:
- int needsLowercasing = -1;
- const ushort *p = value.utf16();
- for (int i = 0; i < len; ++i) {
- if (p[i] >= 'a' && p[i] <= 'z')
+ qsizetype needsLowercasing = -1;
+ const ushort *p = reinterpret_cast<const ushort *>(value.data());
+ for (qsizetype i = 0; i < len; ++i) {
+ if (isAsciiLower(p[i]))
continue;
- if (p[i] >= 'A' && p[i] <= 'Z') {
+ if (isAsciiUpper(p[i])) {
needsLowercasing = i;
continue;
}
if (i) {
- if (p[i] >= '0' && p[i] <= '9')
+ if (isAsciiDigit(p[i]))
continue;
if (p[i] == '+' || p[i] == '-' || p[i] == '.')
continue;
@@ -1003,9 +991,9 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro
if (needsLowercasing != -1) {
// schemes are ASCII only, so we don't need the full Unicode toLower
QChar *schemeData = scheme.data(); // force detaching here
- for (int i = needsLowercasing; i >= 0; --i) {
+ for (qsizetype i = needsLowercasing; i >= 0; --i) {
ushort c = schemeData[i].unicode();
- if (c >= 'A' && c <= 'Z')
+ if (isAsciiUpper(c))
schemeData[i] = QChar(c + 0x20);
}
}
@@ -1023,7 +1011,7 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro
return true;
}
-inline void QUrlPrivate::setAuthority(const QString &auth, int from, int end, QUrl::ParsingMode mode)
+inline void QUrlPrivate::setAuthority(const QString &auth, qsizetype from, qsizetype end, QUrl::ParsingMode mode)
{
sectionIsPresent &= ~Authority;
sectionIsPresent |= Host;
@@ -1031,33 +1019,33 @@ inline void QUrlPrivate::setAuthority(const QString &auth, int from, int end, QU
// we never actually _loop_
while (from != end) {
- int userInfoIndex = auth.indexOf(QLatin1Char('@'), from);
- if (uint(userInfoIndex) < uint(end)) {
+ qsizetype userInfoIndex = auth.indexOf(u'@', from);
+ if (size_t(userInfoIndex) < size_t(end)) {
setUserInfo(auth, from, userInfoIndex);
if (mode == QUrl::StrictMode && !validateComponent(UserInfo, auth, from, userInfoIndex))
break;
from = userInfoIndex + 1;
}
- int colonIndex = auth.lastIndexOf(QLatin1Char(':'), end - 1);
+ qsizetype colonIndex = auth.lastIndexOf(u':', end - 1);
if (colonIndex < from)
colonIndex = -1;
- if (uint(colonIndex) < uint(end)) {
+ if (size_t(colonIndex) < size_t(end)) {
if (auth.at(from).unicode() == '[') {
// check if colonIndex isn't inside the "[...]" part
- int closingBracket = auth.indexOf(QLatin1Char(']'), from);
- if (uint(closingBracket) > uint(colonIndex))
+ qsizetype closingBracket = auth.indexOf(u']', from);
+ if (size_t(closingBracket) > size_t(colonIndex))
colonIndex = -1;
}
}
- if (uint(colonIndex) < uint(end) - 1) {
+ if (size_t(colonIndex) < size_t(end) - 1) {
// found a colon with digits after it
unsigned long x = 0;
- for (int i = colonIndex + 1; i < end; ++i) {
+ for (qsizetype i = colonIndex + 1; i < end; ++i) {
ushort c = auth.at(i).unicode();
- if (c >= '0' && c <= '9') {
+ if (isAsciiDigit(c)) {
x *= 10;
x += c - '0';
} else {
@@ -1074,8 +1062,8 @@ inline void QUrlPrivate::setAuthority(const QString &auth, int from, int end, QU
}
}
- setHost(auth, from, qMin<uint>(end, colonIndex), mode);
- if (mode == QUrl::StrictMode && !validateComponent(Host, auth, from, qMin<uint>(end, colonIndex))) {
+ setHost(auth, from, qMin<size_t>(end, colonIndex), mode);
+ if (mode == QUrl::StrictMode && !validateComponent(Host, auth, from, qMin<size_t>(end, colonIndex))) {
// clear host too
sectionIsPresent &= ~Authority;
break;
@@ -1092,12 +1080,12 @@ inline void QUrlPrivate::setAuthority(const QString &auth, int from, int end, QU
port = -1;
}
-inline void QUrlPrivate::setUserInfo(const QString &userInfo, int from, int end)
+inline void QUrlPrivate::setUserInfo(const QString &userInfo, qsizetype from, qsizetype end)
{
- int delimIndex = userInfo.indexOf(QLatin1Char(':'), from);
- setUserName(userInfo, from, qMin<uint>(delimIndex, end));
+ qsizetype delimIndex = userInfo.indexOf(u':', from);
+ setUserName(userInfo, from, qMin<size_t>(delimIndex, end));
- if (uint(delimIndex) >= uint(end)) {
+ if (size_t(delimIndex) >= size_t(end)) {
password.clear();
sectionIsPresent &= ~Password;
} else {
@@ -1105,31 +1093,31 @@ inline void QUrlPrivate::setUserInfo(const QString &userInfo, int from, int end)
}
}
-inline void QUrlPrivate::setUserName(const QString &value, int from, int end)
+inline void QUrlPrivate::setUserName(const QString &value, qsizetype from, qsizetype end)
{
sectionIsPresent |= UserName;
userName = recodeFromUser(value, userNameInIsolation, from, end);
}
-inline void QUrlPrivate::setPassword(const QString &value, int from, int end)
+inline void QUrlPrivate::setPassword(const QString &value, qsizetype from, qsizetype end)
{
sectionIsPresent |= Password;
password = recodeFromUser(value, passwordInIsolation, from, end);
}
-inline void QUrlPrivate::setPath(const QString &value, int from, int end)
+inline void QUrlPrivate::setPath(const QString &value, qsizetype from, qsizetype end)
{
// sectionIsPresent |= Path; // not used, save some cycles
path = recodeFromUser(value, pathInIsolation, from, end);
}
-inline void QUrlPrivate::setFragment(const QString &value, int from, int end)
+inline void QUrlPrivate::setFragment(const QString &value, qsizetype from, qsizetype end)
{
sectionIsPresent |= Fragment;
fragment = recodeFromUser(value, fragmentInIsolation, from, end);
}
-inline void QUrlPrivate::setQuery(const QString &value, int from, int iend)
+inline void QUrlPrivate::setQuery(const QString &value, qsizetype from, qsizetype iend)
{
sectionIsPresent |= Query;
query = recodeFromUser(value, queryInIsolation, from, iend);
@@ -1179,7 +1167,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 && !(options & 0x4000000))
- appendTo += qt_ACE_do(host, ToAceOnly, AllowLeadingDot);
+ appendTo += qt_ACE_do(host, ToAceOnly, AllowLeadingDot, {});
else
appendTo += host;
}
@@ -1199,16 +1187,14 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar
const QChar *const origBegin = begin;
if (begin[3].unicode() != '.')
return &begin[3];
- if ((begin[2].unicode() >= 'A' && begin[2].unicode() <= 'F') ||
- (begin[2].unicode() >= 'a' && begin[2].unicode() <= 'f') ||
- (begin[2].unicode() >= '0' && begin[2].unicode() <= '9')) {
+ if (isHexDigit(begin[2].unicode())) {
// this is so unlikely that we'll just go down the slow path
// decode the whole string, skipping the "[vH." and "]" which we already know to be there
host += QStringView(begin, 4);
// uppercase the version, if necessary
if (begin[2].unicode() >= 'a')
- host[host.length() - 2] = QChar{begin[2].unicode() - 0x20};
+ host[host.size() - 2] = QChar{begin[2].unicode() - 0x20};
begin += 4;
--end;
@@ -1220,18 +1206,14 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar
}
for ( ; begin != end; ++begin) {
- if (begin->unicode() >= 'A' && begin->unicode() <= 'Z')
- host += *begin;
- else if (begin->unicode() >= 'a' && begin->unicode() <= 'z')
- host += *begin;
- else if (begin->unicode() >= '0' && begin->unicode() <= '9')
+ if (isAsciiLetterOrNumber(begin->unicode()))
host += *begin;
else if (begin->unicode() < 0x80 && strchr(acceptable, begin->unicode()) != nullptr)
host += *begin;
else
return decoded.isEmpty() ? begin : &origBegin[2];
}
- host += QLatin1Char(']');
+ host += u']';
return nullptr;
}
return &origBegin[2];
@@ -1240,54 +1222,57 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar
// ONLY the IPv6 address is parsed here, WITHOUT the brackets
static const QChar *parseIp6(QString &host, const QChar *begin, const QChar *end, QUrl::ParsingMode mode)
{
- // ### Update to use QStringView once QStringView::indexOf and QStringView::lastIndexOf exists
- QString decoded;
+ QStringView decoded(begin, end);
+ QString decodedBuffer;
if (mode == QUrl::TolerantMode) {
// this struct is kept in automatic storage because it's only 4 bytes
const ushort decodeColon[] = { decode(':'), 0 };
- if (qt_urlRecode(decoded, QStringView{begin, end}, QUrl::ComponentFormattingOption::PrettyDecoded, decodeColon) == 0)
- decoded = QString(begin, end-begin);
- } else {
- decoded = QString(begin, end-begin);
+ if (qt_urlRecode(decodedBuffer, decoded, QUrl::ComponentFormattingOption::PrettyDecoded, decodeColon))
+ decoded = decodedBuffer;
}
- const QLatin1String zoneIdIdentifier("%25");
+ const QStringView zoneIdIdentifier(u"%25");
QIPAddressUtils::IPv6Address address;
- QString zoneId;
-
- const QChar *endBeforeZoneId = decoded.constEnd();
+ QStringView zoneId;
- int zoneIdPosition = decoded.indexOf(zoneIdIdentifier);
+ qsizetype zoneIdPosition = decoded.indexOf(zoneIdIdentifier);
if ((zoneIdPosition != -1) && (decoded.lastIndexOf(zoneIdIdentifier) == zoneIdPosition)) {
zoneId = decoded.mid(zoneIdPosition + zoneIdIdentifier.size());
- endBeforeZoneId = decoded.constBegin() + zoneIdPosition;
+ decoded.truncate(zoneIdPosition);
+ // was there anything after the zone ID separator?
if (zoneId.isEmpty())
return end;
}
- const QChar *ret = QIPAddressUtils::parseIp6(address, decoded.constBegin(), endBeforeZoneId);
+ // did the address become empty after removing the zone ID?
+ // (it might have always been empty)
+ if (decoded.isEmpty())
+ return end;
+
+ const QChar *ret = QIPAddressUtils::parseIp6(address, decoded.constBegin(), decoded.constEnd());
if (ret)
return begin + (ret - decoded.constBegin());
- host.reserve(host.size() + (decoded.constEnd() - decoded.constBegin()));
- host += QLatin1Char('[');
+ host.reserve(host.size() + (end - begin) + 2); // +2 for the brackets
+ host += u'[';
QIPAddressUtils::toString(host, address);
if (!zoneId.isEmpty()) {
host += zoneIdIdentifier;
host += zoneId;
}
- host += QLatin1Char(']');
+ host += u']';
return nullptr;
}
-inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl::ParsingMode mode)
+inline bool
+QUrlPrivate::setHost(const QString &value, qsizetype from, qsizetype iend, QUrl::ParsingMode mode)
{
const QChar *begin = value.constData() + from;
const QChar *end = value.constData() + iend;
- const int len = end - begin;
+ const qsizetype len = end - begin;
host.clear();
sectionIsPresent |= Host;
if (len == 0)
@@ -1339,7 +1324,7 @@ inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl:
// Unicode encoding (some non-ASCII characters case-fold to digits
// when nameprepping is done)
//
- // The qt_ACE_do function below applies nameprepping and the STD3 check.
+ // The qt_ACE_do function below does IDNA normalization and the STD3 check.
// That means a Unicode string may become an IPv4 address, but it cannot
// produce a '[' or a '%'.
@@ -1348,17 +1333,17 @@ inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl:
if (mode == QUrl::TolerantMode && qt_urlRecode(s, QStringView{begin, end}, { }, nullptr)) {
// something was decoded
// anything encoded left?
- int pos = s.indexOf(QChar(0x25)); // '%'
+ qsizetype pos = s.indexOf(QChar(0x25)); // '%'
if (pos != -1) {
setError(InvalidRegNameError, s, pos);
return false;
}
// recurse
- return setHost(s, 0, s.length(), QUrl::StrictMode);
+ return setHost(s, 0, s.size(), QUrl::StrictMode);
}
- s = qt_ACE_do(QStringView(begin, len), NormalizeAce, ForbidLeadingDot);
+ s = qt_ACE_do(value.mid(from, iend - from), NormalizeAce, ForbidLeadingDot, {});
if (s.isEmpty()) {
setError(InvalidRegNameError, value);
return false;
@@ -1388,15 +1373,15 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode
clearError();
// find the important delimiters
- int colon = -1;
- int question = -1;
- int hash = -1;
- const int len = url.length();
+ qsizetype colon = -1;
+ qsizetype question = -1;
+ qsizetype hash = -1;
+ const qsizetype len = url.size();
const QChar *const begin = url.constData();
const ushort *const data = reinterpret_cast<const ushort *>(begin);
- for (int i = 0; i < len; ++i) {
- uint uc = data[i];
+ for (qsizetype i = 0; i < len; ++i) {
+ size_t uc = data[i];
if (uc == '#' && hash == -1) {
hash = i;
@@ -1413,7 +1398,7 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode
}
// check if we have a scheme
- int hierStart;
+ qsizetype hierStart;
if (colon != -1 && setScheme(url, colon, /* don't set error */ false)) {
hierStart = colon + 1;
} else {
@@ -1423,12 +1408,12 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode
hierStart = 0;
}
- int pathStart;
- int hierEnd = qMin<uint>(qMin<uint>(question, hash), len);
+ qsizetype pathStart;
+ qsizetype hierEnd = qMin<size_t>(qMin<size_t>(question, hash), len);
if (hierEnd - hierStart >= 2 && data[hierStart] == '/' && data[hierStart + 1] == '/') {
// we have an authority, it ends at the first slash after these
- int authorityEnd = hierEnd;
- for (int i = hierStart + 2; i < authorityEnd ; ++i) {
+ qsizetype authorityEnd = hierEnd;
+ for (qsizetype i = hierStart + 2; i < authorityEnd ; ++i) {
if (data[i] == '/') {
authorityEnd = i;
break;
@@ -1453,8 +1438,8 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode
path.clear();
}
- if (uint(question) < uint(hash))
- setQuery(url, question + 1, qMin<uint>(hash, len));
+ if (size_t(question) < size_t(hash))
+ setQuery(url, question + 1, qMin<size_t>(hash, len));
if (hash != -1)
setFragment(url, hash + 1, len);
@@ -1470,7 +1455,7 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode
if (!validateComponent(Path, url, pathStart, hierEnd))
return;
- if (uint(question) < uint(hash) && !validateComponent(Query, url, question + 1, qMin<uint>(hash, len)))
+ if (size_t(question) < size_t(hash) && !validateComponent(Query, url, question + 1, qMin<size_t>(hash, len)))
return;
if (hash != -1)
validateComponent(Fragment, url, hash + 1, len);
@@ -1484,19 +1469,19 @@ QString QUrlPrivate::toLocalFile(QUrl::FormattingOptions options) const
// magic for shared drive on windows
if (!host.isEmpty()) {
- tmp = QLatin1String("//") + host;
+ tmp = "//"_L1 + host;
#ifdef Q_OS_WIN // QTBUG-42346, WebDAV is visible as local file on Windows only.
if (scheme == webDavScheme())
tmp += webDavSslTag();
#endif
- if (!ourPath.isEmpty() && !ourPath.startsWith(QLatin1Char('/')))
- tmp += QLatin1Char('/');
+ if (!ourPath.isEmpty() && !ourPath.startsWith(u'/'))
+ tmp += u'/';
tmp += ourPath;
} else {
tmp = ourPath;
#ifdef Q_OS_WIN
// magic for drives on windows
- if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':'))
+ if (ourPath.length() > 2 && ourPath.at(0) == u'/' && ourPath.at(2) == u':')
tmp.remove(0, 1);
#endif
}
@@ -1517,7 +1502,7 @@ inline QString QUrlPrivate::mergePaths(const QString &relativePath) const
// path, then return a string consisting of "/" concatenated with
// the reference's path; otherwise,
if (!host.isEmpty() && path.isEmpty())
- return QLatin1Char('/') + relativePath;
+ return u'/' + relativePath;
// Return a string consisting of the reference's path component
// appended to all but the last segment of the base URI's path
@@ -1525,10 +1510,10 @@ inline QString QUrlPrivate::mergePaths(const QString &relativePath) const
// base URI path, or excluding the entire base URI path if it does
// not contain any "/" characters).
QString newPath;
- if (!path.contains(QLatin1Char('/')))
+ if (!path.contains(u'/'))
newPath = relativePath;
else
- newPath = QStringView{path}.left(path.lastIndexOf(QLatin1Char('/')) + 1) + relativePath;
+ newPath = QStringView{path}.left(path.lastIndexOf(u'/') + 1) + relativePath;
return newPath;
}
@@ -1574,7 +1559,7 @@ static void removeDotsFromPath(QString *path)
in += 2;
continue;
} else if (in == end - 2 && in[0].unicode() == '/' && in[1].unicode() == '.') {
- *out++ = QLatin1Char('/');
+ *out++ = u'/';
in += 2;
break;
}
@@ -1615,7 +1600,7 @@ static void removeDotsFromPath(QString *path)
path->truncate(out - path->constData());
}
-inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, int *position) const
+inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, qsizetype *position) const
{
Q_ASSERT(!source == !position);
if (error) {
@@ -1641,8 +1626,8 @@ inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, int *p
if (path.isEmpty())
return NoError;
- if (path.at(0) == QLatin1Char('/')) {
- if (hasAuthority() || path.length() == 1 || path.at(1) != QLatin1Char('/'))
+ if (path.at(0) == u'/') {
+ if (hasAuthority() || path.size() == 1 || path.at(1) != u'/')
return NoError;
if (source) {
*source = path;
@@ -1662,7 +1647,7 @@ inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, int *p
return NoError;
// check for a path of "text:text/"
- for (int i = 0; i < path.length(); ++i) {
+ for (qsizetype i = 0; i < path.size(); ++i) {
ushort c = path.at(i).unicode();
if (c == '/') {
// found the slash before the colon
@@ -1681,7 +1666,7 @@ inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, int *p
}
bool QUrlPrivate::validateComponent(QUrlPrivate::Section section, const QString &input,
- int begin, int end)
+ qsizetype begin, qsizetype end)
{
// What we need to look out for, that the regular parser tolerates:
// - percent signs not followed by two hex digits
@@ -1702,13 +1687,13 @@ bool QUrlPrivate::validateComponent(QUrlPrivate::Section section, const QString
Q_ASSERT(section != Authority && section != Hierarchy && section != FullUrl);
const ushort *const data = reinterpret_cast<const ushort *>(input.constData());
- for (uint i = uint(begin); i < uint(end); ++i) {
+ for (size_t i = size_t(begin); i < size_t(end); ++i) {
uint uc = data[i];
if (uc >= 0x80)
continue;
bool error = false;
- if ((uc == '%' && (uint(end) < i + 2 || !isHex(data[i + 1]) || !isHex(data[i + 2])))
+ if ((uc == '%' && (size_t(end) < i + 2 || !isHex(data[i + 1]) || !isHex(data[i + 2])))
|| uc <= 0x20 || strchr(forbidden, uc)) {
// found an error
error = true;
@@ -1726,7 +1711,7 @@ bool QUrlPrivate::validateComponent(QUrlPrivate::Section section, const QString
if (section == UserInfo) {
// is it the user name or the password?
errorCode = InvalidUserNameError;
- for (uint j = uint(begin); j < i; ++j)
+ for (size_t j = size_t(begin); j < i; ++j)
if (data[j] == ':') {
errorCode = InvalidPasswordError;
break;
@@ -1759,7 +1744,7 @@ inline void QUrlPrivate::validate() const
if (!isHostValid)
return;
- if (scheme == QLatin1String("mailto")) {
+ if (scheme == "mailto"_L1) {
if (!host.isEmpty() || port != -1 || !userName.isEmpty() || !password.isEmpty()) {
that->isValid = false;
that->errorInfo.setParams(0, QT_TRANSLATE_NOOP(QUrl, "expected empty host, username,"
@@ -1788,9 +1773,15 @@ inline void QUrlPrivate::validate() const
help avoid missing QUrl::resolved() calls, and other misuses of
QString to QUrl conversions.
- \oldcode
+ For example, if you have code like
+
+ \code
url = filename; // probably not what you want
- \newcode
+ \endcode
+
+ you can rewrite it as
+
+ \code
url = QUrl::fromLocalFile(filename);
url = baseurl.resolved(QUrl(filename));
\endcode
@@ -1800,10 +1791,23 @@ inline void QUrlPrivate::validate() const
/*!
- Constructs a URL by parsing \a url. QUrl will automatically percent encode
+ Constructs a URL by parsing \a url. Note this constructor expects a proper
+ URL or URL-Reference and will not attempt to guess intent. For example, the
+ following declaration:
+
+ \snippet code/src_corelib_io_qurl.cpp constructor-url-reference
+
+ Will construct a valid URL but it may not be what one expects, as the
+ scheme() part of the input is missing. For a string like the above,
+ applications may want to use fromUserInput(). For this constructor or
+ setUrl(), the following is probably what was intended:
+
+ \snippet code/src_corelib_io_qurl.cpp constructor-url
+
+ QUrl will automatically percent encode
all characters that are not allowed in a URL and decode the percent-encoded
sequences that represent an unreserved character (letters, digits, hyphens,
- undercores, dots and tildes). All other characters are left in their
+ underscores, dots and tildes). All other characters are left in their
original forms.
Parses the \a url using the parser mode \a parsingMode. In TolerantMode
@@ -1845,7 +1849,7 @@ QUrl::QUrl() : d(nullptr)
/*!
Constructs a copy of \a other.
*/
-QUrl::QUrl(const QUrl &other) : d(other.d)
+QUrl::QUrl(const QUrl &other) noexcept : d(other.d)
{
if (d)
d->ref.ref();
@@ -1907,7 +1911,7 @@ void QUrl::clear()
Parses \a url and sets this object to that value. QUrl will automatically
percent encode all characters that are not allowed in a URL and decode the
percent-encoded sequences that represent an unreserved character (letters,
- digits, hyphens, undercores, dots and tildes). All other characters are
+ digits, hyphens, underscores, dots and tildes). All other characters are
left in their original forms.
Parses the \a url using the parser mode \a parsingMode. In TolerantMode
@@ -1932,21 +1936,6 @@ void QUrl::setUrl(const QString &url, ParsingMode parsingMode)
}
/*!
- \fn void QUrl::setEncodedUrl(const QByteArray &encodedUrl, ParsingMode parsingMode)
- \deprecated
- Constructs a URL by parsing the contents of \a encodedUrl.
-
- \a encodedUrl is assumed to be a URL string in percent encoded
- form, containing only ASCII characters.
-
- The parsing mode \a parsingMode is used for parsing \a encodedUrl.
-
- \obsolete Use setUrl(QString::fromUtf8(encodedUrl), parsingMode)
-
- \sa setUrl()
-*/
-
-/*!
Sets the scheme of the URL to \a scheme. As a scheme can only
contain ASCII characters, no conversion or decoding is done on the
input. It must also start with an ASCII letter.
@@ -1954,7 +1943,7 @@ void QUrl::setUrl(const QString &url, ParsingMode parsingMode)
The scheme describes the type (or protocol) of the URL. It's
represented by one or more ASCII characters at the start the URL.
- A scheme is strictly \l {http://www.ietf.org/rfc/rfc3986.txt} {RFC 3986}-compliant:
+ A scheme is strictly \l {RFC 3986}-compliant:
\tt {scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )}
The following example shows a URL where the scheme is "ftp":
@@ -1979,7 +1968,7 @@ void QUrl::setScheme(const QString &scheme)
d->flags &= ~QUrlPrivate::IsLocalFile;
d->scheme.clear();
} else {
- d->setScheme(scheme, scheme.length(), /* do set error */ true);
+ d->setScheme(scheme, scheme.size(), /* do set error */ true);
}
}
@@ -2039,7 +2028,7 @@ void QUrl::setAuthority(const QString &authority, ParsingMode mode)
return;
}
- d->setAuthority(authority, 0, authority.length(), mode);
+ d->setAuthority(authority, 0, authority.size(), mode);
if (authority.isNull()) {
// QUrlPrivate::setAuthority cleared almost everything
// but it leaves the Host bit set
@@ -2110,7 +2099,7 @@ void QUrl::setUserInfo(const QString &userInfo, ParsingMode mode)
return;
}
- d->setUserInfo(trimmed, 0, trimmed.length());
+ d->setUserInfo(trimmed, 0, trimmed.size());
if (userInfo.isNull()) {
// QUrlPrivate::setUserInfo cleared almost everything
// but it leaves the UserName bit set
@@ -2182,7 +2171,7 @@ void QUrl::setUserName(const QString &userName, ParsingMode mode)
mode = TolerantMode;
}
- d->setUserName(data, 0, data.length());
+ d->setUserName(data, 0, data.size());
if (userName.isNull())
d->sectionIsPresent &= ~QUrlPrivate::UserName;
else if (mode == StrictMode && !d->validateComponent(QUrlPrivate::UserName, userName))
@@ -2215,35 +2204,6 @@ QString QUrl::userName(ComponentFormattingOptions options) const
}
/*!
- \fn void QUrl::setEncodedUserName(const QByteArray &userName)
- \deprecated
- \since 4.4
-
- Sets the URL's user name to the percent-encoded \a userName. The \a
- userName is part of the user info element in the authority of the
- URL, as described in setUserInfo().
-
- \obsolete Use setUserName(QString::fromUtf8(userName))
-
- \sa setUserName(), encodedUserName(), setUserInfo()
-*/
-
-/*!
- \fn QByteArray QUrl::encodedUserName() const
- \deprecated
- \since 4.4
-
- Returns the user name of the URL if it is defined; otherwise
- an empty string is returned. The returned value will have its
- non-ASCII and other control characters percent-encoded, as in
- toEncoded().
-
- \obsolete Use userName(QUrl::FullyEncoded).toLatin1()
-
- \sa setEncodedUserName()
-*/
-
-/*!
Sets the URL's password to \a password. The \a password is part of
the user info element in the authority of the URL, as described in
setUserInfo().
@@ -2274,7 +2234,7 @@ void QUrl::setPassword(const QString &password, ParsingMode mode)
mode = TolerantMode;
}
- d->setPassword(data, 0, data.length());
+ d->setPassword(data, 0, data.size());
if (password.isNull())
d->sectionIsPresent &= ~QUrlPrivate::Password;
else if (mode == StrictMode && !d->validateComponent(QUrlPrivate::Password, password))
@@ -2307,35 +2267,6 @@ QString QUrl::password(ComponentFormattingOptions options) const
}
/*!
- \fn void QUrl::setEncodedPassword(const QByteArray &password)
- \deprecated
- \since 4.4
-
- Sets the URL's password to the percent-encoded \a password. The \a
- password is part of the user info element in the authority of the
- URL, as described in setUserInfo().
-
- \obsolete Use setPassword(QString::fromUtf8(password));
-
- \sa setPassword(), encodedPassword(), setUserInfo()
-*/
-
-/*!
- \fn QByteArray QUrl::encodedPassword() const
- \deprecated
- \since 4.4
-
- Returns the password of the URL if it is defined; otherwise an
- empty string is returned. The returned value will have its
- non-ASCII and other control characters percent-encoded, as in
- toEncoded().
-
- \obsolete Use password(QUrl::FullyEncoded).toLatin1()
-
- \sa setEncodedPassword(), toEncoded()
-*/
-
-/*!
Sets the host of the URL to \a host. The host is part of the
authority.
@@ -2365,18 +2296,18 @@ void QUrl::setHost(const QString &host, ParsingMode mode)
mode = TolerantMode;
}
- if (d->setHost(data, 0, data.length(), mode)) {
+ if (d->setHost(data, 0, data.size(), mode)) {
if (host.isNull())
d->sectionIsPresent &= ~QUrlPrivate::Host;
- } else if (!data.startsWith(QLatin1Char('['))) {
+ } else if (!data.startsWith(u'[')) {
// setHost failed, it might be IPv6 or IPvFuture in need of bracketing
Q_ASSERT(d->error);
- data.prepend(QLatin1Char('['));
- data.append(QLatin1Char(']'));
- if (!d->setHost(data, 0, data.length(), mode)) {
+ data.prepend(u'[');
+ data.append(u']');
+ if (!d->setHost(data, 0, data.size(), mode)) {
// failed again
- if (data.contains(QLatin1Char(':'))) {
+ if (data.contains(u':')) {
// source data contains ':', so it's an IPv6 error
d->error->code = QUrlPrivate::InvalidIPv6AddressError;
}
@@ -2410,47 +2341,13 @@ QString QUrl::host(ComponentFormattingOptions options) const
QString result;
if (d) {
d->appendHost(result, options);
- if (result.startsWith(QLatin1Char('[')))
- result = result.mid(1, result.length() - 2);
+ if (result.startsWith(u'['))
+ result = result.mid(1, result.size() - 2);
}
return result;
}
/*!
- \fn void QUrl::setEncodedHost(const QByteArray &host)
- \deprecated
- \since 4.4
-
- Sets the URL's host to the ACE- or percent-encoded \a host. The \a
- host is part of the user info element in the authority of the
- URL, as described in setAuthority().
-
- \obsolete Use setHost(QString::fromUtf8(host)).
-
- \sa setHost(), encodedHost(), setAuthority(), fromAce()
-*/
-
-/*!
- \fn QByteArray QUrl::encodedHost() const
- \deprecated
- \since 4.4
-
- Returns the host part of the URL if it is defined; otherwise
- an empty string is returned.
-
- Note: encodedHost() does not return percent-encoded hostnames. Instead,
- the ACE-encoded (bare ASCII in Punycode encoding) form will be
- returned for any non-ASCII hostname.
-
- This function is equivalent to calling QUrl::toAce() on the return
- value of host().
-
- \obsolete Use host(QUrl::FullyEncoded).toLatin1() or toAce(host()).
-
- \sa setEncodedHost()
-*/
-
-/*!
Sets the port of the URL to \a port. The port is part of the
authority of the URL, as described in setAuthority().
@@ -2524,7 +2421,7 @@ void QUrl::setPath(const QString &path, ParsingMode mode)
mode = TolerantMode;
}
- d->setPath(data, 0, data.length());
+ d->setPath(data, 0, data.size());
// optimized out, since there is no path delimiter
// if (path.isNull())
@@ -2576,42 +2473,6 @@ QString QUrl::path(ComponentFormattingOptions options) const
}
/*!
- \fn void QUrl::setEncodedPath(const QByteArray &path)
- \deprecated
- \since 4.4
-
- Sets the URL's path to the percent-encoded \a path. The path is
- the part of the URL that comes after the authority but before the
- query string.
-
- \image qurl-ftppath.png
-
- For non-hierarchical schemes, the path will be everything
- following the scheme declaration, as in the following example:
-
- \image qurl-mailtopath.png
-
- \obsolete Use setPath(QString::fromUtf8(path)).
-
- \sa setPath(), encodedPath(), setUserInfo()
-*/
-
-/*!
- \fn QByteArray QUrl::encodedPath() const
- \deprecated
- \since 4.4
-
- Returns the path of the URL if it is defined; otherwise an
- empty string is returned. The returned value will have its
- non-ASCII and other control characters percent-encoded, as in
- toEncoded().
-
- \obsolete Use path(QUrl::FullyEncoded).toLatin1().
-
- \sa setEncodedPath(), toEncoded()
-*/
-
-/*!
\since 5.2
Returns the name of the file, excluding the directory path.
@@ -2635,7 +2496,7 @@ QString QUrl::path(ComponentFormattingOptions options) const
QString QUrl::fileName(ComponentFormattingOptions options) const
{
const QString ourPath = path(options);
- const int slash = ourPath.lastIndexOf(QLatin1Char('/'));
+ const qsizetype slash = ourPath.lastIndexOf(u'/');
if (slash == -1)
return ourPath;
return ourPath.mid(slash + 1);
@@ -2696,7 +2557,7 @@ void QUrl::setQuery(const QString &query, ParsingMode mode)
mode = TolerantMode;
}
- d->setQuery(data, 0, data.length());
+ d->setQuery(data, 0, data.size());
if (query.isNull())
d->sectionIsPresent &= ~QUrlPrivate::Query;
else if (mode == StrictMode && !d->validateComponent(QUrlPrivate::Query, query))
@@ -2704,29 +2565,6 @@ void QUrl::setQuery(const QString &query, ParsingMode mode)
}
/*!
- \fn void QUrl::setEncodedQuery(const QByteArray &query)
- \deprecated
-
- Sets the query string of the URL to \a query. The string is
- inserted as-is, and no further encoding is performed when calling
- toEncoded().
-
- This function is useful if you need to pass a query string that
- does not fit into the key-value pattern, or that uses a different
- scheme for encoding special characters than what is suggested by
- QUrl.
-
- Passing a value of QByteArray() to \a query (a null QByteArray) unsets
- the query completely. However, passing a value of QByteArray("")
- will set the query to an empty value, as if the original URL
- had a lone "?".
-
- \obsolete Use setQuery, which has the same null / empty behavior.
-
- \sa encodedQuery(), hasQuery()
-*/
-
-/*!
\overload
\since 5.0
Sets the query string of the URL to \a query.
@@ -2751,248 +2589,6 @@ void QUrl::setQuery(const QUrlQuery &query)
}
/*!
- \fn void QUrl::setQueryItems(const QList<QPair<QString, QString> > &query)
- \deprecated
-
- Sets the query string of the URL to an encoded version of \a
- query. The contents of \a query are converted to a string
- internally, each pair delimited by the character returned by
- \l {QUrlQuery::queryPairDelimiter()}{queryPairDelimiter()}, and the key and value are delimited by
- \l {QUrlQuery::queryValueDelimiter()}{queryValueDelimiter()}
-
- \note This method does not encode spaces (ASCII 0x20) as plus (+) signs,
- like HTML forms do. If you need that kind of encoding, you must encode
- the value yourself and use QUrl::setEncodedQueryItems.
-
- \obsolete Use QUrlQuery and setQuery().
-
- \sa queryItems(), setEncodedQueryItems()
-*/
-
-/*!
- \fn void QUrl::setEncodedQueryItems(const QList<QPair<QByteArray, QByteArray> > &query)
- \deprecated
- \since 4.4
-
- Sets the query string of the URL to the encoded version of \a
- query. The contents of \a query are converted to a string
- internally, each pair delimited by the character returned by
- \l {QUrlQuery::queryPairDelimiter()}{queryPairDelimiter()}, and the key and value are delimited by
- \l {QUrlQuery::queryValueDelimiter()}{queryValueDelimiter()}.
-
- \obsolete Use QUrlQuery and setQuery().
-
- \sa encodedQueryItems(), setQueryItems()
-*/
-
-/*!
- \fn void QUrl::addQueryItem(const QString &key, const QString &value)
- \deprecated
-
- Inserts the pair \a key = \a value into the query string of the
- URL.
-
- The key-value pair is encoded before it is added to the query. The
- pair is converted into separate strings internally. The \a key and
- \a value is first encoded into UTF-8 and then delimited by the
- character returned by \l {QUrlQuery::queryValueDelimiter()}{queryValueDelimiter()}.
- Each key-value pair is delimited by the character returned by
- \l {QUrlQuery::queryPairDelimiter()}{queryPairDelimiter()}
-
- \note This method does not encode spaces (ASCII 0x20) as plus (+) signs,
- like HTML forms do. If you need that kind of encoding, you must encode
- the value yourself and use QUrl::addEncodedQueryItem.
-
- \obsolete Use QUrlQuery and setQuery().
-
- \sa addEncodedQueryItem()
-*/
-
-/*!
- \fn void QUrl::addEncodedQueryItem(const QByteArray &key, const QByteArray &value)
- \deprecated
- \since 4.4
-
- Inserts the pair \a key = \a value into the query string of the
- URL.
-
- \obsolete Use QUrlQuery and setQuery().
-
- \sa addQueryItem()
-*/
-
-/*!
- \fn QList<QPair<QString, QString> > QUrl::queryItems() const
- \deprecated
-
- Returns the query string of the URL, as a map of keys and values.
-
- \note This method does not decode spaces plus (+) signs as spaces (ASCII
- 0x20), like HTML forms do. If you need that kind of decoding, you must
- use QUrl::encodedQueryItems and decode the data yourself.
-
- \obsolete Use QUrlQuery.
-
- \sa setQueryItems(), setEncodedQuery()
-*/
-
-/*!
- \fn QList<QPair<QByteArray, QByteArray> > QUrl::encodedQueryItems() const
- \deprecated
- \since 4.4
-
- Returns the query string of the URL, as a map of encoded keys and values.
-
- \obsolete Use QUrlQuery.
-
- \sa setEncodedQueryItems(), setQueryItems(), setEncodedQuery()
-*/
-
-/*!
- \fn bool QUrl::hasQueryItem(const QString &key) const
- \deprecated
-
- Returns \c true if there is a query string pair whose key is equal
- to \a key from the URL.
-
- \obsolete Use QUrlQuery.
-
- \sa hasEncodedQueryItem()
-*/
-
-/*!
- \fn bool QUrl::hasEncodedQueryItem(const QByteArray &key) const
- \deprecated
- \since 4.4
-
- Returns \c true if there is a query string pair whose key is equal
- to \a key from the URL.
-
- \obsolete Use QUrlQuery.
-
- \sa hasQueryItem()
-*/
-
-/*!
- \fn QString QUrl::queryItemValue(const QString &key) const
- \deprecated
-
- Returns the first query string value whose key is equal to \a key
- from the URL.
-
- \note This method does not decode spaces plus (+) signs as spaces (ASCII
- 0x20), like HTML forms do. If you need that kind of decoding, you must
- use QUrl::encodedQueryItemValue and decode the data yourself.
-
- \obsolete Use QUrlQuery.
-
- \sa allQueryItemValues()
-*/
-
-/*!
- \fn QByteArray QUrl::encodedQueryItemValue(const QByteArray &key) const
- \deprecated
- \since 4.4
-
- Returns the first query string value whose key is equal to \a key
- from the URL.
-
- \obsolete Use QUrlQuery.
-
- \sa queryItemValue(), allQueryItemValues()
-*/
-
-/*!
- \fn QStringList QUrl::allQueryItemValues(const QString &key) const
- \deprecated
-
- Returns the a list of query string values whose key is equal to
- \a key from the URL.
-
- \note This method does not decode spaces plus (+) signs as spaces (ASCII
- 0x20), like HTML forms do. If you need that kind of decoding, you must
- use QUrl::allEncodedQueryItemValues and decode the data yourself.
-
- \obsolete Use QUrlQuery.
-
- \sa queryItemValue()
-*/
-
-/*!
- \fn QList<QByteArray> QUrl::allEncodedQueryItemValues(const QByteArray &key) const
- \deprecated
- \since 4.4
-
- Returns the a list of query string values whose key is equal to
- \a key from the URL.
-
- \obsolete Use QUrlQuery.
-
- \sa allQueryItemValues(), queryItemValue(), encodedQueryItemValue()
-*/
-
-/*!
- \fn void QUrl::removeQueryItem(const QString &key)
- \deprecated
-
- Removes the first query string pair whose key is equal to \a key
- from the URL.
-
- \obsolete Use QUrlQuery.
-
- \sa removeAllQueryItems()
-*/
-
-/*!
- \fn void QUrl::removeEncodedQueryItem(const QByteArray &key)
- \deprecated
- \since 4.4
-
- Removes the first query string pair whose key is equal to \a key
- from the URL.
-
- \obsolete Use QUrlQuery.
-
- \sa removeQueryItem(), removeAllQueryItems()
-*/
-
-/*!
- \fn void QUrl::removeAllQueryItems(const QString &key)
- \deprecated
-
- Removes all the query string pairs whose key is equal to \a key
- from the URL.
-
- \obsolete Use QUrlQuery.
-
- \sa removeQueryItem()
-*/
-
-/*!
- \fn void QUrl::removeAllEncodedQueryItems(const QByteArray &key)
- \deprecated
- \since 4.4
-
- Removes all the query string pairs whose key is equal to \a key
- from the URL.
-
- \obsolete Use QUrlQuery.
-
- \sa removeQueryItem()
-*/
-
-/*!
- \fn QByteArray QUrl::encodedQuery() const
- \deprecated
-
- Returns the query string of the URL in percent encoded form.
-
- \obsolete Use query(QUrl::FullyEncoded).toLatin1()
-
- \sa setEncodedQuery(), query()
-*/
-
-/*!
Returns the query string of the URL if there's a query string, or an empty
result if not. To determine if the parsed URL contained a query string, use
hasQuery().
@@ -3059,7 +2655,7 @@ void QUrl::setFragment(const QString &fragment, ParsingMode mode)
mode = TolerantMode;
}
- d->setFragment(data, 0, data.length());
+ d->setFragment(data, 0, data.size());
if (fragment.isNull())
d->sectionIsPresent &= ~QUrlPrivate::Fragment;
else if (mode == StrictMode && !d->validateComponent(QUrlPrivate::Fragment, fragment))
@@ -3094,45 +2690,6 @@ QString QUrl::fragment(ComponentFormattingOptions options) const
}
/*!
- \fn void QUrl::setEncodedFragment(const QByteArray &fragment)
- \deprecated
- \since 4.4
-
- Sets the URL's fragment to the percent-encoded \a fragment. The fragment is the
- last part of the URL, represented by a '#' followed by a string of
- characters. It is typically used in HTTP for referring to a
- certain link or point on a page:
-
- \image qurl-fragment.png
-
- The fragment is sometimes also referred to as the URL "reference".
-
- Passing an argument of QByteArray() (a null QByteArray) will unset the fragment.
- Passing an argument of QByteArray("") (an empty but not null QByteArray)
- will set the fragment to an empty string (as if the original URL
- had a lone "#").
-
- \obsolete Use setFragment(), which has the same behavior of null / empty.
-
- \sa setFragment(), encodedFragment()
-*/
-
-/*!
- \fn QByteArray QUrl::encodedFragment() const
- \deprecated
- \since 4.4
-
- Returns the fragment of the URL if it is defined; otherwise an
- empty string is returned. The returned value will have its
- non-ASCII and other control characters percent-encoded, as in
- toEncoded().
-
- \obsolete Use query(QUrl::FullyEncoded).toLatin1().
-
- \sa setEncodedFragment(), toEncoded()
-*/
-
-/*!
\since 4.2
Returns \c true if this URL contains a fragment (i.e., if # was seen on it).
@@ -3197,7 +2754,7 @@ QUrl QUrl::resolved(const QUrl &relative) const
t.d->sectionIsPresent |= QUrlPrivate::Query;
}
} else {
- t.d->path = relative.d->path.startsWith(QLatin1Char('/'))
+ t.d->path = relative.d->path.startsWith(u'/')
? relative.d->path
: d->mergePaths(relative.d->path);
if (relative.d->hasQuery()) {
@@ -3304,26 +2861,26 @@ QString QUrl::toString(FormattingOptions options) const
options |= EncodeReserved;
if (!(options & QUrl::RemoveScheme) && d->hasScheme())
- url += d->scheme + QLatin1Char(':');
+ url += d->scheme + u':';
- bool pathIsAbsolute = d->path.startsWith(QLatin1Char('/'));
+ bool pathIsAbsolute = d->path.startsWith(u'/');
if (!((options & QUrl::RemoveAuthority) == QUrl::RemoveAuthority) && d->hasAuthority()) {
- url += QLatin1String("//");
+ url += "//"_L1;
d->appendAuthority(url, options, QUrlPrivate::FullUrl);
} else if (isLocalFile() && pathIsAbsolute) {
// Comply with the XDG file URI spec, which requires triple slashes.
- url += QLatin1String("//");
+ url += "//"_L1;
}
if (!(options & QUrl::RemovePath))
d->appendPath(url, options, QUrlPrivate::FullUrl);
if (!(options & QUrl::RemoveQuery) && d->hasQuery()) {
- url += QLatin1Char('?');
+ url += u'?';
d->appendQuery(url, options, QUrlPrivate::FullUrl);
}
if (!(options & QUrl::RemoveFragment) && d->hasFragment()) {
- url += QLatin1Char('#');
+ url += u'#';
d->appendFragment(url, options, QUrlPrivate::FullUrl);
}
@@ -3392,7 +2949,7 @@ QUrl QUrl::adjusted(QUrl::FormattingOptions options) const
that.detach();
QString path;
d->appendPath(path, options | FullyEncoded, QUrlPrivate::Path);
- that.d->setPath(path, 0, path.length());
+ that.d->setPath(path, 0, path.size());
}
return that;
}
@@ -3413,19 +2970,23 @@ QByteArray QUrl::toEncoded(FormattingOptions options) const
}
/*!
- \fn QUrl QUrl::fromEncoded(const QByteArray &input, ParsingMode parsingMode)
-
Parses \a input and returns the corresponding QUrl. \a input is
assumed to be in encoded form, containing only ASCII characters.
- Parses the URL using \a parsingMode. See setUrl() for more information on
+ Parses the URL using \a mode. See setUrl() for more information on
this parameter. QUrl::DecodedMode is not permitted in this context.
+ \note In Qt versions prior to 6.7, this function took a QByteArray, not
+ QByteArrayView. If you experience compile errors, it's because your code
+ is passing objects that are implicitly convertible to QByteArray, but not
+ QByteArrayView. Wrap the corresponding argument in \c{QByteArray{~~~}} to
+ make the cast explicit. This is backwards-compatible with old Qt versions.
+
\sa toEncoded(), setUrl()
*/
-QUrl QUrl::fromEncoded(const QByteArray &input, ParsingMode mode)
+QUrl QUrl::fromEncoded(QByteArrayView input, ParsingMode mode)
{
- return QUrl(QString::fromUtf8(input.constData(), input.size()), mode);
+ return QUrl(QString::fromUtf8(input), mode);
}
/*!
@@ -3460,166 +3021,149 @@ QByteArray QUrl::toPercentEncoding(const QString &input, const QByteArray &exclu
}
/*!
- \internal
- \since 5.0
- Used in the setEncodedXXX compatibility functions. Converts \a ba to
- QString form.
-*/
-QString QUrl::fromEncodedComponent_helper(const QByteArray &ba)
-{
- return qt_urlRecodeByteArray(ba);
-}
-
-/*!
- \fn QByteArray QUrl::toPunycode(const QString &uc)
- \obsolete
- Returns a \a uc in Punycode encoding.
-
- Punycode is a Unicode encoding used for internationalized domain
- names, as defined in RFC3492. If you want to convert a domain name from
- Unicode to its ASCII-compatible representation, use toAce().
-*/
-
-/*!
- \fn QString QUrl::fromPunycode(const QByteArray &pc)
- \obsolete
- Returns the Punycode decoded representation of \a pc.
-
- Punycode is a Unicode encoding used for internationalized domain
- names, as defined in RFC3492. If you want to convert a domain from
- its ASCII-compatible encoding to the Unicode representation, use
- fromAce().
-*/
-
-/*!
- \since 4.2
+ \since 6.3
Returns the Unicode form of the given domain name
\a domain, which is encoded in the ASCII Compatible Encoding (ACE).
+ The output can be customized by passing flags with \a options.
The result of this function is considered equivalent to \a domain.
If the value in \a domain cannot be encoded, it will be converted
to QString and returned.
- The ASCII Compatible Encoding (ACE) is defined by RFC 3490, RFC 3491
- and RFC 3492. It is part of the Internationalizing Domain Names in
- Applications (IDNA) specification, which allows for domain names
- (like \c "example.com") to be written using international
- characters.
+ The ASCII-Compatible Encoding (ACE) is defined by RFC 3490, RFC 3491
+ and RFC 3492 and updated by the Unicode Technical Standard #46. It is part
+ of the Internationalizing Domain Names in Applications (IDNA) specification,
+ which allows for domain names (like \c "example.com") to be written using
+ non-US-ASCII characters.
*/
-QString QUrl::fromAce(const QByteArray &domain)
+QString QUrl::fromAce(const QByteArray &domain, QUrl::AceProcessingOptions options)
{
- QVarLengthArray<char16_t> buffer;
- buffer.resize(domain.size());
- qt_from_latin1(buffer.data(), domain.data(), domain.size());
- return qt_ACE_do(QStringView{buffer.data(), buffer.size()},
- NormalizeAce, ForbidLeadingDot /*FIXME: make configurable*/);
+ return qt_ACE_do(QString::fromLatin1(domain), NormalizeAce,
+ ForbidLeadingDot /*FIXME: make configurable*/, options);
}
/*!
- \since 4.2
+ \since 6.3
Returns the ASCII Compatible Encoding of the given domain name \a domain.
+ The output can be customized by passing flags with \a options.
The result of this function is considered equivalent to \a domain.
The ASCII-Compatible Encoding (ACE) is defined by RFC 3490, RFC 3491
- and RFC 3492. It is part of the Internationalizing Domain Names in
- Applications (IDNA) specification, which allows for domain names
- (like \c "example.com") to be written using international
- characters.
+ and RFC 3492 and updated by the Unicode Technical Standard #46. It is part
+ of the Internationalizing Domain Names in Applications (IDNA) specification,
+ which allows for domain names (like \c "example.com") to be written using
+ non-US-ASCII characters.
This function returns an empty QByteArray if \a domain is not a valid
hostname. Note, in particular, that IPv6 literals are not valid domain
names.
*/
-QByteArray QUrl::toAce(const QString &domain)
+QByteArray QUrl::toAce(const QString &domain, AceProcessingOptions options)
{
- return qt_ACE_do(domain, ToAceOnly, ForbidLeadingDot /*FIXME: make configurable*/).toLatin1();
+ return qt_ACE_do(domain, ToAceOnly, ForbidLeadingDot /*FIXME: make configurable*/, options)
+ .toLatin1();
}
/*!
\internal
- Returns \c true if this URL is "less than" the given \a url. This
+ \fn bool QUrl::operator<(const QUrl &lhs, const QUrl &rhs)
+
+ Returns \c true if URL \a lhs is "less than" URL \a rhs. This
provides a means of ordering URLs.
*/
-bool QUrl::operator <(const QUrl &url) const
+
+Qt::weak_ordering compareThreeWay(const QUrl &lhs, const QUrl &rhs)
{
- if (!d || !url.d) {
- bool thisIsEmpty = !d || d->isEmpty();
- bool thatIsEmpty = !url.d || url.d->isEmpty();
+ if (!lhs.d || !rhs.d) {
+ bool thisIsEmpty = !lhs.d || lhs.d->isEmpty();
+ bool thatIsEmpty = !rhs.d || rhs.d->isEmpty();
// sort an empty URL first
- return thisIsEmpty && !thatIsEmpty;
+ if (thisIsEmpty) {
+ if (!thatIsEmpty)
+ return Qt::weak_ordering::less;
+ else
+ return Qt::weak_ordering::equivalent;
+ } else {
+ return Qt::weak_ordering::greater;
+ }
}
int cmp;
- cmp = d->scheme.compare(url.d->scheme);
+ cmp = lhs.d->scheme.compare(rhs.d->scheme);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- cmp = d->userName.compare(url.d->userName);
+ cmp = lhs.d->userName.compare(rhs.d->userName);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- cmp = d->password.compare(url.d->password);
+ cmp = lhs.d->password.compare(rhs.d->password);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- cmp = d->host.compare(url.d->host);
+ cmp = lhs.d->host.compare(rhs.d->host);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- if (d->port != url.d->port)
- return d->port < url.d->port;
+ if (lhs.d->port != rhs.d->port)
+ return Qt::compareThreeWay(lhs.d->port, rhs.d->port);
- cmp = d->path.compare(url.d->path);
+ cmp = lhs.d->path.compare(rhs.d->path);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- if (d->hasQuery() != url.d->hasQuery())
- return url.d->hasQuery();
+ if (lhs.d->hasQuery() != rhs.d->hasQuery())
+ return rhs.d->hasQuery() ? Qt::weak_ordering::less : Qt::weak_ordering::greater;
- cmp = d->query.compare(url.d->query);
+ cmp = lhs.d->query.compare(rhs.d->query);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- if (d->hasFragment() != url.d->hasFragment())
- return url.d->hasFragment();
+ if (lhs.d->hasFragment() != rhs.d->hasFragment())
+ return rhs.d->hasFragment() ? Qt::weak_ordering::less : Qt::weak_ordering::greater;
- cmp = d->fragment.compare(url.d->fragment);
- return cmp < 0;
+ cmp = lhs.d->fragment.compare(rhs.d->fragment);
+ return Qt::compareThreeWay(cmp, 0);
}
/*!
- Returns \c true if this URL and the given \a url are equal;
+ \fn bool QUrl::operator==(const QUrl &lhs, const QUrl &rhs)
+
+ Returns \c true if \a lhs and \a rhs URLs are equivalent;
otherwise returns \c false.
+
+ \sa matches()
*/
-bool QUrl::operator ==(const QUrl &url) const
+
+bool comparesEqual(const QUrl &lhs, const QUrl &rhs)
{
- if (!d && !url.d)
+ if (!lhs.d && !rhs.d)
return true;
- if (!d)
- return url.d->isEmpty();
- if (!url.d)
- return d->isEmpty();
+ if (!lhs.d)
+ return rhs.d->isEmpty();
+ if (!rhs.d)
+ return lhs.d->isEmpty();
// First, compare which sections are present, since it speeds up the
// processing considerably. We just have to ignore the host-is-present flag
// for local files (the "file" protocol), due to the requirements of the
// XDG file URI specification.
int mask = QUrlPrivate::FullUrl;
- if (isLocalFile())
+ if (lhs.isLocalFile())
mask &= ~QUrlPrivate::Host;
- return (d->sectionIsPresent & mask) == (url.d->sectionIsPresent & mask) &&
- d->scheme == url.d->scheme &&
- d->userName == url.d->userName &&
- d->password == url.d->password &&
- d->host == url.d->host &&
- d->port == url.d->port &&
- d->path == url.d->path &&
- d->query == url.d->query &&
- d->fragment == url.d->fragment;
+ return (lhs.d->sectionIsPresent & mask) == (rhs.d->sectionIsPresent & mask) &&
+ lhs.d->scheme == rhs.d->scheme &&
+ lhs.d->userName == rhs.d->userName &&
+ lhs.d->password == rhs.d->password &&
+ lhs.d->host == rhs.d->host &&
+ lhs.d->port == rhs.d->port &&
+ lhs.d->path == rhs.d->path &&
+ lhs.d->query == rhs.d->query &&
+ lhs.d->fragment == rhs.d->fragment;
}
/*!
@@ -3699,18 +3243,18 @@ bool QUrl::matches(const QUrl &url, FormattingOptions options) const
}
/*!
- Returns \c true if this URL and the given \a url are not equal;
+ \fn bool QUrl::operator !=(const QUrl &lhs, const QUrl &rhs)
+
+ Returns \c true if \a lhs and \a rhs URLs are not equal;
otherwise returns \c false.
+
+ \sa matches()
*/
-bool QUrl::operator !=(const QUrl &url) const
-{
- return !(*this == url);
-}
/*!
Assigns the specified \a url to this object.
*/
-QUrl &QUrl::operator =(const QUrl &url)
+QUrl &QUrl::operator =(const QUrl &url) noexcept
{
if (!d) {
if (url.d) {
@@ -3769,6 +3313,25 @@ bool QUrl::isDetached() const
return !d || d->ref.loadRelaxed() == 1;
}
+static QString fromNativeSeparators(const QString &pathName)
+{
+#if defined(Q_OS_WIN)
+ QString result(pathName);
+ const QChar nativeSeparator = u'\\';
+ auto i = result.indexOf(nativeSeparator);
+ if (i != -1) {
+ QChar * const data = result.data();
+ const auto length = result.length();
+ for (; i < length; ++i) {
+ if (data[i] == nativeSeparator)
+ data[i] = u'/';
+ }
+ }
+ return result;
+#else
+ return pathName;
+#endif
+}
/*!
Returns a QUrl representation of \a localFile, interpreted as a local
@@ -3807,26 +3370,34 @@ QUrl QUrl::fromLocalFile(const QString &localFile)
if (localFile.isEmpty())
return url;
QString scheme = fileScheme();
- QString deslashified = QDir::fromNativeSeparators(localFile);
+ QString deslashified = fromNativeSeparators(localFile);
// magic for drives on windows
- if (deslashified.length() > 1 && deslashified.at(1) == QLatin1Char(':') && deslashified.at(0) != QLatin1Char('/')) {
- deslashified.prepend(QLatin1Char('/'));
- } else if (deslashified.startsWith(QLatin1String("//"))) {
+ if (deslashified.size() > 1 && deslashified.at(1) == u':' && deslashified.at(0) != u'/') {
+ deslashified.prepend(u'/');
+ } else if (deslashified.startsWith("//"_L1)) {
// magic for shared drive on windows
- int indexOfPath = deslashified.indexOf(QLatin1Char('/'), 2);
+ qsizetype indexOfPath = deslashified.indexOf(u'/', 2);
QStringView hostSpec = QStringView{deslashified}.mid(2, indexOfPath - 2);
// Check for Windows-specific WebDAV specification: "//host@SSL/path".
if (hostSpec.endsWith(webDavSslTag(), Qt::CaseInsensitive)) {
hostSpec.truncate(hostSpec.size() - 4);
scheme = webDavScheme();
}
- url.setHost(hostSpec.toString());
- if (indexOfPath > 2)
- deslashified = deslashified.right(deslashified.length() - indexOfPath);
- else
+ // hosts can't be IPv6 addresses without [], so we can use QUrlPrivate::setHost
+ url.detach();
+ if (!url.d->setHost(hostSpec.toString(), 0, hostSpec.size(), StrictMode)) {
+ if (url.d->error->code != QUrlPrivate::InvalidRegNameError)
+ return url;
+
+ // Path hostname is not a valid URL host, so set it entirely in the path
+ // (by leaving deslashified unchanged)
+ } else if (indexOfPath > 2) {
+ deslashified = deslashified.right(deslashified.size() - indexOfPath);
+ } else {
deslashified.clear();
+ }
}
url.setScheme(scheme);
@@ -3887,16 +3458,16 @@ bool QUrl::isParentOf(const QUrl &childUrl) const
if (!d)
return ((childUrl.scheme().isEmpty())
&& (childUrl.authority().isEmpty())
- && childPath.length() > 0 && childPath.at(0) == QLatin1Char('/'));
+ && childPath.size() > 0 && childPath.at(0) == u'/');
QString ourPath = path();
return ((childUrl.scheme().isEmpty() || d->scheme == childUrl.scheme())
&& (childUrl.authority().isEmpty() || authority() == childUrl.authority())
&& childPath.startsWith(ourPath)
- && ((ourPath.endsWith(QLatin1Char('/')) && childPath.length() > ourPath.length())
- || (!ourPath.endsWith(QLatin1Char('/'))
- && childPath.length() > ourPath.length() && childPath.at(ourPath.length()) == QLatin1Char('/'))));
+ && ((ourPath.endsWith(u'/') && childPath.size() > ourPath.size())
+ || (!ourPath.endsWith(u'/') && childPath.size() > ourPath.size()
+ && childPath.at(ourPath.size()) == u'/')));
}
@@ -3942,34 +3513,31 @@ QDebug operator<<(QDebug d, const QUrl &url)
}
#endif
-static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, int errorPosition)
+static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, qsizetype errorPosition)
{
- QChar c = uint(errorPosition) < uint(errorSource.length()) ?
+ QChar c = size_t(errorPosition) < size_t(errorSource.size()) ?
errorSource.at(errorPosition) : QChar(QChar::Null);
switch (errorCode) {
case QUrlPrivate::NoError:
- Q_ASSERT_X(false, "QUrl::errorString",
- "Impossible: QUrl::errorString should have treated this condition");
- Q_UNREACHABLE();
- return QString();
+ Q_UNREACHABLE_RETURN(QString()); // QUrl::errorString should have treated this condition
case QUrlPrivate::InvalidSchemeError: {
- auto msg = QLatin1String("Invalid scheme (character '%1' not permitted)");
+ auto msg = "Invalid scheme (character '%1' not permitted)"_L1;
return msg.arg(c);
}
case QUrlPrivate::InvalidUserNameError:
- return QLatin1String("Invalid user name (character '%1' not permitted)")
+ return "Invalid user name (character '%1' not permitted)"_L1
.arg(c);
case QUrlPrivate::InvalidPasswordError:
- return QLatin1String("Invalid password (character '%1' not permitted)")
+ return "Invalid password (character '%1' not permitted)"_L1
.arg(c);
case QUrlPrivate::InvalidRegNameError:
- if (errorPosition != -1)
- return QLatin1String("Invalid hostname (character '%1' not permitted)")
+ if (errorPosition >= 0)
+ return "Invalid hostname (character '%1' not permitted)"_L1
.arg(c);
else
return QStringLiteral("Invalid hostname (contains invalid characters)");
@@ -3978,9 +3546,9 @@ static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &err
case QUrlPrivate::InvalidIPv6AddressError:
return QStringLiteral("Invalid IPv6 address");
case QUrlPrivate::InvalidCharacterInIPv6Error:
- return QLatin1String("Invalid IPv6 address (character '%1' not permitted)").arg(c);
+ return "Invalid IPv6 address (character '%1' not permitted)"_L1.arg(c);
case QUrlPrivate::InvalidIPvFutureError:
- return QLatin1String("Invalid IPvFuture address (character '%1' not permitted)").arg(c);
+ return "Invalid IPvFuture address (character '%1' not permitted)"_L1.arg(c);
case QUrlPrivate::HostMissingEndBracket:
return QStringLiteral("Expected ']' to match '[' in hostname");
@@ -3990,15 +3558,15 @@ static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &err
return QStringLiteral("Port field was empty");
case QUrlPrivate::InvalidPathError:
- return QLatin1String("Invalid path (character '%1' not permitted)")
+ return "Invalid path (character '%1' not permitted)"_L1
.arg(c);
case QUrlPrivate::InvalidQueryError:
- return QLatin1String("Invalid query (character '%1' not permitted)")
+ return "Invalid query (character '%1' not permitted)"_L1
.arg(c);
case QUrlPrivate::InvalidFragmentError:
- return QLatin1String("Invalid fragment (character '%1' not permitted)")
+ return "Invalid fragment (character '%1' not permitted)"_L1
.arg(c);
case QUrlPrivate::AuthorityPresentAndPathIsRelative:
@@ -4009,20 +3577,14 @@ static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &err
return QStringLiteral("Relative URL's path component contains ':' before any '/'");
}
- Q_ASSERT_X(false, "QUrl::errorString", "Cannot happen, unknown error");
- Q_UNREACHABLE();
- return QString();
+ Q_UNREACHABLE_RETURN(QString());
}
static inline void appendComponentIfPresent(QString &msg, bool present, const char *componentName,
const QString &component)
{
- if (present) {
- msg += QLatin1String(componentName);
- msg += QLatin1Char('"');
- msg += component;
- msg += QLatin1String("\",");
- }
+ if (present)
+ msg += QLatin1StringView(componentName) % u'"' % component % "\","_L1;
}
/*!
@@ -4045,15 +3607,15 @@ QString QUrl::errorString() const
return msg;
QString errorSource;
- int errorPosition = 0;
+ qsizetype errorPosition = 0;
QUrlPrivate::ErrorCode errorCode = d->validityError(&errorSource, &errorPosition);
if (errorCode == QUrlPrivate::NoError)
return msg;
msg += errorMessage(errorCode, errorSource, errorPosition);
- msg += QLatin1String("; source was \"");
+ msg += "; source was \""_L1;
msg += errorSource;
- msg += QLatin1String("\";");
+ msg += "\";"_L1;
appendComponentIfPresent(msg, d->sectionIsPresent & QUrlPrivate::Scheme,
" scheme = ", d->scheme);
appendComponentIfPresent(msg, d->sectionIsPresent & QUrlPrivate::UserInfo,
@@ -4068,7 +3630,7 @@ QString QUrl::errorString() const
" query = ", d->query);
appendComponentIfPresent(msg, d->sectionIsPresent & QUrlPrivate::Fragment,
" fragment = ", d->fragment);
- if (msg.endsWith(QLatin1Char(',')))
+ if (msg.endsWith(u','))
msg.chop(1);
return msg;
}
@@ -4139,8 +3701,8 @@ static QUrl adjustFtpPath(QUrl url)
{
if (url.scheme() == ftpScheme()) {
QString path = url.path(QUrl::PrettyDecoded);
- if (path.startsWith(QLatin1String("//")))
- url.setPath(QLatin1String("/%2F") + QStringView{path}.mid(2), QUrl::TolerantMode);
+ if (path.startsWith("//"_L1))
+ url.setPath("/%2F"_L1 + QStringView{path}.mid(2), QUrl::TolerantMode);
}
return url;
}
@@ -4155,65 +3717,12 @@ static bool isIp6(const QString &text)
Returns a valid URL from a user supplied \a userInput string if one can be
deduced. In the case that is not possible, an invalid QUrl() is returned.
- This overload takes a \a workingDirectory path, in order to be able to
- handle relative paths. This is especially useful when handling command
- line arguments.
- If \a workingDirectory is empty, no handling of relative paths will be done,
- so this method will behave like its one argument overload.
-
- By default, an input string that looks like a relative path will only be treated
- as such if the file actually exists in the given working directory.
-
- If the application can handle files that don't exist yet, it should pass the
- flag AssumeLocalFile in \a options.
-
- \since 5.4
-*/
-QUrl QUrl::fromUserInput(const QString &userInput, const QString &workingDirectory,
- UserInputResolutionOptions options)
-{
- QString trimmedString = userInput.trimmed();
-
- if (trimmedString.isEmpty())
- return QUrl();
-
-
- // Check for IPv6 addresses, since a path starting with ":" is absolute (a resource)
- // and IPv6 addresses can start with "c:" too
- if (isIp6(trimmedString)) {
- QUrl url;
- url.setHost(trimmedString);
- url.setScheme(QStringLiteral("http"));
- return url;
- }
-
- const QFileInfo fileInfo(QDir(workingDirectory), userInput);
- if (fileInfo.exists()) {
- return QUrl::fromLocalFile(fileInfo.absoluteFilePath());
- }
-
- QUrl url = QUrl(userInput, QUrl::TolerantMode);
- // Check both QUrl::isRelative (to detect full URLs) and QDir::isAbsolutePath (since on Windows drive letters can be interpreted as schemes)
- if ((options & AssumeLocalFile) && url.isRelative() && !QDir::isAbsolutePath(userInput)) {
- return QUrl::fromLocalFile(fileInfo.absoluteFilePath());
- }
-
- return fromUserInput(trimmedString);
-}
-
-/*!
- Returns a valid URL from a user supplied \a userInput string if one can be
- deducted. In the case that is not possible, an invalid QUrl() is returned.
-
- \since 4.6
-
- Most applications that can browse the web, allow the user to input a URL
- in the form of a plain string. This string can be manually typed into
- a location bar, obtained from the clipboard, or passed in via command
- line arguments.
+ This allows the user to input a URL or a local file path in the form of a plain
+ string. This string can be manually typed into a location bar, obtained from
+ the clipboard, or passed in via command line arguments.
When the string is not already a valid URL, a best guess is performed,
- making various web related assumptions.
+ making various assumptions.
In the case the string corresponds to a valid file path on the system,
a file:// URL is constructed, using QUrl::fromLocalFile().
@@ -4231,11 +3740,27 @@ QUrl QUrl::fromUserInput(const QString &userInput, const QString &workingDirecto
\li hostname becomes http://hostname
\li /home/user/test.html becomes file:///home/user/test.html
\endlist
+
+ In order to be able to handle relative paths, this method takes an optional
+ \a workingDirectory path. This is especially useful when handling command
+ line arguments.
+ If \a workingDirectory is empty, no handling of relative paths will be done.
+
+ By default, an input string that looks like a relative path will only be treated
+ as such if the file actually exists in the given working directory.
+ If the application can handle files that don't exist yet, it should pass the
+ flag AssumeLocalFile in \a options.
+
+ \since 5.4
*/
-QUrl QUrl::fromUserInput(const QString &userInput)
+QUrl QUrl::fromUserInput(const QString &userInput, const QString &workingDirectory,
+ UserInputResolutionOptions options)
{
QString trimmedString = userInput.trimmed();
+ if (trimmedString.isEmpty())
+ return QUrl();
+
// Check for IPv6 addresses, since a path starting with ":" is absolute (a resource)
// and IPv6 addresses can start with "c:" too
if (isIp6(trimmedString)) {
@@ -4245,25 +3770,36 @@ QUrl QUrl::fromUserInput(const QString &userInput)
return url;
}
- // Check first for files, since on Windows drive letters can be interpretted as schemes
+ const QUrl url = QUrl(trimmedString, QUrl::TolerantMode);
+
+ // Check for a relative path
+ if (!workingDirectory.isEmpty()) {
+ const QFileInfo fileInfo(QDir(workingDirectory), userInput);
+ if (fileInfo.exists())
+ return QUrl::fromLocalFile(fileInfo.absoluteFilePath());
+
+ // Check both QUrl::isRelative (to detect full URLs) and QDir::isAbsolutePath (since on Windows drive letters can be interpreted as schemes)
+ if ((options & AssumeLocalFile) && url.isRelative() && !QDir::isAbsolutePath(userInput))
+ return QUrl::fromLocalFile(fileInfo.absoluteFilePath());
+ }
+
+ // Check first for files, since on Windows drive letters can be interpreted as schemes
if (QDir::isAbsolutePath(trimmedString))
return QUrl::fromLocalFile(trimmedString);
- QUrl url = QUrl(trimmedString, QUrl::TolerantMode);
- QUrl urlPrepended = QUrl(QLatin1String("http://") + trimmedString, QUrl::TolerantMode);
+ QUrl urlPrepended = QUrl("http://"_L1 + trimmedString, QUrl::TolerantMode);
// Check the most common case of a valid url with a scheme
// We check if the port would be valid by adding the scheme to handle the case host:port
- // where the host would be interpretted as the scheme
+ // where the host would be interpreted as the scheme
if (url.isValid()
&& !url.scheme().isEmpty()
&& urlPrepended.port() == -1)
return adjustFtpPath(url);
// Else, try the prepended one and adjust the scheme from the host name
- if (urlPrepended.isValid() && (!urlPrepended.host().isEmpty() || !urlPrepended.path().isEmpty()))
- {
- int dotIndex = trimmedString.indexOf(QLatin1Char('.'));
+ if (urlPrepended.isValid() && (!urlPrepended.host().isEmpty() || !urlPrepended.path().isEmpty())) {
+ qsizetype dotIndex = trimmedString.indexOf(u'.');
const QStringView hostscheme = QStringView{trimmedString}.left(dotIndex);
if (hostscheme.compare(ftpScheme(), Qt::CaseInsensitive) == 0)
urlPrepended.setScheme(ftpScheme());