diff options
Diffstat (limited to 'src/corelib/io/qurlidna.cpp')
-rw-r--r-- | src/corelib/io/qurlidna.cpp | 49 |
1 files changed, 38 insertions, 11 deletions
diff --git a/src/corelib/io/qurlidna.cpp b/src/corelib/io/qurlidna.cpp index 16bb924b17..226bc8ba28 100644 --- a/src/corelib/io/qurlidna.cpp +++ b/src/corelib/io/qurlidna.cpp @@ -2120,31 +2120,52 @@ Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from) } } -Q_AUTOTEST_EXPORT bool qt_check_std3rules(const QChar *uc, int len) +static const QChar *qt_find_nonstd3(const QChar *uc, int len, Qt::CaseSensitivity cs) { if (len > 63) - return false; + return uc; for (int i = 0; i < len; ++i) { ushort c = uc[i].unicode(); if (c == '-' && (i == 0 || i == len - 1)) - return false; + return uc + i; // verifying the absence of non-LDH is the same as verifying that // only LDH is present + if (cs == Qt::CaseInsensitive && (c >= 'A' && c <= 'Z')) + continue; if (c == '-' || (c >= '0' && c <= '9') - || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') //underscore is not supposed to be allowed, but other browser accept it (QTBUG-7434) || c == '_') continue; - return false; + return uc + i; } - return true; + return nullptr; +} + +Q_AUTOTEST_EXPORT bool qt_check_std3rules(const QChar *uc, int len) +{ + return qt_find_nonstd3(uc, len, Qt::CaseInsensitive) == nullptr; } +static bool qt_check_nameprepped_std3(const QChar *in, int len) +{ + // fast path: check for lowercase ASCII + const QChar *firstNonAscii = qt_find_nonstd3(in, len, Qt::CaseSensitive); + if (firstNonAscii == nullptr) { + // everything was lowercase ASCII, digits or hyphen + return true; + } + + const QChar *e = in + len; + QString origin = QString::fromRawData(firstNonAscii, e - firstNonAscii); + QString copy = origin; + qt_nameprep(©, 0); + return origin == copy; +} static inline uint encodeDigit(uint digit) { @@ -2422,8 +2443,8 @@ static bool qt_is_idn_enabled(const QString &domain) return false; int len = domain.size() - idx - 1; - QString tldString(domain.constData() + idx + 1, len); - qt_nameprep(&tldString, 0); + QString tldString = qt_ACE_do(QString::fromRawData(domain.constData() + idx + 1, len), ToAceOnly, ForbidLeadingDot); + len = tldString.size(); const QChar *tld = tldString.constData(); @@ -2546,13 +2567,19 @@ QString qt_ACE_do(const QString &domain, AceOperation op, AceLeadingDot dot) qt_punycodeEncoder(result.constData() + prevLen, result.size() - prevLen, &aceForm); // We use resize()+memcpy() here because we're overwriting the data we've copied + bool appended = false; if (isIdnEnabled) { QString tmp = qt_punycodeDecoder(aceForm); if (tmp.isEmpty()) return QString(); // shouldn't happen, since we've just punycode-encoded it - result.resize(prevLen + tmp.size()); - memcpy(result.data() + prevLen, tmp.constData(), tmp.size() * sizeof(QChar)); - } else { + if (qt_check_nameprepped_std3(tmp.constData(), tmp.size())) { + result.resize(prevLen + tmp.size()); + memcpy(result.data() + prevLen, tmp.constData(), tmp.size() * sizeof(QChar)); + appended = true; + } + } + + if (!appended) { result.resize(prevLen + aceForm.size()); memcpy(result.data() + prevLen, aceForm.constData(), aceForm.size() * sizeof(QChar)); } |