diff options
Diffstat (limited to 'src/corelib/io/qurl.cpp')
-rw-r--r-- | src/corelib/io/qurl.cpp | 66 |
1 files changed, 35 insertions, 31 deletions
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 438924bd80..e531505877 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -472,16 +472,10 @@ static inline QString webDavSslTag() return QStringLiteral("@SSL"); } -#ifdef Q_COMPILER_CLASS_ENUM -# define colon_uchar : uchar -#else -# define colon_uchar -#endif - class QUrlPrivate { public: - enum Section colon_uchar { + enum Section : uchar { Scheme = 0x01, UserName = 0x02, Password = 0x04, @@ -496,7 +490,7 @@ public: FullUrl = 0xff }; - enum Flags colon_uchar { + enum Flags : uchar { IsLocalFile = 0x01 }; @@ -616,7 +610,6 @@ public: // 32-bit: 2 bytes tail padding available // 64-bit: 6 bytes tail padding available }; -#undef colon_uchar inline QUrlPrivate::QUrlPrivate() : ref(1), port(-1), @@ -1203,15 +1196,13 @@ inline void QUrlPrivate::setQuery(const QString &value, int from, int iend) inline void QUrlPrivate::appendHost(QString &appendTo, QUrl::FormattingOptions options) const { - // EncodeUnicode is the only flag that matters - if ((options & QUrl::FullyDecoded) == QUrl::FullyDecoded) - options = 0; - else - options &= QUrl::EncodeUnicode; if (host.isEmpty()) return; if (host.at(0).unicode() == '[') { - // IPv6Address and IPvFuture address never require any transformation + // IPv6 addresses might contain a zone-id which needs to be recoded + if (options != 0) + if (qt_urlRecode(appendTo, host.constBegin(), host.constEnd(), options, 0)) + return; appendTo += host; } else { // this is either an IPv4Address or a reg-name @@ -1278,31 +1269,44 @@ 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) { - QIPAddressUtils::IPv6Address address; - const QChar *ret = QIPAddressUtils::parseIp6(address, begin, end); - if (ret) { + // ### Update to use QStringView once QStringView::indexOf and QStringView::lastIndexOf exists + QString decoded; + 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, begin, end, QUrl::ComponentFormattingOption::PrettyDecoded, decodeColon) == 0) + decoded = QString(begin, end-begin); + } else { + decoded = QString(begin, end-begin); + } - // IPv6 failed parsing, check if it was a percent-encoded character in - // the middle and try again - QString decoded; - if (mode == QUrl::TolerantMode && qt_urlRecode(decoded, begin, end, 0, decodeColon)) { - // recurse - // if the parsing fails again, the qt_urlRecode above will return 0 - ret = parseIp6(host, decoded.constBegin(), decoded.constEnd(), mode); + const QLatin1String zoneIdIdentifier("%25"); + QIPAddressUtils::IPv6Address address; + QString zoneId; - // we can't return ret, otherwise it would be dangling - return ret ? end : 0; - } + const QChar *endBeforeZoneId = decoded.constEnd(); + + int zoneIdPosition = decoded.indexOf(zoneIdIdentifier); + if ((zoneIdPosition != -1) && (decoded.lastIndexOf(zoneIdIdentifier) == zoneIdPosition)) { + zoneId = decoded.mid(zoneIdPosition + zoneIdIdentifier.size()); + endBeforeZoneId = decoded.constBegin() + zoneIdPosition; - // no transformation, nothing to re-parse - return ret; + if (zoneId.isEmpty()) + return end; } - host.reserve(host.size() + (end - begin)); + const QChar *ret = QIPAddressUtils::parseIp6(address, decoded.constBegin(), endBeforeZoneId); + if (ret) + return begin + (ret - decoded.constBegin()); + + host.reserve(host.size() + (decoded.constEnd() - decoded.constBegin())); host += QLatin1Char('['); QIPAddressUtils::toString(host, address); + + if (!zoneId.isEmpty()) { + host += zoneIdIdentifier; + host += zoneId; + } host += QLatin1Char(']'); return 0; } |