7#include <QtCore/qstringlist.h>
8#include <QtCore/private/qnumeric_p.h>
9#include <QtCore/private/qoffsetstringarray_p.h>
10#include <QtCore/private/qstringiterator_p.h>
11#include <QtCore/private/qunicodetables_p.h>
32 return digit + 22 + 75 * (digit < 26);
37 delta /= (firsttime ?
damp : 2);
38 delta += (delta / numpoints);
44 return k + (((
base -
tmin + 1) * delta) / (delta +
skew));
54 for (qq = delta, k =
base;; k +=
base) {
61 qq = (qq -
t) / (
base -
t);
79 int outLen =
output->size();
86 if (
c.unicode() < 0x80)
98 int copied =
output->size() - outLen;
109 uint inputLength = 0;
113 if (
iter.next(
char32_t(-1)) == char32_t(-1)) {
121 while (
h < inputLength) {
123 uint m = std::numeric_limits<uint>::max();
125 auto c =
iter.nextUnchecked();
126 static_assert(std::numeric_limits<
decltype(
m)>::max()
127 >= std::numeric_limits<
decltype(
c)>::max(),
128 "Punycode uint should be able to cover all codepoints");
135 if (qMulOverflow<uint>(
m -
n,
h + 1, &tmp) || qAddOverflow<uint>(delta, tmp, &delta)) {
142 auto c =
iter.nextUnchecked();
147 if (qAddOverflow<uint>(delta, 1, &delta)) {
167 output->insert(outLen,
"xn--"_L1);
191 auto output = delimiterPos < 4 ? std::u32string()
197 uint cnt = delimiterPos + 1;
210 uint digit = pc.
at(cnt++).unicode();
211 if (digit - 48 < 10) digit -= 22;
212 else if (digit - 65 < 26) digit -= 65;
213 else if (digit - 97 < 26) digit -= 97;
222 if (qMulOverflow<uint>(digit,
w, &tmp) || qAddOverflow<uint>(
i, tmp, &
i))
231 if (digit <
t)
break;
234 if (qMulOverflow<uint>(
w,
base -
t, &
w))
241 bias =
adapt(
i - oldi, outputLength + 1, oldi == 0);
244 if (qAddOverflow<uint>(
n,
i / (outputLength + 1), &
n))
248 i %= (outputLength + 1);
254 qWarning(
"Attempt to insert a basic codepoint. Unhandled overflow?");
269 if (QChar::isSurrogate(
n) ||
n > QChar::LastValidCodePoint)
273 output.insert(
i, 1,
static_cast<char32_t>(
n));
281 "ac",
"ar",
"asia",
"at",
283 "cat",
"ch",
"cl",
"cn",
"com",
289 "il",
"info",
"io",
"is",
"ir",
292 "li",
"lt",
"lu",
"lv",
294 "name",
"net",
"no",
"nu",
"nz",
298 "tel",
"th",
"tm",
"tw",
323 const auto *uc =
reinterpret_cast<const char16_t *
>(
a);
324 const char16_t *e = uc + l;
330 if (uc == e || *uc !=
static_cast<unsigned char>(*
c))
335 return uc == e ? *
c : (*uc < static_cast<unsigned char>(*
c));
340 while (l &&
a->unicode() && *
b) {
352 auto idx = aceDomain.lastIndexOf(u
'.');
356 auto tldString = aceDomain.mid(idx + 1);
357 const auto len = tldString.size();
359 const QChar *tld = tldString.constData();
366 int i = (l +
r + 1) / 2;
381 return c == u
'-' ||
c == u
'_' || (
c >= u
'0' &&
c <= u
'9') || (
c >= u
'a' &&
c <= u
'z');
400 *resultIsAscii =
true;
416 bool allAscii =
true;
419 char32_t uc =
iter.next();
423 if (uc >= U
'A' && uc <= U
'Z')
427 result.append(
static_cast<char16_t>(uc));
452 for (
auto c : QChar::fromUcs4(uc))
463 *resultIsAscii = allAscii;
479 if (
label.first() == u
'-' ||
label.last() == u
'-')
482 return std::all_of(
label.begin(),
label.end(), isValidInNormalizedAsciiLabel<QChar>);
487class DomainValidityChecker
489 bool domainNameIsBidi =
false;
490 bool hadBidiErrors =
false;
491 bool ignoreBidiErrors;
493 static constexpr char32_t ZWNJ = U
'\u200C';
494 static constexpr char32_t ZWJ = U
'\u200D';
497 DomainValidityChecker(
bool ignoreBidiErrors =
false) : ignoreBidiErrors(ignoreBidiErrors) { }
498 bool checkLabel(
const QString &
label, QUrl::AceProcessingOptions options);
529 constexpr unsigned char CombiningClassVirama = 9;
536 State regexpState = State::Initial;
537 bool previousIsVirama =
false;
543 if (!previousIsVirama)
545 regexpState = State::Initial;
546 }
else if (
ch == ZWNJ) {
547 if (!previousIsVirama && regexpState != State::LD_T)
549 regexpState = previousIsVirama ? State::Initial : State::ZWNJ_T;
551 switch (QChar::joiningType(
ch)) {
552 case QChar::Joining_Left:
553 if (regexpState == State::ZWNJ_T)
555 regexpState = State::LD_T;
557 case QChar::Joining_Right:
558 regexpState = State::Initial;
560 case QChar::Joining_Dual:
561 regexpState = State::LD_T;
563 case QChar::Joining_Transparent:
566 regexpState = State::Initial;
571 previousIsVirama = QChar::combiningClass(
ch) == CombiningClassVirama;
574 return regexpState != State::ZWNJ_T;
609 char32_t ch =
iter.next();
610 bool labelIsRTL =
false;
612 switch (QChar::direction(
ch)) {
624 bool labelHasEN =
false;
625 bool labelHasAN =
false;
627 while (
iter.hasNext()) {
630 switch (QChar::direction(
ch)) {
710bool DomainValidityChecker::checkLabel(
const QString &
label, QUrl::AceProcessingOptions options)
718 if (
label.size() >= 4) {
726 if (
label.startsWith(u
'-') ||
label.endsWith(u
'-'))
729 if (
label.contains(u
'.'))
733 auto c =
iter.next();
735 if (QChar::isMark(
c))
740 bool hasJoiners =
false;
743 hasJoiners = hasJoiners ||
c == ZWNJ ||
c == ZWJ;
745 if (!ignoreBidiErrors && !domainNameIsBidi) {
746 switch (QChar::direction(
c)) {
750 domainNameIsBidi =
true;
775 if (hasJoiners && !checkContextJRules(
label))
778 hadBidiErrors = hadBidiErrors || !checkBidiRules(
label);
780 if (domainNameIsBidi && hadBidiErrors)
795 idx = normalizedDomain.size();
797 const qsizetype labelLength = idx - lastIdx;
799 const auto label = normalizedDomain.sliced(lastIdx, labelLength);
802 if (aceForm.isEmpty())
805 aceResult.append(aceForm);
808 if (idx == normalizedDomain.size())
825 bool hasPunycode =
false;
826 *usesPunycode =
false;
828 while (lastIdx < normalizedDomain.size()) {
829 auto idx = normalizedDomain.indexOf(u
'.', lastIdx);
831 idx = normalizedDomain.size();
833 const auto labelLength = idx - lastIdx;
834 if (labelLength == 0) {
835 if (idx == normalizedDomain.size())
840 const auto label = normalizedDomain.sliced(lastIdx, labelLength);
844 hasPunycode = hasPunycode ||
label.startsWith(
"xn--"_L1);
850 *usesPunycode = hasPunycode;
857 result.reserve(asciiDomain.size());
860 DomainValidityChecker checker;
863 auto idx = asciiDomain.indexOf(u
'.', lastIdx);
865 idx = asciiDomain.size();
867 const auto labelLength = idx - lastIdx;
868 if (labelLength == 0) {
869 if (idx == asciiDomain.size())
872 const auto label = asciiDomain.sliced(lastIdx, labelLength);
875 if (unicodeLabel.isEmpty())
878 if (!checker.checkLabel(unicodeLabel, options))
881 result.append(unicodeLabel);
884 if (idx == asciiDomain.size())
897 DomainValidityChecker checker(
true);
900 qsizetype idx = domainName.indexOf(u
'.', lastIdx);
902 idx = domainName.size();
904 const qsizetype labelLength = idx - lastIdx;
906 const auto label = domainName.sliced(lastIdx, labelLength);
908 if (!checker.checkLabel(
label, options))
912 if (idx == domainName.size())
921 QUrl::AceProcessingOptions options)
937 bool needsConversionToUnicode;
942 if (op ==
ToAceOnly || !needsConversionToUnicode
void reserve(qsizetype size)
\macro QT_RESTRICTED_CAST_FROM_ASCII
std::u32string toStdU32String() const
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
QString mid(qsizetype position, qsizetype n=-1) const &
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
qsizetype size() const noexcept
Returns the number of characters in this string.
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
static QString fromStdU32String(const std::u32string &s)
@ AceTransitionalProcessing
static QStringList idnWhitelist()
static void setIdnWhitelist(const QStringList &)
Combined button and popup list for selecting options.
Q_CORE_EXPORT IdnaStatus QT_FASTCALL idnaStatus(char32_t ucs4) noexcept
Q_CORE_EXPORT QStringView QT_FASTCALL idnaMapping(char32_t ucs4) noexcept
QList< QString > QStringList
Constructs a string list that contains the given string, str.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
constexpr auto qOffsetStringArray(const char(&...strings)[Nx]) noexcept
GLboolean GLboolean GLboolean b
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint GLsizei const GLchar * label
[43]
GLfloat GLfloat GLfloat GLfloat h
GLint GLenum GLboolean normalized
static qreal dot(const QPointF &a, const QPointF &b)
#define Q_AUTOTEST_EXPORT
QString Q_CORE_EXPORT qt_ACE_do(const QString &domain, AceOperation op, AceLeadingDot dot, QUrl::AceProcessingOptions options={})
Q_AUTOTEST_EXPORT QString qt_punycodeDecoder(const QString &pc)
Q_AUTOTEST_EXPORT void qt_punycodeEncoder(QStringView in, QString *output)
static QString convertToAscii(QStringView normalizedDomain, AceLeadingDot dot)
static bool checkAsciiDomainName(QStringView normalizedDomain, AceLeadingDot dot, bool *usesPunycode)
static const uint initial_bias
static bool checkUnicodeName(const QString &domainName, QUrl::AceProcessingOptions options)
static bool isValidInNormalizedAsciiName(C c)
static bool qt_is_idn_enabled(QStringView aceDomain)
static constexpr auto idn_whitelist
static constexpr qsizetype MaxDomainLabelLength
static bool validateAsciiLabel(QStringView label)
static bool isValidInNormalizedAsciiLabel(C c)
static void appendEncode(QString *output, uint delta, uint bias)
static Q_CONSTINIT QStringList * user_idn_whitelist
static bool lessThan(const QChar *a, int l, const char *c)
static QString mapDomainName(const QString &in, QUrl::AceProcessingOptions options, bool *resultIsAscii)
static QString convertToUnicode(const QString &asciiDomain, QUrl::AceProcessingOptions options)
Q_AUTOTEST_EXPORT QString qt_punycodeDecoder(const QString &pc)
static const uint initial_n
Q_AUTOTEST_EXPORT void qt_punycodeEncoder(QStringView in, QString *output)
static bool equal(const QChar *a, int l, const char *b)
static uint encodeDigit(uint digit)
static uint adapt(uint delta, uint numpoints, bool firsttime)
QT_BEGIN_NAMESPACE typedef uchar * output
\inmodule QtCore \reentrant