109 lines
4.2 KiB
Diff
109 lines
4.2 KiB
Diff
From 2e492dc6a6cf9e73a04f65e133ea4e97324a68da Mon Sep 17 00:00:00 2001
|
|
From: Robbert Proost <robbert.proost@outlook.com>
|
|
Date: Thu, 18 Jan 2018 09:52:49 +0100
|
|
Subject: [PATCH] QUrl: Support IPv6 addresses with zone id
|
|
|
|
Task-number: QTBUG-25550
|
|
Change-Id: I37ec02b655abe2779aa11945e20550ce00e43723
|
|
---
|
|
src/corelib/io/qurl.cpp | 63 ++++++++++++++++---------
|
|
tests/auto/corelib/io/qurl/tst_qurl.cpp | 52 ++++++++++++++++++++
|
|
2 files changed, 92 insertions(+), 23 deletions(-)
|
|
|
|
diff --git x/qtbase/src/corelib/io/qurl.cpp y/qtbase/src/corelib/io/qurl.cpp
|
|
index 4587b9fcd6..e2a66c8459 100644
|
|
--- x/qtbase/src/corelib/io/qurl.cpp
|
|
+++ y/qtbase/src/corelib/io/qurl.cpp
|
|
@@ -1203,16 +1203,18 @@ 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
|
|
- appendTo += host;
|
|
+ // IPv6 addresses might contain a zone-id which needs to be recoded
|
|
+ QString hostInCorrectFormat;
|
|
+ if (options != 0)
|
|
+ qt_urlRecode(hostInCorrectFormat, host.constBegin(), host.constEnd(), options, 0);
|
|
+
|
|
+ if (hostInCorrectFormat.isEmpty())
|
|
+ hostInCorrectFormat = host;
|
|
+
|
|
+ appendTo += hostInCorrectFormat;
|
|
} else {
|
|
// this is either an IPv4Address or a reg-name
|
|
// if it is a reg-name, it is already stored in Unicode form
|
|
@@ -1278,31 +1280,46 @@ 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) {
|
|
- // this struct is kept in automatic storage because it's only 4 bytes
|
|
+ QString decoded;
|
|
+ if (mode == QUrl::TolerantMode) {
|
|
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;
|
|
+
|
|
+ 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;
|
|
|
|
- // we can't return ret, otherwise it would be dangling
|
|
- return ret ? end : 0;
|
|
+ if (zoneId.isEmpty() == true) {
|
|
+ return end;
|
|
}
|
|
+ }
|
|
|
|
- // no transformation, nothing to re-parse
|
|
- return ret;
|
|
+ const QChar *ret = QIPAddressUtils::parseIp6(address, decoded.constBegin(), endBeforeZoneId);
|
|
+ if (ret) {
|
|
+ return begin + (ret - decoded.constBegin());
|
|
}
|
|
|
|
- host.reserve(host.size() + (end - begin));
|
|
+ host.reserve(host.size() + (decoded.constEnd() - decoded.constBegin()));
|
|
host += QLatin1Char('[');
|
|
QIPAddressUtils::toString(host, address);
|
|
+
|
|
+ if (zoneId.isEmpty() == false) {
|
|
+ host += zoneIdIdentifier;
|
|
+ host += zoneId;
|
|
+ }
|
|
host += QLatin1Char(']');
|
|
return 0;
|
|
}
|
|
--
|
|
2.18.0
|
|
|